diff --git a/analyzers/archive-analyzer.html b/analyzers/archive-analyzer.html index acada5f73..55b32a964 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-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/analyzers/assembly-analyzer.html b/analyzers/assembly-analyzer.html index 83b852012..c0a6377e7 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-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/analyzers/autoconf.html b/analyzers/autoconf.html index 36e0207d8..d1fa7f712 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-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/analyzers/central-analyzer.html b/analyzers/central-analyzer.html index 80820bda2..6d1cd3ac5 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-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/analyzers/cmake.html b/analyzers/cmake.html index 306145b4a..1733e82ef 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-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/analyzers/composer-lock.html b/analyzers/composer-lock.html index 368dac24a..686907cb8 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-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/analyzers/index.html b/analyzers/index.html index 801f29e13..77f7dc242 100644 --- a/analyzers/index.html +++ b/analyzers/index.html @@ -1,13 +1,13 @@ - + dependency-check – File Type Analyzers @@ -59,9 +59,9 @@
  • File Type Analyzers
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/analyzers/jar-analyzer.html b/analyzers/jar-analyzer.html index fb89865e3..5e47f0c74 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-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/analyzers/nexus-analyzer.html b/analyzers/nexus-analyzer.html index a6eee2e2f..89d7a982a 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-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/analyzers/nodejs.html b/analyzers/nodejs.html index 7faaa7eac..0703ebea1 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-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/analyzers/nuspec-analyzer.html b/analyzers/nuspec-analyzer.html index de07e3c57..e457b88c0 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-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/analyzers/openssl.html b/analyzers/openssl.html index f6c6cfcfc..535001009 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-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/analyzers/python.html b/analyzers/python.html index 1d91fb0f0..eeb0ed107 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-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/analyzers/ruby-gemspec.html b/analyzers/ruby-gemspec.html index e8e78db6c..a29429fb5 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-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/cov-scan.bat b/cov-scan.bat new file mode 100644 index 000000000..f40e3c0ec --- /dev/null +++ b/cov-scan.bat @@ -0,0 +1,4 @@ +@REM see https://scan.coverity.com/download?tab=java +cov-build --dir cov-int mvn -DskipTests=true package + +7z a target\dependency-check.zip cov-int\* diff --git a/current.txt b/current.txt index c9929e36a..3c80e4f0f 100644 --- a/current.txt +++ b/current.txt @@ -1 +1 @@ -1.4.2 \ No newline at end of file +1.4.3 \ No newline at end of file diff --git a/data/cachenvd.html b/data/cachenvd.html index ef5f34e1b..8f2456d81 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-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/data/database.html b/data/database.html index d85954cb5..3c020c608 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-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • @@ -286,7 +286,7 @@ <plugin> <groupId>org.owasp</groupId> <artifactId>dependency-check-maven</artifactId> - <version>1.4.2</version> + <version>1.4.3</version> <dependencies> <dependency> <groupId>org.mariadb.jdbc</groupId> diff --git a/data/index.html b/data/index.html index af6a8d577..b4767b43c 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-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/data/mirrornvd.html b/data/mirrornvd.html index 947695f96..c9d5668de 100644 --- a/data/mirrornvd.html +++ b/data/mirrornvd.html @@ -1,13 +1,13 @@ - + dependency-check – Mirroring the NVD from NIST @@ -59,9 +59,9 @@
  • Mirroring the NVD from NIST
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/data/proxy.html b/data/proxy.html index e591d11ab..94e049fd9 100644 --- a/data/proxy.html +++ b/data/proxy.html @@ -1,13 +1,13 @@ - + dependency-check – Proxy Configuration @@ -59,9 +59,9 @@
  • Proxy Configuration
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/data/upgrade.html b/data/upgrade.html index 24153e06d..bbf1326a5 100644 --- a/data/upgrade.html +++ b/data/upgrade.html @@ -1,13 +1,13 @@ - + dependency-check – Database Upgrades @@ -59,9 +59,9 @@
  • Database Upgrades
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/dependency-analysis.html b/dependency-analysis.html index 603b636a2..ce5ae8e78 100644 --- a/dependency-analysis.html +++ b/dependency-analysis.html @@ -1,13 +1,13 @@ - + dependency-check – @@ -59,9 +59,9 @@
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/dependency-check-ant/apidocs/allclasses-frame.html b/dependency-check-ant/apidocs/allclasses-frame.html index 788c6c775..508c6af83 100644 --- a/dependency-check-ant/apidocs/allclasses-frame.html +++ b/dependency-check-ant/apidocs/allclasses-frame.html @@ -2,10 +2,10 @@ - + -All Classes (Dependency-Check Ant Task 1.4.2 API) - +All Classes (Dependency-Check Ant Task 1.4.3 API) + diff --git a/dependency-check-ant/apidocs/allclasses-noframe.html b/dependency-check-ant/apidocs/allclasses-noframe.html index 0adbf1434..51d3ec363 100644 --- a/dependency-check-ant/apidocs/allclasses-noframe.html +++ b/dependency-check-ant/apidocs/allclasses-noframe.html @@ -2,10 +2,10 @@ - + -All Classes (Dependency-Check Ant Task 1.4.2 API) - +All Classes (Dependency-Check Ant Task 1.4.3 API) + diff --git a/dependency-check-ant/apidocs/constant-values.html b/dependency-check-ant/apidocs/constant-values.html index c144a8b19..27646760a 100644 --- a/dependency-check-ant/apidocs/constant-values.html +++ b/dependency-check-ant/apidocs/constant-values.html @@ -2,10 +2,10 @@ - + -Constant Field Values (Dependency-Check Ant Task 1.4.2 API) - +Constant Field Values (Dependency-Check Ant Task 1.4.3 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 @@ diff --git a/dependency-check-ant/apidocs/org/owasp/dependencycheck/ant/logging/package-summary.html b/dependency-check-ant/apidocs/org/owasp/dependencycheck/ant/logging/package-summary.html index e7d8539af..728388303 100644 --- a/dependency-check-ant/apidocs/org/owasp/dependencycheck/ant/logging/package-summary.html +++ b/dependency-check-ant/apidocs/org/owasp/dependencycheck/ant/logging/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.ant.logging (Dependency-Check Ant Task 1.4.2 API) - +org.owasp.dependencycheck.ant.logging (Dependency-Check Ant Task 1.4.3 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-ant/apidocs/org/owasp/dependencycheck/taskdefs/package-summary.html b/dependency-check-ant/apidocs/org/owasp/dependencycheck/taskdefs/package-summary.html index 9c06e7cf7..6499367a5 100644 --- a/dependency-check-ant/apidocs/org/owasp/dependencycheck/taskdefs/package-summary.html +++ b/dependency-check-ant/apidocs/org/owasp/dependencycheck/taskdefs/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.taskdefs (Dependency-Check Ant Task 1.4.2 API) - +org.owasp.dependencycheck.taskdefs (Dependency-Check Ant Task 1.4.3 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-ant/apidocs/org/slf4j/impl/package-summary.html b/dependency-check-ant/apidocs/org/slf4j/impl/package-summary.html index bdad23959..6889a562f 100644 --- a/dependency-check-ant/apidocs/org/slf4j/impl/package-summary.html +++ b/dependency-check-ant/apidocs/org/slf4j/impl/package-summary.html @@ -2,10 +2,10 @@ - + -org.slf4j.impl (Dependency-Check Ant Task 1.4.2 API) - +org.slf4j.impl (Dependency-Check Ant Task 1.4.3 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-ant/apidocs/overview-summary.html b/dependency-check-ant/apidocs/overview-summary.html index af89d6683..1ca1a2fbb 100644 --- a/dependency-check-ant/apidocs/overview-summary.html +++ b/dependency-check-ant/apidocs/overview-summary.html @@ -2,10 +2,10 @@ - + -Overview (Dependency-Check Ant Task 1.4.2 API) - +Overview (Dependency-Check Ant Task 1.4.3 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ - + diff --git a/dependency-check-ant/cobertura/frame-summary-org.owasp.dependencycheck.taskdefs.html b/dependency-check-ant/cobertura/frame-summary-org.owasp.dependencycheck.taskdefs.html index a98879409..0bc8f9fe8 100644 --- a/dependency-check-ant/cobertura/frame-summary-org.owasp.dependencycheck.taskdefs.html +++ b/dependency-check-ant/cobertura/frame-summary-org.owasp.dependencycheck.taskdefs.html @@ -42,6 +42,6 @@ var classTable = new SortableTable(document.getElementById("classResults"), ["String", "Percentage", "Percentage", "FormattedNumber"]); classTable.sort(0); - + diff --git a/dependency-check-ant/cobertura/frame-summary-org.slf4j.impl.html b/dependency-check-ant/cobertura/frame-summary-org.slf4j.impl.html index 6d495b900..c87575da2 100644 --- a/dependency-check-ant/cobertura/frame-summary-org.slf4j.impl.html +++ b/dependency-check-ant/cobertura/frame-summary-org.slf4j.impl.html @@ -37,6 +37,6 @@ var classTable = new SortableTable(document.getElementById("classResults"), ["String", "Percentage", "Percentage", "FormattedNumber"]); classTable.sort(0); - + diff --git a/dependency-check-ant/cobertura/frame-summary.html b/dependency-check-ant/cobertura/frame-summary.html index fdc7eb515..216329af1 100644 --- a/dependency-check-ant/cobertura/frame-summary.html +++ b/dependency-check-ant/cobertura/frame-summary.html @@ -27,6 +27,6 @@ var packageTable = new SortableTable(document.getElementById("packageResults"), ["String", "Number", "Percentage", "Percentage", "FormattedNumber"]); packageTable.sort(0); - + diff --git a/dependency-check-ant/cobertura/org.owasp.dependencycheck.ant.logging.AntLoggerAdapter.html b/dependency-check-ant/cobertura/org.owasp.dependencycheck.ant.logging.AntLoggerAdapter.html index 75abee2e4..e6383190b 100644 --- a/dependency-check-ant/cobertura/org.owasp.dependencycheck.ant.logging.AntLoggerAdapter.html +++ b/dependency-check-ant/cobertura/org.owasp.dependencycheck.ant.logging.AntLoggerAdapter.html @@ -141,11 +141,11 @@
         @Override
     65  
         public void trace(String msg) {
    -  66  32
             if (task != null) {
    +  66  31
             if (task != null) {
     67  27
                 task.log(msg, Project.MSG_VERBOSE);
     68  
             }
    -  69  32
         }
    +  69  31
         }
     70  
     
     71   @@ -208,11 +208,11 @@
         @Override
     108  
         public void debug(String msg) {
    -  109  137
             if (task != null) {
    -  110  117
                 task.log(msg, Project.MSG_DEBUG);
    +  109  136
             if (task != null) {
    +  110  118
                 task.log(msg, Project.MSG_DEBUG);
     111  
             }
    -  112  137
         }
    +  112  136
         }
     113  
     
     114   @@ -465,6 +465,6 @@
     }
    - + diff --git a/dependency-check-ant/cobertura/org.owasp.dependencycheck.ant.logging.AntLoggerFactory.html b/dependency-check-ant/cobertura/org.owasp.dependencycheck.ant.logging.AntLoggerFactory.html index 9e417d03c..6fd80baa3 100644 --- a/dependency-check-ant/cobertura/org.owasp.dependencycheck.ant.logging.AntLoggerFactory.html +++ b/dependency-check-ant/cobertura/org.owasp.dependencycheck.ant.logging.AntLoggerFactory.html @@ -120,13 +120,13 @@
         @Override
     53  
         public Logger getLogger(String name) {
    -  54  52
             return antLoggerAdapter;
    +  54  51
             return antLoggerAdapter;
     55  
         }
     56  
     }
    - + diff --git a/dependency-check-ant/cobertura/org.owasp.dependencycheck.taskdefs.Check.html b/dependency-check-ant/cobertura/org.owasp.dependencycheck.taskdefs.Check.html index f946da362..4c2a1166f 100644 --- a/dependency-check-ant/cobertura/org.owasp.dependencycheck.taskdefs.Check.html +++ b/dependency-check-ant/cobertura/org.owasp.dependencycheck.taskdefs.Check.html @@ -1811,6 +1811,6 @@
     }
    - + diff --git a/dependency-check-ant/cobertura/org.owasp.dependencycheck.taskdefs.Purge.html b/dependency-check-ant/cobertura/org.owasp.dependencycheck.taskdefs.Purge.html index 72d1befa9..fa877c0f3 100644 --- a/dependency-check-ant/cobertura/org.owasp.dependencycheck.taskdefs.Purge.html +++ b/dependency-check-ant/cobertura/org.owasp.dependencycheck.taskdefs.Purge.html @@ -304,6 +304,6 @@
     }
    - + diff --git a/dependency-check-ant/cobertura/org.owasp.dependencycheck.taskdefs.Update.html b/dependency-check-ant/cobertura/org.owasp.dependencycheck.taskdefs.Update.html index 2a5018171..b0404c151 100644 --- a/dependency-check-ant/cobertura/org.owasp.dependencycheck.taskdefs.Update.html +++ b/dependency-check-ant/cobertura/org.owasp.dependencycheck.taskdefs.Update.html @@ -839,6 +839,6 @@
     }
    - + diff --git a/dependency-check-ant/cobertura/org.slf4j.impl.StaticLoggerBinder.html b/dependency-check-ant/cobertura/org.slf4j.impl.StaticLoggerBinder.html index d25b986ee..71882cab0 100644 --- a/dependency-check-ant/cobertura/org.slf4j.impl.StaticLoggerBinder.html +++ b/dependency-check-ant/cobertura/org.slf4j.impl.StaticLoggerBinder.html @@ -108,7 +108,7 @@
          */
     46  
         public static final StaticLoggerBinder getSingleton() {
    -  47  66
             return SINGLETON;
    +  47  65
             return SINGLETON;
     48  
         }
     49   @@ -208,7 +208,7 @@
         @Override
     101  
         public ILoggerFactory getLoggerFactory() {
    -  102  52
             return loggerFactory;
    +  102  51
             return loggerFactory;
     103  
         }
     104   @@ -234,6 +234,6 @@
     }
    - + diff --git a/dependency-check-ant/config-purge.html b/dependency-check-ant/config-purge.html index a7149aee0..069fa8cc2 100644 --- a/dependency-check-ant/config-purge.html +++ b/dependency-check-ant/config-purge.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Configuration @@ -52,7 +52,7 @@ diff --git a/dependency-check-ant/config-update.html b/dependency-check-ant/config-update.html index 2a78af02c..039198a5b 100644 --- a/dependency-check-ant/config-update.html +++ b/dependency-check-ant/config-update.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Configuration @@ -52,7 +52,7 @@ diff --git a/dependency-check-ant/configuration.html b/dependency-check-ant/configuration.html index 9c6f9a4a6..1faea09d0 100644 --- a/dependency-check-ant/configuration.html +++ b/dependency-check-ant/configuration.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Configuration @@ -52,7 +52,7 @@ diff --git a/dependency-check-ant/dependency-analysis.html b/dependency-check-ant/dependency-analysis.html index bd8506db7..4af717f9d 100644 --- a/dependency-check-ant/dependency-analysis.html +++ b/dependency-check-ant/dependency-analysis.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Dependencies Report @@ -52,7 +52,7 @@ @@ -239,7 +239,7 @@ org.owasp dependency-check-core -1.4.2 +1.4.3 compile jar @@ -247,7 +247,7 @@ org.owasp dependency-check-utils -1.4.2 +1.4.3 compile jar @@ -255,7 +255,7 @@ org.owasp dependency-check-core -1.4.2 +1.4.3 test tests test-jar diff --git a/dependency-check-ant/dependency-updates-report.html b/dependency-check-ant/dependency-updates-report.html index d81165dbc..0bf823102 100644 --- a/dependency-check-ant/dependency-updates-report.html +++ b/dependency-check-ant/dependency-updates-report.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Dependency Updates Report @@ -52,7 +52,7 @@ @@ -230,7 +230,7 @@ # of dependencies using the latest version available -25 +23 # of dependencies where the next version available is smaller than an incremental version update @@ -238,15 +238,15 @@ # of dependencies where the next version available is an incremental version update -0 +1 # of dependencies where the next version available is a minor version update -7 +8 # of dependencies where the next version available is a major version update -1 +2

    Dependency Management

    @@ -311,7 +311,7 @@ - + @@ -319,7 +319,7 @@ - + @@ -515,7 +515,7 @@ - + @@ -524,7 +524,7 @@ - + @@ -539,6 +539,18 @@ + + + + + + + + + + + + @@ -550,7 +562,7 @@ - + @@ -562,7 +574,7 @@ - + @@ -574,7 +586,7 @@ - + @@ -586,7 +598,7 @@ - + @@ -598,7 +610,7 @@ - + @@ -610,7 +622,7 @@ - + @@ -622,7 +634,7 @@ - + @@ -634,7 +646,7 @@ - + @@ -649,7 +661,7 @@

    Dependencies

    1.4.177
    com.sun.mail mailapi 1.5.5 jar 1.5.6
    org.apache.maven.plugin-tools maven-plugin-annotations 3.4jar 3.5
    org.apache.maven.sharedmaven-dependency-tree2.2jar3.0
    org.apache.velocity velocity
    org.glassfish javax.json
    org.hamcrest hamcrest-core
    org.jmockit jmockit 1.25
    org.jsoup jsoup
    org.slf4j slf4j-api
    org.slf4j slf4j-simple
    org.sonatype.plexus plexus-sec-dispatcher
    Status Group Id Artifact Id
    - + @@ -661,11 +673,23 @@ - + - + + + + + + + + + + + + + @@ -674,18 +698,6 @@ - - - - - - - - - - - - @@ -703,25 +715,25 @@

    ch.qos.logback:logback-classic

    Status Group Id Artifact IdNext Incremental Next Minor Next Major
    org.owasp dependency-check-core1.4.21.4.3compilejar
    org.owaspdependency-check-utils1.4.3 compile jar
    org.owaspdependency-check-utils1.4.2compilejar
    Status Group Id Artifact Id
    - + - + - + - + - + - + - +
    Status  No newer versions available.
    Group Id ch.qos.logback
    Artifact Id logback-classic
    Current Version 1.1.7
    Scope
    Classifier
    Type jar
    @@ -804,7 +816,7 @@ - + @@ -822,7 +834,10 @@ -
    Status No newer versions available.
     There is at least one newer incremental version available. Incremental updates are typically passive.
    Group Id com.sun.mail
    Typejar
    +jar + +Newer versions +1.5.6 Next Incremental

    commons-cli:commons-cli

    @@ -1047,7 +1062,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.lucene:lucene-core

    @@ -1074,7 +1089,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.lucene:lucene-queryparser

    @@ -1101,7 +1116,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.lucene:lucene-test-framework

    @@ -1128,7 +1143,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.maven:maven-core

    @@ -1230,7 +1245,7 @@
    - + @@ -1248,7 +1263,10 @@ -
    Status No newer versions available.
     There is at least one newer minor version available. Minor updates are sometimes passive.
    Group Id org.apache.maven.plugin-tools
    Typejar
    +jar + +Newer versions +3.5 Next Minor

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

    @@ -1274,6 +1292,33 @@
    Type jar
    +

    org.apache.maven.shared:maven-dependency-tree

    + + + + + + + + + + + + + + + + + + + + + + + + +
    Status There is at least one newer major version available. Major updates are rarely passive.
    Group Idorg.apache.maven.shared
    Artifact Idmaven-dependency-tree
    Current Version2.2
    Scope
    Classifier
    Typejar
    Newer versions3.0 Next Major
    +

    org.apache.velocity:velocity

    @@ -1371,7 +1416,7 @@ -
    jar
    Newer versions1.25 Next Minor
    +1.25 Next Minor
    1.26
    1.27 Latest Minor

    org.jsoup:jsoup

    @@ -1410,7 +1455,7 @@ - + @@ -1434,7 +1479,7 @@ - + diff --git a/dependency-check-ant/findbugs.html b/dependency-check-ant/findbugs.html index 6a633008f..e1e51781f 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 @@ diff --git a/dependency-check-ant/index.html b/dependency-check-ant/index.html index ae431870a..1ade09a95 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 73e98d56f..2d72a7996 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 f2cf2bdda..44aece404 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 a720c353f..81bc5614e 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 4824edfef..e05fc2670 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 fcac7e5d5..1f1ada4cb 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 @@ diff --git a/dependency-check-ant/project-info.html b/dependency-check-ant/project-info.html index 52eee0113..f97296ae8 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 e0b1d2343..8203aad6c 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 bbd602b98..4aa52ae8c 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 1250faa72..880c2d00c 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 153eccf3f..9e894dd88 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-core
    Current Version1.4.2
    1.4.3
    Scope compile
    dependency-check-utils
    Current Version1.4.2
    1.4.3
    Scope compile
    dependency-check-ant
    Version1.4.2
    1.4.3
    Type jar
    0 0 100%16.967

    +16.115

    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.967
    +16.115

    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.967

    +16.115

    Test Cases

    [Summary] [Package List] [Test Cases]

    @@ -312,19 +312,19 @@ function toggleDisplay(elementId) { testGetFailBuildOnCVSS -0.454 +0.317 testAddDirSet -7.177 +6.823 testAddFileSet -4.975 +4.663 testAddFileList -4.258

    +4.244
    diff --git a/dependency-check-ant/taglist.html b/dependency-check-ant/taglist.html index ea957f8cb..4afe3fb96 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 846133cc7..1a748342b 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 a6c03eb1f..2cc37fffa 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.2 Reference + Dependency-Check Ant Task 1.4.3 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 2165a446e..5f18161b7 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.2 Reference Package org.owasp.dependencycheck.taskdefs + Dependency-Check Ant Task 1.4.3 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 a3b1934f2..159df5aeb 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.2 Reference Package org.owasp.dependencycheck.taskdefs + Dependency-Check Ant Task 1.4.3 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 a9ab11169..b7cdf2a83 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.2 Reference + Dependency-Check Ant Task 1.4.3 Reference diff --git a/dependency-check-ant/xref-test/overview-summary.html b/dependency-check-ant/xref-test/overview-summary.html index 43107983f..1e7563905 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.2 Reference + Dependency-Check Ant Task 1.4.3 Reference @@ -24,7 +24,7 @@ -

    Dependency-Check Ant Task 1.4.2 Reference

    +

    Dependency-Check Ant Task 1.4.3 Reference

    diff --git a/dependency-check-ant/xref/index.html b/dependency-check-ant/xref/index.html index a6c03eb1f..2cc37fffa 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.2 Reference + Dependency-Check Ant Task 1.4.3 Reference 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 ae86307de..2b11c19df 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.2 Reference Package org.owasp.dependencycheck.ant.logging + Dependency-Check Ant Task 1.4.3 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 d61fa2b55..4a041fea8 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.2 Reference Package org.owasp.dependencycheck.ant.logging + Dependency-Check Ant Task 1.4.3 Reference Package org.owasp.dependencycheck.ant.logging 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 74f9d9c4c..683c19176 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.2 Reference Package org.owasp.dependencycheck.taskdefs + Dependency-Check Ant Task 1.4.3 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 20dbdc8cf..aa7ba8d8a 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.2 Reference Package org.owasp.dependencycheck.taskdefs + Dependency-Check Ant Task 1.4.3 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 fd362348d..56f691028 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.2 Reference Package org.slf4j.impl + Dependency-Check Ant Task 1.4.3 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 01dd2fbda..65fb0ceeb 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.2 Reference Package org.slf4j.impl + Dependency-Check Ant Task 1.4.3 Reference Package org.slf4j.impl diff --git a/dependency-check-ant/xref/overview-frame.html b/dependency-check-ant/xref/overview-frame.html index b7e15bc6a..9e7c3a85a 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.2 Reference + Dependency-Check Ant Task 1.4.3 Reference diff --git a/dependency-check-ant/xref/overview-summary.html b/dependency-check-ant/xref/overview-summary.html index 73645d9c9..6b8932af8 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.2 Reference + Dependency-Check Ant Task 1.4.3 Reference @@ -24,7 +24,7 @@ -

    Dependency-Check Ant Task 1.4.2 Reference

    +

    Dependency-Check Ant Task 1.4.3 Reference

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

    Dependency Management

    @@ -318,7 +318,7 @@ - + @@ -326,7 +326,7 @@ - + @@ -522,7 +522,7 @@ - + @@ -531,7 +531,7 @@ - + @@ -546,6 +546,18 @@ + + + + + + + + + + + + @@ -557,7 +569,7 @@ - + @@ -569,7 +581,7 @@ - + @@ -581,7 +593,7 @@ - + @@ -593,7 +605,7 @@ - + @@ -605,7 +617,7 @@ - + @@ -617,7 +629,7 @@ - + @@ -629,7 +641,7 @@ - + @@ -641,7 +653,7 @@ - + @@ -656,7 +668,7 @@

    Dependencies

    1.4.177
    com.sun.mail mailapi 1.5.5 jar 1.5.6
    org.apache.maven.plugin-tools maven-plugin-annotations 3.4jar 3.5
    org.apache.maven.sharedmaven-dependency-tree2.2jar3.0
    org.apache.velocity velocity
    org.glassfish javax.json
    org.hamcrest hamcrest-core
    org.jmockit jmockit 1.25
    org.jsoup jsoup
    org.slf4j slf4j-api
    org.slf4j slf4j-simple
    org.sonatype.plexus plexus-sec-dispatcher
    Status Group Id Artifact Id
    - + @@ -668,11 +680,23 @@ - + - + + + + + + + + + + + + + @@ -681,18 +705,6 @@ - - - - - - - - - - - - @@ -710,25 +722,25 @@

    ch.qos.logback:logback-classic

    Status Group Id Artifact IdNext Incremental Next Minor Next Major
    org.owasp dependency-check-core1.4.21.4.3compilejar
    org.owaspdependency-check-utils1.4.3 compile jar
    org.owaspdependency-check-utils1.4.2compilejar
    Status Group Id Artifact Id
    - + - + - + - + - + - + - +
    Status  No newer versions available.
    Group Id ch.qos.logback
    Artifact Id logback-classic
    Current Version 1.1.7
    Scope
    Classifier
    Type jar
    @@ -811,7 +823,7 @@ - + @@ -829,7 +841,10 @@ -
    Status No newer versions available.
     There is at least one newer incremental version available. Incremental updates are typically passive.
    Group Id com.sun.mail
    Typejar
    +jar + +Newer versions +1.5.6 Next Incremental

    commons-cli:commons-cli

    @@ -1054,7 +1069,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.lucene:lucene-core

    @@ -1081,7 +1096,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.lucene:lucene-queryparser

    @@ -1108,7 +1123,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.lucene:lucene-test-framework

    @@ -1135,7 +1150,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.maven:maven-core

    @@ -1237,7 +1252,7 @@
    - + @@ -1255,7 +1270,10 @@ -
    Status No newer versions available.
     There is at least one newer minor version available. Minor updates are sometimes passive.
    Group Id org.apache.maven.plugin-tools
    Typejar
    +jar + +Newer versions +3.5 Next Minor

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

    @@ -1281,6 +1299,33 @@
    Type jar
    +

    org.apache.maven.shared:maven-dependency-tree

    + + + + + + + + + + + + + + + + + + + + + + + + +
    Status There is at least one newer major version available. Major updates are rarely passive.
    Group Idorg.apache.maven.shared
    Artifact Idmaven-dependency-tree
    Current Version2.2
    Scope
    Classifier
    Typejar
    Newer versions3.0 Next Major
    +

    org.apache.velocity:velocity

    @@ -1378,7 +1423,7 @@ -
    jar
    Newer versions1.25 Next Minor
    +1.25 Next Minor
    1.26
    1.27 Latest Minor

    org.jsoup:jsoup

    @@ -1417,7 +1462,7 @@ - + @@ -1441,7 +1486,7 @@ - + diff --git a/dependency-check-cli/findbugs.html b/dependency-check-cli/findbugs.html index 510e324b9..3edbb5812 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 b20d3ce7d..17fe20d5e 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,7 +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:

    +

    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
    diff --git a/dependency-check-cli/integration.html b/dependency-check-cli/integration.html
    index f0eb2ab2c..1a9efc9db 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 5744c112e..e09b4be67 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 0a539e996..fb81d4032 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 44d190e02..a90d72d99 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 b852bab4d..dffdbb034 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 @@
             
    diff --git a/dependency-check-cli/pmd.html b/dependency-check-cli/pmd.html
    index 90153773a..598e407ce 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 @@
     
    -
    dependency-check-core
    Current Version1.4.2
    1.4.3
    Scope compile
    dependency-check-utils
    Current Version1.4.2
    1.4.3
    Scope compile
    Line
    Useless parentheses.235
    +240

    org/owasp/dependencycheck/CliParser.java

    @@ -255,58 +255,64 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + -
    132
    Useless parentheses.508
    199
    Useless parentheses.517
    199
    Useless parentheses.526
    512
    Useless parentheses.555
    521
    Useless parentheses.565
    530
    Useless parentheses.575
    559
    Useless parentheses.585
    569
    Useless parentheses.596
    579
    Useless parentheses.606
    589
    Useless parentheses.616
    600
    Useless parentheses.626
    610
    Useless parentheses.636
    620
    Useless parentheses.646
    630
    Useless parentheses.656
    640
    Useless parentheses.666
    650
    Useless parentheses.676
    660
    Useless parentheses.686
    670
    Useless parentheses.696
    +680 + +Useless parentheses. +690 + +Useless parentheses. +700 diff --git a/dependency-check-cli/project-info.html b/dependency-check-cli/project-info.html index a98130d78..531445810 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 af61c73a6..6896d439d 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 550d35be5..95f1b3520 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.2 +1.4.3 Type jar diff --git a/dependency-check-cli/source-repository.html b/dependency-check-cli/source-repository.html index 7321eb37e..cdeb0e72e 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 5fbe2ccbe..f530e711e 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.497
    +0.371

    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.497
    +0.371

    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.497 +0.336 CliParserTest @@ -318,7 +318,7 @@ function toggleDisplay(elementId) { 0 0 100% -0

    +0.035

    Test Cases

    [Summary] [Package List] [Test Cases]

    @@ -328,7 +328,7 @@ function toggleDisplay(elementId) { testEnsureCanonicalPath2 -0.428 +0.255 testEnsureCanonicalPath @@ -339,7 +339,7 @@ function toggleDisplay(elementId) { testParse_printHelp -0 +0.026 testParse_printVersionInfo @@ -351,7 +351,7 @@ function toggleDisplay(elementId) { testParse_scan -0 +0.001 testParse @@ -359,11 +359,11 @@ function toggleDisplay(elementId) { testParse_unknown -0 +0.001 testParse_version -0 +0.001 testParse_scan_unknownFile @@ -371,7 +371,7 @@ function toggleDisplay(elementId) { testParse_scan_withFileExists -0

    +0.002
    diff --git a/dependency-check-cli/taglist.html b/dependency-check-cli/taglist.html index 877490858..d9d68c67a 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 0cfebe53c..9a5ba503b 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 985be0807..e557c4b07 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.2 Reference + Dependency-Check Command Line 1.4.3 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 0f6e05577..41c25114f 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.2 Reference Package org.owasp.dependencycheck + Dependency-Check Command Line 1.4.3 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 4071821a5..8fbdc2037 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.2 Reference Package org.owasp.dependencycheck + Dependency-Check Command Line 1.4.3 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 587d5b4bc..8dccbdb4d 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.2 Reference + Dependency-Check Command Line 1.4.3 Reference diff --git a/dependency-check-cli/xref-test/overview-summary.html b/dependency-check-cli/xref-test/overview-summary.html index 49ca818ac..d03aa3af5 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.2 Reference + Dependency-Check Command Line 1.4.3 Reference @@ -24,7 +24,7 @@ -

    Dependency-Check Command Line 1.4.2 Reference

    +

    Dependency-Check Command Line 1.4.3 Reference

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

    Dependency-Check Command Line 1.4.2 Reference

    +

    Dependency-Check Command Line 1.4.3 Reference

    diff --git a/dependency-check-core/apidocs/allclasses-frame.html b/dependency-check-core/apidocs/allclasses-frame.html index 96aae0fc8..622197446 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.2 API) - +All Classes (Dependency-Check Core 1.4.3 API) + @@ -31,6 +31,7 @@
  • CentralAnalyzer
  • CentralSearch
  • CMakeAnalyzer
  • +
  • CocoaPodsAnalyzer
  • ComposerDependency
  • ComposerException
  • ComposerLockAnalyzer
  • @@ -133,6 +134,7 @@
  • SuppressionParseException
  • SuppressionParser
  • SuppressionRule
  • +
  • SwiftPackageManagerAnalyzer
  • TokenPairConcatenatingFilter
  • UpdateableNvdCve
  • UpdateException
  • diff --git a/dependency-check-core/apidocs/allclasses-noframe.html b/dependency-check-core/apidocs/allclasses-noframe.html index 05bcb92e1..cb9cfef01 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.2 API) - +All Classes (Dependency-Check Core 1.4.3 API) + @@ -31,6 +31,7 @@
  • CentralAnalyzer
  • CentralSearch
  • CMakeAnalyzer
  • +
  • CocoaPodsAnalyzer
  • ComposerDependency
  • ComposerException
  • ComposerLockAnalyzer
  • @@ -133,6 +134,7 @@
  • SuppressionParseException
  • SuppressionParser
  • SuppressionRule
  • +
  • SwiftPackageManagerAnalyzer
  • TokenPairConcatenatingFilter
  • UpdateableNvdCve
  • UpdateException
  • diff --git a/dependency-check-core/apidocs/constant-values.html b/dependency-check-core/apidocs/constant-values.html index 3e89fa51d..51016ea19 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.2 API) - +Constant Field Values (Dependency-Check Core 1.4.3 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/agent/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/agent/package-summary.html index f420cff1f..e1b76cb39 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.2 API) - +org.owasp.dependencycheck.agent (Dependency-Check Core 1.4.3 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,13 +13,13 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ + + + + + +
    + + +
    Skip navigation links
    + + + + +
    + + + +
    +
    org.owasp.dependencycheck.analyzer
    +

    Class CocoaPodsAnalyzer

    +
    +
    + +
    + +
    +
    +
    + + + + + + + + + +
    Fields 
    Modifier and TypeField and Description
    static StringPODSPEC +
    The file name to scan.
    +
    + + + + + + + + + +
    + +
    + + + +
    + + +
    Skip navigation links
    + + + + +
    + + +

    Copyright? 2012-15 Jeremy Long. All Rights Reserved.

    + + diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.html index c04fa3029..8fa69abd4 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.html @@ -2,10 +2,10 @@ - + -ComposerLockAnalyzer (Dependency-Check Core 1.4.2 API) - +ComposerLockAnalyzer (Dependency-Check Core 1.4.3 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 @@ + + + + + +
    + + +
    Skip navigation links
    + + + + +
    + + + +
    +
    org.owasp.dependencycheck.analyzer
    +

    Class SwiftPackageManagerAnalyzer

    +
    +
    + +
    + +
    +
    + +
    +
    + +
    +
    + + +
    + + +
    Skip navigation links
    + + + + +
    + + +

    Copyright? 2012-15 Jeremy Long. All Rights Reserved.

    + + diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzer.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzer.html index ee1b3e5d8..66a3d7f16 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzer.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzer.html @@ -2,10 +2,10 @@ - + -VulnerabilitySuppressionAnalyzer (Dependency-Check Core 1.4.2 API) - +VulnerabilitySuppressionAnalyzer (Dependency-Check Core 1.4.3 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 @@ + + + + + +
    + + +
    Skip navigation links
    + + + + +
    + + +
    +

    Uses of Class
    org.owasp.dependencycheck.analyzer.CocoaPodsAnalyzer

    +
    +
    No usage of org.owasp.dependencycheck.analyzer.CocoaPodsAnalyzer
    + +
    + + +
    Skip navigation links
    + + + + +
    + + +

    Copyright? 2012-15 Jeremy Long. All Rights Reserved.

    + + diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/class-use/ComposerLockAnalyzer.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/class-use/ComposerLockAnalyzer.html index be143b5b0..a9eea2fc5 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/class-use/ComposerLockAnalyzer.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/class-use/ComposerLockAnalyzer.html @@ -2,10 +2,10 @@ - + -Uses of Class org.owasp.dependencycheck.analyzer.ComposerLockAnalyzer (Dependency-Check Core 1.4.2 API) - +Uses of Class org.owasp.dependencycheck.analyzer.ComposerLockAnalyzer (Dependency-Check Core 1.4.3 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 @@ + + + + + +
    + + +
    Skip navigation links
    + + + + +
    + + +
    +

    Uses of Class
    org.owasp.dependencycheck.analyzer.SwiftPackageManagerAnalyzer

    +
    +
    No usage of org.owasp.dependencycheck.analyzer.SwiftPackageManagerAnalyzer
    + +
    + + +
    Skip navigation links
    + + + + +
    + + +

    Copyright? 2012-15 Jeremy Long. All Rights Reserved.

    + + diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/class-use/VulnerabilitySuppressionAnalyzer.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/class-use/VulnerabilitySuppressionAnalyzer.html index 7d8ebbb31..ae80e0f1a 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/class-use/VulnerabilitySuppressionAnalyzer.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/class-use/VulnerabilitySuppressionAnalyzer.html @@ -2,10 +2,10 @@ - + -Uses of Class org.owasp.dependencycheck.analyzer.VulnerabilitySuppressionAnalyzer (Dependency-Check Core 1.4.2 API) - +Uses of Class org.owasp.dependencycheck.analyzer.VulnerabilitySuppressionAnalyzer (Dependency-Check Core 1.4.3 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-core/apidocs/org/owasp/dependencycheck/analyzer/exception/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/exception/package-summary.html index a7fd53a4a..4df0d8681 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.2 API) - +org.owasp.dependencycheck.analyzer.exception (Dependency-Check Core 1.4.3 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -28,6 +28,7 @@
  • AutoconfAnalyzer
  • CentralAnalyzer
  • CMakeAnalyzer
  • +
  • CocoaPodsAnalyzer
  • ComposerLockAnalyzer
  • CPEAnalyzer
  • CpeSuppressionAnalyzer
  • @@ -47,6 +48,7 @@
  • RubyBundleAuditAnalyzer
  • RubyBundlerAnalyzer
  • RubyGemspecAnalyzer
  • +
  • SwiftPackageManagerAnalyzer
  • VulnerabilitySuppressionAnalyzer
  • Enums

    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 579152a90..aacc9d20d 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.2 API) - +org.owasp.dependencycheck.analyzer (Dependency-Check Core 1.4.3 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 7f5e888e6..e7ff0a544 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.2 API) - +org.owasp.dependencycheck.data.central (Dependency-Check Core 1.4.3 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 034f92e81..af2b1942f 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.2 API) - +org.owasp.dependencycheck.data.composer (Dependency-Check Core 1.4.3 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 1c0021853..3661f7874 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.2 API) - +org.owasp.dependencycheck.data.cpe (Dependency-Check Core 1.4.3 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 5656722b9..4e3ec45e5 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.2 API) - +org.owasp.dependencycheck.data.cwe (Dependency-Check Core 1.4.3 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 9ade01397..a6170cec0 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.2 API) - +org.owasp.dependencycheck.data.lucene (Dependency-Check Core 1.4.3 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 04f0bf987..b05a3e82d 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.2 API) - +org.owasp.dependencycheck.data.nexus (Dependency-Check Core 1.4.3 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 ab2403406..683fc8a20 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.2 API) - +org.owasp.dependencycheck.data.nuget (Dependency-Check Core 1.4.3 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 58dcfdab8..d58a8490a 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.2 API) - +org.owasp.dependencycheck.data.nvdcve (Dependency-Check Core 1.4.3 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,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 @@ 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 1e84874a7..8e4c9e640 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.2 API) - +org.owasp.dependencycheck.data.update.cpe (Dependency-Check Core 1.4.3 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 ca602850d..bf32ccc6c 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.2 API) - +org.owasp.dependencycheck.data.update.exception (Dependency-Check Core 1.4.3 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 5b5df8ac5..cfefffdac 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.2 API) - +org.owasp.dependencycheck.data.update.nvd (Dependency-Check Core 1.4.3 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 4b792a5a8..f604098f7 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.2 API) - +org.owasp.dependencycheck.data.update (Dependency-Check Core 1.4.3 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 58d53a845..295c0cdcc 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.2 API) - +org.owasp.dependencycheck.dependency (Dependency-Check Core 1.4.3 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 2bc5c65c5..432570c8a 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.2 API) - +org.owasp.dependencycheck.exception (Dependency-Check Core 1.4.3 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 20cec8787..9bada77b1 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.2 API) - +org.owasp.dependencycheck (Dependency-Check Core 1.4.3 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 a3937106f..9aae5f043 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.2 API) - +org.owasp.dependencycheck.reporting (Dependency-Check Core 1.4.3 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 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -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 ffa5f861d..696a8c465 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.2 API) - +org.owasp.dependencycheck.utils (Dependency-Check Core 1.4.3 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,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 @@ 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 c5d972a04..16720447c 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.2 API) - +org.owasp.dependencycheck.xml.hints (Dependency-Check Core 1.4.3 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 147a7ec1e..29be3fc47 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.2 API) - +org.owasp.dependencycheck.xml.pom (Dependency-Check Core 1.4.3 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 28dd40131..3156382e6 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.2 API) - +org.owasp.dependencycheck.xml.suppression (Dependency-Check Core 1.4.3 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 04a0f45b4..7dae7e249 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.2 API) - +Overview (Dependency-Check Core 1.4.3 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 e05aa2233..d882c8ff7 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 @@ -16,7 +16,7 @@ - +
    Package # Classes Line Coverage Branch Coverage Complexity
    org.owasp.dependencycheck.analyzer.exception2
    25%
    4/16
    N/A
    1
    org.owasp.dependencycheck.analyzer.exception2
    12%
    2/16
    N/A
    1
    - + 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 51b613639..8ada35276 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,8 +16,8 @@ - - + +
    Package # Classes Line Coverage Branch Coverage Complexity
    org.owasp.dependencycheck.analyzer37
    58%
    1676/2856
    43%
    664/1534
    4.669
    org.owasp.dependencycheck.analyzer.exception2
    25%
    4/16
    N/A
    1
    org.owasp.dependencycheck.analyzer39
    58%
    1757/3029
    42%
    689/1628
    4.67
    org.owasp.dependencycheck.analyzer.exception2
    12%
    2/16
    N/A
    1
    - + 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 ea7945662..889f19382 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 @@ - +
    Package # Classes Line Coverage Branch Coverage Complexity
    org.owasp.dependencycheck.data.central1
    83%
    51/61
    83%
    20/24
    10
    org.owasp.dependencycheck.data.central1
    86%
    53/61
    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 209f120a1..fbb767a97 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 a64125802..46a21f5f6 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 @@ -16,7 +16,7 @@ - +
    Package # Classes Line Coverage Branch Coverage Complexity
    org.owasp.dependencycheck.data.cpe4
    69%
    100/143
    41%
    23/56
    2.552
    org.owasp.dependencycheck.data.cpe4
    70%
    101/144
    43%
    26/60
    2.621
    - + 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 b53d8c582..ac0f568b1 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 0d09ba940..b1d1bcf83 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 62211709e..69524717a 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 @@ -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.nuget.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.nuget.html index 34b89a7be..c553c8c24 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 @@ -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.nvdcve.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.nvdcve.html index cd5f8327e..92f48c732 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 @@ -16,7 +16,7 @@ - +
    Package # Classes Line Coverage Branch Coverage Complexity
    org.owasp.dependencycheck.data.nvdcve9
    41%
    313/749
    43%
    93/216
    4.177
    org.owasp.dependencycheck.data.nvdcve9
    41%
    315/754
    43%
    96/222
    4.258
    - + 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 d4fe6b6b4..149c1c0f3 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 3c5bb3b8c..f2ef4da87 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 285d2a859..4dde40b0f 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
    14%
    52/347
    11%
    14/122
    5.68
    org.owasp.dependencycheck.data.update6
    15%
    52/345
    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%
    290/415
    69%
    134/194
    2.865
    org.owasp.dependencycheck.data.update.nvd8
    69%
    289/413
    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 b878ba377..5d1e7b5a6 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%
    290/415
    69%
    134/194
    2.865
    org.owasp.dependencycheck.data.update.nvd8
    69%
    289/413
    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 58bad1df8..27cb3fdee 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
    64%
    412/639
    55%
    162/294
    1.989
    org.owasp.dependencycheck.dependency14
    63%
    408/639
    54%
    157/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 6c7bcbdfe..3c6d610f1 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
    7%
    6/85
    0%
    0/4
    1.065
    org.owasp.dependencycheck.exception5
    6%
    6/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 4823ffb2b..3ba4ebb21 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.html @@ -18,27 +18,27 @@ org.owasp.dependencycheck1
    55%
    116/208
    62%
    41/66
    3.478 org.owasp.dependencycheck.agent1
    0%
    0/231
    0%
    0/38
    1.375 - org.owasp.dependencycheck.analyzer37
    58%
    1676/2856
    43%
    664/1534
    4.669 - org.owasp.dependencycheck.analyzer.exception2
    25%
    4/16
    N/A
    1 - org.owasp.dependencycheck.data.central1
    83%
    51/61
    83%
    20/24
    10 + org.owasp.dependencycheck.analyzer39
    58%
    1757/3029
    42%
    689/1628
    4.67 + 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.composer3
    79%
    53/67
    45%
    19/42
    3.417 - org.owasp.dependencycheck.data.cpe4
    69%
    100/143
    41%
    23/56
    2.552 + 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.nvdcve9
    41%
    313/749
    43%
    93/216
    4.177 - org.owasp.dependencycheck.data.update6
    14%
    52/347
    11%
    14/122
    5.68 + 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.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%
    290/415
    69%
    134/194
    2.865 - org.owasp.dependencycheck.dependency14
    64%
    412/639
    55%
    162/294
    1.989 - org.owasp.dependencycheck.exception5
    7%
    6/85
    0%
    0/4
    1.065 + 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.reporting4
    0%
    0/164
    0%
    0/90
    5.6 - org.owasp.dependencycheck.utils11
    63%
    231/364
    60%
    113/186
    3.759 - org.owasp.dependencycheck.xml.hints7
    70%
    113/161
    62%
    25/40
    2.152 - org.owasp.dependencycheck.xml.pom7
    61%
    133/217
    54%
    38/70
    2.286 - org.owasp.dependencycheck.xml.suppression6
    74%
    254/342
    64%
    118/182
    3.286 + 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 - + 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 e0252741a..8db2f0781 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 33ded339f..e5c5cfd8d 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%
    231/364
    60%
    113/186
    3.759
    org.owasp.dependencycheck.utils11
    63%
    237/371
    61%
    117/190
    3.782
    - + 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 a64947858..ec4bdfc3b 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
    70%
    113/161
    62%
    25/40
    2.152
    org.owasp.dependencycheck.xml.hints7
    71%
    128/178
    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 dace7da1d..27c978578 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
    61%
    133/217
    54%
    38/70
    2.286
    org.owasp.dependencycheck.xml.pom7
    60%
    132/218
    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 cb410ec49..16a3a8250 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
    74%
    254/342
    64%
    118/182
    3.286
    org.owasp.dependencycheck.xml.suppression6
    73%
    261/353
    64%
    120/186
    3.357
    - + diff --git a/dependency-check-core/cobertura/frame-summary.html b/dependency-check-core/cobertura/frame-summary.html index 3501fd6de..5a5d9e044 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 Packages147
    53%
    3980/7471
    45%
    1510/3320
    3.171
    All Packages149
    53%
    4086/7689
    45%
    1551/3438
    3.207
    org.owasp.dependencycheck1
    55%
    116/208
    62%
    41/66
    3.478
    org.owasp.dependencycheck.agent1
    0%
    0/231
    0%
    0/38
    1.375
    org.owasp.dependencycheck.analyzer37
    58%
    1676/2856
    43%
    664/1534
    4.669
    org.owasp.dependencycheck.analyzer.exception2
    25%
    4/16
    N/A
    1
    org.owasp.dependencycheck.data.central1
    83%
    51/61
    83%
    20/24
    10
    org.owasp.dependencycheck.analyzer39
    58%
    1757/3029
    42%
    689/1628
    4.67
    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.composer3
    79%
    53/67
    45%
    19/42
    3.417
    org.owasp.dependencycheck.data.cpe4
    69%
    100/143
    41%
    23/56
    2.552
    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.nvdcve9
    41%
    313/749
    43%
    93/216
    4.177
    org.owasp.dependencycheck.data.update6
    14%
    52/347
    11%
    14/122
    5.68
    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.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%
    290/415
    69%
    134/194
    2.865
    org.owasp.dependencycheck.dependency14
    64%
    412/639
    55%
    162/294
    1.989
    org.owasp.dependencycheck.exception5
    7%
    6/85
    0%
    0/4
    1.065
    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.reporting4
    0%
    0/164
    0%
    0/90
    5.6
    org.owasp.dependencycheck.utils11
    63%
    231/364
    60%
    113/186
    3.759
    org.owasp.dependencycheck.xml.hints7
    70%
    113/161
    62%
    25/40
    2.152
    org.owasp.dependencycheck.xml.pom7
    61%
    133/217
    54%
    38/70
    2.286
    org.owasp.dependencycheck.xml.suppression6
    74%
    254/342
    64%
    118/182
    3.286
    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
    - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.Engine.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.Engine.html index 6d5a15d42..a4c3ec765 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.Engine.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.Engine.html @@ -273,12 +273,12 @@  138  4
             final AnalyzerService service = new AnalyzerService(serviceClassLoader);
     139  4
             final List<Analyzer> iterator = service.getAnalyzers();
     140  4
             for (Analyzer a : iterator) {
    -  141  96
                 analyzers.get(a.getAnalysisPhase()).add(a);
    -  142  96
                 if (a instanceof FileTypeAnalyzer) {
    -  143  64
                     this.fileTypeAnalyzers.add((FileTypeAnalyzer) a);
    +  141  104
                 analyzers.get(a.getAnalysisPhase()).add(a);
    +  142  104
                 if (a instanceof FileTypeAnalyzer) {
    +  143  72
                     this.fileTypeAnalyzers.add((FileTypeAnalyzer) a);
     144  
                 }
    -  145  96
             }
    +  145  104
             }
     146  4
         }
     147  
     
    @@ -516,17 +516,17 @@
          */
     281  
         protected List<Dependency> scanDirectory(File dir) {
    -  282  10
             final File[] files = dir.listFiles();
    -  283  10
             final List<Dependency> deps = new ArrayList<Dependency>();
    -  284  10
             if (files != null) {
    -  285  21
                 for (File f : files) {
    -  286  11
                     if (f.isDirectory()) {
    -  287  7
                         final List<Dependency> d = scanDirectory(f);
    -  288  7
                         if (d != null) {
    -  289  7
                             deps.addAll(d);
    +  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  7
                     } else {
    +  291  43
                     } else {
     292  4
                         final Dependency d = scanFile(f);
     293  4
                         deps.add(d);
     294   @@ -535,7 +535,7 @@
                 }
     296  
             }
    -  297  10
             return deps;
    +  297  46
             return deps;
     298  
         }
     299   @@ -648,7 +648,7 @@  369  
     
     370  2
             LOGGER.debug("\n----------------------------------------------------\nBEGIN ANALYSIS\n----------------------------------------------------");
    -  371  2
             LOGGER.info("Analysis Starting");
    +  371  2
             LOGGER.info("Analysis Started");
     372  2
             final long analysisStart = System.currentTimeMillis();
     373  
     
    @@ -661,11 +661,11 @@  378  20
                 for (Analyzer a : analyzerList) {
     379  
                     try {
    -  380  48
                         a = initializeAnalyzer(a);
    +  380  52
                         a = initializeAnalyzer(a);
     381  1
                     } catch (InitializationException ex) {
     382  1
                         exceptions.add(ex);
     383  1
                         continue;
    -  384  47
                     }
    +  384  51
                     }
     385  
     
     386   @@ -676,16 +676,16 @@
                      * This is okay for adds/deletes because it happens per analyzer.
     389  
                      */
    -  390  47
                     LOGGER.debug("Begin Analyzer '{}'", a.getName());
    -  391  47
                     final Set<Dependency> dependencySet = new HashSet<Dependency>(dependencies);
    -  392  47
                     for (Dependency d : dependencySet) {
    -  393  94
                         boolean shouldAnalyze = true;
    -  394  94
                         if (a instanceof FileTypeAnalyzer) {
    -  395  62
                             final FileTypeAnalyzer fAnalyzer = (FileTypeAnalyzer) a;
    -  396  62
                             shouldAnalyze = fAnalyzer.accept(d.getActualFile());
    +  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());
     397  
                         }
    -  398  94
                         if (shouldAnalyze) {
    +  398  102
                         if (shouldAnalyze) {
     399  38
                             LOGGER.debug("Begin Analysis of '{}'", d.getActualFilePath());
     400  
                             try {
    @@ -703,8 +703,8 @@  411  38
                             }
     412  
                         }
    -  413  94
                     }
    -  414  47
                 }
    +  413  102
                     }
    +  414  51
                 }
     415  
             }
     416  22
             for (AnalysisPhase phase : AnalysisPhase.values()) {
    @@ -712,8 +712,8 @@  418  
     
     419  20
                 for (Analyzer a : analyzerList) {
    -  420  48
                     closeAnalyzer(a);
    -  421  48
                 }
    +  420  52
                     closeAnalyzer(a);
    +  421  52
                 }
     422  
             }
     423   @@ -747,8 +747,8 @@
         protected Analyzer initializeAnalyzer(Analyzer analyzer) throws InitializationException {
     440  
             try {
    -  441  48
                 LOGGER.debug("Initializing {}", analyzer.getName());
    -  442  48
                 analyzer.initialize();
    +  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);
    @@ -769,8 +769,8 @@  458  0
                     LOGGER.trace("", ex1);
     459  0
                 }
     460  0
                 throw new InitializationException("Unexpected Exception", ex);
    -  461  47
             }
    -  462  47
             return analyzer;
    +  461  51
             }
    +  462  51
             return analyzer;
     463  
         }
     464   @@ -787,14 +787,14 @@
          */
     470  
         protected void closeAnalyzer(Analyzer analyzer) {
    -  471  48
             LOGGER.debug("Closing Analyzer '{}'", analyzer.getName());
    +  471  52
             LOGGER.debug("Closing Analyzer '{}'", analyzer.getName());
     472  
             try {
    -  473  48
                 analyzer.close();
    +  473  52
                 analyzer.close();
     474  0
             } catch (Throwable ex) {
     475  0
                 LOGGER.trace("", ex);
    -  476  48
             }
    -  477  48
         }
    +  476  52
             }
    +  477  52
         }
     478  
     
     479   @@ -866,19 +866,19 @@
         @Override
     520  
         public boolean accept(File file) {
    -  521  6
             if (file == null) {
    +  521  855
             if (file == null) {
     522  0
                 return false;
     523  
             }
    -  524  6
             boolean scan = false;
    -  525  6
             for (FileTypeAnalyzer a : this.fileTypeAnalyzers) {
    +  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  96
                 scan |= a.accept(file);
    -  529  96
             }
    -  530  6
             return scan;
    +  528  15390
                 scan |= a.accept(file);
    +  529  15390
             }
    +  530  855
             return scan;
     531  
         }
     532   @@ -937,6 +937,6 @@
     }
    - + 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 f5ef853cc..4c1abe879 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 24c4f1bbf..e4d63a2a7 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AbstractAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AbstractAnalyzer.html @@ -71,7 +71,7 @@
      * @author Jeremy Long
     27  
      */
    -  28  207
     public abstract class AbstractAnalyzer implements Analyzer {
    +  28  231
     public abstract class AbstractAnalyzer implements Analyzer {
     29  
     
     30   @@ -109,11 +109,11 @@
         public void close() throws Exception {
     47  
             //do nothing
    -  48  81
         }
    +  48  97
         }
     49  
     }
    - + 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 1f3daba70..503e01e9d 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  152
         public AbstractFileTypeAnalyzer() {
    -  49  152
             reset();
    -  50  152
         }
    +  48  176
         public AbstractFileTypeAnalyzer() {
    +  49  176
             reset();
    +  50  176
         }
     51  
     //</editor-fold>
     52   @@ -133,7 +133,7 @@
          * Whether the file type analyzer detected any files it needs to analyze.
     60  
          */
    -  61  152
         private boolean filesMatched = false;
    +  61  176
         private boolean filesMatched = false;
     62  
     
     63   @@ -169,8 +169,8 @@
          */
     79  
         protected void setFilesMatched(boolean filesMatched) {
    -  80  44
             this.filesMatched = filesMatched;
    -  81  44
         }
    +  80  56
             this.filesMatched = filesMatched;
    +  81  56
         }
     82  
     
     83   @@ -179,7 +179,7 @@
          * A flag indicating whether or not the analyzer is enabled.
     85  
          */
    -  86  152
         private boolean enabled = true;
    +  86  176
         private boolean enabled = true;
     87  
     
     88   @@ -321,14 +321,14 @@
         @Override
     158  
         public final void initialize() throws InitializationException {
    -  159  82
             if (filesMatched) {
    -  160  51
                 initializeFileTypeAnalyzer();
    +  159  98
             if (filesMatched) {
    +  160  63
                 initializeFileTypeAnalyzer();
     161  
             } else {
    -  162  31
                 enabled = false;
    +  162  35
                 enabled = false;
     163  
             }
    -  164  78
         }
    +  164  94
         }
     165  
     
     166   @@ -341,16 +341,16 @@
         @Override
     170  
         public final void reset() {
    -  171  152
             final String key = getAnalyzerEnabledSettingKey();
    +  171  176
             final String key = getAnalyzerEnabledSettingKey();
     172  
             try {
    -  173  152
                 enabled = Settings.getBoolean(key, true);
    +  173  176
                 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  152
             }
    -  179  152
         }
    +  178  176
             }
    +  179  176
         }
     180  
     
     181   @@ -375,8 +375,8 @@
         @Override
     191  
         public final void analyze(Dependency dependency, Engine engine) throws AnalysisException {
    -  192  32
             if (enabled) {
    -  193  32
                 analyzeFileType(dependency, engine);
    +  192  31
             if (enabled) {
    +  193  31
                 analyzeFileType(dependency, engine);
     194  
             }
     195  31
         }
    @@ -386,19 +386,19 @@
         @Override
     198  
         public boolean accept(File pathname) {
    -  199  185
             final FileFilter filter = getFileFilter();
    -  200  185
             boolean accepted = false;
    -  201  185
             if (null == filter) {
    +  199  15489
             final FileFilter filter = getFileFilter();
    +  200  15489
             boolean accepted = false;
    +  201  15489
             if (null == filter) {
     202  0
                 LOGGER.error("The '{}' analyzer is misconfigured and does not have a file filter; it will be disabled", getName());
    -  203  185
             } else if (enabled) {
    -  204  119
                 accepted = filter.accept(pathname);
    -  205  119
                 if (accepted) {
    -  206  39
                     filesMatched = true;
    +  203  15489
             } else if (enabled) {
    +  204  13717
                 accepted = filter.accept(pathname);
    +  205  13717
                 if (accepted) {
    +  206  41
                     filesMatched = true;
     207  
                 }
     208  
             }
    -  209  185
             return accepted;
    +  209  15489
             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 bf66f5499..2a9fd7946 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
    80%
    50/62
    71%
    10/14
    4.333
    AbstractSuppressionAnalyzer
    79%
    54/68
    75%
    12/16
    4.667
     
    @@ -248,79 +248,95 @@  130  1
                     }
     131  1
                 } else {
     132  2
                     file = new File(suppressionFilePath);
    -  133  2
                     if (!file.exists()) {
    -  134  2
                         final InputStream suppressionsFromClasspath = this.getClass().getClassLoader().getResourceAsStream(suppressionFilePath);
    -  135  2
                         if (suppressionsFromClasspath != null) {
    -  136  1
                             deleteTempFile = true;
    -  137  1
                             file = FileUtils.getTempFile("suppression", "xml");
    -  138   -
                             try {
    -  139  1
                                 org.apache.commons.io.FileUtils.copyInputStreamToFile(suppressionsFromClasspath, file);
    -  140  0
                             } catch (IOException ex) {
    -  141  0
                                 throwSuppressionParseException("Unable to locate suppressions file in classpath", ex);
    -  142  1
                             }
    -  143   -
                         }
    -  144   -
                     }
    +  133  2
                     InputStream suppressionsFromClasspath = null;
    +  134  2
                     if (!file.exists()) {
    +  135   +
                         try {
    +  136  2
                             suppressionsFromClasspath = this.getClass().getClassLoader().getResourceAsStream(suppressionFilePath);
    +  137  2
                             if (suppressionsFromClasspath != null) {
    +  138  1
                                 deleteTempFile = true;
    +  139  1
                                 file = FileUtils.getTempFile("suppression", "xml");
    +  140   +
                                 try {
    +  141  1
                                     org.apache.commons.io.FileUtils.copyInputStreamToFile(suppressionsFromClasspath, file);
    +  142  0
                                 } catch (IOException ex) {
    +  143  0
                                     throwSuppressionParseException("Unable to locate suppressions file in classpath", ex);
    +  144  1
                                 }
     145   -
                 }
    -  146  3
                 if (file != null) {
    -  147   -
                     try {
    -  148  3
                         rules.addAll(parser.parseSuppressionRules(file));
    -  149  2
                         LOGGER.debug("{} suppression rules were loaded.", rules.size());
    -  150  1
                     } catch (SuppressionParseException ex) {
    -  151  1
                         LOGGER.warn("Unable to parse suppression xml file '{}'", file.getPath());
    -  152  1
                         LOGGER.warn(ex.getMessage());
    -  153  1
                         throw ex;
    -  154  2
                     }
    +
                             }
    +  146   +
                         } finally {
    +  147  2
                             if (suppressionsFromClasspath != null) {
    +  148   +
                                 try {
    +  149  1
                                     suppressionsFromClasspath.close();
    +  150  0
                                 } catch (IOException ex) {
    +  151  0
                                     LOGGER.debug("Failed to close stream", ex);
    +  152  1
                                 }
    +  153   +
                             }
    +  154   +
                         }
     155   +
                     }
    +  156  
                 }
    -  156  0
             } catch (DownloadFailedException ex) {
    -  157  0
                 throwSuppressionParseException("Unable to fetch the configured suppression file", ex);
    -  158  0
             } catch (MalformedURLException ex) {
    -  159  0
                 throwSuppressionParseException("Configured suppression file has an invalid URL", ex);
    -  160  1
             } catch (IOException ex) {
    -  161  1
                 throwSuppressionParseException("Unable to create temp file for suppressions", ex);
    -  162   -
             } finally {
    -  163  3
                 if (deleteTempFile && file != null) {
    -  164  2
                     FileUtils.delete(file);
    -  165   -
                 }
    +  157  3
                 if (file != null) {
    +  158   +
                     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   -
             }
    -  167  2
         }
    -  168   -
     
    -  169   -
         /**
    -  170   -
          * Utility method to throw parse exceptions.
    -  171   -
          *
    -  172   -
          * @param message the exception message
    +
                 }
    +  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   -
          * @param exception the cause of the exception
    -  174   -
          * @throws SuppressionParseException throws the generated
    -  175   -
          * SuppressionParseException
    +
             } finally {
    +  174  3
                 if (deleteTempFile && file != null) {
    +  175  2
                     FileUtils.delete(file);
     176   -
          */
    +
                 }
     177   -
         private void throwSuppressionParseException(String message, Exception exception) throws SuppressionParseException {
    -  178  1
             LOGGER.warn(message);
    -  179  1
             LOGGER.debug("", exception);
    -  180  1
             throw new SuppressionParseException(message, exception);
    +
             }
    +  178  2
         }
    +  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  1
             LOGGER.warn(message);
    +  190  1
             LOGGER.debug("", exception);
    +  191  1
             throw new SuppressionParseException(message, exception);
    +  192   +
         }
    +  193  
     }
    - + 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 a30fd12fd..901c52570 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AnalysisPhase.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AnalysisPhase.html @@ -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 f5468d744..455e9bc2b 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.Analyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.Analyzer.html @@ -175,6 +175,6 @@
     }
    - + 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 b1cbed8d0..7dce151fe 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AnalyzerService.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AnalyzerService.html @@ -140,15 +140,15 @@  65  0
             } catch (InvalidSettingException ex) {
     66  0
                 LOGGER.error("invalide experimental setting", ex);
     67  7
             }
    -  68  175
             while (iterator.hasNext()) {
    -  69  168
                 final Analyzer a = iterator.next();
    -  70  168
                 if (!experimentalEnabled && a.getClass().isAnnotationPresent(Experimental.class)) {
    -  71  9
                     continue;
    +  68  189
             while (iterator.hasNext()) {
    +  69  182
                 final Analyzer a = iterator.next();
    +  70  182
                 if (!experimentalEnabled && a.getClass().isAnnotationPresent(Experimental.class)) {
    +  71  11
                     continue;
     72  
                 }
    -  73  159
                 LOGGER.debug("Loaded Analyzer {}", a.getName());
    -  74  159
                 analyzers.add(a);
    -  75  159
             }
    +  73  171
                 LOGGER.debug("Loaded Analyzer {}", a.getName());
    +  74  171
                 analyzers.add(a);
    +  75  171
             }
     76  7
             return analyzers;
     77  
         }
    @@ -156,6 +156,6 @@
     }
    - + 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 543b99e2c..998fe22f8 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
    34%
    78/225
    14%
    20/136
    6.412
    ArchiveAnalyzer
    37%
    86/230
    20%
    28/140
    6.588
     
    @@ -268,7 +268,7 @@
         @Override
     134  
         protected FileFilter getFileFilter() {
    -  135  10
             return FILTER;
    +  135  859
             return FILTER;
     136  
         }
     137   @@ -629,337 +629,348 @@  358  
         private void extractFiles(File archive, File destination, Engine engine) throws AnalysisException {
     359  2
             if (archive != null && destination != null) {
    -  360   +  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;
    -  361   +  367  
                 try {
    -  362  2
                     fis = new FileInputStream(archive);
    -  363  0
                 } catch (FileNotFoundException ex) {
    -  364  0
                     LOGGER.debug("", ex);
    -  365  0
                     throw new AnalysisException("Archive file was not found.", ex);
    -  366  2
                 }
    -  367  2
                 final String archiveExt = FileUtils.getFileExtension(archive.getName()).toLowerCase();
    -  368   +  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 {
    -  369  2
                     if (ZIPPABLES.contains(archiveExt)) {
    -  370  2
                         final BufferedInputStream in = new BufferedInputStream(fis);
    -  371  2
                         ensureReadableJar(archiveExt, in);
    -  372  2
                         extractArchive(new ZipArchiveInputStream(in), destination, engine);
    -  373  2
                     } else if ("tar".equals(archiveExt)) {
    -  374  0
                         extractArchive(new TarArchiveInputStream(new BufferedInputStream(fis)), destination, engine);
    -  375  0
                     } else if ("gz".equals(archiveExt) || "tgz".equals(archiveExt)) {
    -  376  0
                         final String uncompressedName = GzipUtils.getUncompressedFilename(archive.getName());
    -  377  0
                         final File f = new File(destination, uncompressedName);
    -  378  0
                         if (engine.accept(f)) {
    -  379  0
                             decompressFile(new GzipCompressorInputStream(new BufferedInputStream(fis)), f);
    -  380   +  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  
                         }
    -  381  0
                     } else if ("bz2".equals(archiveExt) || "tbz2".equals(archiveExt)) {
    -  382  0
                         final String uncompressedName = BZip2Utils.getUncompressedFilename(archive.getName());
    -  383  0
                         final File f = new File(destination, uncompressedName);
    -  384  0
                         if (engine.accept(f)) {
    -  385  0
                             decompressFile(new BZip2CompressorInputStream(new BufferedInputStream(fis)), f);
    -  386   +  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  
                         }
    -  387   +  392  
                     }
    -  388  0
                 } catch (ArchiveExtractionException ex) {
    -  389  0
                     LOGGER.warn("Exception extracting archive '{}'.", archive.getName());
    -  390  0
                     LOGGER.debug("", ex);
    -  391  0
                 } catch (IOException ex) {
    -  392  0
                     LOGGER.warn("Exception reading archive '{}'.", archive.getName());
    -  393  0
                     LOGGER.debug("", ex);
    -  394   -
                 } finally {
    -  395  2
                     close(fis);
    -  396  2
                 }
    -  397   -
             }
    -  398  2
         }
    +  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   -
     
    -  400   -
         /**
    -  401   -
          * Checks if the file being scanned is a JAR that begins with '#!/bin' which
    +
                 } finally {
    +  400  2
                     close(fis);
    +  401  2
                 }
     402   -
          * indicates it is a fully executable jar. If a fully executable JAR is
    -  403   -
          * identified the input stream will be advanced to the start of the actual
    +
             }
    +  403  2
         }
     404   -
          * JAR file ( skipping the script).
    +
     
     405   -
          *
    +
         /**
     406   -
          * @see
    +
          * Checks if the file being scanned is a JAR that begins with '#!/bin' which
     407   -
          * <a href="http://docs.spring.io/spring-boot/docs/1.3.0.BUILD-SNAPSHOT/reference/htmlsingle/#deployment-install">Installing
    +
          * indicates it is a fully executable jar. If a fully executable JAR is
     408   -
          * Spring Boot Applications</a>
    +
          * identified the input stream will be advanced to the start of the actual
     409   -
          * @param archiveExt the file extension
    +
          * JAR file ( skipping the script).
     410   -
          * @param in the input stream
    +
          *
     411   -
          * @throws IOException thrown if there is an error reading the stream
    +
          * @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 {
    -  414  2
             if ("jar".equals(archiveExt) && in.markSupported()) {
    -  415  2
                 in.mark(7);
    -  416  2
                 final byte[] b = new byte[7];
    -  417  2
                 in.read(b);
    -  418  2
                 if (b[0] == '#'
    -  419   -
                         && b[1] == '!'
    -  420   -
                         && b[2] == '/'
    -  421   -
                         && b[3] == 'b'
    -  422   -
                         && b[4] == 'i'
    -  423   -
                         && b[5] == 'n'
    +  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[6] == '/') {
    -  425  0
                     boolean stillLooking = true;
    +
                         && 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;
    -  427  0
                     while (stillLooking && (chr = in.read()) != -1) {
    -  428  0
                         if (chr == '\n' || chr == '\r') {
    -  429  0
                             in.mark(4);
    -  430  0
                             if ((chr = in.read()) != -1) {
    -  431  0
                                 if (chr == 'P' && (chr = in.read()) != -1) {
    -  432  0
                                     if (chr == 'K' && (chr = in.read()) != -1) {
    -  433  0
                                         if ((chr == 3 || chr == 5 || chr == 7) && (nxtChr = in.read()) != -1) {
    -  434  0
                                             if (nxtChr == chr + 1) {
    -  435  0
                                                 stillLooking = false;
    -  436  0
                                                 in.reset();
    -  437   -
                                             }
    -  438   -
                                         }
    -  439   -
                                     }
    -  440   -
                                 }
    -  441   -
                             }
    -  442   -
                         }
    +  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  2
         }
    +
                                     }
    +  446   +
                                 }
     447   -
     
    -  448   -
         /**
    -  449   -
          * Extracts files from an archive.
    -  450   -
          *
    -  451   -
          * @param input the archive to extract files from
    -  452   -
          * @param destination the location to write the files too
    -  453   -
          * @param engine the dependency-check engine
    -  454   -
          * @throws ArchiveExtractionException thrown if there is an exception
    -  455   -
          * extracting files from the archive
    -  456   -
          */
    -  457   -
         private void extractArchive(ArchiveInputStream input, File destination, Engine engine) throws ArchiveExtractionException {
    -  458   -
             ArchiveEntry entry;
    -  459   -
             try {
    -  460  2
                 while ((entry = input.getNextEntry()) != null) {
    -  461  0
                     final File file = new File(destination, entry.getName());
    -  462  0
                     if (entry.isDirectory()) {
    -  463  0
                         if (!file.exists() && !file.mkdirs()) {
    -  464  0
                             final String msg = String.format("Unable to create directory '%s'.", file.getAbsolutePath());
    -  465  0
                             throw new AnalysisException(msg);
    -  466   -
                         }
    -  467  0
                     } else if (engine.accept(file)) {
    -  468  0
                         extractAcceptedFile(input, file);
    -  469   -
                     }
    -  470  0
                 }
    -  471  0
             } catch (Throwable ex) {
    -  472  0
                 throw new ArchiveExtractionException(ex);
    -  473   -
             } finally {
    -  474  2
                 close(input);
    -  475  2
             }
    -  476  2
         }
    -  477   -
     
    -  478   -
         /**
    -  479   -
          * Extracts a file from an archive.
    -  480   -
          *
    -  481   -
          * @param input the archives input stream
    -  482   -
          * @param file the file to extract
    -  483   -
          * @throws AnalysisException thrown if there is an error
    -  484   -
          */
    -  485   -
         private static void extractAcceptedFile(ArchiveInputStream input, File file) throws AnalysisException {
    -  486  0
             LOGGER.debug("Extracting '{}'", file.getPath());
    -  487  0
             FileOutputStream fos = null;
    -  488   -
             try {
    -  489  0
                 final File parent = file.getParentFile();
    -  490  0
                 if (!parent.isDirectory() && !parent.mkdirs()) {
    -  491  0
                     final String msg = String.format("Unable to build directory '%s'.", parent.getAbsolutePath());
    -  492  0
                     throw new AnalysisException(msg);
    -  493   -
                 }
    -  494  0
                 fos = new FileOutputStream(file);
    -  495  0
                 IOUtils.copy(input, fos);
    -  496  0
             } catch (FileNotFoundException ex) {
    -  497  0
                 LOGGER.debug("", ex);
    -  498  0
                 final String msg = String.format("Unable to find file '%s'.", file.getName());
    -  499  0
                 throw new AnalysisException(msg, ex);
    -  500  0
             } catch (IOException ex) {
    -  501  0
                 LOGGER.debug("", ex);
    -  502  0
                 final String msg = String.format("IO Exception while parsing file '%s'.", file.getName());
    -  503  0
                 throw new AnalysisException(msg, ex);
    -  504   -
             } finally {
    -  505  0
                 close(fos);
    -  506  0
             }
    -  507  0
         }
    -  508   -
     
    -  509   -
         /**
    -  510   -
          * Decompresses a file.
    -  511   -
          *
    -  512   -
          * @param inputStream the compressed file
    -  513   -
          * @param outputFile the location to write the decompressed file
    -  514   -
          * @throws ArchiveExtractionException thrown if there is an exception
    -  515   -
          * decompressing the file
    -  516   -
          */
    -  517   -
         private void decompressFile(CompressorInputStream inputStream, File outputFile) throws ArchiveExtractionException {
    -  518  0
             LOGGER.debug("Decompressing '{}'", outputFile.getPath());
    -  519  0
             FileOutputStream out = null;
    -  520   -
             try {
    -  521  0
                 out = new FileOutputStream(outputFile);
    -  522  0
                 IOUtils.copy(inputStream, out);
    -  523  0
             } catch (FileNotFoundException ex) {
    -  524  0
                 LOGGER.debug("", ex);
    -  525  0
                 throw new ArchiveExtractionException(ex);
    -  526  0
             } catch (IOException ex) {
    -  527  0
                 LOGGER.debug("", ex);
    -  528  0
                 throw new ArchiveExtractionException(ex);
    -  529   -
             } finally {
    -  530  0
                 close(out);
    -  531  0
             }
    -  532  0
         }
    -  533   -
     
    -  534   -
         /**
    -  535   -
          * Close the given {@link Closeable} instance, ignoring nulls, and logging
    -  536   -
          * any thrown {@link IOException}.
    -  537   -
          *
    -  538   -
          * @param closeable to be closed
    -  539   -
          */
    -  540   -
         private static void close(Closeable closeable) {
    -  541  4
             if (null != closeable) {
    -  542   -
                 try {
    -  543  4
                     closeable.close();
    -  544  0
                 } catch (IOException ex) {
    -  545  0
                     LOGGER.trace("", ex);
    -  546  4
                 }
    -  547   -
             }
    -  548  4
         }
    -  549   -
     
    -  550   -
         /**
    -  551   -
          * Attempts to determine if a zip file is actually a JAR file.
    -  552   -
          *
    -  553   -
          * @param dependency the dependency to check
    -  554   -
          * @return true if the dependency appears to be a JAR file; otherwise false
    -  555   -
          */
    -  556   -
         private boolean isZipFileActuallyJarFile(Dependency dependency) {
    -  557  0
             boolean isJar = false;
    -  558  0
             ZipFile zip = null;
    -  559   -
             try {
    -  560  0
                 zip = new ZipFile(dependency.getActualFilePath());
    -  561  0
                 if (zip.getEntry("META-INF/MANIFEST.MF") != null
    -  562  0
                         || zip.getEntry("META-INF/maven") != null) {
    -  563  0
                     final Enumeration<ZipArchiveEntry> entries = zip.getEntries();
    -  564  0
                     while (entries.hasMoreElements()) {
    -  565  0
                         final ZipArchiveEntry entry = entries.nextElement();
    -  566  0
                         if (!entry.isDirectory()) {
    -  567  0
                             final String name = entry.getName().toLowerCase();
    -  568  0
                             if (name.endsWith(".class")) {
    -  569  0
                                 isJar = true;
    -  570  0
                                 break;
    -  571  
                             }
    -  572   +  448  
                         }
    -  573  0
                     }
    -  574   +  449   +
                     }
    +  450  0
                 } else {
    +  451  2
                     in.reset();
    +  452  
                 }
    -  575  0
             } catch (IOException ex) {
    -  576  0
                 LOGGER.debug("Unable to unzip zip file '{}'", dependency.getFilePath(), ex);
    -  577   -
             } finally {
    -  578  0
                 ZipFile.closeQuietly(zip);
    -  579  0
             }
    -  580   +  453   +
             }
    +  454  2
         }
    +  455  
     
    -  581  0
             return isJar;
    +  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  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  
         }
    -  583   +  591  
     }
    - + 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 64aa33ff8..ab1eb6994 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
    62%
    77/123
    55%
    21/38
    6.5
    AssemblyAnalyzer
    31%
    47/147
    21%
    10/46
    7
     
    @@ -112,436 +112,508 @@  47  
     import org.owasp.dependencycheck.exception.InitializationException;
     48   -
     
    +
     import org.apache.commons.lang3.SystemUtils;
     49   -
     /**
    +
     
     50   -
      * Analyzer for getting company, product, and version information from a .NET
    +
     /**
     51   -
      * assembly.
    +
      * Analyzer for getting company, product, and version information from a .NET
     52   -
      *
    +
      * assembly.
     53   -
      * @author colezlaw
    -  54  
      *
    +  54   +
      * @author colezlaw
     55   +
      *
    +  56  
      */
    -  56  11
     public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
    -  57   -
     
    +  57  11
     public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
     58   -
         /**
    +
     
     59   -
          * The analyzer name
    +
         /**
     60   -
          */
    +
          * The analyzer name
     61   -
         private static final String ANALYZER_NAME = "Assembly Analyzer";
    +
          */
     62   -
         /**
    +
         private static final String ANALYZER_NAME = "Assembly Analyzer";
     63   -
          * The analysis phase
    +
         /**
     64   +
          * The analysis phase
    +  65  
          */
    -  65  1
         private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
    -  66   -
         /**
    +  66  1
         private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
     67   -
          * The list of supported extensions
    +
         /**
     68   +
          * The list of supported extensions
    +  69  
          */
    -  69  1
         private static final String[] SUPPORTED_EXTENSIONS = {"dll", "exe"};
    -  70   -
         /**
    +  70  1
         private static final String[] SUPPORTED_EXTENSIONS = {"dll", "exe"};
     71   -
          * The temp value for GrokAssembly.exe
    +
         /**
     72   +
          * The temp value for GrokAssembly.exe
    +  73  
          */
    -  73  11
         private File grokAssemblyExe = null;
    -  74   -
         /**
    +  74  11
         private File grokAssemblyExe = null;
     75   -
          * The DocumentBuilder for parsing the XML
    +
         /**
     76   -
          */
    +
          * The DocumentBuilder for parsing the XML
     77   -
         private DocumentBuilder builder;
    +
          */
     78   -
         /**
    +
         private DocumentBuilder builder;
     79   -
          * Logger
    +
         /**
     80   +
          * Logger
    +  81  
          */
    -  81  1
         private static final Logger LOGGER = LoggerFactory.getLogger(AssemblyAnalyzer.class);
    -  82   -
     
    +  82  1
         private static final Logger LOGGER = LoggerFactory.getLogger(AssemblyAnalyzer.class);
     83   -
         /**
    +
     
     84   -
          * Builds the beginnings of a List for ProcessBuilder
    -  85   -
          *
    -  86   -
          * @return the list of arguments to begin populating the ProcessBuilder
    -  87   -
          */
    -  88   -
         private List<String> buildArgumentList() {
    -  89   -
             // Use file.separator as a wild guess as to whether this is Windows
    -  90  8
             final List<String> args = new ArrayList<String>();
    -  91  8
             if (!"\\".equals(System.getProperty("file.separator"))) {
    -  92  0
                 if (Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH) != null) {
    -  93  0
                     args.add(Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH));
    -  94   -
                 } else {
    -  95  0
                     args.add("mono");
    -  96   -
                 }
    -  97   -
             }
    -  98  8
             args.add(grokAssemblyExe.getPath());
    -  99   -
     
    -  100  8
             return args;
    -  101   -
         }
    -  102   -
     
    -  103  
         /**
    -  104   -
          * Performs the analysis on a single Dependency.
    -  105   +  85   +
          * Builds the beginnings of a List for ProcessBuilder
    +  86  
          *
    -  106   -
          * @param dependency the dependency to analyze
    -  107   -
          * @param engine the engine to perform the analysis under
    -  108   -
          * @throws AnalysisException if anything goes sideways
    -  109   +  87   +
          * @return the list of arguments to begin populating the ProcessBuilder
    +  88  
          */
    -  110   -
         @Override
    -  111   -
         public void analyzeFileType(Dependency dependency, Engine engine)
    -  112   -
                 throws AnalysisException {
    -  113  3
             if (grokAssemblyExe == null) {
    -  114  0
                 LOGGER.warn("GrokAssembly didn't get deployed");
    -  115  0
                 return;
    -  116   -
             }
    -  117   -
     
    -  118  3
             final List<String> args = buildArgumentList();
    -  119  3
             args.add(dependency.getActualFilePath());
    -  120  3
             final ProcessBuilder pb = new ProcessBuilder(args);
    -  121  3
             Document doc = null;
    -  122   -
             try {
    -  123  3
                 final Process proc = pb.start();
    -  124   -
     
    -  125  3
                 doc = builder.parse(proc.getInputStream());
    -  126   -
     
    -  127   -
                 // Try evacuating the error stream
    -  128  3
                 final String errorStream = IOUtils.toString(proc.getErrorStream(), "UTF-8");
    -  129  3
                 if (null != errorStream && !errorStream.isEmpty()) {
    -  130  0
                     LOGGER.warn("Error from GrokAssembly: {}", errorStream);
    -  131   +  89   +
         protected List<String> buildArgumentList() {
    +  90   +
             // 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   +
                 } else {
    +  98  0
                     return null;
    +  99  
                 }
    +  100   +
             }
    +  101  10
             args.add(grokAssemblyExe.getPath());
    +  102  10
             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  0
             if (grokAssemblyExe == null) {
    +  116  0
                 LOGGER.warn("GrokAssembly didn't get deployed");
    +  117  0
                 return;
    +  118   +
             }
    +  119   +
     
    +  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;
    +  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();
    +  130   +
     
    +  131  0
                 doc = builder.parse(proc.getInputStream());
     132  
     
    -  133  3
                 int rc = 0;
    -  134   +  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);
    +  137   +
                 }
    +  138   +
     
    +  139  0
                 int rc = 0;
    +  140  
                 try {
    -  135  3
                     rc = proc.waitFor();
    -  136  0
                 } catch (InterruptedException ie) {
    -  137  0
                     return;
    -  138  3
                 }
    -  139  3
                 if (rc == 3) {
    -  140  0
                     LOGGER.debug("{} is not a .NET assembly or executable and as such cannot be analyzed by dependency-check",
    -  141  0
                             dependency.getActualFilePath());
    -  142  0
                     return;
    -  143  3
                 } else if (rc != 0) {
    -  144  1
                     LOGGER.warn("Return code {} from GrokAssembly", rc);
    -  145   +  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);
    +  151  
                 }
    -  146   +  152  
     
    -  147  3
                 final XPath xpath = XPathFactory.newInstance().newXPath();
    -  148   -
     
    -  149   -
                 // First, see if there was an error
    -  150  3
                 final String error = xpath.evaluate("/assembly/error", doc);
    -  151  3
                 if (error != null && !error.isEmpty()) {
    -  152  1
                     throw new AnalysisException(error);
    -  153   -
                 }
    +  153  0
                 final XPath xpath = XPathFactory.newInstance().newXPath();
     154  
     
    -  155  2
                 final String version = xpath.evaluate("/assembly/version", doc);
    -  156  2
                 if (version != null) {
    -  157  2
                     dependency.getVersionEvidence().addEvidence(new Evidence("grokassembly", "version",
    -  158   -
                             version, Confidence.HIGHEST));
    +  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  
                 }
     160  
     
    -  161  2
                 final String vendor = xpath.evaluate("/assembly/company", doc);
    -  162  2
                 if (vendor != null) {
    -  163  2
                     dependency.getVendorEvidence().addEvidence(new Evidence("grokassembly", "vendor",
    +  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   -
                             vendor, Confidence.HIGH));
    +
                             version, Confidence.HIGHEST));
     165  
                 }
     166  
     
    -  167  2
                 final String product = xpath.evaluate("/assembly/product", doc);
    -  168  2
                 if (product != null) {
    -  169  2
                     dependency.getProductEvidence().addEvidence(new Evidence("grokassembly", "product",
    +  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   -
                             product, Confidence.HIGH));
    +
                             vendor, Confidence.HIGH));
     171  
                 }
     172  
     
    -  173  0
             } catch (IOException ioe) {
    -  174  0
                 throw new AnalysisException(ioe);
    -  175  0
             } catch (SAXException saxe) {
    -  176  0
                 throw new AnalysisException("Couldn't parse GrokAssembly result", saxe);
    -  177  0
             } catch (XPathExpressionException xpe) {
    +  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   +
                             product, Confidence.HIGH));
    +  177   +
                 }
     178   -
                 // This shouldn't happen
    -  179  0
                 throw new AnalysisException(xpe);
    -  180  2
             }
    -  181  2
         }
    -  182  
     
    -  183   -
         /**
    +  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   -
          * Initialize the analyzer. In this case, extract GrokAssembly.exe to a
    -  185   -
          * temporary location.
    -  186   -
          *
    -  187   -
          * @throws InitializationException thrown if anything goes wrong
    +
                 // This shouldn't happen
    +  185  0
                 throw new AnalysisException(xpe);
    +  186  0
             }
    +  187  0
         }
     188   -
          */
    +
     
     189   -
         @Override
    +
         /**
     190   -
         public void initializeFileTypeAnalyzer() throws InitializationException {
    +
          * Initialize the analyzer. In this case, extract GrokAssembly.exe to a
     191   -
             final File tempFile;
    +
          * 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 {
    -  193  5
                 tempFile = File.createTempFile("GKA", ".exe", Settings.getTempDirectory());
    -  194  0
             } catch (IOException ex) {
    -  195  0
                 setEnabled(false);
    -  196  0
                 throw new InitializationException("Unable to create temporary file for the assembly analyzerr", ex);
    -  197  5
             }
    -  198  5
             FileOutputStream fos = null;
    -  199  5
             InputStream is = null;
    -  200   -
             try {
    -  201  5
                 fos = new FileOutputStream(tempFile);
    -  202  5
                 is = AssemblyAnalyzer.class.getClassLoader().getResourceAsStream("GrokAssembly.exe");
    -  203  5
                 IOUtils.copy(is, fos);
    -  204   -
     
    -  205  5
                 grokAssemblyExe = tempFile;
    +  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   -
                 // Set the temp file to get deleted when we're done
    -  207  5
                 grokAssemblyExe.deleteOnExit();
    -  208  5
                 LOGGER.debug("Extracted GrokAssembly.exe to {}", grokAssemblyExe.getPath());
    -  209  0
             } catch (IOException ioe) {
    -  210  0
                 this.setEnabled(false);
    -  211  0
                 LOGGER.warn("Could not extract GrokAssembly.exe: {}", ioe.getMessage());
    -  212  0
                 throw new InitializationException("Could not extract GrokAssembly.exe", ioe);
    -  213   +
             try {
    +  207  5
                 fos = new FileOutputStream(tempFile);
    +  208  5
                 is = AssemblyAnalyzer.class.getClassLoader().getResourceAsStream("GrokAssembly.exe");
    +  209  5
                 IOUtils.copy(is, fos);
    +  210   +
     
    +  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  
             } finally {
    -  214  5
                 if (fos != null) {
    -  215   +  218  5
                 if (fos != null) {
    +  219  
                     try {
    -  216  5
                         fos.close();
    -  217  0
                     } catch (Throwable e) {
    -  218  0
                         LOGGER.debug("Error closing output stream");
    -  219  5
                     }
    -  220   +  220  5
                         fos.close();
    +  221  0
                     } catch (Throwable e) {
    +  222  0
                         LOGGER.debug("Error closing output stream");
    +  223  5
                     }
    +  224  
                 }
    -  221  5
                 if (is != null) {
    -  222   +  225  5
                 if (is != null) {
    +  226  
                     try {
    -  223  5
                         is.close();
    -  224  0
                     } catch (Throwable e) {
    -  225  0
                         LOGGER.debug("Error closing input stream");
    -  226  5
                     }
    -  227   +  227  5
                         is.close();
    +  228  0
                     } catch (Throwable e) {
    +  229  0
                         LOGGER.debug("Error closing input stream");
    +  230  5
                     }
    +  231  
                 }
    -  228   -
             }
    -  229   -
     
    -  230   -
             // Now, need to see if GrokAssembly actually runs from this location.
    -  231  5
             final List<String> args = buildArgumentList();
     232   -
             try {
    -  233  5
                 final ProcessBuilder pb = new ProcessBuilder(args);
    -  234  5
                 final Process p = pb.start();
    -  235   -
                 // Try evacuating the error stream
    -  236  5
                 IOUtils.copy(p.getErrorStream(), NullOutputStream.NULL_OUTPUT_STREAM);
    +
             }
    +  233   +
     
    +  234   +
             // Now, need to see if GrokAssembly actually runs from this location.
    +  235  5
             final List<String> args = buildArgumentList();
    +  236   +
             //TODO this creaes an "unreported" error - if someone doesn't look
     237   -
     
    -  238  5
                 final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(p.getInputStream());
    -  239  5
                 final XPath xpath = XPathFactory.newInstance().newXPath();
    -  240  5
                 final String error = xpath.evaluate("/assembly/error", doc);
    -  241  5
                 if (p.waitFor() != 1 || error == null || error.isEmpty()) {
    -  242  0
                     LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer, please see the log for more details.");
    -  243  0
                     LOGGER.debug("GrokAssembly.exe is not working properly");
    -  244  0
                     grokAssemblyExe = null;
    -  245  0
                     setEnabled(false);
    -  246  0
                     throw new InitializationException("Could not execute .NET AssemblyAnalyzer");
    +
             // 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  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 "
     247   -
                 }
    -  248  0
             } catch (InitializationException e) {
    -  249  0
                 throw e;
    -  250  0
             } catch (Throwable e) {
    -  251  0
                 LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer;\n"
    +
                         + "'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   +
             }
     252   -
                         + "this can be ignored unless you are scanning .NET DLLs. Please see the log for more details.");
    -  253  0
                 LOGGER.debug("Could not execute GrokAssembly {}", e.getMessage());
    -  254  0
                 setEnabled(false);
    -  255  0
                 throw new InitializationException("An error occurred with the .NET AssemblyAnalyzer", e);
    -  256  5
             }
    +
             try {
    +  253  5
                 final ProcessBuilder pb = new ProcessBuilder(args);
    +  254  5
                 final Process p = pb.start();
    +  255   +
                 // Try evacuating the error stream
    +  256  5
                 IOUtils.copy(p.getErrorStream(), NullOutputStream.NULL_OUTPUT_STREAM);
     257   -
             try {
    -  258  5
                 builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
    -  259  0
             } catch (ParserConfigurationException ex) {
    -  260  0
                 setEnabled(false);
    -  261  0
                 throw new InitializationException("Error initializing the assembly analyzer", ex);
    -  262  5
             }
    -  263  5
         }
    -  264  
     
    -  265   -
         /**
    -  266   -
          * Removes resources used from the local file system.
    +  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   -
          *
    -  268   -
          * @throws Exception thrown if there is a problem closing the analyzer
    -  269   -
          */
    -  270   -
         @Override
    -  271   -
         public void close() throws Exception {
    -  272  7
             super.close();
    -  273   -
             try {
    -  274  7
                 if (grokAssemblyExe != null && !grokAssemblyExe.delete()) {
    -  275  0
                     grokAssemblyExe.deleteOnExit();
    -  276  
                 }
    -  277  0
             } catch (SecurityException se) {
    -  278  0
                 LOGGER.debug("Can't delete temporary GrokAssembly.exe");
    -  279  7
             }
    -  280  7
         }
    -  281   +  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   +
                         + "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  
     
    -  282   +  286  
         /**
    -  283   -
          * The File Filter used to filter supported extensions.
    -  284   -
          */
    -  285  2
         private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(
    -  286  1
                 SUPPORTED_EXTENSIONS).build();
     287   -
     
    +
          * Removes resources used from the local file system.
     288   -
         @Override
    +
          *
     289   -
         protected FileFilter getFileFilter() {
    -  290  15
             return FILTER;
    -  291   -
         }
    -  292   -
     
    -  293   -
         /**
    -  294   -
          * Gets this analyzer's name.
    -  295   -
          *
    -  296   -
          * @return the analyzer name
    -  297   +
          * @throws Exception thrown if there is a problem closing the analyzer
    +  290  
          */
    -  298   +  291  
         @Override
    -  299   -
         public String getName() {
    -  300  17
             return ANALYZER_NAME;
    -  301   -
         }
    -  302   -
     
    -  303   -
         /**
    +  292   +
         public void close() throws Exception {
    +  293  7
             super.close();
    +  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   -
          * Returns the phase this analyzer runs under.
    +
     
     305   -
          *
    +
         /**
     306   -
          * @return the phase this runs under
    +
          * The File Filter used to filter supported extensions.
     307  
          */
    -  308   -
         @Override
    -  309   -
         public AnalysisPhase getAnalysisPhase() {
    -  310  4
             return ANALYSIS_PHASE;
    -  311   -
         }
    -  312   +  308  2
         private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(
    +  309  1
                 SUPPORTED_EXTENSIONS).build();
    +  310  
     
    -  313   -
         /**
    -  314   -
          * Returns the key used in the properties file to reference the analyzer's
    -  315   -
          * enabled property.
    -  316   -
          *
    -  317   -
          * @return the analyzer's enabled property setting key
    -  318   -
          */
    -  319   +  311  
         @Override
    -  320   -
         protected String getAnalyzerEnabledSettingKey() {
    -  321  11
             return Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED;
    -  322   +  312   +
         protected FileFilter getFileFilter() {
    +  313  864
             return FILTER;
    +  314  
         }
    -  323   +  315   +
     
    +  316   +
         /**
    +  317   +
          * Gets this analyzer's name.
    +  318   +
          *
    +  319   +
          * @return the analyzer name
    +  320   +
          */
    +  321   +
         @Override
    +  322   +
         public String getName() {
    +  323  16
             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  4
             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  11
             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  0
             final ProcessBuilder pb = new ProcessBuilder("which", file);
    +  358   +
             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   +
                 }
    +  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   +
         }
    +  371  
     }
    - + 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 f763d1f77..e63c62d14 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AutoconfAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AutoconfAnalyzer.html @@ -254,7 +254,7 @@
         @Override
     123  
         protected FileFilter getFileFilter() {
    -  124  13
             return FILTER;
    +  124  862
             return FILTER;
     125  
         }
     126   @@ -516,6 +516,6 @@
     }
    - + 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 fd8783fd7..94f697257 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CMakeAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CMakeAnalyzer.html @@ -272,7 +272,7 @@
         @Override
     135  
         protected FileFilter getFileFilter() {
    -  136  12
             return FILTER;
    +  136  861
             return FILTER;
     137  
         }
     138   @@ -375,69 +375,75 @@  198  
          */
     199   -
         private void analyzeSetVersionCommand(Dependency dependency, Engine engine, String contents) {
    -  200  3
             Dependency currentDep = dependency;
    +
         @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  
     
    -  202  3
             final Matcher m = SET_VERSION.matcher(contents);
    -  203  3
             int count = 0;
    -  204  8
             while (m.find()) {
    -  205  5
                 count++;
    -  206  10
                 LOGGER.debug("Found project command match with {} groups: {}",
    -  207  5
                         m.groupCount(), m.group(0));
    -  208  5
                 String product = m.group(1);
    -  209  5
                 final String version = m.group(2);
    -  210  5
                 LOGGER.debug("Group 1: " + product);
    -  211  5
                 LOGGER.debug("Group 2: " + version);
    -  212  5
                 final String aliasPrefix = "ALIASOF_";
    -  213  5
                 if (product.startsWith(aliasPrefix)) {
    -  214  5
                     product = product.replaceFirst(aliasPrefix, "");
    -  215   +  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  
                 }
    -  216  5
                 if (count > 1) {
    -  217   +  219  5
                 if (count > 1) {
    +  220  
                     //TODO - refactor so we do not assign to the parameter (checkstyle)
    -  218  4
                     currentDep = new Dependency(dependency.getActualFile());
    -  219  4
                     currentDep.setDisplayFileName(String.format("%s:%s", dependency.getDisplayFileName(), product));
    -  220  4
                     final String filePath = String.format("%s:%s", dependency.getFilePath(), product);
    -  221  4
                     currentDep.setFilePath(filePath);
    -  222   +  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  
     
    -  223   +  226  
                     byte[] path;
    -  224   +  227  
                     try {
    -  225  4
                         path = filePath.getBytes("UTF-8");
    -  226  0
                     } catch (UnsupportedEncodingException ex) {
    -  227  0
                         path = filePath.getBytes();
    -  228  4
                     }
    -  229  4
                     currentDep.setSha1sum(Checksum.getHex(sha1.digest(path)));
    -  230  4
                     engine.getDependencies().add(currentDep);
    -  231   -
                 }
    -  232  5
                 final String source = currentDep.getDisplayFileName();
    -  233  5
                 currentDep.getProductEvidence().addEvidence(source, "Product",
    +  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);
    -  235  5
                 currentDep.getVersionEvidence().addEvidence(source, "Version",
    -  236   +  238  5
                 currentDep.getVersionEvidence().addEvidence(source, "Version",
    +  239  
                         version, Confidence.MEDIUM);
    -  237  5
             }
    -  238  3
             LOGGER.debug(String.format("Found %d matches.", count));
    -  239  3
         }
    -  240   +  240  5
             }
    +  241  3
             LOGGER.debug(String.format("Found %d matches.", count));
    +  242  3
         }
    +  243  
     
    -  241   -
         @Override
    -  242   -
         protected String getAnalyzerEnabledSettingKey() {
    -  243  11
             return Settings.KEYS.ANALYZER_CMAKE_ENABLED;
     244   -
         }
    +
         @Override
     245   +
         protected String getAnalyzerEnabledSettingKey() {
    +  246  11
             return Settings.KEYS.ANALYZER_CMAKE_ENABLED;
    +  247   +
         }
    +  248  
     }
    - + 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 7c4057885..9f62c32ee 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CPEAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CPEAnalyzer.html @@ -12,9 +12,9 @@
     
    - - - + + +
    Classes in this File Line Coverage Branch Coverage Complexity
    CPEAnalyzer
    81%
    194/238
    76%
    103/134
    4.75
    CPEAnalyzer$IdentifierConfidence
    100%
    4/4
    N/A
    4.75
    CPEAnalyzer$IdentifierMatch
    38%
    15/39
    16%
    4/24
    4.75
    CPEAnalyzer
    80%
    191/238
    76%
    103/134
    4.679
    CPEAnalyzer$IdentifierConfidence
    100%
    4/4
    N/A
    4.679
    CPEAnalyzer$IdentifierMatch
    36%
    14/38
    0%
    0/20
    4.679
     
    @@ -74,1300 +74,1317 @@  27  
     import java.util.StringTokenizer;
     28   -
     import org.apache.lucene.document.Document;
    +
     import org.apache.commons.lang3.builder.CompareToBuilder;
     29   -
     import org.apache.lucene.index.CorruptIndexException;
    +
     import org.apache.lucene.document.Document;
     30   -
     import org.apache.lucene.queryparser.classic.ParseException;
    +
     import org.apache.lucene.index.CorruptIndexException;
     31   -
     import org.apache.lucene.search.ScoreDoc;
    +
     import org.apache.lucene.queryparser.classic.ParseException;
     32   -
     import org.apache.lucene.search.TopDocs;
    +
     import org.apache.lucene.search.ScoreDoc;
     33   -
     import org.owasp.dependencycheck.Engine;
    +
     import org.apache.lucene.search.TopDocs;
     34   -
     import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
    +
     import org.owasp.dependencycheck.Engine;
     35   -
     import org.owasp.dependencycheck.data.cpe.CpeMemoryIndex;
    +
     import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
     36   -
     import org.owasp.dependencycheck.data.cpe.Fields;
    +
     import org.owasp.dependencycheck.data.cpe.CpeMemoryIndex;
     37   -
     import org.owasp.dependencycheck.data.cpe.IndexEntry;
    +
     import org.owasp.dependencycheck.data.cpe.Fields;
     38   -
     import org.owasp.dependencycheck.data.cpe.IndexException;
    +
     import org.owasp.dependencycheck.data.cpe.IndexEntry;
     39   -
     import org.owasp.dependencycheck.data.lucene.LuceneUtils;
    +
     import org.owasp.dependencycheck.data.cpe.IndexException;
     40   -
     import org.owasp.dependencycheck.data.nvdcve.CveDB;
    +
     import org.owasp.dependencycheck.data.lucene.LuceneUtils;
     41   -
     import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
    +
     import org.owasp.dependencycheck.data.nvdcve.CveDB;
     42   -
     import org.owasp.dependencycheck.dependency.Confidence;
    +
     import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
     43   -
     import org.owasp.dependencycheck.dependency.Dependency;
    +
     import org.owasp.dependencycheck.dependency.Confidence;
     44   -
     import org.owasp.dependencycheck.dependency.Evidence;
    +
     import org.owasp.dependencycheck.dependency.Dependency;
     45   -
     import org.owasp.dependencycheck.dependency.EvidenceCollection;
    +
     import org.owasp.dependencycheck.dependency.Evidence;
     46   -
     import org.owasp.dependencycheck.dependency.Identifier;
    +
     import org.owasp.dependencycheck.dependency.EvidenceCollection;
     47   -
     import org.owasp.dependencycheck.dependency.VulnerableSoftware;
    +
     import org.owasp.dependencycheck.dependency.Identifier;
     48   -
     import org.owasp.dependencycheck.exception.InitializationException;
    +
     import org.owasp.dependencycheck.dependency.VulnerableSoftware;
     49   -
     import org.owasp.dependencycheck.utils.DependencyVersion;
    +
     import org.owasp.dependencycheck.exception.InitializationException;
     50   -
     import org.owasp.dependencycheck.utils.DependencyVersionUtil;
    +
     import org.owasp.dependencycheck.utils.DependencyVersion;
     51   -
     import org.slf4j.Logger;
    +
     import org.owasp.dependencycheck.utils.DependencyVersionUtil;
     52   -
     import org.slf4j.LoggerFactory;
    +
     import org.slf4j.Logger;
     53   -
     
    +
     import org.slf4j.LoggerFactory;
     54   -
     /**
    +
     
     55   -
      * CPEAnalyzer is a utility class that takes a project dependency and attempts
    +
     /**
     56   -
      * 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
     57   -
      * within the dependency to search the Lucene index.
    +
      * to discern if there is an associated CPE. It uses the evidence contained
     58   -
      *
    +
      * within the dependency to search the Lucene index.
     59   -
      * @author Jeremy Long
    +
      *
     60   +
      * @author Jeremy Long
    +  61  
      */
    -  61  6
     public class CPEAnalyzer implements Analyzer {
    -  62   -
     
    +  62  6
     public class CPEAnalyzer implements Analyzer {
     63   -
         /**
    +
     
     64   -
          * The Logger.
    +
         /**
     65   +
          * The Logger.
    +  66  
          */
    -  66  1
         private static final Logger LOGGER = LoggerFactory.getLogger(CPEAnalyzer.class);
    -  67   -
         /**
    +  67  1
         private static final Logger LOGGER = LoggerFactory.getLogger(CPEAnalyzer.class);
     68   -
          * The maximum number of query results to return.
    +
         /**
     69   -
          */
    +
          * The maximum number of query results to return.
     70   -
         static final int MAX_QUERY_RESULTS = 25;
    +
          */
     71   -
         /**
    +
         static final int MAX_QUERY_RESULTS = 25;
     72   -
          * The weighting boost to give terms when constructing the Lucene query.
    +
         /**
     73   -
          */
    +
          * The weighting boost to give terms when constructing the Lucene query.
     74   -
         static final String WEIGHTING_BOOST = "^5";
    +
          */
     75   -
         /**
    +
         static final String WEIGHTING_BOOST = "^5";
     76   -
          * A string representation of a regular expression defining characters
    +
         /**
     77   -
          * utilized within the CPE Names.
    +
          * A string representation of a regular expression defining characters
     78   -
          */
    +
          * utilized within the CPE Names.
     79   -
         static final String CLEANSE_CHARACTER_RX = "[^A-Za-z0-9 ._-]";
    +
          */
     80   -
         /**
    +
         static final String CLEANSE_CHARACTER_RX = "[^A-Za-z0-9 ._-]";
     81   -
          * A string representation of a regular expression used to remove all but
    +
         /**
     82   -
          * alpha characters.
    +
          * A string representation of a regular expression used to remove all but
     83   -
          */
    +
          * alpha characters.
     84   -
         static final String CLEANSE_NONALPHA_RX = "[^A-Za-z]*";
    +
          */
     85   -
         /**
    +
         static final String CLEANSE_NONALPHA_RX = "[^A-Za-z]*";
     86   -
          * The additional size to add to a new StringBuilder to account for extra
    +
         /**
     87   -
          * data that will be written into the string.
    +
          * The additional size to add to a new StringBuilder to account for extra
     88   -
          */
    +
          * data that will be written into the string.
     89   -
         static final int STRING_BUILDER_BUFFER = 20;
    +
          */
     90   -
         /**
    +
         static final int STRING_BUILDER_BUFFER = 20;
     91   -
          * The CPE in memory index.
    +
         /**
     92   -
          */
    +
          * The CPE in memory index.
     93   -
         private CpeMemoryIndex cpe;
    +
          */
     94   -
         /**
    +
         private CpeMemoryIndex cpe;
     95   -
          * The CVE Database.
    +
         /**
     96   -
          */
    +
          * The CVE Database.
     97   -
         private CveDB cve;
    +
          */
     98   -
     
    +
         private CveDB cve;
     99   -
         /**
    +
     
     100   -
          * The URL to perform a search of the NVD CVE data at NIST.
    +
         /**
     101   -
          */
    +
          * The URL to perform a search of the NVD CVE data at NIST.
     102   -
         public static final String NVD_SEARCH_URL = "https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=%s";
    +
          */
     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   -
          * Returns the name of this analyzer.
    +
         /**
     106   -
          *
    +
          * Returns the name of this analyzer.
     107   -
          * @return the name of this analyzer.
    +
          *
     108   -
          */
    +
          * @return the name of this analyzer.
     109   -
         @Override
    +
          */
     110   +
         @Override
    +  111  
         public String getName() {
    -  111  16
             return "CPE Analyzer";
    -  112   -
         }
    +  112  16
             return "CPE Analyzer";
     113   -
     
    +
         }
     114   -
         /**
    +
     
     115   -
          * Returns the analysis phase that this analyzer should run in.
    +
         /**
     116   -
          *
    +
          * Returns the analysis phase that this analyzer should run in.
     117   -
          * @return the analysis phase that this analyzer should run in.
    +
          *
     118   -
          */
    +
          * @return the analysis phase that this analyzer should run in.
     119   -
         @Override
    +
          */
     120   +
         @Override
    +  121  
         public AnalysisPhase getAnalysisPhase() {
    -  121  4
             return AnalysisPhase.IDENTIFIER_ANALYSIS;
    -  122   -
         }
    +  122  4
             return AnalysisPhase.IDENTIFIER_ANALYSIS;
     123   -
     
    +
         }
     124   -
         /**
    +
     
     125   -
          * Creates the CPE Lucene Index.
    +
         /**
     126   -
          *
    +
          * Creates the CPE Lucene Index.
     127   -
          * @throws InitializationException is thrown if there is an issue opening
    +
          *
     128   -
          * the index.
    +
          * @throws InitializationException is thrown if there is an issue opening
     129   -
          */
    +
          * the index.
     130   -
         @Override
    +
          */
     131   -
         public void initialize() throws InitializationException {
    +
         @Override
     132   +
         public void initialize() throws InitializationException {
    +  133  
             try {
    -  133  2
                 this.open();
    -  134  0
             } catch (IOException ex) {
    -  135  0
                 LOGGER.debug("Exception initializing the Lucene Index", ex);
    -  136  0
                 throw new InitializationException("An exception occurred initializing the Lucene Index", ex);
    -  137  0
             } catch (DatabaseException ex) {
    -  138  0
                 LOGGER.debug("Exception accessing the database", ex);
    -  139  0
                 throw new InitializationException("An exception occurred accessing the database", ex);
    -  140  2
             }
    -  141  2
         }
    -  142   -
     
    +  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   -
         /**
    +
     
     144   -
          * Opens the data source.
    +
         /**
     145   -
          *
    +
          * Opens the data source.
     146   -
          * @throws IOException when the Lucene directory to be queried does not
    +
          *
     147   -
          * exist or is corrupt.
    +
          * @throws IOException when the Lucene directory to be queried does not
     148   -
          * @throws DatabaseException when the database throws an exception. This
    +
          * exist or is corrupt.
     149   -
          * usually occurs when the database is in use by another process.
    +
          * @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 {
    -  152  2
             if (!isOpen()) {
    -  153  2
                 cve = new CveDB();
    -  154  2
                 cve.open();
    -  155  2
                 cpe = CpeMemoryIndex.getInstance();
    -  156   +  153  2
             if (!isOpen()) {
    +  154  2
                 cve = new CveDB();
    +  155  2
                 cve.open();
    +  156  2
                 cpe = CpeMemoryIndex.getInstance();
    +  157  
                 try {
    -  157  2
                     LOGGER.info("Creating the CPE Index");
    -  158  2
                     final long creationStart = System.currentTimeMillis();
    -  159  2
                     cpe.open(cve);
    -  160  2
                     LOGGER.info("CPE Index Created ({} ms)", System.currentTimeMillis() - creationStart);
    -  161  0
                 } catch (IndexException ex) {
    -  162  0
                     LOGGER.debug("IndexException", ex);
    -  163  0
                     throw new DatabaseException(ex);
    -  164  2
                 }
    -  165   +  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  
             }
    -  166  2
         }
    -  167   -
     
    +  167  2
         }
     168   -
         /**
    +
     
     169   -
          * Closes the data sources.
    +
         /**
     170   -
          */
    +
          * Closes the data sources.
     171   -
         @Override
    +
          */
     172   -
         public void close() {
    -  173  2
             if (cpe != null) {
    -  174  2
                 cpe.close();
    -  175  2
                 cpe = null;
    -  176   -
             }
    -  177  2
             if (cve != null) {
    -  178  2
                 cve.close();
    -  179  2
                 cve = null;
    -  180   -
             }
    -  181  2
         }
    -  182   -
     
    -  183   -
         public boolean isOpen() {
    -  184  2
             return cpe != null && cpe.isOpen();
    -  185   -
         }
    -  186   -
     
    -  187   -
         /**
    -  188   -
          * Searches the data store of CPE entries, trying to identify the CPE for
    -  189   -
          * the given dependency based on the evidence contained within. The
    -  190   -
          * dependency passed in is updated with any identified CPE values.
    -  191   -
          *
    -  192   -
          * @param dependency the dependency to search for CPE entries on.
    -  193   -
          * @throws CorruptIndexException is thrown when the Lucene index is corrupt.
    -  194   -
          * @throws IOException is thrown when an IOException occurs.
    -  195   -
          * @throws ParseException is thrown when the Lucene query cannot be parsed.
    -  196   -
          */
    -  197   -
         protected void determineCPE(Dependency dependency) throws CorruptIndexException, IOException, ParseException {
    -  198   -
             //TODO test dojo-war against this. we shold get dojo-toolkit:dojo-toolkit AND dojo-toolkit:toolkit
    -  199  4
             String vendors = "";
    -  200  4
             String products = "";
    -  201  17
             for (Confidence confidence : Confidence.values()) {
    -  202  14
                 if (dependency.getVendorEvidence().contains(confidence)) {
    -  203  9
                     vendors = addEvidenceWithoutDuplicateTerms(vendors, dependency.getVendorEvidence(), confidence);
    -  204  9
                     LOGGER.debug("vendor search: {}", vendors);
    -  205   -
                 }
    -  206  14
                 if (dependency.getProductEvidence().contains(confidence)) {
    -  207  8
                     products = addEvidenceWithoutDuplicateTerms(products, dependency.getProductEvidence(), confidence);
    -  208  8
                     LOGGER.debug("product search: {}", products);
    -  209   -
                 }
    -  210  14
                 if (!vendors.isEmpty() && !products.isEmpty()) {
    -  211  22
                     final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getVendorEvidence().getWeighting(),
    -  212  11
                             dependency.getProductEvidence().getWeighting());
    -  213  11
                     if (entries == null) {
    -  214  0
                         continue;
    -  215   -
                     }
    -  216  11
                     boolean identifierAdded = false;
    -  217  11
                     for (IndexEntry e : entries) {
    -  218  46
                         LOGGER.debug("Verifying entry: {}", e);
    -  219  46
                         if (verifyEntry(e, dependency)) {
    -  220  3
                             final String vendor = e.getVendor();
    -  221  3
                             final String product = e.getProduct();
    -  222  3
                             LOGGER.debug("identified vendor/product: {}/{}", vendor, product);
    -  223  3
                             identifierAdded |= determineIdentifiers(dependency, vendor, product, confidence);
    -  224   -
                         }
    -  225  46
                     }
    -  226  11
                     if (identifierAdded) {
    -  227  1
                         break;
    -  228   -
                     }
    -  229   -
                 }
    -  230   -
             }
    -  231  4
         }
    -  232   -
     
    -  233   -
         /**
    -  234   -
          * Returns the text created by concatenating the text and the values from
    -  235   -
          * the EvidenceCollection (filtered for a specific confidence). This
    -  236   -
          * attempts to prevent duplicate terms from being added.<br/<br/> Note, if
    -  237   -
          * the evidence is longer then 200 characters it will be truncated.
    -  238   -
          *
    -  239   -
          * @param text the base text.
    -  240   -
          * @param ec an EvidenceCollection
    -  241   -
          * @param confidenceFilter a Confidence level to filter the evidence by.
    -  242   -
          * @return the new evidence text
    -  243   -
          */
    -  244   -
         private String addEvidenceWithoutDuplicateTerms(final String text, final EvidenceCollection ec, Confidence confidenceFilter) {
    -  245  17
             final String txt = (text == null) ? "" : text;
    -  246  17
             final StringBuilder sb = new StringBuilder(txt.length() + (20 * ec.size()));
    -  247  17
             sb.append(' ').append(txt).append(' ');
    -  248  17
             for (Evidence e : ec.iterator(confidenceFilter)) {
    -  249  36
                 String value = e.getValue();
    -  250   -
     
    -  251   -
                 //hack to get around the fact that lucene does a really good job of recognizing domains and not
    -  252   -
                 // splitting them. TODO - put together a better lucene analyzer specific to the domain.
    -  253  36
                 if (value.startsWith("http://")) {
    -  254  2
                     value = value.substring(7).replaceAll("\\.", " ");
    -  255   -
                 }
    -  256  36
                 if (value.startsWith("https://")) {
    -  257  1
                     value = value.substring(8).replaceAll("\\.", " ");
    -  258   -
                 }
    -  259  36
                 if (sb.indexOf(" " + value + " ") < 0) {
    -  260  36
                     sb.append(value).append(' ');
    -  261   -
                 }
    -  262  36
             }
    -  263  17
             return sb.toString().trim();
    -  264   -
         }
    -  265   -
     
    -  266   -
         /**
    -  267   -
          * <p>
    -  268   -
          * Searches the Lucene CPE index to identify possible CPE entries associated
    -  269   -
          * with the supplied vendor, product, and version.</p>
    -  270   -
          *
    -  271   -
          * <p>
    -  272   -
          * If either the vendorWeightings or productWeightings lists have been
    -  273   -
          * populated this data is used to add weighting factors to the search.</p>
    -  274   -
          *
    -  275   -
          * @param vendor the text used to search the vendor field
    -  276   -
          * @param product the text used to search the product field
    -  277   -
          * @param vendorWeightings a list of strings to use to add weighting factors
    -  278   -
          * to the vendor field
    -  279   -
          * @param productWeightings Adds a list of strings that will be used to add
    -  280   -
          * weighting factors to the product search
    -  281   -
          * @return a list of possible CPE values
    -  282   -
          */
    -  283   -
         protected List<IndexEntry> searchCPE(String vendor, String product,
    -  284   -
                 Set<String> vendorWeightings, Set<String> productWeightings) {
    -  285   -
     
    -  286  11
             final List<IndexEntry> ret = new ArrayList<IndexEntry>(MAX_QUERY_RESULTS);
    -  287   -
     
    -  288  11
             final String searchString = buildSearch(vendor, product, vendorWeightings, productWeightings);
    -  289  11
             if (searchString == null) {
    -  290  0
                 return ret;
    -  291   -
             }
    -  292   -
             try {
    -  293  11
                 final TopDocs docs = cpe.search(searchString, MAX_QUERY_RESULTS);
    -  294  186
                 for (ScoreDoc d : docs.scoreDocs) {
    -  295  175
                     if (d.score >= 0.08) {
    -  296  46
                         final Document doc = cpe.getDocument(d.doc);
    -  297  46
                         final IndexEntry entry = new IndexEntry();
    -  298  46
                         entry.setVendor(doc.get(Fields.VENDOR));
    -  299  46
                         entry.setProduct(doc.get(Fields.PRODUCT));
    -  300  46
                         entry.setSearchScore(d.score);
    -  301  46
                         if (!ret.contains(entry)) {
    -  302  46
                             ret.add(entry);
    -  303   -
                         }
    -  304   -
                     }
    -  305   -
                 }
    -  306  11
                 return ret;
    -  307  0
             } catch (ParseException ex) {
    -  308  0
                 LOGGER.warn("An error occurred querying the CPE data. See the log for more details.");
    -  309  0
                 LOGGER.info("Unable to parse: {}", searchString, ex);
    -  310  0
             } catch (IOException ex) {
    -  311  0
                 LOGGER.warn("An error occurred reading CPE data. See the log for more details.");
    -  312  0
                 LOGGER.info("IO Error with search string: {}", searchString, ex);
    -  313  0
             }
    -  314  0
             return null;
    -  315   -
         }
    -  316   -
     
    -  317   -
         /**
    -  318   -
          * <p>
    -  319   -
          * Builds a Lucene search string by properly escaping data and constructing
    -  320   -
          * a valid search query.</p>
    -  321   -
          *
    -  322   -
          * <p>
    -  323   -
          * If either the possibleVendor or possibleProducts lists have been
    -  324   -
          * populated this data is used to add weighting factors to the search string
    -  325   -
          * generated.</p>
    -  326   -
          *
    -  327   -
          * @param vendor text to search the vendor field
    -  328   -
          * @param product text to search the product field
    -  329   -
          * @param vendorWeighting a list of strings to apply to the vendor to boost
    -  330   -
          * the terms weight
    -  331   -
          * @param productWeightings a list of strings to apply to the product to
    -  332   -
          * boost the terms weight
    -  333   -
          * @return the Lucene query
    -  334   -
          */
    -  335   -
         protected String buildSearch(String vendor, String product,
    -  336   -
                 Set<String> vendorWeighting, Set<String> productWeightings) {
    -  337  11
             final String v = vendor; //.replaceAll("[^\\w\\d]", " ");
    -  338  11
             final String p = product; //.replaceAll("[^\\w\\d]", " ");
    -  339  11
             final StringBuilder sb = new StringBuilder(v.length() + p.length()
    -  340  11
                     + Fields.PRODUCT.length() + Fields.VENDOR.length() + STRING_BUILDER_BUFFER);
    -  341   -
     
    -  342  11
             if (!appendWeightedSearch(sb, Fields.PRODUCT, p, productWeightings)) {
    -  343  0
                 return null;
    -  344   -
             }
    -  345  11
             sb.append(" AND ");
    -  346  11
             if (!appendWeightedSearch(sb, Fields.VENDOR, v, vendorWeighting)) {
    -  347  0
                 return null;
    -  348   -
             }
    -  349  11
             return sb.toString();
    -  350   -
         }
    -  351   -
     
    -  352   -
         /**
    -  353   -
          * This method constructs a Lucene query for a given field. The searchText
    -  354   -
          * is split into separate words and if the word is within the list of
    -  355   -
          * weighted words then an additional weighting is applied to the term as it
    -  356   -
          * is appended into the query.
    -  357   -
          *
    -  358   -
          * @param sb a StringBuilder that the query text will be appended to.
    -  359   -
          * @param field the field within the Lucene index that the query is
    -  360   -
          * searching.
    -  361   -
          * @param searchText text used to construct the query.
    -  362   -
          * @param weightedText a list of terms that will be considered higher
    -  363   -
          * importance when searching.
    -  364   -
          * @return if the append was successful.
    -  365   -
          */
    -  366   -
         private boolean appendWeightedSearch(StringBuilder sb, String field, String searchText, Set<String> weightedText) {
    -  367  22
             sb.append(' ').append(field).append(":( ");
    -  368   -
     
    -  369  22
             final String cleanText = cleanseText(searchText);
    -  370   -
     
    -  371  22
             if (cleanText.isEmpty()) {
    -  372  0
                 return false;
    -  373   -
             }
    -  374   -
     
    -  375  22
             if (weightedText == null || weightedText.isEmpty()) {
    -  376  14
                 LuceneUtils.appendEscapedLuceneQuery(sb, cleanText);
    -  377   -
             } else {
    -  378  8
                 final StringTokenizer tokens = new StringTokenizer(cleanText);
    -  379  104
                 while (tokens.hasMoreElements()) {
    -  380  96
                     final String word = tokens.nextToken();
    -  381  96
                     StringBuilder temp = null;
    -  382  96
                     for (String weighted : weightedText) {
    -  383  227
                         final String weightedStr = cleanseText(weighted);
    -  384  227
                         if (equalsIgnoreCaseAndNonAlpha(word, weightedStr)) {
    -  385  7
                             temp = new StringBuilder(word.length() + 2);
    -  386  7
                             LuceneUtils.appendEscapedLuceneQuery(temp, word);
    -  387  7
                             temp.append(WEIGHTING_BOOST);
    -  388  7
                             if (!word.equalsIgnoreCase(weightedStr)) {
    -  389  0
                                 temp.append(' ');
    -  390  0
                                 LuceneUtils.appendEscapedLuceneQuery(temp, weightedStr);
    -  391  0
                                 temp.append(WEIGHTING_BOOST);
    -  392   -
                             }
    -  393   -
                             break;
    -  394   -
                         }
    -  395  220
                     }
    -  396  96
                     sb.append(' ');
    -  397  96
                     if (temp == null) {
    -  398  89
                         LuceneUtils.appendEscapedLuceneQuery(sb, word);
    -  399   -
                     } else {
    -  400  7
                         sb.append(temp);
    -  401   -
                     }
    -  402  96
                 }
    -  403   -
             }
    -  404  22
             sb.append(" ) ");
    -  405  22
             return true;
    -  406   -
         }
    -  407   -
     
    -  408   -
         /**
    -  409   -
          * Removes characters from the input text that are not used within the CPE
    -  410   -
          * index.
    -  411   -
          *
    -  412   -
          * @param text is the text to remove the characters from.
    -  413   -
          * @return the text having removed some characters.
    -  414   -
          */
    -  415   -
         private String cleanseText(String text) {
    -  416  249
             return text.replaceAll(CLEANSE_CHARACTER_RX, " ");
    -  417   -
         }
    -  418   -
     
    -  419   -
         /**
    -  420   -
          * Compares two strings after lower casing them and removing the non-alpha
    -  421   -
          * characters.
    -  422   -
          *
    -  423   -
          * @param l string one to compare.
    -  424   -
          * @param r string two to compare.
    -  425   -
          * @return whether or not the two strings are similar.
    -  426   -
          */
    -  427   -
         private boolean equalsIgnoreCaseAndNonAlpha(String l, String r) {
    -  428  227
             if (l == null || r == null) {
    -  429  0
                 return false;
    -  430   -
             }
    -  431   -
     
    -  432  227
             final String left = l.replaceAll(CLEANSE_NONALPHA_RX, "");
    -  433  227
             final String right = r.replaceAll(CLEANSE_NONALPHA_RX, "");
    -  434  227
             return left.equalsIgnoreCase(right);
    -  435   -
         }
    -  436   -
     
    -  437   -
         /**
    -  438   -
          * Ensures that the CPE Identified matches the dependency. This validates
    -  439   -
          * that the product, vendor, and version information for the CPE are
    -  440   -
          * contained within the dependencies evidence.
    -  441   -
          *
    -  442   -
          * @param entry a CPE entry.
    -  443   -
          * @param dependency the dependency that the CPE entries could be for.
    -  444   -
          * @return whether or not the entry is valid.
    -  445   -
          */
    -  446   -
         private boolean verifyEntry(final IndexEntry entry, final Dependency dependency) {
    -  447  46
             boolean isValid = false;
    -  448   -
     
    -  449   -
             //TODO - does this nullify some of the fuzzy matching that happens in the lucene search?
    -  450   -
             // for instance CPE some-component and in the evidence we have SomeComponent.
    -  451  46
             if (collectionContainsString(dependency.getProductEvidence(), entry.getProduct())
    -  452  4
                     && collectionContainsString(dependency.getVendorEvidence(), entry.getVendor())) {
    -  453   -
                 //&& collectionContainsVersion(dependency.getVersionEvidence(), entry.getVersion())
    -  454  3
                 isValid = true;
    -  455   -
             }
    -  456  46
             return isValid;
    -  457   -
         }
    -  458   -
     
    -  459   -
         /**
    -  460   -
          * Used to determine if the EvidenceCollection contains a specific string.
    -  461   -
          *
    -  462   -
          * @param ec an EvidenceCollection
    -  463   -
          * @param text the text to search for
    -  464   -
          * @return whether or not the EvidenceCollection contains the string
    -  465   -
          */
    -  466   -
         private boolean collectionContainsString(EvidenceCollection ec, String text) {
    -  467   -
             //TODO - likely need to change the split... not sure if this will work for CPE with special chars
    -  468  50
             if (text == null) {
    -  469  0
                 return false;
    -  470   -
             }
    -  471  50
             final String[] words = text.split("[\\s_-]");
    -  472  50
             final List<String> list = new ArrayList<String>();
    -  473  50
             String tempWord = null;
    -  474  142
             for (String word : words) {
    -  475   -
                 /*
    -  476   -
                  single letter words should be concatenated with the next word.
    -  477   -
                  so { "m", "core", "sample" } -> { "mcore", "sample" }
    -  478   -
                  */
    -  479  92
                 if (tempWord != null) {
    -  480  3
                     list.add(tempWord + word);
    -  481  3
                     tempWord = null;
    -  482  89
                 } else if (word.length() <= 2) {
    -  483  4
                     tempWord = word;
    -  484   -
                 } else {
    -  485  85
                     list.add(word);
    -  486   -
                 }
    -  487   -
             }
    -  488  50
             if (tempWord != null) {
    -  489  1
                 if (!list.isEmpty()) {
    -  490  1
                     final String tmp = list.get(list.size() - 1) + tempWord;
    -  491  1
                     list.add(tmp);
    -  492  1
                 } else {
    -  493  0
                     list.add(tempWord);
    -  494   -
                 }
    -  495   -
             }
    -  496  50
             if (list.isEmpty()) {
    -  497  0
                 return false;
    -  498   -
             }
    -  499  50
             boolean contains = true;
    -  500  50
             for (String word : list) {
    -  501  89
                 contains &= ec.containsUsedString(word);
    -  502  89
             }
    -  503  50
             return contains;
    -  504   -
         }
    -  505   -
     
    -  506   -
         /**
    -  507   -
          * Analyzes a dependency and attempts to determine if there are any CPE
    -  508   -
          * identifiers for this dependency.
    -  509   -
          *
    -  510   -
          * @param dependency The Dependency to analyze.
    -  511   -
          * @param engine The analysis engine
    -  512   -
          * @throws AnalysisException is thrown if there is an issue analyzing the
    -  513   -
          * dependency.
    -  514   -
          */
    -  515  
         @Override
    -  516   -
         public synchronized void analyze(Dependency dependency, Engine engine) throws AnalysisException {
    -  517   -
             try {
    -  518  4
                 determineCPE(dependency);
    -  519  0
             } catch (CorruptIndexException ex) {
    -  520  0
                 throw new AnalysisException("CPE Index is corrupt.", ex);
    -  521  0
             } catch (IOException ex) {
    -  522  0
                 throw new AnalysisException("Failure opening the CPE Index.", ex);
    -  523  0
             } catch (ParseException ex) {
    -  524  0
                 throw new AnalysisException("Unable to parse the generated Lucene query for this dependency.", ex);
    -  525  4
             }
    -  526  4
         }
    -  527   +  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  
     
    -  528   +  184   +
         public boolean isOpen() {
    +  185  2
             return cpe != null && cpe.isOpen();
    +  186   +
         }
    +  187   +
     
    +  188  
         /**
    -  529   -
          * Retrieves a list of CPE values from the CveDB based on the vendor and
    -  530   -
          * product passed in. The list is then validated to find only CPEs that are
    -  531   -
          * valid for the given dependency. It is possible that the CPE identified is
    -  532   -
          * a best effort "guess" based on the vendor, product, and version
    -  533   -
          * information.
    -  534   +  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  
          *
    -  535   -
          * @param dependency the Dependency being analyzed
    -  536   -
          * @param vendor the vendor for the CPE being analyzed
    -  537   -
          * @param product the product for the CPE being analyzed
    -  538   -
          * @param currentConfidence the current confidence being used during
    -  539   -
          * analysis
    -  540   -
          * @return <code>true</code> if an identifier was added to the dependency;
    -  541   -
          * otherwise <code>false</code>
    -  542   -
          * @throws UnsupportedEncodingException is thrown if UTF-8 is not supported
    -  543   +  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  
          */
    -  544   -
         protected boolean determineIdentifiers(Dependency dependency, String vendor, String product,
    -  545   -
                 Confidence currentConfidence) throws UnsupportedEncodingException {
    -  546  3
             final Set<VulnerableSoftware> cpes = cve.getCPEs(vendor, product);
    -  547  3
             DependencyVersion bestGuess = new DependencyVersion("-");
    -  548  3
             Confidence bestGuessConf = null;
    -  549  3
             boolean hasBroadMatch = false;
    -  550  3
             final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>();
    -  551   -
     
    -  552   -
             //TODO the following algorithm incorrectly identifies things as a lower version
    -  553   -
             // if there lower confidence evidence when the current (highest) version number 
    -  554   -
             // is newer then anything in the NVD.
    -  555  15
             for (Confidence conf : Confidence.values()) {
    -  556  12
                 for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) {
    -  557  12
                     final DependencyVersion evVer = DependencyVersionUtil.parseVersion(evidence.getValue());
    -  558  12
                     if (evVer == null) {
    -  559  0
                         continue;
    -  560   +  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  
                     }
    -  561  12
                     for (VulnerableSoftware vs : cpes) {
    -  562   -
                         DependencyVersion dbVer;
    -  563  436
                         if (vs.getUpdate() != null && !vs.getUpdate().isEmpty()) {
    -  564  128
                             dbVer = DependencyVersionUtil.parseVersion(vs.getVersion() + '.' + vs.getUpdate());
    -  565   -
                         } else {
    -  566  308
                             dbVer = DependencyVersionUtil.parseVersion(vs.getVersion());
    -  567   +  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  
                         }
    -  568  436
                         if (dbVer == null) { //special case, no version specified - everything is vulnerable
    -  569  0
                             hasBroadMatch = true;
    -  570  0
                             final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8"));
    -  571  0
                             final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.BROAD_MATCH, conf);
    -  572  0
                             collected.add(match);
    -  573  0
                         } else if (evVer.equals(dbVer)) { //yeah! exact match
    -  574  8
                             final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8"));
    -  575  8
                             final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf);
    -  576  8
                             collected.add(match);
    -  577   +  226  18
                     }
    +  227  11
                     if (identifierAdded) {
    +  228  1
                         break;
    +  229   +
                     }
    +  230   +
                 }
    +  231   +
             }
    +  232  4
         }
    +  233  
     
    -  578   -
                             //TODO the following isn't quite right is it? need to think about this guessing game a bit more.
    -  579  8
                         } else if (evVer.getVersionParts().size() <= dbVer.getVersionParts().size()
    -  580  420
                                 && evVer.matchesAtLeastThreeLevels(dbVer)) {
    -  581  64
                             if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) {
    -  582  2
                                 if (bestGuess.getVersionParts().size() < dbVer.getVersionParts().size()) {
    -  583  2
                                     bestGuess = dbVer;
    -  584  2
                                     bestGuessConf = conf;
    -  585   -
                                 }
    -  586   +  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  
                             }
    -  587   +  394   +
                             break;
    +  395  
                         }
    -  588  436
                     }
    -  589  12
                     if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) {
    -  590  1
                         if (bestGuess.getVersionParts().size() < evVer.getVersionParts().size()) {
    -  591  1
                             bestGuess = evVer;
    -  592  1
                             bestGuessConf = conf;
    -  593   -
                         }
    -  594   -
                     }
    -  595  12
                 }
    -  596   -
             }
    -  597  3
             final String cpeName = String.format("cpe:/a:%s:%s:%s", vendor, product, bestGuess.toString());
    -  598  3
             String url = null;
    -  599  3
             if (hasBroadMatch) { //if we have a broad match we can add the URL to the best guess.
    -  600  0
                 final String cpeUrlName = String.format("cpe:/a:%s:%s", vendor, product);
    -  601  0
                 url = String.format(NVD_SEARCH_URL, URLEncoder.encode(cpeUrlName, "UTF-8"));
    -  602   -
             }
    -  603  3
             if (bestGuessConf == null) {
    -  604  0
                 bestGuessConf = Confidence.LOW;
    -  605   -
             }
    -  606  3
             final IdentifierMatch match = new IdentifierMatch("cpe", cpeName, url, IdentifierConfidence.BEST_GUESS, bestGuessConf);
    -  607  3
             collected.add(match);
    -  608   -
     
    -  609  3
             Collections.sort(collected);
    -  610  3
             final IdentifierConfidence bestIdentifierQuality = collected.get(0).getConfidence();
    -  611  3
             final Confidence bestEvidenceQuality = collected.get(0).getEvidenceConfidence();
    -  612  3
             boolean identifierAdded = false;
    -  613  3
             for (IdentifierMatch m : collected) {
    -  614  11
                 if (bestIdentifierQuality.equals(m.getConfidence())
    -  615  9
                         && bestEvidenceQuality.equals(m.getEvidenceConfidence())) {
    -  616  3
                     final Identifier i = m.getIdentifier();
    -  617  3
                     if (bestIdentifierQuality == IdentifierConfidence.BEST_GUESS) {
    -  618  1
                         i.setConfidence(Confidence.LOW);
    -  619   +  396  216
                     }
    +  397  94
                     sb.append(' ');
    +  398  94
                     if (temp == null) {
    +  399  87
                         LuceneUtils.appendEscapedLuceneQuery(sb, word);
    +  400  
                     } else {
    -  620  2
                         i.setConfidence(bestEvidenceQuality);
    -  621   +  401  7
                         sb.append(temp);
    +  402  
                     }
    -  622  3
                     dependency.addIdentifier(i);
    -  623  3
                     identifierAdded = true;
    -  624   -
                 }
    -  625  11
             }
    -  626  3
             return identifierAdded;
    -  627   +  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   +
     
    +  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  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   +
                     }
    +  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   +
                         }
    +  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   +
     
    +  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   +
                             }
    +  588   +
                         }
    +  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   +
                     } else {
    +  621  2
                         i.setConfidence(bestEvidenceQuality);
    +  622   +
                     }
    +  623  3
                     dependency.addIdentifier(i);
    +  624  3
                     identifierAdded = true;
    +  625   +
                 }
    +  626  9
             }
    +  627  3
             return identifierAdded;
     628   -
     
    +
         }
     629   -
         /**
    +
     
     630   -
          * The confidence whether the identifier is an exact match, or a best guess.
    -  631   -
          */
    -  632  4
         private enum IdentifierConfidence {
    -  633   -
     
    -  634   -
             /**
    -  635   -
              * An exact match for the CPE.
    -  636   -
              */
    -  637  1
             EXACT_MATCH,
    -  638   -
             /**
    -  639   -
              * A best guess for the CPE.
    -  640   -
              */
    -  641  1
             BEST_GUESS,
    -  642   -
             /**
    -  643   -
              * The entire vendor/product group must be added (without a guess at
    -  644   -
              * version) because there is a CVE with a VS that only specifies
    -  645   -
              * vendor/product.
    -  646   -
              */
    -  647  1
             BROAD_MATCH
    -  648   -
         }
    -  649   -
     
    -  650  
         /**
    -  651   -
          * A simple object to hold an identifier and carry information about the
    -  652   -
          * confidence in the identifier.
    -  653   +  631   +
          * The confidence whether the identifier is an exact match, or a best guess.
    +  632  
          */
    -  654  8
         private static class IdentifierMatch implements Comparable<IdentifierMatch> {
    -  655   +  633  4
         private enum IdentifierConfidence {
    +  634  
     
    -  656   +  635  
             /**
    -  657   -
              * Constructs an IdentifierMatch.
    -  658   -
              *
    -  659   -
              * @param type the type of identifier (such as CPE)
    -  660   -
              * @param value the value of the identifier
    -  661   -
              * @param url the URL of the identifier
    -  662   -
              * @param identifierConfidence the confidence in the identifier: best
    -  663   -
              * guess or exact match
    -  664   -
              * @param evidenceConfidence the confidence of the evidence used to find
    -  665   -
              * the identifier
    -  666   +  636   +
              * An exact match for the CPE.
    +  637  
              */
    -  667  11
             IdentifierMatch(String type, String value, String url, IdentifierConfidence identifierConfidence, Confidence evidenceConfidence) {
    -  668  11
                 this.identifier = new Identifier(type, value, url);
    -  669  11
                 this.confidence = identifierConfidence;
    -  670  11
                 this.evidenceConfidence = evidenceConfidence;
    -  671  11
             }
    -  672   -
             //<editor-fold defaultstate="collapsed" desc="Property implementations: evidenceConfidence, confidence, identifier">
    -  673   +  638  1
             EXACT_MATCH,
    +  639  
             /**
    -  674   -
              * The confidence in the evidence used to identify this match.
    -  675   +  640   +
              * A best guess for the CPE.
    +  641  
              */
    -  676   -
             private Confidence evidenceConfidence;
    -  677   -
     
    -  678   +  642  1
             BEST_GUESS,
    +  643  
             /**
    -  679   -
              * Get the value of evidenceConfidence
    -  680   -
              *
    -  681   -
              * @return the value of evidenceConfidence
    -  682   +  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  
              */
    -  683   -
             public Confidence getEvidenceConfidence() {
    -  684  12
                 return evidenceConfidence;
    -  685   -
             }
    -  686   -
     
    -  687   -
             /**
    -  688   -
              * Set the value of evidenceConfidence
    -  689   -
              *
    -  690   -
              * @param evidenceConfidence new value of evidenceConfidence
    -  691   -
              */
    -  692   -
             public void setEvidenceConfidence(Confidence evidenceConfidence) {
    -  693  0
                 this.evidenceConfidence = evidenceConfidence;
    -  694  0
             }
    -  695   -
             /**
    -  696   -
              * The confidence whether this is an exact match, or a best guess.
    -  697   -
              */
    -  698   -
             private IdentifierConfidence confidence;
    -  699   -
     
    -  700   -
             /**
    -  701   -
              * Get the value of confidence.
    -  702   -
              *
    -  703   -
              * @return the value of confidence
    -  704   -
              */
    -  705   -
             public IdentifierConfidence getConfidence() {
    -  706  14
                 return confidence;
    -  707   -
             }
    -  708   -
     
    -  709   -
             /**
    -  710   -
              * Set the value of confidence.
    -  711   -
              *
    -  712   -
              * @param confidence new value of confidence
    -  713   -
              */
    -  714   -
             public void setConfidence(IdentifierConfidence confidence) {
    -  715  0
                 this.confidence = confidence;
    -  716  0
             }
    -  717   -
             /**
    -  718   -
              * The CPE identifier.
    -  719   -
              */
    -  720   -
             private Identifier identifier;
    -  721   -
     
    -  722   -
             /**
    -  723   -
              * Get the value of identifier.
    -  724   -
              *
    -  725   -
              * @return the value of identifier
    -  726   -
              */
    -  727   -
             public Identifier getIdentifier() {
    -  728  3
                 return identifier;
    -  729   -
             }
    -  730   -
     
    -  731   -
             /**
    -  732   -
              * Set the value of identifier.
    -  733   -
              *
    -  734   -
              * @param identifier new value of identifier
    -  735   -
              */
    -  736   -
             public void setIdentifier(Identifier identifier) {
    -  737  0
                 this.identifier = identifier;
    -  738  0
             }
    -  739   -
             //</editor-fold>
    -  740   -
             //<editor-fold defaultstate="collapsed" desc="Standard implementations of toString, hashCode, and equals">
    -  741   -
     
    -  742   -
             /**
    -  743   -
              * Standard toString() implementation.
    -  744   -
              *
    -  745   -
              * @return the string representation of the object
    -  746   -
              */
    -  747   -
             @Override
    -  748   -
             public String toString() {
    -  749  0
                 return "IdentifierMatch{" + "evidenceConfidence=" + evidenceConfidence
    -  750   -
                         + ", confidence=" + confidence + ", identifier=" + identifier + '}';
    -  751   -
             }
    -  752   -
     
    -  753   -
             /**
    -  754   -
              * Standard hashCode() implementation.
    -  755   -
              *
    -  756   -
              * @return the hashCode
    -  757   -
              */
    -  758   -
             @Override
    -  759   -
             public int hashCode() {
    -  760  0
                 int hash = 5;
    -  761  0
                 hash = 97 * hash + (this.evidenceConfidence != null ? this.evidenceConfidence.hashCode() : 0);
    -  762  0
                 hash = 97 * hash + (this.confidence != null ? this.confidence.hashCode() : 0);
    -  763  0
                 hash = 97 * hash + (this.identifier != null ? this.identifier.hashCode() : 0);
    -  764  0
                 return hash;
    -  765   -
             }
    -  766   -
     
    -  767   -
             /**
    -  768   -
              * Standard equals implementation.
    -  769   -
              *
    -  770   -
              * @param obj the object to compare
    -  771   -
              * @return true if the objects are equal, otherwise false
    -  772   -
              */
    -  773   -
             @Override
    -  774   -
             public boolean equals(Object obj) {
    -  775  0
                 if (obj == null) {
    -  776  0
                     return false;
    -  777   -
                 }
    -  778  0
                 if (getClass() != obj.getClass()) {
    -  779  0
                     return false;
    -  780   -
                 }
    -  781  0
                 final IdentifierMatch other = (IdentifierMatch) obj;
    -  782  0
                 if (this.evidenceConfidence != other.evidenceConfidence) {
    -  783  0
                     return false;
    -  784   -
                 }
    -  785  0
                 if (this.confidence != other.confidence) {
    -  786  0
                     return false;
    -  787   -
                 }
    -  788  0
                 if (this.identifier != other.identifier && (this.identifier == null || !this.identifier.equals(other.identifier))) {
    -  789  0
                     return false;
    -  790   -
                 }
    -  791  0
                 return true;
    -  792   -
             }
    -  793   -
             //</editor-fold>
    -  794   -
     
    -  795   -
             /**
    -  796   -
              * Standard implementation of compareTo that compares identifier
    -  797   -
              * confidence, evidence confidence, and then the identifier.
    -  798   -
              *
    -  799   -
              * @param o the IdentifierMatch to compare to
    -  800   -
              * @return the natural ordering of IdentifierMatch
    -  801   -
              */
    -  802   -
             @Override
    -  803   -
             public int compareTo(IdentifierMatch o) {
    -  804  8
                 int conf = this.confidence.compareTo(o.confidence);
    -  805  8
                 if (conf == 0) {
    -  806  6
                     conf = this.evidenceConfidence.compareTo(o.evidenceConfidence);
    -  807  6
                     if (conf == 0) {
    -  808  2
                         conf = identifier.compareTo(o.identifier);
    -  809   -
                     }
    -  810   -
                 }
    -  811  8
                 return conf;
    -  812   -
             }
    -  813   +  648  1
             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  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   +
             }
    +  687   +
     
    +  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   +
     
    +  701   +
             /**
    +  702   +
              * Get the value of confidence.
    +  703   +
              *
    +  704   +
              * @return the value of confidence
    +  705   +
              */
    +  706   +
             public IdentifierConfidence getConfidence() {
    +  707  12
                 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  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   +
             }
    +  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   +
                 /*
    +  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  
     }
    - + 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 b82a68125..802ad4e38 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CentralAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CentralAnalyzer.html @@ -12,7 +12,7 @@
     
    - +
    Classes in this File Line Coverage Branch Coverage Complexity
    CentralAnalyzer
    24%
    18/73
    10%
    3/30
    3.875
    CentralAnalyzer
    24%
    18/74
    9%
    3/32
    4
     
    @@ -352,7 +352,7 @@
         @Override
     184  
         protected FileFilter getFileFilter() {
    -  185  10
             return FILTER;
    +  185  859
             return FILTER;
     186  
         }
     187   @@ -418,30 +418,31 @@  230  0
                                     + "this could result in undetected CPE/CVEs.", dependency.getFileName());
     231  
                         } finally {
    -  232  0
                             if (pomFile != null && !FileUtils.deleteQuietly(pomFile)) {
    -  233  0
                                 pomFile.deleteOnExit();
    -  234   -
                             }
    +  232  0
                             if (pomFile != null && pomFile.exists() && !FileUtils.deleteQuietly(pomFile)) {
    +  233  0
                                 LOGGER.debug("Failed to delete temporary pom file {}", pomFile.toString());
    +  234  0
                                 pomFile.deleteOnExit();
     235   -
                         }
    +
                             }
     236   -
                     }
    +
                         }
     237   +
                     }
    +  238  
     
    -  238  0
                 }
    -  239  0
             } catch (IllegalArgumentException iae) {
    -  240  0
                 LOGGER.info("invalid sha1-hash on {}", dependency.getFileName());
    -  241  0
             } catch (FileNotFoundException fnfe) {
    -  242  0
                 LOGGER.debug("Artifact not found in repository: '{}", dependency.getFileName());
    -  243  0
             } catch (IOException ioe) {
    -  244  0
                 LOGGER.debug("Could not connect to Central search", ioe);
    -  245  0
                 errorFlag = true;
    -  246  0
             }
    -  247  0
         }
    -  248   +  239  0
                 }
    +  240  0
             } catch (IllegalArgumentException iae) {
    +  241  0
                 LOGGER.info("invalid sha1-hash on {}", dependency.getFileName());
    +  242  0
             } catch (FileNotFoundException fnfe) {
    +  243  0
                 LOGGER.debug("Artifact not found in repository: '{}", dependency.getFileName());
    +  244  0
             } catch (IOException ioe) {
    +  245  0
                 LOGGER.debug("Could not connect to Central search", ioe);
    +  246  0
                 errorFlag = true;
    +  247  0
             }
    +  248  0
         }
    +  249  
     }
    - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CocoaPodsAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CocoaPodsAnalyzer.html new file mode 100644 index 000000000..887ff7670 --- /dev/null +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CocoaPodsAnalyzer.html @@ -0,0 +1,385 @@ + + + + +Coverage Report + + + + +
    Coverage Report - org.owasp.dependencycheck.analyzer.CocoaPodsAnalyzer
    +
     
    + + + + +
    Classes in this File Line Coverage Branch Coverage Complexity
    CocoaPodsAnalyzer
    95%
    47/49
    75%
    9/12
    2
    +
     
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     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 IBM Corporation. All Rights Reserved.
     17  
      */
     18  
     package org.owasp.dependencycheck.analyzer;
     19  
     
     20  
     import java.io.File;
     21  
     import java.io.FileFilter;
     22  
     import java.io.IOException;
     23  
     import java.nio.charset.Charset;
     24  
     import java.util.regex.Matcher;
     25  
     import java.util.regex.Pattern;
     26  
     
     27  
     import org.apache.commons.io.FileUtils;
     28  
     import org.owasp.dependencycheck.Engine;
     29  
     import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
     30  
     import org.owasp.dependencycheck.dependency.Confidence;
     31  
     import org.owasp.dependencycheck.dependency.Dependency;
     32  
     import org.owasp.dependencycheck.dependency.EvidenceCollection;
     33  
     import org.owasp.dependencycheck.utils.FileFilterBuilder;
     34  
     import org.owasp.dependencycheck.utils.Settings;
     35  
     
     36  
     /**
     37  
      * This analyzer is used to analyze SWIFT and Objective-C packages by collecting
     38  
      * information from .podspec files. CocoaPods dependency manager see
     39  
      * https://cocoapods.org/.
     40  
      *
     41  
      * @author Bianca Jiang (https://twitter.com/biancajiang)
     42  
      */
     43  
     @Experimental
     44  12
     public class CocoaPodsAnalyzer extends AbstractFileTypeAnalyzer {
     45  
     
     46  
         /**
     47  
          * The logger.
     48  
          */
     49  
     //    private static final Logger LOGGER = LoggerFactory.getLogger(CocoaPodsAnalyzer.class);
     50  
         /**
     51  
          * The name of the analyzer.
     52  
          */
     53  
         private static final String ANALYZER_NAME = "CocoaPods Package Analyzer";
     54  
     
     55  
         /**
     56  
          * The phase that this analyzer is intended to run in.
     57  
          */
     58  1
         private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
     59  
     
     60  
         /**
     61  
          * The file name to scan.
     62  
          */
     63  
         public static final String PODSPEC = "podspec";
     64  
         /**
     65  
          * Filter that detects files named "*.podspec".
     66  
          */
     67  1
         private static final FileFilter PODSPEC_FILTER = FileFilterBuilder.newInstance().addExtensions(PODSPEC).build();
     68  
     
     69  
         /**
     70  
          * The capture group #1 is the block variable. e.g. "Pod::Spec.new do
     71  
          * |spec|"
     72  
          */
     73  1
         private static final Pattern PODSPEC_BLOCK_PATTERN = Pattern.compile("Pod::Spec\\.new\\s+?do\\s+?\\|(.+?)\\|");
     74  
     
     75  
         /**
     76  
          * Returns the FileFilter
     77  
          *
     78  
          * @return the FileFilter
     79  
          */
     80  
         @Override
     81  
         protected FileFilter getFileFilter() {
     82  860
             return PODSPEC_FILTER;
     83  
         }
     84  
     
     85  
         @Override
     86  
         protected void initializeFileTypeAnalyzer() {
     87  
             // NO-OP
     88  6
         }
     89  
     
     90  
         /**
     91  
          * Returns the name of the analyzer.
     92  
          *
     93  
          * @return the name of the analyzer.
     94  
          */
     95  
         @Override
     96  
         public String getName() {
     97  15
             return ANALYZER_NAME;
     98  
         }
     99  
     
     100  
         /**
     101  
          * Returns the phase that the analyzer is intended to run in.
     102  
          *
     103  
          * @return the phase that the analyzer is intended to run in.
     104  
          */
     105  
         @Override
     106  
         public AnalysisPhase getAnalysisPhase() {
     107  4
             return ANALYSIS_PHASE;
     108  
         }
     109  
     
     110  
         /**
     111  
          * Returns the key used in the properties file to reference the analyzer's
     112  
          * enabled property.
     113  
          *
     114  
          * @return the analyzer's enabled property setting key
     115  
          */
     116  
         @Override
     117  
         protected String getAnalyzerEnabledSettingKey() {
     118  12
             return Settings.KEYS.ANALYZER_COCOAPODS_ENABLED;
     119  
         }
     120  
     
     121  
         @Override
     122  
         protected void analyzeFileType(Dependency dependency, Engine engine)
     123  
                 throws AnalysisException {
     124  
     
     125  
             String contents;
     126  
             try {
     127  1
                 contents = FileUtils.readFileToString(dependency.getActualFile(), Charset.defaultCharset());
     128  0
             } catch (IOException e) {
     129  0
                 throw new AnalysisException(
     130  
                         "Problem occurred while reading dependency file.", e);
     131  1
             }
     132  1
             final Matcher matcher = PODSPEC_BLOCK_PATTERN.matcher(contents);
     133  1
             if (matcher.find()) {
     134  1
                 contents = contents.substring(matcher.end());
     135  1
                 final String blockVariable = matcher.group(1);
     136  
     
     137  1
                 final EvidenceCollection vendor = dependency.getVendorEvidence();
     138  1
                 final EvidenceCollection product = dependency.getProductEvidence();
     139  1
                 final EvidenceCollection version = dependency.getVersionEvidence();
     140  
     
     141  1
                 final String name = addStringEvidence(product, contents, blockVariable, "name", "name", Confidence.HIGHEST);
     142  1
                 if (!name.isEmpty()) {
     143  1
                     vendor.addEvidence(PODSPEC, "name_project", name, Confidence.HIGHEST);
     144  
                 }
     145  1
                 addStringEvidence(product, contents, blockVariable, "summary", "summary", Confidence.HIGHEST);
     146  
     
     147  1
                 addStringEvidence(vendor, contents, blockVariable, "author", "authors?", Confidence.HIGHEST);
     148  1
                 addStringEvidence(vendor, contents, blockVariable, "homepage", "homepage", Confidence.HIGHEST);
     149  1
                 addStringEvidence(vendor, contents, blockVariable, "license", "licen[cs]es?", Confidence.HIGHEST);
     150  
     
     151  1
                 addStringEvidence(version, contents, blockVariable, "version", "version", Confidence.HIGHEST);
     152  
             }
     153  
     
     154  1
             setPackagePath(dependency);
     155  1
         }
     156  
     
     157  
         /**
     158  
          * Extracts evidence from the contents and adds it to the given evidence
     159  
          * collection.
     160  
          *
     161  
          * @param evidences the evidence collection to update
     162  
          * @param contents the text to extract evidence from
     163  
          * @param blockVariable the block variable within the content to search for
     164  
          * @param field the name of the field being searched for
     165  
          * @param fieldPattern the field pattern within the contents to search for
     166  
          * @param confidence the confidence level of the evidence if found
     167  
          * @return the string that was added as evidence
     168  
          */
     169  
         private String addStringEvidence(EvidenceCollection evidences, String contents,
     170  
                 String blockVariable, String field, String fieldPattern, Confidence confidence) {
     171  6
             String value = "";
     172  
     
     173  
             //capture array value between [ ]
     174  12
             final Matcher arrayMatcher = Pattern.compile(
     175  6
                     String.format("\\s*?%s\\.%s\\s*?=\\s*?\\{\\s*?(.*?)\\s*?\\}", blockVariable, fieldPattern),
     176  6
                     Pattern.CASE_INSENSITIVE).matcher(contents);
     177  6
             if (arrayMatcher.find()) {
     178  1
                 value = arrayMatcher.group(1);
     179  
             } else { //capture single value between quotes
     180  10
                 final Matcher matcher = Pattern.compile(
     181  5
                         String.format("\\s*?%s\\.%s\\s*?=\\s*?(['\"])(.*?)\\1", blockVariable, fieldPattern),
     182  5
                         Pattern.CASE_INSENSITIVE).matcher(contents);
     183  5
                 if (matcher.find()) {
     184  4
                     value = matcher.group(2);
     185  
                 }
     186  
             }
     187  6
             if (value.length() > 0) {
     188  5
                 evidences.addEvidence(PODSPEC, field, value, confidence);
     189  
             }
     190  6
             return value;
     191  
         }
     192  
     
     193  
         /**
     194  
          * Sets the package path on the given dependency.
     195  
          *
     196  
          * @param dep the dependency to update
     197  
          */
     198  
         private void setPackagePath(Dependency dep) {
     199  1
             final File file = new File(dep.getFilePath());
     200  1
             final String parent = file.getParent();
     201  1
             if (parent != null) {
     202  1
                 dep.setPackagePath(parent);
     203  
             }
     204  1
         }
     205  
     }
    + + + + 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 7b79e3fda..509d17f64 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.ComposerLockAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.ComposerLockAnalyzer.html @@ -164,7 +164,7 @@
         @Override
     75  
         protected FileFilter getFileFilter() {
    -  76  11
             return FILE_FILTER;
    +  76  860
             return FILE_FILTER;
     77  
         }
     78   @@ -322,6 +322,6 @@
     }
    - + 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 bab0ed12e..1125a5821 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CpeSuppressionAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CpeSuppressionAnalyzer.html @@ -152,13 +152,13 @@  70  
     
     71  4
             for (final SuppressionRule rule : getRules()) {
    -  72  224
                 rule.process(dependency);
    -  73  224
             }
    +  72  228
                 rule.process(dependency);
    +  73  228
             }
     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 f74c05d1f..460a7d7ea 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%
    72/178
    30%
    57/184
    7.688
    DependencyBundlingAnalyzer
    40%
    82/201
    30%
    64/212
    8
     
    @@ -238,40 +238,40 @@  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
                             if (hashesMatch(dependency, nextDependency) && !containedInWar(dependency.getFilePath())
    -  121  0
                                     && !containedInWar(nextDependency.getFilePath())) {
    -  122  0
                                 if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) {
    -  123  0
                                     mergeDependencies(dependency, nextDependency, dependenciesToRemove);
    -  124   +  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);
    +  125  
                                 } else {
    -  125  0
                                     mergeDependencies(nextDependency, dependency, dependenciesToRemove);
    -  126  0
                                     break; //since we merged into the next dependency - skip forward to the next in mainIterator
    -  127   +  126  0
                                     mergeDependencies(nextDependency, dependency, dependenciesToRemove);
    +  127  0
                                     break; //since we merged into the next dependency - skip forward to the next in mainIterator
    +  128  
                                 }
    -  128  2
                             } else if (isShadedJar(dependency, nextDependency)) {
    -  129  0
                                 if (dependency.getFileName().toLowerCase().endsWith("pom.xml")) {
    -  130  0
                                     mergeDependencies(nextDependency, dependency, dependenciesToRemove);
    -  131  0
                                     nextDependency.getRelatedDependencies().remove(dependency);
    -  132  0
                                     break;
    -  133   +  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 {
    -  134  0
                                     mergeDependencies(dependency, nextDependency, dependenciesToRemove);
    -  135  0
                                     dependency.getRelatedDependencies().remove(nextDependency);
    -  136   +  135  0
                                     mergeDependencies(dependency, nextDependency, dependenciesToRemove);
    +  136  0
                                     dependency.getRelatedDependencies().remove(nextDependency);
    +  137  
                                 }
    -  137  2
                             } else if (cpeIdentifiersMatch(dependency, nextDependency)
    -  138  0
                                     && hasSameBasePath(dependency, nextDependency)
    -  139  0
                                     && fileNameMatch(dependency, nextDependency)) {
    -  140  0
                                 if (isCore(dependency, nextDependency)) {
    -  141  0
                                     mergeDependencies(dependency, nextDependency, dependenciesToRemove);
    -  142   +  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 {
    -  143  0
                                     mergeDependencies(nextDependency, dependency, dependenciesToRemove);
    -  144  0
                                     break; //since we merged into the next dependency - skip forward to the next in mainIterator
    -  145   +  144  0
                                     mergeDependencies(nextDependency, dependency, dependenciesToRemove);
    +  145  0
                                     break; //since we merged into the next dependency - skip forward to the next in mainIterator
    +  146  
                                 }
    -  146  2
                             } else if (isSameRubyGem(dependency, nextDependency)) {
    -  147  0
                                 final Dependency main = getMainGemspecDependency(dependency, nextDependency);
    +  147  2
                             } else if ((main = getMainGemspecDependency(dependency, nextDependency)) != null) {
     148  0
                                 if (main == dependency) {
     149  0
                                     mergeDependencies(dependency, nextDependency, dependenciesToRemove);
     150   @@ -280,579 +280,662 @@  152  0
                                     break; //since we merged into the next dependency - skip forward to the next in mainIterator
     153  
                                 }
    -  154   -
                             }
    -  155  2
                         }
    -  156   -
                     }
    -  157  4
                 }
    -  158   -
                 //removing dependencies here as ensuring correctness and avoiding ConcurrentUpdateExceptions
    -  159   -
                 // was difficult because of the inner iterator.
    -  160  2
                 engine.getDependencies().removeAll(dependenciesToRemove);
    +  154  2
                             } else if ((main = getMainSwiftDependency(dependency, nextDependency)) != null) {
    +  155  0
                                 if (main == dependency) {
    +  156  0
                                     mergeDependencies(dependency, nextDependency, dependenciesToRemove);
    +  157   +
                                 } 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   +
                                 }
     161   -
             }
    -  162  4
         }
    +
                             }
    +  162  2
                         }
     163   -
     
    -  164   -
         /**
    +
                     }
    +  164  4
                 }
     165   -
          * Adds the relatedDependency to the dependency's related dependencies.
    +
                 //removing dependencies here as ensuring correctness and avoiding ConcurrentUpdateExceptions
     166   -
          *
    -  167   -
          * @param dependency the main dependency
    +
                 // was difficult because of the inner iterator.
    +  167  2
                 engine.getDependencies().removeAll(dependenciesToRemove);
     168   -
          * @param relatedDependency a collection of dependencies to be removed from
    -  169   -
          * the main analysis loop, this is the source of dependencies to remove
    +
             }
    +  169  4
         }
     170   -
          * @param dependenciesToRemove a collection of dependencies that will be
    -  171   -
          * removed from the main analysis loop, this function adds to this
    -  172   -
          * collection
    -  173   -
          */
    -  174   -
         private void mergeDependencies(final Dependency dependency, final Dependency relatedDependency, final Set<Dependency> dependenciesToRemove) {
    -  175  0
             dependency.addRelatedDependency(relatedDependency);
    -  176  0
             final Iterator<Dependency> i = relatedDependency.getRelatedDependencies().iterator();
    -  177  0
             while (i.hasNext()) {
    -  178  0
                 dependency.addRelatedDependency(i.next());
    -  179  0
                 i.remove();
    -  180   -
             }
    -  181  0
             if (dependency.getSha1sum().equals(relatedDependency.getSha1sum())) {
    -  182  0
                 dependency.addAllProjectReferences(relatedDependency.getProjectReferences());
    -  183   -
             }
    -  184  0
             dependenciesToRemove.add(relatedDependency);
    -  185  0
         }
    -  186  
     
    -  187   +  171  
         /**
    -  188   -
          * Attempts to trim a maven repo to a common base path. This is typically
    -  189   -
          * [drive]\[repo_location]\repository\[path1]\[path2].
    -  190   +  172   +
          * Adds the relatedDependency to the dependency's related dependencies.
    +  173  
          *
    -  191   -
          * @param path the path to trim
    -  192   -
          * @return a string representing the base path.
    -  193   +  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  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());
    +  190   +
             }
    +  191  0
             dependenciesToRemove.add(relatedDependency);
    +  192  0
         }
    +  193   +
     
     194   -
         private String getBaseRepoPath(final String path) {
    -  195  0
             int pos = path.indexOf("repository" + File.separator) + 11;
    -  196  0
             if (pos < 0) {
    -  197  0
                 return path;
    +
         /**
    +  195   +
          * Attempts to trim a maven repo to a common base path. This is typically
    +  196   +
          * [drive]\[repo_location]\repository\[path1]\[path2].
    +  197   +
          *
     198   -
             }
    -  199  0
             int tmp = path.indexOf(File.separator, pos);
    -  200  0
             if (tmp <= 0) {
    -  201  0
                 return path;
    -  202   -
             }
    -  203  0
             if (tmp > 0) {
    -  204  0
                 pos = tmp + 1;
    +
          * @param path the path to trim
    +  199   +
          * @return a string representing the base path.
    +  200   +
          */
    +  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;
     205  
             }
    -  206  0
             tmp = path.indexOf(File.separator, pos);
    -  207  0
             if (tmp > 0) {
    -  208  0
                 pos = tmp + 1;
    +  206  0
             int tmp = path.indexOf(File.separator, pos);
    +  207  0
             if (tmp <= 0) {
    +  208  0
                 return path;
     209  
             }
    -  210  0
             return path.substring(0, pos);
    -  211   -
         }
    +  210  0
             if (tmp > 0) {
    +  211  0
                 pos = tmp + 1;
     212   -
     
    -  213   -
         /**
    -  214   -
          * Returns true if the file names (and version if it exists) of the two
    -  215   -
          * dependencies are sufficiently similar.
    +
             }
    +  213  0
             tmp = path.indexOf(File.separator, pos);
    +  214  0
             if (tmp > 0) {
    +  215  0
                 pos = tmp + 1;
     216   -
          *
    -  217   -
          * @param dependency1 a dependency2 to compare
    +
             }
    +  217  0
             return path.substring(0, pos);
     218   -
          * @param dependency2 a dependency2 to compare
    +
         }
     219   -
          * @return true if the identifiers in the two supplied dependencies are
    -  220   -
          * equal
    -  221   -
          */
    -  222   -
         private boolean fileNameMatch(Dependency dependency1, Dependency dependency2) {
    -  223  0
             if (dependency1 == null || dependency1.getFileName() == null
    -  224  0
                     || dependency2 == null || dependency2.getFileName() == null) {
    -  225  0
                 return false;
    -  226   -
             }
    -  227  0
             final String fileName1 = dependency1.getActualFile().getName();
    -  228  0
             final String fileName2 = dependency2.getActualFile().getName();
    -  229  
     
    -  230   -
             //version check
    -  231  0
             final DependencyVersion version1 = DependencyVersionUtil.parseVersion(fileName1);
    -  232  0
             final DependencyVersion version2 = DependencyVersionUtil.parseVersion(fileName2);
    -  233  0
             if (version1 != null && version2 != null && !version1.equals(version2)) {
    -  234  0
                 return false;
    -  235   +  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  0
             if (dependency1 == null || dependency1.getFileName() == null
    +  231  0
                     || dependency2 == null || dependency2.getFileName() == null) {
    +  232  0
                 return false;
    +  233  
             }
    +  234  0
             final String fileName1 = dependency1.getActualFile().getName();
    +  235  0
             final String fileName2 = dependency2.getActualFile().getName();
     236  
     
     237   -
             //filename check
    -  238  0
             final Matcher match1 = STARTING_TEXT_PATTERN.matcher(fileName1);
    -  239  0
             final Matcher match2 = STARTING_TEXT_PATTERN.matcher(fileName2);
    -  240  0
             if (match1.find() && match2.find()) {
    -  241  0
                 return match1.group().equals(match2.group());
    +
             //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  
             }
     243  
     
    -  244  0
             return false;
    -  245   -
         }
    -  246   -
     
    -  247   -
         /**
    -  248   -
          * Returns true if the CPE identifiers in the two supplied dependencies are
    +  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   -
          * equal.
    +
             }
     250   -
          *
    -  251   -
          * @param dependency1 a dependency2 to compare
    -  252   -
          * @param dependency2 a dependency2 to compare
    -  253   -
          * @return true if the identifiers in the two supplied dependencies are
    -  254   -
          * equal
    -  255   -
          */
    -  256   -
         private boolean cpeIdentifiersMatch(Dependency dependency1, Dependency dependency2) {
    -  257  2
             if (dependency1 == null || dependency1.getIdentifiers() == null
    -  258  2
                     || dependency2 == null || dependency2.getIdentifiers() == null) {
    -  259  0
                 return false;
    -  260   -
             }
    -  261  2
             boolean matches = false;
    -  262  2
             int cpeCount1 = 0;
    -  263  2
             int cpeCount2 = 0;
    -  264  2
             for (Identifier i : dependency1.getIdentifiers()) {
    -  265  0
                 if ("cpe".equals(i.getType())) {
    -  266  0
                     cpeCount1 += 1;
    -  267   -
                 }
    -  268  0
             }
    -  269  2
             for (Identifier i : dependency2.getIdentifiers()) {
    -  270  3
                 if ("cpe".equals(i.getType())) {
    -  271  3
                     cpeCount2 += 1;
    -  272   -
                 }
    -  273  3
             }
    -  274  2
             if (cpeCount1 > 0 && cpeCount1 == cpeCount2) {
    -  275  0
                 for (Identifier i : dependency1.getIdentifiers()) {
    -  276  0
                     if ("cpe".equals(i.getType())) {
    -  277  0
                         matches |= dependency2.getIdentifiers().contains(i);
    -  278  0
                         if (!matches) {
    -  279  0
                             break;
    -  280   -
                         }
    -  281   -
                     }
    -  282  0
                 }
    -  283   -
             }
    -  284  2
             LOGGER.debug("IdentifiersMatch={} ({}, {})", matches, dependency1.getFileName(), dependency2.getFileName());
    -  285  2
             return matches;
    -  286   -
         }
    -  287  
     
    -  288   +  251  0
             return false;
    +  252   +
         }
    +  253   +
     
    +  254  
         /**
    -  289   -
          * Determines if the two dependencies have the same base path.
    -  290   +  255   +
          * Returns true if the CPE identifiers in the two supplied dependencies are
    +  256   +
          * equal.
    +  257  
          *
    -  291   -
          * @param dependency1 a Dependency object
    -  292   -
          * @param dependency2 a Dependency object
    -  293   -
          * @return true if the base paths of the dependencies are identical
    -  294   +  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  
          */
    -  295   -
         private boolean hasSameBasePath(Dependency dependency1, Dependency dependency2) {
    -  296  0
             if (dependency1 == null || dependency2 == null) {
    -  297  0
                 return false;
    -  298   +  263   +
         private boolean cpeIdentifiersMatch(Dependency dependency1, Dependency dependency2) {
    +  264  2
             if (dependency1 == null || dependency1.getIdentifiers() == null
    +  265  2
                     || dependency2 == null || dependency2.getIdentifiers() == null) {
    +  266  0
                 return false;
    +  267  
             }
    -  299  0
             final File lFile = new File(dependency1.getFilePath());
    -  300  0
             String left = lFile.getParent();
    -  301  0
             final File rFile = new File(dependency2.getFilePath());
    -  302  0
             String right = rFile.getParent();
    -  303  0
             if (left == null) {
    -  304  0
                 return right == null;
    +  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;
    +  274   +
                 }
    +  275  0
             }
    +  276  2
             for (Identifier i : dependency2.getIdentifiers()) {
    +  277  3
                 if ("cpe".equals(i.getType())) {
    +  278  3
                     cpeCount2 += 1;
    +  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;
    +  287   +
                         }
    +  288   +
                     }
    +  289  0
                 }
    +  290   +
             }
    +  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
    +  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
             if (left.equalsIgnoreCase(right)) {
    -  307  0
                 return true;
    -  308   +  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  
             }
    -  309  0
             if (left.matches(".*[/\\\\]repository[/\\\\].*") && right.matches(".*[/\\\\]repository[/\\\\].*")) {
    -  310  0
                 left = getBaseRepoPath(left);
    -  311  0
                 right = getBaseRepoPath(right);
    -  312   +  315  0
             if (left.equalsIgnoreCase(right)) {
    +  316  0
                 return true;
    +  317  
             }
    -  313  0
             if (left.equalsIgnoreCase(right)) {
    -  314  0
                 return true;
    -  315   -
             }
    -  316   -
             //new code
    -  317  0
             for (Dependency child : dependency2.getRelatedDependencies()) {
    -  318  0
                 if (hasSameBasePath(dependency1, child)) {
    -  319  0
                     return true;
    -  320   -
                 }
    -  321  0
             }
    -  322  0
             return false;
    -  323   -
         }
    -  324   +  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   -
          * Bundling Ruby gems that are identified from different .gemspec files but
    -  327   -
          * denote the same package path. This happens when Ruby bundler installs an
    -  328   -
          * application's dependencies by running "bundle install".
    -  329   -
          *
    +
             //new code
    +  327  0
             for (Dependency child : dependency2.getRelatedDependencies()) {
    +  328  0
                 if (hasSameBasePath(dependency1, child)) {
    +  329  0
                     return true;
     330   -
          * @param dependency1 dependency to compare
    -  331   -
          * @param dependency2 dependency to compare
    -  332   -
          * @return true if the the dependencies being analyzed appear to be the
    +
                 }
    +  331  0
             }
    +  332  0
             return false;
     333   -
          * same; otherwise false
    +
         }
     334   -
          */
    +
     
     335   -
         private boolean isSameRubyGem(Dependency dependency1, Dependency dependency2) {
    -  336  2
             if (dependency1 == null || dependency2 == null
    -  337  2
                     || !dependency1.getFileName().endsWith(".gemspec")
    -  338  0
                     || !dependency2.getFileName().endsWith(".gemspec")
    -  339  0
                     || dependency1.getPackagePath() == null
    -  340  0
                     || dependency2.getPackagePath() == null) {
    -  341  2
                 return false;
    -  342   -
             }
    -  343  0
             if (dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath())) {
    -  344  0
                 return true;
    -  345   -
             }
    -  346   -
     
    -  347  0
             return false;
    -  348   -
         }
    -  349   -
     
    -  350  
         /**
    -  351   -
          * Ruby gems installed by "bundle install" can have zero or more *.gemspec
    -  352   -
          * files, all of which have the same packagePath and should be grouped. If
    -  353   -
          * one of these gemspec is from <parent>/specifications/*.gemspec, because
    -  354   -
          * it is a stub with fully resolved gem meta-data created by Ruby bundler,
    -  355   -
          * this dependency should be the main one. Otherwise, use dependency2 as
    -  356   -
          * main.
    -  357   +  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  
          *
    -  358   -
          * This method returns null if any dependency is not from *.gemspec, or the
    -  359   -
          * two do not have the same packagePath. In this case, they should not be
    -  360   -
          * grouped.
    -  361   -
          *
    -  362   +  340  
          * @param dependency1 dependency to compare
    -  363   +  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  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   +
             }
    +  353  0
             if (dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath())) {
    +  354  0
                 return true;
    +  355   +
             }
    +  356   +
     
    +  357  0
             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   -
          * @return the main dependency; or null if a gemspec is not included in the
    +
          * it is a stub with fully resolved gem meta-data created by Ruby bundler,
     365   -
          * analysis
    +
          * this dependency should be the main one. Otherwise, use dependency2 as
     366   -
          */
    +
          * main.
     367   -
         private Dependency getMainGemspecDependency(Dependency dependency1, Dependency dependency2) {
    -  368  0
             if (isSameRubyGem(dependency1, dependency2)) {
    -  369  0
                 final File lFile = dependency1.getActualFile();
    -  370  0
                 final File left = lFile.getParentFile();
    -  371  0
                 if (left != null && left.getName().equalsIgnoreCase("specifications")) {
    -  372  0
                     return dependency1;
    +
          *
    +  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   -
                 }
    -  374  0
                 return dependency2;
    +
          * @param dependency2 dependency to compare
    +  374   +
          * @return the main dependency; or null if a gemspec is not included in the
     375   -
             }
    -  376  0
             return null;
    +
          * analysis
    +  376   +
          */
     377   -
         }
    -  378   -
     
    -  379   -
         /**
    -  380   -
          * This is likely a very broken attempt at determining if the 'left'
    -  381   -
          * dependency is the 'core' library in comparison to the 'right' library.
    -  382   -
          *
    +
         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   -
          * @param left the dependency to test
    -  384   -
          * @param right the dependency to test against
    -  385   -
          * @return a boolean indicating whether or not the left dependency should be
    -  386   -
          * considered the "core" version.
    -  387   -
          */
    -  388   -
         boolean isCore(Dependency left, Dependency right) {
    -  389  2
             final String leftName = left.getFileName().toLowerCase();
    -  390  2
             final String rightName = right.getFileName().toLowerCase();
    -  391   -
     
    -  392   -
             final boolean returnVal;
    -  393  2
             if (!rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+")
    -  394  2
                     || rightName.contains("core") && !leftName.contains("core")
    -  395  2
                     || rightName.contains("kernel") && !leftName.contains("kernel")) {
    -  396  0
                 returnVal = false;
    -  397  2
             } else if (rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && !leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+")
    -  398  1
                     || !rightName.contains("core") && leftName.contains("core")
    -  399  1
                     || !rightName.contains("kernel") && leftName.contains("kernel")) {
    -  400  2
                 returnVal = true;
    -  401   -
     //        } else if (leftName.matches(".*struts2\\-core.*") && rightName.matches(".*xwork\\-core.*")) {
    -  402   -
     //            returnVal = true;
    -  403   -
     //        } else if (rightName.matches(".*struts2\\-core.*") && leftName.matches(".*xwork\\-core.*")) {
    -  404   -
     //            returnVal = false;
    -  405   -
             } else {
    -  406   -
                 /*
    -  407   -
                  * considered splitting the names up and comparing the components,
    -  408   -
                  * but decided that the file name length should be sufficient as the
    -  409   -
                  * "core" component, if this follows a normal naming protocol should
    -  410   -
                  * be shorter:
    -  411   -
                  * axis2-saaj-1.4.1.jar
    -  412   -
                  * axis2-1.4.1.jar       <-----
    -  413   -
                  * axis2-kernel-1.4.1.jar
    -  414   -
                  */
    -  415  0
                 returnVal = leftName.length() <= rightName.length();
    -  416   -
             }
    -  417  2
             LOGGER.debug("IsCore={} ({}, {})", returnVal, left.getFileName(), right.getFileName());
    -  418  2
             return returnVal;
    -  419   -
         }
    -  420   -
     
    -  421   -
         /**
    -  422   -
          * Compares the SHA1 hashes of two dependencies to determine if they are
    -  423   -
          * equal.
    -  424   -
          *
    -  425   -
          * @param dependency1 a dependency object to compare
    -  426   -
          * @param dependency2 a dependency object to compare
    -  427   -
          * @return true if the sha1 hashes of the two dependencies match; otherwise
    -  428   -
          * false
    -  429   -
          */
    -  430   -
         private boolean hashesMatch(Dependency dependency1, Dependency dependency2) {
    -  431  2
             if (dependency1 == null || dependency2 == null || dependency1.getSha1sum() == null || dependency2.getSha1sum() == null) {
    -  432  0
                 return false;
    -  433   -
             }
    -  434  2
             return dependency1.getSha1sum().equals(dependency2.getSha1sum());
    -  435   -
         }
    -  436   -
     
    -  437   -
         /**
    -  438   -
          * Determines if the jar is shaded and the created pom.xml identified the
    -  439   -
          * same CPE as the jar - if so, the pom.xml dependency should be removed.
    -  440   -
          *
    -  441   -
          * @param dependency a dependency to check
    -  442   -
          * @param nextDependency another dependency to check
    -  443   -
          * @return true if on of the dependencies is a pom.xml and the identifiers
    -  444   -
          * between the two collections match; otherwise false
    -  445   -
          */
    -  446   -
         private boolean isShadedJar(Dependency dependency, Dependency nextDependency) {
    -  447  2
             final String mainName = dependency.getFileName().toLowerCase();
    -  448  2
             final String nextName = nextDependency.getFileName().toLowerCase();
    -  449  2
             if (mainName.endsWith(".jar") && nextName.endsWith("pom.xml")) {
    -  450  0
                 return dependency.getIdentifiers().containsAll(nextDependency.getIdentifiers());
    -  451  2
             } else if (nextName.endsWith(".jar") && mainName.endsWith("pom.xml")) {
    -  452  0
                 return nextDependency.getIdentifiers().containsAll(dependency.getIdentifiers());
    -  453   -
             }
    -  454  2
             return false;
    -  455   -
         }
    -  456   -
     
    -  457   -
         /**
    -  458   -
          * Determines which path is shortest; if path lengths are equal then we use
    -  459   -
          * compareTo of the string method to determine if the first path is smaller.
    -  460   -
          *
    -  461   -
          * @param left the first path to compare
    -  462   -
          * @param right the second path to compare
    -  463   -
          * @return <code>true</code> if the leftPath is the shortest; otherwise
    -  464   -
          * <code>false</code>
    -  465   -
          */
    -  466   -
         protected boolean firstPathIsShortest(String left, String right) {
    -  467  5
             final String leftPath = left.replace('\\', '/');
    -  468  5
             final String rightPath = right.replace('\\', '/');
    -  469   -
     
    -  470  5
             final int leftCount = countChar(leftPath, '/');
    -  471  5
             final int rightCount = countChar(rightPath, '/');
    -  472  5
             if (leftCount == rightCount) {
    -  473  3
                 return leftPath.compareTo(rightPath) <= 0;
    -  474   -
             } else {
    -  475  2
                 return leftCount < rightCount;
    -  476   -
             }
    -  477   -
         }
    -  478   -
     
    -  479   -
         /**
    -  480   -
          * Counts the number of times the character is present in the string.
    -  481   -
          *
    -  482   -
          * @param string the string to count the characters in
    -  483   -
          * @param c the character to count
    -  484   -
          * @return the number of times the character is present in the string
    -  485   -
          */
    -  486   -
         private int countChar(String string, char c) {
    -  487  10
             int count = 0;
    -  488  10
             final int max = string.length();
    -  489  116
             for (int i = 0; i < max; i++) {
    -  490  106
                 if (c == string.charAt(i)) {
    -  491  28
                     count++;
    -  492  
                 }
    -  493   +  384  0
                 return dependency2;
    +  385  
             }
    -  494  10
             return count;
    -  495   +  386  2
             return null;
    +  387  
         }
    -  496   +  388  
     
    -  497   +  389  
         /**
    -  498   -
          * Checks if the given file path is contained within a war or ear file.
    -  499   +  390   +
          * Bundling same swift dependencies with the same packagePath but identified
    +  391   +
          * by different analyzers.
    +  392  
          *
    -  500   -
          * @param filePath the file path to check
    -  501   -
          * @return true if the path contains '.war\' or '.ear\'.
    -  502   +  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>
    +  397  
          */
    -  503   -
         private boolean containedInWar(String filePath) {
    -  504  0
             return filePath == null ? false : filePath.matches(".*\\.(ear|war)[\\\\/].*");
    -  505   +  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   +
                 }
    +  427  0
                 return dependency2;
    +  428   +
             }
    +  429  2
             return null;
    +  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.
    +  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  2
             final String leftName = left.getFileName().toLowerCase();
    +  443  2
             final String rightName = right.getFileName().toLowerCase();
    +  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   +
             }
    +  547  10
             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  0
             return filePath == null ? false : filePath.matches(".*\\.(ear|war)[\\\\/].*");
    +  558   +
         }
    +  559  
     }
    - + 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 7ec00def3..836a03935 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 9c009e3f7..4e64ba2a1 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.FalsePositiveAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.FalsePositiveAnalyzer.html @@ -761,6 +761,6 @@
     }
    - + 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 a7844f398..e563dbd08 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.FileNameAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.FileNameAnalyzer.html @@ -12,7 +12,7 @@
     
    - +
    Classes in this File Line Coverage Branch Coverage Complexity
    FileNameAnalyzer
    89%
    17/19
    62%
    5/8
    2.333
    FileNameAnalyzer
    90%
    18/20
    62%
    5/8
    2.333
     
    @@ -157,85 +157,88 @@
          * Python init files
     72  
          */
    -  73  1
         private static final NameFileFilter IGNORED_FILES = new NameFileFilter(new String[]{
    -  74   -
             "__init__.py",
    +  73   +
         //CSOFF: WhitespaceAfter
    +  74  1
         private static final NameFileFilter IGNORED_FILES = new NameFileFilter(new String[]{
     75   -
             "__init__.pyc",
    +
             "__init__.py",
     76   -
             "__init__.pyo",
    +
             "__init__.pyc",
     77   -
         });
    +
             "__init__.pyo",});
     78   -
     
    +
         //CSON: WhitespaceAfter
     79   -
         /**
    +
     
     80   -
          * Collects information about the file name.
    +
         /**
     81   -
          *
    +
          * Collects information about the file name.
     82   -
          * @param dependency the dependency to analyze.
    +
          *
     83   -
          * @param engine the engine that is scanning the dependencies
    +
          * @param dependency the dependency to analyze.
     84   -
          * @throws AnalysisException is thrown if there is an error reading the JAR
    +
          * @param engine the engine that is scanning the dependencies
     85   -
          * file.
    +
          * @throws AnalysisException is thrown if there is an error reading the JAR
     86   -
          */
    +
          * file.
     87   -
         @Override
    +
          */
     88   -
         public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
    +
         @Override
     89   -
     
    +
         public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
     90   +
     
    +  91  
             //strip any path information that may get added by ArchiveAnalyzer, etc.
    -  91  6
             final File f = dependency.getActualFile();
    -  92  6
             final String fileName = FilenameUtils.removeExtension(f.getName());
    -  93   -
     
    +  92  6
             final File f = dependency.getActualFile();
    +  93  6
             final String fileName = FilenameUtils.removeExtension(f.getName());
     94   -
             //add version evidence
    -  95  6
             final DependencyVersion version = DependencyVersionUtil.parseVersion(fileName);
    -  96  6
             if (version != null) {
    -  97   -
                 // If the version number is just a number like 2 or 23, reduce the confidence
    -  98   -
                 // a shade. This should hopefully correct for cases like log4j.jar or
    -  99   -
                 // struts2-core.jar
    -  100  5
                 if (version.getVersionParts() == null || version.getVersionParts().size() < 2) {
    -  101  0
                     dependency.getVersionEvidence().addEvidence("file", "name",
    -  102  0
                             version.toString(), Confidence.MEDIUM);
    -  103   -
                 } else {
    -  104  10
                     dependency.getVersionEvidence().addEvidence("file", "version",
    -  105  5
                             version.toString(), Confidence.HIGHEST);
    -  106   -
                 }
    -  107  5
                 dependency.getVersionEvidence().addEvidence("file", "name",
    -  108   -
                         fileName, Confidence.MEDIUM);
    -  109   -
             }
    -  110  
     
    -  111  6
             if (!IGNORED_FILES.accept(f)) {
    -  112  6
                 dependency.getProductEvidence().addEvidence("file", "name",
    -  113   -
                         fileName, Confidence.HIGH);
    -  114  6
                 dependency.getVendorEvidence().addEvidence("file", "name",
    -  115   -
                         fileName, Confidence.HIGH);
    -  116   +  95   +
             //add version evidence
    +  96  6
             final DependencyVersion version = DependencyVersionUtil.parseVersion(fileName);
    +  97  6
             final String packageName = DependencyVersionUtil.parsePreVersion(fileName);
    +  98  6
             if (version != null) {
    +  99   +
                 // If the version number is just a number like 2 or 23, reduce the confidence
    +  100   +
                 // a shade. This should hopefully correct for cases like log4j.jar or
    +  101   +
                 // struts2-core.jar
    +  102  5
                 if (version.getVersionParts() == null || version.getVersionParts().size() < 2) {
    +  103  0
                     dependency.getVersionEvidence().addEvidence("file", "version",
    +  104  0
                             version.toString(), Confidence.MEDIUM);
    +  105   +
                 } else {
    +  106  10
                     dependency.getVersionEvidence().addEvidence("file", "version",
    +  107  5
                             version.toString(), Confidence.HIGHEST);
    +  108   +
                 }
    +  109  5
                 dependency.getVersionEvidence().addEvidence("file", "name",
    +  110   +
                         packageName, Confidence.MEDIUM);
    +  111  
             }
    -  117  6
         }
    +  112   +
     
    +  113  6
             if (!IGNORED_FILES.accept(f)) {
    +  114  6
                 dependency.getProductEvidence().addEvidence("file", "name",
    +  115   +
                         packageName, Confidence.HIGH);
    +  116  6
                 dependency.getVendorEvidence().addEvidence("file", "name",
    +  117   +
                         packageName, Confidence.HIGH);
     118   +
             }
    +  119  6
         }
    +  120  
     }
    - + 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 dbdcde749..12bec1241 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 345de6d05..55bc2c1e8 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.HintAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.HintAnalyzer.html @@ -12,7 +12,7 @@
     
    - +
    Classes in this File Line Coverage Branch Coverage Complexity
    HintAnalyzer
    45%
    49/107
    60%
    28/46
    8.8
    HintAnalyzer
    44%
    50/113
    57%
    29/50
    9.2
     
    @@ -258,16 +258,16 @@  126  
         public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
     127  4
             for (HintRule hint : hints.getHintRules()) {
    -  128  28
                 boolean shouldAdd = false;
    -  129  28
                 for (Evidence given : hint.getGivenVendor()) {
    +  128  48
                 boolean shouldAdd = false;
    +  129  48
                 for (Evidence given : hint.getGivenVendor()) {
     130  8
                     if (dependency.getVendorEvidence().getEvidence().contains(given)) {
     131  0
                         shouldAdd = true;
     132  0
                         break;
     133  
                     }
     134  8
                 }
    -  135  28
                 if (!shouldAdd) {
    -  136  28
                     for (Evidence given : hint.getGivenProduct()) {
    +  135  48
                 if (!shouldAdd) {
    +  136  48
                     for (Evidence given : hint.getGivenProduct()) {
     137  31
                         if (dependency.getProductEvidence().getEvidence().contains(given)) {
     138  1
                             shouldAdd = true;
     139  1
                             break;
    @@ -276,348 +276,362 @@  141  30
                     }
     142  
                 }
    -  143  28
                 if (!shouldAdd) {
    -  144  27
                     for (PropertyType pt : hint.getFilenames()) {
    -  145  4
                         if (pt.matches(dependency.getFileName())) {
    +  143  48
                 if (!shouldAdd) {
    +  144  47
                     for (PropertyType pt : hint.getFilenames()) {
    +  145  24
                         if (pt.matches(dependency.getFileName())) {
     146  0
                             shouldAdd = true;
     147  
                         }
    -  148  4
                     }
    +  148  24
                     }
     149  
                 }
    -  150  28
                 if (shouldAdd) {
    +  150  48
                 if (shouldAdd) {
     151  1
                     for (Evidence e : hint.getAddVendor()) {
     152  3
                         dependency.getVendorEvidence().addEvidence(e);
     153  3
                     }
     154  1
                     for (Evidence e : hint.getAddProduct()) {
     155  1
                         dependency.getProductEvidence().addEvidence(e);
     156  1
                     }
    -  157   +  157  1
                     for (Evidence e : hint.getAddVersion()) {
    +  158  0
                         dependency.getVersionEvidence().addEvidence(e);
    +  159  0
                     }
    +  160  
                 }
    -  158  28
             }
    -  159   +  161  48
             }
    +  162  
     
    -  160  4
             final Iterator<Evidence> itr = dependency.getVendorEvidence().iterator();
    -  161  4
             final List<Evidence> newEntries = new ArrayList<Evidence>();
    -  162  29
             while (itr.hasNext()) {
    -  163  25
                 final Evidence e = itr.next();
    -  164  25
                 for (VendorDuplicatingHintRule dhr : hints.getVendorDuplicatingHintRules()) {
    -  165  50
                     if (dhr.getValue().equalsIgnoreCase(e.getValue(false))) {
    -  166  0
                         newEntries.add(new Evidence(e.getSource() + " (hint)",
    -  167  0
                                 e.getName(), dhr.getDuplicate(), e.getConfidence()));
    -  168   +  163  4
             final Iterator<Evidence> itr = dependency.getVendorEvidence().iterator();
    +  164  4
             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))) {
    +  169  0
                         newEntries.add(new Evidence(e.getSource() + " (hint)",
    +  170  0
                                 e.getName(), dhr.getDuplicate(), e.getConfidence()));
    +  171  
                     }
    -  169  50
                 }
    -  170  25
             }
    -  171  4
             for (Evidence e : newEntries) {
    -  172  0
                 dependency.getVendorEvidence().addEvidence(e);
    -  173  0
             }
    -  174   -
     
    -  175   -
             //<editor-fold defaultstate="collapsed" desc="Old implementation">
    -  176   -
             /*
    +  172  50
                 }
    +  173  25
             }
    +  174  4
             for (Evidence e : newEntries) {
    +  175  0
                 dependency.getVendorEvidence().addEvidence(e);
    +  176  0
             }
     177   -
             final Evidence springTest1 = new Evidence("Manifest",
    +
     
     178   -
                     "Implementation-Title",
    +
             //<editor-fold defaultstate="collapsed" desc="Old implementation">
     179   -
                     "Spring Framework",
    +
             /*
     180   -
                     Confidence.HIGH);
    +
             final Evidence springTest1 = new Evidence("Manifest",
     181   -
     
    +
                     "Implementation-Title",
     182   -
             final Evidence springTest2 = new Evidence("Manifest",
    +
                     "Spring Framework",
     183   -
                     "Implementation-Title",
    +
                     Confidence.HIGH);
     184   -
                     "org.springframework.core",
    +
     
     185   -
                     Confidence.HIGH);
    +
             final Evidence springTest2 = new Evidence("Manifest",
     186   -
     
    -  187   -
             final Evidence springTest3 = new Evidence("Manifest",
    -  188  
                     "Implementation-Title",
    +  187   +
                     "org.springframework.core",
    +  188   +
                     Confidence.HIGH);
     189   -
                     "spring-core",
    +
     
     190   -
                     Confidence.HIGH);
    +
             final Evidence springTest3 = new Evidence("Manifest",
     191   -
     
    +
                     "Implementation-Title",
     192   -
             final Evidence springTest4 = new Evidence("jar",
    +
                     "spring-core",
     193   -
                     "package name",
    -  194   -
                     "springframework",
    -  195   -
                     Confidence.LOW);
    -  196   -
     
    -  197   -
             final Evidence springSecurityTest1 = new Evidence("Manifest",
    -  198   -
                     "Bundle-Name",
    -  199   -
                     "Spring Security Core",
    -  200   -
                     Confidence.MEDIUM);
    -  201   -
     
    -  202   -
             final Evidence springSecurityTest2 = new Evidence("pom",
    -  203   -
                     "artifactid",
    -  204   -
                     "spring-security-core",
    -  205  
                     Confidence.HIGH);
    +  194   +
     
    +  195   +
             final Evidence springTest4 = new Evidence("jar",
    +  196   +
                     "package name",
    +  197   +
                     "springframework",
    +  198   +
                     Confidence.LOW);
    +  199   +
     
    +  200   +
             final Evidence springSecurityTest1 = new Evidence("Manifest",
    +  201   +
                     "Bundle-Name",
    +  202   +
                     "Spring Security Core",
    +  203   +
                     Confidence.MEDIUM);
    +  204   +
     
    +  205   +
             final Evidence springSecurityTest2 = new Evidence("pom",
     206   -
     
    +
                     "artifactid",
     207   -
             final Evidence symfony = new Evidence("composer.lock",
    +
                     "spring-security-core",
     208   -
                 "vendor",
    +
                     Confidence.HIGH);
     209   -
                 "symfony",
    +
     
     210   -
                 Confidence.HIGHEST);
    +
             final Evidence symfony = new Evidence("composer.lock",
     211   -
     
    -  212   -
             final Evidence zendframeworkVendor = new Evidence("composer.lock",
    -  213  
                 "vendor",
    +  212   +
                 "symfony",
    +  213   +
                 Confidence.HIGHEST);
     214   -
                 "zendframework",
    +
     
     215   -
                 Confidence.HIGHEST);
    +
             final Evidence zendframeworkVendor = new Evidence("composer.lock",
     216   -
     
    +
                 "vendor",
     217   -
             final Evidence zendframeworkProduct = new Evidence("composer.lock",
    -  218   -
                 "product",
    -  219  
                 "zendframework",
    -  220   +  218  
                 Confidence.HIGHEST);
    +  219   +
     
    +  220   +
             final Evidence zendframeworkProduct = new Evidence("composer.lock",
     221   -
     
    +
                 "product",
     222   -
             //springsource/vware problem
    +
                 "zendframework",
     223   -
             final Set<Evidence> product = dependency.getProductEvidence().getEvidence();
    +
                 Confidence.HIGHEST);
     224   -
             final Set<Evidence> vendor = dependency.getVendorEvidence().getEvidence();
    +
     
     225   -
     
    +
             //springsource/vware problem
     226   -
             if (product.contains(springTest1) || product.contains(springTest2) || product.contains(springTest3)
    +
             final Set<Evidence> product = dependency.getProductEvidence().getEvidence();
     227   -
                     || (dependency.getFileName().contains("spring") && product.contains(springTest4))) {
    +
             final Set<Evidence> vendor = dependency.getVendorEvidence().getEvidence();
     228   -
                 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource spring framework", Confidence.HIGH);
    +
     
     229   -
                 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "SpringSource", Confidence.HIGH);
    +
             if (product.contains(springTest1) || product.contains(springTest2) || product.contains(springTest3)
     230   -
                 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH);
    +
                     || (dependency.getFileName().contains("spring") && product.contains(springTest4))) {
     231   -
                 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "pivotal", Confidence.HIGH);
    +
                 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource spring framework", Confidence.HIGH);
     232   -
             }
    -  233   -
     
    -  234   -
             if (vendor.contains(springTest4)) {
    -  235   -
                 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource_spring_framework", Confidence.HIGH);
    -  236   -
                 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH);
    -  237   -
                 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "pivotal", Confidence.HIGH);
    -  238   -
             }
    -  239   -
     
    -  240   -
             if (product.contains(springSecurityTest1) || product.contains(springSecurityTest2)) {
    -  241   -
                 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource_spring_security", Confidence.HIGH);
    -  242  
                 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "SpringSource", Confidence.HIGH);
    -  243   +  233  
                 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH);
    +  234   +
                 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "pivotal", Confidence.HIGH);
    +  235   +
             }
    +  236   +
     
    +  237   +
             if (vendor.contains(springTest4)) {
    +  238   +
                 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource_spring_framework", Confidence.HIGH);
    +  239   +
                 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH);
    +  240   +
                 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "pivotal", Confidence.HIGH);
    +  241   +
             }
    +  242   +
     
    +  243   +
             if (product.contains(springSecurityTest1) || product.contains(springSecurityTest2)) {
     244   -
             }
    +
                 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource_spring_security", Confidence.HIGH);
     245   -
     
    +
                 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "SpringSource", Confidence.HIGH);
     246   -
             if (vendor.contains(symfony)) {
    +
                 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH);
     247   -
                 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "sensiolabs", Confidence.HIGHEST);
    +
             }
     248   -
             }
    +
     
     249   -
     
    +
             if (vendor.contains(symfony)) {
     250   -
             if (vendor.contains(zendframeworkVendor)) {
    +
                 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "sensiolabs", Confidence.HIGHEST);
     251   -
                 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "zend", Confidence.HIGHEST);
    +
             }
     252   -
             }
    +
     
     253   -
     
    +
             if (vendor.contains(zendframeworkVendor)) {
     254   -
             if (product.contains(zendframeworkProduct)) {
    +
                 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "zend", Confidence.HIGHEST);
     255   -
                 dependency.getProductEvidence().addEvidence("hint analyzer", "vendor", "zend_framework", Confidence.HIGHEST);
    -  256  
             }
    -  257   +  256  
     
    +  257   +
             if (product.contains(zendframeworkProduct)) {
     258   -
             //sun/oracle problem
    +
                 dependency.getProductEvidence().addEvidence("hint analyzer", "vendor", "zend_framework", Confidence.HIGHEST);
     259   -
             final Iterator<Evidence> itr = dependency.getVendorEvidence().iterator();
    +
             }
     260   -
             final List<Evidence> newEntries = new ArrayList<Evidence>();
    +
     
     261   -
             while (itr.hasNext()) {
    +
             //sun/oracle problem
     262   -
                 final Evidence e = itr.next();
    +
             final Iterator<Evidence> itr = dependency.getVendorEvidence().iterator();
     263   -
                 if ("sun".equalsIgnoreCase(e.getValue(false))) {
    +
             final List<Evidence> newEntries = new ArrayList<Evidence>();
     264   -
                     final Evidence newEvidence = new Evidence(e.getSource() + " (hint)", e.getName(), "oracle", e.getConfidence());
    +
             while (itr.hasNext()) {
     265   -
                     newEntries.add(newEvidence);
    +
                 final Evidence e = itr.next();
     266   -
                 } else if ("oracle".equalsIgnoreCase(e.getValue(false))) {
    +
                 if ("sun".equalsIgnoreCase(e.getValue(false))) {
     267   -
                     final Evidence newEvidence = new Evidence(e.getSource() + " (hint)", e.getName(), "sun", e.getConfidence());
    +
                     final Evidence newEvidence = new Evidence(e.getSource() + " (hint)", e.getName(), "oracle", e.getConfidence());
     268  
                     newEntries.add(newEvidence);
     269   -
                 }
    +
                 } else if ("oracle".equalsIgnoreCase(e.getValue(false))) {
     270   -
             }
    +
                     final Evidence newEvidence = new Evidence(e.getSource() + " (hint)", e.getName(), "sun", e.getConfidence());
     271   -
             for (Evidence e : newEntries) {
    +
                     newEntries.add(newEvidence);
     272   -
                 dependency.getVendorEvidence().addEvidence(e);
    +
                 }
     273  
             }
     274   -
              */
    +
             for (Evidence e : newEntries) {
     275   -
             //</editor-fold>
    -  276  4
         }
    +
                 dependency.getVendorEvidence().addEvidence(e);
    +  276   +
             }
     277   -
     
    +
              */
     278   -
         /**
    -  279   -
          * Loads the hint rules file.
    +
             //</editor-fold>
    +  279  4
         }
     280   -
          *
    +
     
     281   -
          * @throws HintParseException thrown if the XML cannot be parsed.
    +
         /**
     282   -
          */
    +
          * Loads the hint rules file.
     283   -
         private void loadHintRules() throws HintParseException {
    -  284  2
             final HintParser parser = new HintParser();
    -  285  2
             File file = null;
    +
          *
    +  284   +
          * @throws HintParseException thrown if the XML cannot be parsed.
    +  285   +
          */
     286   +
         private void loadHintRules() throws HintParseException {
    +  287  2
             final HintParser parser = new HintParser();
    +  288  2
             File file = null;
    +  289  
             try {
    -  287  2
                 hints = parser.parseHints(this.getClass().getClassLoader().getResourceAsStream(HINT_RULE_FILE_NAME));
    -  288  0
             } catch (HintParseException ex) {
    -  289  0
                 LOGGER.error("Unable to parse the base hint data file");
    -  290  0
                 LOGGER.debug("Unable to parse the base hint data file", ex);
    -  291  0
             } catch (SAXException ex) {
    +  290  2
                 hints = parser.parseHints(this.getClass().getClassLoader().getResourceAsStream(HINT_RULE_FILE_NAME));
    +  291  0
             } catch (HintParseException ex) {
     292  0
                 LOGGER.error("Unable to parse the base hint data file");
     293  0
                 LOGGER.debug("Unable to parse the base hint data file", ex);
    -  294  2
             }
    -  295  2
             final String filePath = Settings.getString(Settings.KEYS.HINTS_FILE);
    -  296  2
             if (filePath == null) {
    -  297  2
                 return;
    -  298   +  294  0
             } catch (SAXException ex) {
    +  295  0
                 LOGGER.error("Unable to parse the base hint data file");
    +  296  0
                 LOGGER.debug("Unable to parse the base hint data file", ex);
    +  297  2
             }
    +  298  2
             final String filePath = Settings.getString(Settings.KEYS.HINTS_FILE);
    +  299  2
             if (filePath == null) {
    +  300  2
                 return;
    +  301  
             }
    -  299  0
             boolean deleteTempFile = false;
    -  300   +  302  0
             boolean deleteTempFile = false;
    +  303  
             try {
    -  301  0
                 final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE);
    -  302  0
                 if (uriRx.matcher(filePath).matches()) {
    -  303  0
                     deleteTempFile = true;
    -  304  0
                     file = FileUtils.getTempFile("hint", "xml");
    -  305  0
                     final URL url = new URL(filePath);
    -  306   +  304  0
                 final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE);
    +  305  0
                 if (uriRx.matcher(filePath).matches()) {
    +  306  0
                     deleteTempFile = true;
    +  307  0
                     file = FileUtils.getTempFile("hint", "xml");
    +  308  0
                     final URL url = new URL(filePath);
    +  309  
                     try {
    -  307  0
                         Downloader.fetchFile(url, file, false);
    -  308  0
                     } catch (DownloadFailedException ex) {
    -  309  0
                         Downloader.fetchFile(url, file, true);
    -  310  0
                     }
    -  311  0
                 } else {
    -  312  0
                     file = new File(filePath);
    -  313  0
                     if (!file.exists()) {
    -  314  0
                         final InputStream fromClasspath = this.getClass().getClassLoader().getResourceAsStream(filePath);
    -  315  0
                         if (fromClasspath != null) {
    -  316  0
                             deleteTempFile = true;
    -  317  0
                             file = FileUtils.getTempFile("hint", "xml");
    +  310  0
                         Downloader.fetchFile(url, file, false);
    +  311  0
                     } catch (DownloadFailedException ex) {
    +  312  0
                         Downloader.fetchFile(url, file, true);
    +  313  0
                     }
    +  314  0
                 } else {
    +  315  0
                     file = new File(filePath);
    +  316  0
                     if (!file.exists()) {
    +  317  0
                         InputStream fromClasspath = null;
     318   -
                             try {
    -  319  0
                                 org.apache.commons.io.FileUtils.copyInputStreamToFile(fromClasspath, file);
    -  320  0
                             } catch (IOException ex) {
    -  321  0
                                 throw new HintParseException("Unable to locate suppressions file in classpath", ex);
    -  322  0
                             }
    +
                         try {
    +  319  0
                             fromClasspath = this.getClass().getClassLoader().getResourceAsStream(filePath);
    +  320  0
                             if (fromClasspath != null) {
    +  321  0
                                 deleteTempFile = true;
    +  322  0
                                 file = FileUtils.getTempFile("hint", "xml");
     323   -
                         }
    -  324   -
                     }
    -  325   -
                 }
    -  326   -
     
    -  327  0
                 if (file != null) {
    +
                                 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);
    +  327  0
                                 }
     328   -
                     try {
    -  329  0
                         final Hints newHints = parser.parseHints(file);
    -  330  0
                         hints.getHintRules().addAll(newHints.getHintRules());
    -  331  0
                         hints.getVendorDuplicatingHintRules().addAll(newHints.getVendorDuplicatingHintRules());
    -  332  0
                         LOGGER.debug("{} hint rules were loaded.", hints.getHintRules().size());
    -  333  0
                         LOGGER.debug("{} duplicating hint rules were loaded.", hints.getVendorDuplicatingHintRules().size());
    -  334  0
                     } catch (HintParseException ex) {
    -  335  0
                         LOGGER.warn("Unable to parse hint rule xml file '{}'", file.getPath());
    -  336  0
                         LOGGER.warn(ex.getMessage());
    -  337  0
                         LOGGER.debug("", ex);
    -  338  0
                         throw ex;
    -  339  0
                     }
    -  340   +
                             }
    +  329   +
                         } finally {
    +  330  0
                             if (fromClasspath != null) {
    +  331  0
                                 fromClasspath.close();
    +  332   +
                             }
    +  333   +
                         }
    +  334   +
                     }
    +  335  
                 }
    -  341  0
             } catch (DownloadFailedException ex) {
    -  342  0
                 throw new HintParseException("Unable to fetch the configured hint file", ex);
    -  343  0
             } catch (MalformedURLException ex) {
    -  344  0
                 throw new HintParseException("Configured hint file has an invalid URL", ex);
    -  345  0
             } catch (IOException ex) {
    -  346  0
                 throw new HintParseException("Unable to create temp file for hints", ex);
    -  347   -
             } finally {
    -  348  0
                 if (deleteTempFile && file != null) {
    -  349  0
                     FileUtils.delete(file);
    +  336   +
     
    +  337  0
                 if (file != null) {
    +  338   +
                     try {
    +  339  0
                         final Hints newHints = parser.parseHints(file);
    +  340  0
                         hints.getHintRules().addAll(newHints.getHintRules());
    +  341  0
                         hints.getVendorDuplicatingHintRules().addAll(newHints.getVendorDuplicatingHintRules());
    +  342  0
                         LOGGER.debug("{} hint rules were loaded.", hints.getHintRules().size());
    +  343  0
                         LOGGER.debug("{} duplicating hint rules were loaded.", hints.getVendorDuplicatingHintRules().size());
    +  344  0
                     } catch (HintParseException ex) {
    +  345  0
                         LOGGER.warn("Unable to parse hint rule xml file '{}'", file.getPath());
    +  346  0
                         LOGGER.warn(ex.getMessage());
    +  347  0
                         LOGGER.debug("", ex);
    +  348  0
                         throw ex;
    +  349  0
                     }
     350  
                 }
    -  351   +  351  0
             } catch (DownloadFailedException ex) {
    +  352  0
                 throw new HintParseException("Unable to fetch the configured hint file", ex);
    +  353  0
             } catch (MalformedURLException ex) {
    +  354  0
                 throw new HintParseException("Configured hint file has an invalid URL", ex);
    +  355  0
             } catch (IOException ex) {
    +  356  0
                 throw new HintParseException("Unable to create temp file for hints", ex);
    +  357   +
             } finally {
    +  358  0
                 if (deleteTempFile && file != null) {
    +  359  0
                     FileUtils.delete(file);
    +  360   +
                 }
    +  361  
             }
    -  352  0
         }
    -  353   +  362  0
         }
    +  363  
     }
    - + 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 5dc2c68f1..b40544064 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%
    350/528
    56%
    195/346
    7.419
    JarAnalyzer$ClassNameInformation
    80%
    17/21
    80%
    8/10
    7.419
    JarAnalyzer
    66%
    351/531
    55%
    198/354
    7.581
    JarAnalyzer$ClassNameInformation
    80%
    17/21
    80%
    8/10
    7.581
     
    @@ -373,7 +373,7 @@
         @Override
     184  
         protected FileFilter getFileFilter() {
    -  185  12
             return FILTER;
    +  185  861
             return FILTER;
     186  
         }
     187   @@ -593,564 +593,561 @@  326  0
                             pom = PomUtils.readPom(externalPom);
     327  
                         }
    -  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  
                     }
    -  331  0
                 } catch (AnalysisException ex) {
    -  332  0
                     LOGGER.warn("An error occurred while analyzing '{}'.", dependency.getActualFilePath());
    -  333  0
                     LOGGER.trace("", ex);
    -  334  2
                 }
    -  335  2
             }
    -  336  2
             return foundSomething;
    -  337   -
         }
    -  338   -
     
    +  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;
     339   -
         /**
    +
         }
     340   -
          * Given a path to a pom.xml within a JarFile, this method attempts to load
    +
     
     341   -
          * a sibling pom.properties if one exists.
    +
         /**
     342   -
          *
    +
          * Given a path to a pom.xml within a JarFile, this method attempts to load
     343   -
          * @param path the path to the pom.xml within the JarFile
    +
          * a sibling pom.properties if one exists.
     344   -
          * @param jar the JarFile to load the pom.properties from
    +
          *
     345   -
          * @return a Properties object or null if no pom.properties was found
    +
          * @param path the path to the pom.xml within the JarFile
     346   -
          * @throws IOException thrown if there is an exception reading the
    +
          * @param jar the JarFile to load the pom.properties from
     347   -
          * pom.properties
    +
          * @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 {
    -  350  2
             Properties pomProperties = null;
    -  351  2
             final String propPath = path.substring(0, path.length() - 7) + "pom.properies";
    -  352  2
             final ZipEntry propEntry = jar.getEntry(propPath);
    -  353  2
             if (propEntry != null) {
    -  354  0
                 Reader reader = null;
    -  355   +  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  
                 try {
    -  356  0
                     reader = new InputStreamReader(jar.getInputStream(propEntry), "UTF-8");
    -  357  0
                     pomProperties = new Properties();
    -  358  0
                     pomProperties.load(reader);
    -  359  0
                     LOGGER.debug("Read pom.properties: {}", propPath);
    -  360   -
                 } finally {
    -  361  0
                     if (reader != null) {
    +  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   +
                 } finally {
    +  363  0
                     if (reader != null) {
    +  364  
                         try {
    -  363  0
                             reader.close();
    -  364  0
                         } catch (IOException ex) {
    -  365  0
                             LOGGER.trace("close error", ex);
    -  366  0
                         }
    -  367   -
                     }
    -  368   -
                 }
    +  365  0
                             reader.close();
    +  366  0
                         } catch (IOException ex) {
    +  367  0
                             LOGGER.trace("close error", ex);
    +  368  0
                         }
     369   -
             }
    -  370  2
             return pomProperties;
    -  371   -
         }
    -  372   -
     
    -  373   -
         /**
    -  374   -
          * Searches a JarFile for pom.xml entries and returns a listing of these
    -  375   -
          * entries.
    -  376   -
          *
    -  377   -
          * @param jar the JarFile to search
    -  378   -
          * @return a list of pom.xml entries
    -  379   -
          * @throws IOException thrown if there is an exception reading a JarEntry
    -  380   -
          */
    -  381   -
         private List<String> retrievePomListing(final JarFile jar) throws IOException {
    -  382  6
             final List<String> pomEntries = new ArrayList<String>();
    -  383  6
             final Enumeration<JarEntry> entries = jar.entries();
    -  384  1852
             while (entries.hasMoreElements()) {
    -  385  1846
                 final JarEntry entry = entries.nextElement();
    -  386  1846
                 final String entryName = (new File(entry.getName())).getName().toLowerCase();
    -  387  1846
                 if (!entry.isDirectory() && "pom.xml".equals(entryName)) {
    -  388  2
                     LOGGER.trace("POM Entry found: {}", entry.getName());
    -  389  2
                     pomEntries.add(entry.getName());
    -  390   +
                     }
    +  370  
                 }
    -  391  1846
             }
    -  392  6
             return pomEntries;
    -  393   +  371   +
             }
    +  372  2
             return pomProperties;
    +  373  
         }
    -  394   +  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  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   +
                 }
    +  393  1846
             }
    +  394  6
             return pomEntries;
     395   -
         /**
    -  396   -
          * Retrieves the specified POM from a jar file and converts it to a Model.
    -  397   -
          *
    -  398   -
          * @param path the path to the pom.xml file within the jar file
    -  399   -
          * @param jar the jar file to extract the pom from
    -  400   -
          * @param dependency the dependency being analyzed
    -  401   -
          * @return returns the POM object
    -  402   -
          * @throws AnalysisException is thrown if there is an exception extracting
    -  403   -
          * or parsing the POM {@link org.owasp.dependencycheck.xml.pom.Model} object
    -  404   -
          */
    -  405   -
         private Model extractPom(String path, JarFile jar, Dependency dependency) throws AnalysisException {
    -  406  0
             InputStream input = null;
    -  407  0
             FileOutputStream fos = null;
    -  408  0
             final File tmpDir = getNextTempDirectory();
    -  409  0
             final File file = new File(tmpDir, "pom.xml");
    -  410   -
             try {
    -  411  0
                 final ZipEntry entry = jar.getEntry(path);
    -  412  0
                 input = jar.getInputStream(entry);
    -  413  0
                 fos = new FileOutputStream(file);
    -  414  0
                 IOUtils.copy(input, fos);
    -  415  0
                 dependency.setActualFilePath(file.getAbsolutePath());
    -  416  0
             } catch (IOException ex) {
    -  417  0
                 LOGGER.warn("An error occurred reading '{}' from '{}'.", path, dependency.getFilePath());
    -  418  0
                 LOGGER.error("", ex);
    -  419   -
             } finally {
    -  420  0
                 closeStream(fos);
    -  421  0
                 closeStream(input);
    -  422  0
             }
    -  423  0
             return PomUtils.readPom(file);
    -  424  
         }
    -  425   +  396  
     
    -  426   +  397  
         /**
    -  427   -
          * Silently closes an input stream ignoring errors.
    -  428   +  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  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   +
             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   +
                 }
    +  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   +
             } finally {
    +  425  0
                 closeStream(fos);
    +  426  0
                 closeStream(input);
    +  427  0
             }
    +  428  0
             return PomUtils.readPom(file);
     429   -
          * @param stream an input stream to close
    +
         }
     430   -
          */
    +
     
     431   -
         private void closeStream(InputStream stream) {
    -  432  0
             if (stream != null) {
    +
         /**
    +  432   +
          * Silently closes an input stream ignoring errors.
     433   -
                 try {
    -  434  0
                     stream.close();
    -  435  0
                 } catch (IOException ex) {
    -  436  0
                     LOGGER.trace("", ex);
    -  437  0
                 }
    +
          *
    +  434   +
          * @param stream an input stream to close
    +  435   +
          */
    +  436   +
         private void closeStream(InputStream stream) {
    +  437  0
             if (stream != null) {
     438   -
             }
    -  439  0
         }
    -  440   -
     
    -  441   -
         /**
    -  442   -
          * Silently closes an output stream ignoring errors.
    -  443   -
          *
    -  444   -
          * @param stream an output stream to close
    -  445   -
          */
    -  446   -
         private void closeStream(OutputStream stream) {
    -  447  0
             if (stream != null) {
    -  448  
                 try {
    -  449  0
                     stream.close();
    -  450  0
                 } catch (IOException ex) {
    -  451  0
                     LOGGER.trace("", ex);
    -  452  0
                 }
    -  453   +  439  0
                     stream.close();
    +  440  0
                 } catch (IOException ex) {
    +  441  0
                     LOGGER.trace("", ex);
    +  442  0
                 }
    +  443  
             }
    -  454  0
         }
    -  455   +  444  0
         }
    +  445  
     
    -  456   +  446  
         /**
    -  457   -
          * Sets evidence from the pom on the supplied dependency.
    -  458   +  447   +
          * Silently closes an output stream ignoring errors.
    +  448  
          *
    -  459   -
          * @param dependency the dependency to set data on
    -  460   -
          * @param pom the information from the pom
    -  461   -
          * @param classes a collection of ClassNameInformation - containing data
    -  462   -
          * about the fully qualified class names within the JAR file being analyzed
    -  463   -
          * @return true if there was evidence within the pom that we could use;
    -  464   -
          * otherwise false
    -  465   +  449   +
          * @param stream an output stream to close
    +  450  
          */
    +  451   +
         private void closeStream(OutputStream stream) {
    +  452  0
             if (stream != null) {
    +  453   +
                 try {
    +  454  0
                     stream.close();
    +  455  0
                 } catch (IOException ex) {
    +  456  0
                     LOGGER.trace("", ex);
    +  457  0
                 }
    +  458   +
             }
    +  459  0
         }
    +  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   -
         public static boolean setPomEvidence(Dependency dependency, Model pom, List<ClassNameInformation> classes) {
    -  467  2
             boolean foundSomething = false;
    -  468  2
             boolean addAsIdentifier = true;
    -  469  2
             if (pom == null) {
    -  470  0
                 return foundSomething;
    +
          * @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  2
             boolean foundSomething = false;
    +  473  2
             boolean addAsIdentifier = true;
    +  474  2
             if (pom == null) {
    +  475  0
                 return foundSomething;
    +  476  
             }
    -  472  2
             String groupid = pom.getGroupId();
    -  473  2
             String parentGroupId = pom.getParentGroupId();
    -  474  2
             String artifactid = pom.getArtifactId();
    -  475  2
             String parentArtifactId = pom.getParentArtifactId();
    -  476  2
             String version = pom.getVersion();
    -  477  2
             String parentVersion = pom.getParentVersion();
    -  478   -
     
    -  479  2
             if ("org.sonatype.oss".equals(parentGroupId) && "oss-parent".equals(parentArtifactId)) {
    -  480  0
                 parentGroupId = null;
    -  481  0
                 parentArtifactId = null;
    -  482  0
                 parentVersion = null;
    +  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   -
             }
    -  484  
     
    -  485  2
             if ((groupid == null || groupid.isEmpty()) && parentGroupId != null && !parentGroupId.isEmpty()) {
    -  486  0
                 groupid = parentGroupId;
    -  487   -
             }
    +  484  2
             if ("org.sonatype.oss".equals(parentGroupId) && "oss-parent".equals(parentArtifactId)) {
    +  485  0
                 parentGroupId = null;
    +  486  0
                 parentArtifactId = null;
    +  487  0
                 parentVersion = null;
     488   +
             }
    +  489  
     
    -  489  2
             final String originalGroupID = groupid;
    -  490  2
             if (groupid.startsWith("org.") || groupid.startsWith("com.")) {
    -  491  1
                 groupid = groupid.substring(4);
    +  490  2
             if ((groupid == null || groupid.isEmpty()) && parentGroupId != null && !parentGroupId.isEmpty()) {
    +  491  0
                 groupid = parentGroupId;
     492  
             }
     493  
     
    -  494  2
             if ((artifactid == null || artifactid.isEmpty()) && parentArtifactId != null && !parentArtifactId.isEmpty()) {
    -  495  0
                 artifactid = parentArtifactId;
    -  496   -
             }
    +  494  2
             final String originalGroupID = groupid;
    +  495  2
             if (groupid != null && (groupid.startsWith("org.") || groupid.startsWith("com."))) {
    +  496  1
                 groupid = groupid.substring(4);
     497   +
             }
    +  498  
     
    -  498  2
             final String originalArtifactID = artifactid;
    -  499  2
             if (artifactid.startsWith("org.") || artifactid.startsWith("com.")) {
    -  500  0
                 artifactid = artifactid.substring(4);
    +  499  2
             if ((artifactid == null || artifactid.isEmpty()) && parentArtifactId != null && !parentArtifactId.isEmpty()) {
    +  500  0
                 artifactid = parentArtifactId;
     501  
             }
     502  
     
    -  503  2
             if ((version == null || version.isEmpty()) && parentVersion != null && !parentVersion.isEmpty()) {
    -  504  1
                 version = parentVersion;
    -  505   -
             }
    +  503  2
             final String originalArtifactID = artifactid;
    +  504  2
             if (artifactid != null && (artifactid.startsWith("org.") || artifactid.startsWith("com."))) {
    +  505  0
                 artifactid = artifactid.substring(4);
     506   +
             }
    +  507  
     
    -  507  2
             if (groupid != null && !groupid.isEmpty()) {
    -  508  2
                 foundSomething = true;
    -  509  2
                 dependency.getVendorEvidence().addEvidence("pom", "groupid", groupid, Confidence.HIGHEST);
    -  510  2
                 dependency.getProductEvidence().addEvidence("pom", "groupid", groupid, Confidence.LOW);
    -  511  2
                 addMatchingValues(classes, groupid, dependency.getVendorEvidence());
    -  512  2
                 addMatchingValues(classes, groupid, dependency.getProductEvidence());
    -  513  2
                 if (parentGroupId != null && !parentGroupId.isEmpty() && !parentGroupId.equals(groupid)) {
    -  514  1
                     dependency.getVendorEvidence().addEvidence("pom", "parent-groupid", parentGroupId, Confidence.MEDIUM);
    -  515  1
                     dependency.getProductEvidence().addEvidence("pom", "parent-groupid", parentGroupId, Confidence.LOW);
    -  516  1
                     addMatchingValues(classes, parentGroupId, dependency.getVendorEvidence());
    -  517  1
                     addMatchingValues(classes, parentGroupId, dependency.getProductEvidence());
    -  518   +  508  2
             if ((version == null || version.isEmpty()) && parentVersion != null && !parentVersion.isEmpty()) {
    +  509  1
                 version = parentVersion;
    +  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());
    +  523  
                 }
    -  519   +  524  
             } else {
    -  520  0
                 addAsIdentifier = false;
    -  521   +  525  0
                 addAsIdentifier = false;
    +  526  
             }
    -  522   +  527  
     
    -  523  2
             if (artifactid != null && !artifactid.isEmpty()) {
    -  524  2
                 foundSomething = true;
    -  525  2
                 dependency.getProductEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.HIGHEST);
    -  526  2
                 dependency.getVendorEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.LOW);
    -  527  2
                 addMatchingValues(classes, artifactid, dependency.getVendorEvidence());
    -  528  2
                 addMatchingValues(classes, artifactid, dependency.getProductEvidence());
    -  529  2
                 if (parentArtifactId != null && !parentArtifactId.isEmpty() && !parentArtifactId.equals(artifactid)) {
    -  530  1
                     dependency.getProductEvidence().addEvidence("pom", "parent-artifactid", parentArtifactId, Confidence.MEDIUM);
    -  531  1
                     dependency.getVendorEvidence().addEvidence("pom", "parent-artifactid", parentArtifactId, Confidence.LOW);
    -  532  1
                     addMatchingValues(classes, parentArtifactId, dependency.getVendorEvidence());
    -  533  1
                     addMatchingValues(classes, parentArtifactId, dependency.getProductEvidence());
    -  534   +  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());
    +  539  
                 }
    -  535   +  540  
             } else {
    -  536  0
                 addAsIdentifier = false;
    -  537   +  541  0
                 addAsIdentifier = false;
    +  542  
             }
    -  538   +  543  
     
    -  539  2
             if (version != null && !version.isEmpty()) {
    -  540  2
                 foundSomething = true;
    -  541  2
                 dependency.getVersionEvidence().addEvidence("pom", "version", version, Confidence.HIGHEST);
    -  542  2
                 if (parentVersion != null && !parentVersion.isEmpty() && !parentVersion.equals(version)) {
    -  543  0
                     dependency.getVersionEvidence().addEvidence("pom", "parent-version", version, Confidence.LOW);
    -  544   +  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);
    +  549  
                 }
    -  545   +  550  
             } else {
    -  546  0
                 addAsIdentifier = false;
    -  547   -
             }
    -  548   -
     
    -  549  2
             if (addAsIdentifier) {
    -  550  2
                 dependency.addIdentifier("maven", String.format("%s:%s:%s", originalGroupID, originalArtifactID, version), null, Confidence.HIGH);
    -  551   -
             }
    +  551  0
                 addAsIdentifier = false;
     552   -
     
    +
             }
     553   +
     
    +  554  2
             if (addAsIdentifier) {
    +  555  2
                 dependency.addIdentifier("maven", String.format("%s:%s:%s", originalGroupID, originalArtifactID, version), null, Confidence.HIGH);
    +  556   +
             }
    +  557   +
     
    +  558  
             // org name
    -  554  2
             final String org = pom.getOrganization();
    -  555  2
             if (org != null && !org.isEmpty()) {
    -  556  0
                 dependency.getVendorEvidence().addEvidence("pom", "organization name", org, Confidence.HIGH);
    -  557  0
                 dependency.getProductEvidence().addEvidence("pom", "organization name", org, Confidence.LOW);
    -  558  0
                 addMatchingValues(classes, org, dependency.getVendorEvidence());
    -  559  0
                 addMatchingValues(classes, org, dependency.getProductEvidence());
    -  560   +  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());
    +  565  
             }
    -  561   +  566  
             //pom name
    -  562  2
             final String pomName = pom.getName();
    -  563  2
             if (pomName
    -  564  2
                     != null && !pomName.isEmpty()) {
    -  565  2
                 foundSomething = true;
    -  566  2
                 dependency.getProductEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH);
    -  567  2
                 dependency.getVendorEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH);
    -  568  2
                 addMatchingValues(classes, pomName, dependency.getVendorEvidence());
    -  569  2
                 addMatchingValues(classes, pomName, dependency.getProductEvidence());
    -  570   +  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());
    +  575  
             }
    -  571   +  576  
     
    -  572   +  577  
             //Description
    -  573  2
             final String description = pom.getDescription();
    -  574  2
             if (description != null && !description.isEmpty() && !description.startsWith("POM was created by")) {
    -  575  1
                 foundSomething = true;
    -  576  1
                 final String trimmedDescription = addDescription(dependency, description, "pom", "description");
    -  577  1
                 addMatchingValues(classes, trimmedDescription, dependency.getVendorEvidence());
    -  578  1
                 addMatchingValues(classes, trimmedDescription, dependency.getProductEvidence());
    -  579   -
             }
    -  580   -
     
    -  581  2
             final String projectURL = pom.getProjectURL();
    -  582  2
             if (projectURL != null && !projectURL.trim().isEmpty()) {
    -  583  1
                 dependency.getVendorEvidence().addEvidence("pom", "url", projectURL, Confidence.HIGHEST);
    +  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());
     584  
             }
     585  
     
    -  586  2
             extractLicense(pom, dependency);
    -  587  2
             return foundSomething;
    -  588   -
         }
    +  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);
     589   -
     
    +
             }
     590   -
         /**
    -  591   -
          * Analyzes the path information of the classes contained within the
    -  592   -
          * JarAnalyzer to try and determine possible vendor or product names. If any
    +
     
    +  591  2
             extractLicense(pom, dependency);
    +  592  2
             return foundSomething;
     593   -
          * are found they are stored in the packageVendor and packageProduct
    +
         }
     594   -
          * hashSets.
    +
     
     595   -
          *
    -  596   -
          * @param classNames a list of class names
    -  597   -
          * @param dependency a dependency to analyze
    -  598   -
          * @param addPackagesAsEvidence a flag indicating whether or not package
    -  599   -
          * names should be added as evidence.
    -  600   -
          */
    -  601   -
         protected void analyzePackageNames(List<ClassNameInformation> classNames,
    -  602   -
                 Dependency dependency, boolean addPackagesAsEvidence) {
    -  603  6
             final Map<String, Integer> vendorIdentifiers = new HashMap<String, Integer>();
    -  604  6
             final Map<String, Integer> productIdentifiers = new HashMap<String, Integer>();
    -  605  6
             analyzeFullyQualifiedClassNames(classNames, vendorIdentifiers, productIdentifiers);
    -  606   -
     
    -  607  6
             final int classCount = classNames.size();
    -  608  6
             final EvidenceCollection vendor = dependency.getVendorEvidence();
    -  609  6
             final EvidenceCollection product = dependency.getProductEvidence();
    -  610   -
     
    -  611  6
             for (Map.Entry<String, Integer> entry : vendorIdentifiers.entrySet()) {
    -  612  48
                 final float ratio = entry.getValue() / (float) classCount;
    -  613  48
                 if (ratio > 0.5) {
    -  614   -
                     //TODO remove weighting
    -  615  10
                     vendor.addWeighting(entry.getKey());
    -  616  10
                     if (addPackagesAsEvidence && entry.getKey().length() > 1) {
    -  617  8
                         vendor.addEvidence("jar", "package name", entry.getKey(), Confidence.LOW);
    -  618   -
                     }
    -  619   -
                 }
    -  620  48
             }
    -  621  6
             for (Map.Entry<String, Integer> entry : productIdentifiers.entrySet()) {
    -  622  985
                 final float ratio = entry.getValue() / (float) classCount;
    -  623  985
                 if (ratio > 0.5) {
    -  624  5
                     product.addWeighting(entry.getKey());
    -  625  5
                     if (addPackagesAsEvidence && entry.getKey().length() > 1) {
    -  626  4
                         product.addEvidence("jar", "package name", entry.getKey(), Confidence.LOW);
    -  627   -
                     }
    -  628   -
                 }
    -  629  985
             }
    -  630  6
         }
    -  631   -
     
    -  632  
         /**
    -  633   -
          * <p>
    -  634   -
          * Reads the manifest from the JAR file and collects the entries. Some
    -  635   -
          * vendorKey entries are:</p>
    -  636   -
          * <ul><li>Implementation Title</li>
    -  637   -
          * <li>Implementation Version</li> <li>Implementation Vendor</li>
    -  638   -
          * <li>Implementation VendorId</li> <li>Bundle Name</li> <li>Bundle
    -  639   -
          * Version</li> <li>Bundle Vendor</li> <li>Bundle Description</li> <li>Main
    -  640   -
          * Class</li> </ul>
    -  641   -
          * However, all but a handful of specific entries are read in.
    -  642   +  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  
          *
    -  643   -
          * @param dependency A reference to the dependency
    -  644   -
          * @param classInformation a collection of class information
    -  645   -
          * @return whether evidence was identified parsing the manifest
    -  646   -
          * @throws IOException if there is an issue reading the JAR file
    -  647   +  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  
          */
    -  648   -
         protected boolean parseManifest(Dependency dependency, List<ClassNameInformation> classInformation) throws IOException {
    -  649  7
             boolean foundSomething = false;
    -  650  7
             JarFile jar = null;
    -  651   -
             try {
    -  652  7
                 jar = new JarFile(dependency.getActualFilePath());
    -  653  7
                 final Manifest manifest = jar.getManifest();
    -  654  7
                 if (manifest == null) {
    -  655  0
                     if (!dependency.getFileName().toLowerCase().endsWith("-sources.jar")
    -  656  0
                             && !dependency.getFileName().toLowerCase().endsWith("-javadoc.jar")
    -  657  0
                             && !dependency.getFileName().toLowerCase().endsWith("-src.jar")
    -  658  0
                             && !dependency.getFileName().toLowerCase().endsWith("-doc.jar")) {
    -  659  0
                         LOGGER.debug("Jar file '{}' does not contain a manifest.",
    -  660  0
                                 dependency.getFileName());
    -  661   +  606   +
         protected void analyzePackageNames(List<ClassNameInformation> classNames,
    +  607   +
                 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   +
     
    +  612  6
             final int classCount = classNames.size();
    +  613  6
             final EvidenceCollection vendor = dependency.getVendorEvidence();
    +  614  6
             final EvidenceCollection product = dependency.getProductEvidence();
    +  615   +
     
    +  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   +
                     //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);
    +  623  
                     }
    -  662  0
                     return false;
    -  663   +  624  
                 }
    -  664  7
                 final EvidenceCollection vendorEvidence = dependency.getVendorEvidence();
    -  665  7
                 final EvidenceCollection productEvidence = dependency.getProductEvidence();
    -  666  7
                 final EvidenceCollection versionEvidence = dependency.getVersionEvidence();
    -  667  7
                 String source = "Manifest";
    -  668  7
                 String specificationVersion = null;
    -  669  7
                 boolean hasImplementationVersion = false;
    -  670  7
                 Attributes atts = manifest.getMainAttributes();
    -  671  7
                 for (Entry<Object, Object> entry : atts.entrySet()) {
    -  672  72
                     String key = entry.getKey().toString();
    -  673  72
                     String value = atts.getValue(key);
    -  674  72
                     if (HTML_DETECTION_PATTERN.matcher(value).find()) {
    -  675  0
                         value = Jsoup.parse(value).text();
    -  676   +  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);
    +  632  
                     }
    -  677  72
                     if (IGNORE_VALUES.contains(value)) {
    -  678  0
                         continue;
    -  679  72
                     } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_TITLE.toString())) {
    -  680  1
                         foundSomething = true;
    -  681  1
                         productEvidence.addEvidence(source, key, value, Confidence.HIGH);
    -  682  1
                         addMatchingValues(classInformation, value, productEvidence);
    -  683  71
                     } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VERSION.toString())) {
    -  684  2
                         hasImplementationVersion = true;
    -  685  2
                         foundSomething = true;
    -  686  2
                         versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
    -  687  69
                     } else if ("specification-version".equalsIgnoreCase(key)) {
    -  688  1
                         specificationVersion = key;
    -  689  68
                     } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) {
    -  690  1
                         foundSomething = true;
    -  691  1
                         vendorEvidence.addEvidence(source, key, value, Confidence.HIGH);
    -  692  1
                         addMatchingValues(classInformation, value, vendorEvidence);
    -  693  67
                     } else if (key.equalsIgnoreCase(IMPLEMENTATION_VENDOR_ID)) {
    -  694  0
                         foundSomething = true;
    -  695  0
                         vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
    -  696  0
                         addMatchingValues(classInformation, value, vendorEvidence);
    -  697  67
                     } else if (key.equalsIgnoreCase(BUNDLE_DESCRIPTION)) {
    -  698  2
                         foundSomething = true;
    -  699  2
                         addDescription(dependency, value, "manifest", key);
    -  700  2
                         addMatchingValues(classInformation, value, productEvidence);
    -  701  65
                     } else if (key.equalsIgnoreCase(BUNDLE_NAME)) {
    -  702  3
                         foundSomething = true;
    -  703  3
                         productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
    -  704  3
                         addMatchingValues(classInformation, value, productEvidence);
    -  705   +  633   +
                 }
    +  634  985
             }
    +  635  6
         }
    +  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  7
             boolean foundSomething = false;
    +  655  7
             JarFile jar = null;
    +  656   +
             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   +
                     }
    +  667  0
                     return false;
    +  668   +
                 }
    +  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   +
                     }
    +  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  
     //                //the following caused false positives.
    -  706   +  711  
     //                } else if (key.equalsIgnoreCase(BUNDLE_VENDOR)) {
    -  707   -
     //                    foundSomething = true;
    -  708   -
     //                    vendorEvidence.addEvidence(source, key, value, Confidence.HIGH);
    -  709   -
     //                    addMatchingValues(classInformation, value, vendorEvidence);
    -  710  62
                     } else if (key.equalsIgnoreCase(BUNDLE_VERSION)) {
    -  711  3
                         foundSomething = true;
    -  712  3
                         versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
    -  713  59
                     } else if (key.equalsIgnoreCase(Attributes.Name.MAIN_CLASS.toString())) {
    -  714  3
                         continue;
    -  715   -
                         //skipping main class as if this has important information to add
    -  716   -
                         // it will be added during class name analysis...  if other fields
    +  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   -
                         // have the information from the class name then they will get added...
    +
                         //skipping main class as if this has important information to add it will be added during class name analysis...
     718  
                     } else {
     719  56
                         key = key.toLowerCase();
    @@ -1937,6 +1934,6 @@
     }
    - + 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 ce683db9c..049b29ba1 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
    20%
    14/70
    4%
    1/24
    3.625
    NexusAnalyzer
    19%
    14/71
    3%
    1/26
    3.75
     
    @@ -392,7 +392,7 @@
         @Override
     204  
         protected FileFilter getFileFilter() {
    -  205  10
             return FILTER;
    +  205  859
             return FILTER;
     206  
         }
     207   @@ -452,33 +452,34 @@  246  0
                                 + "this could result in undetected CPE/CVEs.", dependency.getFileName());
     247  
                     } finally {
    -  248  0
                         if (pomFile != null && !FileUtils.deleteQuietly(pomFile)) {
    -  249  0
                             pomFile.deleteOnExit();
    -  250   -
                         }
    +  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   +
                     }
    +  253  
                 }
    -  253  0
             } catch (IllegalArgumentException iae) {
    -  254   +  254  0
             } catch (IllegalArgumentException iae) {
    +  255  
                 //dependency.addAnalysisException(new AnalysisException("Invalid SHA-1"));
    -  255  0
                 LOGGER.info("invalid sha-1 hash on {}", dependency.getFileName());
    -  256  0
             } catch (FileNotFoundException fnfe) {
    -  257   +  256  0
                 LOGGER.info("invalid sha-1 hash on {}", dependency.getFileName());
    +  257  0
             } catch (FileNotFoundException fnfe) {
    +  258  
                 //dependency.addAnalysisException(new AnalysisException("Artifact not found on repository"));
    -  258  0
                 LOGGER.debug("Artifact not found in repository '{}'", dependency.getFileName());
    -  259  0
                 LOGGER.debug(fnfe.getMessage(), fnfe);
    -  260  0
             } catch (IOException ioe) {
    -  261   +  259  0
                 LOGGER.debug("Artifact not found in repository '{}'", dependency.getFileName());
    +  260  0
                 LOGGER.debug(fnfe.getMessage(), fnfe);
    +  261  0
             } catch (IOException ioe) {
    +  262  
                 //dependency.addAnalysisException(new AnalysisException("Could not connect to repository", ioe));
    -  262  0
                 LOGGER.debug("Could not connect to nexus repository", ioe);
    -  263  0
             }
    -  264  0
         }
    -  265   +  263  0
                 LOGGER.debug("Could not connect to nexus repository", ioe);
    +  264  0
             }
    +  265  0
         }
    +  266  
     }
    - + 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 1e7afcc43..0ec6c82fe 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NodePackageAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NodePackageAnalyzer.html @@ -178,7 +178,7 @@
         @Override
     83  
         protected FileFilter getFileFilter() {
    -  84  11
             return PACKAGE_JSON_FILTER;
    +  84  860
             return PACKAGE_JSON_FILTER;
     85  
         }
     86   @@ -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 fa2a77811..c4b5d80db 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NuspecAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NuspecAnalyzer.html @@ -244,7 +244,7 @@
         @Override
     118  
         protected FileFilter getFileFilter() {
    -  119  12
             return FILTER;
    +  119  861
             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 c63b35707..98357ff14 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NvdCveAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NvdCveAnalyzer.html @@ -169,7 +169,7 @@
          */
     80  
         public boolean isOpen() {
    -  81  5
             return cveDB != null;
    +  81  6
             return cveDB != null;
     82  
         }
     83   @@ -188,12 +188,12 @@
         @Override
     90  
         protected void finalize() throws Throwable {
    -  91  5
             super.finalize();
    -  92  5
             if (isOpen()) {
    +  91  6
             super.finalize();
    +  92  6
             if (isOpen()) {
     93  0
                 close();
     94  
             }
    -  95  5
         }
    +  95  6
         }
     96  
     
     97   @@ -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 83538ba5e..126a97005 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.OpenSSLAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.OpenSSLAnalyzer.html @@ -288,7 +288,7 @@
         @Override
     142  
         protected FileFilter getFileFilter() {
    -  143  11
             return OPENSSLV_FILTER;
    +  143  860
             return OPENSSLV_FILTER;
     144  
         }
     145   @@ -412,6 +412,6 @@
     }
    - + 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 02e011e54..74ecc5351 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
    81%
    90/110
    65%
    30/46
    3.462
    PythonDistributionAnalyzer
    80%
    96/119
    61%
    32/52
    3.769
     
    @@ -70,11 +70,11 @@  26  
     import java.io.IOException;
     27   -
     import org.apache.commons.io.filefilter.NameFileFilter;
    +
     import java.io.InputStream;
     28   -
     import org.apache.commons.io.filefilter.SuffixFileFilter;
    +
     import org.apache.commons.io.filefilter.NameFileFilter;
     29   -
     import org.apache.commons.io.input.AutoCloseInputStream;
    +
     import org.apache.commons.io.filefilter.SuffixFileFilter;
     30  
     import org.apache.commons.lang3.StringUtils;
     31   @@ -297,7 +297,7 @@
         @Override
     147  
         protected FileFilter getFileFilter() {
    -  148  15
             return FILTER;
    +  148  864
             return FILTER;
     149  
         }
     150   @@ -435,264 +435,279 @@  229  3
             }
     230  
     
    -  231  6
             collectWheelMetadata(
    -  232   -
                     dependency,
    -  233  3
                     getMatchingFile(getMatchingFile(temp, folderFilter),
    -  234   -
                             metadataFilter));
    -  235  3
         }
    +  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   -
          * Makes sure a usable temporary directory is available.
    +
             }
    +  238  3
         }
     239   -
          *
    +
     
     240   -
          * @throws InitializationException an AnalyzeException is thrown when the
    +
         /**
     241   -
          * temp directory cannot be created
    +
          * Makes sure a usable temporary directory is available.
     242   -
          */
    +
          *
     243   -
         @Override
    +
          * @throws InitializationException an AnalyzeException is thrown when the
     244   -
         protected void initializeFileTypeAnalyzer() throws InitializationException {
    +
          * temp directory cannot be created
     245   -
             try {
    -  246  8
                 final File baseDir = Settings.getTempDirectory();
    -  247  8
                 tempFileLocation = File.createTempFile("check", "tmp", baseDir);
    -  248  8
                 if (!tempFileLocation.delete()) {
    -  249  0
                     setEnabled(false);
    -  250  0
                     final String msg = String.format(
    -  251   -
                             "Unable to delete temporary file '%s'.",
    -  252  0
                             tempFileLocation.getAbsolutePath());
    -  253  0
                     throw new InitializationException(msg);
    -  254   -
                 }
    -  255  8
                 if (!tempFileLocation.mkdirs()) {
    -  256  0
                     setEnabled(false);
    -  257  0
                     final String msg = String.format(
    -  258   -
                             "Unable to create directory '%s'.",
    -  259  0
                             tempFileLocation.getAbsolutePath());
    -  260  0
                     throw new InitializationException(msg);
    -  261   -
                 }
    -  262  0
             } catch (IOException ex) {
    -  263  0
                 setEnabled(false);
    -  264  0
                 throw new InitializationException("Unable to create a temporary file", ex);
    -  265  8
             }
    -  266  8
         }
    -  267   -
     
    -  268   -
         /**
    -  269   -
          * Deletes any files extracted from the Wheel during analysis.
    -  270  
          */
    -  271   +  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() {
    -  273  10
             if (tempFileLocation != null && tempFileLocation.exists()) {
    -  274  8
                 LOGGER.debug("Attempting to delete temporary files");
    -  275  8
                 final boolean success = FileUtils.delete(tempFileLocation);
    -  276  8
                 if (!success) {
    -  277  1
                     LOGGER.warn(
    -  278   +  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");
    -  279   -
                 }
    -  280   -
             }
    -  281  10
         }
     282   -
     
    -  283   -
         /**
    -  284   -
          * Gathers evidence from the METADATA file.
    -  285   -
          *
    -  286   -
          * @param dependency the dependency being analyzed
    -  287   -
          * @param file a reference to the manifest/properties file
    -  288   -
          */
    -  289   -
         private static void collectWheelMetadata(Dependency dependency, File file) {
    -  290  6
             final InternetHeaders headers = getManifestProperties(file);
    -  291  6
             addPropertyToEvidence(headers, dependency.getVersionEvidence(),
    -  292   -
                     "Version", Confidence.HIGHEST);
    -  293  6
             addPropertyToEvidence(headers, dependency.getProductEvidence(), "Name",
    -  294   -
                     Confidence.HIGHEST);
    -  295  6
             final String url = headers.getHeader("Home-page", null);
    -  296  6
             final EvidenceCollection vendorEvidence = dependency
    -  297  6
                     .getVendorEvidence();
    -  298  6
             if (StringUtils.isNotBlank(url)) {
    -  299  6
                 if (UrlStringUtils.isUrl(url)) {
    -  300  6
                     vendorEvidence.addEvidence(METADATA, "vendor", url,
    -  301   -
                             Confidence.MEDIUM);
    -  302  
                 }
    -  303   +  283  
             }
    -  304  6
             addPropertyToEvidence(headers, vendorEvidence, "Author", Confidence.LOW);
    -  305  6
             final String summary = headers.getHeader("Summary", null);
    -  306  6
             if (StringUtils.isNotBlank(summary)) {
    -  307  6
                 JarAnalyzer
    -  308  6
                         .addDescription(dependency, summary, METADATA, "summary");
    -  309   -
             }
    -  310  6
         }
    -  311   +  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   -
          * Adds a value to the evidence collection.
    +
             }
    +  313  6
         }
     314   -
          *
    +
     
     315   -
          * @param headers the properties collection
    +
         /**
     316   -
          * @param evidence the evidence collection to add the value
    +
          * Adds a value to the evidence collection.
     317   -
          * @param property the property name
    +
          *
     318   -
          * @param confidence the confidence of the evidence
    +
          * @param headers the properties collection
     319   -
          */
    +
          * @param evidence the evidence collection to add the value
     320   -
         private static void addPropertyToEvidence(InternetHeaders headers,
    +
          * @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) {
    -  322  18
             final String value = headers.getHeader(property, null);
    -  323  18
             LOGGER.debug("Property: {}, Value: {}", property, value);
    -  324  18
             if (StringUtils.isNotBlank(value)) {
    -  325  18
                 evidence.addEvidence(METADATA, property, value, confidence);
    -  326   -
             }
    -  327  18
         }
    -  328   -
     
    +  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   -
          * Returns a list of files that match the given filter, this does not
    +
             }
    +  330  18
         }
     331   -
          * recursively scan the directory.
    +
     
     332   -
          *
    +
         /**
     333   -
          * @param folder the folder to filter
    +
          * Returns a list of files that match the given filter, this does not
     334   -
          * @param filter the filter to apply to the files in the directory
    +
          * recursively scan the directory.
     335   -
          * @return the list of Files in the directory that match the provided filter
    +
          *
     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) {
    -  338  6
             File result = null;
    -  339  6
             final File[] matches = folder.listFiles(filter);
    -  340  6
             if (null != matches && 1 == matches.length) {
    -  341  6
                 result = matches[0];
    -  342   -
             }
    -  343  6
             return result;
    -  344   -
         }
    +  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   -
         /**
    +
             }
    +  346  6
             return result;
     347   -
          * Reads the manifest entries from the provided file.
    +
         }
     348   -
          *
    +
     
     349   -
          * @param manifest the manifest
    -  350   -
          * @return the manifest entries
    -  351   -
          */
    -  352   -
         private static InternetHeaders getManifestProperties(File manifest) {
    -  353  6
             final InternetHeaders result = new InternetHeaders();
    -  354  6
             if (null == manifest) {
    -  355  0
                 LOGGER.debug("Manifest file not found.");
    -  356   -
             } else {
    -  357   -
                 try {
    -  358  6
                     result.load(new AutoCloseInputStream(new BufferedInputStream(
    -  359   -
                             new FileInputStream(manifest))));
    -  360  0
                 } catch (MessagingException e) {
    -  361  0
                     LOGGER.warn(e.getMessage(), e);
    -  362  0
                 } catch (FileNotFoundException e) {
    -  363  0
                     LOGGER.warn(e.getMessage(), e);
    -  364  6
                 }
    -  365   -
             }
    -  366  6
             return result;
    -  367   -
         }
    -  368   -
     
    -  369  
         /**
    -  370   -
          * Retrieves the next temporary destination directory for extracting an
    -  371   -
          * archive.
    -  372   +  350   +
          * Reads the manifest entries from the provided file.
    +  351  
          *
    -  373   -
          * @return a directory
    -  374   -
          * @throws AnalysisException thrown if unable to create temporary directory
    -  375   +  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   -
         private File getNextTempDirectory() throws AnalysisException {
    +
                 }
     377   -
             File directory;
    -  378   -
     
    -  379   -
             // getting an exception for some directories not being able to be
    -  380   -
             // created; might be because the directory already exists?
    -  381   -
             do {
    -  382  3
                 dirCount += 1;
    -  383  3
                 directory = new File(tempFileLocation, String.valueOf(dirCount));
    -  384  3
             } while (directory.exists());
    -  385  3
             if (!directory.mkdirs()) {
    -  386  0
                 throw new AnalysisException(String.format(
    -  387   -
                         "Unable to create temp directory '%s'.",
    -  388  0
                         directory.getAbsolutePath()));
    -  389  
             }
    -  390  3
             return directory;
    -  391   +  378  6
             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  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   +
             }
    +  402  3
             return directory;
    +  403   +
         }
    +  404  
     }
    - + 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 042991dec..d2619abc2 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.PythonPackageAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.PythonPackageAnalyzer.html @@ -286,7 +286,7 @@
         @Override
     141  
         protected FileFilter getFileFilter() {
    -  142  11
             return FILTER;
    +  142  860
             return FILTER;
     143  
         }
     144   @@ -595,6 +595,6 @@
     }
    - + 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 525e35978..e07591f28 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/217
    2%
    2/74
    5.846
    RubyBundleAuditAnalyzer
    14%
    32/221
    2%
    2/78
    6.154
     
    @@ -68,734 +68,746 @@  25  
     import java.io.UnsupportedEncodingException;
     26   -
     import java.util.ArrayList;
    -  27   -
     import java.util.HashMap;
    -  28   -
     import java.util.List;
    -  29   -
     import java.util.Map;
    -  30  
     import java.nio.charset.Charset;
    +  27   +
     import java.util.ArrayList;
    +  28   +
     import java.util.HashMap;
    +  29   +
     import java.util.List;
    +  30   +
     import java.util.Map;
     31   -
     import org.apache.commons.io.FileUtils;
    +
     
     32   -
     import org.owasp.dependencycheck.Engine;
    +
     import org.apache.commons.io.FileUtils;
     33   -
     import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
    +
     import org.owasp.dependencycheck.Engine;
     34   -
     import org.owasp.dependencycheck.data.nvdcve.CveDB;
    +
     import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
     35   -
     import org.owasp.dependencycheck.dependency.Confidence;
    +
     import org.owasp.dependencycheck.data.nvdcve.CveDB;
     36   -
     import org.owasp.dependencycheck.dependency.Dependency;
    -  37   -
     import org.owasp.dependencycheck.dependency.Reference;
    -  38   -
     import org.owasp.dependencycheck.dependency.Vulnerability;
    -  39   -
     import org.owasp.dependencycheck.utils.FileFilterBuilder;
    -  40   -
     import org.owasp.dependencycheck.utils.Settings;
    -  41   -
     import org.slf4j.Logger;
    -  42   -
     import org.slf4j.LoggerFactory;
    -  43  
     import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
    -  44   +  37   +
     import org.owasp.dependencycheck.dependency.Confidence;
    +  38   +
     import org.owasp.dependencycheck.dependency.Dependency;
    +  39   +
     import org.owasp.dependencycheck.dependency.Reference;
    +  40   +
     import org.owasp.dependencycheck.dependency.Vulnerability;
    +  41  
     import org.owasp.dependencycheck.exception.InitializationException;
    +  42   +
     import org.owasp.dependencycheck.utils.FileFilterBuilder;
    +  43   +
     import org.owasp.dependencycheck.utils.Settings;
    +  44   +
     import org.slf4j.Logger;
     45   -
     
    +
     import org.slf4j.LoggerFactory;
     46   -
     /**
    +
     
     47   -
      * Used to analyze Ruby Bundler Gemspec.lock files utilizing the 3rd party
    +
     /**
     48   -
      * bundle-audit tool.
    +
      * Used to analyze Ruby Bundler Gemspec.lock files utilizing the 3rd party
     49   -
      *
    +
      * bundle-audit tool.
     50   -
      * @author Dale Visser
    +
      *
     51   -
      */
    +
      * @author Dale Visser
     52   +
      */
    +  53  
     @Experimental
    -  53  12
     public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
    -  54   -
     
    +  54  12
     public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
     55   -
         /**
    +
     
     56   -
          * The logger.
    +
         /**
     57   +
          * The logger.
    +  58  
          */
    -  58  1
         private static final Logger LOGGER = LoggerFactory.getLogger(RubyBundleAuditAnalyzer.class);
    -  59   -
     
    +  59  1
         private static final Logger LOGGER = LoggerFactory.getLogger(RubyBundleAuditAnalyzer.class);
     60   -
         /**
    +
     
     61   -
          * The name of the analyzer.
    +
         /**
     62   -
          */
    +
          * The name of the analyzer.
     63   -
         private static final String ANALYZER_NAME = "Ruby Bundle Audit Analyzer";
    +
          */
     64   -
     
    +
         private static final String ANALYZER_NAME = "Ruby Bundle Audit Analyzer";
     65   -
         /**
    +
     
     66   -
          * The phase that this analyzer is intended to run in.
    +
         /**
     67   +
          * The phase that this analyzer is intended to run in.
    +  68  
          */
    -  68  1
         private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.PRE_INFORMATION_COLLECTION;
    -  69   -
         /**
    +  69  1
         private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.PRE_INFORMATION_COLLECTION;
     70   -
          * The filter defining which files will be analyzed.
    +
         /**
     71   +
          * The filter defining which files will be analyzed.
    +  72  
          */
    -  72  1
         private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFilenames("Gemfile.lock").build();
    -  73   -
         /**
    +  73  1
         private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFilenames("Gemfile.lock").build();
     74   -
          * Name.
    +
         /**
     75   -
          */
    +
          * Name.
     76   -
         public static final String NAME = "Name: ";
    +
          */
     77   -
         /**
    +
         public static final String NAME = "Name: ";
     78   -
          * Version.
    +
         /**
     79   -
          */
    +
          * Version.
     80   -
         public static final String VERSION = "Version: ";
    +
          */
     81   -
         /**
    +
         public static final String VERSION = "Version: ";
     82   -
          * Advisory.
    +
         /**
     83   -
          */
    +
          * Advisory.
     84   -
         public static final String ADVISORY = "Advisory: ";
    +
          */
     85   -
         /**
    +
         public static final String ADVISORY = "Advisory: ";
     86   -
          * Criticality.
    +
         /**
     87   -
          */
    +
          * Criticality.
     88   -
         public static final String CRITICALITY = "Criticality: ";
    +
          */
     89   -
     
    +
         public static final String CRITICALITY = "Criticality: ";
     90   -
         /**
    +
     
     91   -
          * The DAL.
    +
         /**
     92   -
          */
    +
          * The DAL.
     93   -
         private CveDB cvedb;
    +
          */
     94   -
     
    +
         private CveDB cvedb;
     95   -
         /**
    +
     
     96   -
          * @return a filter that accepts files named Gemfile.lock
    +
         /**
     97   -
          */
    +
          * @return a filter that accepts files named Gemfile.lock
     98   -
         @Override
    +
          */
     99   +
         @Override
    +  100  
         protected FileFilter getFileFilter() {
    -  100  9
             return FILTER;
    -  101   -
         }
    +  101  858
             return FILTER;
     102   -
     
    +
         }
     103   -
         /**
    +
     
     104   -
          * Launch bundle-audit.
    +
         /**
     105   -
          *
    +
          * Launch bundle-audit.
     106   -
          * @param folder directory that contains bundle audit
    +
          *
     107   -
          * @return a handle to the process
    +
          * @param folder directory that contains bundle audit
     108   -
          * @throws AnalysisException thrown when there is an issue launching bundle
    +
          * @return a handle to the process
     109   -
          * audit
    +
          * @throws AnalysisException thrown when there is an issue launching bundle
     110   -
          */
    +
          * audit
     111   +
          */
    +  112  
         private Process launchBundleAudit(File folder) throws AnalysisException {
    -  112  4
             if (!folder.isDirectory()) {
    -  113  0
                 throw new AnalysisException(String.format("%s should have been a directory.", folder.getAbsolutePath()));
    -  114   +  113  4
             if (!folder.isDirectory()) {
    +  114  0
                 throw new AnalysisException(String.format("%s should have been a directory.", folder.getAbsolutePath()));
    +  115  
             }
    -  115  4
             final List<String> args = new ArrayList<String>();
    -  116  4
             final String bundleAuditPath = Settings.getString(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH);
    -  117  4
             args.add(null == bundleAuditPath ? "bundle-audit" : bundleAuditPath);
    -  118  4
             args.add("check");
    -  119  4
             args.add("--verbose");
    -  120  4
             final ProcessBuilder builder = new ProcessBuilder(args);
    -  121  4
             builder.directory(folder);
    -  122   +  116  4
             final List<String> args = new ArrayList<String>();
    +  117  4
             final String bundleAuditPath = Settings.getString(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH);
    +  118  4
             args.add(null == bundleAuditPath ? "bundle-audit" : bundleAuditPath);
    +  119  4
             args.add("check");
    +  120  4
             args.add("--verbose");
    +  121  4
             final ProcessBuilder builder = new ProcessBuilder(args);
    +  122  4
             builder.directory(folder);
    +  123  
             try {
    -  123  4
                 LOGGER.info("Launching: " + args + " from " + folder);
    -  124  4
                 return builder.start();
    -  125  4
             } catch (IOException ioe) {
    -  126  4
                 throw new AnalysisException("bundle-audit failure", ioe);
    -  127   -
             }
    +  124  4
                 LOGGER.info("Launching: " + args + " from " + folder);
    +  125  4
                 return builder.start();
    +  126  4
             } catch (IOException ioe) {
    +  127  4
                 throw new AnalysisException("bundle-audit failure", ioe);
     128   -
         }
    +
             }
     129   -
     
    +
         }
     130   -
         /**
    +
     
     131   -
          * Initialize the analyzer. In this case, extract GrokAssembly.exe to a
    +
         /**
     132   -
          * temporary location.
    +
          * Initialize the analyzer. In this case, extract GrokAssembly.exe to a
     133   -
          *
    +
          * temporary location.
     134   -
          * @throws InitializationException if anything goes wrong
    +
          *
     135   -
          */
    +
          * @throws InitializationException if anything goes wrong
     136   -
         @Override
    +
          */
     137   -
         public void initializeFileTypeAnalyzer() throws InitializationException {
    +
         @Override
     138   +
         public void initializeFileTypeAnalyzer() throws InitializationException {
    +  139  
             try {
    -  139  4
                 cvedb = new CveDB();
    -  140  4
                 cvedb.open();
    -  141  0
             } catch (DatabaseException ex) {
    -  142  0
                 LOGGER.warn("Exception opening the database");
    -  143  0
                 LOGGER.debug("error", ex);
    -  144  0
                 setEnabled(false);
    -  145  0
                 throw new InitializationException("Error connecting to the database", ex);
    -  146  4
             }
    -  147   +  140  4
                 cvedb = new CveDB();
    +  141  4
                 cvedb.open();
    +  142  0
             } catch (DatabaseException ex) {
    +  143  0
                 LOGGER.warn("Exception opening the database");
    +  144  0
                 LOGGER.debug("error", ex);
    +  145  0
                 setEnabled(false);
    +  146  0
                 throw new InitializationException("Error connecting to the database", ex);
    +  147  4
             }
    +  148  
             // Now, need to see if bundle-audit actually runs from this location.
    -  148  4
             Process process = null;
    -  149   +  149  4
             Process process = null;
    +  150  
             try {
    -  150  4
                 process = launchBundleAudit(Settings.getTempDirectory());
    -  151  4
             } catch (AnalysisException ae) {
    -  152   -
     
    -  153  4
                 setEnabled(false);
    -  154  4
                 cvedb.close();
    -  155  4
                 cvedb = null;
    -  156  4
                 final String msg = String.format("Exception from bundle-audit process: %s. Disabling %s", ae.getCause(), ANALYZER_NAME);
    -  157  4
                 throw new InitializationException(msg, ae);
    -  158  0
             } catch (IOException ex) {
    -  159  0
                 setEnabled(false);
    -  160  0
                 throw new InitializationException("Unable to create temporary file, the Ruby Bundle Audit Analyzer will be disabled", ex);
    -  161  0
             }
    -  162   +  151  4
                 process = launchBundleAudit(Settings.getTempDirectory());
    +  152  4
             } catch (AnalysisException ae) {
    +  153  
     
    +  154  4
                 setEnabled(false);
    +  155  4
                 cvedb.close();
    +  156  4
                 cvedb = null;
    +  157  4
                 final String msg = String.format("Exception from bundle-audit process: %s. Disabling %s", ae.getCause(), ANALYZER_NAME);
    +  158  4
                 throw new InitializationException(msg, ae);
    +  159  0
             } catch (IOException ex) {
    +  160  0
                 setEnabled(false);
    +  161  0
                 throw new InitializationException("Unable to create temporary file, the Ruby Bundle Audit Analyzer will be disabled", ex);
    +  162  0
             }
     163   -
             final int exitValue;
    +
     
     164   +
             final int exitValue;
    +  165  
             try {
    -  165  0
                 exitValue = process.waitFor();
    -  166  0
             } catch (InterruptedException ex) {
    -  167  0
                 setEnabled(false);
    -  168  0
                 final String msg = String.format("Bundle-audit process was interupted. Disabling %s", ANALYZER_NAME);
    -  169  0
                 throw new InitializationException(msg);
    -  170  0
             }
    -  171  0
             if (0 == exitValue) {
    -  172  0
                 setEnabled(false);
    -  173  0
                 final String msg = String.format("Unexpected exit code from bundle-audit process. Disabling %s: %s", ANALYZER_NAME, exitValue);
    -  174  0
                 throw new InitializationException(msg);
    -  175   +  166  0
                 exitValue = process.waitFor();
    +  167  0
             } catch (InterruptedException ex) {
    +  168  0
                 setEnabled(false);
    +  169  0
                 final String msg = String.format("Bundle-audit process was interupted. Disabling %s", ANALYZER_NAME);
    +  170  0
                 throw new InitializationException(msg);
    +  171  0
             }
    +  172  0
             if (0 == exitValue) {
    +  173  0
                 setEnabled(false);
    +  174  0
                 final String msg = String.format("Unexpected exit code from bundle-audit process. Disabling %s: %s", ANALYZER_NAME, exitValue);
    +  175  0
                 throw new InitializationException(msg);
    +  176  
             } else {
    -  176  0
                 BufferedReader reader = null;
    -  177   +  177  0
                 BufferedReader reader = null;
    +  178  
                 try {
    -  178  0
                     reader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8"));
    -  179  0
                     if (!reader.ready()) {
    -  180  0
                         LOGGER.warn("Bundle-audit error stream unexpectedly not ready. Disabling " + ANALYZER_NAME);
    -  181  0
                         setEnabled(false);
    -  182  0
                         throw new InitializationException("Bundle-audit error stream unexpectedly not ready.");
    -  183   +  179  0
                     reader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8"));
    +  180  0
                     if (!reader.ready()) {
    +  181  0
                         LOGGER.warn("Bundle-audit error stream unexpectedly not ready. Disabling " + ANALYZER_NAME);
    +  182  0
                         setEnabled(false);
    +  183  0
                         throw new InitializationException("Bundle-audit error stream unexpectedly not ready.");
    +  184  
                     } else {
    -  184  0
                         final String line = reader.readLine();
    -  185  0
                         if (line == null || !line.contains("Errno::ENOENT")) {
    -  186  0
                             LOGGER.warn("Unexpected bundle-audit output. Disabling {}: {}", ANALYZER_NAME, line);
    -  187  0
                             setEnabled(false);
    -  188  0
                             throw new InitializationException("Unexpected bundle-audit output.");
    -  189   -
                         }
    +  185  0
                         final String line = reader.readLine();
    +  186  0
                         if (line == null || !line.contains("Errno::ENOENT")) {
    +  187  0
                             LOGGER.warn("Unexpected bundle-audit output. Disabling {}: {}", ANALYZER_NAME, line);
    +  188  0
                             setEnabled(false);
    +  189  0
                             throw new InitializationException("Unexpected bundle-audit output.");
     190   +
                         }
    +  191  
                     }
    -  191  0
                 } catch (UnsupportedEncodingException ex) {
    -  192  0
                     setEnabled(false);
    -  193  0
                     throw new InitializationException("Unexpected bundle-audit encoding.", ex);
    -  194  0
                 } catch (IOException ex) {
    -  195  0
                     setEnabled(false);
    -  196  0
                     throw new InitializationException("Unable to read bundle-audit output.", ex);
    -  197   +  192  0
                 } catch (UnsupportedEncodingException ex) {
    +  193  0
                     setEnabled(false);
    +  194  0
                     throw new InitializationException("Unexpected bundle-audit encoding.", ex);
    +  195  0
                 } catch (IOException ex) {
    +  196  0
                     setEnabled(false);
    +  197  0
                     throw new InitializationException("Unable to read bundle-audit output.", ex);
    +  198  
                 } finally {
    -  198  0
                     if (null != reader) {
    -  199   +  199  0
                     if (null != reader) {
    +  200  
                         try {
    -  200  0
                             reader.close();
    -  201  0
                         } catch (IOException ex) {
    -  202  0
                             LOGGER.debug("Error closing reader", ex);
    -  203  0
                         }
    -  204   -
                     }
    +  201  0
                             reader.close();
    +  202  0
                         } catch (IOException ex) {
    +  203  0
                             LOGGER.debug("Error closing reader", ex);
    +  204  0
                         }
     205   -
                 }
    +
                     }
     206   -
             }
    +
                 }
     207   +
             }
    +  208  
     
    -  208  0
             if (isEnabled()) {
    -  209  0
                 LOGGER.info(ANALYZER_NAME + " is enabled. It is necessary to manually run \"bundle-audit update\" "
    -  210   -
                         + "occasionally to keep its database up to date.");
    +  209  0
             if (isEnabled()) {
    +  210  0
                 LOGGER.info(ANALYZER_NAME + " is enabled. It is necessary to manually run \"bundle-audit update\" "
     211   +
                         + "occasionally to keep its database up to date.");
    +  212  
             }
    -  212  0
         }
    -  213   -
     
    +  213  0
         }
     214   -
         /**
    +
     
     215   -
          * Returns the name of the analyzer.
    +
         /**
     216   -
          *
    +
          * Returns the name of the analyzer.
     217   -
          * @return the name of the analyzer.
    +
          *
     218   -
          */
    +
          * @return the name of the analyzer.
     219   -
         @Override
    +
          */
     220   +
         @Override
    +  221  
         public String getName() {
    -  221  15
             return ANALYZER_NAME;
    -  222   -
         }
    +  222  15
             return ANALYZER_NAME;
     223   -
     
    +
         }
     224   -
         /**
    +
     
     225   -
          * Returns the phase that the analyzer is intended to run in.
    +
         /**
     226   -
          *
    +
          * Returns the phase that the analyzer is intended to run in.
     227   -
          * @return the phase that the analyzer is intended to run in.
    +
          *
     228   -
          */
    +
          * @return the phase that the analyzer is intended to run in.
     229   -
         @Override
    +
          */
     230   +
         @Override
    +  231  
         public AnalysisPhase getAnalysisPhase() {
    -  231  4
             return ANALYSIS_PHASE;
    -  232   -
         }
    +  232  4
             return ANALYSIS_PHASE;
     233   -
     
    +
         }
     234   -
         /**
    +
     
     235   -
          * Returns the key used in the properties file to reference the analyzer's
    +
         /**
     236   -
          * enabled property.
    +
          * Returns the key used in the properties file to reference the analyzer's
     237   -
          *
    +
          * enabled property.
     238   -
          * @return the analyzer's enabled property setting key
    +
          *
     239   -
          */
    +
          * @return the analyzer's enabled property setting key
     240   -
         @Override
    +
          */
     241   -
         protected String getAnalyzerEnabledSettingKey() {
    -  242  12
             return Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED;
    -  243   -
         }
    -  244   -
     
    -  245   -
         /**
    -  246   -
          * If {@link #analyzeFileType(Dependency, Engine)} is called, then we have
    -  247   -
          * successfully initialized, and it will be necessary to disable
    -  248   -
          * {@link RubyGemspecAnalyzer}.
    -  249   -
          */
    -  250  12
         private boolean needToDisableGemspecAnalyzer = true;
    -  251   -
     
    -  252   -
         /**
    -  253   -
          * Determines if the analyzer can analyze the given file type.
    -  254   -
          *
    -  255   -
          * @param dependency the dependency to determine if it can analyze
    -  256   -
          * @param engine the dependency-check engine
    -  257   -
          * @throws AnalysisException thrown if there is an analysis exception.
    -  258   -
          */
    -  259  
         @Override
    -  260   -
         protected void analyzeFileType(Dependency dependency, Engine engine)
    -  261   -
                 throws AnalysisException {
    -  262  0
             if (needToDisableGemspecAnalyzer) {
    -  263  0
                 boolean failed = true;
    -  264  0
                 final String className = RubyGemspecAnalyzer.class.getName();
    -  265  0
                 for (FileTypeAnalyzer analyzer : engine.getFileTypeAnalyzers()) {
    -  266  0
                     if (analyzer instanceof RubyBundlerAnalyzer) {
    -  267  0
                         ((RubyBundlerAnalyzer) analyzer).setEnabled(false);
    -  268  0
                         LOGGER.info("Disabled " + RubyBundlerAnalyzer.class.getName() + " to avoid noisy duplicate results.");
    -  269  0
                     } else if (analyzer instanceof RubyGemspecAnalyzer) {
    -  270  0
                         ((RubyGemspecAnalyzer) analyzer).setEnabled(false);
    -  271  0
                         LOGGER.info("Disabled " + className + " to avoid noisy duplicate results.");
    -  272  0
                         failed = false;
    -  273   -
                     }
    -  274  0
                 }
    -  275  0
                 if (failed) {
    -  276  0
                     LOGGER.warn("Did not find " + className + '.');
    -  277   -
                 }
    -  278  0
                 needToDisableGemspecAnalyzer = false;
    -  279   -
             }
    -  280  0
             final File parentFile = dependency.getActualFile().getParentFile();
    -  281  0
             final Process process = launchBundleAudit(parentFile);
    -  282   -
             try {
    -  283  0
                 process.waitFor();
    -  284  0
             } catch (InterruptedException ie) {
    -  285  0
                 throw new AnalysisException("bundle-audit process interrupted", ie);
    -  286  0
             }
    -  287  0
             BufferedReader rdr = null;
    -  288  0
             BufferedReader errReader = null;
    -  289   -
             try {
    -  290  0
                 errReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8"));
    -  291  0
                 while (errReader.ready()) {
    -  292  0
                     final String error = errReader.readLine();
    -  293  0
                     LOGGER.warn(error);
    -  294  0
                 }
    -  295  0
                 rdr = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
    -  296  0
                 processBundlerAuditOutput(dependency, engine, rdr);
    -  297  0
             } catch (IOException ioe) {
    -  298  0
                 LOGGER.warn("bundle-audit failure", ioe);
    -  299   -
             } finally {
    -  300  0
                 if (errReader != null) {
    -  301   -
                     try {
    -  302  0
                         errReader.close();
    -  303  0
                     } catch (IOException ioe) {
    -  304  0
                         LOGGER.warn("bundle-audit close failure", ioe);
    -  305  0
                     }
    -  306   -
                 }
    -  307  0
                 if (null != rdr) {
    -  308   -
                     try {
    -  309  0
                         rdr.close();
    -  310  0
                     } catch (IOException ioe) {
    -  311  0
                         LOGGER.warn("bundle-audit close failure", ioe);
    -  312  0
                     }
    -  313   -
                 }
    -  314   -
             }
    -  315   +  242   +
         protected String getAnalyzerEnabledSettingKey() {
    +  243  12
             return Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED;
    +  244   +
         }
    +  245  
     
    -  316  0
         }
    -  317   -
     
    -  318   +  246  
         /**
    -  319   -
          * Processes the bundler audit output.
    -  320   +  247   +
          * If {@link #analyzeFileType(Dependency, Engine)} is called, then we have
    +  248   +
          * successfully initialized, and it will be necessary to disable
    +  249   +
          * {@link RubyGemspecAnalyzer}.
    +  250   +
          */
    +  251  12
         private boolean needToDisableGemspecAnalyzer = true;
    +  252   +
     
    +  253   +
         /**
    +  254   +
          * Determines if the analyzer can analyze the given file type.
    +  255  
          *
    -  321   -
          * @param original the dependency
    -  322   +  256   +
          * @param dependency the dependency to determine if it can analyze
    +  257  
          * @param engine the dependency-check engine
    +  258   +
          * @throws AnalysisException thrown if there is an analysis exception.
    +  259   +
          */
    +  260   +
         @Override
    +  261   +
         protected void analyzeFileType(Dependency dependency, Engine engine)
    +  262   +
                 throws AnalysisException {
    +  263  0
             if (needToDisableGemspecAnalyzer) {
    +  264  0
                 boolean failed = true;
    +  265  0
                 final String className = RubyGemspecAnalyzer.class.getName();
    +  266  0
                 for (FileTypeAnalyzer analyzer : engine.getFileTypeAnalyzers()) {
    +  267  0
                     if (analyzer instanceof RubyBundlerAnalyzer) {
    +  268  0
                         ((RubyBundlerAnalyzer) analyzer).setEnabled(false);
    +  269  0
                         LOGGER.info("Disabled " + RubyBundlerAnalyzer.class.getName() + " to avoid noisy duplicate results.");
    +  270  0
                     } else if (analyzer instanceof RubyGemspecAnalyzer) {
    +  271  0
                         ((RubyGemspecAnalyzer) analyzer).setEnabled(false);
    +  272  0
                         LOGGER.info("Disabled " + className + " to avoid noisy duplicate results.");
    +  273  0
                         failed = false;
    +  274   +
                     }
    +  275  0
                 }
    +  276  0
                 if (failed) {
    +  277  0
                     LOGGER.warn("Did not find " + className + '.');
    +  278   +
                 }
    +  279  0
                 needToDisableGemspecAnalyzer = false;
    +  280   +
             }
    +  281  0
             final File parentFile = dependency.getActualFile().getParentFile();
    +  282  0
             final Process process = launchBundleAudit(parentFile);
    +  283   +
             final int exitValue;
    +  284   +
             try {
    +  285  0
                 exitValue = process.waitFor();
    +  286  0
             } catch (InterruptedException ie) {
    +  287  0
                 throw new AnalysisException("bundle-audit process interrupted", ie);
    +  288  0
             }
    +  289  0
             if (exitValue != 0) {
    +  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   +
             }
    +  293  0
             BufferedReader rdr = null;
    +  294  0
             BufferedReader errReader = null;
    +  295   +
             try {
    +  296  0
                 errReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8"));
    +  297  0
                 while (errReader.ready()) {
    +  298  0
                     final String error = errReader.readLine();
    +  299  0
                     LOGGER.warn(error);
    +  300  0
                 }
    +  301  0
                 rdr = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
    +  302  0
                 processBundlerAuditOutput(dependency, engine, rdr);
    +  303  0
             } catch (IOException ioe) {
    +  304  0
                 LOGGER.warn("bundle-audit failure", ioe);
    +  305   +
             } finally {
    +  306  0
                 if (errReader != null) {
    +  307   +
                     try {
    +  308  0
                         errReader.close();
    +  309  0
                     } catch (IOException ioe) {
    +  310  0
                         LOGGER.warn("bundle-audit close failure", ioe);
    +  311  0
                     }
    +  312   +
                 }
    +  313  0
                 if (null != rdr) {
    +  314   +
                     try {
    +  315  0
                         rdr.close();
    +  316  0
                     } catch (IOException ioe) {
    +  317  0
                         LOGGER.warn("bundle-audit close failure", ioe);
    +  318  0
                     }
    +  319   +
                 }
    +  320   +
             }
    +  321   +
     
    +  322  0
         }
     323   -
          * @param rdr the reader of the report
    +
     
     324   -
          * @throws IOException thrown if the report cannot be read.
    +
         /**
     325   -
          */
    +
          * Processes the bundler audit output.
     326   +
          *
    +  327   +
          * @param original the dependency
    +  328   +
          * @param engine the dependency-check engine
    +  329   +
          * @param rdr the reader of the report
    +  330   +
          * @throws IOException thrown if the report cannot be read.
    +  331   +
          */
    +  332  
         private void processBundlerAuditOutput(Dependency original, Engine engine, BufferedReader rdr) throws IOException {
    -  327  0
             final String parentName = original.getActualFile().getParentFile().getName();
    -  328  0
             final String fileName = original.getFileName();
    -  329  0
             final String filePath = original.getFilePath();
    -  330  0
             Dependency dependency = null;
    -  331  0
             Vulnerability vulnerability = null;
    -  332  0
             String gem = null;
    -  333  0
             final Map<String, Dependency> map = new HashMap<String, Dependency>();
    -  334  0
             boolean appendToDescription = false;
    -  335  0
             while (rdr.ready()) {
    -  336  0
                 final String nextLine = rdr.readLine();
    -  337  0
                 if (null == nextLine) {
    -  338  0
                     break;
    -  339  0
                 } else if (nextLine.startsWith(NAME)) {
    -  340  0
                     appendToDescription = false;
    -  341  0
                     gem = nextLine.substring(NAME.length());
    -  342  0
                     if (!map.containsKey(gem)) {
    -  343  0
                         map.put(gem, createDependencyForGem(engine, parentName, fileName, filePath, gem));
    -  344   +  333  0
             final String parentName = original.getActualFile().getParentFile().getName();
    +  334  0
             final String fileName = original.getFileName();
    +  335  0
             final String filePath = original.getFilePath();
    +  336  0
             Dependency dependency = null;
    +  337  0
             Vulnerability vulnerability = null;
    +  338  0
             String gem = null;
    +  339  0
             final Map<String, Dependency> map = new HashMap<String, Dependency>();
    +  340  0
             boolean appendToDescription = false;
    +  341  0
             while (rdr.ready()) {
    +  342  0
                 final String nextLine = rdr.readLine();
    +  343  0
                 if (null == nextLine) {
    +  344  0
                     break;
    +  345  0
                 } else if (nextLine.startsWith(NAME)) {
    +  346  0
                     appendToDescription = false;
    +  347  0
                     gem = nextLine.substring(NAME.length());
    +  348  0
                     if (!map.containsKey(gem)) {
    +  349  0
                         map.put(gem, createDependencyForGem(engine, parentName, fileName, filePath, gem));
    +  350  
                     }
    -  345  0
                     dependency = map.get(gem);
    -  346  0
                     LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine));
    -  347  0
                 } else if (nextLine.startsWith(VERSION)) {
    -  348  0
                     vulnerability = createVulnerability(parentName, dependency, gem, nextLine);
    -  349  0
                 } else if (nextLine.startsWith(ADVISORY)) {
    -  350  0
                     setVulnerabilityName(parentName, dependency, vulnerability, nextLine);
    -  351  0
                 } else if (nextLine.startsWith(CRITICALITY)) {
    -  352  0
                     addCriticalityToVulnerability(parentName, vulnerability, nextLine);
    -  353  0
                 } else if (nextLine.startsWith("URL: ")) {
    -  354  0
                     addReferenceToVulnerability(parentName, vulnerability, nextLine);
    -  355  0
                 } else if (nextLine.startsWith("Description:")) {
    -  356  0
                     appendToDescription = true;
    -  357  0
                     if (null != vulnerability) {
    -  358  0
                         vulnerability.setDescription("*** Vulnerability obtained from bundle-audit verbose report. "
    -  359   -
                                 + "Title link may not work. CPE below is guessed. CVSS score is estimated (-1.0 "
    -  360   -
                                 + " indicates unknown). See link below for full details. *** ");
    -  361   -
                     }
    -  362  0
                 } else if (appendToDescription) {
    +  351  0
                     dependency = map.get(gem);
    +  352  0
                     LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine));
    +  353  0
                 } else if (nextLine.startsWith(VERSION)) {
    +  354  0
                     vulnerability = createVulnerability(parentName, dependency, gem, nextLine);
    +  355  0
                 } else if (nextLine.startsWith(ADVISORY)) {
    +  356  0
                     setVulnerabilityName(parentName, dependency, vulnerability, nextLine);
    +  357  0
                 } else if (nextLine.startsWith(CRITICALITY)) {
    +  358  0
                     addCriticalityToVulnerability(parentName, vulnerability, nextLine);
    +  359  0
                 } else if (nextLine.startsWith("URL: ")) {
    +  360  0
                     addReferenceToVulnerability(parentName, vulnerability, nextLine);
    +  361  0
                 } else if (nextLine.startsWith("Description:")) {
    +  362  0
                     appendToDescription = true;
     363  0
                     if (null != vulnerability) {
    -  364  0
                         vulnerability.setDescription(vulnerability.getDescription() + nextLine + "\n");
    +  364  0
                         vulnerability.setDescription("*** Vulnerability obtained from bundle-audit verbose report. "
     365   -
                     }
    +
                                 + "Title link may not work. CPE below is guessed. CVSS score is estimated (-1.0 "
     366   -
                 }
    -  367  0
             }
    -  368  0
         }
    -  369   -
     
    -  370   -
         /**
    +
                                 + " indicates unknown). See link below for full details. *** ");
    +  367   +
                     }
    +  368  0
                 } else if (appendToDescription) {
    +  369  0
                     if (null != vulnerability) {
    +  370  0
                         vulnerability.setDescription(vulnerability.getDescription() + nextLine + "\n");
     371   -
          * Sets the vulnerability name.
    +
                     }
     372   -
          *
    -  373   -
          * @param parentName the parent name
    -  374   -
          * @param dependency the dependency
    -  375   -
          * @param vulnerability the vulnerability
    -  376   -
          * @param nextLine the line to parse
    -  377   -
          */
    -  378   -
         private void setVulnerabilityName(String parentName, Dependency dependency, Vulnerability vulnerability, String nextLine) {
    -  379  0
             final String advisory = nextLine.substring((ADVISORY.length()));
    -  380  0
             if (null != vulnerability) {
    -  381  0
                 vulnerability.setName(advisory);
    -  382   -
             }
    -  383  0
             if (null != dependency) {
    -  384  0
                 dependency.getVulnerabilities().add(vulnerability); // needed to wait for vulnerability name to avoid NPE
    -  385   -
             }
    -  386  0
             LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine));
    -  387  0
         }
    -  388   -
     
    -  389   -
         /**
    -  390   -
          * Adds a reference to the vulnerability.
    -  391   -
          *
    -  392   -
          * @param parentName the parent name
    -  393   -
          * @param vulnerability the vulnerability
    -  394   -
          * @param nextLine the line to parse
    -  395   -
          */
    -  396   -
         private void addReferenceToVulnerability(String parentName, Vulnerability vulnerability, String nextLine) {
    -  397  0
             final String url = nextLine.substring(("URL: ").length());
    -  398  0
             if (null != vulnerability) {
    -  399  0
                 final Reference ref = new Reference();
    -  400  0
                 ref.setName(vulnerability.getName());
    -  401  0
                 ref.setSource("bundle-audit");
    -  402  0
                 ref.setUrl(url);
    -  403  0
                 vulnerability.getReferences().add(ref);
    -  404   -
             }
    -  405  0
             LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine));
    -  406  0
         }
    -  407   -
     
    -  408   -
         /**
    -  409   -
          * Adds the criticality to the vulnerability
    -  410   -
          *
    -  411   -
          * @param parentName the parent name
    -  412   -
          * @param vulnerability the vulnerability
    -  413   -
          * @param nextLine the line to parse
    -  414   -
          */
    -  415   -
         private void addCriticalityToVulnerability(String parentName, Vulnerability vulnerability, String nextLine) {
    -  416  0
             if (null != vulnerability) {
    -  417  0
                 final String criticality = nextLine.substring(CRITICALITY.length()).trim();
    -  418  0
                 float score = -1.0f;
    -  419  0
                 Vulnerability v = null;
    -  420   -
                 try {
    -  421  0
                     v = cvedb.getVulnerability(vulnerability.getName());
    -  422  0
                 } catch (DatabaseException ex) {
    -  423  0
                     LOGGER.debug("Unable to look up vulnerability {}", vulnerability.getName());
    -  424  0
                 }
    -  425  0
                 if (v != null) {
    -  426  0
                     score = v.getCvssScore();
    -  427  0
                 } else if ("High".equalsIgnoreCase(criticality)) {
    -  428  0
                     score = 8.5f;
    -  429  0
                 } else if ("Medium".equalsIgnoreCase(criticality)) {
    -  430  0
                     score = 5.5f;
    -  431  0
                 } else if ("Low".equalsIgnoreCase(criticality)) {
    -  432  0
                     score = 2.0f;
    -  433  
                 }
    -  434  0
                 vulnerability.setCvssScore(score);
    -  435   -
             }
    -  436  0
             LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine));
    -  437  0
         }
    -  438   +  373  0
             }
    +  374  0
         }
    +  375  
     
    -  439   +  376  
         /**
    -  440   -
          * Creates a vulnerability.
    -  441   +  377   +
          * Sets the vulnerability name.
    +  378  
          *
    -  442   +  379  
          * @param parentName the parent name
    -  443   +  380  
          * @param dependency the dependency
    -  444   -
          * @param gem the gem name
    -  445   +  381   +
          * @param vulnerability the vulnerability
    +  382  
          * @param nextLine the line to parse
    -  446   -
          * @return the vulnerability
    -  447   +  383  
          */
    -  448   -
         private Vulnerability createVulnerability(String parentName, Dependency dependency, String gem, String nextLine) {
    -  449  0
             Vulnerability vulnerability = null;
    -  450  0
             if (null != dependency) {
    -  451  0
                 final String version = nextLine.substring(VERSION.length());
    -  452  0
                 dependency.getVersionEvidence().addEvidence(
    -  453   -
                         "bundler-audit",
    -  454   -
                         "Version",
    -  455   -
                         version,
    -  456   -
                         Confidence.HIGHEST);
    -  457  0
                 vulnerability = new Vulnerability(); // don't add to dependency until we have name set later
    -  458  0
                 vulnerability.setMatchedCPE(
    -  459  0
                         String.format("cpe:/a:%1$s_project:%1$s:%2$s::~~~ruby~~", gem, version),
    -  460   -
                         null);
    -  461  0
                 vulnerability.setCvssAccessVector("-");
    -  462  0
                 vulnerability.setCvssAccessComplexity("-");
    -  463  0
                 vulnerability.setCvssAuthentication("-");
    -  464  0
                 vulnerability.setCvssAvailabilityImpact("-");
    -  465  0
                 vulnerability.setCvssConfidentialityImpact("-");
    -  466  0
                 vulnerability.setCvssIntegrityImpact("-");
    -  467   +  384   +
         private void setVulnerabilityName(String parentName, Dependency dependency, Vulnerability vulnerability, String nextLine) {
    +  385  0
             final String advisory = nextLine.substring((ADVISORY.length()));
    +  386  0
             if (null != vulnerability) {
    +  387  0
                 vulnerability.setName(advisory);
    +  388  
             }
    -  468  0
             LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine));
    -  469  0
             return vulnerability;
    -  470   -
         }
    -  471   +  389  0
             if (null != dependency) {
    +  390  0
                 dependency.getVulnerabilities().add(vulnerability); // needed to wait for vulnerability name to avoid NPE
    +  391   +
             }
    +  392  0
             LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine));
    +  393  0
         }
    +  394  
     
    -  472   +  395  
         /**
    -  473   -
          * Creates the dependency based off of the gem.
    -  474   +  396   +
          * Adds a reference to the vulnerability.
    +  397  
          *
    -  475   -
          * @param engine the engine used for scanning
    -  476   -
          * @param parentName the gem parent
    -  477   -
          * @param fileName the file name
    -  478   -
          * @param filePath the file path
    -  479   -
          * @param gem the gem name
    -  480   -
          * @return the dependency to add
    -  481   -
          * @throws IOException thrown if a temporary gem file could not be written
    -  482   +  398   +
          * @param parentName the parent name
    +  399   +
          * @param vulnerability the vulnerability
    +  400   +
          * @param nextLine the line to parse
    +  401  
          */
    -  483   -
         private Dependency createDependencyForGem(Engine engine, String parentName, String fileName, String filePath, String gem) throws IOException {
    -  484  0
             final File gemFile = new File(Settings.getTempDirectory(), gem + "_Gemfile.lock");
    -  485  0
             gemFile.createNewFile();
    -  486  0
             final String displayFileName = String.format("%s%c%s:%s", parentName, File.separatorChar, fileName, gem);
    -  487   +  402   +
         private void addReferenceToVulnerability(String parentName, Vulnerability vulnerability, String nextLine) {
    +  403  0
             final String url = nextLine.substring(("URL: ").length());
    +  404  0
             if (null != vulnerability) {
    +  405  0
                 final Reference ref = new Reference();
    +  406  0
                 ref.setName(vulnerability.getName());
    +  407  0
                 ref.setSource("bundle-audit");
    +  408  0
                 ref.setUrl(url);
    +  409  0
                 vulnerability.getReferences().add(ref);
    +  410   +
             }
    +  411  0
             LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine));
    +  412  0
         }
    +  413  
     
    -  488  0
             FileUtils.write(gemFile, displayFileName, Charset.defaultCharset()); // unique contents to avoid dependency bundling
    -  489  0
             final Dependency dependency = new Dependency(gemFile);
    -  490  0
             dependency.getProductEvidence().addEvidence("bundler-audit", "Name", gem, Confidence.HIGHEST);
    -  491  0
             dependency.setDisplayFileName(displayFileName);
    -  492  0
             dependency.setFileName(fileName);
    -  493  0
             dependency.setFilePath(filePath);
    -  494  0
             engine.getDependencies().add(dependency);
    -  495  0
             return dependency;
    -  496   +  414   +
         /**
    +  415   +
          * Adds the criticality to the vulnerability
    +  416   +
          *
    +  417   +
          * @param parentName the parent name
    +  418   +
          * @param vulnerability the vulnerability
    +  419   +
          * @param nextLine the line to parse
    +  420   +
          */
    +  421   +
         private void addCriticalityToVulnerability(String parentName, Vulnerability vulnerability, String nextLine) {
    +  422  0
             if (null != vulnerability) {
    +  423  0
                 final String criticality = nextLine.substring(CRITICALITY.length()).trim();
    +  424  0
                 float score = -1.0f;
    +  425  0
                 Vulnerability v = null;
    +  426   +
                 try {
    +  427  0
                     v = cvedb.getVulnerability(vulnerability.getName());
    +  428  0
                 } catch (DatabaseException ex) {
    +  429  0
                     LOGGER.debug("Unable to look up vulnerability {}", vulnerability.getName());
    +  430  0
                 }
    +  431  0
                 if (v != null) {
    +  432  0
                     score = v.getCvssScore();
    +  433  0
                 } else if ("High".equalsIgnoreCase(criticality)) {
    +  434  0
                     score = 8.5f;
    +  435  0
                 } else if ("Medium".equalsIgnoreCase(criticality)) {
    +  436  0
                     score = 5.5f;
    +  437  0
                 } else if ("Low".equalsIgnoreCase(criticality)) {
    +  438  0
                     score = 2.0f;
    +  439   +
                 }
    +  440  0
                 vulnerability.setCvssScore(score);
    +  441   +
             }
    +  442  0
             LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine));
    +  443  0
         }
    +  444   +
     
    +  445   +
         /**
    +  446   +
          * Creates a vulnerability.
    +  447   +
          *
    +  448   +
          * @param parentName the parent name
    +  449   +
          * @param dependency the dependency
    +  450   +
          * @param gem the gem name
    +  451   +
          * @param nextLine the line to parse
    +  452   +
          * @return the vulnerability
    +  453   +
          */
    +  454   +
         private Vulnerability createVulnerability(String parentName, Dependency dependency, String gem, String nextLine) {
    +  455  0
             Vulnerability vulnerability = null;
    +  456  0
             if (null != dependency) {
    +  457  0
                 final String version = nextLine.substring(VERSION.length());
    +  458  0
                 dependency.getVersionEvidence().addEvidence(
    +  459   +
                         "bundler-audit",
    +  460   +
                         "Version",
    +  461   +
                         version,
    +  462   +
                         Confidence.HIGHEST);
    +  463  0
                 vulnerability = new Vulnerability(); // don't add to dependency until we have name set later
    +  464  0
                 vulnerability.setMatchedCPE(
    +  465  0
                         String.format("cpe:/a:%1$s_project:%1$s:%2$s::~~~ruby~~", gem, version),
    +  466   +
                         null);
    +  467  0
                 vulnerability.setCvssAccessVector("-");
    +  468  0
                 vulnerability.setCvssAccessComplexity("-");
    +  469  0
                 vulnerability.setCvssAuthentication("-");
    +  470  0
                 vulnerability.setCvssAvailabilityImpact("-");
    +  471  0
                 vulnerability.setCvssConfidentialityImpact("-");
    +  472  0
                 vulnerability.setCvssIntegrityImpact("-");
    +  473   +
             }
    +  474  0
             LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine));
    +  475  0
             return vulnerability;
    +  476  
         }
    -  497   +  477   +
     
    +  478   +
         /**
    +  479   +
          * Creates the dependency based off of the gem.
    +  480   +
          *
    +  481   +
          * @param engine the engine used for scanning
    +  482   +
          * @param parentName the gem parent
    +  483   +
          * @param fileName the file name
    +  484   +
          * @param filePath the file path
    +  485   +
          * @param gem the gem name
    +  486   +
          * @return the dependency to add
    +  487   +
          * @throws IOException thrown if a temporary gem file could not be written
    +  488   +
          */
    +  489   +
         private Dependency createDependencyForGem(Engine engine, String parentName, String fileName, String filePath, String gem) throws IOException {
    +  490  0
             final File gemFile = new File(Settings.getTempDirectory(), gem + "_Gemfile.lock");
    +  491  0
             if (!gemFile.createNewFile()) {
    +  492  0
                 throw new IOException("Unable to create temporary gem file");
    +  493   +
             }
    +  494  0
             final String displayFileName = String.format("%s%c%s:%s", parentName, File.separatorChar, fileName, gem);
    +  495   +
     
    +  496  0
             FileUtils.write(gemFile, displayFileName, Charset.defaultCharset()); // unique contents to avoid dependency bundling
    +  497  0
             final Dependency dependency = new Dependency(gemFile);
    +  498  0
             dependency.getProductEvidence().addEvidence("bundler-audit", "Name", gem, Confidence.HIGHEST);
    +  499  0
             dependency.setDisplayFileName(displayFileName);
    +  500  0
             dependency.setFileName(fileName);
    +  501  0
             dependency.setFilePath(filePath);
    +  502  0
             engine.getDependencies().add(dependency);
    +  503  0
             return dependency;
    +  504   +
         }
    +  505  
     }
    - + 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 6e203c679..16abdfcd7 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.RubyBundlerAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.RubyBundlerAnalyzer.html @@ -49,7 +49,7 @@  15  
      *
     16   -
      * Copyright (c) 2016 Bianca Jiang. All Rights Reserved.
    +
      * Copyright (c) 2016 IBM Corporation. All Rights Reserved.
     17  
      */
     18   @@ -109,7 +109,7 @@  45  
      *
     46   -
      * @author Bianca Jiang (biancajiang@gmail.com)
    +
      * @author Bianca Jiang (https://twitter.com/biancajiang)
     47  
      */
     48   @@ -186,15 +186,15 @@
         public boolean accept(File pathname) {
     85  
     
    -  86  12
             boolean accepted = super.accept(pathname);
    -  87  12
             if (accepted) {
    +  86  861
             boolean accepted = super.accept(pathname);
    +  87  861
             if (accepted) {
     88  4
                 final File parentDir = pathname.getParentFile();
     89  4
                 accepted = parentDir != null && parentDir.getName().equals(SPECIFICATIONS);
     90  
             }
     91  
     
    -  92  12
             return accepted;
    +  92  861
             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 50dcf9e47..13fbc9c16 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.RubyGemspecAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.RubyGemspecAnalyzer.html @@ -12,8 +12,8 @@
     
    - - + +
    Classes in this File Line Coverage Branch Coverage Complexity
    RubyGemspecAnalyzer
    76%
    49/64
    40%
    8/20
    2.3
    RubyGemspecAnalyzer$1
    0%
    0/2
    N/A
    2.3
    RubyGemspecAnalyzer
    74%
    49/66
    36%
    8/22
    2.5
    RubyGemspecAnalyzer$1
    0%
    0/2
    N/A
    2.5
     
    @@ -188,7 +188,7 @@
         @Override
     87  
         protected FileFilter getFileFilter() {
    -  88  23
             return FILTER;
    +  88  1721
             return FILTER;
     89  
         }
     90   @@ -405,48 +405,52 @@
                     }
     219  
                 });
    -  220  0
                 for (File f : matchingFiles) {
    -  221   -
                     try {
    -  222  0
                         final List<String> lines = FileUtils.readLines(f, Charset.defaultCharset());
    -  223  0
                         if (lines.size() == 1) { //TODO other checking?
    -  224  0
                             final String value = lines.get(0).trim();
    -  225  0
                             versionEvidences.addEvidence(GEMSPEC, "version", value, Confidence.HIGH);
    -  226   -
                         }
    -  227  0
                     } catch (IOException e) {
    -  228  0
                         LOGGER.debug("Error reading gemspec", e);
    -  229  0
                     }
    -  230   +  220  0
                 if (matchingFiles == null) {
    +  221  0
                     return;
    +  222  
                 }
    -  231   -
             }
    -  232  0
         }
    +  223  0
                 for (File f : matchingFiles) {
    +  224   +
                     try {
    +  225  0
                         final List<String> lines = FileUtils.readLines(f, Charset.defaultCharset());
    +  226  0
                         if (lines.size() == 1) { //TODO other checking?
    +  227  0
                             final String value = lines.get(0).trim();
    +  228  0
                             versionEvidences.addEvidence(GEMSPEC, "version", value, Confidence.HIGH);
    +  229   +
                         }
    +  230  0
                     } catch (IOException e) {
    +  231  0
                         LOGGER.debug("Error reading gemspec", e);
    +  232  0
                     }
     233   -
     
    +
                 }
     234   -
         /**
    -  235   -
          * Sets the package path on the dependency.
    -  236   -
          *
    -  237   -
          * @param dep the dependency to alter
    -  238   -
          */
    -  239   -
         private void setPackagePath(Dependency dep) {
    -  240  4
             final File file = new File(dep.getFilePath());
    -  241  4
             final String parent = file.getParent();
    -  242  4
             if (parent != null) {
    -  243  4
                 dep.setPackagePath(parent);
    -  244  
             }
    -  245  4
         }
    -  246   +  235  0
         }
    +  236   +
     
    +  237   +
         /**
    +  238   +
          * Sets the package path on the dependency.
    +  239   +
          *
    +  240   +
          * @param dep the dependency to alter
    +  241   +
          */
    +  242   +
         private void setPackagePath(Dependency dep) {
    +  243  4
             final File file = new File(dep.getFilePath());
    +  244  4
             final String parent = file.getParent();
    +  245  4
             if (parent != null) {
    +  246  4
                 dep.setPackagePath(parent);
    +  247   +
             }
    +  248  4
         }
    +  249  
     }
    - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.SwiftPackageManagerAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.SwiftPackageManagerAnalyzer.html new file mode 100644 index 000000000..2ac91fe9a --- /dev/null +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.SwiftPackageManagerAnalyzer.html @@ -0,0 +1,368 @@ + + + + +Coverage Report + + + + +
    Coverage Report - org.owasp.dependencycheck.analyzer.SwiftPackageManagerAnalyzer
    +
     
    + + + + +
    Classes in this File Line Coverage Branch Coverage Complexity
    SwiftPackageManagerAnalyzer
    92%
    37/40
    50%
    8/16
    2.375
    +
     
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     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 IBM Corporation. All Rights Reserved.
     17  
      */
     18  
     package org.owasp.dependencycheck.analyzer;
     19  
     
     20  
     import java.io.File;
     21  
     import java.io.FileFilter;
     22  
     import java.io.IOException;
     23  
     import java.nio.charset.Charset;
     24  
     import java.util.regex.Matcher;
     25  
     import java.util.regex.Pattern;
     26  
     
     27  
     import org.apache.commons.io.FileUtils;
     28  
     import org.owasp.dependencycheck.Engine;
     29  
     import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
     30  
     import org.owasp.dependencycheck.dependency.Confidence;
     31  
     import org.owasp.dependencycheck.dependency.Dependency;
     32  
     import org.owasp.dependencycheck.dependency.EvidenceCollection;
     33  
     import org.owasp.dependencycheck.utils.FileFilterBuilder;
     34  
     import org.owasp.dependencycheck.utils.Settings;
     35  
     
     36  
     /**
     37  
      * This analyzer is used to analyze the SWIFT Package Manager
     38  
      * (https://swift.org/package-manager/). It collects information about a package
     39  
      * from Package.swift files.
     40  
      *
     41  
      * @author Bianca Jiang (https://twitter.com/biancajiang)
     42  
      */
     43  
     @Experimental
     44  12
     public class SwiftPackageManagerAnalyzer extends AbstractFileTypeAnalyzer {
     45  
     
     46  
         /**
     47  
          * The name of the analyzer.
     48  
          */
     49  
         private static final String ANALYZER_NAME = "SWIFT Package Manager Analyzer";
     50  
     
     51  
         /**
     52  
          * The phase that this analyzer is intended to run in.
     53  
          */
     54  1
         private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
     55  
     
     56  
         /**
     57  
          * The file name to scan.
     58  
          */
     59  
         public static final String SPM_FILE_NAME = "Package.swift";
     60  
     
     61  
         /**
     62  
          * Filter that detects files named "package.json".
     63  
          */
     64  1
         private static final FileFilter SPM_FILE_FILTER = FileFilterBuilder.newInstance().addFilenames(SPM_FILE_NAME).build();
     65  
     
     66  
         /**
     67  
          * The capture group #1 is the block variable. e.g. "import
     68  
          * PackageDescription let package = Package( name: "Gloss" )"
     69  
          */
     70  1
         private static final Pattern SPM_BLOCK_PATTERN = Pattern.compile("let[^=]+=\\s*Package\\s*\\(\\s*([^)]*)\\s*\\)", Pattern.DOTALL);
     71  
     
     72  
         /**
     73  
          * Returns the FileFilter
     74  
          *
     75  
          * @return the FileFilter
     76  
          */
     77  
         @Override
     78  
         protected FileFilter getFileFilter() {
     79  860
             return SPM_FILE_FILTER;
     80  
         }
     81  
     
     82  
         @Override
     83  
         protected void initializeFileTypeAnalyzer() {
     84  
             // NO-OP
     85  6
         }
     86  
     
     87  
         /**
     88  
          * Returns the name of the analyzer.
     89  
          *
     90  
          * @return the name of the analyzer.
     91  
          */
     92  
         @Override
     93  
         public String getName() {
     94  15
             return ANALYZER_NAME;
     95  
         }
     96  
     
     97  
         /**
     98  
          * Returns the phase that the analyzer is intended to run in.
     99  
          *
     100  
          * @return the phase that the analyzer is intended to run in.
     101  
          */
     102  
         @Override
     103  
         public AnalysisPhase getAnalysisPhase() {
     104  4
             return ANALYSIS_PHASE;
     105  
         }
     106  
     
     107  
         /**
     108  
          * Returns the key used in the properties file to reference the analyzer's
     109  
          * enabled property.
     110  
          *
     111  
          * @return the analyzer's enabled property setting key
     112  
          */
     113  
         @Override
     114  
         protected String getAnalyzerEnabledSettingKey() {
     115  12
             return Settings.KEYS.ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED;
     116  
         }
     117  
     
     118  
         @Override
     119  
         protected void analyzeFileType(Dependency dependency, Engine engine)
     120  
                 throws AnalysisException {
     121  
     
     122  
             String contents;
     123  
             try {
     124  1
                 contents = FileUtils.readFileToString(dependency.getActualFile(), Charset.defaultCharset());
     125  0
             } catch (IOException e) {
     126  0
                 throw new AnalysisException(
     127  
                         "Problem occurred while reading dependency file.", e);
     128  1
             }
     129  1
             final Matcher matcher = SPM_BLOCK_PATTERN.matcher(contents);
     130  1
             if (matcher.find()) {
     131  1
                 final String packageDescription = matcher.group(1);
     132  1
                 if (packageDescription.isEmpty()) {
     133  0
                     return;
     134  
                 }
     135  
     
     136  1
                 final EvidenceCollection product = dependency.getProductEvidence();
     137  1
                 final EvidenceCollection vendor = dependency.getVendorEvidence();
     138  
     
     139  
                 //SPM is currently under development for SWIFT 3. Its current metadata includes package name and dependencies.
     140  
                 //Future interesting metadata: version, license, homepage, author, summary, etc.
     141  1
                 final String name = addStringEvidence(product, packageDescription, "name", "name", Confidence.HIGHEST);
     142  1
                 if (name != null && !name.isEmpty()) {
     143  1
                     vendor.addEvidence(SPM_FILE_NAME, "name_project", name, Confidence.HIGHEST);
     144  
                 }
     145  
             }
     146  1
             setPackagePath(dependency);
     147  1
         }
     148  
     
     149  
         /**
     150  
          * Extracts evidence from the package description and adds it to the given
     151  
          * evidence collection.
     152  
          *
     153  
          * @param evidences the evidence collection to update
     154  
          * @param packageDescription the text to extract evidence from
     155  
          * @param field the name of the field being searched for
     156  
          * @param fieldPattern the field pattern within the contents to search for
     157  
          * @param confidence the confidence level of the evidence if found
     158  
          * @return the string that was added as evidence
     159  
          */
     160  
         private String addStringEvidence(EvidenceCollection evidences,
     161  
                 String packageDescription, String field, String fieldPattern, Confidence confidence) {
     162  1
             String value = "";
     163  
     
     164  2
             final Matcher matcher = Pattern.compile(
     165  2
                     String.format("%s *:\\s*\"([^\"]*)", fieldPattern), Pattern.DOTALL).matcher(packageDescription);
     166  1
             if (matcher.find()) {
     167  1
                 value = matcher.group(1);
     168  
             }
     169  
     
     170  1
             if (value != null) {
     171  1
                 value = value.trim();
     172  1
                 if (value.length() > 0) {
     173  1
                     evidences.addEvidence(SPM_FILE_NAME, field, value, confidence);
     174  
                 }
     175  
             }
     176  
     
     177  1
             return value;
     178  
         }
     179  
     
     180  
         /**
     181  
          * Sets the package path on the given dependency.
     182  
          *
     183  
          * @param dep the dependency to update
     184  
          */
     185  
         private void setPackagePath(Dependency dep) {
     186  1
             final File file = new File(dep.getFilePath());
     187  1
             final String parent = file.getParent();
     188  1
             if (parent != null) {
     189  1
                 dep.setPackagePath(parent);
     190  
             }
     191  1
         }
     192  
     }
    + + + + 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 f172d0c3c..9fd8fdd81 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.VulnerabilitySuppressionAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.VulnerabilitySuppressionAnalyzer.html @@ -152,13 +152,13 @@  70  
     
     71  4
             for (final SuppressionRule rule : getRules()) {
    -  72  224
                 rule.process(dependency);
    -  73  224
             }
    +  72  228
                 rule.process(dependency);
    +  73  228
             }
     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 d603e0ffc..ee241d6f1 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 @@ -12,7 +12,7 @@
     
    - +
    Classes in this File Line Coverage Branch Coverage Complexity
    AnalysisException
    50%
    4/8
    N/A
    1
    AnalysisException
    25%
    2/8
    N/A
    1
     
    @@ -103,8 +103,8 @@
          */
     44  
         public AnalysisException(String msg) {
    -  45  1
             super(msg);
    -  46  1
         }
    +  45  0
             super(msg);
    +  46  0
         }
     47  
     
     48   @@ -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 bb62eeeb1..0dbd92e12 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 d22de8f31..c30a9b6d9 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
    83%
    51/61
    83%
    20/24
    10
    CentralSearch
    86%
    53/61
    87%
    21/24
    9.5
     
    @@ -143,9 +143,9 @@  63  
          *
     64   -
          * @param rootURL the URL of the repository on which searches should execute. Only parameters are added to this (so it should
    +
          * @param rootURL the URL of the repository on which searches should
     65   -
          * end in /select)
    +
          * execute. Only parameters are added to this (so it should end in /select)
     66  
          */
     67  5
         public CentralSearch(URL rootURL) {
    @@ -165,141 +165,135 @@  78  
         /**
     79   -
          * Searches the configured Central URL for the given sha1 hash. If the artifact is found, a <code>MavenArtifact</code> is
    +
          * Searches the configured Central URL for the given sha1 hash. If the
     80   -
          * populated with the GAV.
    +
          * artifact is found, a <code>MavenArtifact</code> is populated with the
     81   -
          *
    +
          * GAV.
     82   -
          * @param sha1 the SHA-1 hash string for which to search
    +
          *
     83   -
          * @return the populated Maven GAV.
    +
          * @param sha1 the SHA-1 hash string for which to search
     84   -
          * @throws IOException if it's unable to connect to the specified repository or if the specified artifact is not found.
    +
          * @return the populated Maven GAV.
     85   -
          */
    +
          * @throws IOException if it's unable to connect to the specified repository
     86   +
          * or if the specified artifact is not found.
    +  87   +
          */
    +  88  
         public List<MavenArtifact> searchSha1(String sha1) throws IOException {
    -  87  5
             if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) {
    -  88  2
                 throw new IllegalArgumentException("Invalid SHA1 format");
    -  89   +  89  5
             if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) {
    +  90  2
                 throw new IllegalArgumentException("Invalid SHA1 format");
    +  91  
             }
    -  90   -
     
    -  91  3
             final URL url = new URL(rootURL + String.format("?q=1:\"%s\"&wt=xml", sha1));
    -  92   -
     
    -  93  3
             LOGGER.debug("Searching Central url {}", url);
    +  92  3
             List<MavenArtifact> result = null;
    +  93  3
             final URL url = new URL(rootURL + String.format("?q=1:\"%s\"&wt=xml", sha1));
     94  
     
    -  95   -
             // Determine if we need to use a proxy. The rules:
    +  95  3
             LOGGER.debug("Searching Central url {}", url);
     96   -
             // 1) If the proxy is set, AND the setting is set to true, use the proxy
    -  97   -
             // 2) Otherwise, don't use the proxy (either the proxy isn't configured,
    -  98   -
             // or proxy is specifically set to false)
    -  99  3
             final HttpURLConnection conn = URLConnectionFactory.createHttpURLConnection(url, useProxy);
    -  100  
     
    -  101  3
             conn.setDoOutput(true);
    +  97   +
             // Determine if we need to use a proxy. The rules:
    +  98   +
             // 1) If the proxy is set, AND the setting is set to true, use the proxy
    +  99   +
             // 2) Otherwise, don't use the proxy (either the proxy isn't configured,
    +  100   +
             // or proxy is specifically set to false)
    +  101  3
             final HttpURLConnection conn = URLConnectionFactory.createHttpURLConnection(url, useProxy);
     102  
     
    -  103   -
             // JSON would be more elegant, but there's not currently a dependency
    +  103  3
             conn.setDoOutput(true);
     104   +
     
    +  105   +
             // JSON would be more elegant, but there's not currently a dependency
    +  106  
             // on JSON, so don't want to add one just for this
    -  105  3
             conn.addRequestProperty("Accept", "application/xml");
    -  106  3
             conn.connect();
    -  107   +  107  3
             conn.addRequestProperty("Accept", "application/xml");
    +  108  3
             conn.connect();
    +  109  
     
    -  108  3
             if (conn.getResponseCode() == 200) {
    -  109  3
                 boolean missing = false;
    -  110   +  110  3
             if (conn.getResponseCode() == 200) {
    +  111  3
                 boolean missing = false;
    +  112  
                 try {
    -  111   +  113  
                     final DocumentBuilder builder = DocumentBuilderFactory
    -  112  3
                             .newInstance().newDocumentBuilder();
    -  113  3
                     final Document doc = builder.parse(conn.getInputStream());
    -  114  3
                     final XPath xpath = XPathFactory.newInstance().newXPath();
    -  115  3
                     final String numFound = xpath.evaluate("/response/result/@numFound", doc);
    -  116  3
                     if ("0".equals(numFound)) {
    -  117  1
                         missing = true;
    -  118   +  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  
                     } else {
    -  119  2
                         final List<MavenArtifact> result = new ArrayList<MavenArtifact>();
    -  120  2
                         final NodeList docs = (NodeList) xpath.evaluate("/response/result/doc", doc, XPathConstants.NODESET);
    -  121  5
                         for (int i = 0; i < docs.getLength(); i++) {
    -  122  3
                             final String g = xpath.evaluate("./str[@name='g']", docs.item(i));
    -  123  3
                             LOGGER.trace("GroupId: {}", g);
    -  124  3
                             final String a = xpath.evaluate("./str[@name='a']", docs.item(i));
    -  125  3
                             LOGGER.trace("ArtifactId: {}", a);
    -  126  3
                             final String v = xpath.evaluate("./str[@name='v']", docs.item(i));
    -  127  3
                             NodeList atts = (NodeList) xpath.evaluate("./arr[@name='ec']/str", docs.item(i), XPathConstants.NODESET);
    -  128  3
                             boolean pomAvailable = false;
    -  129  3
                             boolean jarAvailable = false;
    -  130  14
                             for (int x = 0; x < atts.getLength(); x++) {
    -  131  11
                                 final String tmp = xpath.evaluate(".", atts.item(x));
    -  132  11
                                 if (".pom".equals(tmp)) {
    -  133  3
                                     pomAvailable = true;
    -  134  8
                                 } else if (".jar".equals(tmp)) {
    -  135  3
                                     jarAvailable = true;
    -  136   -
                                 }
    -  137   -
                             }
    +  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   -
     
    -  139  3
                             atts = (NodeList) xpath.evaluate("./arr[@name='tags']/str", docs.item(i), XPathConstants.NODESET);
    -  140  3
                             boolean useHTTPS = false;
    -  141  21
                             for (int x = 0; x < atts.getLength(); x++) {
    -  142  18
                                 final String tmp = xpath.evaluate(".", atts.item(x));
    -  143  18
                                 if ("https".equals(tmp)) {
    -  144  0
                                     useHTTPS = true;
    -  145  
                                 }
    -  146   +  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  3
                             LOGGER.trace("Version: {}", v);
    -  149  3
                             result.add(new MavenArtifact(g, a, v, jarAvailable, pomAvailable, useHTTPS));
    -  150   -
                         }
    +
                                 }
    +  148   +
                             }
    +  149  3
                             LOGGER.trace("Version: {}", v);
    +  150  3
                             result.add(new MavenArtifact(g, a, v, jarAvailable, pomAvailable, useHTTPS));
     151   -
     
    -  152  2
                         return result;
    -  153   +
                         }
    +  152  
                     }
    -  154  0
                 } catch (Throwable e) {
    -  155   -
                     // Anything else is jacked up XML stuff that we really can't recover
    -  156   -
                     // from well
    -  157  0
                     throw new IOException(e.getMessage(), e);
    -  158  1
                 }
    -  159   +  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  
     
    -  160  1
                 if (missing) {
    -  161  1
                     throw new FileNotFoundException("Artifact not found in Central");
    -  162   +  158  3
                 if (missing) {
    +  159  1
                     throw new FileNotFoundException("Artifact not found in Central");
    +  160  
                 }
    -  163  0
             } else {
    -  164  0
                 LOGGER.debug("Could not connect to Central received response code: {} {}",
    -  165  0
                     conn.getResponseCode(), conn.getResponseMessage());
    -  166  0
                 throw new IOException("Could not connect to Central");
    -  167   +  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  
             }
    -  168   -
     
    -  169  0
             return null;
    -  170   +  166  2
             return result;
    +  167  
         }
    -  171   +  168  
     }
    - + 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 7fceaf379..1cc5ed73c 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 422f1fb32..3d7d61ae5 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 e733613a7..29f43e080 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 37403a392..01ddf49bc 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 @@ -12,7 +12,7 @@
     
    - +
    Classes in this File Line Coverage Branch Coverage Complexity
    CpeMemoryIndex
    79%
    77/97
    50%
    12/24
    3.25
    CpeMemoryIndex
    79%
    78/98
    53%
    15/28
    3.417
     
    @@ -383,169 +383,174 @@
     
     210  2
                     final Set<Pair<String, String>> data = cve.getVendorProductList();
     211  2
                     for (Pair<String, String> pair : data) {
    -  212  52138
                         v.setStringValue(pair.getLeft());
    -  213  52138
                         p.setStringValue(pair.getRight());
    -  214  52138
                         indexWriter.addDocument(doc);
    -  215  52138
                         resetFieldAnalyzer();
    -  216  52138
                     }
    -  217  0
                 } catch (DatabaseException ex) {
    -  218  0
                     LOGGER.debug("", ex);
    -  219  0
                     throw new IndexException("Error reading CPE data", ex);
    -  220  2
                 }
    -  221  0
             } catch (CorruptIndexException ex) {
    -  222  0
                 throw new IndexException("Unable to close an in-memory index", ex);
    -  223  0
             } catch (IOException ex) {
    -  224  0
                 throw new IndexException("Unable to close an in-memory index", ex);
    -  225   -
             } finally {
    -  226  2
                 if (indexWriter != null) {
    -  227   -
                     try {
    +  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();
    +  218   +
                         }
    +  219  52334
                     }
    +  220  0
                 } catch (DatabaseException ex) {
    +  221  0
                     LOGGER.debug("", ex);
    +  222  0
                     throw new IndexException("Error reading CPE data", ex);
    +  223  2
                 }
    +  224  0
             } catch (CorruptIndexException ex) {
    +  225  0
                 throw new IndexException("Unable to close an in-memory index", ex);
    +  226  0
             } catch (IOException ex) {
    +  227  0
                 throw new IndexException("Unable to close an in-memory index", ex);
     228   -
                         try {
    -  229  2
                             indexWriter.commit();
    +
             } finally {
    +  229  2
                 if (indexWriter != null) {
     230   +
                     try {
    +  231   +
                         try {
    +  232  2
                             indexWriter.commit();
    +  233  
                         } finally {
    -  231  2
                             indexWriter.close(true);
    -  232  2
                         }
    -  233  0
                     } catch (CorruptIndexException ex) {
    -  234  0
                         throw new IndexException("Unable to close an in-memory index", ex);
    -  235  0
                     } catch (IOException ex) {
    -  236  0
                         throw new IndexException("Unable to close an in-memory index", ex);
    -  237  2
                     }
    -  238  2
                     if (analyzer != null) {
    -  239  2
                         analyzer.close();
    -  240   +  234  2
                             indexWriter.close(true);
    +  235  2
                         }
    +  236  0
                     } catch (CorruptIndexException ex) {
    +  237  0
                         throw new IndexException("Unable to close an in-memory index", ex);
    +  238  0
                     } catch (IOException ex) {
    +  239  0
                         throw new IndexException("Unable to close an in-memory index", ex);
    +  240  2
                     }
    +  241  2
                     if (analyzer != null) {
    +  242  2
                         analyzer.close();
    +  243  
                     }
    -  241   -
                 }
    -  242   -
             }
    -  243  2
         }
     244   -
     
    +
                 }
     245   -
         /**
    -  246   -
          * Resets the product and vendor field analyzers.
    -  247   -
          */
    -  248   -
         private void resetFieldAnalyzer() {
    -  249  52149
             if (productFieldAnalyzer != null) {
    -  250  52149
                 productFieldAnalyzer.clear();
    -  251  
             }
    -  252  52149
             if (vendorFieldAnalyzer != null) {
    -  253  52149
                 vendorFieldAnalyzer.clear();
    +  246  2
         }
    +  247   +
     
    +  248   +
         /**
    +  249   +
          * Resets the product and vendor field analyzers.
    +  250   +
          */
    +  251   +
         private void resetFieldAnalyzer() {
    +  252  52343
             if (productFieldAnalyzer != null) {
    +  253  52343
                 productFieldAnalyzer.clear();
     254  
             }
    -  255  52149
         }
    -  256   -
     
    +  255  52343
             if (vendorFieldAnalyzer != null) {
    +  256  52343
                 vendorFieldAnalyzer.clear();
     257   -
         /**
    -  258   -
          * Searches the index using the given search string.
    +
             }
    +  258  52343
         }
     259   -
          *
    +
     
     260   -
          * @param searchString the query text
    +
         /**
     261   -
          * @param maxQueryResults the maximum number of documents to return
    +
          * Searches the index using the given search string.
     262   -
          * @return the TopDocs found by the search
    +
          *
     263   -
          * @throws ParseException thrown when the searchString is invalid
    +
          * @param searchString the query text
     264   -
          * @throws IOException is thrown if there is an issue with the underlying
    +
          * @param maxQueryResults the maximum number of documents to return
     265   -
          * Index
    +
          * @return the TopDocs found by the search
     266   -
          */
    +
          * @throws ParseException thrown when the searchString is invalid
     267   -
         public TopDocs search(String searchString, int maxQueryResults) throws ParseException, IOException {
    -  268  11
             if (searchString == null || searchString.trim().isEmpty()) {
    -  269  0
                 throw new ParseException("Query is null or empty");
    +
          * @throws IOException is thrown if there is an issue with the underlying
    +  268   +
          * Index
    +  269   +
          */
     270   +
         public TopDocs search(String searchString, int maxQueryResults) throws ParseException, IOException {
    +  271  11
             if (searchString == null || searchString.trim().isEmpty()) {
    +  272  0
                 throw new ParseException("Query is null or empty");
    +  273  
             }
    -  271  11
             LOGGER.debug(searchString);
    -  272  11
             final Query query = queryParser.parse(searchString);
    -  273  11
             return search(query, maxQueryResults);
    -  274   -
         }
    -  275   -
     
    -  276   -
         /**
    +  274  11
             LOGGER.debug(searchString);
    +  275  11
             final Query query = queryParser.parse(searchString);
    +  276  11
             return search(query, maxQueryResults);
     277   -
          * Searches the index using the given query.
    +
         }
     278   -
          *
    +
     
     279   -
          * @param query the query used to search the index
    +
         /**
     280   -
          * @param maxQueryResults the max number of results to return
    +
          * Searches the index using the given query.
     281   -
          * @return the TopDocs found be the query
    +
          *
     282   -
          * @throws CorruptIndexException thrown if the Index is corrupt
    +
          * @param query the query used to search the index
     283   -
          * @throws IOException thrown if there is an IOException
    +
          * @param maxQueryResults the max number of results to return
     284   -
          */
    +
          * @return the TopDocs found be the query
     285   -
         public TopDocs search(Query query, int maxQueryResults) throws CorruptIndexException, IOException {
    -  286  11
             resetFieldAnalyzer();
    -  287  11
             return indexSearcher.search(query, maxQueryResults);
    -  288   -
         }
    -  289   -
     
    -  290   -
         /**
    -  291   -
          * Retrieves a document from the Index.
    -  292   -
          *
    -  293   -
          * @param documentId the id of the document to retrieve
    -  294   -
          * @return the Document
    -  295   +
          * @throws CorruptIndexException thrown if the Index is corrupt
    +  286  
          * @throws IOException thrown if there is an IOException
    -  296   +  287  
          */
    -  297   -
         public Document getDocument(int documentId) throws IOException {
    -  298  46
             return indexSearcher.doc(documentId);
    -  299   +  288   +
         public TopDocs search(Query query, int maxQueryResults) throws CorruptIndexException, IOException {
    +  289  11
             resetFieldAnalyzer();
    +  290  11
             return indexSearcher.search(query, maxQueryResults);
    +  291  
         }
    -  300   +  292  
     
    -  301   +  293  
         /**
    -  302   -
          * Returns the number of CPE entries stored in the index.
    -  303   +  294   +
          * Retrieves a document from the Index.
    +  295  
          *
    -  304   -
          * @return the number of CPE entries stored in the index
    -  305   +  296   +
          * @param documentId the id of the document to retrieve
    +  297   +
          * @return the Document
    +  298   +
          * @throws IOException thrown if there is an IOException
    +  299  
          */
    -  306   -
         public int numDocs() {
    -  307  0
             if (indexReader == null) {
    -  308  0
                 return -1;
    -  309   -
             }
    -  310  0
             return indexReader.numDocs();
    -  311   +  300   +
         public Document getDocument(int documentId) throws IOException {
    +  301  18
             return indexSearcher.doc(documentId);
    +  302  
         }
    +  303   +
     
    +  304   +
         /**
    +  305   +
          * Returns the number of CPE entries stored in the index.
    +  306   +
          *
    +  307   +
          * @return the number of CPE entries stored in the index
    +  308   +
          */
    +  309   +
         public int numDocs() {
    +  310  0
             if (indexReader == null) {
    +  311  0
                 return -1;
     312   +
             }
    +  313  0
             return indexReader.numDocs();
    +  314   +
         }
    +  315  
     }
    - + 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 607f8dc12..33a8e420c 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 5b4d55430..ea7a1e540 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  1638
     public class IndexEntry implements Serializable {
    +  29  1610
     public class IndexEntry implements Serializable {
     30  
     
     31   @@ -168,8 +168,8 @@
          */
     79  
         public void setVendor(String vendor) {
    -  80  1640
             this.vendor = vendor;
    -  81  1640
         }
    +  80  1612
             this.vendor = vendor;
    +  81  1612
         }
     82  
         /**
     83   @@ -192,7 +192,7 @@
          */
     92  
         public String getProduct() {
    -  93  67
             return product;
    +  93  39
             return product;
     94  
         }
     95   @@ -209,8 +209,8 @@
          */
     101  
         public void setProduct(String product) {
    -  102  1639
             this.product = product;
    -  103  1639
         }
    +  102  1611
             this.product = product;
    +  103  1611
         }
     104  
         /**
     105   @@ -250,8 +250,8 @@
          */
     123  
         public void setSearchScore(float searchScore) {
    -  124  46
             this.searchScore = searchScore;
    -  125  46
         }
    +  124  18
             this.searchScore = searchScore;
    +  125  18
         }
     126  
     
     127   @@ -320,21 +320,21 @@
         @Override
     164  
         public boolean equals(Object obj) {
    -  165  381
             if (obj == null) {
    +  165  72
             if (obj == null) {
     166  0
                 return false;
     167  
             }
    -  168  381
             if (getClass() != obj.getClass()) {
    +  168  72
             if (getClass() != obj.getClass()) {
     169  0
                 return false;
     170  
             }
    -  171  381
             final IndexEntry other = (IndexEntry) obj;
    -  172  381
             if ((this.vendor == null) ? (other.vendor != null) : !this.vendor.equals(other.vendor)) {
    -  173  376
                 return false;
    +  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;
     174  
             }
    -  175  5
             if ((this.product == null) ? (other.product != null) : !this.product.equals(other.product)) {
    -  176  5
                 return false;
    +  175  2
             if ((this.product == null) ? (other.product != null) : !this.product.equals(other.product)) {
    +  176  2
                 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 5f2a95069..ed5ec7688 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 6ed238a03..fe7d7c8cd 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 510905b81..d014da909 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 be660b4de..4e831504a 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  16
         private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
    +  35  15
         private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
     36  
     
     37   @@ -100,7 +100,7 @@
          */
     42  
         protected CharTermAttribute getTermAtt() {
    -  43  603638
             return termAtt;
    +  43  599757
             return termAtt;
     44  
         }
     45   @@ -125,7 +125,7 @@
          */
     55  
         protected LinkedList<String> getTokens() {
    -  56  603637
             return tokens;
    +  56  599755
             return tokens;
     57  
         }
     58   @@ -142,9 +142,9 @@
          */
     64  
         public AbstractTokenizingFilter(TokenStream stream) {
    -  65  16
             super(stream);
    -  66  16
             tokens = new LinkedList<String>();
    -  67  16
         }
    +  65  15
             super(stream);
    +  66  15
             tokens = new LinkedList<String>();
    +  67  15
         }
     68  
     
     69   @@ -159,20 +159,20 @@
          */
     74  
         protected boolean addTerm() {
    -  75  603545
             final boolean termAdded = !tokens.isEmpty();
    -  76  603548
             if (termAdded) {
    -  77  210017
                 final String term = tokens.pop();
    -  78  210017
                 clearAttributes();
    -  79  210014
                 termAtt.append(term);
    +  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);
     80  
             }
    -  81  603548
             return termAdded;
    +  81  599702
             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 1c11ac532..4afec0b8a 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 @@ -131,13 +131,13 @@
         @Override
     59  
         protected boolean isTokenChar(int c) {
    -  60  1253271
             return Character.isLetter(c) || Character.isDigit(c);
    +  60  1258696
             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 70ba8dd6b..9125d2cf7 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 ed4ee5474..3ea7005fa 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 ecbfecb50..80e276b25 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  113
             if (text == null || buf == null) {
    +  56  111
             if (text == null || buf == null) {
     57  1
                 return;
     58  
             }
     59  
     
    -  60  1445
             for (int i = 0; i < text.length(); i++) {
    -  61  1333
                 final char c = text.charAt(i);
    -  62  1333
                 switch (c) {
    +  60  1327
             for (int i = 0; i < text.length(); i++) {
    +  61  1217
                 final char c = text.charAt(i);
    +  62  1217
                 switch (c) {
     63  
                     case '+':
     64   @@ -171,17 +171,17 @@
                     case '/':
     81  
                     case '\\': //it is supposed to fall through here
    -  82  58
                         buf.append('\\');
    +  82  44
                         buf.append('\\');
     83  
                     default:
    -  84  1333
                         buf.append(c);
    +  84  1217
                         buf.append(c);
     85  
                         break;
     86  
                 }
     87  
             }
    -  88  112
         }
    +  88  110
         }
     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 a8a32a9c5..cefe3df20 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 @@ -187,15 +187,15 @@
          */
     91  
         public void clear() {
    -  92  104300
             if (concatenatingFilter != null) {
    -  93  104300
                 concatenatingFilter.clear();
    +  92  104688
             if (concatenatingFilter != null) {
    +  93  104688
                 concatenatingFilter.clear();
     94  
             }
    -  95  104300
         }
    +  95  104688
         }
     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 c345415fe..318fcfff3 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 @@ -185,35 +185,35 @@
     
     87  
             //collect all the terms into the words collection
    -  88  578223
             while (input.incrementToken()) {
    -  89  192691
                 final String word = new String(termAtt.buffer(), 0, termAtt.length());
    -  90  192691
                 words.add(word);
    -  91  192691
             }
    +  88  580669
             while (input.incrementToken()) {
    +  89  193508
                 final String word = new String(termAtt.buffer(), 0, termAtt.length());
    +  90  193508
                 words.add(word);
    +  91  193508
             }
     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  385532
             if (previousWord != null && !words.isEmpty()) {
    -  96  88389
                 final String word = words.getFirst();
    -  97  88389
                 clearAttributes();
    -  98  88389
                 termAtt.append(previousWord).append(word);
    -  99  88389
                 previousWord = null;
    -  100  88389
                 return true;
    +  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;
     101  
             }
     102  
             //if we have words, write it out as a single token
    -  103  297143
             if (!words.isEmpty()) {
    -  104  192691
                 final String word = words.removeFirst();
    -  105  192691
                 clearAttributes();
    -  106  192691
                 termAtt.append(word);
    -  107  192691
                 previousWord = word;
    -  108  192691
                 return true;
    +  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;
     109  
             }
    -  110  104452
             return false;
    +  110  104835
             return false;
     111  
         }
     112   @@ -232,9 +232,9 @@
          */
     119  
         public void clear() {
    -  120  104301
             previousWord = null;
    -  121  104301
             words.clear();
    -  122  104301
         }
    +  120  104689
             previousWord = null;
    +  121  104689
             words.clear();
    +  122  104689
         }
     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 dd3fbdd91..79a180269 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  16
             super(stream);
    -  52  16
         }
    +  51  15
             super(stream);
    +  52  15
         }
     53  
     
     54   @@ -138,11 +138,11 @@
         @Override
     62  
         public boolean incrementToken() throws IOException {
    -  63  603636
             final LinkedList<String> tokens = getTokens();
    -  64  603638
             final CharTermAttribute termAtt = getTermAtt();
    -  65  603639
             if (tokens.isEmpty() && input.incrementToken()) {
    -  66  210014
                 final String text = new String(termAtt.buffer(), 0, termAtt.length());
    -  67  210014
                 if (UrlStringUtils.containsUrl(text)) {
    +  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)) {
     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  210005
                     tokens.add(text);
    +  83  206539
                     tokens.add(text);
     84  
                 }
     85  
             }
    -  86  603546
             return addTerm();
    +  86  599684
             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 4652d6b1e..152817e29 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 ea0334940..bd3c01253 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 @@ -327,6 +327,6 @@
     // 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 fd3599d2c..2e13db31f 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 de40fc40a..dc7e0d8f4 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 9a194ab36..0ab9765cf 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 ec9b9a007..45b765e47 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 @@ -160,6 +160,6 @@
     }
    - + 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 3414bc9df..e1fb006ff 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 @@ -12,7 +12,7 @@
     
    - +
    Classes in this File Line Coverage Branch Coverage Complexity
    ConnectionFactory
    38%
    68/177
    26%
    11/42
    8
    ConnectionFactory
    38%
    70/181
    28%
    13/46
    8.5
     
    @@ -94,518 +94,556 @@  38  
     /**
     39   -
      * Loads the configured database driver and returns the database connection. If the embedded H2 database is used obtaining a
    +
      * Loads the configured database driver and returns the database connection. If
     40   -
      * connection will ensure the database file exists and that the appropriate table structure has been created.
    +
      * the embedded H2 database is used obtaining a connection will ensure the
     41   -
      *
    +
      * database file exists and that the appropriate table structure has been
     42   -
      * @author Jeremy Long
    +
      * created.
     43   -
      */
    +
      *
     44   -
     public final class ConnectionFactory {
    +
      * @author Jeremy Long
     45   -
     
    +
      */
     46   -
         /**
    +
     public final class ConnectionFactory {
     47   -
          * The Logger.
    +
     
     48   -
          */
    -  49  1
         private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionFactory.class);
    +
         /**
    +  49   +
          * The Logger.
     50   -
         /**
    -  51   -
          * The version of the current DB Schema.
    +
          */
    +  51  1
         private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionFactory.class);
     52   -
          */
    -  53  1
         public static final String DB_SCHEMA_VERSION = Settings.getString(Settings.KEYS.DB_VERSION);
    +
         /**
    +  53   +
          * The version of the current DB Schema.
     54   -
         /**
    -  55   -
          * Resource location for SQL file used to create the database schema.
    +
          */
    +  55  1
         public static final String DB_SCHEMA_VERSION = Settings.getString(Settings.KEYS.DB_VERSION);
     56   -
          */
    +
         /**
     57   -
         public static final String DB_STRUCTURE_RESOURCE = "data/initialize.sql";
    -  58   -
         /**
    -  59  
          * Resource location for SQL file used to create the database schema.
    +  58   +
          */
    +  59   +
         public static final String DB_STRUCTURE_RESOURCE = "data/initialize.sql";
     60   -
          */
    +
         /**
     61   -
         public static final String DB_STRUCTURE_UPDATE_RESOURCE = "data/upgrade_%s.sql";
    +
          * Resource location for SQL file used to create the database schema.
     62   -
         /**
    +
          */
     63   -
          * The URL that discusses upgrading non-H2 databases.
    +
         public static final String DB_STRUCTURE_UPDATE_RESOURCE = "data/upgrade_%s.sql";
     64   -
          */
    +
         /**
     65   -
         public static final String UPGRADE_HELP_URL = "http://jeremylong.github.io/DependencyCheck/data/upgrade.html";
    +
          * The URL that discusses upgrading non-H2 databases.
     66   -
         /**
    +
          */
     67   -
          * The database driver used to connect to the database.
    +
         public static final String UPGRADE_HELP_URL = "http://jeremylong.github.io/DependencyCheck/data/upgrade.html";
     68   -
          */
    -  69  1
         private static Driver driver = null;
    +
         /**
    +  69   +
          * The database driver used to connect to the database.
     70   -
         /**
    -  71   -
          * The database connection string.
    +
          */
    +  71  1
         private static Driver driver = null;
     72   -
          */
    -  73  1
         private static String connectionString = null;
    +
         /**
    +  73   +
          * The database connection string.
     74   -
         /**
    -  75   -
          * The username to connect to the database.
    +
          */
    +  75  1
         private static String connectionString = null;
     76   -
          */
    -  77  1
         private static String userName = null;
    +
         /**
    +  77   +
          * The username to connect to the database.
     78   -
         /**
    -  79   -
          * The password for the database.
    +
          */
    +  79  1
         private static String userName = null;
     80   -
          */
    -  81  1
         private static String password = null;
    +
         /**
    +  81   +
          * The password for the database.
     82   -
     
    -  83   -
         /**
    +
          */
    +  83  1
         private static String password = null;
     84   -
          * Private constructor for this factory class; no instance is ever needed.
    +
     
     85   -
          */
    -  86  0
         private ConnectionFactory() {
    -  87  0
         }
    -  88   -
     
    -  89  
         /**
    +  86   +
          * Private constructor for this factory class; no instance is ever needed.
    +  87   +
          */
    +  88  0
         private ConnectionFactory() {
    +  89  0
         }
     90   -
          * Initializes the connection factory. Ensuring that the appropriate drivers are loaded and that a connection can be made
    +
     
     91   -
          * successfully.
    +
         /**
     92   -
          *
    +
          * Initializes the connection factory. Ensuring that the appropriate drivers
     93   -
          * @throws DatabaseException thrown if we are unable to connect to the database
    +
          * are loaded and that a connection can be made successfully.
     94   -
          */
    +
          *
     95   -
         public static synchronized void initialize() throws DatabaseException {
    +
          * @throws DatabaseException thrown if we are unable to connect to the
     96   -
             //this only needs to be called once.
    -  97  19
             if (connectionString != null) {
    -  98  17
                 return;
    +
          * database
    +  97   +
          */
    +  98   +
         public static void initialize() throws DatabaseException {
     99   -
             }
    -  100  2
             Connection conn = null;
    -  101   -
             try {
    +
             //this only needs to be called once.
    +  100  19
             if (connectionString != null) {
    +  101  17
                 return;
     102   +
             }
    +  103  2
             Connection conn = null;
    +  104   +
             try {
    +  105  
                 //load the driver if necessary
    -  103  2
                 final String driverName = Settings.getString(Settings.KEYS.DB_DRIVER_NAME, "");
    -  104  2
                 if (!driverName.isEmpty()) { //likely need to load the correct driver
    -  105  2
                     LOGGER.debug("Loading driver: {}", driverName);
    -  106  2
                     final String driverPath = Settings.getString(Settings.KEYS.DB_DRIVER_PATH, "");
    -  107   +  106  2
                 final String driverName = Settings.getString(Settings.KEYS.DB_DRIVER_NAME, "");
    +  107  2
                 if (!driverName.isEmpty()) { //likely need to load the correct driver
    +  108  2
                     LOGGER.debug("Loading driver: {}", driverName);
    +  109  2
                     final String driverPath = Settings.getString(Settings.KEYS.DB_DRIVER_PATH, "");
    +  110  
                     try {
    -  108  2
                         if (!driverPath.isEmpty()) {
    -  109  0
                             LOGGER.debug("Loading driver from: {}", driverPath);
    -  110  0
                             driver = DriverLoader.load(driverName, driverPath);
    -  111   +  111  2
                         if (!driverPath.isEmpty()) {
    +  112  0
                             LOGGER.debug("Loading driver from: {}", driverPath);
    +  113  0
                             driver = DriverLoader.load(driverName, driverPath);
    +  114  
                         } else {
    -  112  2
                             driver = DriverLoader.load(driverName);
    -  113   +  115  2
                             driver = DriverLoader.load(driverName);
    +  116  
                         }
    -  114  0
                     } catch (DriverLoadException ex) {
    -  115  0
                         LOGGER.debug("Unable to load database driver", ex);
    -  116  0
                         throw new DatabaseException("Unable to load database driver");
    -  117  2
                     }
    -  118   +  117  0
                     } catch (DriverLoadException ex) {
    +  118  0
                         LOGGER.debug("Unable to load database driver", ex);
    +  119  0
                         throw new DatabaseException("Unable to load database driver");
    +  120  2
                     }
    +  121  
                 }
    -  119  2
                 userName = Settings.getString(Settings.KEYS.DB_USER, "dcuser");
    -  120   +  122  2
                 userName = Settings.getString(Settings.KEYS.DB_USER, "dcuser");
    +  123  
                 //yes, yes - hard-coded password - only if there isn't one in the properties file.
    -  121  2
                 password = Settings.getString(Settings.KEYS.DB_PASSWORD, "DC-Pass1337!");
    -  122   -
                 try {
    -  123  2
                     connectionString = Settings.getConnectionString(
    -  124   -
                             Settings.KEYS.DB_CONNECTION_STRING,
    +  124  2
                 password = Settings.getString(Settings.KEYS.DB_PASSWORD, "DC-Pass1337!");
     125   -
                             Settings.KEYS.DB_FILE_NAME);
    -  126  0
                 } catch (IOException ex) {
    -  127  0
                     LOGGER.debug(
    +
                 try {
    +  126  2
                     connectionString = Settings.getConnectionString(
    +  127   +
                             Settings.KEYS.DB_CONNECTION_STRING,
     128   +
                             Settings.KEYS.DB_FILE_NAME);
    +  129  0
                 } catch (IOException ex) {
    +  130  0
                     LOGGER.debug(
    +  131  
                             "Unable to retrieve the database connection string", ex);
    -  129  0
                     throw new DatabaseException("Unable to retrieve the database connection string");
    -  130  2
                 }
    -  131  2
                 boolean shouldCreateSchema = false;
    -  132   +  132  0
                     throw new DatabaseException("Unable to retrieve the database connection string");
    +  133  2
                 }
    +  134  2
                 boolean shouldCreateSchema = false;
    +  135  
                 try {
    -  133  2
                     if (connectionString.startsWith("jdbc:h2:file:")) { //H2
    -  134  2
                         shouldCreateSchema = !h2DataFileExists();
    -  135  2
                         LOGGER.debug("Need to create DB Structure: {}", shouldCreateSchema);
    -  136   +  136  2
                     if (connectionString.startsWith("jdbc:h2:file:")) { //H2
    +  137  2
                         shouldCreateSchema = !h2DataFileExists();
    +  138  2
                         LOGGER.debug("Need to create DB Structure: {}", shouldCreateSchema);
    +  139  
                     }
    -  137  0
                 } catch (IOException ioex) {
    -  138  0
                     LOGGER.debug("Unable to verify database exists", ioex);
    -  139  0
                     throw new DatabaseException("Unable to verify database exists");
    -  140  2
                 }
    -  141  2
                 LOGGER.debug("Loading database connection");
    -  142  2
                 LOGGER.debug("Connection String: {}", connectionString);
    -  143  2
                 LOGGER.debug("Database User: {}", userName);
    -  144   +  140  0
                 } catch (IOException ioex) {
    +  141  0
                     LOGGER.debug("Unable to verify database exists", ioex);
    +  142  0
                     throw new DatabaseException("Unable to verify database exists");
    +  143  2
                 }
    +  144  2
                 LOGGER.debug("Loading database connection");
    +  145  2
                 LOGGER.debug("Connection String: {}", connectionString);
    +  146  2
                 LOGGER.debug("Database User: {}", userName);
    +  147  
     
    -  145   +  148  
                 try {
    -  146  2
                     conn = DriverManager.getConnection(connectionString, userName, password);
    -  147  0
                 } catch (SQLException ex) {
    -  148  0
                     if (ex.getMessage().contains("java.net.UnknownHostException") && connectionString.contains("AUTO_SERVER=TRUE;")) {
    -  149  0
                         connectionString = connectionString.replace("AUTO_SERVER=TRUE;", "");
    -  150   +  149  2
                     conn = DriverManager.getConnection(connectionString, userName, password);
    +  150  0
                 } catch (SQLException ex) {
    +  151  0
                     if (ex.getMessage().contains("java.net.UnknownHostException") && connectionString.contains("AUTO_SERVER=TRUE;")) {
    +  152  0
                         connectionString = connectionString.replace("AUTO_SERVER=TRUE;", "");
    +  153  
                         try {
    -  151  0
                             conn = DriverManager.getConnection(connectionString, userName, password);
    -  152  0
                             Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
    -  153  0
                             LOGGER.debug(
    -  154   +  154  0
                             conn = DriverManager.getConnection(connectionString, userName, password);
    +  155  0
                             Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
    +  156  0
                             LOGGER.debug(
    +  157  
                                     "Unable to start the database in server mode; reverting to single user mode");
    -  155  0
                         } catch (SQLException sqlex) {
    -  156  0
                             LOGGER.debug("Unable to connect to the database", ex);
    -  157  0
                             throw new DatabaseException("Unable to connect to the database");
    -  158  0
                         }
    -  159   -
                     } else {
    -  160  0
                         LOGGER.debug("Unable to connect to the database", ex);
    -  161  0
                         throw new DatabaseException("Unable to connect to the database");
    +  158  0
                         } catch (SQLException sqlex) {
    +  159  0
                             LOGGER.debug("Unable to connect to the database", ex);
    +  160  0
                             throw new DatabaseException("Unable to connect to the database");
    +  161  0
                         }
     162   +
                     } else {
    +  163  0
                         LOGGER.debug("Unable to connect to the database", ex);
    +  164  0
                         throw new DatabaseException("Unable to connect to the database");
    +  165  
                     }
    -  163  2
                 }
    -  164   +  166  2
                 }
    +  167  
     
    -  165  2
                 if (shouldCreateSchema) {
    -  166   +  168  2
                 if (shouldCreateSchema) {
    +  169  
                     try {
    -  167  0
                         createTables(conn);
    -  168  0
                     } catch (DatabaseException dex) {
    -  169  0
                         LOGGER.debug("", dex);
    -  170  0
                         throw new DatabaseException("Unable to create the database structure");
    -  171  0
                     }
    -  172   +  170  0
                         createTables(conn);
    +  171  0
                     } catch (DatabaseException dex) {
    +  172  0
                         LOGGER.debug("", dex);
    +  173  0
                         throw new DatabaseException("Unable to create the database structure");
    +  174  0
                     }
    +  175  
                 }
    -  173   +  176  
                 try {
    -  174  2
                     ensureSchemaVersion(conn);
    -  175  0
                 } catch (DatabaseException dex) {
    -  176  0
                     LOGGER.debug("", dex);
    -  177  0
                     throw new DatabaseException("Database schema does not match this version of dependency-check", dex);
    -  178  2
                 }
    -  179   +  177  2
                     ensureSchemaVersion(conn);
    +  178  0
                 } catch (DatabaseException dex) {
    +  179  0
                     LOGGER.debug("", dex);
    +  180  0
                     throw new DatabaseException("Database schema does not match this version of dependency-check", dex);
    +  181  2
                 }
    +  182  
             } finally {
    -  180  2
                 if (conn != null) {
    -  181   +  183  2
                 if (conn != null) {
    +  184  
                     try {
    -  182  2
                         conn.close();
    -  183  0
                     } catch (SQLException ex) {
    -  184  0
                         LOGGER.debug("An error occurred closing the connection", ex);
    -  185  2
                     }
    -  186   -
                 }
    -  187   -
             }
    -  188  2
         }
    +  185  2
                         conn.close();
    +  186  0
                     } catch (SQLException ex) {
    +  187  0
                         LOGGER.debug("An error occurred closing the connection", ex);
    +  188  2
                     }
     189   -
     
    +
                 }
     190   -
         /**
    -  191   -
          * Cleans up resources and unloads any registered database drivers. This needs to be called to ensure the driver is
    +
             }
    +  191  2
         }
     192   -
          * unregistered prior to the finalize method being called as during shutdown the class loader used to load the driver may be
    +
     
     193   -
          * unloaded prior to the driver being de-registered.
    +
         /**
     194   -
          */
    +
          * Cleans up resources and unloads any registered database drivers. This
     195   -
         public static synchronized void cleanup() {
    -  196  1
             if (driver != null) {
    +
          * needs to be called to ensure the driver is unregistered prior to the
    +  196   +
          * finalize method being called as during shutdown the class loader used to
     197   +
          * load the driver may be unloaded prior to the driver being de-registered.
    +  198   +
          */
    +  199   +
         public static void cleanup() {
    +  200  1
             if (driver != null) {
    +  201  
                 try {
    -  198  1
                     DriverManager.deregisterDriver(driver);
    -  199  0
                 } catch (SQLException ex) {
    -  200  0
                     LOGGER.debug("An error occurred unloading the database driver", ex);
    -  201  0
                 } catch (Throwable unexpected) {
    -  202  0
                     LOGGER.debug(
    -  203   +  202  1
                     DriverManager.deregisterDriver(driver);
    +  203  0
                 } catch (SQLException ex) {
    +  204  0
                     LOGGER.debug("An error occurred unloading the database driver", ex);
    +  205  0
                 } catch (Throwable unexpected) {
    +  206  0
                     LOGGER.debug(
    +  207  
                             "An unexpected throwable occurred unloading the database driver", unexpected);
    -  204  1
                 }
    -  205  1
                 driver = null;
    -  206   +  208  1
                 }
    +  209  1
                 driver = null;
    +  210  
             }
    -  207  1
             connectionString = null;
    -  208  1
             userName = null;
    -  209  1
             password = null;
    -  210  1
         }
    -  211   -
     
    -  212   -
         /**
    -  213   -
          * Constructs a new database connection object per the database configuration.
    -  214   -
          *
    +  211  1
             connectionString = null;
    +  212  1
             userName = null;
    +  213  1
             password = null;
    +  214  1
         }
     215   -
          * @return a database connection object
    +
     
     216   -
          * @throws DatabaseException thrown if there is an exception loading the database connection
    +
         /**
     217   -
          */
    +
          * Constructs a new database connection object per the database
     218   -
         public static Connection getConnection() throws DatabaseException {
    -  219  14
             initialize();
    -  220  14
             Connection conn = null;
    +
          * configuration.
    +  219   +
          *
    +  220   +
          * @return a database connection object
     221   +
          * @throws DatabaseException thrown if there is an exception loading the
    +  222   +
          * database connection
    +  223   +
          */
    +  224   +
         public static Connection getConnection() throws DatabaseException {
    +  225  14
             initialize();
    +  226  14
             Connection conn = null;
    +  227  
             try {
    -  222  14
                 conn = DriverManager.getConnection(connectionString, userName, password);
    -  223  0
             } catch (SQLException ex) {
    -  224  0
                 LOGGER.debug("", ex);
    -  225  0
                 throw new DatabaseException("Unable to connect to the database");
    -  226  14
             }
    -  227  14
             return conn;
    -  228   -
         }
    -  229   -
     
    -  230   -
         /**
    -  231   -
          * Determines if the H2 database file exists. If it does not exist then the data structure will need to be created.
    -  232   -
          *
    -  233   -
          * @return true if the H2 database file does not exist; otherwise false
    +  228  14
                 conn = DriverManager.getConnection(connectionString, userName, password);
    +  229  0
             } catch (SQLException ex) {
    +  230  0
                 LOGGER.debug("", ex);
    +  231  0
                 throw new DatabaseException("Unable to connect to the database");
    +  232  14
             }
    +  233  14
             return conn;
     234   -
          * @throws IOException thrown if the data directory does not exist and cannot be created
    -  235   -
          */
    -  236   -
         private static boolean h2DataFileExists() throws IOException {
    -  237  2
             final File dir = Settings.getDataDirectory();
    -  238  2
             final String fileName = Settings.getString(Settings.KEYS.DB_FILE_NAME);
    -  239  2
             final File file = new File(dir, fileName);
    -  240  2
             return file.exists();
    -  241  
         }
    +  235   +
     
    +  236   +
         /**
    +  237   +
          * Determines if the H2 database file exists. If it does not exist then the
    +  238   +
          * data structure will need to be created.
    +  239   +
          *
    +  240   +
          * @return true if the H2 database file does not exist; otherwise false
    +  241   +
          * @throws IOException thrown if the data directory does not exist and
     242   -
     
    +
          * cannot be created
     243   -
         /**
    +
          */
     244   -
          * Creates the database structure (tables and indexes) to store the CVE data.
    -  245   -
          *
    -  246   -
          * @param conn the database connection
    -  247   -
          * @throws DatabaseException thrown if there is a Database Exception
    -  248   -
          */
    +
         private static boolean h2DataFileExists() throws IOException {
    +  245  2
             final File dir = Settings.getDataDirectory();
    +  246  2
             final String fileName = Settings.getString(Settings.KEYS.DB_FILE_NAME);
    +  247  2
             final File file = new File(dir, fileName);
    +  248  2
             return file.exists();
     249   -
         private static void createTables(Connection conn) throws DatabaseException {
    -  250  0
             LOGGER.debug("Creating database structure");
    -  251  0
             InputStream is = null;
    +
         }
    +  250   +
     
    +  251   +
         /**
     252   -
             try {
    -  253  0
                 is = ConnectionFactory.class.getClassLoader().getResourceAsStream(DB_STRUCTURE_RESOURCE);
    -  254  0
                 final String dbStructure = IOUtils.toString(is, "UTF-8");
    +
          * Creates the database structure (tables and indexes) to store the CVE
    +  253   +
          * data.
    +  254   +
          *
     255   -
     
    -  256  0
                 Statement statement = null;
    +
          * @param conn the database connection
    +  256   +
          * @throws DatabaseException thrown if there is a Database Exception
     257   +
          */
    +  258   +
         private static void createTables(Connection conn) throws DatabaseException {
    +  259  0
             LOGGER.debug("Creating database structure");
    +  260  0
             InputStream is = null;
    +  261   +
             try {
    +  262  0
                 is = ConnectionFactory.class.getClassLoader().getResourceAsStream(DB_STRUCTURE_RESOURCE);
    +  263  0
                 final String dbStructure = IOUtils.toString(is, "UTF-8");
    +  264   +
     
    +  265  0
                 Statement statement = null;
    +  266  
                 try {
    -  258  0
                     statement = conn.createStatement();
    -  259  0
                     statement.execute(dbStructure);
    -  260  0
                 } catch (SQLException ex) {
    -  261  0
                     LOGGER.debug("", ex);
    -  262  0
                     throw new DatabaseException("Unable to create database statement", ex);
    -  263   -
                 } finally {
    -  264  0
                     DBUtils.closeStatement(statement);
    -  265  0
                 }
    -  266  0
             } catch (IOException ex) {
    -  267  0
                 throw new DatabaseException("Unable to create database schema", ex);
    -  268   -
             } finally {
    -  269  0
                 IOUtils.closeQuietly(is);
    -  270  0
             }
    -  271  0
         }
    +  267  0
                     statement = conn.createStatement();
    +  268  0
                     statement.execute(dbStructure);
    +  269  0
                 } catch (SQLException ex) {
    +  270  0
                     LOGGER.debug("", ex);
    +  271  0
                     throw new DatabaseException("Unable to create database statement", ex);
     272   -
     
    -  273   -
         /**
    -  274   -
          * Updates the database schema by loading the upgrade script for the version specified. The intended use is that if the
    -  275   -
          * current schema version is 2.9 then we would call updateSchema(conn, "2.9"). This would load the upgrade_2.9.sql file and
    -  276   -
          * execute it against the database. The upgrade script must update the 'version' in the properties table.
    -  277   -
          *
    -  278   -
          * @param conn the database connection object
    -  279   -
          * @param appExpectedVersion the schema version that the application expects
    -  280   -
          * @param currentDbVersion the current schema version of the database
    -  281   -
          * @throws DatabaseException thrown if there is an exception upgrading the database schema
    -  282   -
          */
    -  283   -
         private static void updateSchema(Connection conn, DependencyVersion appExpectedVersion, DependencyVersion currentDbVersion)
    -  284   -
                 throws DatabaseException {
    -  285   -
     
    -  286   -
             final String databaseProductName;
    -  287   -
             try {
    -  288  0
                 databaseProductName = conn.getMetaData().getDatabaseProductName();
    -  289  0
             } catch (SQLException ex) {
    -  290  0
                 throw new DatabaseException("Unable to get the database product name");
    -  291  0
             }
    -  292  0
             if ("h2".equalsIgnoreCase(databaseProductName)) {
    -  293  0
                 LOGGER.debug("Updating database structure");
    -  294  0
                 InputStream is = null;
    -  295  0
                 String updateFile = null;
    -  296   -
                 try {
    -  297  0
                     updateFile = String.format(DB_STRUCTURE_UPDATE_RESOURCE, currentDbVersion.toString());
    -  298  0
                     is = ConnectionFactory.class.getClassLoader().getResourceAsStream(updateFile);
    -  299  0
                     if (is == null) {
    -  300  0
                         throw new DatabaseException(String.format("Unable to load update file '%s'", updateFile));
    -  301   -
                     }
    -  302  0
                     final String dbStructureUpdate = IOUtils.toString(is, "UTF-8");
    -  303   -
     
    -  304  0
                     Statement statement = null;
    -  305   -
                     try {
    -  306  0
                         statement = conn.createStatement();
    -  307  0
                         final boolean success = statement.execute(dbStructureUpdate);
    -  308  0
                         if (!success && statement.getUpdateCount() <= 0) {
    -  309  0
                             throw new DatabaseException(String.format("Unable to upgrade the database schema to %s",
    -  310  0
                                     currentDbVersion.toString()));
    -  311   -
                         }
    -  312  0
                     } catch (SQLException ex) {
    -  313  0
                         LOGGER.debug("", ex);
    -  314  0
                         throw new DatabaseException("Unable to update database schema", ex);
    -  315   -
                     } finally {
    -  316  0
                         DBUtils.closeStatement(statement);
    -  317  0
                     }
    -  318  0
                 } catch (IOException ex) {
    -  319  0
                     final String msg = String.format("Upgrade SQL file does not exist: %s", updateFile);
    -  320  0
                     throw new DatabaseException(msg, ex);
    -  321  
                 } finally {
    -  322  0
                     IOUtils.closeQuietly(is);
    -  323  0
                 }
    -  324  0
             } else {
    -  325  0
                 final int e0 = Integer.parseInt(appExpectedVersion.getVersionParts().get(0));
    -  326  0
                 final int c0 = Integer.parseInt(currentDbVersion.getVersionParts().get(0));
    -  327  0
                 final int e1 = Integer.parseInt(appExpectedVersion.getVersionParts().get(1));
    -  328  0
                 final int c1 = Integer.parseInt(currentDbVersion.getVersionParts().get(1));
    -  329  0
                 if (e0 == c0 && e1 < c1) {
    -  330  0
                     LOGGER.warn("A new version of dependency-check is available; consider upgrading");
    -  331  0
                     Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
    -  332  0
                 } else if (e0 == c0 && e1 == c1) {
    -  333   -
                     //do nothing - not sure how we got here, but just incase...
    -  334   -
                 } else {
    -  335  0
                     LOGGER.error("The database schema must be upgraded to use this version of dependency-check. Please see {} for more information.",
    -  336   -
                             UPGRADE_HELP_URL);
    -  337  0
                     throw new DatabaseException("Database schema is out of date");
    -  338   -
                 }
    -  339   -
             }
    -  340  0
         }
    -  341   -
     
    -  342   -
         /**
    -  343   -
          * Counter to ensure that calls to ensureSchemaVersion does not end up in an endless loop.
    -  344   -
          */
    -  345  1
         private static int callDepth = 0;
    -  346   -
     
    -  347   -
         /**
    -  348   -
          * Uses the provided connection to check the specified schema version within the database.
    -  349   -
          *
    -  350   -
          * @param conn the database connection object
    -  351   -
          * @throws DatabaseException thrown if the schema version is not compatible with this version of dependency-check
    -  352   -
          */
    -  353   -
         private static void ensureSchemaVersion(Connection conn) throws DatabaseException {
    -  354  2
             ResultSet rs = null;
    -  355  2
             PreparedStatement ps = null;
    -  356   -
             try {
    -  357   -
                 //TODO convert this to use DatabaseProperties
    -  358  2
                 ps = conn.prepareStatement("SELECT value FROM properties WHERE id = 'version'");
    -  359  2
                 rs = ps.executeQuery();
    -  360  2
                 if (rs.next()) {
    -  361  2
                     final DependencyVersion appDbVersion = DependencyVersionUtil.parseVersion(DB_SCHEMA_VERSION);
    -  362  2
                     final DependencyVersion db = DependencyVersionUtil.parseVersion(rs.getString(1));
    -  363  2
                     if (appDbVersion.compareTo(db) > 0) {
    -  364  0
                         LOGGER.debug("Current Schema: {}", DB_SCHEMA_VERSION);
    -  365  0
                         LOGGER.debug("DB Schema: {}", rs.getString(1));
    -  366  0
                         updateSchema(conn, appDbVersion, db);
    -  367  0
                         if (++callDepth < 10) {
    -  368  0
                             ensureSchemaVersion(conn);
    -  369   -
                         }
    -  370   -
                     }
    -  371  2
                 } else {
    -  372  0
                     throw new DatabaseException("Database schema is missing");
    -  373   -
                 }
    -  374  0
             } catch (SQLException ex) {
    -  375  0
                 LOGGER.debug("", ex);
    -  376  0
                 throw new DatabaseException("Unable to check the database schema version");
    -  377   +  273  0
                     DBUtils.closeStatement(statement);
    +  274  0
                 }
    +  275  0
             } catch (IOException ex) {
    +  276  0
                 throw new DatabaseException("Unable to create database schema", ex);
    +  277  
             } finally {
    -  378  2
                 DBUtils.closeResultSet(rs);
    -  379  2
                 DBUtils.closeStatement(ps);
    -  380  2
             }
    -  381  2
         }
    -  382   +  278  0
                 IOUtils.closeQuietly(is);
    +  279  0
             }
    +  280  0
         }
    +  281   +
     
    +  282   +
         /**
    +  283   +
          * Updates the database schema by loading the upgrade script for the version
    +  284   +
          * specified. The intended use is that if the current schema version is 2.9
    +  285   +
          * then we would call updateSchema(conn, "2.9"). This would load the
    +  286   +
          * upgrade_2.9.sql file and execute it against the database. The upgrade
    +  287   +
          * script must update the 'version' in the properties table.
    +  288   +
          *
    +  289   +
          * @param conn the database connection object
    +  290   +
          * @param appExpectedVersion the schema version that the application expects
    +  291   +
          * @param currentDbVersion the current schema version of the database
    +  292   +
          * @throws DatabaseException thrown if there is an exception upgrading the
    +  293   +
          * database schema
    +  294   +
          */
    +  295   +
         private static void updateSchema(Connection conn, DependencyVersion appExpectedVersion, DependencyVersion currentDbVersion)
    +  296   +
                 throws DatabaseException {
    +  297   +
     
    +  298   +
             final String databaseProductName;
    +  299   +
             try {
    +  300  0
                 databaseProductName = conn.getMetaData().getDatabaseProductName();
    +  301  0
             } catch (SQLException ex) {
    +  302  0
                 throw new DatabaseException("Unable to get the database product name");
    +  303  0
             }
    +  304  0
             if ("h2".equalsIgnoreCase(databaseProductName)) {
    +  305  0
                 LOGGER.debug("Updating database structure");
    +  306  0
                 InputStream is = null;
    +  307  0
                 String updateFile = null;
    +  308   +
                 try {
    +  309  0
                     updateFile = String.format(DB_STRUCTURE_UPDATE_RESOURCE, currentDbVersion.toString());
    +  310  0
                     is = ConnectionFactory.class.getClassLoader().getResourceAsStream(updateFile);
    +  311  0
                     if (is == null) {
    +  312  0
                         throw new DatabaseException(String.format("Unable to load update file '%s'", updateFile));
    +  313   +
                     }
    +  314  0
                     final String dbStructureUpdate = IOUtils.toString(is, "UTF-8");
    +  315   +
     
    +  316  0
                     Statement statement = null;
    +  317   +
                     try {
    +  318  0
                         statement = conn.createStatement();
    +  319  0
                         final boolean success = statement.execute(dbStructureUpdate);
    +  320  0
                         if (!success && statement.getUpdateCount() <= 0) {
    +  321  0
                             throw new DatabaseException(String.format("Unable to upgrade the database schema to %s",
    +  322  0
                                     currentDbVersion.toString()));
    +  323   +
                         }
    +  324  0
                     } catch (SQLException ex) {
    +  325  0
                         LOGGER.debug("", ex);
    +  326  0
                         throw new DatabaseException("Unable to update database schema", ex);
    +  327   +
                     } finally {
    +  328  0
                         DBUtils.closeStatement(statement);
    +  329  0
                     }
    +  330  0
                 } catch (IOException ex) {
    +  331  0
                     final String msg = String.format("Upgrade SQL file does not exist: %s", updateFile);
    +  332  0
                     throw new DatabaseException(msg, ex);
    +  333   +
                 } finally {
    +  334  0
                     IOUtils.closeQuietly(is);
    +  335  0
                 }
    +  336  0
             } else {
    +  337  0
                 final int e0 = Integer.parseInt(appExpectedVersion.getVersionParts().get(0));
    +  338  0
                 final int c0 = Integer.parseInt(currentDbVersion.getVersionParts().get(0));
    +  339  0
                 final int e1 = Integer.parseInt(appExpectedVersion.getVersionParts().get(1));
    +  340  0
                 final int c1 = Integer.parseInt(currentDbVersion.getVersionParts().get(1));
    +  341  0
                 if (e0 == c0 && e1 < c1) {
    +  342  0
                     LOGGER.warn("A new version of dependency-check is available; consider upgrading");
    +  343  0
                     Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
    +  344  0
                 } else if (e0 == c0 && e1 == c1) {
    +  345   +
                     //do nothing - not sure how we got here, but just incase...
    +  346   +
                 } else {
    +  347  0
                     LOGGER.error("The database schema must be upgraded to use this version of dependency-check. Please see {} for more information.",
    +  348   +
                             UPGRADE_HELP_URL);
    +  349  0
                     throw new DatabaseException("Database schema is out of date");
    +  350   +
                 }
    +  351   +
             }
    +  352  0
         }
    +  353   +
     
    +  354   +
         /**
    +  355   +
          * Counter to ensure that calls to ensureSchemaVersion does not end up in an
    +  356   +
          * endless loop.
    +  357   +
          */
    +  358  1
         private static int callDepth = 0;
    +  359   +
     
    +  360   +
         /**
    +  361   +
          * Uses the provided connection to check the specified schema version within
    +  362   +
          * the database.
    +  363   +
          *
    +  364   +
          * @param conn the database connection object
    +  365   +
          * @throws DatabaseException thrown if the schema version is not compatible
    +  366   +
          * with this version of dependency-check
    +  367   +
          */
    +  368   +
         private static void ensureSchemaVersion(Connection conn) throws DatabaseException {
    +  369  2
             ResultSet rs = null;
    +  370  2
             PreparedStatement ps = null;
    +  371   +
             try {
    +  372   +
                 //TODO convert this to use DatabaseProperties
    +  373  2
                 ps = conn.prepareStatement("SELECT value FROM properties WHERE id = 'version'");
    +  374  2
                 rs = ps.executeQuery();
    +  375  2
                 if (rs.next()) {
    +  376  2
                     final DependencyVersion appDbVersion = DependencyVersionUtil.parseVersion(DB_SCHEMA_VERSION);
    +  377  2
                     if (appDbVersion == null) {
    +  378  0
                         throw new DatabaseException("Invalid application database schema");
    +  379   +
                     }
    +  380  2
                     final DependencyVersion db = DependencyVersionUtil.parseVersion(rs.getString(1));
    +  381  2
                     if (db == null) {
    +  382  0
                         throw new DatabaseException("Invalid database schema");
    +  383   +
                     }
    +  384  2
                     if (appDbVersion.compareTo(db) > 0) {
    +  385  0
                         LOGGER.debug("Current Schema: {}", DB_SCHEMA_VERSION);
    +  386  0
                         LOGGER.debug("DB Schema: {}", rs.getString(1));
    +  387  0
                         updateSchema(conn, appDbVersion, db);
    +  388  0
                         if (++callDepth < 10) {
    +  389  0
                             ensureSchemaVersion(conn);
    +  390   +
                         }
    +  391   +
                     }
    +  392  2
                 } else {
    +  393  0
                     throw new DatabaseException("Database schema is missing");
    +  394   +
                 }
    +  395  0
             } catch (SQLException ex) {
    +  396  0
                 LOGGER.debug("", ex);
    +  397  0
                 throw new DatabaseException("Unable to check the database schema version");
    +  398   +
             } finally {
    +  399  2
                 DBUtils.closeResultSet(rs);
    +  400  2
                 DBUtils.closeStatement(ps);
    +  401  2
             }
    +  402  2
         }
    +  403  
     }
    - + 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 3d1c721f4..a25963e0a 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 10fbad8ab..ea7f55c29 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 @@ -12,7 +12,7 @@
     
    - +
    Classes in this File Line Coverage Branch Coverage Complexity
    CveDB
    46%
    201/436
    52%
    73/138
    5.591
    CveDB
    45%
    201/437
    52%
    74/140
    5.636
     
    @@ -190,1097 +190,1100 @@  88  
                 try {
     89  13
                     final String databaseProductName = conn.getMetaData().getDatabaseProductName();
    -  90  13
                     batchSupported = conn.getMetaData().supportsBatchUpdates();
    -  91  13
                     LOGGER.debug("Database dialect: {}", databaseProductName);
    -  92  13
                     final Locale dbDialect = new Locale(databaseProductName);
    -  93  13
                     statementBundle = ResourceBundle.getBundle("data/dbStatements", dbDialect);
    -  94  0
                 } catch (SQLException se) {
    -  95  0
                     LOGGER.warn("Problem loading database specific dialect!", se);
    -  96  0
                     statementBundle = ResourceBundle.getBundle("data/dbStatements");
    -  97  13
                 }
    -  98  13
                 databaseProperties = new DatabaseProperties(this);
    -  99  0
             } catch (DatabaseException ex) {
    -  100  0
                 throw ex;
    -  101  13
             }
    -  102  13
         }
    -  103   -
     
    -  104   -
         /**
    +  90  13
                     LOGGER.debug("Database dialect: {}", databaseProductName);
    +  91  13
                     final Locale dbDialect = new Locale(databaseProductName);
    +  92  13
                     statementBundle = ResourceBundle.getBundle("data/dbStatements", dbDialect);
    +  93  13
                     if ("mysql".equalsIgnoreCase(databaseProductName)) {
    +  94  0
                         batchSupported = false;
    +  95   +
                     }
    +  96  0
                 } catch (SQLException se) {
    +  97  0
                     LOGGER.warn("Problem loading database specific dialect!", se);
    +  98  0
                     statementBundle = ResourceBundle.getBundle("data/dbStatements");
    +  99  13
                 }
    +  100  13
                 databaseProperties = new DatabaseProperties(this);
    +  101  0
             } catch (DatabaseException ex) {
    +  102  0
                 throw ex;
    +  103  13
             }
    +  104  13
         }
     105   -
          * Returns the database connection.
    +
     
     106   -
          *
    +
         /**
     107   -
          * @return the database connection
    +
          * Returns the database connection.
     108   -
          */
    +
          *
     109   -
         protected Connection getConnection() {
    -  110  45
             return conn;
    +
          * @return the database connection
    +  110   +
          */
     111   -
         }
    -  112   -
     
    +
         protected Connection getConnection() {
    +  112  45
             return conn;
     113   -
         /**
    +
         }
     114   -
          * Opens the database connection. If the database does not exist, it will
    +
     
     115   -
          * create a new one.
    +
         /**
     116   -
          *
    +
          * Opens the database connection. If the database does not exist, it will
     117   -
          * @throws DatabaseException thrown if there is an error opening the
    +
          * create a new one.
     118   -
          * database connection
    +
          *
     119   -
          */
    +
          * @throws DatabaseException thrown if there is an error opening the
     120   +
          * database connection
    +  121   +
          */
    +  122  
         public final void open() throws DatabaseException {
    -  121  26
             if (!isOpen()) {
    -  122  13
                 conn = ConnectionFactory.getConnection();
    -  123   -
             }
    -  124  26
         }
    +  123  26
             if (!isOpen()) {
    +  124  13
                 conn = ConnectionFactory.getConnection();
     125   -
     
    -  126   -
         /**
    -  127   -
          * Closes the DB4O database. Close should be called on this object when it
    -  128   -
          * is done being used.
    -  129   -
          */
    -  130   -
         public void close() {
    -  131  25
             if (conn != null) {
    -  132   -
                 try {
    -  133  13
                     conn.close();
    -  134  0
                 } catch (SQLException ex) {
    -  135  0
                     LOGGER.error("There was an error attempting to close the CveDB, see the log for more details.");
    -  136  0
                     LOGGER.debug("", ex);
    -  137  0
                 } catch (Throwable ex) {
    -  138  0
                     LOGGER.error("There was an exception attempting to close the CveDB, see the log for more details.");
    -  139  0
                     LOGGER.debug("", ex);
    -  140  13
                 }
    -  141  13
                 conn = null;
    -  142  
             }
    -  143  25
         }
    +  126  26
         }
    +  127   +
     
    +  128   +
         /**
    +  129   +
          * Closes the DB4O database. Close should be called on this object when it
    +  130   +
          * is done being used.
    +  131   +
          */
    +  132   +
         public void close() {
    +  133  26
             if (conn != null) {
    +  134   +
                 try {
    +  135  13
                     conn.close();
    +  136  0
                 } catch (SQLException ex) {
    +  137  0
                     LOGGER.error("There was an error attempting to close the CveDB, see the log for more details.");
    +  138  0
                     LOGGER.debug("", ex);
    +  139  0
                 } catch (Throwable ex) {
    +  140  0
                     LOGGER.error("There was an exception attempting to close the CveDB, see the log for more details.");
    +  141  0
                     LOGGER.debug("", ex);
    +  142  13
                 }
    +  143  13
                 conn = null;
     144   -
     
    -  145   -
         /**
    +
             }
    +  145  26
         }
     146   -
          * Returns whether the database connection is open or closed.
    +
     
     147   -
          *
    +
         /**
     148   -
          * @return whether the database connection is open or closed
    +
          * Returns whether the database connection is open or closed.
     149   -
          */
    +
          *
     150   -
         public boolean isOpen() {
    -  151  26
             return conn != null;
    +
          * @return whether the database connection is open or closed
    +  151   +
          */
     152   -
         }
    -  153   -
     
    +
         public boolean isOpen() {
    +  153  26
             return conn != null;
     154   -
         /**
    +
         }
     155   -
          * Commits all completed transactions.
    +
     
     156   -
          *
    +
         /**
     157   -
          * @throws SQLException thrown if a SQL Exception occurs
    +
          * Commits all completed transactions.
     158   -
          */
    +
          *
     159   -
         public void commit() throws SQLException {
    +
          * @throws SQLException thrown if a SQL Exception occurs
     160   -
             //temporary remove this as autocommit is on.
    +
          */
     161   -
             //if (conn != null) {
    +
         public void commit() throws SQLException {
     162   -
             //    conn.commit();
    +
             //temporary remove this as autocommit is on.
     163   -
             //}
    -  164  0
         }
    +
             //if (conn != null) {
    +  164   +
             //    conn.commit();
     165   -
     
    -  166   -
         /**
    +
             //}
    +  166  0
         }
     167   -
          * Cleans up the object and ensures that "close" has been called.
    +
     
     168   -
          *
    +
         /**
     169   -
          * @throws Throwable thrown if there is a problem
    +
          * Cleans up the object and ensures that "close" has been called.
     170   -
          */
    +
          *
     171   -
         @Override
    +
          * @throws Throwable thrown if there is a problem
     172   -
         @SuppressWarnings("FinalizeDeclaration")
    +
          */
     173   +
         @Override
    +  174   +
         @SuppressWarnings("FinalizeDeclaration")
    +  175  
         protected void finalize() throws Throwable {
    -  174  12
             LOGGER.debug("Entering finalize");
    -  175  12
             close();
    -  176  12
             super.finalize();
    -  177  12
         }
    -  178   -
         /**
    -  179   -
          * Database properties object containing the 'properties' from the database
    +  176  13
             LOGGER.debug("Entering finalize");
    +  177  13
             close();
    +  178  13
             super.finalize();
    +  179  13
         }
     180   -
          * table.
    +
         /**
     181   -
          */
    +
          * Database properties object containing the 'properties' from the database
     182   -
         private DatabaseProperties databaseProperties;
    +
          * table.
     183   -
     
    +
          */
     184   -
         /**
    +
         private DatabaseProperties databaseProperties;
     185   -
          * Get the value of databaseProperties.
    +
     
     186   -
          *
    +
         /**
     187   -
          * @return the value of databaseProperties
    +
          * Get the value of databaseProperties.
     188   -
          */
    +
          *
     189   -
         public DatabaseProperties getDatabaseProperties() {
    -  190  3
             return databaseProperties;
    +
          * @return the value of databaseProperties
    +  190   +
          */
     191   -
         }
    -  192   -
     
    +
         public DatabaseProperties getDatabaseProperties() {
    +  192  3
             return databaseProperties;
     193   -
         /**
    +
         }
     194   -
          * Searches the CPE entries in the database and retrieves all entries for a
    +
     
     195   -
          * given vendor and product combination. The returned list will include all
    +
         /**
     196   -
          * versions of the product that are registered in the NVD CVE data.
    +
          * Searches the CPE entries in the database and retrieves all entries for a
     197   -
          *
    +
          * given vendor and product combination. The returned list will include all
     198   -
          * @param vendor the identified vendor name of the dependency being analyzed
    +
          * versions of the product that are registered in the NVD CVE data.
     199   -
          * @param product the identified name of the product of the dependency being
    +
          *
     200   -
          * analyzed
    +
          * @param vendor the identified vendor name of the dependency being analyzed
     201   -
          * @return a set of vulnerable software
    +
          * @param product the identified name of the product of the dependency being
     202   -
          */
    -  203   -
         public Set<VulnerableSoftware> getCPEs(String vendor, String product) {
    -  204  3
             final Set<VulnerableSoftware> cpe = new HashSet<VulnerableSoftware>();
    -  205  3
             ResultSet rs = null;
    -  206  3
             PreparedStatement ps = null;
    -  207   -
             try {
    -  208  3
                 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_CPE_ENTRIES"));
    -  209  3
                 ps.setString(1, vendor);
    -  210  3
                 ps.setString(2, product);
    -  211  3
                 rs = ps.executeQuery();
    -  212   -
     
    -  213  112
                 while (rs.next()) {
    -  214  109
                     final VulnerableSoftware vs = new VulnerableSoftware();
    -  215  109
                     vs.setCpe(rs.getString(1));
    -  216  109
                     cpe.add(vs);
    -  217  109
                 }
    -  218  0
             } catch (SQLException ex) {
    -  219  0
                 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details.");
    -  220  0
                 LOGGER.debug("", ex);
    -  221   -
             } finally {
    -  222  3
                 DBUtils.closeResultSet(rs);
    -  223  3
                 DBUtils.closeStatement(ps);
    -  224  3
             }
    -  225  3
             return cpe;
    -  226   -
         }
    -  227   -
     
    -  228   -
         /**
    -  229   -
          * Returns the entire list of vendor/product combinations.
    -  230   -
          *
    -  231   -
          * @return the entire list of vendor/product combinations
    -  232   -
          * @throws DatabaseException thrown when there is an error retrieving the
    -  233   -
          * data from the DB
    -  234   -
          */
    -  235   -
         public Set<Pair<String, String>> getVendorProductList() throws DatabaseException {
    -  236  2
             final Set<Pair<String, String>> data = new HashSet<Pair<String, String>>();
    -  237  2
             ResultSet rs = null;
    -  238  2
             PreparedStatement ps = null;
    -  239   -
             try {
    -  240  2
                 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_VENDOR_PRODUCT_LIST"));
    -  241  2
                 rs = ps.executeQuery();
    -  242  52140
                 while (rs.next()) {
    -  243  52138
                     data.add(new Pair<String, String>(rs.getString(1), rs.getString(2)));
    -  244   -
                 }
    -  245  0
             } catch (SQLException ex) {
    -  246  0
                 final String msg = "An unexpected SQL Exception occurred; please see the verbose log for more details.";
    -  247  0
                 throw new DatabaseException(msg, ex);
    -  248   -
             } finally {
    -  249  2
                 DBUtils.closeResultSet(rs);
    -  250  2
                 DBUtils.closeStatement(ps);
    -  251  2
             }
    -  252  2
             return data;
    -  253   -
         }
    -  254   -
     
    -  255   -
         /**
    -  256   -
          * Returns a set of properties.
    -  257   -
          *
    -  258   -
          * @return the properties from the database
    -  259   -
          */
    -  260   -
         Properties getProperties() {
    -  261  13
             final Properties prop = new Properties();
    -  262  13
             PreparedStatement ps = null;
    -  263  13
             ResultSet rs = null;
    -  264   -
             try {
    -  265  13
                 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_PROPERTIES"));
    -  266  13
                 rs = ps.executeQuery();
    -  267  273
                 while (rs.next()) {
    -  268  260
                     prop.setProperty(rs.getString(1), rs.getString(2));
    -  269   -
                 }
    -  270  0
             } catch (SQLException ex) {
    -  271  0
                 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details.");
    -  272  0
                 LOGGER.debug("", ex);
    -  273   -
             } finally {
    -  274  13
                 DBUtils.closeStatement(ps);
    -  275  13
                 DBUtils.closeResultSet(rs);
    -  276  13
             }
    -  277  13
             return prop;
    -  278   -
         }
    -  279   -
     
    -  280   -
         /**
    -  281   -
          * Saves a property to the database.
    -  282   -
          *
    -  283   -
          * @param key the property key
    -  284   -
          * @param value the property value
    -  285   -
          */
    -  286   -
         void saveProperty(String key, String value) {
    -  287   -
             try {
    -  288   -
                 try {
    -  289  0
                     final PreparedStatement mergeProperty = getConnection().prepareStatement(statementBundle.getString("MERGE_PROPERTY"));
    -  290   -
                     try {
    -  291  0
                         mergeProperty.setString(1, key);
    -  292  0
                         mergeProperty.setString(2, value);
    -  293  0
                         mergeProperty.executeUpdate();
    -  294   -
                     } finally {
    -  295  0
                         DBUtils.closeStatement(mergeProperty);
    -  296  0
                     }
    -  297  0
                 } catch (MissingResourceException mre) {
    -  298   -
                     // No Merge statement, so doing an Update/Insert...
    -  299  0
                     PreparedStatement updateProperty = null;
    -  300  0
                     PreparedStatement insertProperty = null;
    -  301   -
                     try {
    -  302  0
                         updateProperty = getConnection().prepareStatement(statementBundle.getString("UPDATE_PROPERTY"));
    -  303  0
                         updateProperty.setString(1, value);
    -  304  0
                         updateProperty.setString(2, key);
    -  305  0
                         if (updateProperty.executeUpdate() == 0) {
    -  306  0
                             insertProperty = getConnection().prepareStatement(statementBundle.getString("INSERT_PROPERTY"));
    -  307  0
                             insertProperty.setString(1, key);
    -  308  0
                             insertProperty.setString(2, value);
    -  309  0
                             insertProperty.executeUpdate();
    -  310   -
                         }
    -  311   -
                     } finally {
    -  312  0
                         DBUtils.closeStatement(updateProperty);
    -  313  0
                         DBUtils.closeStatement(insertProperty);
    -  314  0
                     }
    -  315  0
                 }
    -  316  0
             } catch (SQLException ex) {
    -  317  0
                 LOGGER.warn("Unable to save property '{}' with a value of '{}' to the database", key, value);
    -  318  0
                 LOGGER.debug("", ex);
    -  319  0
             }
    -  320  0
         }
    -  321   -
     
    -  322   -
         /**
    -  323   -
          * Retrieves the vulnerabilities associated with the specified CPE.
    -  324   -
          *
    -  325   -
          * @param cpeStr the CPE name
    -  326   -
          * @return a list of Vulnerabilities
    -  327   -
          * @throws DatabaseException thrown if there is an exception retrieving data
    -  328   -
          */
    -  329   -
         public List<Vulnerability> getVulnerabilities(String cpeStr) throws DatabaseException {
    -  330  3
             final VulnerableSoftware cpe = new VulnerableSoftware();
    -  331   -
             try {
    -  332  3
                 cpe.parseName(cpeStr);
    -  333  0
             } catch (UnsupportedEncodingException ex) {
    -  334  0
                 LOGGER.trace("", ex);
    -  335  3
             }
    -  336  3
             final DependencyVersion detectedVersion = parseDependencyVersion(cpe);
    -  337  3
             final List<Vulnerability> vulnerabilities = new ArrayList<Vulnerability>();
    -  338   -
     
    -  339  3
             PreparedStatement ps = null;
    -  340  3
             ResultSet rs = null;
    -  341   -
             try {
    -  342  3
                 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_CVE_FROM_SOFTWARE"));
    -  343  3
                 ps.setString(1, cpe.getVendor());
    -  344  3
                 ps.setString(2, cpe.getProduct());
    -  345  3
                 rs = ps.executeQuery();
    -  346  3
                 String currentCVE = "";
    -  347   -
     
    -  348  3
                 final Map<String, Boolean> vulnSoftware = new HashMap<String, Boolean>();
    -  349  282
                 while (rs.next()) {
    -  350  279
                     final String cveId = rs.getString(1);
    -  351  279
                     if (!currentCVE.equals(cveId)) { //check for match and add
    -  352  10
                         final Entry<String, Boolean> matchedCPE = getMatchingSoftware(vulnSoftware, cpe.getVendor(), cpe.getProduct(), detectedVersion);
    -  353  10
                         if (matchedCPE != null) {
    -  354  6
                             final Vulnerability v = getVulnerability(currentCVE);
    -  355  6
                             v.setMatchedCPE(matchedCPE.getKey(), matchedCPE.getValue() ? "Y" : null);
    -  356  6
                             vulnerabilities.add(v);
    -  357   -
                         }
    -  358  10
                         vulnSoftware.clear();
    -  359  10
                         currentCVE = cveId;
    -  360   -
                     }
    -  361   -
     
    -  362  279
                     final String cpeId = rs.getString(2);
    -  363  279
                     final String previous = rs.getString(3);
    -  364  279
                     final Boolean p = previous != null && !previous.isEmpty();
    -  365  279
                     vulnSoftware.put(cpeId, p);
    -  366  279
                 }
    -  367   -
                 //remember to process the last set of CVE/CPE entries
    -  368  3
                 final Entry<String, Boolean> matchedCPE = getMatchingSoftware(vulnSoftware, cpe.getVendor(), cpe.getProduct(), detectedVersion);
    -  369  3
                 if (matchedCPE != null) {
    -  370  2
                     final Vulnerability v = getVulnerability(currentCVE);
    -  371  2
                     v.setMatchedCPE(matchedCPE.getKey(), matchedCPE.getValue() ? "Y" : null);
    -  372  2
                     vulnerabilities.add(v);
    -  373   -
                 }
    -  374  0
             } catch (SQLException ex) {
    -  375  0
                 throw new DatabaseException("Exception retrieving vulnerability for " + cpeStr, ex);
    -  376   -
             } finally {
    -  377  3
                 DBUtils.closeResultSet(rs);
    -  378  3
                 DBUtils.closeStatement(ps);
    -  379  3
             }
    -  380  3
             return vulnerabilities;
    -  381   -
         }
    -  382   -
     
    -  383   -
         /**
    -  384   -
          * Gets a vulnerability for the provided CVE.
    -  385   -
          *
    -  386   -
          * @param cve the CVE to lookup
    -  387   -
          * @return a vulnerability object
    -  388   -
          * @throws DatabaseException if an exception occurs
    -  389   -
          */
    -  390   -
         public Vulnerability getVulnerability(String cve) throws DatabaseException {
    -  391  8
             PreparedStatement psV = null;
    -  392  8
             PreparedStatement psR = null;
    -  393  8
             PreparedStatement psS = null;
    -  394  8
             ResultSet rsV = null;
    -  395  8
             ResultSet rsR = null;
    -  396  8
             ResultSet rsS = null;
    -  397  8
             Vulnerability vuln = null;
    -  398   -
     
    -  399   -
             try {
    -  400  8
                 psV = getConnection().prepareStatement(statementBundle.getString("SELECT_VULNERABILITY"));
    -  401  8
                 psV.setString(1, cve);
    -  402  8
                 rsV = psV.executeQuery();
    -  403  8
                 if (rsV.next()) {
    -  404  8
                     vuln = new Vulnerability();
    -  405  8
                     vuln.setName(cve);
    -  406  8
                     vuln.setDescription(rsV.getString(2));
    -  407  8
                     String cwe = rsV.getString(3);
    -  408  8
                     if (cwe != null) {
    -  409  8
                         final String name = CweDB.getCweName(cwe);
    -  410  8
                         if (name != null) {
    -  411  7
                             cwe += ' ' + name;
    -  412   -
                         }
    -  413   -
                     }
    -  414  8
                     final int cveId = rsV.getInt(1);
    -  415  8
                     vuln.setCwe(cwe);
    -  416  8
                     vuln.setCvssScore(rsV.getFloat(4));
    -  417  8
                     vuln.setCvssAccessVector(rsV.getString(5));
    -  418  8
                     vuln.setCvssAccessComplexity(rsV.getString(6));
    -  419  8
                     vuln.setCvssAuthentication(rsV.getString(7));
    -  420  8
                     vuln.setCvssConfidentialityImpact(rsV.getString(8));
    -  421  8
                     vuln.setCvssIntegrityImpact(rsV.getString(9));
    -  422  8
                     vuln.setCvssAvailabilityImpact(rsV.getString(10));
    -  423   -
     
    -  424  8
                     psR = getConnection().prepareStatement(statementBundle.getString("SELECT_REFERENCES"));
    -  425  8
                     psR.setInt(1, cveId);
    -  426  8
                     rsR = psR.executeQuery();
    -  427  76
                     while (rsR.next()) {
    -  428  68
                         vuln.addReference(rsR.getString(1), rsR.getString(2), rsR.getString(3));
    -  429   -
                     }
    -  430  8
                     psS = getConnection().prepareStatement(statementBundle.getString("SELECT_SOFTWARE"));
    -  431  8
                     psS.setInt(1, cveId);
    -  432  8
                     rsS = psS.executeQuery();
    -  433  244
                     while (rsS.next()) {
    -  434  236
                         final String cpe = rsS.getString(1);
    -  435  236
                         final String prevVersion = rsS.getString(2);
    -  436  236
                         if (prevVersion == null) {
    -  437  228
                             vuln.addVulnerableSoftware(cpe);
    -  438   -
                         } else {
    -  439  8
                             vuln.addVulnerableSoftware(cpe, prevVersion);
    -  440   -
                         }
    -  441  236
                     }
    -  442   -
                 }
    -  443  0
             } catch (SQLException ex) {
    -  444  0
                 throw new DatabaseException("Error retrieving " + cve, ex);
    -  445   -
             } finally {
    -  446  8
                 DBUtils.closeResultSet(rsV);
    -  447  8
                 DBUtils.closeResultSet(rsR);
    -  448  8
                 DBUtils.closeResultSet(rsS);
    -  449  8
                 DBUtils.closeStatement(psV);
    -  450  8
                 DBUtils.closeStatement(psR);
    -  451  8
                 DBUtils.closeStatement(psS);
    -  452  8
             }
    -  453  8
             return vuln;
    -  454   -
         }
    -  455   -
     
    -  456   -
         /**
    -  457   -
          * Updates the vulnerability within the database. If the vulnerability does
    -  458   -
          * not exist it will be added.
    -  459   -
          *
    -  460   -
          * @param vuln the vulnerability to add to the database
    -  461   -
          * @throws DatabaseException is thrown if the database
    -  462   -
          */
    -  463   -
         public void updateVulnerability(Vulnerability vuln) throws DatabaseException {
    -  464  0
             PreparedStatement selectVulnerabilityId = null;
    -  465  0
             PreparedStatement deleteVulnerability = null;
    -  466  0
             PreparedStatement deleteReferences = null;
    -  467  0
             PreparedStatement deleteSoftware = null;
    -  468  0
             PreparedStatement updateVulnerability = null;
    -  469  0
             PreparedStatement insertVulnerability = null;
    -  470  0
             PreparedStatement insertReference = null;
    -  471  0
             PreparedStatement selectCpeId = null;
    -  472  0
             PreparedStatement insertCpe = null;
    -  473  0
             PreparedStatement insertSoftware = null;
    -  474   -
     
    -  475   -
             try {
    -  476  0
                 selectVulnerabilityId = getConnection().prepareStatement(statementBundle.getString("SELECT_VULNERABILITY_ID"));
    -  477  0
                 deleteVulnerability = getConnection().prepareStatement(statementBundle.getString("DELETE_VULNERABILITY"));
    -  478  0
                 deleteReferences = getConnection().prepareStatement(statementBundle.getString("DELETE_REFERENCE"));
    -  479  0
                 deleteSoftware = getConnection().prepareStatement(statementBundle.getString("DELETE_SOFTWARE"));
    -  480  0
                 updateVulnerability = getConnection().prepareStatement(statementBundle.getString("UPDATE_VULNERABILITY"));
    -  481  0
                 final String[] ids = {"id"};
    -  482  0
                 insertVulnerability = getConnection().prepareStatement(statementBundle.getString("INSERT_VULNERABILITY"),
    -  483   -
                         //Statement.RETURN_GENERATED_KEYS);
    -  484   -
                         ids);
    -  485  0
                 insertReference = getConnection().prepareStatement(statementBundle.getString("INSERT_REFERENCE"));
    -  486  0
                 selectCpeId = getConnection().prepareStatement(statementBundle.getString("SELECT_CPE_ID"));
    -  487  0
                 insertCpe = getConnection().prepareStatement(statementBundle.getString("INSERT_CPE"),
    -  488   -
                         //Statement.RETURN_GENERATED_KEYS);
    -  489   -
                         ids);
    -  490  0
                 insertSoftware = getConnection().prepareStatement(statementBundle.getString("INSERT_SOFTWARE"));
    -  491  0
                 int vulnerabilityId = 0;
    -  492  0
                 selectVulnerabilityId.setString(1, vuln.getName());
    -  493  0
                 ResultSet rs = selectVulnerabilityId.executeQuery();
    -  494  0
                 if (rs.next()) {
    -  495  0
                     vulnerabilityId = rs.getInt(1);
    -  496   -
                     // first delete any existing vulnerability info. We don't know what was updated. yes, slower but atm easier.
    -  497  0
                     deleteReferences.setInt(1, vulnerabilityId);
    -  498  0
                     deleteReferences.execute();
    -  499  0
                     deleteSoftware.setInt(1, vulnerabilityId);
    -  500  0
                     deleteSoftware.execute();
    -  501   -
                 }
    -  502  0
                 DBUtils.closeResultSet(rs);
    -  503  0
                 rs = null;
    -  504   -
     
    -  505  0
                 if (vulnerabilityId != 0) {
    -  506  0
                     if (vuln.getDescription().contains("** REJECT **")) {
    -  507  0
                         deleteVulnerability.setInt(1, vulnerabilityId);
    -  508  0
                         deleteVulnerability.executeUpdate();
    -  509   -
                     } else {
    -  510  0
                         updateVulnerability.setString(1, vuln.getDescription());
    -  511  0
                         updateVulnerability.setString(2, vuln.getCwe());
    -  512  0
                         updateVulnerability.setFloat(3, vuln.getCvssScore());
    -  513  0
                         updateVulnerability.setString(4, vuln.getCvssAccessVector());
    -  514  0
                         updateVulnerability.setString(5, vuln.getCvssAccessComplexity());
    -  515  0
                         updateVulnerability.setString(6, vuln.getCvssAuthentication());
    -  516  0
                         updateVulnerability.setString(7, vuln.getCvssConfidentialityImpact());
    -  517  0
                         updateVulnerability.setString(8, vuln.getCvssIntegrityImpact());
    -  518  0
                         updateVulnerability.setString(9, vuln.getCvssAvailabilityImpact());
    -  519  0
                         updateVulnerability.setInt(10, vulnerabilityId);
    -  520  0
                         updateVulnerability.executeUpdate();
    -  521   -
                     }
    -  522   -
                 } else {
    -  523  0
                     insertVulnerability.setString(1, vuln.getName());
    -  524  0
                     insertVulnerability.setString(2, vuln.getDescription());
    -  525  0
                     insertVulnerability.setString(3, vuln.getCwe());
    -  526  0
                     insertVulnerability.setFloat(4, vuln.getCvssScore());
    -  527  0
                     insertVulnerability.setString(5, vuln.getCvssAccessVector());
    -  528  0
                     insertVulnerability.setString(6, vuln.getCvssAccessComplexity());
    -  529  0
                     insertVulnerability.setString(7, vuln.getCvssAuthentication());
    -  530  0
                     insertVulnerability.setString(8, vuln.getCvssConfidentialityImpact());
    -  531  0
                     insertVulnerability.setString(9, vuln.getCvssIntegrityImpact());
    -  532  0
                     insertVulnerability.setString(10, vuln.getCvssAvailabilityImpact());
    -  533  0
                     insertVulnerability.execute();
    -  534   -
                     try {
    -  535  0
                         rs = insertVulnerability.getGeneratedKeys();
    -  536  0
                         rs.next();
    -  537  0
                         vulnerabilityId = rs.getInt(1);
    -  538  0
                     } catch (SQLException ex) {
    -  539  0
                         final String msg = String.format("Unable to retrieve id for new vulnerability for '%s'", vuln.getName());
    -  540  0
                         throw new DatabaseException(msg, ex);
    -  541   -
                     } finally {
    -  542  0
                         DBUtils.closeResultSet(rs);
    -  543  0
                         rs = null;
    -  544  0
                     }
    -  545   -
                 }
    -  546   -
     
    -  547  0
                 for (Reference r : vuln.getReferences()) {
    -  548  0
                     insertReference.setInt(1, vulnerabilityId);
    -  549  0
                     insertReference.setString(2, r.getName());
    -  550  0
                     insertReference.setString(3, r.getUrl());
    -  551  0
                     insertReference.setString(4, r.getSource());
    -  552   -
     
    -  553  0
                     if (batchSupported) {
    -  554  0
                         insertReference.addBatch();
    -  555   -
                     } else {
    -  556  0
                         insertReference.execute();
    -  557   -
                     }
    -  558  0
                 }
    -  559   -
     
    -  560  0
                 if (batchSupported) {
    -  561  0
                     insertReference.executeBatch();
    -  562   -
                 }
    -  563   -
     
    -  564  0
                 for (VulnerableSoftware s : vuln.getVulnerableSoftware()) {
    -  565  0
                     int cpeProductId = 0;
    -  566  0
                     selectCpeId.setString(1, s.getName());
    -  567   -
                     try {
    -  568  0
                         rs = selectCpeId.executeQuery();
    -  569  0
                         if (rs.next()) {
    -  570  0
                             cpeProductId = rs.getInt(1);
    -  571   -
                         }
    -  572  0
                     } catch (SQLException ex) {
    -  573  0
                         throw new DatabaseException("Unable to get primary key for new cpe: " + s.getName(), ex);
    -  574   -
                     } finally {
    -  575  0
                         DBUtils.closeResultSet(rs);
    -  576  0
                         rs = null;
    -  577  0
                     }
    -  578   -
     
    -  579  0
                     if (cpeProductId == 0) {
    -  580  0
                         insertCpe.setString(1, s.getName());
    -  581  0
                         insertCpe.setString(2, s.getVendor());
    -  582  0
                         insertCpe.setString(3, s.getProduct());
    -  583  0
                         insertCpe.executeUpdate();
    -  584  0
                         cpeProductId = DBUtils.getGeneratedKey(insertCpe);
    -  585   -
                     }
    -  586  0
                     if (cpeProductId == 0) {
    -  587  0
                         throw new DatabaseException("Unable to retrieve cpeProductId - no data returned");
    -  588   -
                     }
    -  589   -
     
    -  590  0
                     insertSoftware.setInt(1, vulnerabilityId);
    -  591  0
                     insertSoftware.setInt(2, cpeProductId);
    -  592   -
     
    -  593  0
                     if (s.getPreviousVersion() == null) {
    -  594  0
                         insertSoftware.setNull(3, java.sql.Types.VARCHAR);
    -  595   -
                     } else {
    -  596  0
                         insertSoftware.setString(3, s.getPreviousVersion());
    -  597   -
                     }
    -  598  0
                     if (batchSupported) {
    -  599  0
                         insertSoftware.addBatch();
    -  600   -
                     } else {
    -  601   -
                         try {
    -  602  0
                             insertSoftware.execute();
    -  603  0
                         } catch (SQLException ex) {
    -  604  0
                             if (ex.getMessage().contains("Duplicate entry")) {
    -  605  0
                                 final String msg = String.format("Duplicate software key identified in '%s:%s'", vuln.getName(), s.getName());
    -  606  0
                                 LOGGER.debug(msg, ex);
    -  607  0
                             } else {
    -  608  0
                                 throw ex;
    -  609   -
                             }
    -  610  0
                         }
    -  611   -
                     }
    -  612  0
                 }
    -  613  0
                 if (batchSupported) {
    -  614  0
                     insertSoftware.executeBatch();
    -  615   -
                 }
    -  616  0
             } catch (SQLException ex) {
    -  617  0
                 final String msg = String.format("Error updating '%s'", vuln.getName());
    -  618  0
                 LOGGER.debug(msg, ex);
    -  619  0
                 throw new DatabaseException(msg, ex);
    -  620   -
             } finally {
    -  621  0
                 DBUtils.closeStatement(selectVulnerabilityId);
    -  622  0
                 DBUtils.closeStatement(deleteReferences);
    -  623  0
                 DBUtils.closeStatement(deleteSoftware);
    -  624  0
                 DBUtils.closeStatement(updateVulnerability);
    -  625  0
                 DBUtils.closeStatement(deleteVulnerability);
    -  626  0
                 DBUtils.closeStatement(insertVulnerability);
    -  627  0
                 DBUtils.closeStatement(insertReference);
    -  628  0
                 DBUtils.closeStatement(selectCpeId);
    -  629  0
                 DBUtils.closeStatement(insertCpe);
    -  630  0
                 DBUtils.closeStatement(insertSoftware);
    -  631  0
             }
    -  632  0
         }
    -  633   -
     
    -  634   -
         /**
    -  635   -
          * Checks to see if data exists so that analysis can be performed.
    -  636   -
          *
    -  637   -
          * @return <code>true</code> if data exists; otherwise <code>false</code>
    -  638   -
          */
    -  639   -
         public boolean dataExists() {
    -  640  2
             Statement cs = null;
    -  641  2
             ResultSet rs = null;
    -  642   -
             try {
    -  643  2
                 cs = conn.createStatement();
    -  644  2
                 rs = cs.executeQuery("SELECT COUNT(*) records FROM cpeEntry");
    -  645  2
                 if (rs.next()) {
    -  646  2
                     if (rs.getInt(1) > 0) {
    -  647  4
                         return true;
    -  648   -
                     }
    -  649   -
                 }
    -  650  0
             } catch (SQLException ex) {
    -  651   -
                 String dd;
    -  652   -
                 try {
    -  653  0
                     dd = Settings.getDataDirectory().getAbsolutePath();
    -  654  0
                 } catch (IOException ex1) {
    -  655  0
                     dd = Settings.getString(Settings.KEYS.DATA_DIRECTORY);
    -  656  0
                 }
    -  657  0
                 LOGGER.error("Unable to access the local database.\n\nEnsure that '{}' is a writable directory. "
    -  658   -
                         + "If the problem persist try deleting the files in '{}' and running {} again. If the problem continues, please "
    -  659   -
                         + "create a log file (see documentation at http://jeremylong.github.io/DependencyCheck/) and open a ticket at "
    -  660   -
                         + "https://github.com/jeremylong/DependencyCheck/issues and include the log file.\n\n",
    -  661  0
                         dd, dd, Settings.getString(Settings.KEYS.APPLICATION_VAME));
    -  662  0
                 LOGGER.debug("", ex);
    -  663   -
             } finally {
    -  664  2
                 DBUtils.closeResultSet(rs);
    -  665  2
                 DBUtils.closeStatement(cs);
    -  666  0
             }
    -  667  0
             return false;
    -  668   -
         }
    -  669   -
     
    -  670   -
         /**
    -  671   -
          * It is possible that orphaned rows may be generated during database
    -  672   -
          * updates. This should be called after all updates have been completed to
    -  673   -
          * ensure orphan entries are removed.
    -  674   -
          */
    -  675   -
         public void cleanupDatabase() {
    -  676  0
             PreparedStatement ps = null;
    -  677   -
             try {
    -  678  0
                 ps = getConnection().prepareStatement(statementBundle.getString("CLEANUP_ORPHANS"));
    -  679  0
                 if (ps != null) {
    -  680  0
                     ps.executeUpdate();
    -  681   -
                 }
    -  682  0
             } catch (SQLException ex) {
    -  683  0
                 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details.");
    -  684  0
                 LOGGER.debug("", ex);
    -  685   -
             } finally {
    -  686  0
                 DBUtils.closeStatement(ps);
    -  687  0
             }
    -  688  0
         }
    -  689   -
     
    -  690   -
         /**
    -  691   -
          * Determines if the given identifiedVersion is affected by the given cpeId
    -  692   -
          * and previous version flag. A non-null, non-empty string passed to the
    -  693   -
          * previous version argument indicates that all previous versions are
    -  694   -
          * affected.
    -  695   -
          *
    -  696   -
          * @param vendor the vendor of the dependency being analyzed
    -  697   -
          * @param product the product name of the dependency being analyzed
    -  698   -
          * @param vulnerableSoftware a map of the vulnerable software with a boolean
    -  699   -
          * indicating if all previous versions are affected
    -  700   -
          * @param identifiedVersion the identified version of the dependency being
    -  701  
          * analyzed
    -  702   -
          * @return true if the identified version is affected, otherwise false
    -  703   +  203   +
          * @return a set of vulnerable software
    +  204  
          */
    -  704   -
         Entry<String, Boolean> getMatchingSoftware(Map<String, Boolean> vulnerableSoftware, String vendor, String product,
    -  705   -
                 DependencyVersion identifiedVersion) {
    -  706   +  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;
    +  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();
    +  214  
     
    -  707  13
             final boolean isVersionTwoADifferentProduct = "apache".equals(vendor) && "struts".equals(product);
    +  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
                 }
    +  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;
    +  228   +
         }
    +  229   +
     
    +  230   +
         /**
    +  231   +
          * Returns the entire list of vendor/product combinations.
    +  232   +
          *
    +  233   +
          * @return the entire list of vendor/product combinations
    +  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 {
    +  238  2
             final Set<Pair<String, String>> data = new HashSet<Pair<String, String>>();
    +  239  2
             ResultSet rs = null;
    +  240  2
             PreparedStatement ps = null;
    +  241   +
             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)));
    +  246   +
                 }
    +  247  0
             } catch (SQLException ex) {
    +  248  0
                 final String msg = "An unexpected SQL Exception occurred; please see the verbose log for more details.";
    +  249  0
                 throw new DatabaseException(msg, ex);
    +  250   +
             } finally {
    +  251  2
                 DBUtils.closeResultSet(rs);
    +  252  2
                 DBUtils.closeStatement(ps);
    +  253  2
             }
    +  254  2
             return data;
    +  255   +
         }
    +  256   +
     
    +  257   +
         /**
    +  258   +
          * Returns a set of properties.
    +  259   +
          *
    +  260   +
          * @return the properties from the database
    +  261   +
          */
    +  262   +
         Properties getProperties() {
    +  263  13
             final Properties prop = new Properties();
    +  264  13
             PreparedStatement ps = null;
    +  265  13
             ResultSet rs = null;
    +  266   +
             try {
    +  267  13
                 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_PROPERTIES"));
    +  268  13
                 rs = ps.executeQuery();
    +  269  273
                 while (rs.next()) {
    +  270  260
                     prop.setProperty(rs.getString(1), rs.getString(2));
    +  271   +
                 }
    +  272  0
             } catch (SQLException ex) {
    +  273  0
                 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details.");
    +  274  0
                 LOGGER.debug("", ex);
    +  275   +
             } finally {
    +  276  13
                 DBUtils.closeStatement(ps);
    +  277  13
                 DBUtils.closeResultSet(rs);
    +  278  13
             }
    +  279  13
             return prop;
    +  280   +
         }
    +  281   +
     
    +  282   +
         /**
    +  283   +
          * Saves a property to the database.
    +  284   +
          *
    +  285   +
          * @param key the property key
    +  286   +
          * @param value the property value
    +  287   +
          */
    +  288   +
         void saveProperty(String key, String value) {
    +  289   +
             try {
    +  290   +
                 try {
    +  291  0
                     final PreparedStatement mergeProperty = getConnection().prepareStatement(statementBundle.getString("MERGE_PROPERTY"));
    +  292   +
                     try {
    +  293  0
                         mergeProperty.setString(1, key);
    +  294  0
                         mergeProperty.setString(2, value);
    +  295  0
                         mergeProperty.executeUpdate();
    +  296   +
                     } finally {
    +  297  0
                         DBUtils.closeStatement(mergeProperty);
    +  298  0
                     }
    +  299  0
                 } catch (MissingResourceException mre) {
    +  300   +
                     // No Merge statement, so doing an Update/Insert...
    +  301  0
                     PreparedStatement updateProperty = null;
    +  302  0
                     PreparedStatement insertProperty = null;
    +  303   +
                     try {
    +  304  0
                         updateProperty = getConnection().prepareStatement(statementBundle.getString("UPDATE_PROPERTY"));
    +  305  0
                         updateProperty.setString(1, value);
    +  306  0
                         updateProperty.setString(2, key);
    +  307  0
                         if (updateProperty.executeUpdate() == 0) {
    +  308  0
                             insertProperty = getConnection().prepareStatement(statementBundle.getString("INSERT_PROPERTY"));
    +  309  0
                             insertProperty.setString(1, key);
    +  310  0
                             insertProperty.setString(2, value);
    +  311  0
                             insertProperty.executeUpdate();
    +  312   +
                         }
    +  313   +
                     } finally {
    +  314  0
                         DBUtils.closeStatement(updateProperty);
    +  315  0
                         DBUtils.closeStatement(insertProperty);
    +  316  0
                     }
    +  317  0
                 }
    +  318  0
             } catch (SQLException ex) {
    +  319  0
                 LOGGER.warn("Unable to save property '{}' with a value of '{}' to the database", key, value);
    +  320  0
                 LOGGER.debug("", ex);
    +  321  0
             }
    +  322  0
         }
    +  323   +
     
    +  324   +
         /**
    +  325   +
          * Retrieves the vulnerabilities associated with the specified CPE.
    +  326   +
          *
    +  327   +
          * @param cpeStr the CPE name
    +  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 {
    +  332  3
             final VulnerableSoftware cpe = new VulnerableSoftware();
    +  333   +
             try {
    +  334  3
                 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>();
    +  340   +
     
    +  341  3
             PreparedStatement ps = null;
    +  342  3
             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 = "";
    +  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) {
    +  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;
    +  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
                 }
    +  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) {
    +  372  2
                     final Vulnerability v = getVulnerability(currentCVE);
    +  373  2
                     v.setMatchedCPE(matchedCPE.getKey(), matchedCPE.getValue() ? "Y" : null);
    +  374  2
                     vulnerabilities.add(v);
    +  375   +
                 }
    +  376  0
             } catch (SQLException ex) {
    +  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;
    +  383   +
         }
    +  384   +
     
    +  385   +
         /**
    +  386   +
          * Gets a vulnerability for the provided CVE.
    +  387   +
          *
    +  388   +
          * @param cve the CVE to lookup
    +  389   +
          * @return a vulnerability object
    +  390   +
          * @throws DatabaseException if an exception occurs
    +  391   +
          */
    +  392   +
         public Vulnerability getVulnerability(String cve) throws DatabaseException {
    +  393  8
             PreparedStatement psV = null;
    +  394  8
             PreparedStatement psR = null;
    +  395  8
             PreparedStatement psS = null;
    +  396  8
             ResultSet rsV = null;
    +  397  8
             ResultSet rsR = null;
    +  398  8
             ResultSet rsS = null;
    +  399  8
             Vulnerability vuln = null;
    +  400   +
     
    +  401   +
             try {
    +  402  8
                 psV = getConnection().prepareStatement(statementBundle.getString("SELECT_VULNERABILITY"));
    +  403  8
                 psV.setString(1, cve);
    +  404  8
                 rsV = psV.executeQuery();
    +  405  8
                 if (rsV.next()) {
    +  406  8
                     vuln = new Vulnerability();
    +  407  8
                     vuln.setName(cve);
    +  408  8
                     vuln.setDescription(rsV.getString(2));
    +  409  8
                     String cwe = rsV.getString(3);
    +  410  8
                     if (cwe != null) {
    +  411  8
                         final String name = CweDB.getCweName(cwe);
    +  412  8
                         if (name != null) {
    +  413  7
                             cwe += ' ' + name;
    +  414   +
                         }
    +  415   +
                     }
    +  416  8
                     final int cveId = rsV.getInt(1);
    +  417  8
                     vuln.setCwe(cwe);
    +  418  8
                     vuln.setCvssScore(rsV.getFloat(4));
    +  419  8
                     vuln.setCvssAccessVector(rsV.getString(5));
    +  420  8
                     vuln.setCvssAccessComplexity(rsV.getString(6));
    +  421  8
                     vuln.setCvssAuthentication(rsV.getString(7));
    +  422  8
                     vuln.setCvssConfidentialityImpact(rsV.getString(8));
    +  423  8
                     vuln.setCvssIntegrityImpact(rsV.getString(9));
    +  424  8
                     vuln.setCvssAvailabilityImpact(rsV.getString(10));
    +  425   +
     
    +  426  8
                     psR = getConnection().prepareStatement(statementBundle.getString("SELECT_REFERENCES"));
    +  427  8
                     psR.setInt(1, cveId);
    +  428  8
                     rsR = psR.executeQuery();
    +  429  76
                     while (rsR.next()) {
    +  430  68
                         vuln.addReference(rsR.getString(1), rsR.getString(2), rsR.getString(3));
    +  431   +
                     }
    +  432  8
                     psS = getConnection().prepareStatement(statementBundle.getString("SELECT_SOFTWARE"));
    +  433  8
                     psS.setInt(1, cveId);
    +  434  8
                     rsS = psS.executeQuery();
    +  435  244
                     while (rsS.next()) {
    +  436  236
                         final String cpe = rsS.getString(1);
    +  437  236
                         final String prevVersion = rsS.getString(2);
    +  438  236
                         if (prevVersion == null) {
    +  439  228
                             vuln.addVulnerableSoftware(cpe);
    +  440   +
                         } else {
    +  441  8
                             vuln.addVulnerableSoftware(cpe, prevVersion);
    +  442   +
                         }
    +  443  236
                     }
    +  444   +
                 }
    +  445  0
             } catch (SQLException ex) {
    +  446  0
                 throw new DatabaseException("Error retrieving " + cve, ex);
    +  447   +
             } finally {
    +  448  8
                 DBUtils.closeResultSet(rsV);
    +  449  8
                 DBUtils.closeResultSet(rsR);
    +  450  8
                 DBUtils.closeResultSet(rsS);
    +  451  8
                 DBUtils.closeStatement(psV);
    +  452  8
                 DBUtils.closeStatement(psR);
    +  453  8
                 DBUtils.closeStatement(psS);
    +  454  8
             }
    +  455  8
             return vuln;
    +  456   +
         }
    +  457   +
     
    +  458   +
         /**
    +  459   +
          * Updates the vulnerability within the database. If the vulnerability does
    +  460   +
          * not exist it will be added.
    +  461   +
          *
    +  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 {
    +  466  0
             PreparedStatement selectVulnerabilityId = null;
    +  467  0
             PreparedStatement deleteVulnerability = null;
    +  468  0
             PreparedStatement deleteReferences = null;
    +  469  0
             PreparedStatement deleteSoftware = null;
    +  470  0
             PreparedStatement updateVulnerability = null;
    +  471  0
             PreparedStatement insertVulnerability = null;
    +  472  0
             PreparedStatement insertReference = null;
    +  473  0
             PreparedStatement selectCpeId = null;
    +  474  0
             PreparedStatement insertCpe = null;
    +  475  0
             PreparedStatement insertSoftware = null;
    +  476   +
     
    +  477   +
             try {
    +  478  0
                 selectVulnerabilityId = getConnection().prepareStatement(statementBundle.getString("SELECT_VULNERABILITY_ID"));
    +  479  0
                 deleteVulnerability = getConnection().prepareStatement(statementBundle.getString("DELETE_VULNERABILITY"));
    +  480  0
                 deleteReferences = getConnection().prepareStatement(statementBundle.getString("DELETE_REFERENCE"));
    +  481  0
                 deleteSoftware = getConnection().prepareStatement(statementBundle.getString("DELETE_SOFTWARE"));
    +  482  0
                 updateVulnerability = getConnection().prepareStatement(statementBundle.getString("UPDATE_VULNERABILITY"));
    +  483  0
                 final String[] ids = {"id"};
    +  484  0
                 insertVulnerability = getConnection().prepareStatement(statementBundle.getString("INSERT_VULNERABILITY"),
    +  485   +
                         //Statement.RETURN_GENERATED_KEYS);
    +  486   +
                         ids);
    +  487  0
                 insertReference = getConnection().prepareStatement(statementBundle.getString("INSERT_REFERENCE"));
    +  488  0
                 selectCpeId = getConnection().prepareStatement(statementBundle.getString("SELECT_CPE_ID"));
    +  489  0
                 insertCpe = getConnection().prepareStatement(statementBundle.getString("INSERT_CPE"),
    +  490   +
                         //Statement.RETURN_GENERATED_KEYS);
    +  491   +
                         ids);
    +  492  0
                 insertSoftware = getConnection().prepareStatement(statementBundle.getString("INSERT_SOFTWARE"));
    +  493  0
                 int vulnerabilityId = 0;
    +  494  0
                 selectVulnerabilityId.setString(1, vuln.getName());
    +  495  0
                 ResultSet rs = selectVulnerabilityId.executeQuery();
    +  496  0
                 if (rs.next()) {
    +  497  0
                     vulnerabilityId = rs.getInt(1);
    +  498   +
                     // first delete any existing vulnerability info. We don't know what was updated. yes, slower but atm easier.
    +  499  0
                     deleteReferences.setInt(1, vulnerabilityId);
    +  500  0
                     deleteReferences.execute();
    +  501  0
                     deleteSoftware.setInt(1, vulnerabilityId);
    +  502  0
                     deleteSoftware.execute();
    +  503   +
                 }
    +  504  0
                 DBUtils.closeResultSet(rs);
    +  505  0
                 rs = null;
    +  506   +
     
    +  507  0
                 if (vulnerabilityId != 0) {
    +  508  0
                     if (vuln.getDescription().contains("** REJECT **")) {
    +  509  0
                         deleteVulnerability.setInt(1, vulnerabilityId);
    +  510  0
                         deleteVulnerability.executeUpdate();
    +  511   +
                     } else {
    +  512  0
                         updateVulnerability.setString(1, vuln.getDescription());
    +  513  0
                         updateVulnerability.setString(2, vuln.getCwe());
    +  514  0
                         updateVulnerability.setFloat(3, vuln.getCvssScore());
    +  515  0
                         updateVulnerability.setString(4, vuln.getCvssAccessVector());
    +  516  0
                         updateVulnerability.setString(5, vuln.getCvssAccessComplexity());
    +  517  0
                         updateVulnerability.setString(6, vuln.getCvssAuthentication());
    +  518  0
                         updateVulnerability.setString(7, vuln.getCvssConfidentialityImpact());
    +  519  0
                         updateVulnerability.setString(8, vuln.getCvssIntegrityImpact());
    +  520  0
                         updateVulnerability.setString(9, vuln.getCvssAvailabilityImpact());
    +  521  0
                         updateVulnerability.setInt(10, vulnerabilityId);
    +  522  0
                         updateVulnerability.executeUpdate();
    +  523   +
                     }
    +  524   +
                 } else {
    +  525  0
                     insertVulnerability.setString(1, vuln.getName());
    +  526  0
                     insertVulnerability.setString(2, vuln.getDescription());
    +  527  0
                     insertVulnerability.setString(3, vuln.getCwe());
    +  528  0
                     insertVulnerability.setFloat(4, vuln.getCvssScore());
    +  529  0
                     insertVulnerability.setString(5, vuln.getCvssAccessVector());
    +  530  0
                     insertVulnerability.setString(6, vuln.getCvssAccessComplexity());
    +  531  0
                     insertVulnerability.setString(7, vuln.getCvssAuthentication());
    +  532  0
                     insertVulnerability.setString(8, vuln.getCvssConfidentialityImpact());
    +  533  0
                     insertVulnerability.setString(9, vuln.getCvssIntegrityImpact());
    +  534  0
                     insertVulnerability.setString(10, vuln.getCvssAvailabilityImpact());
    +  535  0
                     insertVulnerability.execute();
    +  536   +
                     try {
    +  537  0
                         rs = insertVulnerability.getGeneratedKeys();
    +  538  0
                         rs.next();
    +  539  0
                         vulnerabilityId = rs.getInt(1);
    +  540  0
                     } catch (SQLException ex) {
    +  541  0
                         final String msg = String.format("Unable to retrieve id for new vulnerability for '%s'", vuln.getName());
    +  542  0
                         throw new DatabaseException(msg, ex);
    +  543   +
                     } finally {
    +  544  0
                         DBUtils.closeResultSet(rs);
    +  545  0
                         rs = null;
    +  546  0
                     }
    +  547   +
                 }
    +  548   +
     
    +  549  0
                 for (Reference r : vuln.getReferences()) {
    +  550  0
                     insertReference.setInt(1, vulnerabilityId);
    +  551  0
                     insertReference.setString(2, r.getName());
    +  552  0
                     insertReference.setString(3, r.getUrl());
    +  553  0
                     insertReference.setString(4, r.getSource());
    +  554   +
     
    +  555  0
                     if (batchSupported) {
    +  556  0
                         insertReference.addBatch();
    +  557   +
                     } else {
    +  558  0
                         insertReference.execute();
    +  559   +
                     }
    +  560  0
                 }
    +  561   +
     
    +  562  0
                 if (batchSupported) {
    +  563  0
                     insertReference.executeBatch();
    +  564   +
                 }
    +  565   +
     
    +  566  0
                 for (VulnerableSoftware s : vuln.getVulnerableSoftware()) {
    +  567  0
                     int cpeProductId = 0;
    +  568  0
                     selectCpeId.setString(1, s.getName());
    +  569   +
                     try {
    +  570  0
                         rs = selectCpeId.executeQuery();
    +  571  0
                         if (rs.next()) {
    +  572  0
                             cpeProductId = rs.getInt(1);
    +  573   +
                         }
    +  574  0
                     } catch (SQLException ex) {
    +  575  0
                         throw new DatabaseException("Unable to get primary key for new cpe: " + s.getName(), ex);
    +  576   +
                     } finally {
    +  577  0
                         DBUtils.closeResultSet(rs);
    +  578  0
                         rs = null;
    +  579  0
                     }
    +  580   +
     
    +  581  0
                     if (cpeProductId == 0) {
    +  582  0
                         insertCpe.setString(1, s.getName());
    +  583  0
                         insertCpe.setString(2, s.getVendor());
    +  584  0
                         insertCpe.setString(3, s.getProduct());
    +  585  0
                         insertCpe.executeUpdate();
    +  586  0
                         cpeProductId = DBUtils.getGeneratedKey(insertCpe);
    +  587   +
                     }
    +  588  0
                     if (cpeProductId == 0) {
    +  589  0
                         throw new DatabaseException("Unable to retrieve cpeProductId - no data returned");
    +  590   +
                     }
    +  591   +
     
    +  592  0
                     insertSoftware.setInt(1, vulnerabilityId);
    +  593  0
                     insertSoftware.setInt(2, cpeProductId);
    +  594   +
     
    +  595  0
                     if (s.getPreviousVersion() == null) {
    +  596  0
                         insertSoftware.setNull(3, java.sql.Types.VARCHAR);
    +  597   +
                     } else {
    +  598  0
                         insertSoftware.setString(3, s.getPreviousVersion());
    +  599   +
                     }
    +  600  0
                     if (batchSupported) {
    +  601  0
                         insertSoftware.addBatch();
    +  602   +
                     } else {
    +  603   +
                         try {
    +  604  0
                             insertSoftware.execute();
    +  605  0
                         } catch (SQLException ex) {
    +  606  0
                             if (ex.getMessage().contains("Duplicate entry")) {
    +  607  0
                                 final String msg = String.format("Duplicate software key identified in '%s:%s'", vuln.getName(), s.getName());
    +  608  0
                                 LOGGER.debug(msg, ex);
    +  609  0
                             } else {
    +  610  0
                                 throw ex;
    +  611   +
                             }
    +  612  0
                         }
    +  613   +
                     }
    +  614  0
                 }
    +  615  0
                 if (batchSupported) {
    +  616  0
                     insertSoftware.executeBatch();
    +  617   +
                 }
    +  618  0
             } catch (SQLException ex) {
    +  619  0
                 final String msg = String.format("Error updating '%s'", vuln.getName());
    +  620  0
                 LOGGER.debug(msg, ex);
    +  621  0
                 throw new DatabaseException(msg, ex);
    +  622   +
             } finally {
    +  623  0
                 DBUtils.closeStatement(selectVulnerabilityId);
    +  624  0
                 DBUtils.closeStatement(deleteReferences);
    +  625  0
                 DBUtils.closeStatement(deleteSoftware);
    +  626  0
                 DBUtils.closeStatement(updateVulnerability);
    +  627  0
                 DBUtils.closeStatement(deleteVulnerability);
    +  628  0
                 DBUtils.closeStatement(insertVulnerability);
    +  629  0
                 DBUtils.closeStatement(insertReference);
    +  630  0
                 DBUtils.closeStatement(selectCpeId);
    +  631  0
                 DBUtils.closeStatement(insertCpe);
    +  632  0
                 DBUtils.closeStatement(insertSoftware);
    +  633  0
             }
    +  634  0
         }
    +  635   +
     
    +  636   +
         /**
    +  637   +
          * Checks to see if data exists so that analysis can be performed.
    +  638   +
          *
    +  639   +
          * @return <code>true</code> if data exists; otherwise <code>false</code>
    +  640   +
          */
    +  641   +
         public boolean dataExists() {
    +  642  2
             Statement cs = null;
    +  643  2
             ResultSet rs = null;
    +  644   +
             try {
    +  645  2
                 cs = conn.createStatement();
    +  646  2
                 rs = cs.executeQuery("SELECT COUNT(*) records FROM cpeEntry");
    +  647  2
                 if (rs.next()) {
    +  648  2
                     if (rs.getInt(1) > 0) {
    +  649  4
                         return true;
    +  650   +
                     }
    +  651   +
                 }
    +  652  0
             } catch (SQLException ex) {
    +  653   +
                 String dd;
    +  654   +
                 try {
    +  655  0
                     dd = Settings.getDataDirectory().getAbsolutePath();
    +  656  0
                 } catch (IOException ex1) {
    +  657  0
                     dd = Settings.getString(Settings.KEYS.DATA_DIRECTORY);
    +  658  0
                 }
    +  659  0
                 LOGGER.error("Unable to access the local database.\n\nEnsure that '{}' is a writable directory. "
    +  660   +
                         + "If the problem persist try deleting the files in '{}' and running {} again. If the problem continues, please "
    +  661   +
                         + "create a log file (see documentation at http://jeremylong.github.io/DependencyCheck/) and open a ticket at "
    +  662   +
                         + "https://github.com/jeremylong/DependencyCheck/issues and include the log file.\n\n",
    +  663  0
                         dd, dd, Settings.getString(Settings.KEYS.APPLICATION_NAME));
    +  664  0
                 LOGGER.debug("", ex);
    +  665   +
             } finally {
    +  666  2
                 DBUtils.closeResultSet(rs);
    +  667  2
                 DBUtils.closeStatement(cs);
    +  668  0
             }
    +  669  0
             return false;
    +  670   +
         }
    +  671   +
     
    +  672   +
         /**
    +  673   +
          * It is possible that orphaned rows may be generated during database
    +  674   +
          * updates. This should be called after all updates have been completed to
    +  675   +
          * ensure orphan entries are removed.
    +  676   +
          */
    +  677   +
         public void cleanupDatabase() {
    +  678  0
             PreparedStatement ps = null;
    +  679   +
             try {
    +  680  0
                 ps = getConnection().prepareStatement(statementBundle.getString("CLEANUP_ORPHANS"));
    +  681  0
                 if (ps != null) {
    +  682  0
                     ps.executeUpdate();
    +  683   +
                 }
    +  684  0
             } catch (SQLException ex) {
    +  685  0
                 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details.");
    +  686  0
                 LOGGER.debug("", ex);
    +  687   +
             } finally {
    +  688  0
                 DBUtils.closeStatement(ps);
    +  689  0
             }
    +  690  0
         }
    +  691   +
     
    +  692   +
         /**
    +  693   +
          * Determines if the given identifiedVersion is affected by the given cpeId
    +  694   +
          * and previous version flag. A non-null, non-empty string passed to the
    +  695   +
          * previous version argument indicates that all previous versions are
    +  696   +
          * affected.
    +  697   +
          *
    +  698   +
          * @param vendor the vendor of the dependency being analyzed
    +  699   +
          * @param product the product name of the dependency being analyzed
    +  700   +
          * @param vulnerableSoftware a map of the vulnerable software with a boolean
    +  701   +
          * indicating if all previous versions are affected
    +  702   +
          * @param identifiedVersion the identified version of the dependency being
    +  703   +
          * analyzed
    +  704   +
          * @return true if the identified version is affected, otherwise false
    +  705   +
          */
    +  706   +
         Entry<String, Boolean> getMatchingSoftware(Map<String, Boolean> vulnerableSoftware, String vendor, String product,
    +  707   +
                 DependencyVersion identifiedVersion) {
     708  
     
    -  709  13
             final Set<String> majorVersionsAffectingAllPrevious = new HashSet<String>();
    -  710  13
             final boolean matchesAnyPrevious = identifiedVersion == null || "-".equals(identifiedVersion.toString());
    -  711  13
             String majorVersionMatch = null;
    -  712  13
             for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) {
    -  713  279
                 final DependencyVersion v = parseDependencyVersion(entry.getKey());
    -  714  279
                 if (v == null || "-".equals(v.toString())) { //all versions
    -  715  0
                     return entry;
    -  716   +  709  13
             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
    +  717  0
                     return entry;
    +  718  
                 }
    -  717  279
                 if (entry.getValue()) {
    -  718  8
                     if (matchesAnyPrevious) {
    -  719  0
                         return entry;
    -  720   +  719  279
                 if (entry.getValue()) {
    +  720  8
                     if (matchesAnyPrevious) {
    +  721  0
                         return entry;
    +  722  
                     }
    -  721  8
                     if (identifiedVersion != null && identifiedVersion.getVersionParts().get(0).equals(v.getVersionParts().get(0))) {
    -  722  6
                         majorVersionMatch = v.getVersionParts().get(0);
    -  723   -
                     }
    -  724  8
                     majorVersionsAffectingAllPrevious.add(v.getVersionParts().get(0));
    +  723  8
                     if (identifiedVersion != null && identifiedVersion.getVersionParts().get(0).equals(v.getVersionParts().get(0))) {
    +  724  6
                         majorVersionMatch = v.getVersionParts().get(0);
     725   +
                     }
    +  726  8
                     majorVersionsAffectingAllPrevious.add(v.getVersionParts().get(0));
    +  727  
                 }
    -  726  279
             }
    -  727  13
             if (matchesAnyPrevious) {
    -  728  0
                 return null;
    -  729   +  728  279
             }
    +  729  13
             if (matchesAnyPrevious) {
    +  730  0
                 return null;
    +  731  
             }
    -  730   -
     
    -  731  13
             final boolean canSkipVersions = majorVersionMatch != null && majorVersionsAffectingAllPrevious.size() > 1;
     732   +
     
    +  733  13
             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
    -  733   +  735  
             //then later we process those that affect all versions. This could be done with sorting...
    -  734  13
             for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) {
    -  735  237
                 if (!entry.getValue()) {
    -  736  229
                     final DependencyVersion v = parseDependencyVersion(entry.getKey());
    -  737   +  736  13
             for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) {
    +  737  237
                 if (!entry.getValue()) {
    +  738  229
                     final DependencyVersion v = parseDependencyVersion(entry.getKey());
    +  739  
                     //this can't dereference a null 'majorVersionMatch' as canSkipVersions accounts for this.
    -  738  229
                     if (canSkipVersions && !majorVersionMatch.equals(v.getVersionParts().get(0))) {
    -  739  8
                         continue;
    -  740   -
                     }
    -  741   -
                     //this can't dereference a null 'identifiedVersion' because if it was null we would have exited
    +  740  229
                     if (canSkipVersions && !majorVersionMatch.equals(v.getVersionParts().get(0))) {
    +  741  8
                         continue;
     742   -
                     //in the above loop or just after loop (if matchesAnyPrevious return null).
    -  743  221
                     if (identifiedVersion.equals(v)) {
    -  744  8
                         return entry;
    -  745  
                     }
    -  746   -
                 }
    -  747  221
             }
    -  748  5
             for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) {
    -  749  56
                 if (entry.getValue()) {
    -  750  0
                     final DependencyVersion v = parseDependencyVersion(entry.getKey());
    -  751   -
                     //this can't dereference a null 'majorVersionMatch' as canSkipVersions accounts for this.
    -  752  0
                     if (canSkipVersions && !majorVersionMatch.equals(v.getVersionParts().get(0))) {
    -  753  0
                         continue;
    -  754   -
                     }
    -  755   +  743  
                     //this can't dereference a null 'identifiedVersion' because if it was null we would have exited
    -  756   +  744  
                     //in the above loop or just after loop (if matchesAnyPrevious return null).
    -  757  0
                     if (entry.getValue() && identifiedVersion.compareTo(v) <= 0) {
    -  758  0
                         if (!(isVersionTwoADifferentProduct && !identifiedVersion.getVersionParts().get(0).equals(v.getVersionParts().get(0)))) {
    -  759  0
                             return entry;
    -  760   -
                         }
    -  761   +  745  221
                     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()) {
    +  752  0
                     final DependencyVersion v = parseDependencyVersion(entry.getKey());
    +  753   +
                     //this can't dereference a null 'majorVersionMatch' as canSkipVersions accounts for this.
    +  754  0
                     if (canSkipVersions && !majorVersionMatch.equals(v.getVersionParts().get(0))) {
    +  755  0
                         continue;
    +  756   +
                     }
    +  757   +
                     //this can't dereference a null 'identifiedVersion' because if it was null we would have exited
    +  758   +
                     //in the above loop or just after loop (if matchesAnyPrevious return null).
    +  759  0
                     if (entry.getValue() && identifiedVersion.compareTo(v) <= 0) {
    +  760  0
                         if (!(isVersionTwoADifferentProduct && !identifiedVersion.getVersionParts().get(0).equals(v.getVersionParts().get(0)))) {
    +  761  0
                             return entry;
     762   +
                         }
    +  763   +
                     }
    +  764  
                 }
    -  763  56
             }
    -  764  5
             return null;
    -  765   -
         }
    -  766   -
     
    +  765  56
             }
    +  766  5
             return null;
     767   -
         /**
    +
         }
     768   -
          * Parses the version (including revision) from a CPE identifier. If no
    +
     
     769   -
          * version is identified then a '-' is returned.
    +
         /**
     770   -
          *
    +
          * Parses the version (including revision) from a CPE identifier. If no
     771   -
          * @param cpeStr a cpe identifier
    +
          * version is identified then a '-' is returned.
     772   -
          * @return a dependency version
    +
          *
     773   -
          */
    +
          * @param cpeStr a cpe identifier
     774   -
         private DependencyVersion parseDependencyVersion(String cpeStr) {
    -  775  508
             final VulnerableSoftware cpe = new VulnerableSoftware();
    -  776   -
             try {
    -  777  508
                 cpe.parseName(cpeStr);
    -  778  0
             } catch (UnsupportedEncodingException ex) {
    -  779   -
                 //never going to happen.
    -  780  0
                 LOGGER.trace("", ex);
    -  781  508
             }
    -  782  508
             return parseDependencyVersion(cpe);
    -  783   -
         }
    -  784   -
     
    -  785   -
         /**
    -  786   -
          * Takes a CPE and parses out the version number. If no version is
    -  787   -
          * identified then a '-' is returned.
    -  788   -
          *
    -  789   -
          * @param cpe a cpe object
    -  790  
          * @return a dependency version
    -  791   +  775  
          */
    -  792   -
         private DependencyVersion parseDependencyVersion(VulnerableSoftware cpe) {
    -  793   -
             final DependencyVersion cpeVersion;
    -  794  511
             if (cpe.getVersion() != null && !cpe.getVersion().isEmpty()) {
    -  795   -
                 final String versionText;
    -  796  511
                 if (cpe.getUpdate() != null && !cpe.getUpdate().isEmpty()) {
    -  797  113
                     versionText = String.format("%s.%s", cpe.getVersion(), cpe.getUpdate());
    -  798   -
                 } else {
    -  799  398
                     versionText = cpe.getVersion();
    -  800   -
                 }
    -  801  511
                 cpeVersion = DependencyVersionUtil.parseVersion(versionText);
    -  802  511
             } else {
    -  803  0
                 cpeVersion = new DependencyVersion("-");
    -  804   -
             }
    -  805  511
             return cpeVersion;
    -  806   -
         }
    -  807   -
     
    -  808   -
         /**
    -  809   -
          * This method is only referenced in unused code.
    -  810   -
          *
    -  811   -
          * Deletes unused dictionary entries from the database.
    -  812   -
          */
    -  813   -
         public void deleteUnusedCpe() {
    -  814  0
             PreparedStatement ps = null;
    -  815   +  776   +
         private DependencyVersion parseDependencyVersion(String cpeStr) {
    +  777  508
             final VulnerableSoftware cpe = new VulnerableSoftware();
    +  778  
             try {
    -  816  0
                 ps = getConnection().prepareStatement(statementBundle.getString("DELETE_UNUSED_DICT_CPE"));
    -  817  0
                 ps.executeUpdate();
    -  818  0
             } catch (SQLException ex) {
    -  819  0
                 LOGGER.error("Unable to delete CPE dictionary entries", ex);
    -  820   -
             } finally {
    -  821  0
                 DBUtils.closeStatement(ps);
    -  822  0
             }
    -  823  0
         }
    -  824   +  779  508
                 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);
    +  785   +
         }
    +  786  
     
    -  825   +  787  
         /**
    -  826   -
          * This method is only referenced in unused code and will likely break on
    -  827   -
          * MySQL if ever used due to the MERGE statement.
    -  828   +  788   +
          * Takes a CPE and parses out the version number. If no version is
    +  789   +
          * identified then a '-' is returned.
    +  790  
          *
    +  791   +
          * @param cpe a cpe object
    +  792   +
          * @return a dependency version
    +  793   +
          */
    +  794   +
         private DependencyVersion parseDependencyVersion(VulnerableSoftware cpe) {
    +  795   +
             final DependencyVersion cpeVersion;
    +  796  511
             if (cpe.getVersion() != null && !cpe.getVersion().isEmpty()) {
    +  797   +
                 final String versionText;
    +  798  511
                 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();
    +  802   +
                 }
    +  803  511
                 cpeVersion = DependencyVersionUtil.parseVersion(versionText);
    +  804  511
             } else {
    +  805  0
                 cpeVersion = new DependencyVersion("-");
    +  806   +
             }
    +  807  511
             return cpeVersion;
    +  808   +
         }
    +  809   +
     
    +  810   +
         /**
    +  811   +
          * This method is only referenced in unused code.
    +  812   +
          *
    +  813   +
          * Deletes unused dictionary entries from the database.
    +  814   +
          */
    +  815   +
         public void deleteUnusedCpe() {
    +  816  0
             PreparedStatement ps = null;
    +  817   +
             try {
    +  818  0
                 ps = getConnection().prepareStatement(statementBundle.getString("DELETE_UNUSED_DICT_CPE"));
    +  819  0
                 ps.executeUpdate();
    +  820  0
             } catch (SQLException ex) {
    +  821  0
                 LOGGER.error("Unable to delete CPE dictionary entries", ex);
    +  822   +
             } finally {
    +  823  0
                 DBUtils.closeStatement(ps);
    +  824  0
             }
    +  825  0
         }
    +  826   +
     
    +  827   +
         /**
    +  828   +
          * This method is only referenced in unused code and will likely break on
     829   -
          * Merges CPE entries into the database.
    +
          * MySQL if ever used due to the MERGE statement.
     830  
          *
     831   -
          * @param cpe the CPE identifier
    +
          * Merges CPE entries into the database.
     832   -
          * @param vendor the CPE vendor
    +
          *
     833   -
          * @param product the CPE product
    +
          * @param cpe the CPE identifier
     834   -
          */
    +
          * @param vendor the CPE vendor
     835   -
         public void addCpe(String cpe, String vendor, String product) {
    -  836  0
             PreparedStatement ps = null;
    +
          * @param product the CPE product
    +  836   +
          */
     837   +
         public void addCpe(String cpe, String vendor, String product) {
    +  838  0
             PreparedStatement ps = null;
    +  839  
             try {
    -  838  0
                 ps = getConnection().prepareStatement(statementBundle.getString("ADD_DICT_CPE"));
    -  839  0
                 ps.setString(1, cpe);
    -  840  0
                 ps.setString(2, vendor);
    -  841  0
                 ps.setString(3, product);
    -  842  0
                 ps.executeUpdate();
    -  843  0
             } catch (SQLException ex) {
    -  844  0
                 LOGGER.error("Unable to add CPE dictionary entry", ex);
    -  845   +  840  0
                 ps = getConnection().prepareStatement(statementBundle.getString("ADD_DICT_CPE"));
    +  841  0
                 ps.setString(1, cpe);
    +  842  0
                 ps.setString(2, vendor);
    +  843  0
                 ps.setString(3, product);
    +  844  0
                 ps.executeUpdate();
    +  845  0
             } catch (SQLException ex) {
    +  846  0
                 LOGGER.error("Unable to add CPE dictionary entry", ex);
    +  847  
             } finally {
    -  846  0
                 DBUtils.closeStatement(ps);
    -  847  0
             }
    -  848  0
         }
    -  849   +  848  0
                 DBUtils.closeStatement(ps);
    +  849  0
             }
    +  850  0
         }
    +  851  
     }
    - + 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 fecdb29b2..9c3d5e85c 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 3bec7a7e5..e64d238c4 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 1795e002e..8758dcc93 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 41ffda4e6..04d7c987e 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 @@ -173,15 +173,15 @@  82  5
                 if (file.isDirectory()) {
     83  2
                     final File[] files = file.listFiles();
     84  2
                     if (files != null) {
    -  85  43
                         for (File f : files) {
    +  85  44
                         for (File f : files) {
     86  
                             try {
    -  87  41
                                 urls.add(f.toURI().toURL());
    +  87  42
                                 urls.add(f.toURI().toURL());
     88  0
                             } catch (MalformedURLException ex) {
     89  0
                                 LOGGER.debug("Unable to load database driver '{}'; invalid path provided '{}'",
     90  0
                                         className, f.getAbsoluteFile(), ex);
     91  0
                                 throw new DriverLoadException("Unable to load database driver. Invalid path provided", ex);
    -  92  41
                             }
    +  92  42
                             }
     93  
                         }
     94   @@ -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 35e0ad329..671867816 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 4ec38fd8c..cce113631 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 d59f7ac8d..71cefd94d 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 665ca2df1..f4d4a2c2d 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/75
    0%
    0/26
    6.6
    CpeUpdater
    0%
    0/77
    0%
    0/28
    6.8
     
    @@ -286,64 +286,66 @@  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
                 gzip.deleteOnExit();
    -  162   +  161  0
                 LOGGER.debug("Failed to delete intial temporary file {}", gzip.toString());
    +  162  0
                 gzip.deleteOnExit();
    +  163  
             }
    -  163  0
             if (!file.renameTo(gzip)) {
    -  164  0
                 throw new IOException("Unable to rename '" + file.getPath() + "'");
    -  165   +  164  0
             if (!file.renameTo(gzip)) {
    +  165  0
                 throw new IOException("Unable to rename '" + file.getPath() + "'");
    +  166  
             }
    -  166  0
             final File newfile = new File(originalPath);
    -  167   +  167  0
             final File newfile = new File(originalPath);
    +  168  
     
    -  168  0
             final byte[] buffer = new byte[4096];
    -  169   +  169  0
             final byte[] buffer = new byte[4096];
    +  170  
     
    -  170  0
             GZIPInputStream cin = null;
    -  171  0
             FileOutputStream out = null;
    -  172   +  171  0
             GZIPInputStream cin = null;
    +  172  0
             FileOutputStream out = null;
    +  173  
             try {
    -  173  0
                 cin = new GZIPInputStream(new FileInputStream(gzip));
    -  174  0
                 out = new FileOutputStream(newfile);
    -  175   -
     
    +  174  0
                 cin = new GZIPInputStream(new FileInputStream(gzip));
    +  175  0
                 out = new FileOutputStream(newfile);
     176   +
     
    +  177  
                 int len;
    -  177  0
                 while ((len = cin.read(buffer)) > 0) {
    -  178  0
                     out.write(buffer, 0, len);
    -  179   -
                 }
    +  178  0
                 while ((len = cin.read(buffer)) > 0) {
    +  179  0
                     out.write(buffer, 0, len);
     180   +
                 }
    +  181  
             } finally {
    -  181  0
                 if (cin != null) {
    -  182   +  182  0
                 if (cin != null) {
    +  183  
                     try {
    -  183  0
                         cin.close();
    -  184  0
                     } catch (IOException ex) {
    -  185  0
                         LOGGER.trace("ignore", ex);
    -  186  0
                     }
    -  187   +  184  0
                         cin.close();
    +  185  0
                     } catch (IOException ex) {
    +  186  0
                         LOGGER.trace("ignore", ex);
    +  187  0
                     }
    +  188  
                 }
    -  188  0
                 if (out != null) {
    -  189   +  189  0
                 if (out != null) {
    +  190  
                     try {
    -  190  0
                         out.close();
    -  191  0
                     } catch (IOException ex) {
    -  192  0
                         LOGGER.trace("ignore", ex);
    -  193  0
                     }
    -  194   +  191  0
                         out.close();
    +  192  0
                     } catch (IOException ex) {
    +  193  0
                         LOGGER.trace("ignore", ex);
    +  194  0
                     }
    +  195  
                 }
    -  195  0
                 if (gzip.isFile()) {
    -  196  0
                     FileUtils.deleteQuietly(gzip);
    -  197   +  196  0
                 if (gzip.isFile() && !FileUtils.deleteQuietly(gzip)) {
    +  197  0
                     LOGGER.debug("Failed to delete temporary file {}", gzip.toString());
    +  198  0
                     gzip.deleteOnExit();
    +  199  
                 }
    -  198   -
             }
    -  199  0
         }
     200   +
             }
    +  201  0
         }
    +  202  
     }
    - + 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 8fd578130..551d44d1d 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 @@ -388,11 +388,11 @@  221  
                 }
     222  0
             } catch (MalformedURLException ex) {
    -  223  0
                 LOGGER.debug("Unable to retrieve current release version of dependency-check", ex);
    +  223  0
                 LOGGER.debug("Unable to retrieve current release version of dependency-check - malformed url?");
     224  0
             } catch (URLConnectionFailureException ex) {
    -  225  0
                 LOGGER.debug("Unable to retrieve current release version of dependency-check", ex);
    +  225  0
                 LOGGER.debug("Unable to retrieve current release version of dependency-check - connection failed");
     226  0
             } catch (IOException ex) {
    -  227  0
                 LOGGER.debug("Unable to retrieve current release version of dependency-check", ex);
    +  227  0
                 LOGGER.debug("Unable to retrieve current release version of dependency-check - i/o exception");
     228  
             } finally {
     229  3
                 if (conn != null) {
    @@ -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 eda3067db..c56aaabc7 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 @@ -12,7 +12,7 @@
     
    - +
    Classes in this File Line Coverage Branch Coverage Complexity
    NvdCveUpdater
    0%
    0/163
    0%
    0/64
    10.5
    NvdCveUpdater
    0%
    0/159
    0%
    0/62
    10.333
     
    @@ -164,11 +164,11 @@  77  0
                 }
     78  0
                 if (autoUpdate && checkUpdate()) {
     79  0
                     final UpdateableNvdCve updateable = getUpdatesNeeded();
    -  80  0
                     getProperties().save(DatabaseProperties.LAST_CHECKED, Long.toString(System.currentTimeMillis()));
    -  81  0
                     if (updateable.isUpdateNeeded()) {
    -  82  0
                         performUpdate(updateable);
    -  83   +  80  0
                     if (updateable.isUpdateNeeded()) {
    +  81  0
                         performUpdate(updateable);
    +  82  
                     }
    +  83  0
                     getProperties().save(DatabaseProperties.LAST_CHECKED, Long.toString(System.currentTimeMillis()));
     84  
                 }
     85  0
             } catch (MalformedURLException ex) {
    @@ -290,276 +290,266 @@  158  
          */
     159   -
         public void performUpdate(UpdateableNvdCve updateable) throws UpdateException {
    +
         private void performUpdate(UpdateableNvdCve updateable) throws UpdateException {
     160  0
             int maxUpdates = 0;
    -  161   -
             try {
    -  162  0
                 for (NvdCveInfo cve : updateable) {
    -  163  0
                     if (cve.getNeedsUpdate()) {
    -  164  0
                         maxUpdates += 1;
    -  165   -
                     }
    -  166  0
                 }
    -  167  0
                 if (maxUpdates <= 0) {
    -  168  0
                     return;
    -  169   +  161  0
             for (NvdCveInfo cve : updateable) {
    +  162  0
                 if (cve.getNeedsUpdate()) {
    +  163  0
                     maxUpdates += 1;
    +  164  
                 }
    -  170  0
                 if (maxUpdates > 3) {
    -  171  0
                     LOGGER.info("NVD CVE requires several updates; this could take a couple of minutes.");
    +  165  0
             }
    +  166  0
             if (maxUpdates <= 0) {
    +  167  0
                 return;
    +  168   +
             }
    +  169  0
             if (maxUpdates > 3) {
    +  170  0
                 LOGGER.info("NVD CVE requires several updates; this could take a couple of minutes.");
    +  171   +
             }
     172   -
                 }
    -  173  0
                 if (maxUpdates > 0) {
    -  174  0
                     openDataStores();
    -  175   -
                 }
    -  176  
     
    -  177  0
                 final int poolSize = (MAX_THREAD_POOL_SIZE < maxUpdates) ? MAX_THREAD_POOL_SIZE : maxUpdates;
    -  178   +  173  0
             final int poolSize = (MAX_THREAD_POOL_SIZE < maxUpdates) ? MAX_THREAD_POOL_SIZE : maxUpdates;
    +  174   +
     
    +  175  0
             final ExecutorService downloadExecutors = Executors.newFixedThreadPool(poolSize);
    +  176  0
             final ExecutorService processExecutor = Executors.newSingleThreadExecutor();
    +  177  0
             final Set<Future<Future<ProcessTask>>> downloadFutures = new HashSet<Future<Future<ProcessTask>>>(maxUpdates);
    +  178  0
             for (NvdCveInfo cve : updateable) {
    +  179  0
                 if (cve.getNeedsUpdate()) {
    +  180  0
                     final DownloadTask call = new DownloadTask(cve, processExecutor, getCveDB(), Settings.getInstance());
    +  181  0
                     downloadFutures.add(downloadExecutors.submit(call));
    +  182   +
                 }
    +  183  0
             }
    +  184  0
             downloadExecutors.shutdown();
    +  185  
     
    -  179  0
                 final ExecutorService downloadExecutors = Executors.newFixedThreadPool(poolSize);
    -  180  0
                 final ExecutorService processExecutor = Executors.newSingleThreadExecutor();
    -  181  0
                 final Set<Future<Future<ProcessTask>>> downloadFutures = new HashSet<Future<Future<ProcessTask>>>(maxUpdates);
    -  182  0
                 for (NvdCveInfo cve : updateable) {
    -  183  0
                     if (cve.getNeedsUpdate()) {
    -  184  0
                         final DownloadTask call = new DownloadTask(cve, processExecutor, getCveDB(), Settings.getInstance());
    -  185  0
                         downloadFutures.add(downloadExecutors.submit(call));
     186   -
                     }
    -  187  0
                 }
    -  188  0
                 downloadExecutors.shutdown();
    -  189   -
     
    +
             //next, move the future future processTasks to just future processTasks
    +  187  0
             final Set<Future<ProcessTask>> processFutures = new HashSet<Future<ProcessTask>>(maxUpdates);
    +  188  0
             for (Future<Future<ProcessTask>> future : downloadFutures) {
    +  189  0
                 Future<ProcessTask> task = null;
     190   -
                 //next, move the future future processTasks to just future processTasks
    -  191  0
                 final Set<Future<ProcessTask>> processFutures = new HashSet<Future<ProcessTask>>(maxUpdates);
    -  192  0
                 for (Future<Future<ProcessTask>> future : downloadFutures) {
    -  193  0
                     Future<ProcessTask> task = null;
    -  194   -
                     try {
    -  195  0
                         task = future.get();
    -  196  0
                     } catch (InterruptedException ex) {
    -  197  0
                         downloadExecutors.shutdownNow();
    -  198  0
                         processExecutor.shutdownNow();
    -  199   -
     
    -  200  0
                         LOGGER.debug("Thread was interrupted during download", ex);
    -  201  0
                         throw new UpdateException("The download was interrupted", ex);
    -  202  0
                     } catch (ExecutionException ex) {
    -  203  0
                         downloadExecutors.shutdownNow();
    -  204  0
                         processExecutor.shutdownNow();
    -  205   -
     
    -  206  0
                         LOGGER.debug("Thread was interrupted during download execution", ex);
    -  207  0
                         throw new UpdateException("The execution of the download was interrupted", ex);
    -  208  0
                     }
    -  209  0
                     if (task == null) {
    -  210  0
                         downloadExecutors.shutdownNow();
    -  211  0
                         processExecutor.shutdownNow();
    -  212  0
                         LOGGER.debug("Thread was interrupted during download");
    -  213  0
                         throw new UpdateException("The download was interrupted; unable to complete the update");
    -  214   -
                     } else {
    -  215  0
                         processFutures.add(task);
    -  216   -
                     }
    -  217  0
                 }
    -  218   -
     
    -  219  0
                 for (Future<ProcessTask> future : processFutures) {
    -  220   -
                     try {
    -  221  0
                         final ProcessTask task = future.get();
    -  222  0
                         if (task.getException() != null) {
    -  223  0
                             throw task.getException();
    -  224   -
                         }
    -  225  0
                     } catch (InterruptedException ex) {
    -  226  0
                         processExecutor.shutdownNow();
    -  227  0
                         LOGGER.debug("Thread was interrupted during processing", ex);
    -  228  0
                         throw new UpdateException(ex);
    -  229  0
                     } catch (ExecutionException ex) {
    -  230  0
                         processExecutor.shutdownNow();
    -  231  0
                         LOGGER.debug("Execution Exception during process", ex);
    -  232  0
                         throw new UpdateException(ex);
    -  233   -
                     } finally {
    -  234  0
                         processExecutor.shutdown();
    -  235  0
                     }
    -  236  0
                 }
    -  237   -
     
    -  238  0
                 if (maxUpdates >= 1) { //ensure the modified file date gets written (we may not have actually updated it)
    -  239  0
                     getProperties().save(updateable.get(MODIFIED));
    -  240  0
                     LOGGER.info("Begin database maintenance.");
    -  241  0
                     getCveDB().cleanupDatabase();
    -  242  0
                     LOGGER.info("End database maintenance.");
    -  243   -
                 }
    -  244   -
             } finally {
    -  245  0
                 closeDataStores();
    -  246  0
             }
    -  247  0
         }
    -  248   -
     
    -  249   -
         /**
    -  250   -
          * Determines if the index needs to be updated. This is done by fetching the
    -  251   -
          * NVD CVE meta data and checking the last update date. If the data needs to
    -  252   -
          * be refreshed this method will return the NvdCveUrl for the files that
    -  253   -
          * need to be updated.
    -  254   -
          *
    -  255   -
          * @return the collection of files that need to be updated
    -  256   -
          * @throws MalformedURLException is thrown if the URL for the NVD CVE Meta
    -  257   -
          * data is incorrect
    -  258   -
          * @throws DownloadFailedException is thrown if there is an error.
    -  259   -
          * downloading the NVD CVE download data file
    -  260   -
          * @throws UpdateException Is thrown if there is an issue with the last
    -  261   -
          * updated properties file
    -  262   -
          */
    -  263   -
         protected final UpdateableNvdCve getUpdatesNeeded() throws MalformedURLException, DownloadFailedException, UpdateException {
    -  264  0
             UpdateableNvdCve updates = null;
    -  265   -
             try {
    -  266  0
                 updates = retrieveCurrentTimestampsFromWeb();
    -  267  0
             } catch (InvalidDataException ex) {
    -  268  0
                 final String msg = "Unable to retrieve valid timestamp from nvd cve downloads page";
    -  269  0
                 LOGGER.debug(msg, ex);
    -  270  0
                 throw new DownloadFailedException(msg, ex);
    -  271  0
             } catch (InvalidSettingException ex) {
    -  272  0
                 LOGGER.debug("Invalid setting found when retrieving timestamps", ex);
    -  273  0
                 throw new DownloadFailedException("Invalid settings", ex);
    -  274  0
             }
    -  275   -
     
    -  276  0
             if (updates == null) {
    -  277  0
                 throw new DownloadFailedException("Unable to retrieve the timestamps of the currently published NVD CVE data");
    -  278   -
             }
    -  279  0
             if (!getProperties().isEmpty()) {
    -  280  
                 try {
    -  281  0
                     final long lastUpdated = Long.parseLong(getProperties().getProperty(DatabaseProperties.LAST_UPDATED, "0"));
    -  282  0
                     final long now = System.currentTimeMillis();
    -  283  0
                     final int days = Settings.getInt(Settings.KEYS.CVE_MODIFIED_VALID_FOR_DAYS, 7);
    -  284  0
                     if (lastUpdated == updates.getTimeStamp(MODIFIED)) {
    -  285  0
                         updates.clear(); //we don't need to update anything.
    -  286  0
                     } else if (DateUtil.withinDateRange(lastUpdated, now, days)) {
    -  287  0
                         for (NvdCveInfo entry : updates) {
    -  288  0
                             if (MODIFIED.equals(entry.getId())) {
    -  289  0
                                 entry.setNeedsUpdate(true);
    -  290   -
                             } else {
    -  291  0
                                 entry.setNeedsUpdate(false);
    -  292   -
                             }
    -  293  0
                         }
    -  294   -
                     } else { //we figure out which of the several XML files need to be downloaded.
    -  295  0
                         for (NvdCveInfo entry : updates) {
    -  296  0
                             if (MODIFIED.equals(entry.getId())) {
    -  297  0
                                 entry.setNeedsUpdate(true);
    -  298   -
                             } else {
    -  299  0
                                 long currentTimestamp = 0;
    -  300   -
                                 try {
    -  301  0
                                     currentTimestamp = Long.parseLong(getProperties().getProperty(DatabaseProperties.LAST_UPDATED_BASE
    -  302  0
                                             + entry.getId(), "0"));
    -  303  0
                                 } catch (NumberFormatException ex) {
    -  304  0
                                     LOGGER.debug("Error parsing '{}' '{}' from nvdcve.lastupdated",
    -  305  0
                                             DatabaseProperties.LAST_UPDATED_BASE, entry.getId(), ex);
    -  306  0
                                 }
    -  307  0
                                 if (currentTimestamp == entry.getTimestamp()) {
    -  308  0
                                     entry.setNeedsUpdate(false);
    -  309   -
                                 }
    -  310   -
                             }
    -  311  0
                         }
    -  312   +  191  0
                     task = future.get();
    +  192  0
                 } catch (InterruptedException ex) {
    +  193  0
                     downloadExecutors.shutdownNow();
    +  194  0
                     processExecutor.shutdownNow();
    +  195   +
     
    +  196  0
                     LOGGER.debug("Thread was interrupted during download", ex);
    +  197  0
                     throw new UpdateException("The download was interrupted", ex);
    +  198  0
                 } catch (ExecutionException ex) {
    +  199  0
                     downloadExecutors.shutdownNow();
    +  200  0
                     processExecutor.shutdownNow();
    +  201   +
     
    +  202  0
                     LOGGER.debug("Thread was interrupted during download execution", ex);
    +  203  0
                     throw new UpdateException("The execution of the download was interrupted", ex);
    +  204  0
                 }
    +  205  0
                 if (task == null) {
    +  206  0
                     downloadExecutors.shutdownNow();
    +  207  0
                     processExecutor.shutdownNow();
    +  208  0
                     LOGGER.debug("Thread was interrupted during download");
    +  209  0
                     throw new UpdateException("The download was interrupted; unable to complete the update");
    +  210   +
                 } else {
    +  211  0
                     processFutures.add(task);
    +  212   +
                 }
    +  213  0
             }
    +  214   +
     
    +  215  0
             for (Future<ProcessTask> future : processFutures) {
    +  216   +
                 try {
    +  217  0
                     final ProcessTask task = future.get();
    +  218  0
                     if (task.getException() != null) {
    +  219  0
                         throw task.getException();
    +  220  
                     }
    -  313  0
                 } catch (NumberFormatException ex) {
    -  314  0
                     LOGGER.warn("An invalid schema version or timestamp exists in the data.properties file.");
    -  315  0
                     LOGGER.debug("", ex);
    -  316  0
                 }
    -  317   -
             }
    -  318  0
             return updates;
    -  319   -
         }
    -  320   +  221  0
                 } catch (InterruptedException ex) {
    +  222  0
                     processExecutor.shutdownNow();
    +  223  0
                     LOGGER.debug("Thread was interrupted during processing", ex);
    +  224  0
                     throw new UpdateException(ex);
    +  225  0
                 } catch (ExecutionException ex) {
    +  226  0
                     processExecutor.shutdownNow();
    +  227  0
                     LOGGER.debug("Execution Exception during process", ex);
    +  228  0
                     throw new UpdateException(ex);
    +  229   +
                 } finally {
    +  230  0
                     processExecutor.shutdown();
    +  231  0
                 }
    +  232  0
             }
    +  233  
     
    -  321   +  234  0
             if (maxUpdates >= 1) { //ensure the modified file date gets written (we may not have actually updated it)
    +  235  0
                 getProperties().save(updateable.get(MODIFIED));
    +  236  0
                 LOGGER.info("Begin database maintenance.");
    +  237  0
                 getCveDB().cleanupDatabase();
    +  238  0
                 LOGGER.info("End database maintenance.");
    +  239   +
             }
    +  240  0
         }
    +  241   +
     
    +  242  
         /**
    -  322   -
          * Retrieves the timestamps from the NVD CVE meta data file.
    -  323   +  243   +
          * Determines if the index needs to be updated. This is done by fetching the
    +  244   +
          * NVD CVE meta data and checking the last update date. If the data needs to
    +  245   +
          * be refreshed this method will return the NvdCveUrl for the files that
    +  246   +
          * need to be updated.
    +  247  
          *
    -  324   -
          * @return the timestamp from the currently published nvdcve downloads page
    -  325   -
          * @throws MalformedURLException thrown if the URL for the NVD CCE Meta data
    -  326   -
          * is incorrect.
    -  327   -
          * @throws DownloadFailedException thrown if there is an error downloading
    -  328   -
          * the nvd cve meta data file
    -  329   -
          * @throws InvalidDataException thrown if there is an exception parsing the
    -  330   -
          * timestamps
    -  331   -
          * @throws InvalidSettingException thrown if the settings are invalid
    -  332   +  248   +
          * @return the collection of files that need to be updated
    +  249   +
          * @throws MalformedURLException is thrown if the URL for the NVD CVE Meta
    +  250   +
          * data is incorrect
    +  251   +
          * @throws DownloadFailedException is thrown if there is an error.
    +  252   +
          * downloading the NVD CVE download data file
    +  253   +
          * @throws UpdateException Is thrown if there is an issue with the last
    +  254   +
          * updated properties file
    +  255  
          */
    -  333   -
         private UpdateableNvdCve retrieveCurrentTimestampsFromWeb()
    -  334   -
                 throws MalformedURLException, DownloadFailedException, InvalidDataException, InvalidSettingException {
    -  335   +  256   +
         protected final UpdateableNvdCve getUpdatesNeeded() throws MalformedURLException, DownloadFailedException, UpdateException {
    +  257  0
             UpdateableNvdCve updates = null;
    +  258   +
             try {
    +  259  0
                 updates = retrieveCurrentTimestampsFromWeb();
    +  260  0
             } catch (InvalidDataException ex) {
    +  261  0
                 final String msg = "Unable to retrieve valid timestamp from nvd cve downloads page";
    +  262  0
                 LOGGER.debug(msg, ex);
    +  263  0
                 throw new DownloadFailedException(msg, ex);
    +  264  0
             } catch (InvalidSettingException ex) {
    +  265  0
                 LOGGER.debug("Invalid setting found when retrieving timestamps", ex);
    +  266  0
                 throw new DownloadFailedException("Invalid settings", ex);
    +  267  0
             }
    +  268  
     
    -  336  0
             final UpdateableNvdCve updates = new UpdateableNvdCve();
    -  337  0
             updates.add(MODIFIED, Settings.getString(Settings.KEYS.CVE_MODIFIED_20_URL),
    -  338  0
                     Settings.getString(Settings.KEYS.CVE_MODIFIED_12_URL),
    -  339   -
                     false);
    -  340   -
     
    -  341  0
             final int start = Settings.getInt(Settings.KEYS.CVE_START_YEAR);
    -  342  0
             final int end = Calendar.getInstance().get(Calendar.YEAR);
    -  343  0
             final String baseUrl20 = Settings.getString(Settings.KEYS.CVE_SCHEMA_2_0);
    -  344  0
             final String baseUrl12 = Settings.getString(Settings.KEYS.CVE_SCHEMA_1_2);
    -  345  0
             for (int i = start; i <= end; i++) {
    -  346  0
                 updates.add(Integer.toString(i), String.format(baseUrl20, i),
    -  347  0
                         String.format(baseUrl12, i),
    -  348   -
                         true);
    -  349   +  269  0
             if (updates == null) {
    +  270  0
                 throw new DownloadFailedException("Unable to retrieve the timestamps of the currently published NVD CVE data");
    +  271  
             }
    -  350  0
             return updates;
    -  351   +  272  0
             if (!getProperties().isEmpty()) {
    +  273   +
                 try {
    +  274  0
                     final long lastUpdated = Long.parseLong(getProperties().getProperty(DatabaseProperties.LAST_UPDATED, "0"));
    +  275  0
                     final long now = System.currentTimeMillis();
    +  276  0
                     final int days = Settings.getInt(Settings.KEYS.CVE_MODIFIED_VALID_FOR_DAYS, 7);
    +  277  0
                     if (lastUpdated == updates.getTimeStamp(MODIFIED)) {
    +  278  0
                         updates.clear(); //we don't need to update anything.
    +  279  0
                     } else if (DateUtil.withinDateRange(lastUpdated, now, days)) {
    +  280  0
                         for (NvdCveInfo entry : updates) {
    +  281  0
                             if (MODIFIED.equals(entry.getId())) {
    +  282  0
                                 entry.setNeedsUpdate(true);
    +  283   +
                             } else {
    +  284  0
                                 entry.setNeedsUpdate(false);
    +  285   +
                             }
    +  286  0
                         }
    +  287   +
                     } else { //we figure out which of the several XML files need to be downloaded.
    +  288  0
                         for (NvdCveInfo entry : updates) {
    +  289  0
                             if (MODIFIED.equals(entry.getId())) {
    +  290  0
                                 entry.setNeedsUpdate(true);
    +  291   +
                             } else {
    +  292  0
                                 long currentTimestamp = 0;
    +  293   +
                                 try {
    +  294  0
                                     currentTimestamp = Long.parseLong(getProperties().getProperty(DatabaseProperties.LAST_UPDATED_BASE
    +  295  0
                                             + entry.getId(), "0"));
    +  296  0
                                 } catch (NumberFormatException ex) {
    +  297  0
                                     LOGGER.debug("Error parsing '{}' '{}' from nvdcve.lastupdated",
    +  298  0
                                             DatabaseProperties.LAST_UPDATED_BASE, entry.getId(), ex);
    +  299  0
                                 }
    +  300  0
                                 if (currentTimestamp == entry.getTimestamp()) {
    +  301  0
                                     entry.setNeedsUpdate(false);
    +  302   +
                                 }
    +  303   +
                             }
    +  304  0
                         }
    +  305   +
                     }
    +  306  0
                 } catch (NumberFormatException ex) {
    +  307  0
                     LOGGER.warn("An invalid schema version or timestamp exists in the data.properties file.");
    +  308  0
                     LOGGER.debug("", ex);
    +  309  0
                 }
    +  310   +
             }
    +  311  0
             return updates;
    +  312  
         }
    -  352   +  313   +
     
    +  314   +
         /**
    +  315   +
          * Retrieves the timestamps from the NVD CVE meta data file.
    +  316   +
          *
    +  317   +
          * @return the timestamp from the currently published nvdcve downloads page
    +  318   +
          * @throws MalformedURLException thrown if the URL for the NVD CCE Meta data
    +  319   +
          * is incorrect.
    +  320   +
          * @throws DownloadFailedException thrown if there is an error downloading
    +  321   +
          * the nvd cve meta data file
    +  322   +
          * @throws InvalidDataException thrown if there is an exception parsing the
    +  323   +
          * timestamps
    +  324   +
          * @throws InvalidSettingException thrown if the settings are invalid
    +  325   +
          */
    +  326   +
         private UpdateableNvdCve retrieveCurrentTimestampsFromWeb()
    +  327   +
                 throws MalformedURLException, DownloadFailedException, InvalidDataException, InvalidSettingException {
    +  328   +
     
    +  329  0
             final UpdateableNvdCve updates = new UpdateableNvdCve();
    +  330  0
             updates.add(MODIFIED, Settings.getString(Settings.KEYS.CVE_MODIFIED_20_URL),
    +  331  0
                     Settings.getString(Settings.KEYS.CVE_MODIFIED_12_URL),
    +  332   +
                     false);
    +  333   +
     
    +  334  0
             final int start = Settings.getInt(Settings.KEYS.CVE_START_YEAR);
    +  335  0
             final int end = Calendar.getInstance().get(Calendar.YEAR);
    +  336  0
             final String baseUrl20 = Settings.getString(Settings.KEYS.CVE_SCHEMA_2_0);
    +  337  0
             final String baseUrl12 = Settings.getString(Settings.KEYS.CVE_SCHEMA_1_2);
    +  338  0
             for (int i = start; i <= end; i++) {
    +  339  0
                 updates.add(Integer.toString(i), String.format(baseUrl20, i),
    +  340  0
                         String.format(baseUrl12, i),
    +  341   +
                         true);
    +  342   +
             }
    +  343  0
             return updates;
    +  344   +
         }
    +  345  
     }
    - + 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 85ba483a0..107f822d3 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 06735d5c9..5d743af43 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 75683cc92..6d4dfa5f6 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 65c63eb6a..60fb5c96b 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 b90d0e918..331554243 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 f1e240d6d..40a921585 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 @@ -12,7 +12,7 @@
     
    - +
    Classes in this File Line Coverage Branch Coverage Complexity
    DownloadTask
    55%
    61/110
    31%
    22/70
    5.636
    DownloadTask
    55%
    60/108
    35%
    23/64
    5.364
     
    @@ -130,425 +130,411 @@  57  
          * @param cveDB the CVE DB to use to store the vulnerability data
     58   -
          * @param settings a reference to the global settings object; this is necessary so that when the thread is started the
    +
          * @param settings a reference to the global settings object; this is
     59   -
          * dependencies have a correct reference to the global settings.
    +
          * necessary so that when the thread is started the dependencies have a
     60   -
          * @throws UpdateException thrown if temporary files could not be created
    +
          * correct reference to the global settings.
     61   +
          * @throws UpdateException thrown if temporary files could not be created
    +  62  
          */
    -  62  1
         public DownloadTask(NvdCveInfo nvdCveInfo, ExecutorService processor, CveDB cveDB, Settings settings) throws UpdateException {
    -  63  1
             this.nvdCveInfo = nvdCveInfo;
    -  64  1
             this.processorService = processor;
    -  65  1
             this.cveDB = cveDB;
    -  66  1
             this.settings = settings;
    -  67   -
     
    +  63  1
         public DownloadTask(NvdCveInfo nvdCveInfo, ExecutorService processor, CveDB cveDB, Settings settings) throws UpdateException {
    +  64  1
             this.nvdCveInfo = nvdCveInfo;
    +  65  1
             this.processorService = processor;
    +  66  1
             this.cveDB = cveDB;
    +  67  1
             this.settings = settings;
     68   -
             final File file1;
    +
     
     69   -
             final File file2;
    +
             final File file1;
     70   -
     
    +
             final File file2;
     71   -
             try {
    -  72  1
                 file1 = File.createTempFile("cve" + nvdCveInfo.getId() + '_', ".xml", Settings.getTempDirectory());
    -  73  1
                 file2 = File.createTempFile("cve_1_2_" + nvdCveInfo.getId() + '_', ".xml", Settings.getTempDirectory());
    -  74  0
             } catch (IOException ex) {
    -  75  0
                 throw new UpdateException("Unable to create temporary files", ex);
    -  76  1
             }
    -  77  1
             this.first = file1;
    -  78  1
             this.second = file2;
    -  79  
     
    -  80  1
         }
    -  81   -
         /**
    +  72   +
             try {
    +  73  1
                 file1 = File.createTempFile("cve" + nvdCveInfo.getId() + '_', ".xml", Settings.getTempDirectory());
    +  74  1
                 file2 = File.createTempFile("cve_1_2_" + nvdCveInfo.getId() + '_', ".xml", Settings.getTempDirectory());
    +  75  0
             } catch (IOException ex) {
    +  76  0
                 throw new UpdateException("Unable to create temporary files", ex);
    +  77  1
             }
    +  78  1
             this.first = file1;
    +  79  1
             this.second = file2;
    +  80   +
     
    +  81  1
         }
     82   -
          * The CVE DB to use when processing the files.
    +
         /**
     83   -
          */
    +
          * The CVE DB to use when processing the files.
     84   -
         private final CveDB cveDB;
    +
          */
     85   -
         /**
    +
         private final CveDB cveDB;
     86   -
          * The processor service to pass the results of the download to.
    +
         /**
     87   -
          */
    +
          * The processor service to pass the results of the download to.
     88   -
         private final ExecutorService processorService;
    +
          */
     89   -
         /**
    +
         private final ExecutorService processorService;
     90   -
          * The NVD CVE Meta Data.
    +
         /**
     91   -
          */
    +
          * The NVD CVE Meta Data.
     92   -
         private NvdCveInfo nvdCveInfo;
    +
          */
     93   -
         /**
    +
         private NvdCveInfo nvdCveInfo;
     94   -
          * A reference to the global settings object.
    +
         /**
     95   -
          */
    +
          * A reference to the global settings object.
     96   -
         private final Settings settings;
    +
          */
     97   -
     
    +
         private final Settings settings;
     98   -
         /**
    +
     
     99   -
          * Get the value of nvdCveInfo.
    +
         /**
     100   -
          *
    +
          * Get the value of nvdCveInfo.
     101   -
          * @return the value of nvdCveInfo
    +
          *
     102   -
          */
    +
          * @return the value of nvdCveInfo
     103   +
          */
    +  104  
         public NvdCveInfo getNvdCveInfo() {
    -  104  0
             return nvdCveInfo;
    -  105   -
         }
    +  105  0
             return nvdCveInfo;
     106   -
     
    +
         }
     107   -
         /**
    +
     
     108   -
          * Set the value of nvdCveInfo.
    +
         /**
     109   -
          *
    +
          * Set the value of nvdCveInfo.
     110   -
          * @param nvdCveInfo new value of nvdCveInfo
    +
          *
     111   -
          */
    +
          * @param nvdCveInfo new value of nvdCveInfo
     112   +
          */
    +  113  
         public void setNvdCveInfo(NvdCveInfo nvdCveInfo) {
    -  113  0
             this.nvdCveInfo = nvdCveInfo;
    -  114  0
         }
    -  115   -
         /**
    +  114  0
             this.nvdCveInfo = nvdCveInfo;
    +  115  0
         }
     116   -
          * a file.
    +
         /**
     117   -
          */
    -  118   -
         private File first;
    -  119   -
     
    -  120   -
         /**
    -  121   -
          * Get the value of first.
    -  122   -
          *
    -  123   -
          * @return the value of first
    -  124   -
          */
    -  125   -
         public File getFirst() {
    -  126  0
             return first;
    -  127   -
         }
    -  128   -
     
    -  129   -
         /**
    -  130   -
          * Set the value of first.
    -  131   -
          *
    -  132   -
          * @param first new value of first
    -  133   -
          */
    -  134   -
         public void setFirst(File first) {
    -  135  0
             this.first = first;
    -  136  0
         }
    -  137   -
         /**
    -  138  
          * a file.
    +  118   +
          */
    +  119   +
         private File first;
    +  120   +
     
    +  121   +
         /**
    +  122   +
          * Get the value of first.
    +  123   +
          *
    +  124   +
          * @return the value of first
    +  125   +
          */
    +  126   +
         public File getFirst() {
    +  127  0
             return first;
    +  128   +
         }
    +  129   +
     
    +  130   +
         /**
    +  131   +
          * Set the value of first.
    +  132   +
          *
    +  133   +
          * @param first new value of first
    +  134   +
          */
    +  135   +
         public void setFirst(File first) {
    +  136  0
             this.first = first;
    +  137  0
         }
    +  138   +
         /**
     139   -
          */
    +
          * a file.
     140   -
         private File second;
    +
          */
     141   -
     
    +
         private File second;
     142   -
         /**
    +
     
     143   -
          * Get the value of second.
    +
         /**
     144   -
          *
    +
          * Get the value of second.
     145   -
          * @return the value of second
    +
          *
     146   -
          */
    +
          * @return the value of second
     147   +
          */
    +  148  
         public File getSecond() {
    -  148  0
             return second;
    -  149   -
         }
    +  149  0
             return second;
     150   -
     
    +
         }
     151   -
         /**
    +
     
     152   -
          * Set the value of second.
    +
         /**
     153   -
          *
    +
          * Set the value of second.
     154   -
          * @param second new value of second
    +
          *
     155   -
          */
    +
          * @param second new value of second
     156   +
          */
    +  157  
         public void setSecond(File second) {
    -  157  0
             this.second = second;
    -  158  0
         }
    -  159   -
     
    +  158  0
             this.second = second;
    +  159  0
         }
     160   -
         @Override
    +
     
     161   -
         public Future<ProcessTask> call() throws Exception {
    +
         @Override
     162   +
         public Future<ProcessTask> call() throws Exception {
    +  163  
             try {
    -  163  1
                 Settings.setInstance(settings);
    -  164  1
                 final URL url1 = new URL(nvdCveInfo.getUrl());
    -  165  1
                 final URL url2 = new URL(nvdCveInfo.getOldSchemaVersionUrl());
    -  166  1
                 LOGGER.info("Download Started for NVD CVE - {}", nvdCveInfo.getId());
    -  167  1
                 final long startDownload = System.currentTimeMillis();
    -  168   +  164  1
                 Settings.setInstance(settings);
    +  165  1
                 final URL url1 = new URL(nvdCveInfo.getUrl());
    +  166  1
                 final URL url2 = new URL(nvdCveInfo.getOldSchemaVersionUrl());
    +  167  1
                 LOGGER.info("Download Started for NVD CVE - {}", nvdCveInfo.getId());
    +  168  1
                 final long startDownload = System.currentTimeMillis();
    +  169  
                 try {
    -  169  1
                     Downloader.fetchFile(url1, first);
    -  170  1
                     Downloader.fetchFile(url2, second);
    -  171  0
                 } catch (DownloadFailedException ex) {
    -  172  0
                     LOGGER.warn("Download Failed for NVD CVE - {}\nSome CVEs may not be reported.", nvdCveInfo.getId());
    -  173  0
                     if (Settings.getString(Settings.KEYS.PROXY_SERVER) == null) {
    -  174  0
                         LOGGER.info(
    -  175   -
                                 "If you are behind a proxy you may need to configure dependency-check to use the proxy.");
    +  170  1
                     Downloader.fetchFile(url1, first);
    +  171  1
                     Downloader.fetchFile(url2, second);
    +  172  0
                 } catch (DownloadFailedException ex) {
    +  173  0
                     LOGGER.warn("Download Failed for NVD CVE - {}\nSome CVEs may not be reported.", nvdCveInfo.getId());
    +  174  0
                     if (Settings.getString(Settings.KEYS.PROXY_SERVER) == null) {
    +  175  0
                         LOGGER.info(
     176   +
                                 "If you are behind a proxy you may need to configure dependency-check to use the proxy.");
    +  177  
                     }
    -  177  0
                     LOGGER.debug("", ex);
    -  178  0
                     return null;
    -  179  1
                 }
    -  180  1
                 if (url1.toExternalForm().endsWith(".xml.gz") && !isXml(first)) {
    -  181  1
                     extractGzip(first);
    -  182   -
                 }
    -  183  1
                 if (url2.toExternalForm().endsWith(".xml.gz") && !isXml(second)) {
    -  184  1
                     extractGzip(second);
    -  185   +  178  0
                     LOGGER.debug("", ex);
    +  179  0
                     return null;
    +  180  1
                 }
    +  181  1
                 if (url1.toExternalForm().endsWith(".xml.gz") && !isXml(first)) {
    +  182  1
                     extractGzip(first);
    +  183  
                 }
    +  184  1
                 if (url2.toExternalForm().endsWith(".xml.gz") && !isXml(second)) {
    +  185  1
                     extractGzip(second);
     186   -
     
    -  187  2
                 LOGGER.info("Download Complete for NVD CVE - {}  ({} ms)", nvdCveInfo.getId(),
    -  188  1
                         System.currentTimeMillis() - startDownload);
    -  189  1
                 if (this.processorService == null) {
    -  190  2
                     return null;
    -  191  
                 }
    -  192  0
                 final ProcessTask task = new ProcessTask(cveDB, this, settings);
    -  193  0
                 return this.processorService.submit(task);
    -  194   +  187  
     
    -  195  0
             } catch (Throwable ex) {
    -  196  0
                 LOGGER.warn("An exception occurred downloading NVD CVE - {}\nSome CVEs may not be reported.", nvdCveInfo.getId());
    -  197  0
                 LOGGER.debug("Download Task Failed", ex);
    -  198   +  188  2
                 LOGGER.info("Download Complete for NVD CVE - {}  ({} ms)", nvdCveInfo.getId(),
    +  189  1
                         System.currentTimeMillis() - startDownload);
    +  190  1
                 if (this.processorService == null) {
    +  191  2
                     return null;
    +  192   +
                 }
    +  193  0
                 final ProcessTask task = new ProcessTask(cveDB, this, settings);
    +  194  0
                 return this.processorService.submit(task);
    +  195   +
     
    +  196  0
             } catch (Throwable ex) {
    +  197  0
                 LOGGER.warn("An exception occurred downloading NVD CVE - {}\nSome CVEs may not be reported.", nvdCveInfo.getId());
    +  198  0
                 LOGGER.debug("Download Task Failed", ex);
    +  199  
             } finally {
    -  199  1
                 Settings.cleanup(false);
    -  200  0
             }
    -  201  0
             return null;
    -  202   -
         }
    +  200  1
                 Settings.cleanup(false);
    +  201  0
             }
    +  202  0
             return null;
     203   -
     
    -  204   -
         /**
    -  205   -
          * Attempts to delete the files that were downloaded.
    -  206   -
          */
    -  207   -
         public void cleanup() {
    -  208  0
             boolean deleted = false;
    -  209   -
             try {
    -  210  0
                 if (first != null && first.exists()) {
    -  211  0
                     deleted = first.delete();
    -  212   -
                 }
    -  213   -
             } finally {
    -  214  0
                 if (first != null && (first.exists() || !deleted)) {
    -  215  0
                     first.deleteOnExit();
    -  216   -
                 }
    -  217   -
             }
    -  218   -
             try {
    -  219  0
                 deleted = false;
    -  220  0
                 if (second != null && second.exists()) {
    -  221  0
                     deleted = second.delete();
    -  222   -
                 }
    -  223   -
             } finally {
    -  224  0
                 if (second != null && (second.exists() || !deleted)) {
    -  225  0
                     second.deleteOnExit();
    -  226   -
                 }
    -  227   -
             }
    -  228  0
         }
    -  229   -
     
    -  230   -
         /**
    -  231   -
          * Checks the file header to see if it is an XML file.
    -  232   -
          *
    -  233   -
          * @param file the file to check
    -  234   -
          * @return true if the file is XML
    -  235   -
          */
    -  236   -
         public static boolean isXml(File file) {
    -  237  4
             if (file == null || !file.isFile()) {
    -  238  0
                 return false;
    -  239   -
             }
    -  240  4
             InputStream is = null;
    -  241   -
             try {
    -  242  4
                 is = new FileInputStream(file);
    -  243   -
     
    -  244  4
                 final byte[] buf = new byte[5];
    -  245  4
                 int read = 0;
    -  246   -
                 try {
    -  247  4
                     read = is.read(buf);
    -  248  0
                 } catch (IOException ex) {
    -  249  0
                     return false;
    -  250  4
                 }
    -  251  8
                 return read == 5
    -  252   -
                         && buf[0] == '<'
    -  253   -
                         && (buf[1] == '?')
    -  254   -
                         && (buf[2] == 'x' || buf[2] == 'X')
    -  255   -
                         && (buf[3] == 'm' || buf[3] == 'M')
    -  256   -
                         && (buf[4] == 'l' || buf[4] == 'L');
    -  257  0
             } catch (FileNotFoundException ex) {
    -  258  0
                 return false;
    -  259   -
             } finally {
    -  260  4
                 if (is != null) {
    -  261   -
                     try {
    -  262  4
                         is.close();
    -  263  0
                     } catch (IOException ex) {
    -  264  0
                         LOGGER.debug("Error closing stream", ex);
    -  265  4
                     }
    -  266   -
                 }
    -  267   -
             }
    -  268  
         }
    -  269   +  204  
     
    -  270   +  205  
         /**
    -  271   -
          * Extracts the file contained in a gzip archive. The extracted file is placed in the exact same path as the file specified.
    -  272   -
          *
    -  273   -
          * @param file the archive file
    -  274   -
          * @throws FileNotFoundException thrown if the file does not exist
    -  275   -
          * @throws IOException thrown if there is an error extracting the file.
    -  276   +  206   +
          * Attempts to delete the files that were downloaded.
    +  207  
          */
    -  277   -
         private void extractGzip(File file) throws FileNotFoundException, IOException {
    -  278  2
             final String originalPath = file.getPath();
    -  279  2
             final File gzip = new File(originalPath + ".gz");
    -  280  2
             if (gzip.isFile() && !gzip.delete()) {
    -  281  0
                 gzip.deleteOnExit();
    -  282   +  208   +
         public void cleanup() {
    +  209  0
             if (first != null && first.exists() && first.delete()) {
    +  210  0
                 LOGGER.debug("Failed to delete first temporary file {}", second.toString());
    +  211  0
                 first.deleteOnExit();
    +  212  
             }
    -  283  2
             if (!file.renameTo(gzip)) {
    -  284  0
                 throw new IOException("Unable to rename '" + file.getPath() + "'");
    -  285   +  213  0
             if (second != null && second.exists() && !second.delete()) {
    +  214  0
                 LOGGER.debug("Failed to delete second temporary file {}", second.toString());
    +  215  0
                 second.deleteOnExit();
    +  216  
             }
    -  286  2
             final File newfile = new File(originalPath);
    -  287   +  217  0
         }
    +  218  
     
    -  288  2
             final byte[] buffer = new byte[4096];
    -  289   -
     
    -  290  2
             GZIPInputStream cin = null;
    -  291  2
             FileOutputStream out = null;
    -  292   +  219   +
         /**
    +  220   +
          * Checks the file header to see if it is an XML file.
    +  221   +
          *
    +  222   +
          * @param file the file to check
    +  223   +
          * @return true if the file is XML
    +  224   +
          */
    +  225   +
         public static boolean isXml(File file) {
    +  226  4
             if (file == null || !file.isFile()) {
    +  227  0
                 return false;
    +  228   +
             }
    +  229  4
             InputStream is = null;
    +  230  
             try {
    -  293  2
                 cin = new GZIPInputStream(new FileInputStream(gzip));
    -  294  2
                 out = new FileOutputStream(newfile);
    -  295   +  231  4
                 is = new FileInputStream(file);
    +  232  
     
    -  296   -
                 int len;
    -  297  1060
                 while ((len = cin.read(buffer)) > 0) {
    -  298  1058
                     out.write(buffer, 0, len);
    -  299   -
                 }
    -  300   +  233  4
                 final byte[] buf = new byte[5];
    +  234  4
                 int read = 0;
    +  235   +
                 try {
    +  236  4
                     read = is.read(buf);
    +  237  0
                 } catch (IOException ex) {
    +  238  0
                     return false;
    +  239  4
                 }
    +  240  8
                 return read == 5
    +  241   +
                         && buf[0] == '<'
    +  242   +
                         && (buf[1] == '?')
    +  243   +
                         && (buf[2] == 'x' || buf[2] == 'X')
    +  244   +
                         && (buf[3] == 'm' || buf[3] == 'M')
    +  245   +
                         && (buf[4] == 'l' || buf[4] == 'L');
    +  246  0
             } catch (FileNotFoundException ex) {
    +  247  0
                 return false;
    +  248  
             } finally {
    -  301  2
                 if (cin != null) {
    -  302   +  249  4
                 if (is != null) {
    +  250  
                     try {
    -  303  2
                         cin.close();
    -  304  0
                     } catch (IOException ex) {
    -  305  0
                         LOGGER.trace("ignore", ex);
    -  306  2
                     }
    -  307   +  251  4
                         is.close();
    +  252  0
                     } catch (IOException ex) {
    +  253  0
                         LOGGER.debug("Error closing stream", ex);
    +  254  4
                     }
    +  255  
                 }
    -  308  2
                 if (out != null) {
    -  309   -
                     try {
    -  310  2
                         out.close();
    -  311  0
                     } catch (IOException ex) {
    -  312  0
                         LOGGER.trace("ignore", ex);
    -  313  2
                     }
    -  314   -
                 }
    -  315  2
                 if (gzip.isFile()) {
    -  316  2
                     FileUtils.deleteQuietly(gzip);
    -  317   -
                 }
    -  318   +  256  
             }
    -  319  2
         }
    -  320   +  257   +
         }
    +  258   +
     
    +  259   +
         /**
    +  260   +
          * Extracts the file contained in a gzip archive. The extracted file is
    +  261   +
          * placed in the exact same path as the file specified.
    +  262   +
          *
    +  263   +
          * @param file the archive file
    +  264   +
          * @throws FileNotFoundException thrown if the file does not exist
    +  265   +
          * @throws IOException thrown if there is an error extracting the file.
    +  266   +
          */
    +  267   +
         private void extractGzip(File file) throws FileNotFoundException, IOException {
    +  268  2
             final String originalPath = file.getPath();
    +  269  2
             final File gzip = new File(originalPath + ".gz");
    +  270  2
             if (gzip.isFile() && !gzip.delete()) {
    +  271  0
                 LOGGER.debug("Failed to delete initial temporary file when extracting 'gz' {}", gzip.toString());
    +  272  0
                 gzip.deleteOnExit();
    +  273   +
             }
    +  274  2
             if (!file.renameTo(gzip)) {
    +  275  0
                 throw new IOException("Unable to rename '" + file.getPath() + "'");
    +  276   +
             }
    +  277  2
             final File newfile = new File(originalPath);
    +  278   +
     
    +  279  2
             final byte[] buffer = new byte[4096];
    +  280   +
     
    +  281  2
             GZIPInputStream cin = null;
    +  282  2
             FileOutputStream out = null;
    +  283   +
             try {
    +  284  2
                 cin = new GZIPInputStream(new FileInputStream(gzip));
    +  285  2
                 out = new FileOutputStream(newfile);
    +  286   +
     
    +  287   +
                 int len;
    +  288  591
                 while ((len = cin.read(buffer)) > 0) {
    +  289  589
                     out.write(buffer, 0, len);
    +  290   +
                 }
    +  291   +
             } finally {
    +  292  2
                 if (cin != null) {
    +  293   +
                     try {
    +  294  2
                         cin.close();
    +  295  0
                     } catch (IOException ex) {
    +  296  0
                         LOGGER.trace("ignore", ex);
    +  297  2
                     }
    +  298   +
                 }
    +  299  2
                 if (out != null) {
    +  300   +
                     try {
    +  301  2
                         out.close();
    +  302  0
                     } catch (IOException ex) {
    +  303  0
                         LOGGER.trace("ignore", ex);
    +  304  2
                     }
    +  305   +
                 }
    +  306  2
                 if (gzip.isFile() && !FileUtils.deleteQuietly(gzip)) {
    +  307  0
                     LOGGER.debug("Failed to delete temporary file when extracting 'gz' {}", gzip.toString());
    +  308  0
                     gzip.deleteOnExit();
    +  309   +
                 }
    +  310   +
             }
    +  311  2
         }
    +  312  
     }
    - + 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 5ed3d4cec..a2d7bd8a8 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 b4e35dfb2..d7f4d6914 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 8fa8ca593..32fa3bd14 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 d157fbadf..5950499ff 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 @@ -336,6 +336,6 @@
     }
    - + 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 cb23ec4e4..958e30ad4 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 81b2530b6..cf0421329 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  85
     public enum Confidence {
    +  25  95
     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 0c38f5eea..d37592203 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Dependency.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Dependency.html @@ -12,7 +12,7 @@
     
    - +
    Classes in this File Line Coverage Branch Coverage Complexity
    Dependency
    64%
    122/189
    50%
    20/40
    1.414
    Dependency
    62%
    119/189
    50%
    20/40
    1.414
     
    @@ -206,8 +206,8 @@
          */
     96  
         public void setPackagePath(String packagePath) {
    -  97  4
             this.packagePath = packagePath;
    -  98  4
         }
    +  97  6
             this.packagePath = packagePath;
    +  98  6
         }
     99  
     
     100   @@ -266,15 +266,15 @@
          * Constructs a new Dependency object.
     127  
          */
    -  128  92
         public Dependency() {
    -  129  92
             vendorEvidence = new EvidenceCollection();
    -  130  92
             productEvidence = new EvidenceCollection();
    -  131  92
             versionEvidence = new EvidenceCollection();
    -  132  92
             identifiers = new TreeSet<Identifier>();
    -  133  92
             vulnerabilities = new TreeSet<Vulnerability>(new VulnerabilityComparator());
    -  134  92
             suppressedIdentifiers = new TreeSet<Identifier>();
    -  135  92
             suppressedVulnerabilities = new TreeSet<Vulnerability>(new VulnerabilityComparator());
    -  136  92
         }
    +  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
         }
     137  
     
     138   @@ -289,13 +289,13 @@
          */
     143  
         public Dependency(File file) {
    -  144  71
             this();
    -  145  71
             this.actualFilePath = file.getAbsolutePath();
    -  146  71
             this.filePath = this.actualFilePath;
    -  147  71
             this.fileName = file.getName();
    -  148  71
             this.packagePath = filePath;
    -  149  71
             determineHashes(file);
    -  150  71
         }
    +  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
         }
     151  
     
     152   @@ -310,7 +310,7 @@
          */
     157  
         public String getFileName() {
    -  158  50
             return this.fileName;
    +  158  74
             return this.fileName;
     159  
         }
     160   @@ -387,7 +387,7 @@
          */
     200  
         public String getActualFilePath() {
    -  201  72
             return this.actualFilePath;
    +  201  69
             return this.actualFilePath;
     202  
         }
     203   @@ -404,7 +404,7 @@
          */
     209  
         public File getActualFile() {
    -  210  134
             return new File(this.actualFilePath);
    +  210  144
             return new File(this.actualFilePath);
     211  
         }
     212   @@ -435,7 +435,7 @@
          * The file name to display in reports.
     227  
          */
    -  228  92
         private String displayName = null;
    +  228  91
         private String displayName = null;
     229  
     
     230   @@ -499,7 +499,7 @@
          */
     262  
         public String getFilePath() {
    -  263  118
             return this.filePath;
    +  263  120
             return this.filePath;
     264  
         }
     265   @@ -533,8 +533,8 @@
          */
     280  
         public void setMd5sum(String md5sum) {
    -  281  72
             this.md5sum = md5sum;
    -  282  72
         }
    +  281  71
             this.md5sum = md5sum;
    +  282  71
         }
     283  
     
     284   @@ -566,8 +566,8 @@
          */
     298  
         public void setSha1sum(String sha1sum) {
    -  299  110
             this.sha1sum = sha1sum;
    -  300  110
         }
    +  299  109
             this.sha1sum = sha1sum;
    +  300  109
         }
     301  
     
     302   @@ -582,7 +582,7 @@
          */
     307  
         public Set<Identifier> getIdentifiers() {
    -  308  460
             return this.identifiers;
    +  308  468
             return this.identifiers;
     309  
         }
     310   @@ -904,7 +904,7 @@
          */
     491  
         public EvidenceCollection getVendorEvidence() {
    -  492  176
             return this.vendorEvidence;
    +  492  175
             return this.vendorEvidence;
     493  
         }
     494   @@ -921,7 +921,7 @@
          */
     500  
         public EvidenceCollection getProductEvidence() {
    -  501  240
             return this.productEvidence;
    +  501  212
             return this.productEvidence;
     502  
         }
     503   @@ -938,7 +938,7 @@
          */
     509  
         public EvidenceCollection getVersionEvidence() {
    -  510  111
             return this.versionEvidence;
    +  510  110
             return this.versionEvidence;
     511  
         }
     512   @@ -1084,22 +1084,22 @@
          */
     587  
         private void determineHashes(File file) {
    -  588  71
             String md5 = null;
    -  589  71
             String sha1 = null;
    +  588  70
             String md5 = null;
    +  589  70
             String sha1 = null;
     590  
             try {
    -  591  71
                 md5 = Checksum.getMD5Checksum(file);
    +  591  70
                 md5 = Checksum.getMD5Checksum(file);
     592  70
                 sha1 = Checksum.getSHA1Checksum(file);
    -  593  1
             } catch (IOException ex) {
    -  594  1
                 LOGGER.warn("Unable to read '{}' to determine hashes.", file.getName());
    -  595  1
                 LOGGER.debug("", ex);
    +  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  71
             }
    -  600  71
             this.setMd5sum(md5);
    -  601  71
             this.setSha1sum(sha1);
    -  602  71
         }
    +  599  70
             }
    +  600  70
             this.setMd5sum(md5);
    +  601  70
             this.setSha1sum(sha1);
    +  602  70
         }
     603  
     
     604   @@ -1124,7 +1124,7 @@
          * A collection of related dependencies.
     615  
          */
    -  616  92
         private Set<Dependency> relatedDependencies = new TreeSet<Dependency>();
    +  616  91
         private Set<Dependency> relatedDependencies = new TreeSet<Dependency>();
     617  
     
     618   @@ -1154,7 +1154,7 @@
          * A list of projects that reference this dependency.
     631  
          */
    -  632  92
         private Set<String> projectReferences = new HashSet<String>();
    +  632  91
         private Set<String> projectReferences = new HashSet<String>();
     633  
     
     634   @@ -1279,7 +1279,7 @@
          * A list of available versions.
     703  
          */
    -  704  92
         private List<String> availableVersions = new ArrayList<String>();
    +  704  91
         private List<String> availableVersions = new ArrayList<String>();
     705  
     
     706   @@ -1413,24 +1413,24 @@
         @Override
     784  
         public int hashCode() {
    -  785  200
             return new HashCodeBuilder(MAGIC_HASH_INIT_VALUE, MAGIC_HASH_MULTIPLIER)
    -  786  100
                     .append(actualFilePath)
    -  787  100
                     .append(filePath)
    -  788  100
                     .append(fileName)
    -  789  100
                     .append(md5sum)
    -  790  100
                     .append(sha1sum)
    -  791  100
                     .append(identifiers)
    -  792  100
                     .append(vendorEvidence)
    -  793  100
                     .append(productEvidence)
    -  794  100
                     .append(versionEvidence)
    -  795  100
                     .append(description)
    -  796  100
                     .append(license)
    -  797  100
                     .append(vulnerabilities)
    +  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)
     798  
                     //.append(relatedDependencies)
    -  799  100
                     .append(projectReferences)
    -  800  100
                     .append(availableVersions)
    -  801  100
                     .toHashCode();
    +  799  108
                     .append(projectReferences)
    +  800  108
                     .append(availableVersions)
    +  801  108
                     .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 90121200d..4fcf5409b 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  691
     public class Evidence implements Serializable, Comparable<Evidence> {
    +  31  692
     public class Evidence implements Serializable, Comparable<Evidence> {
     32  
     
     33   @@ -134,12 +134,12 @@
          * @param confidence the confidence of the evidence.
     60  
          */
    -  61  428
         public Evidence(String source, String name, String value, Confidence confidence) {
    -  62  428
             this.source = source;
    -  63  428
             this.name = name;
    -  64  428
             this.value = value;
    -  65  428
             this.confidence = confidence;
    -  66  428
         }
    +  61  437
         public Evidence(String source, String name, String value, Confidence confidence) {
    +  62  437
             this.source = source;
    +  63  437
             this.name = name;
    +  64  437
             this.value = value;
    +  65  437
             this.confidence = confidence;
    +  66  437
         }
     67  
     
     68   @@ -164,7 +164,7 @@
          */
     78  
         public String getName() {
    -  79  27
             return name;
    +  79  25
             return name;
     80  
         }
     81   @@ -207,7 +207,7 @@
          */
     101  
         public String getSource() {
    -  102  16
             return source;
    +  102  14
             return source;
     103  
         }
     104   @@ -250,8 +250,8 @@
          */
     124  
         public String getValue() {
    -  125  446
             used = true;
    -  126  446
             return value;
    +  125  406
             used = true;
    +  126  406
             return value;
     127  
         }
     128   @@ -314,7 +314,7 @@
          */
     159  
         public boolean isUsed() {
    -  160  651
             return used;
    +  160  340
             return used;
     161  
         }
     162   @@ -392,12 +392,12 @@
         @Override
     201  
         public int hashCode() {
    -  202  16
             return new HashCodeBuilder(MAGIC_HASH_INIT_VALUE, MAGIC_HASH_MULTIPLIER)
    -  203  8
                 .append(StringUtils.lowerCase(name))
    -  204  8
                 .append(StringUtils.lowerCase(source))
    -  205  8
                 .append(StringUtils.lowerCase(value))
    -  206  8
                 .append(confidence)
    -  207  8
                 .toHashCode();
    +  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   @@ -453,15 +453,15 @@
         @Override
     239  
         public int compareTo(Evidence o) {
    -  240  701
             if (o == null) {
    +  240  702
             if (o == null) {
     241  0
                 return 1;
     242  
             }
    -  243  701
             if (StringUtils.equalsIgnoreCase(source, o.source)) {
    -  244  450
                 if (StringUtils.equalsIgnoreCase(name, o.name)) {
    -  245  244
                     if (StringUtils.equalsIgnoreCase(value, o.value)) {
    -  246  219
                         if (ObjectUtils.equals(confidence, o.confidence)) {
    -  247  217
                             return 0; //they are equal
    +  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);
    @@ -474,7 +474,7 @@
                     }
     254  
                 } else {
    -  255  206
                     return compareToIgnoreCaseWithNullCheck(name, o.name);
    +  255  211
                     return compareToIgnoreCaseWithNullCheck(name, o.name);
     256  
                 }
     257   @@ -504,15 +504,15 @@
          */
     270  
         private int compareToIgnoreCaseWithNullCheck(String me, String other) {
    -  271  482
             if (me == null && other == null) {
    +  271  487
             if (me == null && other == null) {
     272  0
                 return 0;
    -  273  482
             } else if (me == null) {
    +  273  487
             } else if (me == null) {
     274  0
                 return -1; //the other string is greater then me
    -  275  482
             } else if (other == null) {
    +  275  487
             } else if (other == null) {
     276  0
                 return 1; //me is greater then the other string
     277  
             }
    -  278  482
             return me.compareToIgnoreCase(other);
    +  278  487
             return me.compareToIgnoreCase(other);
     279  
         }
     280   @@ -538,6 +538,6 @@
     }
    - + 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 9abbcb33c..53b9e1374 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.EvidenceCollection.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.EvidenceCollection.html @@ -189,12 +189,12 @@
          * Used to iterate over evidence that has was used (aka read) from the collection.
     88  
          */
    -  89  650
         private static final Filter<Evidence> EVIDENCE_USED = new Filter<Evidence>() {
    +  89  339
         private static final Filter<Evidence> EVIDENCE_USED = new Filter<Evidence>() {
     90  
             @Override
     91  
             public boolean passes(Evidence evidence) {
    -  92  649
                 return evidence.isUsed();
    +  92  338
                 return evidence.isUsed();
     93  
             }
     94   @@ -252,10 +252,10 @@
          * Creates a new EvidenceCollection.
     124  
          */
    -  125  288
         public EvidenceCollection() {
    -  126  288
             list = new TreeSet<Evidence>();
    -  127  288
             weightedStrings = new HashSet<String>();
    -  128  288
         }
    +  125  285
         public EvidenceCollection() {
    +  126  285
             list = new TreeSet<Evidence>();
    +  127  285
             weightedStrings = new HashSet<String>();
    +  128  285
         }
     129  
     
     130   @@ -270,8 +270,8 @@
          */
     135  
         public void addEvidence(Evidence e) {
    -  136  330
             list.add(e);
    -  137  330
         }
    +  136  332
             list.add(e);
    +  137  332
         }
     138  
     
     139   @@ -292,9 +292,9 @@
          */
     147  
         public void addEvidence(String source, String name, String value, Confidence confidence) {
    -  148  319
             final Evidence e = new Evidence(source, name, value, confidence);
    -  149  319
             addEvidence(e);
    -  150  319
         }
    +  148  327
             final Evidence e = new Evidence(source, name, value, confidence);
    +  149  327
             addEvidence(e);
    +  150  327
         }
     151  
     
     152   @@ -356,7 +356,7 @@
          */
     182  
         public Set<Evidence> getEvidence() {
    -  183  44
             return list;
    +  183  41
             return list;
     184  
         }
     185   @@ -407,18 +407,18 @@
          */
     212  
         public Set<Evidence> getEvidence(String source, String name) {
    -  213  8
             if (source == null || name == null) {
    +  213  6
             if (source == null || name == null) {
     214  0
                 return null;
     215  
             }
    -  216  8
             final Set<Evidence> ret = new HashSet<Evidence>();
    -  217  8
             for (Evidence e : list) {
    -  218  11
                 if (source.equals(e.getSource()) && name.equals(e.getName())) {
    -  219  5
                     ret.add(e);
    +  216  6
             final Set<Evidence> ret = new HashSet<Evidence>();
    +  217  6
             for (Evidence e : list) {
    +  218  9
                 if (source.equals(e.getSource()) && name.equals(e.getName())) {
    +  219  3
                     ret.add(e);
     220  
                 }
    -  221  11
             }
    -  222  8
             return ret;
    +  221  9
             }
    +  222  6
             return ret;
     223  
         }
     224   @@ -437,7 +437,7 @@
         @Override
     231  
         public Iterator<Evidence> iterator() {
    -  232  105
             return list.iterator();
    +  232  67
             return list.iterator();
     233  
         }
     234   @@ -456,23 +456,23 @@
          */
     241  
         public boolean containsUsedString(String text) {
    -  242  90
             if (text == null) {
    +  242  52
             if (text == null) {
     243  0
                 return false;
     244  
             }
    -  245  90
             final String textToTest = text.toLowerCase();
    +  245  52
             final String textToTest = text.toLowerCase();
     246  
     
    -  247  90
             for (Evidence e : EvidenceCollection.EVIDENCE_USED.filter(this)) {
    +  247  52
             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  299
                 final String value = urlCorrection(e.getValue().toLowerCase()).replaceAll("[\\s_-]", "");
    -  250  299
                 if (value.contains(textToTest)) {
    +  249  254
                 final String value = urlCorrection(e.getValue().toLowerCase()).replaceAll("[\\s_-]", "");
    +  250  254
                 if (value.contains(textToTest)) {
     251  27
                     return true;
     252  
                 }
    -  253  272
             }
    -  254  63
             return false;
    +  253  227
             }
    +  254  25
             return false;
     255  
         }
     256   @@ -634,11 +634,11 @@
         @Override
     351  
         public String toString() {
    -  352  43
             final StringBuilder sb = new StringBuilder();
    -  353  43
             for (Evidence e : this.list) {
    -  354  85
                 sb.append(e.getValue()).append(' ');
    -  355  85
             }
    -  356  43
             return sb.toString();
    +  352  47
             final StringBuilder sb = new StringBuilder();
    +  353  47
             for (Evidence e : this.list) {
    +  354  92
                 sb.append(e.getValue()).append(' ');
    +  355  92
             }
    +  356  47
             return sb.toString();
     357  
         }
     358   @@ -698,8 +698,8 @@
          */
     386  
         private String urlCorrection(String value) {
    -  387  299
             if (value == null || !UrlStringUtils.containsUrl(value)) {
    -  388  280
                 return value;
    +  387  254
             if (value == null || !UrlStringUtils.containsUrl(value)) {
    +  388  235
                 return value;
     389  
             }
     390  19
             final StringBuilder sb = new StringBuilder(value.length());
    @@ -728,6 +728,6 @@
     }
    - + 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 2325941c7..b3bb49e1e 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  31
     public class Identifier implements Serializable, Comparable<Identifier> {
    +  26  33
     public class Identifier implements Serializable, Comparable<Identifier> {
     27  
     
     28   @@ -110,11 +110,11 @@
          * @param url the identifier url.
     48  
          */
    -  49  28
         public Identifier(String type, String value, String url) {
    -  50  28
             this.type = type;
    -  51  28
             this.value = value;
    -  52  28
             this.url = url;
    -  53  28
         }
    +  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
         }
     54  
     
     55   @@ -287,7 +287,7 @@
          */
     145  
         public String getType() {
    -  146  378
             return type;
    +  146  384
             return type;
     147  
         }
     148   @@ -437,6 +437,6 @@
     }
    - + 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 4684783ed..3860f9e39 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Reference.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Reference.html @@ -12,7 +12,7 @@
     
    - +
    Classes in this File Line Coverage Branch Coverage Complexity
    Reference
    37%
    13/35
    14%
    5/34
    3.2
    Reference
    36%
    12/33
    0%
    0/28
    2.6
     
    @@ -58,248 +58,236 @@  20  
     import java.io.Serializable;
     21   -
     
    +
     import org.apache.commons.lang3.builder.CompareToBuilder;
     22   -
     /**
    +
     
     23   -
      * An external reference for a vulnerability. This contains a name, URL, and a
    +
     /**
     24   -
      * source.
    +
      * An external reference for a vulnerability. This contains a name, URL, and a
     25   -
      *
    +
      * source.
     26   -
      * @author Jeremy Long
    +
      *
     27   +
      * @author Jeremy Long
    +  28  
      */
    -  28  526
     public class Reference implements Serializable, Comparable<Reference> {
    -  29   -
     
    +  29  526
     public class Reference implements Serializable, Comparable<Reference> {
     30   -
         /**
    +
     
     31   -
          * the serial version uid.
    +
         /**
     32   -
          */
    +
          * the serial version uid.
     33   -
         private static final long serialVersionUID = -3444464824563008021L;
    +
          */
     34   -
         /**
    +
         private static final long serialVersionUID = -3444464824563008021L;
     35   -
          * The name of the reference.
    +
         /**
     36   -
          */
    +
          * The name of the reference.
     37   -
         private String name;
    +
          */
     38   -
     
    +
         private String name;
     39   -
         /**
    +
     
     40   -
          * Get the value of name.
    +
         /**
     41   -
          *
    +
          * Get the value of name.
     42   -
          * @return the value of name
    +
          *
     43   -
          */
    +
          * @return the value of name
     44   +
          */
    +  45  
         public String getName() {
    -  45  0
             return name;
    -  46   -
         }
    +  46  0
             return name;
     47   -
     
    +
         }
     48   -
         /**
    +
     
     49   -
          * Set the value of name.
    +
         /**
     50   -
          *
    +
          * Set the value of name.
     51   -
          * @param name new value of name
    +
          *
     52   -
          */
    +
          * @param name new value of name
     53   +
          */
    +  54  
         public void setName(String name) {
    -  54  163
             this.name = name;
    -  55  163
         }
    -  56   -
         /**
    +  55  163
             this.name = name;
    +  56  163
         }
     57   -
          * the url for the reference.
    +
         /**
     58   -
          */
    +
          * the url for the reference.
     59   -
         private String url;
    +
          */
     60   -
     
    +
         private String url;
     61   -
         /**
    +
     
     62   -
          * Get the value of url.
    +
         /**
     63   -
          *
    +
          * Get the value of url.
     64   -
          * @return the value of url
    +
          *
     65   -
          */
    +
          * @return the value of url
     66   +
          */
    +  67  
         public String getUrl() {
    -  67  0
             return url;
    -  68   -
         }
    +  68  0
             return url;
     69   -
     
    +
         }
     70   -
         /**
    +
     
     71   -
          * Set the value of url.
    +
         /**
     72   -
          *
    +
          * Set the value of url.
     73   -
          * @param url new value of url
    +
          *
     74   -
          */
    +
          * @param url new value of url
     75   +
          */
    +  76  
         public void setUrl(String url) {
    -  76  163
             this.url = url;
    -  77  163
         }
    -  78   -
         /**
    +  77  163
             this.url = url;
    +  78  163
         }
     79   -
          * the source of the reference.
    +
         /**
     80   -
          */
    +
          * the source of the reference.
     81   -
         private String source;
    +
          */
     82   -
     
    +
         private String source;
     83   -
         /**
    +
     
     84   -
          * Get the value of source.
    +
         /**
     85   -
          *
    +
          * Get the value of source.
     86   -
          * @return the value of source
    +
          *
     87   -
          */
    +
          * @return the value of source
     88   +
          */
    +  89  
         public String getSource() {
    -  89  0
             return source;
    -  90   -
         }
    +  90  0
             return source;
     91   -
     
    +
         }
     92   -
         /**
    +
     
     93   -
          * Set the value of source.
    -  94   -
          *
    -  95   -
          * @param source new value of source
    -  96   -
          */
    -  97   -
         public void setSource(String source) {
    -  98  163
             this.source = source;
    -  99  163
         }
    -  100   -
     
    -  101   -
         @Override
    -  102   -
         public String toString() {
    -  103  0
             return "Reference: { name='" + this.name + "', url='" + this.url + "', source='" + this.source + "' }";
    -  104   -
         }
    -  105   -
     
    -  106   -
         @Override
    -  107   -
         public boolean equals(Object obj) {
    -  108  0
             if (obj == null) {
    -  109  0
                 return false;
    -  110   -
             }
    -  111  0
             if (getClass() != obj.getClass()) {
    -  112  0
                 return false;
    -  113   -
             }
    -  114  0
             final Reference other = (Reference) obj;
    -  115  0
             if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
    -  116  0
                 return false;
    -  117   -
             }
    -  118  0
             if ((this.url == null) ? (other.url != null) : !this.url.equals(other.url)) {
    -  119  0
                 return false;
    -  120   -
             }
    -  121  0
             if ((this.source == null) ? (other.source != null) : !this.source.equals(other.source)) {
    -  122  0
                 return false;
    -  123   -
             }
    -  124  0
             return true;
    -  125   -
         }
    -  126   -
     
    -  127   -
         @Override
    -  128   -
         public int hashCode() {
    -  129  0
             int hash = 5;
    -  130  0
             hash = 67 * hash + (this.name != null ? this.name.hashCode() : 0);
    -  131  0
             hash = 67 * hash + (this.url != null ? this.url.hashCode() : 0);
    -  132  0
             hash = 67 * hash + (this.source != null ? this.source.hashCode() : 0);
    -  133  0
             return hash;
    -  134   -
         }
    -  135   -
     
    -  136  
         /**
    -  137   -
          * Implementation of the comparable interface.
    -  138   +  94   +
          * Set the value of source.
    +  95  
          *
    -  139   -
          * @param o the Reference being compared
    -  140   -
          * @return an integer indicating the ordering of the two objects
    -  141   +  96   +
          * @param source new value of source
    +  97  
          */
    -  142   +  98   +
         public void setSource(String source) {
    +  99  163
             this.source = source;
    +  100  163
         }
    +  101   +
     
    +  102  
         @Override
    -  143   -
         public int compareTo(Reference o) {
    -  144  363
             if (source.equals(o.source)) {
    -  145  105
                 if (name.equals(o.name)) {
    -  146  35
                     if (url.equals(o.url)) {
    -  147  35
                         return 0; //they are equal
    -  148   -
                     } else {
    -  149  0
                         return url.compareTo(o.url);
    -  150   -
                     }
    -  151   -
                 } else {
    -  152  70
                     return name.compareTo(o.name);
    -  153   -
                 }
    -  154   -
             } else {
    -  155  258
                 return source.compareTo(o.source);
    -  156   -
             }
    -  157   +  103   +
         public String toString() {
    +  104  0
             return "Reference: { name='" + this.name + "', url='" + this.url + "', source='" + this.source + "' }";
    +  105  
         }
    -  158   +  106   +
     
    +  107   +
         @Override
    +  108   +
         public boolean equals(Object obj) {
    +  109  0
             if (obj == null) {
    +  110  0
                 return false;
    +  111   +
             }
    +  112  0
             if (getClass() != obj.getClass()) {
    +  113  0
                 return false;
    +  114   +
             }
    +  115  0
             final Reference other = (Reference) obj;
    +  116  0
             if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
    +  117  0
                 return false;
    +  118   +
             }
    +  119  0
             if ((this.url == null) ? (other.url != null) : !this.url.equals(other.url)) {
    +  120  0
                 return false;
    +  121   +
             }
    +  122  0
             if ((this.source == null) ? (other.source != null) : !this.source.equals(other.source)) {
    +  123  0
                 return false;
    +  124   +
             }
    +  125  0
             return true;
    +  126   +
         }
    +  127   +
     
    +  128   +
         @Override
    +  129   +
         public int hashCode() {
    +  130  0
             int hash = 5;
    +  131  0
             hash = 67 * hash + (this.name != null ? this.name.hashCode() : 0);
    +  132  0
             hash = 67 * hash + (this.url != null ? this.url.hashCode() : 0);
    +  133  0
             hash = 67 * hash + (this.source != null ? this.source.hashCode() : 0);
    +  134  0
             return hash;
    +  135   +
         }
    +  136   +
     
    +  137   +
         /**
    +  138   +
          * Implementation of the comparable interface.
    +  139   +
          *
    +  140   +
          * @param o the Reference being compared
    +  141   +
          * @return an integer indicating the ordering of the two objects
    +  142   +
          */
    +  143   +
         @Override
    +  144   +
         public int compareTo(Reference o) {
    +  145  726
             return new CompareToBuilder()
    +  146  363
                     .append(source, o.source)
    +  147  363
                     .append(name, o.name)
    +  148  363
                     .append(url, o.url)
    +  149  363
                     .toComparison();
    +  150   +
         }
    +  151  
     }
    - + 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 58c3ee7d7..35f0f5924 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
    56%
    50/89
    22%
    5/22
    1.324
    Vulnerability
    54%
    50/91
    22%
    5/22
    1.324
     
    @@ -64,800 +64,810 @@  23  
     import java.util.TreeSet;
     24   -
     
    +
     import org.apache.commons.lang3.builder.CompareToBuilder;
     25   -
     /**
    +
     
     26   -
      * Contains the information about a vulnerability.
    +
     /**
     27   -
      *
    +
      * Contains the information about a vulnerability.
     28   -
      * @author Jeremy Long
    +
      *
     29   +
      * @author Jeremy Long
    +  30  
      */
    -  30  40
     public class Vulnerability implements Serializable, Comparable<Vulnerability> {
    -  31   -
     
    +  31  40
     public class Vulnerability implements Serializable, Comparable<Vulnerability> {
     32   -
         /**
    +
     
     33   -
          * The serial version uid.
    +
         /**
     34   -
          */
    +
          * The serial version uid.
     35   -
         private static final long serialVersionUID = 307319490326651052L;
    +
          */
     36   -
     
    +
         private static final long serialVersionUID = 307319490326651052L;
     37   -
         /**
    +
     
     38   -
          * The name of the vulnerability.
    +
         /**
     39   -
          */
    +
          * The name of the vulnerability.
     40   -
         private String name;
    +
          */
     41   -
     
    +
         private String name;
     42   -
         /**
    +
     
     43   -
          * Get the value of name.
    +
         /**
     44   -
          *
    +
          * Get the value of name.
     45   -
          * @return the value of name
    +
          *
     46   -
          */
    +
          * @return the value of name
     47   +
          */
    +  48  
         public String getName() {
    -  48  73
             return name;
    -  49   -
         }
    +  49  73
             return name;
     50   -
     
    +
         }
     51   -
         /**
    +
     
     52   -
          * Set the value of name.
    +
         /**
     53   -
          *
    +
          * Set the value of name.
     54   -
          * @param name new value of name
    +
          *
     55   -
          */
    +
          * @param name new value of name
     56   +
          */
    +  57  
         public void setName(String name) {
    -  57  37
             this.name = name;
    -  58  37
         }
    -  59   -
         /**
    +  58  37
             this.name = name;
    +  59  37
         }
     60   -
          * the description of the vulnerability.
    +
         /**
     61   -
          */
    +
          * the description of the vulnerability.
     62   -
         private String description;
    +
          */
     63   -
     
    +
         private String description;
     64   -
         /**
    +
     
     65   -
          * Get the value of description.
    +
         /**
     66   -
          *
    +
          * Get the value of description.
     67   -
          * @return the value of description
    +
          *
     68   -
          */
    +
          * @return the value of description
     69   +
          */
    +  70  
         public String getDescription() {
    -  70  0
             return description;
    -  71   -
         }
    +  71  0
             return description;
     72   -
     
    +
         }
     73   -
         /**
    +
     
     74   -
          * Set the value of description.
    +
         /**
     75   -
          *
    +
          * Set the value of description.
     76   -
          * @param description new value of description
    +
          *
     77   -
          */
    +
          * @param description new value of description
     78   +
          */
    +  79  
         public void setDescription(String description) {
    -  79  36
             this.description = description;
    -  80  36
         }
    -  81   -
         /**
    +  80  36
             this.description = description;
    +  81  36
         }
     82   -
          * References for this vulnerability.
    +
         /**
     83   +
          * References for this vulnerability.
    +  84  
          */
    -  84  40
         private SortedSet<Reference> references = new TreeSet<Reference>();
    -  85   -
     
    +  85  40
         private SortedSet<Reference> references = new TreeSet<Reference>();
     86   -
         /**
    +
     
     87   -
          * Get the value of references.
    +
         /**
     88   -
          *
    +
          * Get the value of references.
     89   -
          * @return the value of references
    +
          *
     90   -
          */
    +
          * @return the value of references
     91   +
          */
    +  92  
         public Set<Reference> getReferences() {
    -  92  0
             return references;
    -  93   -
         }
    +  93  0
             return references;
     94   -
     
    +
         }
     95   -
         /**
    +
     
     96   -
          * Set the value of references.
    +
         /**
     97   -
          *
    +
          * Set the value of references.
     98   -
          * @param references new value of references
    +
          *
     99   -
          */
    +
          * @param references new value of references
     100   +
          */
    +  101  
         public void setReferences(SortedSet<Reference> references) {
    -  101  0
             this.references = references;
    -  102  0
         }
    -  103   -
     
    +  102  0
             this.references = references;
    +  103  0
         }
     104   -
         /**
    +
     
     105   -
          * Adds a reference to the references collection.
    +
         /**
     106   -
          *
    +
          * Adds a reference to the references collection.
     107   -
          * @param ref a reference for the vulnerability
    +
          *
     108   -
          */
    +
          * @param ref a reference for the vulnerability
     109   +
          */
    +  110  
         public void addReference(Reference ref) {
    -  110  95
             this.references.add(ref);
    -  111  95
         }
    -  112   -
     
    +  111  95
             this.references.add(ref);
    +  112  95
         }
     113   -
         /**
    +
     
     114   -
          * Adds a reference.
    +
         /**
     115   -
          *
    +
          * Adds a reference.
     116   -
          * @param referenceSource the source of the reference
    +
          *
     117   -
          * @param referenceName the referenceName of the reference
    +
          * @param referenceSource the source of the reference
     118   -
          * @param referenceUrl the url of the reference
    +
          * @param referenceName the referenceName of the reference
     119   -
          */
    +
          * @param referenceUrl the url of the reference
     120   +
          */
    +  121  
         public void addReference(String referenceSource, String referenceName, String referenceUrl) {
    -  121  68
             final Reference ref = new Reference();
    -  122  68
             ref.setSource(referenceSource);
    -  123  68
             ref.setName(referenceName);
    -  124  68
             ref.setUrl(referenceUrl);
    -  125  68
             this.references.add(ref);
    -  126  68
         }
    -  127   -
         /**
    +  122  68
             final Reference ref = new Reference();
    +  123  68
             ref.setSource(referenceSource);
    +  124  68
             ref.setName(referenceName);
    +  125  68
             ref.setUrl(referenceUrl);
    +  126  68
             this.references.add(ref);
    +  127  68
         }
     128   -
          * A set of vulnerable software.
    +
         /**
     129   +
          * A set of vulnerable software.
    +  130  
          */
    -  130  40
         private SortedSet<VulnerableSoftware> vulnerableSoftware = new TreeSet<VulnerableSoftware>();
    -  131   -
     
    +  131  40
         private SortedSet<VulnerableSoftware> vulnerableSoftware = new TreeSet<VulnerableSoftware>();
     132   -
         /**
    +
     
     133   -
          * Get the value of vulnerableSoftware.
    +
         /**
     134   -
          *
    +
          * Get the value of vulnerableSoftware.
     135   -
          * @return the value of vulnerableSoftware
    +
          *
     136   -
          */
    +
          * @return the value of vulnerableSoftware
     137   +
          */
    +  138  
         public Set<VulnerableSoftware> getVulnerableSoftware() {
    -  138  3
             return vulnerableSoftware;
    -  139   -
         }
    +  139  3
             return vulnerableSoftware;
     140   -
     
    +
         }
     141   -
         /**
    +
     
     142   -
          * Set the value of vulnerableSoftware.
    +
         /**
     143   -
          *
    +
          * Set the value of vulnerableSoftware.
     144   -
          * @param vulnerableSoftware new value of vulnerableSoftware
    +
          *
     145   -
          */
    +
          * @param vulnerableSoftware new value of vulnerableSoftware
     146   +
          */
    +  147  
         public void setVulnerableSoftware(SortedSet<VulnerableSoftware> vulnerableSoftware) {
    -  147  0
             this.vulnerableSoftware = vulnerableSoftware;
    -  148  0
         }
    -  149   -
     
    +  148  0
             this.vulnerableSoftware = vulnerableSoftware;
    +  149  0
         }
     150   -
         /**
    +
     
     151   -
          * Adds an entry for vulnerable software.
    +
         /**
     152   -
          *
    -  153   -
          * @param cpe string representation of a CPE entry
    -  154   -
          * @return if the add succeeded
    -  155   -
          */
    -  156   -
         public boolean addVulnerableSoftware(String cpe) {
    -  157  876
             return addVulnerableSoftware(cpe, null);
    -  158   -
         }
    -  159   -
     
    -  160   -
         /**
    -  161  
          * Adds an entry for vulnerable software.
    -  162   +  153  
          *
    -  163   -
          * @param cpe string representation of a cpe
    -  164   -
          * @param previousVersion the previous version (previousVersion - cpe would be considered vulnerable)
    -  165   +  154   +
          * @param cpe string representation of a CPE entry
    +  155  
          * @return if the add succeeded
    +  156   +
          */
    +  157   +
         public boolean addVulnerableSoftware(String cpe) {
    +  158  876
             return addVulnerableSoftware(cpe, null);
    +  159   +
         }
    +  160   +
     
    +  161   +
         /**
    +  162   +
          * Adds an entry for vulnerable software.
    +  163   +
          *
    +  164   +
          * @param cpe string representation of a cpe
    +  165   +
          * @param previousVersion the previous version (previousVersion - cpe would
     166   -
          */
    +
          * be considered vulnerable)
     167   +
          * @return if the add succeeded
    +  168   +
          */
    +  169  
         public boolean addVulnerableSoftware(String cpe, String previousVersion) {
    -  168  947
             final VulnerableSoftware vs = new VulnerableSoftware();
    -  169  947
             vs.setCpe(cpe);
    -  170  947
             if (previousVersion != null) {
    -  171  9
                 vs.setPreviousVersion(previousVersion);
    -  172   -
             }
    -  173  947
             return updateVulnerableSoftware(vs);
    +  170  947
             final VulnerableSoftware vs = new VulnerableSoftware();
    +  171  947
             vs.setCpe(cpe);
    +  172  947
             if (previousVersion != null) {
    +  173  9
                 vs.setPreviousVersion(previousVersion);
     174   -
         }
    -  175   -
     
    +
             }
    +  175  947
             return updateVulnerableSoftware(vs);
     176   -
         /**
    +
         }
     177   -
          * Adds or updates a vulnerable software entry.
    +
     
     178   -
          *
    +
         /**
     179   -
          * @param vulnSoftware the vulnerable software
    +
          * Adds or updates a vulnerable software entry.
     180   -
          * @return if the update succeeded
    +
          *
     181   -
          */
    +
          * @param vulnSoftware the vulnerable software
     182   +
          * @return if the update succeeded
    +  183   +
          */
    +  184  
         public boolean updateVulnerableSoftware(VulnerableSoftware vulnSoftware) {
    -  183  948
             if (vulnerableSoftware.contains(vulnSoftware)) {
    -  184  3
                 vulnerableSoftware.remove(vulnSoftware);
    -  185   -
             }
    -  186  948
             return vulnerableSoftware.add(vulnSoftware);
    +  185  948
             if (vulnerableSoftware.contains(vulnSoftware)) {
    +  186  3
                 vulnerableSoftware.remove(vulnSoftware);
     187   -
         }
    -  188   -
         /**
    +
             }
    +  188  948
             return vulnerableSoftware.add(vulnSoftware);
     189   -
          * The CWE for the vulnerability.
    +
         }
     190   -
          */
    +
         /**
     191   -
         private String cwe;
    +
          * The CWE for the vulnerability.
     192   -
     
    +
          */
     193   -
         /**
    +
         private String cwe;
     194   -
          * Get the value of cwe.
    +
     
     195   -
          *
    +
         /**
     196   -
          * @return the value of cwe
    +
          * Get the value of cwe.
     197   -
          */
    +
          *
     198   -
         public String getCwe() {
    -  199  2
             return cwe;
    +
          * @return the value of cwe
    +  199   +
          */
     200   -
         }
    -  201   -
     
    +
         public String getCwe() {
    +  201  2
             return cwe;
     202   -
         /**
    +
         }
     203   -
          * Set the value of cwe.
    +
     
     204   -
          *
    +
         /**
     205   -
          * @param cwe new value of cwe
    +
          * Set the value of cwe.
     206   -
          */
    +
          *
     207   +
          * @param cwe new value of cwe
    +  208   +
          */
    +  209  
         public void setCwe(String cwe) {
    -  208  29
             this.cwe = cwe;
    -  209  29
         }
    -  210   -
         /**
    -  211   -
          * CVSS Score.
    +  210  29
             this.cwe = cwe;
    +  211  29
         }
     212   -
          */
    +
         /**
     213   -
         private float cvssScore;
    +
          * CVSS Score.
     214   -
     
    +
          */
     215   -
         /**
    +
         private float cvssScore;
     216   -
          * Get the value of cvssScore.
    +
     
     217   -
          *
    +
         /**
     218   -
          * @return the value of cvssScore
    +
          * Get the value of cvssScore.
     219   -
          */
    +
          *
     220   -
         public float getCvssScore() {
    -  221  3
             return cvssScore;
    +
          * @return the value of cvssScore
    +  221   +
          */
     222   -
         }
    -  223   -
     
    +
         public float getCvssScore() {
    +  223  3
             return cvssScore;
     224   -
         /**
    +
         }
     225   -
          * Set the value of cvssScore.
    +
     
     226   -
          *
    +
         /**
     227   -
          * @param cvssScore new value of cvssScore
    +
          * Set the value of cvssScore.
     228   -
          */
    +
          *
     229   +
          * @param cvssScore new value of cvssScore
    +  230   +
          */
    +  231  
         public void setCvssScore(float cvssScore) {
    -  230  36
             this.cvssScore = cvssScore;
    -  231  36
         }
    -  232   -
         /**
    -  233   -
          * CVSS Access Vector.
    +  232  36
             this.cvssScore = cvssScore;
    +  233  36
         }
     234   -
          */
    +
         /**
     235   -
         private String cvssAccessVector;
    +
          * CVSS Access Vector.
     236   -
     
    +
          */
     237   -
         /**
    +
         private String cvssAccessVector;
     238   -
          * Get the value of cvssAccessVector.
    +
     
     239   -
          *
    +
         /**
     240   -
          * @return the value of cvssAccessVector
    +
          * Get the value of cvssAccessVector.
     241   -
          */
    +
          *
     242   -
         public String getCvssAccessVector() {
    -  243  0
             return cvssAccessVector;
    +
          * @return the value of cvssAccessVector
    +  243   +
          */
     244   -
         }
    -  245   -
     
    +
         public String getCvssAccessVector() {
    +  245  0
             return cvssAccessVector;
     246   -
         /**
    +
         }
     247   -
          * Set the value of cvssAccessVector.
    +
     
     248   -
          *
    +
         /**
     249   -
          * @param cvssAccessVector new value of cvssAccessVector
    +
          * Set the value of cvssAccessVector.
     250   -
          */
    +
          *
     251   +
          * @param cvssAccessVector new value of cvssAccessVector
    +  252   +
          */
    +  253  
         public void setCvssAccessVector(String cvssAccessVector) {
    -  252  35
             this.cvssAccessVector = cvssAccessVector;
    -  253  35
         }
    -  254   -
         /**
    -  255   -
          * CVSS Access Complexity.
    +  254  35
             this.cvssAccessVector = cvssAccessVector;
    +  255  35
         }
     256   -
          */
    +
         /**
     257   -
         private String cvssAccessComplexity;
    +
          * CVSS Access Complexity.
     258   -
     
    +
          */
     259   -
         /**
    +
         private String cvssAccessComplexity;
     260   -
          * Get the value of cvssAccessComplexity.
    +
     
     261   -
          *
    +
         /**
     262   -
          * @return the value of cvssAccessComplexity
    +
          * Get the value of cvssAccessComplexity.
     263   -
          */
    +
          *
     264   -
         public String getCvssAccessComplexity() {
    -  265  0
             return cvssAccessComplexity;
    +
          * @return the value of cvssAccessComplexity
    +  265   +
          */
     266   -
         }
    -  267   -
     
    +
         public String getCvssAccessComplexity() {
    +  267  0
             return cvssAccessComplexity;
     268   -
         /**
    +
         }
     269   -
          * Set the value of cvssAccessComplexity.
    +
     
     270   -
          *
    +
         /**
     271   -
          * @param cvssAccessComplexity new value of cvssAccessComplexity
    +
          * Set the value of cvssAccessComplexity.
     272   -
          */
    +
          *
     273   +
          * @param cvssAccessComplexity new value of cvssAccessComplexity
    +  274   +
          */
    +  275  
         public void setCvssAccessComplexity(String cvssAccessComplexity) {
    -  274  35
             this.cvssAccessComplexity = cvssAccessComplexity;
    -  275  35
         }
    -  276   -
         /**
    -  277   -
          * CVSS Authentication.
    +  276  35
             this.cvssAccessComplexity = cvssAccessComplexity;
    +  277  35
         }
     278   -
          */
    +
         /**
     279   -
         private String cvssAuthentication;
    +
          * CVSS Authentication.
     280   -
     
    +
          */
     281   -
         /**
    +
         private String cvssAuthentication;
     282   -
          * Get the value of cvssAuthentication.
    +
     
     283   -
          *
    +
         /**
     284   -
          * @return the value of cvssAuthentication
    +
          * Get the value of cvssAuthentication.
     285   -
          */
    +
          *
     286   -
         public String getCvssAuthentication() {
    -  287  0
             return cvssAuthentication;
    +
          * @return the value of cvssAuthentication
    +  287   +
          */
     288   -
         }
    -  289   -
     
    +
         public String getCvssAuthentication() {
    +  289  0
             return cvssAuthentication;
     290   -
         /**
    +
         }
     291   -
          * Set the value of cvssAuthentication.
    +
     
     292   -
          *
    +
         /**
     293   -
          * @param cvssAuthentication new value of cvssAuthentication
    +
          * Set the value of cvssAuthentication.
     294   -
          */
    +
          *
     295   +
          * @param cvssAuthentication new value of cvssAuthentication
    +  296   +
          */
    +  297  
         public void setCvssAuthentication(String cvssAuthentication) {
    -  296  35
             this.cvssAuthentication = cvssAuthentication;
    -  297  35
         }
    -  298   -
         /**
    -  299   -
          * CVSS Confidentiality Impact.
    +  298  35
             this.cvssAuthentication = cvssAuthentication;
    +  299  35
         }
     300   -
          */
    +
         /**
     301   -
         private String cvssConfidentialityImpact;
    +
          * CVSS Confidentiality Impact.
     302   -
     
    +
          */
     303   -
         /**
    +
         private String cvssConfidentialityImpact;
     304   -
          * Get the value of cvssConfidentialityImpact.
    +
     
     305   -
          *
    +
         /**
     306   -
          * @return the value of cvssConfidentialityImpact
    +
          * Get the value of cvssConfidentialityImpact.
     307   -
          */
    +
          *
     308   -
         public String getCvssConfidentialityImpact() {
    -  309  0
             return cvssConfidentialityImpact;
    +
          * @return the value of cvssConfidentialityImpact
    +  309   +
          */
     310   -
         }
    -  311   -
     
    +
         public String getCvssConfidentialityImpact() {
    +  311  0
             return cvssConfidentialityImpact;
     312   -
         /**
    +
         }
     313   -
          * Set the value of cvssConfidentialityImpact.
    +
     
     314   -
          *
    +
         /**
     315   -
          * @param cvssConfidentialityImpact new value of cvssConfidentialityImpact
    +
          * Set the value of cvssConfidentialityImpact.
     316   -
          */
    +
          *
     317   +
          * @param cvssConfidentialityImpact new value of cvssConfidentialityImpact
    +  318   +
          */
    +  319  
         public void setCvssConfidentialityImpact(String cvssConfidentialityImpact) {
    -  318  35
             this.cvssConfidentialityImpact = cvssConfidentialityImpact;
    -  319  35
         }
    -  320   -
         /**
    -  321   -
          * CVSS Integrity Impact.
    +  320  35
             this.cvssConfidentialityImpact = cvssConfidentialityImpact;
    +  321  35
         }
     322   -
          */
    +
         /**
     323   -
         private String cvssIntegrityImpact;
    +
          * CVSS Integrity Impact.
     324   -
     
    +
          */
     325   -
         /**
    +
         private String cvssIntegrityImpact;
     326   -
          * Get the value of cvssIntegrityImpact.
    +
     
     327   -
          *
    +
         /**
     328   -
          * @return the value of cvssIntegrityImpact
    +
          * Get the value of cvssIntegrityImpact.
     329   -
          */
    +
          *
     330   -
         public String getCvssIntegrityImpact() {
    -  331  0
             return cvssIntegrityImpact;
    +
          * @return the value of cvssIntegrityImpact
    +  331   +
          */
     332   -
         }
    -  333   -
     
    +
         public String getCvssIntegrityImpact() {
    +  333  0
             return cvssIntegrityImpact;
     334   -
         /**
    +
         }
     335   -
          * Set the value of cvssIntegrityImpact.
    +
     
     336   -
          *
    +
         /**
     337   -
          * @param cvssIntegrityImpact new value of cvssIntegrityImpact
    +
          * Set the value of cvssIntegrityImpact.
     338   -
          */
    +
          *
     339   +
          * @param cvssIntegrityImpact new value of cvssIntegrityImpact
    +  340   +
          */
    +  341  
         public void setCvssIntegrityImpact(String cvssIntegrityImpact) {
    -  340  35
             this.cvssIntegrityImpact = cvssIntegrityImpact;
    -  341  35
         }
    -  342   -
         /**
    -  343   -
          * CVSS Availability Impact.
    +  342  35
             this.cvssIntegrityImpact = cvssIntegrityImpact;
    +  343  35
         }
     344   -
          */
    +
         /**
     345   -
         private String cvssAvailabilityImpact;
    +
          * CVSS Availability Impact.
     346   -
     
    +
          */
     347   -
         /**
    +
         private String cvssAvailabilityImpact;
     348   -
          * Get the value of cvssAvailabilityImpact.
    +
     
     349   -
          *
    +
         /**
     350   -
          * @return the value of cvssAvailabilityImpact
    +
          * Get the value of cvssAvailabilityImpact.
     351   -
          */
    +
          *
     352   -
         public String getCvssAvailabilityImpact() {
    -  353  0
             return cvssAvailabilityImpact;
    +
          * @return the value of cvssAvailabilityImpact
    +  353   +
          */
     354   -
         }
    -  355   -
     
    +
         public String getCvssAvailabilityImpact() {
    +  355  0
             return cvssAvailabilityImpact;
     356   -
         /**
    +
         }
     357   -
          * Set the value of cvssAvailabilityImpact.
    +
     
     358   -
          *
    +
         /**
     359   -
          * @param cvssAvailabilityImpact new value of cvssAvailabilityImpact
    +
          * Set the value of cvssAvailabilityImpact.
     360   -
          */
    +
          *
     361   +
          * @param cvssAvailabilityImpact new value of cvssAvailabilityImpact
    +  362   +
          */
    +  363  
         public void setCvssAvailabilityImpact(String cvssAvailabilityImpact) {
    -  362  35
             this.cvssAvailabilityImpact = cvssAvailabilityImpact;
    -  363  35
         }
    -  364   -
     
    -  365   -
         @Override
    +  364  35
             this.cvssAvailabilityImpact = cvssAvailabilityImpact;
    +  365  35
         }
     366   +
     
    +  367   +
         @Override
    +  368  
         public boolean equals(Object obj) {
    -  367  0
             if (obj == null) {
    -  368  0
                 return false;
    -  369   +  369  0
             if (obj == null) {
    +  370  0
                 return false;
    +  371  
             }
    -  370  0
             if (getClass() != obj.getClass()) {
    -  371  0
                 return false;
    -  372   +  372  0
             if (getClass() != obj.getClass()) {
    +  373  0
                 return false;
    +  374  
             }
    -  373  0
             final Vulnerability other = (Vulnerability) obj;
    -  374  0
             if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
    -  375  0
                 return false;
    -  376   -
             }
    -  377  0
             return true;
    +  375  0
             final Vulnerability other = (Vulnerability) obj;
    +  376  0
             if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
    +  377  0
                 return false;
     378   -
         }
    -  379   -
     
    +
             }
    +  379  0
             return true;
     380   -
         @Override
    +
         }
     381   +
     
    +  382   +
         @Override
    +  383  
         public int hashCode() {
    -  382  8
             int hash = 5;
    -  383  8
             hash = 41 * hash + (this.name != null ? this.name.hashCode() : 0);
    -  384  8
             return hash;
    -  385   -
         }
    -  386   -
     
    +  384  8
             int hash = 5;
    +  385  8
             hash = 41 * hash + (this.name != null ? this.name.hashCode() : 0);
    +  386  8
             return hash;
     387   -
         @Override
    +
         }
     388   -
         public String toString() {
    -  389  0
             final StringBuilder sb = new StringBuilder("Vulnerability ");
    -  390  0
             sb.append(this.name);
    -  391  0
             sb.append("\nReferences:\n");
    -  392  0
             for (Reference reference : this.references) {
    -  393  0
               sb.append("=> ");
    -  394  0
               sb.append(reference);
    -  395  0
               sb.append("\n");
    -  396  0
             }
    -  397  0
             sb.append("\nSoftware:\n");
    -  398  0
             for (VulnerableSoftware software : this.vulnerableSoftware) {
    -  399  0
               sb.append("=> ");
    -  400  0
               sb.append(software);
    -  401  0
               sb.append("\n");
    -  402  0
             }
    -  403  0
             return sb.toString();
    -  404   -
         }
    -  405   -
         /**
    -  406   -
          * Compares two vulnerabilities.
    -  407   -
          *
    -  408   -
          * @param v a vulnerability to be compared
    -  409   -
          * @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than
    -  410   -
          * the specified vulnerability
    -  411   -
          */
    -  412   +
     
    +  389  
         @Override
    +  390   +
         public String toString() {
    +  391  0
             final StringBuilder sb = new StringBuilder("Vulnerability ");
    +  392  0
             sb.append(this.name);
    +  393  0
             sb.append("\nReferences:\n");
    +  394  0
             for (Reference reference : this.references) {
    +  395  0
                 sb.append("=> ");
    +  396  0
                 sb.append(reference);
    +  397  0
                 sb.append("\n");
    +  398  0
             }
    +  399  0
             sb.append("\nSoftware:\n");
    +  400  0
             for (VulnerableSoftware software : this.vulnerableSoftware) {
    +  401  0
                 sb.append("=> ");
    +  402  0
                 sb.append(software);
    +  403  0
                 sb.append("\n");
    +  404  0
             }
    +  405  0
             return sb.toString();
    +  406   +
         }
    +  407   +
     
    +  408   +
         /**
    +  409   +
          * Compares two vulnerabilities.
    +  410   +
          *
    +  411   +
          * @param v a vulnerability to be compared
    +  412   +
          * @return a negative integer, zero, or a positive integer as this object is
     413   -
         public int compareTo(Vulnerability v) {
    -  414  0
             return v.getName().compareTo(this.getName());
    +
          * less than, equal to, or greater than the specified vulnerability
    +  414   +
          */
     415   -
         }
    +
         @Override
     416   -
     
    -  417   -
         /**
    -  418   -
          * The CPE id that caused this vulnerability to be flagged.
    -  419   -
          */
    +
         public int compareTo(Vulnerability v) {
    +  417  0
             return new CompareToBuilder()
    +  418  0
                     .append(this.name, v.name)
    +  419  0
                     .toComparison();
     420   -
         private String matchedCPE;
    +
             //return v.getName().compareTo(this.getName());
     421   -
         /**
    +
         }
     422   -
          * Whether or not all previous versions were affected.
    +
     
     423   -
          */
    +
         /**
     424   -
         private String matchedAllPreviousCPE;
    +
          * The CPE id that caused this vulnerability to be flagged.
     425   -
     
    +
          */
     426   -
         /**
    +
         private String matchedCPE;
     427   -
          * Sets the CPE that caused this vulnerability to be flagged.
    +
         /**
     428   -
          *
    +
          * Whether or not all previous versions were affected.
     429   -
          * @param cpeId a CPE identifier
    +
          */
     430   -
          * @param previous a flag indicating whether or not all previous versions were affected (any non-null value is
    +
         private String matchedAllPreviousCPE;
     431   -
          * considered true)
    +
     
     432   -
          */
    +
         /**
     433   -
         public void setMatchedCPE(String cpeId, String previous) {
    -  434  8
             matchedCPE = cpeId;
    -  435  8
             matchedAllPreviousCPE = previous;
    -  436  8
         }
    +
          * Sets the CPE that caused this vulnerability to be flagged.
    +  434   +
          *
    +  435   +
          * @param cpeId a CPE identifier
    +  436   +
          * @param previous a flag indicating whether or not all previous versions
     437   -
     
    +
          * were affected (any non-null value is considered true)
     438   -
         /**
    +
          */
     439   -
          * Get the value of matchedCPE.
    -  440   -
          *
    -  441   -
          * @return the value of matchedCPE
    -  442   -
          */
    +
         public void setMatchedCPE(String cpeId, String previous) {
    +  440  8
             matchedCPE = cpeId;
    +  441  8
             matchedAllPreviousCPE = previous;
    +  442  8
         }
     443   -
         public String getMatchedCPE() {
    -  444  0
             return matchedCPE;
    +
     
    +  444   +
         /**
     445   -
         }
    +
          * Get the value of matchedCPE.
     446   -
     
    +
          *
     447   -
         /**
    +
          * @return the value of matchedCPE
     448   -
          * Get the value of matchedAllPreviousCPE.
    +
          */
     449   -
          *
    -  450   -
          * @return the value of matchedAllPreviousCPE
    +
         public String getMatchedCPE() {
    +  450  0
             return matchedCPE;
     451   -
          */
    +
         }
     452   -
         public String getMatchedAllPreviousCPE() {
    -  453  0
             return matchedAllPreviousCPE;
    -  454   -
         }
    -  455  
     
    -  456   +  453  
         /**
    -  457   -
          * Determines whether or not matchedAllPreviousCPE has been set.
    -  458   +  454   +
          * Get the value of matchedAllPreviousCPE.
    +  455  
          *
    -  459   -
          * @return true if matchedAllPreviousCPE is not null; otherwise false
    -  460   +  456   +
          * @return the value of matchedAllPreviousCPE
    +  457  
          */
    -  461   -
         public boolean hasMatchedAllPreviousCPE() {
    -  462  0
             return matchedAllPreviousCPE != null;
    -  463   +  458   +
         public String getMatchedAllPreviousCPE() {
    +  459  0
             return matchedAllPreviousCPE;
    +  460  
         }
    +  461   +
     
    +  462   +
         /**
    +  463   +
          * Determines whether or not matchedAllPreviousCPE has been set.
     464   +
          *
    +  465   +
          * @return true if matchedAllPreviousCPE is not null; otherwise false
    +  466   +
          */
    +  467   +
         public boolean hasMatchedAllPreviousCPE() {
    +  468  0
             return matchedAllPreviousCPE != null;
    +  469   +
         }
    +  470  
     }
    - + 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 f6c736c2f..7b47a02a3 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  209
     public class VulnerabilityComparator implements Comparator<Vulnerability>, Serializable {
    +  28  207
     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 ee5b09c13..c4fe01b82 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.VulnerableSoftware.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.VulnerableSoftware.html @@ -450,7 +450,7 @@
          */
     255  
         public String getName() {
    -  256  10787
             return name;
    +  256  10783
             return name;
     257  
         }
     258   @@ -491,7 +491,7 @@
          */
     277  
         public String getVersion() {
    -  278  1970
             return version;
    +  278  1861
             return version;
     279  
         }
     280   @@ -532,7 +532,7 @@
          */
     299  
         public String getUpdate() {
    -  300  1429
             return update;
    +  300  1256
             return update;
     301  
         }
     302   @@ -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 be3075c67..0ad825119 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
    7%
    4/53
    0%
    0/4
    1.133
    ExceptionCollection
    6%
    4/60
    0%
    0/10
    1.333
     
    @@ -183,217 +183,236 @@  91  0
             this.fatal = fatal;
     92  0
         }
     93   -
             /**
    +
     
     94   -
          * Instantiates a new exception collection.
    +
         /**
     95   -
          *
    -  96   -
          * @param msg the exception message
    -  97   -
          * @param exception a list of exceptions
    -  98   -
          */
    -  99   -
         public ExceptionCollection(String msg, Throwable exception) {
    -  100  0
             super(msg);
    -  101  0
             this.exceptions = new ArrayList<Throwable>();
    -  102  0
             this.exceptions.add(exception);
    -  103  0
             this.fatal = false;
    -  104  0
         }
    -  105   -
     
    -  106   -
         /**
    -  107  
          * Instantiates a new exception collection.
    +  96   +
          *
    +  97   +
          * @param msg the exception message
    +  98   +
          * @param exception a list of exceptions
    +  99   +
          */
    +  100   +
         public ExceptionCollection(String msg, Throwable exception) {
    +  101  0
             super(msg);
    +  102  0
             this.exceptions = new ArrayList<Throwable>();
    +  103  0
             this.exceptions.add(exception);
    +  104  0
             this.fatal = false;
    +  105  0
         }
    +  106   +
     
    +  107   +
         /**
     108   -
          */
    +
          * Instantiates a new exception collection.
     109   +
          */
    +  110  
         public ExceptionCollection() {
    -  110  0
             super();
    -  111  0
             this.exceptions = new ArrayList<Throwable>();
    -  112  0
         }
    -  113   -
         /**
    +  111  0
             super();
    +  112  0
             this.exceptions = new ArrayList<Throwable>();
    +  113  0
         }
     114   -
          * The serial version uid.
    +
         /**
     115   -
          */
    +
          * The serial version uid.
     116   -
         private static final long serialVersionUID = 1L;
    +
          */
     117   -
     
    +
         private static final long serialVersionUID = 1L;
     118   -
         /**
    +
     
     119   -
          * A collection of exceptions.
    +
         /**
     120   -
          */
    +
          * A collection of exceptions.
     121   -
         private List<Throwable> exceptions;
    +
          */
     122   -
     
    +
         private List<Throwable> exceptions;
     123   -
         /**
    +
     
     124   -
          * Get the value of exceptions.
    +
         /**
     125   -
          *
    +
          * Get the value of exceptions.
     126   -
          * @return the value of exceptions
    +
          *
     127   -
          */
    +
          * @return the value of exceptions
     128   +
          */
    +  129  
         public List<Throwable> getExceptions() {
    -  129  0
             return exceptions;
    -  130   -
         }
    +  130  0
             return exceptions;
     131   -
     
    -  132   -
         /**
    -  133   -
          * Adds an exception to the collection.
    -  134   -
          *
    -  135   -
          * @param ex the exception to add
    -  136   -
          */
    -  137   -
         public void addException(Throwable ex) {
    -  138  0
             this.exceptions.add(ex);
    -  139  0
         }
    -  140   -
     
    -  141   -
         /**
    -  142   -
          * Adds an exception to the collection.
    -  143   -
          *
    -  144   -
          * @param ex the exception to add
    -  145   -
          * @param fatal flag indicating if this is a fatal error
    -  146   -
          */
    -  147   -
         public void addException(Throwable ex, boolean fatal) {
    -  148  0
             addException(ex);
    -  149  0
             this.fatal = fatal;
    -  150  0
         }
    -  151   -
     
    -  152   -
         /**
    -  153   -
          * Flag indicating if a fatal exception occurred that would prevent the
    -  154   -
          * attempt at completing the analysis even if exceptions occurred.
    -  155   -
          */
    -  156  1
         private boolean fatal = false;
    -  157   -
     
    -  158   -
         /**
    -  159   -
          * Get the value of fatal.
    -  160   -
          *
    -  161   -
          * @return the value of fatal
    -  162   -
          */
    -  163   -
         public boolean isFatal() {
    -  164  0
             return fatal;
    -  165  
         }
    +  132   +
     
    +  133   +
         /**
    +  134   +
          * Adds an exception to the collection.
    +  135   +
          *
    +  136   +
          * @param ex the exception to add
    +  137   +
          */
    +  138   +
         public void addException(Throwable ex) {
    +  139  0
             this.exceptions.add(ex);
    +  140  0
         }
    +  141   +
     
    +  142   +
         /**
    +  143   +
          * Adds an exception to the collection.
    +  144   +
          *
    +  145   +
          * @param ex the exception to add
    +  146   +
          * @param fatal flag indicating if this is a fatal error
    +  147   +
          */
    +  148   +
         public void addException(Throwable ex, boolean fatal) {
    +  149  0
             addException(ex);
    +  150  0
             this.fatal = fatal;
    +  151  0
         }
    +  152   +
     
    +  153   +
         /**
    +  154   +
          * Flag indicating if a fatal exception occurred that would prevent the
    +  155   +
          * attempt at completing the analysis even if exceptions occurred.
    +  156   +
          */
    +  157  1
         private boolean fatal = false;
    +  158   +
     
    +  159   +
         /**
    +  160   +
          * Get the value of fatal.
    +  161   +
          *
    +  162   +
          * @return the value of fatal
    +  163   +
          */
    +  164   +
         public boolean isFatal() {
    +  165  0
             return fatal;
     166   -
     
    +
         }
     167   -
         /**
    +
     
     168   -
          * Set the value of fatal.
    +
         /**
     169   -
          *
    +
          * Set the value of fatal.
     170   -
          * @param fatal new value of fatal
    +
          *
     171   -
          */
    +
          * @param fatal new value of fatal
     172   +
          */
    +  173  
         public void setFatal(boolean fatal) {
    -  173  0
             this.fatal = fatal;
    -  174  0
         }
    -  175   -
     
    +  174  0
             this.fatal = fatal;
    +  175  0
         }
     176   -
         /**
    +
     
     177   -
          * Prints the stack trace.
    +
         /**
     178   -
          *
    -  179   -
          * @param s the writer to print to
    -  180   -
          */
    -  181   -
         @Override
    -  182   -
         public void printStackTrace(PrintWriter s) {
    -  183  0
             s.println("Multiple Exceptions Occured");
    -  184  0
             super.printStackTrace(s);
    -  185  0
             for (Throwable t : this.exceptions) {
    -  186  0
                 s.println("Next Exception:");
    -  187  0
                 t.printStackTrace(s);
    -  188  0
             }
    -  189  0
         }
    -  190   -
     
    -  191   -
         /**
    -  192  
          * Prints the stack trace.
    -  193   +  179  
          *
    -  194   -
          * @param s the stream to write the stack trace to
    -  195   +  180   +
          * @param s the writer to print to
    +  181  
          */
    -  196   +  182  
         @Override
    -  197   -
         public void printStackTrace(PrintStream s) {
    -  198  0
             s.println("Multiple Exceptions Occured");
    -  199  0
             super.printStackTrace(s);
    -  200  0
             for (Throwable t : this.exceptions) {
    -  201  0
                 s.println("Next Exception:");
    -  202  0
                 t.printStackTrace(s);
    -  203  0
             }
    -  204  0
         }
    -  205   +  183   +
         public void printStackTrace(PrintWriter s) {
    +  184  0
             s.println("Multiple Exceptions Occured");
    +  185  0
             super.printStackTrace(s);
    +  186  0
             for (Throwable t : this.exceptions) {
    +  187  0
                 s.println("Next Exception:");
    +  188  0
                 t.printStackTrace(s);
    +  189  0
             }
    +  190  0
         }
    +  191  
     
    -  206   +  192  
         /**
    -  207   -
          * Prints the stack trace to standard error.
    -  208   +  193   +
          * Prints the stack trace.
    +  194   +
          *
    +  195   +
          * @param s the stream to write the stack trace to
    +  196  
          */
    -  209   +  197  
         @Override
    -  210   -
         public void printStackTrace() {
    -  211  0
             this.printStackTrace(System.err);
    -  212  0
         }
    -  213   +  198   +
         public void printStackTrace(PrintStream s) {
    +  199  0
             s.println("Multiple Exceptions Occurred");
    +  200  0
             super.printStackTrace(s);
    +  201  0
             for (Throwable t : this.exceptions) {
    +  202  0
                 s.println("Next Exception:");
    +  203  0
                 t.printStackTrace(s);
    +  204  0
             }
    +  205  0
         }
    +  206  
     
    +  207   +
         /**
    +  208   +
          * Returns the error message, including the message from all contained
    +  209   +
          * exceptions.
    +  210   +
          *
    +  211   +
          * @return the error message
    +  212   +
          */
    +  213   +
         @Override
     214   +
         public String getMessage() {
    +  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:");
    +  219   +
             } else {
    +  220  0
                 sb.append(msg);
    +  221   +
             }
    +  222  0
             for (Throwable t : this.exceptions) {
    +  223  0
                 sb.append("\n\t").append(t.getMessage());
    +  224  0
             }
    +  225  0
             return sb.toString();
    +  226   +
         }
    +  227  
     }
    - + 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 b704a5364..591fc0d95 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.InitializationException.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.InitializationException.html @@ -143,6 +143,6 @@
     }
    - + 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 d0033c10a..a63f5468b 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 454d8e2f5..3ad1eea14 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 d391feccd..874b82627 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 38e85e2f8..503571df4 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 0ec55e4aa..03a979a8e 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 4c0b43ca7..2dafb8d41 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 251297ff4..c33ec613b 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DBUtils.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DBUtils.html @@ -189,6 +189,6 @@
     }
    - + 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 a9752d1b6..a6f87ad9b 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 5b280f1ff..5319a6375 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DependencyVersion.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DependencyVersion.html @@ -122,9 +122,9 @@
          * @param version the well formatted version number to parse
     54  
          */
    -  55  1038
         public DependencyVersion(String version) {
    -  56  1038
             parseVersion(version);
    -  57  1038
         }
    +  55  931
         public DependencyVersion(String version) {
    +  56  931
             parseVersion(version);
    +  57  931
         }
     58  
     
     59   @@ -141,21 +141,21 @@
          */
     65  
         public final void parseVersion(String version) {
    -  66  1040
             versionParts = new ArrayList<String>();
    -  67  1040
             if (version != null) {
    -  68  1040
                 final Pattern rx = Pattern.compile("(\\d+[a-z]{1,3}$|[a-z]+\\d+|\\d+|(release|beta|alpha)$)");
    -  69  1040
                 final Matcher matcher = rx.matcher(version.toLowerCase());
    -  70  4325
                 while (matcher.find()) {
    -  71  3285
                     versionParts.add(matcher.group());
    +  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  1040
                 if (versionParts.isEmpty()) {
    +  73  933
                 if (versionParts.isEmpty()) {
     74  6
                     versionParts.add(version);
     75  
                 }
     76  
             }
    -  77  1040
         }
    +  77  933
         }
     78  
         /**
     79   @@ -178,7 +178,7 @@
          */
     88  
         public List<String> getVersionParts() {
    -  89  1815
             return versionParts;
    +  89  1402
             return versionParts;
     90  
         }
     91   @@ -253,29 +253,29 @@
         @Override
     128  
         public boolean equals(Object obj) {
    -  129  666
             if (obj == null) {
    +  129  557
             if (obj == null) {
     130  0
                 return false;
     131  
             }
    -  132  666
             if (getClass() != obj.getClass()) {
    +  132  557
             if (getClass() != obj.getClass()) {
     133  0
                 return false;
     134  
             }
    -  135  666
             final DependencyVersion other = (DependencyVersion) obj;
    -  136  666
             final int max = (this.versionParts.size() < other.versionParts.size())
    -  137  127
                     ? this.versionParts.size() : other.versionParts.size();
    +  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  
             //TODO steal better version of code from compareTo
    -  139  1450
             for (int i = 0; i < max; i++) {
    -  140  1333
                 final String thisPart = this.versionParts.get(i);
    -  141  1333
                 final String otherPart = other.versionParts.get(i);
    -  142  1333
                 if (!thisPart.equals(otherPart)) {
    -  143  549
                     return false;
    +  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  
                 }
     145  
             }
    -  146  117
             if (this.versionParts.size() > max) {
    +  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;
    @@ -287,10 +287,10 @@
             }
     153  
     
    -  154  117
             if (other.versionParts.size() > max) {
    -  155  93
                 for (int i = max; i < other.versionParts.size(); i++) {
    -  156  93
                     if (!"0".equals(other.versionParts.get(i))) {
    -  157  93
                         return false;
    +  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   @@ -309,7 +309,7 @@
              *  }
     166  
              */
    -  167  24
             return true;
    +  167  22
             return true;
     168  
         }
     169   @@ -351,40 +351,40 @@
          */
     189  
         public boolean matchesAtLeastThreeLevels(DependencyVersion version) {
    -  190  424
             if (version == null) {
    +  190  319
             if (version == null) {
     191  0
                 return false;
     192  
             }
    -  193  424
             if (Math.abs(this.versionParts.size() - version.versionParts.size()) >= 3) {
    +  193  319
             if (Math.abs(this.versionParts.size() - version.versionParts.size()) >= 3) {
     194  1
                 return false;
     195  
             }
     196  
     
    -  197  423
             final int max = (this.versionParts.size() < version.versionParts.size())
    -  198  88
                     ? this.versionParts.size() : version.versionParts.size();
    +  197  318
             final int max = (this.versionParts.size() < version.versionParts.size())
    +  198  66
                     ? this.versionParts.size() : version.versionParts.size();
     199  
     
    -  200  423
             boolean ret = true;
    -  201  872
             for (int i = 0; i < max; i++) {
    -  202  806
                 final String thisVersion = this.versionParts.get(i);
    -  203  806
                 final String otherVersion = version.getVersionParts().get(i);
    -  204  806
                 if (i >= 3) {
    +  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  804
                 } else if (!thisVersion.equals(otherVersion)) {
    -  210  356
                     ret = false;
    -  211  356
                     break;
    +  209  605
                 } else if (!thisVersion.equals(otherVersion)) {
    +  210  267
                     ret = false;
    +  211  267
                     break;
     212  
                 }
     213  
             }
     214  
     
    -  215  423
             return ret;
    +  215  318
             return ret;
     216  
         }
     217   @@ -445,6 +445,6 @@
     }
    - + 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 a1cf4e230..b874b3dd6 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DependencyVersionUtil.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DependencyVersionUtil.html @@ -12,7 +12,7 @@
     
    - +
    Classes in this File Line Coverage Branch Coverage Complexity
    DependencyVersionUtil
    89%
    25/28
    85%
    17/20
    8.5
    DependencyVersionUtil
    88%
    31/35
    83%
    20/24
    7.333
     
    @@ -70,123 +70,188 @@  26  
      * <p>
     27   -
      * A utility class to extract version numbers from file names (or other strings containing version numbers.</p>
    +
      * A utility class to extract version numbers from file names (or other strings
     28   -
      *
    +
      * containing version numbers.</p>
     29   -
      * @author Jeremy Long
    +
      *
     30   -
      */
    +
      * @author Jeremy Long
     31   -
     public final class DependencyVersionUtil {
    +
      */
     32   -
     
    +
     public final class DependencyVersionUtil {
     33   -
         /**
    +
     
     34   -
          * Regular expression to extract version numbers from file names.
    +
         /**
     35   +
          * Regular expression to extract version numbers from file names.
    +  36  
          */
    -  36  1
         private static final Pattern RX_VERSION = Pattern.compile("\\d+(\\.\\d{1,6})+(\\.?([_-](release|beta|alpha|\\d+)|[a-zA-Z_-]{1,3}\\d{0,8}))?");
    -  37   -
         /**
    +  37  1
         private static final Pattern RX_VERSION = Pattern.compile("\\d+(\\.\\d{1,6})+(\\.?([_-](release|beta|alpha|\\d+)|[a-zA-Z_-]{1,3}\\d{0,8}))?");
     38   -
          * Regular expression to extract a single version number without periods. This is a last ditch effort just to check in case we
    +
         /**
     39   -
          * are missing a version number using the previous regex.
    +
          * Regular expression to extract a single version number without periods.
     40   -
          */
    -  41  1
         private static final Pattern RX_SINGLE_VERSION = Pattern.compile("\\d+(\\.?([_-](release|beta|alpha)|[a-zA-Z_-]{1,3}\\d{1,8}))?");
    +
          * This is a last ditch effort just to check in case we are missing a
    +  41   +
          * version number using the previous regex.
     42   -
     
    -  43   -
         /**
    +
          */
    +  43  1
         private static final Pattern RX_SINGLE_VERSION = Pattern.compile("\\d+(\\.?([_-](release|beta|alpha)|[a-zA-Z_-]{1,3}\\d{1,8}))?");
     44   -
          * Private constructor for utility class.
    -  45   -
          */
    -  46  0
         private DependencyVersionUtil() {
    -  47  0
         }
    -  48  
     
    -  49   +  45  
         /**
    -  50   -
          * <p>
    -  51   -
          * A utility class to extract version numbers from file names (or other strings containing version numbers.</p>
    -  52   -
          * <pre>
    -  53   -
          * Example:
    -  54   -
          * Give the file name: library-name-1.4.1r2-release.jar
    -  55   -
          * This function would return: 1.4.1.r2</pre>
    -  56   -
          *
    -  57   -
          * @param text the text being analyzed
    -  58   -
          * @return a DependencyVersion containing the version
    -  59   +  46   +
          * Regular expression to extract the part before the version numbers if
    +  47   +
          * there are any based on RX_VERSION. In most cases, this part represents a
    +  48   +
          * more accurate name.
    +  49  
          */
    +  50  1
         private static final Pattern RX_PRE_VERSION = Pattern.compile("^(.+)[_-](\\d+\\.\\d{1,6})+");
    +  51   +
     
    +  52   +
         /**
    +  53   +
          * Private constructor for utility class.
    +  54   +
          */
    +  55  0
         private DependencyVersionUtil() {
    +  56  0
         }
    +  57   +
     
    +  58   +
         /**
    +  59   +
          * <p>
     60   -
         public static DependencyVersion parseVersion(String text) {
    -  61  989
             if (text == null) {
    -  62  0
                 return null;
    +
          * A utility class to extract version numbers from file names (or other
    +  61   +
          * strings containing version numbers.</p>
    +  62   +
          * <pre>
     63   -
             }
    +
          * Example:
     64   +
          * Give the file name: library-name-1.4.1r2-release.jar
    +  65   +
          * This function would return: 1.4.1.r2</pre>
    +  66   +
          *
    +  67   +
          * @param text the text being analyzed
    +  68   +
          * @return a DependencyVersion containing the version
    +  69   +
          */
    +  70   +
         public static DependencyVersion parseVersion(String text) {
    +  71  886
             if (text == null) {
    +  72  0
                 return null;
    +  73   +
             }
    +  74  
             //'-' is a special case used within the CVE entries, just include it as the version.
    -  65  989
             if ("-".equals(text)) {
    -  66  1
                 final DependencyVersion dv = new DependencyVersion();
    -  67  1
                 final List<String> list = new ArrayList<String>();
    -  68  1
                 list.add(text);
    -  69  1
                 dv.setVersionParts(list);
    -  70  1
                 return dv;
    -  71   +  75  886
             if ("-".equals(text)) {
    +  76  1
                 final DependencyVersion dv = new DependencyVersion();
    +  77  1
                 final List<String> list = new ArrayList<String>();
    +  78  1
                 list.add(text);
    +  79  1
                 dv.setVersionParts(list);
    +  80  1
                 return dv;
    +  81  
             }
    -  72  988
             String version = null;
    -  73  988
             Matcher matcher = RX_VERSION.matcher(text);
    -  74  988
             if (matcher.find()) {
    -  75  983
                 version = matcher.group();
    -  76   +  82  885
             String version = null;
    +  83  885
             Matcher matcher = RX_VERSION.matcher(text);
    +  84  885
             if (matcher.find()) {
    +  85  876
                 version = matcher.group();
    +  86  
             }
    -  77   -
             //throw away the results if there are two things that look like version numbers
    -  78  988
             if (matcher.find()) {
    -  79  2
                 return null;
    -  80   -
             }
    -  81  986
             if (version == null) {
    -  82  5
                 matcher = RX_SINGLE_VERSION.matcher(text);
    -  83  5
                 if (matcher.find()) {
    -  84  2
                     version = matcher.group();
    -  85   -
                 } else {
    -  86  3
                     return null;
     87   -
                 }
    -  88   -
                 //throw away the results if there are two things that look like version numbers
    -  89  2
                 if (matcher.find()) {
    -  90  1
                     return null;
    -  91   -
                 }
    -  92   +
             //throw away the results if there are two things that look like version numbers
    +  88  885
             if (matcher.find()) {
    +  89  2
                 return null;
    +  90  
             }
    -  93  982
             if (version != null && version.endsWith("-py2") && version.length() > 4) {
    -  94  1
                 version = version.substring(0, version.length() - 4);
    +  91  883
             if (version == null) {
    +  92  9
                 matcher = RX_SINGLE_VERSION.matcher(text);
    +  93  9
                 if (matcher.find()) {
    +  94  2
                     version = matcher.group();
     95   -
             }
    -  96  982
             return new DependencyVersion(version);
    +
                 } else {
    +  96  7
                     return null;
     97   -
         }
    +
                 }
     98   +
                 //throw away the results if there are two things that look like version numbers
    +  99  2
                 if (matcher.find()) {
    +  100  1
                     return null;
    +  101   +
                 }
    +  102   +
             }
    +  103  875
             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);
    +  107   +
         }
    +  108   +
     
    +  109   +
         /**
    +  110   +
          * <p>
    +  111   +
          * A utility class to extract the part before version numbers from file
    +  112   +
          * names (or other strings containing version numbers. In most cases, this
    +  113   +
          * part represents a more accurate name than the full file name.</p>
    +  114   +
          * <pre>
    +  115   +
          * Example:
    +  116   +
          * Give the file name: library-name-1.4.1r2-release.jar
    +  117   +
          * This function would return: library-name</pre>
    +  118   +
          *
    +  119   +
          * @param text the text being analyzed
    +  120   +
          * @return the part before the version numbers if any, otherwise return the
    +  121   +
          * text itself.
    +  122   +
          */
    +  123   +
         public static String parsePreVersion(String text) {
    +  124  6
             if (parseVersion(text) == null) {
    +  125  1
                 return text;
    +  126   +
             }
    +  127   +
     
    +  128  5
             final Matcher matcher = RX_PRE_VERSION.matcher(text);
    +  129  5
             if (matcher.find()) {
    +  130  5
                 return matcher.group(1);
    +  131   +
             }
    +  132  0
             return text;
    +  133   +
         }
    +  134  
     }
    - + 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 e03552ae6..0f2dca99d 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 14b49c2f2..333e0452a 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.FileFilterBuilder.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.FileFilterBuilder.html @@ -107,7 +107,7 @@
      * @see <a href="https://en.wikipedia.org/wiki/Builder_pattern">Builder pattern</a>
     45  
      */
    -  46  20
     public class FileFilterBuilder {
    +  46  22
     public class FileFilterBuilder {
     47  
     
     48   @@ -116,21 +116,21 @@
          * A set of filenames to filter.
     50  
          */
    -  51  20
         private final Set<String> filenames = new HashSet<String>();
    +  51  22
         private final Set<String> filenames = new HashSet<String>();
     52  
         /**
     53  
          * A set of extensions to filter.
     54  
          */
    -  55  20
         private final Set<String> extensions = new HashSet<String>();
    +  55  22
         private final Set<String> extensions = new HashSet<String>();
     56  
         /**
     57  
          * An array list of file filters.
     58  
          */
    -  59  20
         private final List<IOFileFilter> fileFilters = new ArrayList<IOFileFilter>();
    +  59  22
         private final List<IOFileFilter> fileFilters = new ArrayList<IOFileFilter>();
     60  
     
     61   @@ -145,7 +145,7 @@
          */
     66  
         public static FileFilterBuilder newInstance() {
    -  67  20
             return new FileFilterBuilder();
    +  67  22
             return new FileFilterBuilder();
     68  
         }
     69   @@ -164,8 +164,8 @@
          */
     76  
         public FileFilterBuilder addFilenames(String... names) {
    -  77  6
             filenames.addAll(Arrays.asList(names));
    -  78  6
             return this;
    +  77  7
             filenames.addAll(Arrays.asList(names));
    +  78  7
             return this;
     79  
         }
     80   @@ -184,7 +184,7 @@
          */
     87  
         public FileFilterBuilder addExtensions(String... extensions) {
    -  88  15
             return this.addExtensions(Arrays.asList(extensions));
    +  88  16
             return this.addExtensions(Arrays.asList(extensions));
     89  
         }
     90   @@ -203,12 +203,12 @@
          */
     97  
         public FileFilterBuilder addExtensions(Iterable<String> extensions) {
    -  98  16
             for (String extension : extensions) {
    +  98  17
             for (String extension : extensions) {
     99  
                 // Ultimately, SuffixFileFilter will be used, and the "." needs to be explicit.
    -  100  39
                 this.extensions.add(extension.startsWith(".") ? extension : "." + extension);
    -  101  39
             }
    -  102  16
             return this;
    +  100  40
                 this.extensions.add(extension.startsWith(".") ? extension : "." + extension);
    +  101  40
             }
    +  102  17
             return this;
     103  
         }
     104   @@ -247,29 +247,29 @@
          */
     122  
         public FileFilter build() {
    -  123  20
             if (filenames.isEmpty() && extensions.isEmpty() && fileFilters.isEmpty()) {
    +  123  22
             if (filenames.isEmpty() && extensions.isEmpty() && fileFilters.isEmpty()) {
     124  0
                 throw new IllegalStateException("May only be invoked after at least one add... method has been invoked.");
     125  
             }
    -  126  20
             final OrFileFilter filter = new OrFileFilter();
    -  127  20
             if (!filenames.isEmpty()) {
    -  128  6
                 filter.addFileFilter(new NameFileFilter(new ArrayList<String>(filenames)));
    +  126  22
             final OrFileFilter filter = new OrFileFilter();
    +  127  22
             if (!filenames.isEmpty()) {
    +  128  7
                 filter.addFileFilter(new NameFileFilter(new ArrayList<String>(filenames)));
     129  
             }
    -  130  20
             if (!extensions.isEmpty()) {
    -  131  16
                 filter.addFileFilter(new SuffixFileFilter(new ArrayList<String>(extensions), IOCase.INSENSITIVE));
    +  130  22
             if (!extensions.isEmpty()) {
    +  131  17
                 filter.addFileFilter(new SuffixFileFilter(new ArrayList<String>(extensions), IOCase.INSENSITIVE));
     132  
             }
    -  133  20
             for (IOFileFilter iof : fileFilters) {
    +  133  22
             for (IOFileFilter iof : fileFilters) {
     134  2
                 filter.addFileFilter(iof);
     135  2
             }
    -  136  20
             return filter;
    +  136  22
             return filter;
     137  
         }
     138  
     }
    - + 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 7babda0a3..89c444ba4 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  121
             return new FilterIterator(iterator);
    +  20  83
             return new FilterIterator(iterator);
     21  
         }
     22  
     
     23  
         public Iterable<T> filter(final Iterable<T> iterable) {
    -  24  121
             return new Iterable<T>() {
    +  24  83
             return new Iterable<T>() {
     25  
     
     26  
                 @Override
     27  
                 public Iterator<T> iterator() {
    -  28  121
                     return filter(iterable.iterator());
    +  28  83
                     return filter(iterable.iterator());
     29  
                 }
     30   @@ -79,7 +79,7 @@
         }
     32  
     
    -  33  121
         private class FilterIterator implements Iterator<T> {
    +  33  83
         private class FilterIterator implements Iterator<T> {
     34  
     
     35   @@ -88,17 +88,17 @@
             private T next;
     37  
     
    -  38  121
             private FilterIterator(Iterator<T> iterator) {
    -  39  121
                 this.iterator = iterator;
    -  40  121
                 toNext();
    -  41  121
             }
    +  38  83
             private FilterIterator(Iterator<T> iterator) {
    +  39  83
                 this.iterator = iterator;
    +  40  83
                 toNext();
    +  41  83
             }
     42  
     
     43  
             @Override
     44  
             public boolean hasNext() {
    -  45  444
                 return next != null;
    +  45  361
                 return next != null;
     46  
             }
     47   @@ -107,13 +107,13 @@
             @Override
     49  
             public T next() {
    -  50  350
                 if (next == null) {
    +  50  305
                 if (next == null) {
     51  0
                     throw new NoSuchElementException();
     52  
                 }
    -  53  350
                 final T returnValue = next;
    -  54  350
                 toNext();
    -  55  350
                 return returnValue;
    +  53  305
                 final T returnValue = next;
    +  54  305
                 toNext();
    +  55  305
                 return returnValue;
     56  
             }
     57   @@ -129,22 +129,22 @@
     
     63  
             private void toNext() {
    -  64  471
                 next = null;
    -  65  904
                 while (iterator.hasNext()) {
    -  66  808
                     final T item = iterator.next();
    -  67  808
                     if (item != null && passes(item)) {
    -  68  375
                         next = item;
    -  69  375
                         break;
    +  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;
     70  
                     }
    -  71  433
                 }
    -  72  471
             }
    +  71  167
                 }
    +  72  388
             }
     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 dfe044e1f..0a53b72ef 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.Pair.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.Pair.html @@ -12,7 +12,7 @@
     
    - +
    Classes in this File Line Coverage Branch Coverage Complexity
    Pair
    42%
    12/28
    10%
    2/20
    2.75
    Pair
    42%
    12/28
    15%
    3/20
    2.75
     
    @@ -97,17 +97,17 @@
          * @param right the value for the right pair
     41  
          */
    -  42  52138
         public Pair(L left, R right) {
    -  43  52138
             this.left = left;
    -  44  52138
             this.right = right;
    -  45  52138
         }
    +  42  52334
         public Pair(L left, R right) {
    +  43  52334
             this.left = left;
    +  44  52334
             this.right = right;
    +  45  52334
         }
     46  
         /**
     47  
          * The left element of the pair.
     48  
          */
    -  49  52138
         private L left = null;
    +  49  52334
         private L left = null;
     50  
     
     51   @@ -122,7 +122,7 @@
          */
     56  
         public L getLeft() {
    -  57  52138
             return left;
    +  57  104666
             return left;
     58  
         }
     59   @@ -147,7 +147,7 @@
          * The right element of the pair.
     70  
          */
    -  71  52138
         private R right = null;
    +  71  52334
         private R right = null;
     72  
     
     73   @@ -162,7 +162,7 @@
          */
     78  
         public R getRight() {
    -  79  52138
             return right;
    +  79  104666
             return right;
     80  
         }
     81   @@ -197,10 +197,10 @@
         @Override
     97  
         public int hashCode() {
    -  98  52138
             int hash = 3;
    -  99  52138
             hash = 53 * hash + (this.left != null ? this.left.hashCode() : 0);
    -  100  52138
             hash = 53 * hash + (this.right != null ? this.right.hashCode() : 0);
    -  101  52138
             return hash;
    +  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;
     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 c272b0567..f7d8c45d8 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  210313
             return CONTAINS_URL_TEST.matcher(text).matches();
    +  57  206801
             return CONTAINS_URL_TEST.matcher(text).matches();
     58  
         }
     59   @@ -221,6 +221,6 @@
     }
    - + 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 2df1e8b72..09595f53a 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 a0f5c9296..0425eb26e 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 @@ -12,7 +12,7 @@
     
    - +
    Classes in this File Line Coverage Branch Coverage Complexity
    HintHandler
    100%
    51/51
    85%
    24/28
    4.5
    HintHandler
    100%
    58/58
    82%
    28/34
    5.25
     
    @@ -145,7 +145,7 @@  64  
         /**
     65   -
          * Attribute name.
    +
          * Attribute value.
     66  
          */
     67   @@ -153,19 +153,19 @@  68  
         /**
     69   -
          * Attribute name.
    +
          * Attribute value.
     70  
          */
     71   -
         private static final String CONFIDENCE = "confidence";
    +
         private static final String PRODUCT = "product";
     72  
         /**
     73   -
          * Attribute name.
    +
          * Attribute value.
     74  
          */
     75   -
         private static final String VALUE = "value";
    +
         private static final String VERSION = "version";
     76  
         /**
     77   @@ -173,7 +173,7 @@  78  
          */
     79   -
         private static final String NAME = "name";
    +
         private static final String CONFIDENCE = "confidence";
     80  
         /**
     81   @@ -181,7 +181,7 @@  82  
          */
     83   -
         private static final String SOURCE = "source";
    +
         private static final String VALUE = "value";
     84  
         /**
     85   @@ -189,7 +189,7 @@  86  
          */
     87   -
         private static final String TYPE = "type";
    +
         private static final String NAME = "name";
     88  
         /**
     89   @@ -197,7 +197,7 @@  90  
          */
     91   -
         private static final String CASE_SENSITIVE = "caseSensitive";
    +
         private static final String SOURCE = "source";
     92  
         /**
     93   @@ -205,7 +205,7 @@  94  
          */
     95   -
         private static final String REGEX = "regex";
    +
         private static final String TYPE = "type";
     96  
         /**
     97   @@ -213,195 +213,222 @@  98  
          */
     99   -
         private static final String CONTAINS = "contains";
    +
         private static final String CASE_SENSITIVE = "caseSensitive";
     100   -
         //</editor-fold>
    +
         /**
     101   -
     
    +
          * Attribute name.
     102   -
         /**
    +
          */
     103   -
          * The list of hint rules.
    +
         private static final String REGEX = "regex";
     104   -
          */
    -  105  5
         private final List<HintRule> hintRules = new ArrayList<HintRule>();
    +
         /**
    +  105   +
          * Attribute name.
     106   -
     
    +
          */
     107   -
         /**
    +
         private static final String CONTAINS = "contains";
     108   -
          * Returns the list of hint rules.
    +
         //</editor-fold>
     109   -
          *
    +
     
     110   -
          * @return the value of hintRules
    +
         /**
     111   -
          */
    +
          * The list of hint rules.
     112   -
         public List<HintRule> getHintRules() {
    -  113  5
             return hintRules;
    +
          */
    +  113  5
         private final List<HintRule> hintRules = new ArrayList<HintRule>();
     114   -
         }
    +
     
     115   -
     
    +
         /**
     116   -
         /**
    +
          * Returns the list of hint rules.
     117   -
          * The list of vendor duplicating hint rules.
    +
          *
     118   +
          * @return the value of hintRules
    +  119  
          */
    -  119  5
         private final List<VendorDuplicatingHintRule> vendorDuplicatingHintRules = new ArrayList<VendorDuplicatingHintRule>();
     120   -
     
    -  121   -
         /**
    +
         public List<HintRule> getHintRules() {
    +  121  5
             return hintRules;
     122   -
          * Returns the list of vendor duplicating hint rules.
    -  123   -
          *
    -  124   -
          * @return the list of vendor duplicating hint rules
    -  125   -
          */
    -  126   -
         public List<VendorDuplicatingHintRule> getVendorDuplicatingHintRules() {
    -  127  4
             return vendorDuplicatingHintRules;
    -  128  
         }
    +  123   +
     
    +  124   +
         /**
    +  125   +
          * The list of vendor duplicating hint rules.
    +  126   +
          */
    +  127  5
         private final List<VendorDuplicatingHintRule> vendorDuplicatingHintRules = new ArrayList<VendorDuplicatingHintRule>();
    +  128   +
     
     129   -
     
    +
         /**
     130   -
         /**
    +
          * Returns the list of vendor duplicating hint rules.
     131   -
          * The current rule being read.
    +
          *
     132   -
          */
    +
          * @return the list of vendor duplicating hint rules
     133   -
         private HintRule rule;
    +
          */
     134   -
         /**
    -  135   -
          * The current state of the parent node (to differentiate between 'add' and
    +
         public List<VendorDuplicatingHintRule> getVendorDuplicatingHintRules() {
    +  135  4
             return vendorDuplicatingHintRules;
     136   -
          * 'given').
    +
         }
     137   -
          */
    -  138  5
         private boolean inAddNode = false;
    +
     
    +  138   +
         /**
     139   -
     
    +
          * The current rule being read.
     140   -
         /**
    +
          */
     141   -
          * Handles the start element event.
    +
         private HintRule rule;
     142   -
          *
    -  143   -
          * @param uri the uri of the element being processed
    -  144   -
          * @param localName the local name of the element being processed
    -  145   -
          * @param qName the qName of the element being processed
    -  146   -
          * @param attr the attributes of the element being processed
    -  147   -
          * @throws SAXException thrown if there is an exception processing
    -  148   -
          */
    -  149   -
         @Override
    -  150   -
         public void startElement(String uri, String localName, String qName, Attributes attr) throws SAXException {
    -  151  155
             if (HINT.equals(qName)) {
    -  152  20
                 rule = new HintRule();
    -  153  135
             } else if (ADD.equals(qName)) {
    -  154  20
                 inAddNode = true;
    -  155  115
             } else if (GIVEN.equals(qName)) {
    -  156  20
                 inAddNode = false;
    -  157  95
             } else if (EVIDENCE.equals(qName)) {
    -  158  72
                 final String hintType = attr.getValue(TYPE);
    -  159  72
                 if (VENDOR.equals(hintType)) {
    -  160  39
                     if (inAddNode) {
    -  161  64
                         rule.addAddVendor(attr.getValue(SOURCE),
    -  162  32
                                 attr.getValue(NAME),
    -  163  32
                                 attr.getValue(VALUE),
    -  164  32
                                 Confidence.valueOf(attr.getValue(CONFIDENCE)));
    -  165   -
                     } else {
    -  166  14
                         rule.addGivenVendor(attr.getValue(SOURCE),
    -  167  7
                                 attr.getValue(NAME),
    -  168  7
                                 attr.getValue(VALUE),
    -  169  7
                                 Confidence.valueOf(attr.getValue(CONFIDENCE)));
    -  170   -
                     }
    -  171  33
                 } else if (inAddNode) {
    -  172  28
                     rule.addAddProduct(attr.getValue(SOURCE),
    -  173  14
                             attr.getValue(NAME),
    -  174  14
                             attr.getValue(VALUE),
    -  175  14
                             Confidence.valueOf(attr.getValue(CONFIDENCE)));
    -  176   -
                 } else {
    -  177  38
                     rule.addGivenProduct(attr.getValue(SOURCE),
    -  178  19
                             attr.getValue(NAME),
    -  179  19
                             attr.getValue(VALUE),
    -  180  19
                             Confidence.valueOf(attr.getValue(CONFIDENCE)));
    -  181   -
                 }
    -  182  72
             } else if (FILE_NAME.equals(qName)) {
    -  183  8
                 final PropertyType pt = new PropertyType();
    -  184  8
                 pt.setValue(attr.getValue(CONTAINS));
    -  185  8
                 if (attr.getLength() > 0) {
    -  186  8
                     final String regex = attr.getValue(REGEX);
    -  187  8
                     if (regex != null) {
    -  188  8
                         pt.setRegex(Boolean.parseBoolean(regex));
    -  189   -
                     }
    -  190  8
                     final String caseSensitive = attr.getValue(CASE_SENSITIVE);
    -  191  8
                     if (caseSensitive != null) {
    -  192  8
                         pt.setCaseSensitive(Boolean.parseBoolean(caseSensitive));
    -  193   -
                     }
    -  194   -
                 }
    -  195  8
                 rule.addFilename(pt);
    -  196  8
             } else if (VENDOR_DUPLICATING_RULE.equals(qName)) {
    -  197  10
                 vendorDuplicatingHintRules.add(new VendorDuplicatingHintRule(attr.getValue(VALUE), attr.getValue(DUPLICATE)));
    -  198   -
             }
    -  199  155
         }
    -  200   -
     
    -  201  
         /**
    -  202   -
          * Handles the end element event.
    -  203   -
          *
    -  204   -
          * @param uri the element's URI
    -  205   -
          * @param localName the local name
    -  206   -
          * @param qName the qualified name
    -  207   -
          * @throws SAXException thrown if there is an exception processing the
    -  208   -
          * element
    -  209   +  143   +
          * The current state of the parent node (to differentiate between 'add' and
    +  144   +
          * 'given').
    +  145  
          */
    -  210   +  146  5
         private boolean inAddNode = false;
    +  147   +
     
    +  148   +
         /**
    +  149   +
          * Handles the start element event.
    +  150   +
          *
    +  151   +
          * @param uri the uri of the element being processed
    +  152   +
          * @param localName the local name of the element being processed
    +  153   +
          * @param qName the qName of the element being processed
    +  154   +
          * @param attr the attributes of the element being processed
    +  155   +
          * @throws SAXException thrown if there is an exception processing
    +  156   +
          */
    +  157  
         @Override
    +  158   +
         public void startElement(String uri, String localName, String qName, Attributes attr) throws SAXException {
    +  159  205
             if (HINT.equals(qName)) {
    +  160  30
                 rule = new HintRule();
    +  161  175
             } else if (ADD.equals(qName)) {
    +  162  30
                 inAddNode = true;
    +  163  145
             } else if (GIVEN.equals(qName)) {
    +  164  30
                 inAddNode = false;
    +  165  115
             } else if (EVIDENCE.equals(qName)) {
    +  166  82
                 final String hintType = attr.getValue(TYPE);
    +  167  82
                 if (VENDOR.equals(hintType)) {
    +  168  39
                     if (inAddNode) {
    +  169  64
                         rule.addAddVendor(attr.getValue(SOURCE),
    +  170  32
                                 attr.getValue(NAME),
    +  171  32
                                 attr.getValue(VALUE),
    +  172  32
                                 Confidence.valueOf(attr.getValue(CONFIDENCE)));
    +  173   +
                     } else {
    +  174  14
                         rule.addGivenVendor(attr.getValue(SOURCE),
    +  175  7
                                 attr.getValue(NAME),
    +  176  7
                                 attr.getValue(VALUE),
    +  177  7
                                 Confidence.valueOf(attr.getValue(CONFIDENCE)));
    +  178   +
                     }
    +  179  43
                 } else if (PRODUCT.equals(hintType)) {
    +  180  33
                     if (inAddNode) {
    +  181  28
                         rule.addAddProduct(attr.getValue(SOURCE),
    +  182  14
                                 attr.getValue(NAME),
    +  183  14
                                 attr.getValue(VALUE),
    +  184  14
                                 Confidence.valueOf(attr.getValue(CONFIDENCE)));
    +  185   +
                     } else {
    +  186  38
                         rule.addGivenProduct(attr.getValue(SOURCE),
    +  187  19
                                 attr.getValue(NAME),
    +  188  19
                                 attr.getValue(VALUE),
    +  189  19
                                 Confidence.valueOf(attr.getValue(CONFIDENCE)));
    +  190   +
                     }
    +  191  10
                 } else if (VERSION.equals(hintType)) {
    +  192  10
                     if (inAddNode) {
    +  193  20
                         rule.addAddVersion(attr.getValue(SOURCE),
    +  194  10
                                 attr.getValue(NAME),
    +  195  10
                                 attr.getValue(VALUE),
    +  196  10
                                 Confidence.valueOf(attr.getValue(CONFIDENCE)));
    +  197   +
                     }
    +  198   +
                 }
    +  199  82
             } else if (FILE_NAME.equals(qName)) {
    +  200  18
                 final PropertyType pt = new PropertyType();
    +  201  18
                 pt.setValue(attr.getValue(CONTAINS));
    +  202  18
                 if (attr.getLength() > 0) {
    +  203  18
                     final String regex = attr.getValue(REGEX);
    +  204  18
                     if (regex != null) {
    +  205  18
                         pt.setRegex(Boolean.parseBoolean(regex));
    +  206   +
                     }
    +  207  18
                     final String caseSensitive = attr.getValue(CASE_SENSITIVE);
    +  208  18
                     if (caseSensitive != null) {
    +  209  18
                         pt.setCaseSensitive(Boolean.parseBoolean(caseSensitive));
    +  210   +
                     }
     211   -
         public void endElement(String uri, String localName, String qName) throws SAXException {
    -  212  155
             if (HINT.equals(qName) && rule != null) {
    -  213  20
                 hintRules.add(rule);
    -  214  20
                 rule = null;
    +
                 }
    +  212  18
                 rule.addFilename(pt);
    +  213  18
             } else if (VENDOR_DUPLICATING_RULE.equals(qName)) {
    +  214  10
                 vendorDuplicatingHintRules.add(new VendorDuplicatingHintRule(attr.getValue(VALUE), attr.getValue(DUPLICATE)));
     215  
             }
    -  216  155
         }
    +  216  205
         }
     217   +
     
    +  218   +
         /**
    +  219   +
          * Handles the end element event.
    +  220   +
          *
    +  221   +
          * @param uri the element's URI
    +  222   +
          * @param localName the local name
    +  223   +
          * @param qName the qualified name
    +  224   +
          * @throws SAXException thrown if there is an exception processing the
    +  225   +
          * element
    +  226   +
          */
    +  227   +
         @Override
    +  228   +
         public void endElement(String uri, String localName, String qName) throws SAXException {
    +  229  205
             if (HINT.equals(qName) && rule != null) {
    +  230  30
                 hintRules.add(rule);
    +  231  30
                 rule = null;
    +  232   +
             }
    +  233  205
         }
    +  234  
     }
    - + 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 2ade01c6c..8abd9d521 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 5acce48ad..5fae50d96 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
    55%
    26/47
    25%
    1/4
    10
    HintParser
    56%
    30/53
    33%
    2/6
    11
     
    @@ -148,7 +148,7 @@  66  
          */
     67   -
         private static final String HINT_SCHEMA = "schema/dependency-hint.1.0.xsd";
    +
         private static final String HINT_SCHEMA = "schema/dependency-hint.1.1.xsd";
     68  
     
     69   @@ -214,56 +214,68 @@
          */
     106  
         public Hints parseHints(InputStream inputStream) throws HintParseException, SAXException {
    -  107   +  107  4
             InputStream schemaStream = null;
    +  108  
             try {
    -  108  4
                 final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream(HINT_SCHEMA);
    -  109  4
                 final HintHandler handler = new HintHandler();
    -  110  4
                 final SAXParserFactory factory = SAXParserFactory.newInstance();
    -  111  4
                 factory.setNamespaceAware(true);
    -  112  4
                 factory.setValidating(true);
    -  113  4
                 final SAXParser saxParser = factory.newSAXParser();
    -  114  4
                 saxParser.setProperty(HintParser.JAXP_SCHEMA_LANGUAGE, HintParser.W3C_XML_SCHEMA);
    -  115  4
                 saxParser.setProperty(HintParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream));
    -  116  4
                 final XMLReader xmlReader = saxParser.getXMLReader();
    -  117  4
                 xmlReader.setErrorHandler(new HintErrorHandler());
    -  118  4
                 xmlReader.setContentHandler(handler);
    -  119   +  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  
     
    -  120  4
                 final Reader reader = new InputStreamReader(inputStream, "UTF-8");
    -  121  4
                 final InputSource in = new InputSource(reader);
    -  122   +  121  4
                 final Reader reader = new InputStreamReader(inputStream, "UTF-8");
    +  122  4
                 final InputSource in = new InputSource(reader);
    +  123  
     
    -  123  4
                 xmlReader.parse(in);
    -  124  4
                 final Hints hints = new Hints();
    -  125  4
                 hints.setHintRules(handler.getHintRules());
    -  126  4
                 hints.setVendorDuplicatingHintRules(handler.getVendorDuplicatingHintRules());
    -  127  4
                 return hints;
    -  128  0
             } catch (ParserConfigurationException ex) {
    -  129  0
                 LOGGER.debug("", ex);
    -  130  0
                 throw new HintParseException(ex);
    -  131  0
             } catch (SAXException ex) {
    -  132  0
                 if (ex.getMessage().contains("Cannot find the declaration of element 'hints'.")) {
    -  133  0
                     throw ex;
    -  134   +  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  
                 } else {
    -  135  0
                     LOGGER.debug("", ex);
    -  136  0
                     throw new HintParseException(ex);
    -  137   +  136  0
                     LOGGER.debug("", ex);
    +  137  0
                     throw new HintParseException(ex);
    +  138  
                 }
    -  138  0
             } catch (FileNotFoundException ex) {
    -  139  0
                 LOGGER.debug("", ex);
    -  140  0
                 throw new HintParseException(ex);
    -  141  0
             } catch (IOException ex) {
    -  142  0
                 LOGGER.debug("", ex);
    -  143  0
                 throw new HintParseException(ex);
    -  144   -
             }
    +  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   +
             } finally {
    +  146  4
                 if (schemaStream != null) {
    +  147   +
                     try {
    +  148  4
                         schemaStream.close();
    +  149  0
                     } catch (IOException ex) {
    +  150  0
                         LOGGER.debug("Error closing hint file stream", ex);
    +  151  4
                     }
    +  152   +
                 }
    +  153   +
             }
    +  154  
         }
    -  146   +  155  
     }
    - + 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 5479c7cad..f1806a55d 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 @@ -12,7 +12,7 @@
     
    - +
    Classes in this File Line Coverage Branch Coverage Complexity
    HintRule
    100%
    21/21
    N/A
    1
    HintRule
    100%
    25/25
    N/A
    1
     
    @@ -81,7 +81,7 @@
      * @author Jeremy Long
     32  
      */
    -  33  20
     public class HintRule {
    +  33  30
     public class HintRule {
     34  
     
     35   @@ -90,7 +90,7 @@
          * The list of file names to match.
     37  
          */
    -  38  20
         private final List<PropertyType> filenames = new ArrayList<PropertyType>();
    +  38  30
         private final List<PropertyType> filenames = new ArrayList<PropertyType>();
     39  
     
     40   @@ -105,8 +105,8 @@
          */
     45  
         public void addFilename(PropertyType filename) {
    -  46  8
             this.filenames.add(filename);
    -  47  8
         }
    +  46  18
             this.filenames.add(filename);
    +  47  18
         }
     48  
     
     49   @@ -121,7 +121,7 @@
          */
     54  
         public List<PropertyType> getFilenames() {
    -  55  33
             return filenames;
    +  55  53
             return filenames;
     56  
         }
     57   @@ -130,7 +130,7 @@
          * The list of product evidence that is being matched.
     59  
          */
    -  60  20
         private final List<Evidence> givenProduct = new ArrayList<Evidence>();
    +  60  30
         private final List<Evidence> givenProduct = new ArrayList<Evidence>();
     61  
     
     62   @@ -167,7 +167,7 @@
          */
     79  
         public List<Evidence> getGivenProduct() {
    -  80  29
             return givenProduct;
    +  80  49
             return givenProduct;
     81  
         }
     82   @@ -178,146 +178,192 @@
          * The list of vendor evidence that is being matched.
     85  
          */
    -  86  20
         private final List<Evidence> givenVendor = new ArrayList<Evidence>();
    +  86  30
         private final List<Evidence> givenVendor = new ArrayList<Evidence>();
     87  
     
     88  
         /**
     89   -
          * Adds a given vendors to the list of evidence to matched.
    +
          * The list of product evidence to add.
     90   -
          *
    -  91   -
          * @param source the source of the evidence
    -  92   -
          * @param name the name of the evidence
    -  93   -
          * @param value the value of the evidence
    -  94   -
          * @param confidence the confidence of the evidence
    -  95  
          */
    -  96   -
         public void addGivenVendor(String source, String name, String value, Confidence confidence) {
    -  97  7
             givenVendor.add(new Evidence(source, name, value, confidence));
    -  98  7
         }
    -  99   -
     
    -  100   +  91  30
         private final List<Evidence> addProduct = new ArrayList<Evidence>();
    +  92  
         /**
    -  101   -
          * Get the value of givenVendor.
    -  102   +  93   +
          * The list of version evidence to add.
    +  94   +
          */
    +  95  30
         private final List<Evidence> addVersion = new ArrayList<Evidence>();
    +  96   +
     
    +  97   +
         /**
    +  98   +
          * Adds a given vendors to the list of evidence to matched.
    +  99  
          *
    +  100   +
          * @param source the source of the evidence
    +  101   +
          * @param name the name of the evidence
    +  102   +
          * @param value the value of the evidence
     103   -
          * @return the value of givenVendor
    +
          * @param confidence the confidence of the evidence
     104  
          */
     105   -
         public List<Evidence> getGivenVendor() {
    -  106  29
             return givenVendor;
    -  107   -
         }
    +
         public void addGivenVendor(String source, String name, String value, Confidence confidence) {
    +  106  7
             givenVendor.add(new Evidence(source, name, value, confidence));
    +  107  7
         }
     108  
     
     109  
         /**
     110   -
          * The list of product evidence to add.
    +
          * Get the value of givenVendor.
     111   -
          */
    -  112  20
         private final List<Evidence> addProduct = new ArrayList<Evidence>();
    +
          *
    +  112   +
          * @return the value of givenVendor
     113   -
     
    +
          */
     114   -
         /**
    -  115   -
          * Adds a given product to the list of evidence to add when matched.
    +
         public List<Evidence> getGivenVendor() {
    +  115  49
             return givenVendor;
     116   -
          *
    +
         }
     117   -
          * @param source the source of the evidence
    +
     
     118   -
          * @param name the name of the evidence
    +
         /**
     119   -
          * @param value the value of the evidence
    +
          * Adds a given product to the list of evidence to add when matched.
     120   -
          * @param confidence the confidence of the evidence
    +
          *
     121   -
          */
    -  122   -
         public void addAddProduct(String source, String name, String value, Confidence confidence) {
    -  123  14
             addProduct.add(new Evidence(source, name, value, confidence));
    -  124  14
         }
    -  125   -
     
    -  126   -
         /**
    -  127   -
          * Get the value of addProduct.
    -  128   -
          *
    -  129   -
          * @return the value of addProduct
    -  130   -
          */
    -  131   -
         public List<Evidence> getAddProduct() {
    -  132  3
             return addProduct;
    -  133   -
         }
    -  134   -
     
    -  135   -
         /**
    -  136   -
          * The list of vendor hints to add.
    -  137   -
          */
    -  138  20
         private final List<Evidence> addVendor = new ArrayList<Evidence>();
    -  139   -
     
    -  140   -
         /**
    -  141   -
          * Adds a given vendor to the list of evidence to add when matched.
    -  142   -
          *
    -  143  
          * @param source the source of the evidence
    -  144   +  122  
          * @param name the name of the evidence
    -  145   +  123  
          * @param value the value of the evidence
    -  146   +  124  
          * @param confidence the confidence of the evidence
    -  147   +  125  
          */
    -  148   -
         public void addAddVendor(String source, String name, String value, Confidence confidence) {
    -  149  32
             addVendor.add(new Evidence(source, name, value, confidence));
    -  150  32
         }
    -  151   +  126   +
         public void addAddProduct(String source, String name, String value, Confidence confidence) {
    +  127  14
             addProduct.add(new Evidence(source, name, value, confidence));
    +  128  14
         }
    +  129  
     
    -  152   +  130  
         /**
    -  153   -
          * Get the value of addVendor.
    -  154   +  131   +
          * Get the value of addProduct.
    +  132  
          *
    -  155   -
          * @return the value of addVendor
    -  156   +  133   +
          * @return the value of addProduct
    +  134  
          */
    -  157   -
         public List<Evidence> getAddVendor() {
    -  158  3
             return addVendor;
    -  159   +  135   +
         public List<Evidence> getAddProduct() {
    +  136  3
             return addProduct;
    +  137  
         }
    +  138   +
     
    +  139   +
         /**
    +  140   +
          * Adds a given version to the list of evidence to add when matched.
    +  141   +
          *
    +  142   +
          * @param source the source of the evidence
    +  143   +
          * @param name the name of the evidence
    +  144   +
          * @param value the value of the evidence
    +  145   +
          * @param confidence the confidence of the evidence
    +  146   +
          */
    +  147   +
         public void addAddVersion(String source, String name, String value, Confidence confidence) {
    +  148  10
             addVersion.add(new Evidence(source, name, value, confidence));
    +  149  10
         }
    +  150   +
     
    +  151   +
         /**
    +  152   +
          * Get the value of addVersion.
    +  153   +
          *
    +  154   +
          * @return the value of addVersion
    +  155   +
          */
    +  156   +
         public List<Evidence> getAddVersion() {
    +  157  1
             return addVersion;
    +  158   +
         }
    +  159   +
     
     160   +
         /**
    +  161   +
          * The list of vendor hints to add.
    +  162   +
          */
    +  163  30
         private final List<Evidence> addVendor = new ArrayList<Evidence>();
    +  164   +
     
    +  165   +
         /**
    +  166   +
          * Adds a given vendor to the list of evidence to add when matched.
    +  167   +
          *
    +  168   +
          * @param source the source of the evidence
    +  169   +
          * @param name the name of the evidence
    +  170   +
          * @param value the value of the evidence
    +  171   +
          * @param confidence the confidence of the evidence
    +  172   +
          */
    +  173   +
         public void addAddVendor(String source, String name, String value, Confidence confidence) {
    +  174  32
             addVendor.add(new Evidence(source, name, value, confidence));
    +  175  32
         }
    +  176   +
     
    +  177   +
         /**
    +  178   +
          * Get the value of addVendor.
    +  179   +
          *
    +  180   +
          * @return the value of addVendor
    +  181   +
          */
    +  182   +
         public List<Evidence> getAddVendor() {
    +  183  3
             return addVendor;
    +  184   +
         }
    +  185  
     }
    - + 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 9b3d1a386..70077200b 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 2fa74c4fe..19b515e91 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 a1a6d0f4d..98749cf17 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 6e41b5f61..9dbc41f35 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 @@ -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 a9a418e77..50f3f73e1 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 152665fa6..336fcf6ab 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 937c4151b..b7a57d228 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 @@ -211,6 +211,6 @@
     }
    - + 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 0b350eb62..06d6f9a10 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 @@ -12,7 +12,7 @@
     
    - +
    Classes in this File Line Coverage Branch Coverage Complexity
    PomUtils
    32%
    14/43
    50%
    1/2
    4.25
    PomUtils
    29%
    13/44
    50%
    3/6
    5.5
     
    @@ -115,103 +115,118 @@  50  
          * @return returns a
     51   -
          * @throws AnalysisException is thrown if there is an exception extracting or parsing the POM {@link Model} object
    +
          * @throws AnalysisException is thrown if there is an exception extracting
     52   -
          */
    +
          * or parsing the POM {@link Model} object
     53   +
          */
    +  54  
         public static Model readPom(File file) throws AnalysisException {
    -  54  1
             Model model = null;
     55  
             try {
     56  1
                 final PomParser parser = new PomParser();
    -  57  1
                 model = parser.parse(file);
    -  58  0
             } catch (PomParseException ex) {
    -  59  0
                 LOGGER.warn("Unable to parse pom '{}'", file.getPath());
    -  60  0
                 LOGGER.debug("", ex);
    -  61  0
                 throw new AnalysisException(ex);
    -  62  0
             } catch (IOException ex) {
    -  63  0
                 LOGGER.warn("Unable to parse pom '{}'(IO Exception)", file.getPath());
    +  57  1
                 final Model model = parser.parse(file);
    +  58  1
                 if (model == null) {
    +  59  0
                     throw new AnalysisException(String.format("Unable to parse pom '%s'", file.getPath()));
    +  60   +
                 }
    +  61  1
                 return model;
    +  62  0
             } catch (PomParseException ex) {
    +  63  0
                 LOGGER.warn("Unable to parse pom '{}'", file.getPath());
     64  0
                 LOGGER.debug("", ex);
     65  0
                 throw new AnalysisException(ex);
    -  66  0
             } catch (Throwable ex) {
    -  67  0
                 LOGGER.warn("Unexpected error during parsing of the pom '{}'", file.getPath());
    +  66  0
             } catch (IOException ex) {
    +  67  0
                 LOGGER.warn("Unable to parse pom '{}'(IO Exception)", file.getPath());
     68  0
                 LOGGER.debug("", ex);
     69  0
                 throw new AnalysisException(ex);
    -  70  1
             }
    -  71  1
             return model;
    -  72   -
         }
    -  73   -
     
    +  70  0
             } catch (Throwable ex) {
    +  71  0
                 LOGGER.warn("Unexpected error during parsing of the pom '{}'", file.getPath());
    +  72  0
                 LOGGER.debug("", ex);
    +  73  0
                 throw new AnalysisException(ex);
     74   -
         /**
    -  75   -
          * Retrieves the specified POM from a jar file and converts it to a Model.
    -  76   -
          *
    -  77   -
          * @param path the path to the pom.xml file within the jar file
    -  78   -
          * @param jar the jar file to extract the pom from
    -  79   -
          * @return returns a
    -  80   -
          * @throws AnalysisException is thrown if there is an exception extracting or parsing the POM {@link Model} object
    -  81   -
          */
    -  82   -
         public static Model readPom(String path, JarFile jar) throws AnalysisException {
    -  83  2
             final ZipEntry entry = jar.getEntry(path);
    -  84  2
             Model model = null;
    -  85  2
             if (entry != null) { //should never be null
    -  86   -
                 try {
    -  87  2
                     final PomParser parser = new PomParser();
    -  88  2
                     model = parser.parse(jar.getInputStream(entry));
    -  89  2
                     LOGGER.debug("Read POM {}", path);
    -  90  0
                 } catch (SecurityException ex) {
    -  91  0
                     LOGGER.warn("Unable to parse pom '{}' in jar '{}'; invalid signature", path, jar.getName());
    -  92  0
                     LOGGER.debug("", ex);
    -  93  0
                     throw new AnalysisException(ex);
    -  94  0
                 } catch (IOException ex) {
    -  95  0
                     LOGGER.warn("Unable to parse pom '{}' in jar '{}' (IO Exception)", path, jar.getName());
    -  96  0
                     LOGGER.debug("", ex);
    -  97  0
                     throw new AnalysisException(ex);
    -  98  0
                 } catch (Throwable ex) {
    -  99  0
                     LOGGER.warn("Unexpected error during parsing of the pom '{}' in jar '{}'", path, jar.getName());
    -  100  0
                     LOGGER.debug("", ex);
    -  101  0
                     throw new AnalysisException(ex);
    -  102  2
                 }
    -  103  
             }
    -  104  2
             return model;
    -  105   +  75  
         }
    -  106   +  76  
     
    -  107   +  77  
         /**
    -  108   -
          * Reads in the pom file and adds elements as evidence to the given dependency.
    -  109   +  78   +
          * Retrieves the specified POM from a jar file and converts it to a Model.
    +  79  
          *
    -  110   -
          * @param dependency the dependency being analyzed
    -  111   -
          * @param pomFile the pom file to read
    -  112   -
          * @throws AnalysisException is thrown if there is an exception parsing the pom
    -  113   +  80   +
          * @param path the path to the pom.xml file within the jar file
    +  81   +
          * @param jar the jar file to extract the pom from
    +  82   +
          * @return returns a
    +  83   +
          * @throws AnalysisException is thrown if there is an exception extracting
    +  84   +
          * or parsing the POM {@link Model} object
    +  85  
          */
    +  86   +
         public static Model readPom(String path, JarFile jar) throws AnalysisException {
    +  87  2
             final ZipEntry entry = jar.getEntry(path);
    +  88  2
             Model model = null;
    +  89  2
             if (entry != null) { //should never be null
    +  90   +
                 try {
    +  91  2
                     final PomParser parser = new PomParser();
    +  92  2
                     model = parser.parse(jar.getInputStream(entry));
    +  93  2
                     if (model == null) {
    +  94  0
                         throw new AnalysisException(String.format("Unable to parse pom '%s/%s'", jar.getName(), path));
    +  95   +
                     }
    +  96  0
                 } catch (SecurityException ex) {
    +  97  0
                     LOGGER.warn("Unable to parse pom '{}' in jar '{}'; invalid signature", path, jar.getName());
    +  98  0
                     LOGGER.debug("", ex);
    +  99  0
                     throw new AnalysisException(ex);
    +  100  0
                 } catch (IOException ex) {
    +  101  0
                     LOGGER.warn("Unable to parse pom '{}' in jar '{}' (IO Exception)", path, jar.getName());
    +  102  0
                     LOGGER.debug("", ex);
    +  103  0
                     throw new AnalysisException(ex);
    +  104  0
                 } catch (Throwable ex) {
    +  105  0
                     LOGGER.warn("Unexpected error during parsing of the pom '{}' in jar '{}'", path, jar.getName());
    +  106  0
                     LOGGER.debug("", ex);
    +  107  0
                     throw new AnalysisException(ex);
    +  108  2
                 }
    +  109   +
             }
    +  110  2
             return model;
    +  111   +
         }
    +  112   +
     
    +  113   +
         /**
     114   -
         public static void analyzePOM(Dependency dependency, File pomFile) throws AnalysisException {
    -  115  0
             final Model pom = PomUtils.readPom(pomFile);
    -  116  0
             JarAnalyzer.setPomEvidence(dependency, pom, null);
    -  117  0
         }
    +
          * Reads in the pom file and adds elements as evidence to the given
    +  115   +
          * dependency.
    +  116   +
          *
    +  117   +
          * @param dependency the dependency being analyzed
     118   +
          * @param pomFile the pom file to read
    +  119   +
          * @throws AnalysisException is thrown if there is an exception parsing the
    +  120   +
          * pom
    +  121   +
          */
    +  122   +
         public static void analyzePOM(Dependency dependency, File pomFile) throws AnalysisException {
    +  123  0
             final Model pom = PomUtils.readPom(pomFile);
    +  124  0
             JarAnalyzer.setPomEvidence(dependency, pom, null);
    +  125  0
         }
    +  126  
     }
    - + 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 5fa2ac730..55e086301 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  1010
     public class PropertyType {
    +  28  1034
     public class PropertyType {
     29  
     
     30   @@ -117,15 +117,15 @@
          */
     51  
         public void setValue(String value) {
    -  52  1019
             this.value = value;
    -  53  1019
         }
    +  52  1043
             this.value = value;
    +  53  1043
         }
     54  
         /**
     55  
          * Whether or not the expression is a regex.
     56  
          */
    -  57  1010
         private boolean regex = false;
    +  57  1034
         private boolean regex = false;
     58  
     
     59   @@ -161,15 +161,15 @@
          */
     75  
         public void setRegex(boolean value) {
    -  76  1003
             this.regex = value;
    -  77  1003
         }
    +  76  1027
             this.regex = value;
    +  77  1027
         }
     78  
         /**
     79  
          * Indicates case sensitivity.
     80  
          */
    -  81  1010
         private boolean caseSensitive = false;
    +  81  1034
         private boolean caseSensitive = false;
     82  
     
     83   @@ -205,8 +205,8 @@
          */
     99  
         public void setCaseSensitive(boolean value) {
    -  100  1004
             this.caseSensitive = value;
    -  101  1004
         }
    +  100  1028
             this.caseSensitive = value;
    +  101  1028
         }
     102  
         //</editor-fold>
     103   @@ -225,21 +225,21 @@
          */
     110  
         public boolean matches(String text) {
    -  111  148
             if (text == null) {
    +  111  168
             if (text == null) {
     112  0
                 return false;
     113  
             }
    -  114  148
             if (this.regex) {
    +  114  168
             if (this.regex) {
     115  
                 Pattern rx;
    -  116  80
                 if (this.caseSensitive) {
    +  116  100
                 if (this.caseSensitive) {
     117  2
                     rx = Pattern.compile(this.value);
     118  
                 } else {
    -  119  78
                     rx = Pattern.compile(this.value, Pattern.CASE_INSENSITIVE);
    +  119  98
                     rx = Pattern.compile(this.value, Pattern.CASE_INSENSITIVE);
     120  
                 }
    -  121  80
                 return rx.matcher(text).matches();
    +  121  100
                 return rx.matcher(text).matches();
     122  
             } else {
     123  68
                 if (this.caseSensitive) {
    @@ -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 81d2397a8..3b60ad0ce 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 @@ -12,7 +12,7 @@
     
    - +
    Classes in this File Line Coverage Branch Coverage Complexity
    SuppressionErrorHandler
    81%
    13/16
    50%
    4/8
    2.5
    SuppressionErrorHandler
    80%
    12/15
    50%
    4/8
    2.5
     
    @@ -56,147 +56,144 @@  19  
     
     20   -
     import org.slf4j.Logger;
    -  21   -
     import org.slf4j.LoggerFactory;
    -  22  
     import org.xml.sax.ErrorHandler;
    -  23   +  21  
     import org.xml.sax.SAXException;
    -  24   +  22  
     import org.xml.sax.SAXParseException;
    -  25   +  23  
     
    -  26   +  24  
     /**
    -  27   +  25  
      * An XML parsing error handler.
    -  28   +  26  
      *
    -  29   +  27  
      * @author Jeremy Long
    -  30   +  28  
      */
    -  31  14
     public class SuppressionErrorHandler implements ErrorHandler {
    +  29  14
     public class SuppressionErrorHandler implements ErrorHandler {
    +  30   +
     
    +  31   +
         /**
     32   -
     
    -  33   -
         /**
    -  34  
          * The logger.
    +  33   +
          */
    +  34   +
         //private static final Logger LOGGER = LoggerFactory.getLogger(SuppressionErrorHandler.class);
     35   -
          */
    -  36  1
         private static final Logger LOGGER = LoggerFactory.getLogger(SuppressionErrorHandler.class);
    -  37  
     
    -  38   +  36  
         /**
    -  39   +  37  
          * Builds a prettier exception message.
    -  40   +  38  
          *
    -  41   +  39  
          * @param ex the SAXParseException
    -  42   +  40  
          * @return an easier to read exception message
    -  43   +  41  
          */
    -  44   +  42  
         private String getPrettyParseExceptionInfo(SAXParseException ex) {
    +  43   +
     
    +  44  3
             final StringBuilder sb = new StringBuilder();
     45  
     
    -  46  3
             final StringBuilder sb = new StringBuilder();
    -  47   -
     
    -  48  3
             if (ex.getSystemId() != null) {
    -  49  0
                 sb.append("systemId=").append(ex.getSystemId()).append(", ");
    -  50   +  46  3
             if (ex.getSystemId() != null) {
    +  47  0
                 sb.append("systemId=").append(ex.getSystemId()).append(", ");
    +  48  
             }
    -  51  3
             if (ex.getPublicId() != null) {
    -  52  0
                 sb.append("publicId=").append(ex.getPublicId()).append(", ");
    -  53   +  49  3
             if (ex.getPublicId() != null) {
    +  50  0
                 sb.append("publicId=").append(ex.getPublicId()).append(", ");
    +  51  
             }
    -  54  3
             if (ex.getLineNumber() > 0) {
    -  55  3
                 sb.append("Line=").append(ex.getLineNumber());
    -  56   +  52  3
             if (ex.getLineNumber() > 0) {
    +  53  3
                 sb.append("Line=").append(ex.getLineNumber());
    +  54  
             }
    -  57  3
             if (ex.getColumnNumber() > 0) {
    -  58  3
                 sb.append(", Column=").append(ex.getColumnNumber());
    +  55  3
             if (ex.getColumnNumber() > 0) {
    +  56  3
                 sb.append(", Column=").append(ex.getColumnNumber());
    +  57   +
             }
    +  58  3
             sb.append(": ").append(ex.getMessage());
     59   -
             }
    -  60  3
             sb.append(": ").append(ex.getMessage());
    +
     
    +  60  3
             return sb.toString();
     61   +
         }
    +  62  
     
    -  62  3
             return sb.toString();
     63   -
         }
    +
         /**
     64   -
     
    -  65   -
         /**
    -  66  
          * Logs warnings.
    -  67   +  65  
          *
    -  68   +  66  
          * @param ex the warning to log
    -  69   +  67  
          * @throws SAXException is never thrown
    +  68   +
          */
    +  69   +
         @Override
     70   -
          */
    -  71   -
         @Override
    -  72  
         public void warning(SAXParseException ex) throws SAXException {
    -  73   +  71  
             //LOGGER.debug("", ex);
    -  74  3
         }
    +  72  3
         }
    +  73   +
     
    +  74   +
         /**
     75   -
     
    -  76   -
         /**
    -  77  
          * Handles errors.
    -  78   +  76  
          *
    -  79   +  77  
          * @param ex the error to handle
    -  80   +  78  
          * @throws SAXException is always thrown
    +  79   +
          */
    +  80   +
         @Override
     81   -
          */
    -  82   -
         @Override
    -  83  
         public void error(SAXParseException ex) throws SAXException {
    -  84  3
             throw new SAXException(getPrettyParseExceptionInfo(ex));
    -  85   +  82  3
             throw new SAXException(getPrettyParseExceptionInfo(ex));
    +  83  
         }
    -  86   +  84  
     
    -  87   +  85  
         /**
    -  88   +  86  
          * Handles fatal exceptions.
    -  89   +  87  
          *
    -  90   +  88  
          * @param ex a fatal exception
    -  91   +  89  
          * @throws SAXException is always
    -  92   +  90  
          */
    -  93   +  91  
         @Override
    -  94   +  92  
         public void fatalError(SAXParseException ex) throws SAXException {
    -  95  0
             throw new SAXException(getPrettyParseExceptionInfo(ex));
    -  96   +  93  0
             throw new SAXException(getPrettyParseExceptionInfo(ex));
    +  94  
         }
    -  97   +  95  
     }
    - + 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 3d8aeaac5..53333e149 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  1837
             currentAttributes = attributes;
    -  103  1837
             currentText = new StringBuilder();
    -  104  1837
             if (SUPPRESS.equals(qName)) {
    -  105  412
                 rule = new SuppressionRule();
    -  106  412
                 final String base = currentAttributes.getValue("base");
    -  107  412
                 if (base != null) {
    -  108  412
                     rule.setBase(Boolean.parseBoolean(base));
    +  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));
     109  
                 } else {
     110  0
                     rule.setBase(false);
    @@ -230,7 +230,7 @@
                 }
     112  
             }
    -  113  1837
         }
    +  113  1865
         }
     114  
     
     115   @@ -253,30 +253,30 @@
         @Override
     124  
         public void endElement(String uri, String localName, String qName) throws SAXException {
    -  125  1837
             if (SUPPRESS.equals(qName)) {
    -  126  412
                 suppressionRules.add(rule);
    -  127  412
                 rule = null;
    -  128  1425
             } else if (FILE_PATH.equals(qName)) {
    +  125  1865
             if (SUPPRESS.equals(qName)) {
    +  126  419
                 suppressionRules.add(rule);
    +  127  419
                 rule = null;
    +  128  1446
             } 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  1346
             } else if (GAV.equals(qName)) {
    -  134  329
                 final PropertyType pt = processPropertyType();
    -  135  329
                 rule.setGav(pt);
    -  136  329
             } else if (CPE.equals(qName)) {
    -  137  582
                 final PropertyType pt = processPropertyType();
    -  138  582
                 rule.addCpe(pt);
    -  139  582
             } else if (CWE.equals(qName)) {
    +  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)) {
     140  0
                 rule.addCwe(currentText.toString());
    -  141  435
             } else if (CVE.equals(qName)) {
    +  141  442
             } else if (CVE.equals(qName)) {
     142  8
                 rule.addCve(currentText.toString());
    -  143  427
             } else if (CVSS_BELOW.equals(qName)) {
    +  143  434
             } else if (CVSS_BELOW.equals(qName)) {
     144  4
                 final float cvss = Float.parseFloat(currentText.toString());
     145  4
                 rule.addCvssBelow(cvss);
     146  
             }
    -  147  1837
         }
    +  147  1865
         }
     148  
     
     149   @@ -299,8 +299,8 @@
         @Override
     158  
         public void characters(char[] ch, int start, int length) throws SAXException {
    -  159  4159
             currentText.append(ch, start, length);
    -  160  4159
         }
    +  159  4222
             currentText.append(ch, start, length);
    +  160  4222
         }
     161  
     
     162   @@ -317,28 +317,28 @@
          */
     168  
         private PropertyType processPropertyType() {
    -  169  986
             final PropertyType pt = new PropertyType();
    -  170  986
             pt.setValue(currentText.toString());
    -  171  986
             if (currentAttributes != null && currentAttributes.getLength() > 0) {
    -  172  986
                 final String regex = currentAttributes.getValue("regex");
    -  173  986
                 if (regex != null) {
    -  174  986
                     pt.setRegex(Boolean.parseBoolean(regex));
    +  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));
     175  
                 }
    -  176  986
                 final String caseSensitive = currentAttributes.getValue("caseSensitive");
    -  177  986
                 if (caseSensitive != null) {
    -  178  986
                     pt.setCaseSensitive(Boolean.parseBoolean(caseSensitive));
    +  176  1000
                 final String caseSensitive = currentAttributes.getValue("caseSensitive");
    +  177  1000
                 if (caseSensitive != null) {
    +  178  1000
                     pt.setCaseSensitive(Boolean.parseBoolean(caseSensitive));
     179  
                 }
     180  
             }
    -  181  986
             return pt;
    +  181  1000
             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 c20133581..785eb63ab 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 @@ -147,6 +147,6 @@
     }
    - + 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 68eb64991..873ff2965 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
    63%
    51/80
    50%
    3/6
    11.333
    SuppressionParser
    64%
    59/92
    50%
    5/10
    12.667
     
    @@ -239,116 +239,140 @@
          */
     123  
         public List<SuppressionRule> parseSuppressionRules(InputStream inputStream) throws SuppressionParseException, SAXException {
    -  124   +  124  10
             InputStream schemaStream = null;
    +  125  
             try {
    -  125  10
                 final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream(SUPPRESSION_SCHEMA);
    -  126  10
                 final SuppressionHandler handler = new SuppressionHandler();
    -  127  10
                 final SAXParserFactory factory = SAXParserFactory.newInstance();
    -  128  10
                 factory.setNamespaceAware(true);
    -  129  10
                 factory.setValidating(true);
    -  130  10
                 final SAXParser saxParser = factory.newSAXParser();
    -  131  10
                 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA);
    -  132  10
                 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream));
    -  133  10
                 final XMLReader xmlReader = saxParser.getXMLReader();
    -  134  10
                 xmlReader.setErrorHandler(new SuppressionErrorHandler());
    -  135  10
                 xmlReader.setContentHandler(handler);
    -  136   +  126  10
                 schemaStream = this.getClass().getClassLoader().getResourceAsStream(SUPPRESSION_SCHEMA);
    +  127  10
                 final SuppressionHandler handler = new SuppressionHandler();
    +  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  
     
    -  137  10
                 final Reader reader = new InputStreamReader(inputStream, "UTF-8");
    -  138  10
                 final InputSource in = new InputSource(reader);
    -  139   -
                 //in.setEncoding("UTF-8");
    +  138  10
                 final Reader reader = new InputStreamReader(inputStream, "UTF-8");
    +  139  10
                 final InputSource in = new InputSource(reader);
     140   +
                 //in.setEncoding("UTF-8");
    +  141  
     
    -  141  10
                 xmlReader.parse(in);
    -  142   +  142  10
                 xmlReader.parse(in);
    +  143  
     
    -  143  7
                 return handler.getSuppressionRules();
    -  144  0
             } catch (ParserConfigurationException ex) {
    -  145  0
                 LOGGER.debug("", ex);
    -  146  0
                 throw new SuppressionParseException(ex);
    -  147  3
             } catch (SAXException ex) {
    -  148  3
                 if (ex.getMessage().contains("Cannot find the declaration of element 'suppressions'.")) {
    -  149  3
                     throw ex;
    -  150   +  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  
                 } else {
    -  151  0
                     LOGGER.debug("", ex);
    -  152  0
                     throw new SuppressionParseException(ex);
    -  153   +  152  0
                     LOGGER.debug("", ex);
    +  153  0
                     throw new SuppressionParseException(ex);
    +  154  
                 }
    -  154  0
             } catch (FileNotFoundException ex) {
    -  155  0
                 LOGGER.debug("", ex);
    -  156  0
                 throw new SuppressionParseException(ex);
    -  157  0
             } catch (IOException ex) {
    -  158  0
                 LOGGER.debug("", ex);
    -  159  0
                 throw new SuppressionParseException(ex);
    -  160   -
             }
    +  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   -
         }
    -  162   -
     
    +
             } finally {
    +  162  10
                 if (schemaStream != null) {
     163   -
         /**
    -  164   -
          * Parses the given XML stream and returns a list of the suppression rules
    -  165   -
          * contained.
    -  166   -
          *
    -  167   -
          * @param inputStream an InputStream containing suppression rues
    +
                     try {
    +  164  10
                         schemaStream.close();
    +  165  0
                     } catch (IOException ex) {
    +  166  0
                         LOGGER.debug("Error closing suppression file stream", ex);
    +  167  13
                     }
     168   -
          * @return a list of suppression rules
    +
                 }
     169   -
          * @throws SuppressionParseException if the XML cannot be parsed
    -  170   -
          */
    -  171   -
         private List<SuppressionRule> parseOldSuppressionRules(InputStream inputStream) throws SuppressionParseException {
    -  172   -
             try {
    -  173  3
                 final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream(OLD_SUPPRESSION_SCHEMA);
    -  174  3
                 final SuppressionHandler handler = new SuppressionHandler();
    -  175  3
                 final SAXParserFactory factory = SAXParserFactory.newInstance();
    -  176  3
                 factory.setNamespaceAware(true);
    -  177  3
                 factory.setValidating(true);
    -  178  3
                 final SAXParser saxParser = factory.newSAXParser();
    -  179  3
                 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA);
    -  180  3
                 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream));
    -  181  3
                 final XMLReader xmlReader = saxParser.getXMLReader();
    -  182  3
                 xmlReader.setErrorHandler(new SuppressionErrorHandler());
    -  183  3
                 xmlReader.setContentHandler(handler);
    -  184   -
     
    -  185  3
                 final Reader reader = new InputStreamReader(inputStream, "UTF-8");
    -  186  3
                 final InputSource in = new InputSource(reader);
    -  187   -
     
    -  188  3
                 xmlReader.parse(in);
    -  189   -
     
    -  190  3
                 return handler.getSuppressionRules();
    -  191  0
             } catch (ParserConfigurationException ex) {
    -  192  0
                 LOGGER.debug("", ex);
    -  193  0
                 throw new SuppressionParseException(ex);
    -  194  0
             } catch (SAXException ex) {
    -  195  0
                 LOGGER.debug("", ex);
    -  196  0
                 throw new SuppressionParseException(ex);
    -  197  0
             } catch (FileNotFoundException ex) {
    -  198  0
                 LOGGER.debug("", ex);
    -  199  0
                 throw new SuppressionParseException(ex);
    -  200  0
             } catch (IOException ex) {
    -  201  0
                 LOGGER.debug("", ex);
    -  202  0
                 throw new SuppressionParseException(ex);
    -  203  
             }
    -  204   +  170  
         }
    -  205   +  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   +
             }
    +  222   +
         }
    +  223  
     }
    - + 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 1e16404cf..2691ebfdf 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  427
     public class SuppressionRule {
    +  31  434
     public class SuppressionRule {
     32  
     
     33   @@ -168,7 +168,7 @@
          * A list of CPEs to suppression
     79  
          */
    -  80  427
         private List<PropertyType> cpe = new ArrayList<PropertyType>();
    +  80  434
         private List<PropertyType> cpe = new ArrayList<PropertyType>();
     81  
     
     82   @@ -216,8 +216,8 @@
          */
     105  
         public void addCpe(PropertyType cpe) {
    -  106  589
             this.cpe.add(cpe);
    -  107  589
         }
    +  106  596
             this.cpe.add(cpe);
    +  107  596
         }
     108  
     
     109   @@ -241,7 +241,7 @@
          * The list of cvssBelow scores.
     119  
          */
    -  120  427
         private List<Float> cvssBelow = new ArrayList<Float>();
    +  120  434
         private List<Float> cvssBelow = new ArrayList<Float>();
     121  
     
     122   @@ -314,7 +314,7 @@
          * The list of cwe entries to suppress.
     159  
          */
    -  160  427
         private List<String> cwe = new ArrayList<String>();
    +  160  434
         private List<String> cwe = new ArrayList<String>();
     161  
     
     162   @@ -387,7 +387,7 @@
          * The list of cve entries to suppress.
     199  
          */
    -  200  427
         private List<String> cve = new ArrayList<String>();
    +  200  434
         private List<String> cve = new ArrayList<String>();
     201  
     
     202   @@ -460,7 +460,7 @@
          * A Maven GAV to suppression.
     239  
          */
    -  240  427
         private PropertyType gav = null;
    +  240  434
         private PropertyType gav = null;
     241  
     
     242   @@ -492,8 +492,8 @@
          */
     256  
         public void setGav(PropertyType gav) {
    -  257  330
             this.gav = gav;
    -  258  330
         }
    +  257  337
             this.gav = gav;
    +  258  337
         }
     259  
     
     260   @@ -554,8 +554,8 @@
          */
     289  
         public void setBase(boolean base) {
    -  290  414
             this.base = base;
    -  291  414
         }
    +  290  421
             this.base = base;
    +  291  421
         }
     292  
     
     293   @@ -572,27 +572,27 @@
          */
     299  
         public void process(Dependency dependency) {
    -  300  458
             if (filePath != null && !filePath.matches(dependency.getFilePath())) {
    +  300  466
             if (filePath != null && !filePath.matches(dependency.getFilePath())) {
     301  48
                 return;
     302  
             }
    -  303  410
             if (sha1 != null && !sha1.equalsIgnoreCase(dependency.getSha1sum())) {
    +  303  418
             if (sha1 != null && !sha1.equalsIgnoreCase(dependency.getSha1sum())) {
     304  1
                 return;
     305  
             }
    -  306  409
             if (gav != null) {
    -  307  377
                 final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
    -  308  377
                 boolean gavFound = false;
    -  309  663
                 while (itr.hasNext()) {
    -  310  287
                     final Identifier i = itr.next();
    -  311  287
                     if (identifierMatches("maven", this.gav, i)) {
    +  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)) {
     312  1
                         gavFound = true;
     313  1
                         break;
     314  
                     }
    -  315  286
                 }
    -  316  377
                 if (!gavFound) {
    -  317  376
                     return;
    +  315  292
                 }
    +  316  385
                 if (!gavFound) {
    +  317  384
                     return;
     318  
                 }
     319   @@ -733,7 +733,7 @@
          */
     412  
         boolean identifierMatches(String identifierType, PropertyType suppressionEntry, Identifier identifier) {
    -  413  356
             if (identifierType.equals(identifier.getType())) {
    +  413  362
             if (identifierType.equals(identifier.getType())) {
     414  67
                 if (suppressionEntry.matches(identifier.getValue())) {
     415  5
                     return true;
     416  62
                 } else if ("cpe".equals(identifierType) && cpeHasNoVersion(suppressionEntry)) {
    @@ -750,7 +750,7 @@
                 }
     425  
             }
    -  426  296
             return false;
    +  426  302
             return false;
     427  
         }
     428   @@ -823,6 +823,6 @@
     }
    - + diff --git a/dependency-check-core/cpd.html b/dependency-check-core/cpd.html index 5c39a07ff..01479e4e7 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,26 +247,13 @@ Line org\owasp\dependencycheck\data\update\CpeUpdater.java -147 +161 org\owasp\dependencycheck\data\update\nvd\DownloadTask.java -268 +271
    -
        }
    -
    -    /**
    -     * Extracts the file contained in a gzip archive. The extracted file is placed in the exact same path as the file specified.
    -     *
    -     * @param file the archive file
    -     * @throws FileNotFoundException thrown if the file does not exist
    -     * @throws IOException thrown if there is an error extracting the file.
    -     */
    -    private void extractGzip(File file) throws FileNotFoundException, IOException {
    -        //TODO - move this to a util class as it is duplicative of (copy of) code in the DownloadTask
    -        final String originalPath = file.getPath();
    -        final File gzip = new File(originalPath + ".gz");
    -        if (gzip.isFile() && !gzip.delete()) {
    +
                LOGGER.debug("Failed to delete intial temporary file {}", gzip.toString());
                 gzip.deleteOnExit();
             }
             if (!file.renameTo(gzip)) {
    @@ -301,33 +288,21 @@
                         LOGGER.trace("ignore", ex);
                     }
                 }
    -            if (gzip.isFile()) {
    -                FileUtils.deleteQuietly(gzip);
    -            }
    -        }
    -    }
    -}
    + if (gzip.isFile() && !FileUtils.deleteQuietly(gzip)) { + LOGGER.debug("Failed to delete temporary file {}", gzip.toString()); - + - + - + - + - + - + diff --git a/dependency-check-core/dependency-updates-report.html b/dependency-check-core/dependency-updates-report.html index 97a7e306d..86d3b269d 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 @@ - + @@ -251,15 +251,15 @@ - + - + -
    File Line
    org\owasp\dependencycheck\xml\hints\HintErrorHandler.java36
    44
    org\owasp\dependencycheck\xml\suppression\SuppressionErrorHandler.java36
    42
    -
        private static final Logger LOGGER = LoggerFactory.getLogger(HintErrorHandler.class);
    -
    -    /**
    -     * Builds a prettier exception message.
    -     *
    -     * @param ex the SAXParseException
    -     * @return an easier to read exception message
    -     */
    -    private String getPrettyParseExceptionInfo(SAXParseException ex) {
    +
        private String getPrettyParseExceptionInfo(SAXParseException ex) {
     
             final StringBuilder sb = new StringBuilder();
     
    @@ -362,13 +337,13 @@
     
    Line
    org\owasp\dependencycheck\xml\suppression\SuppressionParser.java125
    126
    org\owasp\dependencycheck\xml\suppression\SuppressionParser.java173
    183
    -
                final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream(SUPPRESSION_SCHEMA);
    +
                schemaStream = this.getClass().getClassLoader().getResourceAsStream(SUPPRESSION_SCHEMA);
                 final SuppressionHandler handler = new SuppressionHandler();
                 final SAXParserFactory factory = SAXParserFactory.newInstance();
                 factory.setNamespaceAware(true);
    @@ -400,7 +375,7 @@
     
    182
    org\owasp\dependencycheck\analyzer\PythonDistributionAnalyzer.java244
    247
        public void initializeFileTypeAnalyzer() throws InitializationException {
    diff --git a/dependency-check-core/dependency-analysis.html b/dependency-check-core/dependency-analysis.html
    index fbbca43a3..62f2ec4f1 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-utils1.4.21.4.3 compile jar
    # of dependencies using the latest version available26
    24
    # 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 update7
    8
    # of dependencies where the next version available is a minor version update15
    16
    # of dependencies where the next version available is a major version update1
    +2

    Dependency Management

    @@ -324,7 +324,7 @@ - + @@ -332,7 +332,7 @@ - + @@ -528,7 +528,7 @@ - + @@ -537,7 +537,7 @@ - + @@ -552,6 +552,18 @@ + + + + + + + + + + + + @@ -563,7 +575,7 @@ - + @@ -575,7 +587,7 @@ - + @@ -587,7 +599,7 @@ - + @@ -599,7 +611,7 @@ - + @@ -611,7 +623,7 @@ - + @@ -623,7 +635,7 @@ - + @@ -635,7 +647,7 @@ - + @@ -647,7 +659,7 @@ - + @@ -662,7 +674,7 @@

    Dependencies

    1.4.177
    com.sun.mail mailapi 1.5.5 jar 1.5.6
    org.apache.maven.plugin-tools maven-plugin-annotations 3.4jar 3.5
    org.apache.maven.sharedmaven-dependency-tree2.2jar3.0
    org.apache.velocity velocity
    org.glassfish javax.json
    org.hamcrest hamcrest-core
    org.jmockit jmockit 1.25
    org.jsoup jsoup
    org.slf4j slf4j-api
    org.slf4j slf4j-simple
    org.sonatype.plexus plexus-sec-dispatcher
    Status Group Id Artifact Id
    - + @@ -674,7 +686,7 @@ - + @@ -686,7 +698,7 @@ - + @@ -698,7 +710,7 @@ - + @@ -710,7 +722,7 @@ - + @@ -722,7 +734,7 @@ - + @@ -734,7 +746,7 @@ - + @@ -746,7 +758,7 @@ - + @@ -758,7 +770,7 @@ - + @@ -770,7 +782,7 @@ - + @@ -782,7 +794,7 @@ - + @@ -794,7 +806,7 @@ - + @@ -806,7 +818,7 @@ - + @@ -818,7 +830,7 @@ - + @@ -830,11 +842,11 @@ - + - + @@ -842,7 +854,7 @@ - + @@ -854,7 +866,7 @@ - + @@ -866,7 +878,7 @@ - + @@ -878,7 +890,7 @@ - + @@ -890,7 +902,7 @@ - + @@ -902,7 +914,7 @@ - + @@ -920,25 +932,25 @@

    ch.qos.logback:logback-classic

    Status Group Id Artifact IdNext Incremental Next Minor Next Major
    com.google.inject guice 4.0-beta
    com.hazelcast hazelcast2.5.1 2.6 3.0
    com.thoughtworks.xstream xstream1.4.9
    net.sf.ehcache ehcache-core 2.3.0
    org.apache.axis2 axis2-adb 1.5
    org.apache.axis2 axis2-spring 1.5
    org.apache.geronimo.daytrader daytrader-ear
    org.apache.maven.scm maven-scm-provider-cvsexe 1.9
    org.apache.openjpa openjpa 2.1.0
    org.apache.struts struts2-core2.1.6 2.2.1
    org.dojotoolkit dojo-war 1.11.1
    org.glassfish.main.admingui war 4.1
    org.mortbay.jetty jetty6.1.17
    org.owasp dependency-check-utils1.4.21.4.3 compile jar
    org.springframework spring-webmvc2.5.6 3.0.0.RELEASE
    org.springframework.retry spring-retry1.1.1.RELEASE
    org.springframework.security spring-security-web3.0.1.RELEASE 3.1.0.RELEASE 4.0.0.RELEASE
    uk.ltd.getahead dwr
    xalan xalan2.7.2
    Status Group Id Artifact Id
    - + - + - + - + - + - + - +
    Status  No newer versions available.
    Group Id ch.qos.logback
    Artifact Id logback-classic
    Current Version 1.1.7
    Scope
    Classifier
    Type jar
    @@ -1069,13 +1081,13 @@ jar Newer versions -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.7-EA 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.7
    3.7-EA
    3.7.1 Latest Major

    com.sun.mail:mailapi

    - + @@ -1093,7 +1105,10 @@ -
    Status No newer versions available.
     There is at least one newer incremental version available. Incremental updates are typically passive.
    Group Id com.sun.mail
    Typejar
    +jar + +Newer versions +1.5.6 Next Incremental

    com.thoughtworks.xstream:xstream

    @@ -1450,7 +1465,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.lucene:lucene-core

    @@ -1477,7 +1492,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.lucene:lucene-queryparser

    @@ -1504,7 +1519,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.lucene:lucene-test-framework

    @@ -1531,7 +1546,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.maven:maven-core

    @@ -1633,7 +1648,7 @@
    - + @@ -1651,7 +1666,10 @@ -
    Status No newer versions available.
     There is at least one newer minor version available. Minor updates are sometimes passive.
    Group Id org.apache.maven.plugin-tools
    Typejar
    +jar + +Newer versions +3.5 Next Minor

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

    @@ -1704,6 +1722,33 @@
    Newer versions 1.9 Next Minor
    1.9.1
    1.9.2
    1.9.4
    1.9.5 Latest Minor
    +

    org.apache.maven.shared:maven-dependency-tree

    + + + + + + + + + + + + + + + + + + + + + + + + +
    Status There is at least one newer major version available. Major updates are rarely passive.
    Group Idorg.apache.maven.shared
    Artifact Idmaven-dependency-tree
    Current Version2.2
    Scope
    Classifier
    Typejar
    Newer versions3.0 Next Major
    +

    org.apache.openjpa:openjpa

    @@ -1909,7 +1954,7 @@ -
    jar
    Newer versions1.25 Next Minor
    +1.25 Next Minor
    1.26
    1.27 Latest Minor

    org.jsoup:jsoup

    @@ -1975,7 +2020,7 @@ - + @@ -2137,7 +2182,7 @@ -
    dependency-check-utils
    Current Version1.4.2
    1.4.3
    Scope compile
    jar
    Newer versions3.0.1.RELEASE Next Incremental
    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.0.8.RELEASE Latest Incremental
    3.1.0.RELEASE Next Minor
    3.1.1.RELEASE
    3.1.2.RELEASE
    3.1.3.RELEASE
    3.1.4.RELEASE
    3.1.5.RELEASE
    3.1.6.RELEASE
    3.1.7.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 Latest Minor
    4.0.0.RELEASE Next Major
    4.0.1.RELEASE
    4.0.2.RELEASE
    4.0.3.RELEASE
    4.0.4.RELEASE
    4.1.0.RELEASE
    4.1.1.RELEASE Latest Major
    +3.0.1.RELEASE Next Incremental
    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.0.8.RELEASE Latest Incremental
    3.1.0.RELEASE Next Minor
    3.1.1.RELEASE
    3.1.2.RELEASE
    3.1.3.RELEASE
    3.1.4.RELEASE
    3.1.5.RELEASE
    3.1.6.RELEASE
    3.1.7.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 Latest Minor
    4.0.0.RELEASE Next Major
    4.0.1.RELEASE
    4.0.2.RELEASE
    4.0.3.RELEASE
    4.0.4.RELEASE
    4.1.0.RELEASE
    4.1.1.RELEASE
    4.1.2.RELEASE
    4.1.3.RELEASE Latest Major

    uk.ltd.getahead:dwr

    diff --git a/dependency-check-core/failsafe-report.html b/dependency-check-core/failsafe-report.html index 66c25ebc4..9a86b2d1b 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%127.255

    +130.044

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


    Package List

    @@ -288,12 +288,12 @@ function toggleDisplay(elementId) { Time org.owasp.dependencycheck.data.update -2 +3 0 0 0 100% -1.11 +4.471 org.owasp.dependencycheck.reporting 2 @@ -301,39 +301,31 @@ function toggleDisplay(elementId) { 0 0 100% -7.627 +7.617 -org.owasp.dependencycheck.data.update.nvd -1 -0 -0 -0 -100% -2.642 - org.owasp.dependencycheck.data.nvdcve 10 0 0 0 100% -6.628 - +6.318 + org.owasp.dependencycheck 1 0 0 0 100% -46.583 - +44.53 + org.owasp.dependencycheck.analyzer 22 0 0 0 100% -62.665
    +67.108

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

    org.owasp.dependencycheck.data.update

    @@ -355,16 +347,16 @@ function toggleDisplay(elementId) { 0 0 100% -0.021 +0 NvdCveUpdaterIntegrationTest -1 +2 0 0 0 100% -1.089
    +4.471

    org.owasp.dependencycheck.reporting

    @@ -385,28 +377,7 @@ function toggleDisplay(elementId) { -
    0 0 100%7.627
    -
    -

    org.owasp.dependencycheck.data.update.nvd

    - - - - - - - - - - - - - - - - - - -
    ClassTestsErrors FailuresSkippedSuccess RateTime
    NvdCveUpdaterIntegrationTest1000100%2.642
    +7.617

    org.owasp.dependencycheck.data.nvdcve

    @@ -427,7 +398,7 @@ function toggleDisplay(elementId) { - + @@ -436,7 +407,7 @@ function toggleDisplay(elementId) { -
    0 0 100%3.513
    3.134
    DatabasePropertiesIntegrationTest0 0 100%3.115
    +3.184

    org.owasp.dependencycheck

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

    org.owasp.dependencycheck.analyzer

    @@ -478,7 +449,7 @@ function toggleDisplay(elementId) { - + @@ -487,7 +458,7 @@ function toggleDisplay(elementId) { - + @@ -496,7 +467,7 @@ function toggleDisplay(elementId) { - + @@ -505,7 +476,7 @@ function toggleDisplay(elementId) { -
    0 0 100%19.052
    21.696
    CPEAnalyzerIntegrationTest0 0 100%41.103
    42.85
    DependencyBundlingAnalyzerIntegrationTest0 0 100%0
    0.015
    VulnerabilitySuppressionAnalyzerIntegrationTest0 0 100%2.51

    +2.547

    Test Cases

    [Summary] [Package List] [Test Cases]

    @@ -515,23 +486,23 @@ function toggleDisplay(elementId) { testAnalyzeExecutableJar -1.079 +1.086 testAnalyzeTar -1.418 +1.411 testAnalyzeTgz -4.873 +5.4 testAnalyzeTarBz2 -3.642 +3.692 testAnalyze -0.818 +0.847 testGetAnalysisPhase @@ -543,7 +514,7 @@ function toggleDisplay(elementId) { testAnalyze_badZip -0.521 +0.523 testInitialize @@ -551,11 +522,11 @@ function toggleDisplay(elementId) { testAnalyzeTbz2 -3.137 +3.182 testAnalyzeTarGz -2.96 +2.9 testSupportsExtension @@ -570,23 +541,23 @@ function toggleDisplay(elementId) { testSearchCPE -1.768 +1.486 testDetermineCPE -1.156 +1.055 testDetermineIdentifiers -0.908 +1.115 testDetermineCPE_full -37.271 +39.175 testBuildSearch -0
    +0.001

    DependencyBundlingAnalyzerIntegrationTest

    @@ -600,7 +571,7 @@ function toggleDisplay(elementId) { - + @@ -608,53 +579,53 @@ function toggleDisplay(elementId) { -
    testAnalyze2.495
    2.547
    testGetAnalysisPhase
    testGetName0.015
    +0

    CveDBIntegrationTest

    - + - + - + - + -
    testOpen1.073
    0.966
    testGetCPEs0.528
    0.503
    testGetVulnerabilities0.815
    0.634
    testGetMatchingSoftware0.552
    0.508
    testgetVulnerability0.529
    +0.523

    DatabasePropertiesIntegrationTest

    - + - + - + - + -
    testSave1.024
    1.041
    testGetProperty_String_String0.515
    0.53
    testGetProperties0.541
    0.533
    testGetProperty_String0.513
    0.535
    testIsEmpty0.522
    +0.529

    CpeUpdaterIntegrationTest

    @@ -663,37 +634,34 @@ function toggleDisplay(elementId) {
    testUpdate 0
    -

    NvdCveUpdaterIntegrationTest

    - - - - -
    testUpdate2.642
    -

    NvdCveUpdaterIntegrationTest

    -
    testUpdatesNeeded1.089
    +1.081 + + +testUpdate +3.39

    EngineIntegrationTest

    -
    testEngine46.567
    +44.529

    ReportGeneratorIntegrationTest

    - + -
    testGenerateXMLReport7.624
    7.612
    testGenerateReport0

    +0.001
    diff --git a/dependency-check-core/findbugs.html b/dependency-check-core/findbugs.html index 88d4afb0b..134dea97b 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,8 +251,8 @@ Errors Missing Classes -147 -6 +149 +2 0 0
    @@ -262,50 +262,8 @@ Class Bugs -org.owasp.dependencycheck.analyzer.ArchiveAnalyzer -1 - -org.owasp.dependencycheck.analyzer.CMakeAnalyzer -1 - org.owasp.dependencycheck.analyzer.FalsePositiveAnalyzer -2 - -org.owasp.dependencycheck.analyzer.RubyBundleAuditAnalyzer -1 - -org.owasp.dependencycheck.analyzer.RubyGemspecAnalyzer -1
    -
    -

    org.owasp.dependencycheck.analyzer.ArchiveAnalyzer

    - - - - - - - - - - - - -
    BugCategoryDetailsLinePriority
    org.owasp.dependencycheck.analyzer.ArchiveAnalyzer.ensureReadableJar(String, BufferedInputStream) ignores result of java.io.BufferedInputStream.read(byte[])BAD_PRACTICERR_NOT_CHECKED417Medium
    -
    -

    org.owasp.dependencycheck.analyzer.CMakeAnalyzer

    - - - - - - - - - - - - -
    BugCategoryDetailsLinePriority
    Found reliance on default encoding in org.owasp.dependencycheck.analyzer.CMakeAnalyzer.analyzeSetVersionCommand(Dependency, Engine, String): String.getBytes()I18NDM_DEFAULT_ENCODING227High
    +2

    org.owasp.dependencycheck.analyzer.FalsePositiveAnalyzer

    @@ -326,36 +284,6 @@ -
    STYLE NP_NULL_ON_SOME_PATH_MIGHT_BE_INFEASIBLE 188Medium
    -
    -

    org.owasp.dependencycheck.analyzer.RubyBundleAuditAnalyzer

    - - - - - - - - - - - - -
    BugCategoryDetailsLinePriority
    Exceptional return value of java.io.File.createNewFile() ignored in org.owasp.dependencycheck.analyzer.RubyBundleAuditAnalyzer.createDependencyForGem(Engine, String, String, String, String)BAD_PRACTICERV_RETURN_VALUE_IGNORED_BAD_PRACTICE485Medium
    -
    -

    org.owasp.dependencycheck.analyzer.RubyGemspecAnalyzer

    - - - - - - - - - - - -
    BugCategoryDetailsLinePriority
    Possible null pointer dereference in org.owasp.dependencycheck.analyzer.RubyGemspecAnalyzer.addEvidenceFromVersionFile(File, EvidenceCollection) due to return value of called methodSTYLENP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE220 Medium
    diff --git a/dependency-check-core/index.html b/dependency-check-core/index.html index 968d06a9c..7ddecad75 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 eeb717174..d9a17a61f 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 2a8585ec8..24e06d49c 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 2ed5544bb..e49e58886 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 c4ec30abf..bb38d2003 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 22d24734f..b45361237 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 @@ diff --git a/dependency-check-core/pmd.html b/dependency-check-core/pmd.html index 2df97c251..fd2a87fac 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 combined -431440 +437446 These nested if statements could be combined -432439 +438445 These nested if statements could be combined -433438 +439444 These nested if statements could be combined -434437 +440443

    org/owasp/dependencycheck/analyzer/CPEAnalyzer.java

    @@ -267,241 +267,253 @@ - + - + -
    Line
    These nested if statements could be combined581586
    582587
    These nested if statements could be combined582585
    583586
    These nested if statements could be combined590593
    +591594
    -

    org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.java

    +

    org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.java

    + + + + +
    Violation Line
    Useless parentheses.400401
    Useless parentheses.402403
    +
    +

    org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.java

    + + + + + - +
    ViolationLine
    These nested if statements could be combined 115121
    These nested if statements could be combined 177197

    org/owasp/dependencycheck/analyzer/JarAnalyzer.java

    - + - + -
    Violation Line
    Useless parentheses.386
    +388

    org/owasp/dependencycheck/analyzer/OpenSSLAnalyzer.java

    - + - +
    Violation Line
    Useless parentheses. 112

    org/owasp/dependencycheck/analyzer/PythonDistributionAnalyzer.java

    - + - + -
    Violation Line
    These nested if statements could be combined299302
    +302305

    org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.java

    - + - + - + + + + - - - -
    Violation Line
    These nested if statements could be combined363365
    369371
    Useless parentheses.385
    Useless parentheses.379
    Useless parentheses.397
    +403

    org/owasp/dependencycheck/data/cpe/IndexEntry.java

    - + - + - +
    Violation Line
    Useless parentheses. 172
    Useless parentheses. 175

    org/owasp/dependencycheck/data/lucene/TokenPairConcatenatingFilter.java

    - + - +
    Violation Line
    Useless parentheses. 156

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

    - + - + -
    Violation Line
    Avoid empty if statements332334
    +344346

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

    - + - - - -
    Violation Line
    These nested if statements could be combined646648
    These nested if statements could be combined758760
    +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.177
    +173

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

    - + - + -
    Violation Line
    Useless parentheses.253
    +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.115
    Useless parentheses.118
    116
    Useless parentheses.121
    +119 + +Useless parentheses. +122

    org/owasp/dependencycheck/dependency/Vulnerability.java

    - + - + -
    Violation Line
    Useless parentheses.374
    +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
    -

    org/owasp/dependencycheck/xml/pom/License.java

    +

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

    - + + + +
    Violation Line
    These nested if statements could be combined192197
    +
    +

    org/owasp/dependencycheck/xml/pom/License.java

    + + + + - +
    ViolationLine
    Useless parentheses. 118
    Useless parentheses. 121

    org/owasp/dependencycheck/xml/pom/PomHandler.java

    - + - + - +
    Violation Line
    These nested if statements could be combined 170176
    These nested if statements could be combined 171175

    org/owasp/dependencycheck/xml/suppression/PropertyType.java

    - + - + -
    Violation Line
    Useless parentheses.161
    -
    -

    org/owasp/dependencycheck/xml/suppression/SuppressionErrorHandler.java

    - - - - - - -
    ViolationLine
    Avoid unused private fields such as 'LOGGER'.36
    +161 diff --git a/dependency-check-core/project-info.html b/dependency-check-core/project-info.html index e159da074..91ef98c22 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 f431d0eb0..1266ea2bf 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 d3e91d6d9..1415e07e7 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 @@ dependency-check-core Version -1.4.2 +1.4.3 Type jar diff --git a/dependency-check-core/source-repository.html b/dependency-check-core/source-repository.html index 262975588..ae9c0b050 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 e73d6af29..a28daba0c 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) { Success Rate Time -245 +251 0 0 -9 -96.327% -21.366
    +13 +94.821% +18.21

    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.413 +2.604 org.owasp.dependencycheck.dependency 34 @@ -301,7 +301,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.015 +0.005 org.owasp.dependencycheck.data.nexus 4 @@ -309,7 +309,7 @@ function toggleDisplay(elementId) { 0 4 0% -0.002 +0 org.owasp.dependencycheck.data.composer 4 @@ -317,7 +317,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.016 +0 org.owasp.dependencycheck.data.nuget 3 @@ -325,7 +325,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.006 +0.001 org.owasp.dependencycheck.xml.hints 3 @@ -341,15 +341,15 @@ function toggleDisplay(elementId) { 0 0 100% -0.012 +0.008 org.owasp.dependencycheck.analyzer -80 +86 0 0 -5 -93.75% -16.582 +9 +89.535% +12.868 org.owasp.dependencycheck.data.cpe 1 @@ -357,7 +357,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.016 +0 org.owasp.dependencycheck.data.lucene 10 @@ -365,7 +365,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.466 +0.943 org.owasp.dependencycheck.data.cwe 1 @@ -381,7 +381,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.978 +0.923 org.owasp.dependencycheck.xml.pom 23 @@ -397,7 +397,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.547 +0.563 org.owasp.dependencycheck.xml.suppression 36 @@ -413,7 +413,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.297
    +0.279

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

    org.owasp.dependencycheck.data.update

    @@ -435,7 +435,7 @@ function toggleDisplay(elementId) { 0 0 100% -2.171 +2.39 EngineVersionCheckTest @@ -444,7 +444,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.242
    +0.214

    org.owasp.dependencycheck.dependency

    @@ -465,7 +465,7 @@ function toggleDisplay(elementId) { - + @@ -474,7 +474,7 @@ function toggleDisplay(elementId) { - + @@ -483,7 +483,7 @@ function toggleDisplay(elementId) { - + @@ -492,7 +492,7 @@ function toggleDisplay(elementId) { -
    0 0 100%0.007
    0
    EvidenceTest0 0 100%0.002
    0
    VulnerabilityTest0 0 100%0.003
    0
    VulnerableSoftwareTest0 0 100%0.003
    +0.005

    org.owasp.dependencycheck.data.nexus

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

    org.owasp.dependencycheck.data.composer

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

    org.owasp.dependencycheck.data.nuget

    @@ -555,7 +555,7 @@ function toggleDisplay(elementId) { -
    0 0 100%0.006
    +0.001

    org.owasp.dependencycheck.xml.hints

    @@ -606,7 +606,7 @@ function toggleDisplay(elementId) { - + @@ -615,7 +615,7 @@ function toggleDisplay(elementId) { - + @@ -624,7 +624,7 @@ function toggleDisplay(elementId) { - + @@ -633,7 +633,7 @@ function toggleDisplay(elementId) { -
    0 0 100%0.004
    0
    DependencyVersionTest0 0 100%0.003
    0.006
    DependencyVersionUtilTest0 0 100%0.003
    0.002
    FilterTest0 0 100%0.002
    +0

    org.owasp.dependencycheck.analyzer

    @@ -654,7 +654,7 @@ function toggleDisplay(elementId) { - + @@ -663,7 +663,7 @@ function toggleDisplay(elementId) { - + @@ -672,7 +672,7 @@ function toggleDisplay(elementId) { - + @@ -681,16 +681,16 @@ function toggleDisplay(elementId) { - + - - - + + + @@ -699,7 +699,7 @@ function toggleDisplay(elementId) { - + @@ -708,7 +708,7 @@ function toggleDisplay(elementId) { - + @@ -717,7 +717,7 @@ function toggleDisplay(elementId) { - + @@ -735,7 +735,7 @@ function toggleDisplay(elementId) { - + @@ -753,7 +753,7 @@ function toggleDisplay(elementId) { - + @@ -762,7 +762,7 @@ function toggleDisplay(elementId) { - + @@ -771,7 +771,7 @@ function toggleDisplay(elementId) { - + @@ -780,7 +780,7 @@ function toggleDisplay(elementId) { - + @@ -789,7 +789,7 @@ function toggleDisplay(elementId) { - + @@ -798,7 +798,7 @@ function toggleDisplay(elementId) { - + @@ -807,7 +807,7 @@ function toggleDisplay(elementId) { - + @@ -816,7 +816,7 @@ function toggleDisplay(elementId) { - + @@ -834,6 +834,15 @@ function toggleDisplay(elementId) { + + + + + + + + +
    0 0 100%0.569
    0.691
    AbstractSuppressionAnalyzerTest0 0 100%0.394
    0.475
    AnalyzerServiceTest0 0 100%0.064
    0.085
    ArchiveAnalyzerTest0 1 0%0.002
    0.015
    AssemblyAnalyzerTest 5 0 0180%0.667
    50%0.59
    AutoconfAnalyzerTest0 0 100%0.031
    0.085
    CMakeAnalyzerTest0 0 100%0.837
    0.807
    ComposerLockAnalyzerTest0 0 100%1.071
    0.1
    DependencyBundlingAnalyzerTest0 0 100%0.002
    0
    FileNameAnalyzerTest0 0 100%3.262
    4.868
    JarAnalyzerTest0 0 100%0.14
    0.134
    NodePackageAnalyzerTest0 0 100%0.008
    0.002
    NuspecAnalyzerTest0 0 100%0.003
    0
    OpenSSLAnalyzerTest0 0 100%0.002
    0.001
    PythonDistributionAnalyzerTest0 0 100%2.052
    0.025
    PythonPackageAnalyzerTest0 0 100%1.975
    0.003
    RubyBundleAuditAnalyzerTest0 3 50%5.503
    4.987
    RubyBundlerAnalyzerTest0 0 100%0
    SwiftAnalyzersTest6000100% 0

    org.owasp.dependencycheck.data.cpe

    @@ -855,7 +864,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.016
    +0

    org.owasp.dependencycheck.data.lucene

    @@ -894,7 +903,7 @@ function toggleDisplay(elementId) { - + @@ -903,7 +912,7 @@ function toggleDisplay(elementId) { -
    0 0 100%0.116
    0.17
    UrlTokenizingFilterTest0 0 100%0.35
    +0.773

    org.owasp.dependencycheck.data.cwe

    @@ -945,7 +954,7 @@ function toggleDisplay(elementId) { - + @@ -954,7 +963,7 @@ function toggleDisplay(elementId) { - + @@ -963,7 +972,7 @@ function toggleDisplay(elementId) { - + @@ -972,7 +981,7 @@ function toggleDisplay(elementId) { - + @@ -981,7 +990,7 @@ function toggleDisplay(elementId) { -
    0 0 100%0.86
    0.823
    NvdCveInfoTest0 0 100%0.025
    0.016
    NvdCve_1_2_HandlerTest0 0 100%0.003
    0
    NvdCve_2_0_HandlerTest0 0 100%0.087
    0.084
    UpdateableNvdCveTest0 0 100%0.003
    +0

    org.owasp.dependencycheck.xml.pom

    @@ -1032,7 +1041,7 @@ function toggleDisplay(elementId) { - + @@ -1041,7 +1050,7 @@ function toggleDisplay(elementId) { -
    0 0 100%0.497
    0.5
    DriverLoaderTest0 0 100%0.05
    +0.063

    org.owasp.dependencycheck.xml.suppression

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

    org.owasp.dependencycheck.data.central

    @@ -1110,7 +1119,7 @@ function toggleDisplay(elementId) { -
    0 0 100%0.297

    +0.279

    Test Cases

    [Summary] [Package List] [Test Cases]

    @@ -1120,22 +1129,22 @@ function toggleDisplay(elementId) { testNewHashSet -0.02
    +0.017

    AbstractSuppressionAnalyzerTest

    - + - + - + @@ -1146,11 +1155,11 @@ function toggleDisplay(elementId) { - + -
    testFailureToLocateSuppressionFileAnywhere0.199
    0.241
    testGetRulesFromSuppressionFileFromURL0.17
    0.193
    testGetRulesFromSuppressionFileInClasspath0.022
    0.037
    testGetSupportedExtensions
    testGetAnalyzers0.047
    0.069
    testGetExperimentalAnalyzers0.017
    +0.016

    ArchiveAnalyzerTest

    @@ -1167,13 +1176,23 @@ function toggleDisplay(elementId) {

    AssemblyAnalyzerTest

    - - - + + + - - - + + + + + + + + + + + - - - + + + - - -
    testGetName0.253
    testGetName +0
    testAnalysis0.128
    skipped
    testAnalysis +0
    skipped
    testWithSettingMono @@ -1184,20 +1203,30 @@ function toggleDisplay(elementId) { skipped
    testNonexistent0.099
    testNonexistent +0
    testLog4Net0.138
    + +skipped + + + +testLog4Net +
    + [ Detail ]
    +0 + + +skipped +

    AutoconfAnalyzerTest

    - + @@ -1209,11 +1238,11 @@ function toggleDisplay(elementId) { - + - + @@ -1236,7 +1265,7 @@ function toggleDisplay(elementId) { - + @@ -1251,7 +1280,7 @@ function toggleDisplay(elementId) { - + @@ -1323,7 +1352,7 @@ function toggleDisplay(elementId) { - + @@ -1331,14 +1360,14 @@ function toggleDisplay(elementId) { -
    testAnalyzeReadableConfigureScript0
    0.031
    testGetName
    testAnalyzeConfigureScript0.031
    0.038
    testAnalyzeConfigureAC10
    0.016
    testAnalyzeConfigureAC2
    testAnalyzeCMakeListsOpenCV3rdParty0.837
    0.807
    testAccept
    testAnalyzePackageJson1.071
    0.1
    testSupportsFiles
    testAnalyze3.246
    4.868
    testGetAnalysisPhase
    testGetName0.016
    +0

    JarAnalyzerTest

    - + @@ -1350,7 +1379,7 @@ function toggleDisplay(elementId) { -
    testAnalyze0.096
    0.101
    testGetName
    testParseManifest0.027
    +0.032

    NodePackageAnalyzerTest

    @@ -1414,19 +1443,19 @@ function toggleDisplay(elementId) { - + - + - + - + @@ -1434,7 +1463,7 @@ function toggleDisplay(elementId) { -
    testAnalyzeEggArchive0
    0.001
    testAnalyzeEggArchiveNamedZip0.002
    0
    testAnalyzeWheel0.02
    0.012
    testAnalyzeEggInfoFolder0.002
    0.005
    testAnalyzeSitePackage
    testSupportsFiles0.004
    +0.002

    PythonPackageAnalyzerTest

    @@ -1456,7 +1485,7 @@ function toggleDisplay(elementId) { - + @@ -1523,12 +1552,39 @@ function toggleDisplay(elementId) {
    testMissingBundleAudit0.713
    0.53
    testGetNametestSupportsFiles 0
    +

    SwiftAnalyzersTest

    + + + + + + + + + + + + + + + + + + + + + + + + +
    testSPMGetName0
    testPodsGetName0
    testSPMSupportsFiles0
    testPodsSupportsFiles0
    testCocoaPodsAnalyzer0
    testSPMAnalyzer0
    +

    CentralSearchTest

    - + @@ -1563,7 +1619,7 @@ function toggleDisplay(elementId) { -
    testMultipleReturns0.181
    0.163
    testNullSha1
    testNotJSON0.016
    +0

    IndexEntryTest

    @@ -1609,27 +1665,27 @@ function toggleDisplay(elementId) {
    - - + + - +
    testClear0.038
    testExamples0.054
    testExamplestestClear 0

    UrlTokenizingFilterTest

    - - + + - - + + - -
    testRandomStrings0.325
    testEmptyTerm0.007
    testEmptyTerm0.003
    testExamples0.026
    testExamples0.005
    +testRandomStrings +0.578

    NexusSearchTest

    @@ -1679,7 +1735,7 @@ function toggleDisplay(elementId) { - + @@ -1713,11 +1769,11 @@ function toggleDisplay(elementId) { - + -
    testMissingDocument0
    0.001
    testNotNuspec
    testLoad_String_String0.016
    0.031
    testLoad_String_String_multiple_paths0.018
    +0.032

    BaseUpdaterTest

    @@ -1728,26 +1784,26 @@ function toggleDisplay(elementId) { - + - + -
    testOpenDataStores1.048
    1
    testGetProperties0.547
    0.882
    testCloseDataStores0.56
    +0.506

    EngineVersionCheckTest

    - + -
    testShouldUpdate0.205
    0.183
    testGetCurrentReleaseVersion0.037
    +0.031

    DownloadTaskTest

    @@ -1758,7 +1814,7 @@ function toggleDisplay(elementId) { -
    testCall0.857
    +0.808

    NvdCveInfoTest

    @@ -2234,7 +2290,7 @@ function toggleDisplay(elementId) { - + @@ -2319,12 +2375,36 @@ function toggleDisplay(elementId) { + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dependency-check-core/taglist.html b/dependency-check-core/taglist.html index 0d8e9d463..3b52e0c2a 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,12 +246,12 @@ - +
    testAddCvssBelow0
    0.016
    testFilePathskipped: skipped
    testGetName
    skipped: skipped
    testAnalysis
    skipped: skipped
    testWithSettingMono
    skipped: skipped
    testNonexistent
    skipped: skipped
    testLog4Net
    skipped: skipped
    testAnalysis
    Tag strings used by tag class
    Todo Work2526 todo, FIXME

    Each tag is detailed below:

    Todo Work

    -

    Number of occurrences found in the code: 25

    +

    Number of occurrences found in the code: 26

    @@ -260,29 +260,35 @@ + + + + + + - + - + - + - + - + - + @@ -309,7 +315,7 @@ - + @@ -321,7 +327,7 @@ - + @@ -329,11 +335,17 @@ + + + + + + - + @@ -341,12 +353,6 @@ - - - - - - diff --git a/dependency-check-core/team-list.html b/dependency-check-core/team-list.html index a6ad0ec64..39169c35e 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 fb24b4ccb..016e88106 100644 --- a/dependency-check-core/xref-test/allclasses-frame.html +++ b/dependency-check-core/xref-test/allclasses-frame.html @@ -159,7 +159,7 @@ NvdCveInfoTest
  • - NvdCveUpdaterIntegrationTest + NvdCveUpdaterIntegrationTest
  • NvdCve_1_2_HandlerTest @@ -202,6 +202,9 @@
  • SuppressionRuleTest +
  • +
  • + SwiftAnalyzersTest
  • TokenPairConcatenatingFilterTest diff --git a/dependency-check-core/xref-test/index.html b/dependency-check-core/xref-test/index.html index 49f52c91f..415806e7b 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.2 Reference + Dependency-Check Core 1.4.3 Reference diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/AssemblyAnalyzerTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/AssemblyAnalyzerTest.html index 5cf08bcba..0fe7f7832 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/AssemblyAnalyzerTest.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/AssemblyAnalyzerTest.html @@ -32,161 +32,164 @@ 24 import static org.junit.Assert.fail; 25 import org.junit.Assume; 26 import static org.junit.Assume.assumeFalse; -27 import org.junit.Before; -28 import org.junit.Test; -29 import org.owasp.dependencycheck.BaseTest; -30 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; -31 import org.owasp.dependencycheck.dependency.Confidence; -32 import org.owasp.dependencycheck.dependency.Dependency; -33 import org.owasp.dependencycheck.dependency.Evidence; -34 import org.owasp.dependencycheck.exception.InitializationException; -35 import org.owasp.dependencycheck.utils.Settings; -36 import org.slf4j.Logger; -37 import org.slf4j.LoggerFactory; -38 -39 /** -40 * Tests for the AssemblyAnalyzer. -41 * -42 * @author colezlaw -43 * -44 */ -45 public class AssemblyAnalyzerTest extends BaseTest { -46 -47 private static final Logger LOGGER = LoggerFactory.getLogger(AssemblyAnalyzerTest.class); -48 -49 private static final String LOG_KEY = "org.slf4j.simpleLogger.org.owasp.dependencycheck.analyzer.AssemblyAnalyzer"; -50 -51 AssemblyAnalyzer analyzer; -52 -53 /** -54 * Sets up the analyzer. -55 * -56 * @throws Exception if anything goes sideways -57 */ -58 @Before -59 public void setUp() throws Exception { -60 try { -61 analyzer = new AssemblyAnalyzer(); -62 analyzer.accept(new File("test.dll")); // trick into "thinking it is active" -63 analyzer.initialize(); -64 } catch (Exception e) { -65 if (e.getMessage().contains("Could not execute .NET AssemblyAnalyzer")) { -66 LOGGER.warn("Exception setting up AssemblyAnalyzer. Tests will be incomplete"); -67 } else { +27 import static org.junit.Assume.assumeNotNull; +28 import org.junit.Before; +29 import org.junit.Test; +30 import org.owasp.dependencycheck.BaseTest; +31 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; +32 import org.owasp.dependencycheck.dependency.Confidence; +33 import org.owasp.dependencycheck.dependency.Dependency; +34 import org.owasp.dependencycheck.dependency.Evidence; +35 import org.owasp.dependencycheck.exception.InitializationException; +36 import org.owasp.dependencycheck.utils.Settings; +37 import org.slf4j.Logger; +38 import org.slf4j.LoggerFactory; +39 +40 /** +41 * Tests for the AssemblyAnalyzer. +42 * +43 * @author colezlaw +44 * +45 */ +46 public class AssemblyAnalyzerTest extends BaseTest { +47 +48 private static final Logger LOGGER = LoggerFactory.getLogger(AssemblyAnalyzerTest.class); +49 +50 private static final String LOG_KEY = "org.slf4j.simpleLogger.org.owasp.dependencycheck.analyzer.AssemblyAnalyzer"; +51 +52 AssemblyAnalyzer analyzer; +53 +54 /** +55 * Sets up the analyzer. +56 * +57 * @throws Exception if anything goes sideways +58 */ +59 @Before +60 public void setUp() throws Exception { +61 try { +62 analyzer = new AssemblyAnalyzer(); +63 analyzer.accept(new File("test.dll")); // trick into "thinking it is active" +64 analyzer.initialize(); +65 Assume.assumeTrue("Mono is not installed, skipping tests.", analyzer.buildArgumentList() == null); +66 } catch (Exception e) { +67 if (e.getMessage().contains("Could not execute .NET AssemblyAnalyzer")) { 68 LOGGER.warn("Exception setting up AssemblyAnalyzer. Tests will be incomplete"); -69 } -70 Assume.assumeNoException("Is mono installed? TESTS WILL BE INCOMPLETE", e); -71 } -72 } -73 -74 /** -75 * Tests to make sure the name is correct. -76 */ -77 @Test -78 public void testGetName() { -79 assertEquals("Assembly Analyzer", analyzer.getName()); -80 } -81 -82 @Test -83 public void testAnalysis() throws Exception { -84 //File f = new File(AssemblyAnalyzerTest.class.getClassLoader().getResource("GrokAssembly.exe").getPath()); -85 File f = BaseTest.getResourceAsFile(this, "GrokAssembly.exe"); -86 Dependency d = new Dependency(f); -87 analyzer.analyze(d, null); -88 boolean foundVendor = false; -89 for (Evidence e : d.getVendorEvidence().getEvidence("grokassembly", "vendor")) { -90 if ("OWASP".equals(e.getValue())) { -91 foundVendor = true; -92 } -93 } -94 assertTrue(foundVendor); -95 -96 boolean foundProduct = false; -97 for (Evidence e : d.getProductEvidence().getEvidence("grokassembly", "product")) { -98 if ("GrokAssembly".equals(e.getValue())) { -99 foundProduct = true; -100 } -101 } -102 assertTrue(foundProduct); -103 } -104 -105 @Test -106 public void testLog4Net() throws Exception { -107 //File f = new File(AssemblyAnalyzerTest.class.getClassLoader().getResource("log4net.dll").getPath()); -108 File f = BaseTest.getResourceAsFile(this, "log4net.dll"); -109 -110 Dependency d = new Dependency(f); -111 analyzer.analyze(d, null); -112 assertTrue(d.getVersionEvidence().getEvidence().contains(new Evidence("grokassembly", "version", "1.2.13.0", Confidence.HIGHEST))); -113 assertTrue(d.getVendorEvidence().getEvidence().contains(new Evidence("grokassembly", "vendor", "The Apache Software Foundation", Confidence.HIGH))); -114 assertTrue(d.getProductEvidence().getEvidence().contains(new Evidence("grokassembly", "product", "log4net", Confidence.HIGH))); -115 } -116 -117 @Test -118 public void testNonexistent() { -119 // Tweak the log level so the warning doesn't show in the console -120 String oldProp = System.getProperty(LOG_KEY, "info"); -121 //File f = new File(AssemblyAnalyzerTest.class.getClassLoader().getResource("log4net.dll").getPath()); -122 File f = BaseTest.getResourceAsFile(this, "log4net.dll"); -123 File test = new File(f.getParent(), "nonexistent.dll"); -124 Dependency d = new Dependency(test); -125 -126 try { -127 analyzer.analyze(d, null); -128 fail("Expected an AnalysisException"); -129 } catch (AnalysisException ae) { -130 assertEquals("File does not exist", ae.getMessage()); -131 } finally { -132 System.setProperty(LOG_KEY, oldProp); -133 } -134 } -135 -136 @Test -137 public void testWithSettingMono() throws Exception { +69 } else { +70 LOGGER.warn("Exception setting up AssemblyAnalyzer. Tests will be incomplete"); +71 } +72 Assume.assumeNoException("Is mono installed? TESTS WILL BE INCOMPLETE", e); +73 } +74 } +75 +76 /** +77 * Tests to make sure the name is correct. +78 */ +79 @Test +80 public void testGetName() { +81 assertEquals("Assembly Analyzer", analyzer.getName()); +82 } +83 +84 @Test +85 public void testAnalysis() throws Exception { +86 assumeNotNull(analyzer.buildArgumentList()); +87 File f = BaseTest.getResourceAsFile(this, "GrokAssembly.exe"); +88 Dependency d = new Dependency(f); +89 analyzer.analyze(d, null); +90 boolean foundVendor = false; +91 for (Evidence e : d.getVendorEvidence().getEvidence("grokassembly", "vendor")) { +92 if ("OWASP".equals(e.getValue())) { +93 foundVendor = true; +94 } +95 } +96 assertTrue(foundVendor); +97 +98 boolean foundProduct = false; +99 for (Evidence e : d.getProductEvidence().getEvidence("grokassembly", "product")) { +100 if ("GrokAssembly".equals(e.getValue())) { +101 foundProduct = true; +102 } +103 } +104 assertTrue(foundProduct); +105 } +106 +107 @Test +108 public void testLog4Net() throws Exception { +109 assumeNotNull(analyzer.buildArgumentList()); +110 File f = BaseTest.getResourceAsFile(this, "log4net.dll"); +111 +112 Dependency d = new Dependency(f); +113 analyzer.analyze(d, null); +114 assertTrue(d.getVersionEvidence().getEvidence().contains(new Evidence("grokassembly", "version", "1.2.13.0", Confidence.HIGHEST))); +115 assertTrue(d.getVendorEvidence().getEvidence().contains(new Evidence("grokassembly", "vendor", "The Apache Software Foundation", Confidence.HIGH))); +116 assertTrue(d.getProductEvidence().getEvidence().contains(new Evidence("grokassembly", "product", "log4net", Confidence.HIGH))); +117 } +118 +119 @Test +120 public void testNonexistent() { +121 assumeNotNull(analyzer.buildArgumentList()); +122 +123 // Tweak the log level so the warning doesn't show in the console +124 String oldProp = System.getProperty(LOG_KEY, "info"); +125 File f = BaseTest.getResourceAsFile(this, "log4net.dll"); +126 File test = new File(f.getParent(), "nonexistent.dll"); +127 Dependency d = new Dependency(test); +128 +129 try { +130 analyzer.analyze(d, null); +131 fail("Expected an AnalysisException"); +132 } catch (AnalysisException ae) { +133 assertEquals("File does not exist", ae.getMessage()); +134 } finally { +135 System.setProperty(LOG_KEY, oldProp); +136 } +137 } 138 -139 //This test doesn't work on Windows. -140 assumeFalse(System.getProperty("os.name").startsWith("Windows")); +139 @Test +140 public void testWithSettingMono() throws Exception { 141 -142 String oldValue = Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH); -143 // if oldValue is null, that means that neither the system property nor the setting has -144 // been set. If that's the case, then we have to make it such that when we recover, -145 // null still comes back. But you can't put a null value in a HashMap, so we have to set -146 // the system property rather than the setting. -147 if (oldValue == null) { -148 System.setProperty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, "/yooser/bine/mono"); -149 } else { -150 Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, "/yooser/bine/mono"); -151 } -152 -153 String oldProp = System.getProperty(LOG_KEY, "info"); -154 try { -155 // Tweak the logging to swallow the warning when testing -156 System.setProperty(LOG_KEY, "error"); -157 // Have to make a NEW analyzer because during setUp, it would have gotten the correct one -158 AssemblyAnalyzer aanalyzer = new AssemblyAnalyzer(); -159 aanalyzer.accept(new File("test.dll")); // trick into "thinking it is active" -160 aanalyzer.initialize(); -161 fail("Expected an InitializationException"); -162 } catch (InitializationException ae) { -163 assertEquals("An error occurred with the .NET AssemblyAnalyzer", ae.getMessage()); -164 } finally { -165 System.setProperty(LOG_KEY, oldProp); -166 // Recover the logger -167 // Now recover the way we came in. If we had to set a System property, delete it. Otherwise, -168 // reset the old value -169 if (oldValue == null) { -170 System.getProperties().remove(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH); -171 } else { -172 Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, oldValue); -173 } -174 } -175 } -176 -177 @After -178 public void tearDown() throws Exception { -179 analyzer.close(); -180 } -181 } +142 //This test doesn't work on Windows. +143 assumeFalse(System.getProperty("os.name").startsWith("Windows")); +144 +145 String oldValue = Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH); +146 // if oldValue is null, that means that neither the system property nor the setting has +147 // been set. If that's the case, then we have to make it such that when we recover, +148 // null still comes back. But you can't put a null value in a HashMap, so we have to set +149 // the system property rather than the setting. +150 if (oldValue == null) { +151 System.setProperty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, "/yooser/bine/mono"); +152 } else { +153 Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, "/yooser/bine/mono"); +154 } +155 +156 String oldProp = System.getProperty(LOG_KEY, "info"); +157 try { +158 // Tweak the logging to swallow the warning when testing +159 System.setProperty(LOG_KEY, "error"); +160 // Have to make a NEW analyzer because during setUp, it would have gotten the correct one +161 AssemblyAnalyzer aanalyzer = new AssemblyAnalyzer(); +162 aanalyzer.accept(new File("test.dll")); // trick into "thinking it is active" +163 aanalyzer.initialize(); +164 fail("Expected an InitializationException"); +165 } catch (InitializationException ae) { +166 assertEquals("An error occurred with the .NET AssemblyAnalyzer", ae.getMessage()); +167 } finally { +168 System.setProperty(LOG_KEY, oldProp); +169 // Recover the logger +170 // Now recover the way we came in. If we had to set a System property, delete it. Otherwise, +171 // reset the old value +172 if (oldValue == null) { +173 System.getProperties().remove(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH); +174 } else { +175 Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, oldValue); +176 } +177 } +178 } +179 +180 @After +181 public void tearDown() throws Exception { +182 analyzer.close(); +183 } +184 }
    diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/CPEAnalyzerIntegrationTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/CPEAnalyzerIntegrationTest.html index 2f11380ef..c0687c636 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/CPEAnalyzerIntegrationTest.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/CPEAnalyzerIntegrationTest.html @@ -197,84 +197,85 @@ 189 instance.determineCPE(spring); 190 instance.determineCPE(spring3); 191 instance.close(); -192 -193 String expResult = "cpe:/a:apache:struts:2.1.2"; -194 Identifier expIdentifier = new Identifier("cpe", expResult, expResult); -195 String expResultSpring = "cpe:/a:springsource:spring_framework:2.5.5"; -196 String expResultSpring3 = "cpe:/a:vmware:springsource_spring_framework:3.0.0"; -197 -198 for (Identifier i : commonValidator.getIdentifiers()) { -199 Assert.assertFalse("Apache Common Validator - found a CPE identifier?", "cpe".equals(i.getType())); -200 } -201 -202 Assert.assertTrue("Incorrect match size - struts", struts.getIdentifiers().size() >= 1); -203 Assert.assertTrue("Incorrect match - struts", struts.getIdentifiers().contains(expIdentifier)); -204 Assert.assertTrue("Incorrect match size - spring3 - " + spring3.getIdentifiers().size(), spring3.getIdentifiers().size() >= 1); -205 -206 //the following two only work if the HintAnalyzer is used. -207 //Assert.assertTrue("Incorrect match size - spring", spring.getIdentifiers().size() == 1); -208 //Assert.assertTrue("Incorrect match - spring", spring.getIdentifiers().get(0).getValue().equals(expResultSpring)); -209 jarAnalyzer.close(); -210 } -211 -212 /** -213 * Test of determineIdentifiers method, of class CPEAnalyzer. -214 * -215 * @throws Exception is thrown when an exception occurs -216 */ -217 @Test -218 public void testDetermineIdentifiers() throws Exception { -219 Dependency openssl = new Dependency(); -220 openssl.getVendorEvidence().addEvidence("test", "vendor", "openssl", Confidence.HIGHEST); -221 openssl.getProductEvidence().addEvidence("test", "product", "openssl", Confidence.HIGHEST); -222 openssl.getVersionEvidence().addEvidence("test", "version", "1.0.1c", Confidence.HIGHEST); -223 -224 CPEAnalyzer instance = new CPEAnalyzer(); -225 instance.open(); -226 instance.determineIdentifiers(openssl, "openssl", "openssl", Confidence.HIGHEST); -227 instance.close(); -228 -229 String expResult = "cpe:/a:openssl:openssl:1.0.1c"; -230 Identifier expIdentifier = new Identifier("cpe", expResult, expResult); -231 -232 assertTrue(openssl.getIdentifiers().contains(expIdentifier)); -233 -234 } -235 -236 /** -237 * Test of searchCPE method, of class CPEAnalyzer. -238 * -239 * @throws Exception is thrown when an exception occurs -240 */ -241 @Test -242 public void testSearchCPE() throws Exception { -243 String vendor = "apache software foundation"; -244 String product = "struts 2 core"; -245 String version = "2.1.2"; -246 String expVendor = "apache"; -247 String expProduct = "struts"; -248 -249 CPEAnalyzer instance = new CPEAnalyzer(); -250 instance.open(); -251 -252 Set<String> productWeightings = Collections.singleton("struts2"); -253 -254 Set<String> vendorWeightings = Collections.singleton("apache"); -255 -256 List<IndexEntry> result = instance.searchCPE(vendor, product, vendorWeightings, productWeightings); -257 instance.close(); -258 -259 boolean found = false; -260 for (IndexEntry entry : result) { -261 if (expVendor.equals(entry.getVendor()) && expProduct.equals(entry.getProduct())) { -262 found = true; -263 break; -264 } -265 } -266 assertTrue("apache:struts was not identified", found); -267 -268 } -269 } +192 +193 +194 String expResult = "cpe:/a:apache:struts:2.1.2"; +195 Identifier expIdentifier = new Identifier("cpe", expResult, expResult); +196 String expResultSpring = "cpe:/a:springsource:spring_framework:2.5.5"; +197 String expResultSpring3 = "cpe:/a:vmware:springsource_spring_framework:3.0.0"; +198 +199 for (Identifier i : commonValidator.getIdentifiers()) { +200 Assert.assertFalse("Apache Common Validator - found a CPE identifier?", "cpe".equals(i.getType())); +201 } +202 +203 Assert.assertTrue("Incorrect match size - struts", struts.getIdentifiers().size() >= 1); +204 Assert.assertTrue("Incorrect match - struts", struts.getIdentifiers().contains(expIdentifier)); +205 Assert.assertTrue("Incorrect match size - spring3 - " + spring3.getIdentifiers().size(), spring3.getIdentifiers().size() >= 1); +206 +207 //the following two only work if the HintAnalyzer is used. +208 //Assert.assertTrue("Incorrect match size - spring", spring.getIdentifiers().size() == 1); +209 //Assert.assertTrue("Incorrect match - spring", spring.getIdentifiers().get(0).getValue().equals(expResultSpring)); +210 jarAnalyzer.close(); +211 } +212 +213 /** +214 * Test of determineIdentifiers method, of class CPEAnalyzer. +215 * +216 * @throws Exception is thrown when an exception occurs +217 */ +218 @Test +219 public void testDetermineIdentifiers() throws Exception { +220 Dependency openssl = new Dependency(); +221 openssl.getVendorEvidence().addEvidence("test", "vendor", "openssl", Confidence.HIGHEST); +222 openssl.getProductEvidence().addEvidence("test", "product", "openssl", Confidence.HIGHEST); +223 openssl.getVersionEvidence().addEvidence("test", "version", "1.0.1c", Confidence.HIGHEST); +224 +225 CPEAnalyzer instance = new CPEAnalyzer(); +226 instance.open(); +227 instance.determineIdentifiers(openssl, "openssl", "openssl", Confidence.HIGHEST); +228 instance.close(); +229 +230 String expResult = "cpe:/a:openssl:openssl:1.0.1c"; +231 Identifier expIdentifier = new Identifier("cpe", expResult, expResult); +232 +233 assertTrue(openssl.getIdentifiers().contains(expIdentifier)); +234 +235 } +236 +237 /** +238 * Test of searchCPE method, of class CPEAnalyzer. +239 * +240 * @throws Exception is thrown when an exception occurs +241 */ +242 @Test +243 public void testSearchCPE() throws Exception { +244 String vendor = "apache software foundation"; +245 String product = "struts 2 core"; +246 String version = "2.1.2"; +247 String expVendor = "apache"; +248 String expProduct = "struts"; +249 +250 CPEAnalyzer instance = new CPEAnalyzer(); +251 instance.open(); +252 +253 Set<String> productWeightings = Collections.singleton("struts2"); +254 +255 Set<String> vendorWeightings = Collections.singleton("apache"); +256 +257 List<IndexEntry> result = instance.searchCPE(vendor, product, vendorWeightings, productWeightings); +258 instance.close(); +259 +260 boolean found = false; +261 for (IndexEntry entry : result) { +262 if (expVendor.equals(entry.getVendor()) && expProduct.equals(entry.getProduct())) { +263 found = true; +264 break; +265 } +266 } +267 assertTrue("apache:struts was not identified", found); +268 +269 } +270 }
    diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzerTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzerTest.html index 02d2e1b11..b42f4c06f 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzerTest.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzerTest.html @@ -125,118 +125,117 @@ 117 final Engine engine = new Engine(); 118 analyzer.analyze(result, engine); 119 int size = engine.getDependencies().size(); -120 -121 assertTrue(size >= 1); -122 -123 Dependency dependency = engine.getDependencies().get(0); -124 assertTrue(dependency.getProductEvidence().toString().toLowerCase().contains("redcarpet")); -125 assertTrue(dependency.getVersionEvidence().toString().toLowerCase().contains("2.2.2")); -126 assertTrue(dependency.getFilePath().endsWith(resource)); -127 assertTrue(dependency.getFileName().equals("Gemfile.lock")); -128 } catch (Exception e) { -129 LOGGER.warn("Exception setting up RubyBundleAuditAnalyzer. Make sure Ruby gem bundle-audit is installed. You may also need to set property \"analyzer.bundle.audit.path\"."); -130 Assume.assumeNoException("Exception setting up RubyBundleAuditAnalyzer; bundle audit may not be installed, or property \"analyzer.bundle.audit.path\" may not be set.", e); -131 } -132 } -133 -134 /** -135 * Test Ruby addCriticalityToVulnerability -136 */ -137 @Test -138 public void testAddCriticalityToVulnerability() throws AnalysisException, DatabaseException { -139 try { -140 analyzer.initialize(); -141 -142 final Dependency result = new Dependency(BaseTest.getResourceAsFile(this, -143 "ruby/vulnerable/gems/sinatra/Gemfile.lock")); -144 final Engine engine = new Engine(); -145 analyzer.analyze(result, engine); -146 -147 Dependency dependency = engine.getDependencies().get(0); -148 Vulnerability vulnerability = dependency.getVulnerabilities().first(); -149 assertEquals(vulnerability.getCvssScore(), 5.0f, 0.0); -150 -151 } catch (Exception e) { -152 LOGGER.warn("Exception setting up RubyBundleAuditAnalyzer. Make sure Ruby gem bundle-audit is installed. You may also need to set property \"analyzer.bundle.audit.path\"."); -153 Assume.assumeNoException("Exception setting up RubyBundleAuditAnalyzer; bundle audit may not be installed, or property \"analyzer.bundle.audit.path\" may not be set.", e); -154 } -155 } -156 -157 /** -158 * Test when Ruby bundle-audit is not available on the system. -159 * -160 * @throws AnalysisException is thrown when an exception occurs. -161 */ -162 @Test -163 public void testMissingBundleAudit() throws AnalysisException, DatabaseException { -164 //set a non-exist bundle-audit -165 Settings.setString(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH, "phantom-bundle-audit"); -166 try { -167 //initialize should fail. -168 analyzer.initialize(); -169 } catch (Exception e) { -170 //expected, so ignore. -171 } finally { -172 assertThat(analyzer.isEnabled(), is(false)); -173 LOGGER.info("phantom-bundle-audit is not available. Ruby Bundle Audit Analyzer is disabled as expected."); -174 } -175 } -176 -177 /** -178 * Test Ruby dependencies and their paths. -179 * -180 * @throws AnalysisException is thrown when an exception occurs. -181 * @throws DatabaseException thrown when an exception occurs -182 */ -183 @Test -184 public void testDependenciesPath() throws AnalysisException, DatabaseException { -185 final Engine engine = new Engine(); -186 engine.scan(BaseTest.getResourceAsFile(this, -187 "ruby/vulnerable/gems/rails-4.1.15/")); -188 try { -189 engine.analyzeDependencies(); -190 } catch (NullPointerException ex) { -191 LOGGER.error("NPE", ex); -192 throw ex; -193 } catch (ExceptionCollection ex) { -194 Assume.assumeNoException("Exception setting up RubyBundleAuditAnalyzer; bundle audit may not be installed, or property \"analyzer.bundle.audit.path\" may not be set.", ex); -195 } -196 List<Dependency> dependencies = engine.getDependencies(); -197 LOGGER.info(dependencies.size() + " dependencies found."); -198 Iterator<Dependency> dIterator = dependencies.iterator(); -199 while (dIterator.hasNext()) { -200 Dependency dept = dIterator.next(); -201 LOGGER.info("dept path: " + dept.getActualFilePath()); -202 -203 Set<Identifier> identifiers = dept.getIdentifiers(); -204 Iterator<Identifier> idIterator = identifiers.iterator(); -205 while (idIterator.hasNext()) { -206 Identifier id = idIterator.next(); -207 LOGGER.info(" Identifier: " + id.getValue() + ", type=" + id.getType() + ", url=" + id.getUrl() + ", conf=" + id.getConfidence()); -208 } -209 -210 Set<Evidence> prodEv = dept.getProductEvidence().getEvidence(); -211 Iterator<Evidence> it = prodEv.iterator(); -212 while (it.hasNext()) { -213 Evidence e = it.next(); -214 LOGGER.info(" prod: name=" + e.getName() + ", value=" + e.getValue() + ", source=" + e.getSource() + ", confidence=" + e.getConfidence()); -215 } -216 Set<Evidence> versionEv = dept.getVersionEvidence().getEvidence(); -217 Iterator<Evidence> vIt = versionEv.iterator(); -218 while (vIt.hasNext()) { -219 Evidence e = vIt.next(); -220 LOGGER.info(" version: name=" + e.getName() + ", value=" + e.getValue() + ", source=" + e.getSource() + ", confidence=" + e.getConfidence()); -221 } -222 -223 Set<Evidence> vendorEv = dept.getVendorEvidence().getEvidence(); -224 Iterator<Evidence> vendorIt = vendorEv.iterator(); -225 while (vendorIt.hasNext()) { -226 Evidence e = vendorIt.next(); -227 LOGGER.info(" vendor: name=" + e.getName() + ", value=" + e.getValue() + ", source=" + e.getSource() + ", confidence=" + e.getConfidence()); -228 } -229 } -230 } -231 } +120 assertTrue(size >= 1); +121 +122 Dependency dependency = engine.getDependencies().get(0); +123 assertTrue(dependency.getProductEvidence().toString().toLowerCase().contains("redcarpet")); +124 assertTrue(dependency.getVersionEvidence().toString().toLowerCase().contains("2.2.2")); +125 assertTrue(dependency.getFilePath().endsWith(resource)); +126 assertTrue(dependency.getFileName().equals("Gemfile.lock")); +127 } catch (Exception e) { +128 LOGGER.warn("Exception setting up RubyBundleAuditAnalyzer. Make sure Ruby gem bundle-audit is installed. You may also need to set property \"analyzer.bundle.audit.path\"."); +129 Assume.assumeNoException("Exception setting up RubyBundleAuditAnalyzer; bundle audit may not be installed, or property \"analyzer.bundle.audit.path\" may not be set.", e); +130 } +131 } +132 +133 /** +134 * Test Ruby addCriticalityToVulnerability +135 */ +136 @Test +137 public void testAddCriticalityToVulnerability() throws AnalysisException, DatabaseException { +138 try { +139 analyzer.initialize(); +140 +141 final Dependency result = new Dependency(BaseTest.getResourceAsFile(this, +142 "ruby/vulnerable/gems/sinatra/Gemfile.lock")); +143 final Engine engine = new Engine(); +144 analyzer.analyze(result, engine); +145 +146 Dependency dependency = engine.getDependencies().get(0); +147 Vulnerability vulnerability = dependency.getVulnerabilities().first(); +148 assertEquals(vulnerability.getCvssScore(), 5.0f, 0.0); +149 +150 } catch (Exception e) { +151 LOGGER.warn("Exception setting up RubyBundleAuditAnalyzer. Make sure Ruby gem bundle-audit is installed. You may also need to set property \"analyzer.bundle.audit.path\"."); +152 Assume.assumeNoException("Exception setting up RubyBundleAuditAnalyzer; bundle audit may not be installed, or property \"analyzer.bundle.audit.path\" may not be set.", e); +153 } +154 } +155 +156 /** +157 * Test when Ruby bundle-audit is not available on the system. +158 * +159 * @throws AnalysisException is thrown when an exception occurs. +160 */ +161 @Test +162 public void testMissingBundleAudit() throws AnalysisException, DatabaseException { +163 //set a non-exist bundle-audit +164 Settings.setString(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH, "phantom-bundle-audit"); +165 try { +166 //initialize should fail. +167 analyzer.initialize(); +168 } catch (Exception e) { +169 //expected, so ignore. +170 } finally { +171 assertThat(analyzer.isEnabled(), is(false)); +172 LOGGER.info("phantom-bundle-audit is not available. Ruby Bundle Audit Analyzer is disabled as expected."); +173 } +174 } +175 +176 /** +177 * Test Ruby dependencies and their paths. +178 * +179 * @throws AnalysisException is thrown when an exception occurs. +180 * @throws DatabaseException thrown when an exception occurs +181 */ +182 @Test +183 public void testDependenciesPath() throws AnalysisException, DatabaseException { +184 final Engine engine = new Engine(); +185 engine.scan(BaseTest.getResourceAsFile(this, +186 "ruby/vulnerable/gems/rails-4.1.15/")); +187 try { +188 engine.analyzeDependencies(); +189 } catch (NullPointerException ex) { +190 LOGGER.error("NPE", ex); +191 throw ex; +192 } catch (ExceptionCollection ex) { +193 Assume.assumeNoException("Exception setting up RubyBundleAuditAnalyzer; bundle audit may not be installed, or property \"analyzer.bundle.audit.path\" may not be set.", ex); +194 } +195 List<Dependency> dependencies = engine.getDependencies(); +196 LOGGER.info(dependencies.size() + " dependencies found."); +197 Iterator<Dependency> dIterator = dependencies.iterator(); +198 while (dIterator.hasNext()) { +199 Dependency dept = dIterator.next(); +200 LOGGER.info("dept path: " + dept.getActualFilePath()); +201 +202 Set<Identifier> identifiers = dept.getIdentifiers(); +203 Iterator<Identifier> idIterator = identifiers.iterator(); +204 while (idIterator.hasNext()) { +205 Identifier id = idIterator.next(); +206 LOGGER.info(" Identifier: " + id.getValue() + ", type=" + id.getType() + ", url=" + id.getUrl() + ", conf=" + id.getConfidence()); +207 } +208 +209 Set<Evidence> prodEv = dept.getProductEvidence().getEvidence(); +210 Iterator<Evidence> it = prodEv.iterator(); +211 while (it.hasNext()) { +212 Evidence e = it.next(); +213 LOGGER.info(" prod: name=" + e.getName() + ", value=" + e.getValue() + ", source=" + e.getSource() + ", confidence=" + e.getConfidence()); +214 } +215 Set<Evidence> versionEv = dept.getVersionEvidence().getEvidence(); +216 Iterator<Evidence> vIt = versionEv.iterator(); +217 while (vIt.hasNext()) { +218 Evidence e = vIt.next(); +219 LOGGER.info(" version: name=" + e.getName() + ", value=" + e.getValue() + ", source=" + e.getSource() + ", confidence=" + e.getConfidence()); +220 } +221 +222 Set<Evidence> vendorEv = dept.getVendorEvidence().getEvidence(); +223 Iterator<Evidence> vendorIt = vendorEv.iterator(); +224 while (vendorIt.hasNext()) { +225 Evidence e = vendorIt.next(); +226 LOGGER.info(" vendor: name=" + e.getName() + ", value=" + e.getValue() + ", source=" + e.getSource() + ", confidence=" + e.getConfidence()); +227 } +228 } +229 } +230 }
    diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/SwiftAnalyzersTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/SwiftAnalyzersTest.html new file mode 100644 index 000000000..5dc465095 --- /dev/null +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/SwiftAnalyzersTest.html @@ -0,0 +1,136 @@ + + + +SwiftAnalyzersTest xref + + + +
    +1   package org.owasp.dependencycheck.analyzer;
    +2   
    +3   import org.junit.After;
    +4   import org.junit.Before;
    +5   import org.junit.Test;
    +6   import org.owasp.dependencycheck.BaseTest;
    +7   import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
    +8   import org.owasp.dependencycheck.dependency.Dependency;
    +9   
    +10  import static org.hamcrest.CoreMatchers.containsString;
    +11  import static org.hamcrest.CoreMatchers.is;
    +12  import static org.junit.Assert.assertThat;
    +13  
    +14  import java.io.File;
    +15  
    +16  /**
    +17   * Unit tests for CocoaPodsAnalyzer.
    +18   *
    +19   * @author Bianca Jiang
    +20   */
    +21  public class SwiftAnalyzersTest extends BaseTest {
    +22  
    +23      /**
    +24       * The analyzer to test.
    +25       */
    +26  	CocoaPodsAnalyzer podsAnalyzer;
    +27  	SwiftPackageManagerAnalyzer spmAnalyzer;
    +28  
    +29      /**
    +30       * Correctly setup the analyzer for testing.
    +31       *
    +32       * @throws Exception thrown if there is a problem
    +33       */
    +34      @Before
    +35      public void setUp() throws Exception {
    +36          podsAnalyzer = new CocoaPodsAnalyzer();
    +37          podsAnalyzer.setFilesMatched(true);
    +38          podsAnalyzer.initialize();
    +39          
    +40          spmAnalyzer = new SwiftPackageManagerAnalyzer();
    +41          spmAnalyzer.setFilesMatched(true);
    +42          spmAnalyzer.initialize();
    +43      }
    +44  
    +45      /**
    +46       * Cleanup the analyzer's temp files, etc.
    +47       *
    +48       * @throws Exception thrown if there is a problem
    +49       */
    +50      @After
    +51      public void tearDown() throws Exception {
    +52          podsAnalyzer.close();
    +53          podsAnalyzer = null;
    +54  
    +55          spmAnalyzer.close();
    +56          spmAnalyzer = null;
    +57      }
    +58  
    +59      /**
    +60       * Test of getName method, of class CocoaPodsAnalyzer.
    +61       */
    +62      @Test
    +63      public void testPodsGetName() {
    +64          assertThat(podsAnalyzer.getName(), is("CocoaPods Package Analyzer"));
    +65      }
    +66  
    +67      /**
    +68       * Test of getName method, of class SwiftPackageManagerAnalyzer.
    +69       */
    +70      @Test
    +71      public void testSPMGetName() {
    +72          assertThat(spmAnalyzer.getName(), is("SWIFT Package Manager Analyzer"));
    +73      }
    +74  
    +75      /**
    +76       * Test of supportsFiles method, of class CocoaPodsAnalyzer.
    +77       */
    +78      @Test
    +79      public void testPodsSupportsFiles() {
    +80          assertThat(podsAnalyzer.accept(new File("test.podspec")), is(true));
    +81      }
    +82  
    +83      /**
    +84       * Test of supportsFiles method, of class SwiftPackageManagerAnalyzer.
    +85       */
    +86      @Test
    +87      public void testSPMSupportsFiles() {
    +88          assertThat(spmAnalyzer.accept(new File("Package.swift")), is(true));
    +89      }
    +90      
    +91      /**
    +92       * Test of analyze method, of class CocoaPodsAnalyzer.
    +93       *
    +94       * @throws AnalysisException is thrown when an exception occurs.
    +95       */
    +96      @Test
    +97      public void testCocoaPodsAnalyzer() throws AnalysisException {
    +98          final Dependency result = new Dependency(BaseTest.getResourceAsFile(this,
    +99                  "swift/cocoapods/EasyPeasy.podspec"));
    +100         podsAnalyzer.analyze(result, null);
    +101         final String vendorString = result.getVendorEvidence().toString();
    +102         
    +103         assertThat(vendorString, containsString("Carlos Vidal"));
    +104         assertThat(vendorString, containsString("https://github.com/nakiostudio/EasyPeasy"));
    +105         assertThat(vendorString, containsString("MIT"));
    +106         assertThat(result.getProductEvidence().toString(), containsString("EasyPeasy"));
    +107         assertThat(result.getVersionEvidence().toString(), containsString("0.2.3"));
    +108     }
    +109 
    +110     /**
    +111      * Test of analyze method, of class SwiftPackageManagerAnalyzer.
    +112      *
    +113      * @throws AnalysisException is thrown when an exception occurs.
    +114      */
    +115     @Test
    +116     public void testSPMAnalyzer() throws AnalysisException {
    +117         final Dependency result = new Dependency(BaseTest.getResourceAsFile(this,
    +118                 "swift/Gloss/Package.swift"));
    +119         spmAnalyzer.analyze(result, null);
    +120 
    +121         assertThat(result.getProductEvidence().toString(), containsString("Gloss"));
    +122     }
    +123 }
    +
    +
    + + + 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 2aae2817a..9a3476fc4 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.2 Reference Package org.owasp.dependencycheck.analyzer + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.analyzer @@ -89,6 +89,9 @@
  • RubyGemspecAnalyzerTest +
  • +
  • + SwiftAnalyzersTest
  • VulnerabilitySuppressionAnalyzerIntegrationTest 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 e7d14168a..71e087843 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.2 Reference Package org.owasp.dependencycheck.analyzer + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.analyzer @@ -159,6 +159,11 @@
  • + + + - - - - + @@ -100,1885 +100,2096 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + + - + - + - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - - + + + - + - + - + - + - - - - - - + + + + + + - - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - + - + - + - + - + - - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + + - + - - - - + + + + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - + + + + + + + + + + + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - - + + + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + - + - + - + - + - + - + - + - + - + - + - - + + + - + - + - + - + - - + + + - + - + - + - + - - - - - - - - - - + + + + + + + + + + + + + - - + - + - + - + - + - + - + - + - + - + - + - + - - - + + - + - + - + - + - - - + + - + - + - + - + - - - + + - + - + - + - + - - - - - - + + + + + - - - - - - + + + + + + - + - + - + - + + - + - + - + - + - + - + - + + + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + + + + - - - - + + + + + + + - - + + + - - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - + - + - + - + - + - + - - - - - - + + + + + - - - + + - - - + + - + - + - + - - + + + - - - - - - + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + - - - + + - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + - + - + - + - - - + + + + + - - - - - - + + + + + + + + + + - - - + + + + + - - + + + - + - + - - - - - - - + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + + + - + - + - + - + - + - + - + - - + + + - + - + - + - + - + - + - + - - + + + - + - + - - - - - - - - - - - - - + + + + + + + - - - + + - + - + + + - + - + - + - + - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + - - - - - - - - - + + + + + + - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - + + + + + + + + + + + + + + + - + + + + + + + + - + - + - - - - - + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + - + - - - - - - + + + + - - - - - - - - + + + + - + - - + + + - + - + - + - + - - - - - + + + - + - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - + + + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - - - + + - - + + + - + - + - + - + - + - + - + - + - - - - + + + - - - - - - - - - - - - - + + + + + + + - + - - - - - + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + - - - + + - - - - - - - + + + + - - - - - - - - + + + + + + - - - - - - - - - - - - - - - - - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    org.owasp.dependencycheck.analyzer.ArchiveAnalyzer- 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
    org.owasp.dependencycheck.analyzer.AssemblyAnalyzerLine
    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
    org.owasp.dependencycheck.analyzer.CMakeAnalyzer Line
    - refactor so we do not assign to the parameter (checkstyle)217
    220
    org.owasp.dependencycheck.analyzer.CPEAnalyzer Line
    test dojo-war against this. we shold get dojo-toolkit:dojo-toolkit AND dojo-toolkit:toolkit198
    199
    - 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.449
    450
    - likely need to change the split... not sure if this will work for CPE with special chars467
    468
    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.552
    553
    the following isn't quite right is it? need to think about this guessing game a bit more.578
    579
    org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzerTest Line
    Line
    remove weighting614
    619
    change this to a regex? 726
    75
    other checking?223
    226
    org.owasp.dependencycheck.analyzer.RubyGemspecAnalyzerTest Line
    add verification 114
    org.owasp.dependencycheck.data.cpe.CpeMemoryIndexLine
    figure out why there are null products212
    org.owasp.dependencycheck.data.nvdcve.ConnectionFactory Line
    convert this to use DatabaseProperties357
    372
    org.owasp.dependencycheck.data.update.CpeUpdater Line
    - move this to a util class as it is duplicative of (copy of) code in the DownloadTask 157
    org.owasp.dependencycheck.data.update.NvdCveUpdaterIntegrationTestLine
    make this an actual test }47
    org.owasp.dependencycheck.dependency.EvidenceCollection Line
    RubyGemspecAnalyzerTest
    + SwiftAnalyzersTest +
    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 153863233..fed1488d5 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.2 Reference Package org.owasp.dependencycheck.data.central + Dependency-Check Core 1.4.3 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 0c975aa84..53d4a8081 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.2 Reference Package org.owasp.dependencycheck.data.central + Dependency-Check Core 1.4.3 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 7d0ed4d35..ac762f573 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.2 Reference Package org.owasp.dependencycheck.data.composer + Dependency-Check Core 1.4.3 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 eb833f352..647d277b8 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.2 Reference Package org.owasp.dependencycheck.data.composer + Dependency-Check Core 1.4.3 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 99c73871c..60b71a47b 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.2 Reference Package org.owasp.dependencycheck.data.cpe + Dependency-Check Core 1.4.3 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 9922b9c7b..50a570359 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.2 Reference Package org.owasp.dependencycheck.data.cpe + Dependency-Check Core 1.4.3 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 345a05414..2d6a6718b 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.2 Reference Package org.owasp.dependencycheck.data.cwe + Dependency-Check Core 1.4.3 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 cd3df348a..29407e190 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.2 Reference Package org.owasp.dependencycheck.data.cwe + Dependency-Check Core 1.4.3 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 e8868aa26..344e73d10 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.2 Reference Package org.owasp.dependencycheck.data.lucene + Dependency-Check Core 1.4.3 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 22d61f710..8a992b644 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.2 Reference Package org.owasp.dependencycheck.data.lucene + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.lucene 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 f37318529..02f59cec6 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.2 Reference Package org.owasp.dependencycheck.data.nexus + Dependency-Check Core 1.4.3 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 bc64db70e..9e4b312ba 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.2 Reference Package org.owasp.dependencycheck.data.nexus + Dependency-Check Core 1.4.3 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 51eed6cf6..66257befa 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.2 Reference Package org.owasp.dependencycheck.data.nuget + Dependency-Check Core 1.4.3 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 962f3cd60..3fbfb5760 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.2 Reference Package org.owasp.dependencycheck.data.nuget + Dependency-Check Core 1.4.3 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 41e54f75a..328555170 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.2 Reference Package org.owasp.dependencycheck.data.nvdcve + Dependency-Check Core 1.4.3 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 a746453f5..b8790d31b 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.2 Reference Package org.owasp.dependencycheck.data.nvdcve + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.nvdcve diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/update/NvdCveUpdaterIntegrationTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/update/NvdCveUpdaterIntegrationTest.html index 2bd3a4681..f2118830d 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/update/NvdCveUpdaterIntegrationTest.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/update/NvdCveUpdaterIntegrationTest.html @@ -37,7 +37,7 @@ 29 * 30 * @author Jeremy Long 31 */ -32 public class NvdCveUpdaterIntegrationTest extends BaseTest { +32 public class NvdCveUpdaterIntegrationTest extends BaseTest { 33 34 public NvdCveUpdater getUpdater() throws MalformedURLException, DownloadFailedException, UpdateException { 35 NvdCveUpdater instance = new NvdCveUpdater(); @@ -48,27 +48,26 @@ 40 // /** 41 // * Test of update method, of class StandardUpdate. 42 // */ -43 // @Test -44 // public void testUpdate() throws Exception { -45 // StandardUpdate instance = getStandardUpdateTask(); -46 // instance.update(); -47 // //TODO make this an actual test -48 // } -49 /** -50 * Test of updatesNeeded method, of class StandardUpdate. -51 */ -52 @Test -53 public void testUpdatesNeeded() throws Exception { -54 NvdCveUpdater instance = getUpdater(); -55 try { -56 instance.openDataStores(); -57 UpdateableNvdCve result = instance.getUpdatesNeeded(); -58 assertNotNull(result); -59 } finally { -60 instance.closeDataStores(); -61 } -62 } -63 } +43 @Test +44 public void testUpdate() throws Exception { +45 NvdCveUpdater instance = getUpdater(); +46 instance.update(); +47 } +48 /** +49 * Test of updatesNeeded method, of class StandardUpdate. +50 */ +51 @Test +52 public void testUpdatesNeeded() throws Exception { +53 NvdCveUpdater instance = getUpdater(); +54 try { +55 instance.openDataStores(); +56 UpdateableNvdCve result = instance.getUpdatesNeeded(); +57 assertNotNull(result); +58 } finally { +59 instance.closeDataStores(); +60 } +61 } +62 }
    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 2d0641a0c..ee732556a 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.2 Reference Package org.owasp.dependencycheck.data.update.nvd + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.update.nvd @@ -20,9 +20,6 @@
  • NvdCveInfoTest -
  • -
  • - NvdCveUpdaterIntegrationTest
  • NvdCve_1_2_HandlerTest 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 7ba1e7d85..dd3307e96 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.2 Reference Package org.owasp.dependencycheck.data.update.nvd + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.update.nvd @@ -44,11 +44,6 @@
  • NvdCveInfoTest
    - NvdCveUpdaterIntegrationTest -
    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 b5664a2a5..070bd9485 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.2 Reference Package org.owasp.dependencycheck.data.update + Dependency-Check Core 1.4.3 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 946ef7ac4..5c26f559e 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.2 Reference Package org.owasp.dependencycheck.data.update + Dependency-Check Core 1.4.3 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 3a67080c2..bca7a96ca 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.2 Reference Package org.owasp.dependencycheck.dependency + Dependency-Check Core 1.4.3 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 c7f69de41..0f8dbd4b1 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.2 Reference Package org.owasp.dependencycheck.dependency + Dependency-Check Core 1.4.3 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 26625084b..f09f21625 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.2 Reference Package org.owasp.dependencycheck + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck 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 b8b8c63c0..7ee87d3e7 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.2 Reference Package org.owasp.dependencycheck + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck 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 2347b4ca1..bfe2a7523 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.2 Reference Package org.owasp.dependencycheck.reporting + Dependency-Check Core 1.4.3 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 725df7315..5c3817787 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.2 Reference Package org.owasp.dependencycheck.reporting + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.reporting 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 7e9e98b17..5ad5102dc 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.2 Reference Package org.owasp.dependencycheck.utils + Dependency-Check Core 1.4.3 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 eb7292890..8884a7097 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.2 Reference Package org.owasp.dependencycheck.utils + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.utils diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/hints/HintHandlerTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/hints/HintHandlerTest.html index 24a30c1b7..eb87a5d9a 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/hints/HintHandlerTest.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/hints/HintHandlerTest.html @@ -60,7 +60,7 @@ 52 @Test 53 public void testHandler() throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException, SAXException, FileNotFoundException, UnsupportedEncodingException, IOException { 54 File file = BaseTest.getResourceAsFile(this, "hints.xml"); -55 File schema = BaseTest.getResourceAsFile(this, "schema/dependency-hint.1.0.xsd"); +55 File schema = BaseTest.getResourceAsFile(this, "schema/dependency-hint.1.1.xsd"); 56 HintHandler handler = new HintHandler(); 57 58 SAXParserFactory factory = SAXParserFactory.newInstance(); 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 ff24e93a1..0cdebc918 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.2 Reference Package org.owasp.dependencycheck.xml.hints + Dependency-Check Core 1.4.3 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 f5abc0d96..e818d33bf 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.2 Reference Package org.owasp.dependencycheck.xml.hints + Dependency-Check Core 1.4.3 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 cdc21cc41..7965e7f28 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.2 Reference Package org.owasp.dependencycheck.xml.pom + Dependency-Check Core 1.4.3 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 635690fc9..018ec9d8c 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.2 Reference Package org.owasp.dependencycheck.xml.pom + Dependency-Check Core 1.4.3 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 2fad43252..5ef0c33b5 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.2 Reference Package org.owasp.dependencycheck.xml.suppression + Dependency-Check Core 1.4.3 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 c42af6355..fcf079aee 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.2 Reference Package org.owasp.dependencycheck.xml.suppression + Dependency-Check Core 1.4.3 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 7763a64e9..65b25635e 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.2 Reference + Dependency-Check Core 1.4.3 Reference diff --git a/dependency-check-core/xref-test/overview-summary.html b/dependency-check-core/xref-test/overview-summary.html index cf3bc72e7..e688ce64b 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.2 Reference + Dependency-Check Core 1.4.3 Reference @@ -24,7 +24,7 @@ -

    Dependency-Check Core 1.4.2 Reference

    +

    Dependency-Check Core 1.4.3 Reference

    diff --git a/dependency-check-core/xref/allclasses-frame.html b/dependency-check-core/xref/allclasses-frame.html index ae6b3291d..013dbcdc5 100644 --- a/dependency-check-core/xref/allclasses-frame.html +++ b/dependency-check-core/xref/allclasses-frame.html @@ -73,6 +73,9 @@
  • ClassNameInformation +
  • +
  • + CocoaPodsAnalyzer
  • ComposerDependency @@ -379,6 +382,9 @@
  • SuppressionRule +
  • +
  • + SwiftPackageManagerAnalyzer
  • TokenPairConcatenatingFilter diff --git a/dependency-check-core/xref/index.html b/dependency-check-core/xref/index.html index 49f52c91f..415806e7b 100644 --- a/dependency-check-core/xref/index.html +++ b/dependency-check-core/xref/index.html @@ -4,7 +4,7 @@ - Dependency-Check Core 1.4.2 Reference + Dependency-Check Core 1.4.3 Reference diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/Engine.html b/dependency-check-core/xref/org/owasp/dependencycheck/Engine.html index 3f0c2ae7e..e4cd6cf99 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/Engine.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/Engine.html @@ -376,7 +376,7 @@ 368 } 369 370 LOGGER.debug("\n----------------------------------------------------\nBEGIN ANALYSIS\n----------------------------------------------------"); -371 LOGGER.info("Analysis Starting"); +371 LOGGER.info("Analysis Started"); 372 final long analysisStart = System.currentTimeMillis(); 373 374 // analysis phases 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 84cb20b59..9a2c6afe5 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.2 Reference Package org.owasp.dependencycheck.agent + Dependency-Check Core 1.4.3 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 054104309..cf61e872d 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.2 Reference Package org.owasp.dependencycheck.agent + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.agent 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 0e9f20d3b..dff6d6872 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.html @@ -138,56 +138,67 @@ 130 } 131 } else { 132 file = new File(suppressionFilePath); -133 if (!file.exists()) { -134 final InputStream suppressionsFromClasspath = this.getClass().getClassLoader().getResourceAsStream(suppressionFilePath); -135 if (suppressionsFromClasspath != null) { -136 deleteTempFile = true; -137 file = FileUtils.getTempFile("suppression", "xml"); -138 try { -139 org.apache.commons.io.FileUtils.copyInputStreamToFile(suppressionsFromClasspath, file); -140 } catch (IOException ex) { -141 throwSuppressionParseException("Unable to locate suppressions file in classpath", ex); -142 } -143 } -144 } -145 } -146 if (file != null) { -147 try { -148 rules.addAll(parser.parseSuppressionRules(file)); -149 LOGGER.debug("{} suppression rules were loaded.", rules.size()); -150 } catch (SuppressionParseException ex) { -151 LOGGER.warn("Unable to parse suppression xml file '{}'", file.getPath()); -152 LOGGER.warn(ex.getMessage()); -153 throw ex; -154 } -155 } -156 } catch (DownloadFailedException ex) { -157 throwSuppressionParseException("Unable to fetch the configured suppression file", ex); -158 } catch (MalformedURLException ex) { -159 throwSuppressionParseException("Configured suppression file has an invalid URL", ex); -160 } catch (IOException ex) { -161 throwSuppressionParseException("Unable to create temp file for suppressions", ex); -162 } finally { -163 if (deleteTempFile && file != null) { -164 FileUtils.delete(file); -165 } -166 } -167 } -168 -169 /** -170 * Utility method to throw parse exceptions. -171 * -172 * @param message the exception message -173 * @param exception the cause of the exception -174 * @throws SuppressionParseException throws the generated -175 * SuppressionParseException -176 */ -177 private void throwSuppressionParseException(String message, Exception exception) throws SuppressionParseException { -178 LOGGER.warn(message); -179 LOGGER.debug("", exception); -180 throw new SuppressionParseException(message, exception); -181 } -182 } +133 InputStream suppressionsFromClasspath = null; +134 if (!file.exists()) { +135 try { +136 suppressionsFromClasspath = this.getClass().getClassLoader().getResourceAsStream(suppressionFilePath); +137 if (suppressionsFromClasspath != null) { +138 deleteTempFile = true; +139 file = FileUtils.getTempFile("suppression", "xml"); +140 try { +141 org.apache.commons.io.FileUtils.copyInputStreamToFile(suppressionsFromClasspath, file); +142 } catch (IOException ex) { +143 throwSuppressionParseException("Unable to locate suppressions file in classpath", ex); +144 } +145 } +146 } finally { +147 if (suppressionsFromClasspath != null) { +148 try { +149 suppressionsFromClasspath.close(); +150 } catch (IOException ex) { +151 LOGGER.debug("Failed to close stream", ex); +152 } +153 } +154 } +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 }
    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 357c4dac7..101341061 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.html @@ -365,230 +365,238 @@ 357 */ 358 private void extractFiles(File archive, File destination, Engine engine) throws AnalysisException { 359 if (archive != null && destination != null) { -360 FileInputStream fis; -361 try { -362 fis = new FileInputStream(archive); -363 } catch (FileNotFoundException ex) { -364 LOGGER.debug("", ex); -365 throw new AnalysisException("Archive file was not found.", ex); -366 } -367 final String archiveExt = FileUtils.getFileExtension(archive.getName()).toLowerCase(); -368 try { -369 if (ZIPPABLES.contains(archiveExt)) { -370 final BufferedInputStream in = new BufferedInputStream(fis); -371 ensureReadableJar(archiveExt, in); -372 extractArchive(new ZipArchiveInputStream(in), destination, engine); -373 } else if ("tar".equals(archiveExt)) { -374 extractArchive(new TarArchiveInputStream(new BufferedInputStream(fis)), destination, engine); -375 } else if ("gz".equals(archiveExt) || "tgz".equals(archiveExt)) { -376 final String uncompressedName = GzipUtils.getUncompressedFilename(archive.getName()); -377 final File f = new File(destination, uncompressedName); -378 if (engine.accept(f)) { -379 decompressFile(new GzipCompressorInputStream(new BufferedInputStream(fis)), f); -380 } -381 } else if ("bz2".equals(archiveExt) || "tbz2".equals(archiveExt)) { -382 final String uncompressedName = BZip2Utils.getUncompressedFilename(archive.getName()); -383 final File f = new File(destination, uncompressedName); -384 if (engine.accept(f)) { -385 decompressFile(new BZip2CompressorInputStream(new BufferedInputStream(fis)), f); -386 } -387 } -388 } catch (ArchiveExtractionException ex) { -389 LOGGER.warn("Exception extracting archive '{}'.", archive.getName()); -390 LOGGER.debug("", ex); -391 } catch (IOException ex) { -392 LOGGER.warn("Exception reading archive '{}'.", archive.getName()); -393 LOGGER.debug("", ex); -394 } finally { -395 close(fis); -396 } -397 } -398 } -399 -400 /** -401 * Checks if the file being scanned is a JAR that begins with '#!/bin' which -402 * indicates it is a fully executable jar. If a fully executable JAR is -403 * identified the input stream will be advanced to the start of the actual -404 * JAR file ( skipping the script). -405 * -406 * @see -407 * <a href="http://docs.spring.io/spring-boot/docs/1.3.0.BUILD-SNAPSHOT/reference/htmlsingle/#deployment-install">Installing -408 * Spring Boot Applications</a> -409 * @param archiveExt the file extension -410 * @param in the input stream -411 * @throws IOException thrown if there is an error reading the stream -412 */ -413 private void ensureReadableJar(final String archiveExt, BufferedInputStream in) throws IOException { -414 if ("jar".equals(archiveExt) && in.markSupported()) { -415 in.mark(7); -416 final byte[] b = new byte[7]; -417 in.read(b); -418 if (b[0] == '#' -419 && b[1] == '!' -420 && b[2] == '/' -421 && b[3] == 'b' -422 && b[4] == 'i' -423 && b[5] == 'n' -424 && b[6] == '/') { -425 boolean stillLooking = true; -426 int chr, nxtChr; -427 while (stillLooking && (chr = in.read()) != -1) { -428 if (chr == '\n' || chr == '\r') { -429 in.mark(4); -430 if ((chr = in.read()) != -1) { -431 if (chr == 'P' && (chr = in.read()) != -1) { -432 if (chr == 'K' && (chr = in.read()) != -1) { -433 if ((chr == 3 || chr == 5 || chr == 7) && (nxtChr = in.read()) != -1) { -434 if (nxtChr == chr + 1) { -435 stillLooking = false; -436 in.reset(); -437 } -438 } -439 } -440 } -441 } -442 } -443 } -444 } -445 } -446 } -447 -448 /** -449 * Extracts files from an archive. -450 * -451 * @param input the archive to extract files from -452 * @param destination the location to write the files too -453 * @param engine the dependency-check engine -454 * @throws ArchiveExtractionException thrown if there is an exception -455 * extracting files from the archive -456 */ -457 private void extractArchive(ArchiveInputStream input, File destination, Engine engine) throws ArchiveExtractionException { -458 ArchiveEntry entry; -459 try { -460 while ((entry = input.getNextEntry()) != null) { -461 final File file = new File(destination, entry.getName()); -462 if (entry.isDirectory()) { -463 if (!file.exists() && !file.mkdirs()) { -464 final String msg = String.format("Unable to create directory '%s'.", file.getAbsolutePath()); -465 throw new AnalysisException(msg); -466 } -467 } else if (engine.accept(file)) { -468 extractAcceptedFile(input, file); -469 } -470 } -471 } catch (Throwable ex) { -472 throw new ArchiveExtractionException(ex); -473 } finally { -474 close(input); -475 } -476 } -477 -478 /** -479 * Extracts a file from an archive. -480 * -481 * @param input the archives input stream -482 * @param file the file to extract -483 * @throws AnalysisException thrown if there is an error -484 */ -485 private static void extractAcceptedFile(ArchiveInputStream input, File file) throws AnalysisException { -486 LOGGER.debug("Extracting '{}'", file.getPath()); -487 FileOutputStream fos = null; -488 try { -489 final File parent = file.getParentFile(); -490 if (!parent.isDirectory() && !parent.mkdirs()) { -491 final String msg = String.format("Unable to build directory '%s'.", parent.getAbsolutePath()); -492 throw new AnalysisException(msg); -493 } -494 fos = new FileOutputStream(file); -495 IOUtils.copy(input, fos); -496 } catch (FileNotFoundException ex) { -497 LOGGER.debug("", ex); -498 final String msg = String.format("Unable to find file '%s'.", file.getName()); -499 throw new AnalysisException(msg, ex); -500 } catch (IOException ex) { -501 LOGGER.debug("", ex); -502 final String msg = String.format("IO Exception while parsing file '%s'.", file.getName()); -503 throw new AnalysisException(msg, ex); -504 } finally { -505 close(fos); -506 } -507 } -508 -509 /** -510 * Decompresses a file. -511 * -512 * @param inputStream the compressed file -513 * @param outputFile the location to write the decompressed file -514 * @throws ArchiveExtractionException thrown if there is an exception -515 * decompressing the file -516 */ -517 private void decompressFile(CompressorInputStream inputStream, File outputFile) throws ArchiveExtractionException { -518 LOGGER.debug("Decompressing '{}'", outputFile.getPath()); -519 FileOutputStream out = null; -520 try { -521 out = new FileOutputStream(outputFile); -522 IOUtils.copy(inputStream, out); -523 } catch (FileNotFoundException ex) { -524 LOGGER.debug("", ex); -525 throw new ArchiveExtractionException(ex); -526 } catch (IOException ex) { -527 LOGGER.debug("", ex); -528 throw new ArchiveExtractionException(ex); -529 } finally { -530 close(out); -531 } -532 } -533 -534 /** -535 * Close the given {@link Closeable} instance, ignoring nulls, and logging -536 * any thrown {@link IOException}. -537 * -538 * @param closeable to be closed -539 */ -540 private static void close(Closeable closeable) { -541 if (null != closeable) { -542 try { -543 closeable.close(); -544 } catch (IOException ex) { -545 LOGGER.trace("", ex); -546 } -547 } -548 } -549 -550 /** -551 * Attempts to determine if a zip file is actually a JAR file. -552 * -553 * @param dependency the dependency to check -554 * @return true if the dependency appears to be a JAR file; otherwise false -555 */ -556 private boolean isZipFileActuallyJarFile(Dependency dependency) { -557 boolean isJar = false; -558 ZipFile zip = null; -559 try { -560 zip = new ZipFile(dependency.getActualFilePath()); -561 if (zip.getEntry("META-INF/MANIFEST.MF") != null -562 || zip.getEntry("META-INF/maven") != null) { -563 final Enumeration<ZipArchiveEntry> entries = zip.getEntries(); -564 while (entries.hasMoreElements()) { -565 final ZipArchiveEntry entry = entries.nextElement(); -566 if (!entry.isDirectory()) { -567 final String name = entry.getName().toLowerCase(); -568 if (name.endsWith(".class")) { -569 isJar = true; -570 break; -571 } -572 } -573 } -574 } -575 } catch (IOException ex) { -576 LOGGER.debug("Unable to unzip zip file '{}'", dependency.getFilePath(), ex); -577 } finally { -578 ZipFile.closeQuietly(zip); -579 } -580 -581 return isJar; -582 } -583 } +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 }
    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 12b21ab99..34acd7d46 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.html @@ -53,282 +53,330 @@ 45 import java.util.List; 46 import javax.xml.parsers.ParserConfigurationException; 47 import org.owasp.dependencycheck.exception.InitializationException; -48 -49 /** -50 * Analyzer for getting company, product, and version information from a .NET -51 * assembly. -52 * -53 * @author colezlaw -54 * -55 */ -56 public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer { -57 -58 /** -59 * The analyzer name -60 */ -61 private static final String ANALYZER_NAME = "Assembly Analyzer"; -62 /** -63 * The analysis phase -64 */ -65 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION; -66 /** -67 * The list of supported extensions -68 */ -69 private static final String[] SUPPORTED_EXTENSIONS = {"dll", "exe"}; -70 /** -71 * The temp value for GrokAssembly.exe -72 */ -73 private File grokAssemblyExe = null; -74 /** -75 * The DocumentBuilder for parsing the XML -76 */ -77 private DocumentBuilder builder; -78 /** -79 * Logger -80 */ -81 private static final Logger LOGGER = LoggerFactory.getLogger(AssemblyAnalyzer.class); -82 -83 /** -84 * Builds the beginnings of a List for ProcessBuilder -85 * -86 * @return the list of arguments to begin populating the ProcessBuilder -87 */ -88 private List<String> buildArgumentList() { -89 // Use file.separator as a wild guess as to whether this is Windows -90 final List<String> args = new ArrayList<String>(); -91 if (!"\\".equals(System.getProperty("file.separator"))) { -92 if (Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH) != null) { -93 args.add(Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH)); -94 } else { -95 args.add("mono"); -96 } -97 } -98 args.add(grokAssemblyExe.getPath()); -99 -100 return args; -101 } -102 -103 /** -104 * Performs the analysis on a single Dependency. -105 * -106 * @param dependency the dependency to analyze -107 * @param engine the engine to perform the analysis under -108 * @throws AnalysisException if anything goes sideways -109 */ -110 @Override -111 public void analyzeFileType(Dependency dependency, Engine engine) -112 throws AnalysisException { -113 if (grokAssemblyExe == null) { -114 LOGGER.warn("GrokAssembly didn't get deployed"); -115 return; -116 } -117 -118 final List<String> args = buildArgumentList(); -119 args.add(dependency.getActualFilePath()); -120 final ProcessBuilder pb = new ProcessBuilder(args); -121 Document doc = null; -122 try { -123 final Process proc = pb.start(); -124 -125 doc = builder.parse(proc.getInputStream()); -126 -127 // Try evacuating the error stream -128 final String errorStream = IOUtils.toString(proc.getErrorStream(), "UTF-8"); -129 if (null != errorStream && !errorStream.isEmpty()) { -130 LOGGER.warn("Error from GrokAssembly: {}", errorStream); -131 } +48 import org.apache.commons.lang3.SystemUtils; +49 +50 /** +51 * Analyzer for getting company, product, and version information from a .NET +52 * assembly. +53 * +54 * @author colezlaw +55 * +56 */ +57 public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer { +58 +59 /** +60 * The analyzer name +61 */ +62 private static final String ANALYZER_NAME = "Assembly Analyzer"; +63 /** +64 * The analysis phase +65 */ +66 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION; +67 /** +68 * The list of supported extensions +69 */ +70 private static final String[] SUPPORTED_EXTENSIONS = {"dll", "exe"}; +71 /** +72 * The temp value for GrokAssembly.exe +73 */ +74 private File grokAssemblyExe = null; +75 /** +76 * The DocumentBuilder for parsing the XML +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 int rc = 0; -134 try { -135 rc = proc.waitFor(); -136 } catch (InterruptedException ie) { -137 return; -138 } -139 if (rc == 3) { -140 LOGGER.debug("{} is not a .NET assembly or executable and as such cannot be analyzed by dependency-check", -141 dependency.getActualFilePath()); -142 return; -143 } else if (rc != 0) { -144 LOGGER.warn("Return code {} from GrokAssembly", rc); -145 } -146 -147 final XPath xpath = XPathFactory.newInstance().newXPath(); -148 -149 // First, see if there was an error -150 final String error = xpath.evaluate("/assembly/error", doc); -151 if (error != null && !error.isEmpty()) { -152 throw new AnalysisException(error); -153 } +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 final String version = xpath.evaluate("/assembly/version", doc); -156 if (version != null) { -157 dependency.getVersionEvidence().addEvidence(new Evidence("grokassembly", "version", -158 version, Confidence.HIGHEST)); +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 vendor = xpath.evaluate("/assembly/company", doc); -162 if (vendor != null) { -163 dependency.getVendorEvidence().addEvidence(new Evidence("grokassembly", "vendor", -164 vendor, Confidence.HIGH)); +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 product = xpath.evaluate("/assembly/product", doc); -168 if (product != null) { -169 dependency.getProductEvidence().addEvidence(new Evidence("grokassembly", "product", -170 product, Confidence.HIGH)); +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 } catch (IOException ioe) { -174 throw new AnalysisException(ioe); -175 } catch (SAXException saxe) { -176 throw new AnalysisException("Couldn't parse GrokAssembly result", saxe); -177 } catch (XPathExpressionException xpe) { -178 // This shouldn't happen -179 throw new AnalysisException(xpe); -180 } -181 } -182 -183 /** -184 * Initialize the analyzer. In this case, extract GrokAssembly.exe to a -185 * temporary location. -186 * -187 * @throws InitializationException thrown if anything goes wrong -188 */ -189 @Override -190 public void initializeFileTypeAnalyzer() throws InitializationException { -191 final File tempFile; -192 try { -193 tempFile = File.createTempFile("GKA", ".exe", Settings.getTempDirectory()); -194 } catch (IOException ex) { -195 setEnabled(false); -196 throw new InitializationException("Unable to create temporary file for the assembly analyzerr", ex); -197 } -198 FileOutputStream fos = null; -199 InputStream is = null; -200 try { -201 fos = new FileOutputStream(tempFile); -202 is = AssemblyAnalyzer.class.getClassLoader().getResourceAsStream("GrokAssembly.exe"); -203 IOUtils.copy(is, fos); -204 -205 grokAssemblyExe = tempFile; -206 // Set the temp file to get deleted when we're done -207 grokAssemblyExe.deleteOnExit(); -208 LOGGER.debug("Extracted GrokAssembly.exe to {}", grokAssemblyExe.getPath()); -209 } catch (IOException ioe) { -210 this.setEnabled(false); -211 LOGGER.warn("Could not extract GrokAssembly.exe: {}", ioe.getMessage()); -212 throw new InitializationException("Could not extract GrokAssembly.exe", ioe); -213 } finally { -214 if (fos != null) { -215 try { -216 fos.close(); -217 } catch (Throwable e) { -218 LOGGER.debug("Error closing output stream"); -219 } -220 } -221 if (is != null) { -222 try { -223 is.close(); -224 } catch (Throwable e) { -225 LOGGER.debug("Error closing input stream"); -226 } -227 } -228 } -229 -230 // Now, need to see if GrokAssembly actually runs from this location. -231 final List<String> args = buildArgumentList(); -232 try { -233 final ProcessBuilder pb = new ProcessBuilder(args); -234 final Process p = pb.start(); -235 // Try evacuating the error stream -236 IOUtils.copy(p.getErrorStream(), NullOutputStream.NULL_OUTPUT_STREAM); -237 -238 final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(p.getInputStream()); -239 final XPath xpath = XPathFactory.newInstance().newXPath(); -240 final String error = xpath.evaluate("/assembly/error", doc); -241 if (p.waitFor() != 1 || error == null || error.isEmpty()) { -242 LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer, please see the log for more details."); -243 LOGGER.debug("GrokAssembly.exe is not working properly"); -244 grokAssemblyExe = null; -245 setEnabled(false); -246 throw new InitializationException("Could not execute .NET AssemblyAnalyzer"); -247 } -248 } catch (InitializationException e) { -249 throw e; -250 } catch (Throwable e) { -251 LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer;\n" -252 + "this can be ignored unless you are scanning .NET DLLs. Please see the log for more details."); -253 LOGGER.debug("Could not execute GrokAssembly {}", e.getMessage()); -254 setEnabled(false); -255 throw new InitializationException("An error occurred with the .NET AssemblyAnalyzer", e); -256 } -257 try { -258 builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); -259 } catch (ParserConfigurationException ex) { -260 setEnabled(false); -261 throw new InitializationException("Error initializing the assembly analyzer", ex); -262 } -263 } -264 -265 /** -266 * Removes resources used from the local file system. -267 * -268 * @throws Exception thrown if there is a problem closing the analyzer -269 */ -270 @Override -271 public void close() throws Exception { -272 super.close(); -273 try { -274 if (grokAssemblyExe != null && !grokAssemblyExe.delete()) { -275 grokAssemblyExe.deleteOnExit(); -276 } -277 } catch (SecurityException se) { -278 LOGGER.debug("Can't delete temporary GrokAssembly.exe"); -279 } -280 } -281 -282 /** -283 * The File Filter used to filter supported extensions. -284 */ -285 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions( -286 SUPPORTED_EXTENSIONS).build(); -287 -288 @Override -289 protected FileFilter getFileFilter() { -290 return FILTER; -291 } -292 -293 /** -294 * Gets this analyzer's name. -295 * -296 * @return the analyzer name -297 */ -298 @Override -299 public String getName() { -300 return ANALYZER_NAME; -301 } -302 -303 /** -304 * Returns the phase this analyzer runs under. -305 * -306 * @return the phase this runs under +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 @Override -309 public AnalysisPhase getAnalysisPhase() { -310 return ANALYSIS_PHASE; -311 } -312 -313 /** -314 * Returns the key used in the properties file to reference the analyzer's -315 * enabled property. -316 * -317 * @return the analyzer's enabled property setting key -318 */ -319 @Override -320 protected String getAnalyzerEnabledSettingKey() { -321 return Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED; -322 } -323 } +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 }
    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 f090a3223..d9f5e97dd 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.html @@ -204,53 +204,56 @@ 196 * @param engine the dependency-check engine 197 * @param contents the version information 198 */ -199 private void analyzeSetVersionCommand(Dependency dependency, Engine engine, String contents) { -200 Dependency currentDep = dependency; -201 -202 final Matcher m = SET_VERSION.matcher(contents); -203 int count = 0; -204 while (m.find()) { -205 count++; -206 LOGGER.debug("Found project command match with {} groups: {}", -207 m.groupCount(), m.group(0)); -208 String product = m.group(1); -209 final String version = m.group(2); -210 LOGGER.debug("Group 1: " + product); -211 LOGGER.debug("Group 2: " + version); -212 final String aliasPrefix = "ALIASOF_"; -213 if (product.startsWith(aliasPrefix)) { -214 product = product.replaceFirst(aliasPrefix, ""); -215 } -216 if (count > 1) { -217 //TODO - refactor so we do not assign to the parameter (checkstyle) -218 currentDep = new Dependency(dependency.getActualFile()); -219 currentDep.setDisplayFileName(String.format("%s:%s", dependency.getDisplayFileName(), product)); -220 final String filePath = String.format("%s:%s", dependency.getFilePath(), product); -221 currentDep.setFilePath(filePath); -222 -223 byte[] path; -224 try { -225 path = filePath.getBytes("UTF-8"); -226 } catch (UnsupportedEncodingException ex) { -227 path = filePath.getBytes(); -228 } -229 currentDep.setSha1sum(Checksum.getHex(sha1.digest(path))); -230 engine.getDependencies().add(currentDep); -231 } -232 final String source = currentDep.getDisplayFileName(); -233 currentDep.getProductEvidence().addEvidence(source, "Product", -234 product, Confidence.MEDIUM); -235 currentDep.getVersionEvidence().addEvidence(source, "Version", -236 version, Confidence.MEDIUM); -237 } -238 LOGGER.debug(String.format("Found %d matches.", count)); -239 } -240 -241 @Override -242 protected String getAnalyzerEnabledSettingKey() { -243 return Settings.KEYS.ANALYZER_CMAKE_ENABLED; -244 } -245 } +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 }
    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 dada8235f..1cd289873 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CPEAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CPEAnalyzer.html @@ -33,793 +33,801 @@ 25 import java.util.List; 26 import java.util.Set; 27 import java.util.StringTokenizer; -28 import org.apache.lucene.document.Document; -29 import org.apache.lucene.index.CorruptIndexException; -30 import org.apache.lucene.queryparser.classic.ParseException; -31 import org.apache.lucene.search.ScoreDoc; -32 import org.apache.lucene.search.TopDocs; -33 import org.owasp.dependencycheck.Engine; -34 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; -35 import org.owasp.dependencycheck.data.cpe.CpeMemoryIndex; -36 import org.owasp.dependencycheck.data.cpe.Fields; -37 import org.owasp.dependencycheck.data.cpe.IndexEntry; -38 import org.owasp.dependencycheck.data.cpe.IndexException; -39 import org.owasp.dependencycheck.data.lucene.LuceneUtils; -40 import org.owasp.dependencycheck.data.nvdcve.CveDB; -41 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; -42 import org.owasp.dependencycheck.dependency.Confidence; -43 import org.owasp.dependencycheck.dependency.Dependency; -44 import org.owasp.dependencycheck.dependency.Evidence; -45 import org.owasp.dependencycheck.dependency.EvidenceCollection; -46 import org.owasp.dependencycheck.dependency.Identifier; -47 import org.owasp.dependencycheck.dependency.VulnerableSoftware; -48 import org.owasp.dependencycheck.exception.InitializationException; -49 import org.owasp.dependencycheck.utils.DependencyVersion; -50 import org.owasp.dependencycheck.utils.DependencyVersionUtil; -51 import org.slf4j.Logger; -52 import org.slf4j.LoggerFactory; -53 -54 /** -55 * CPEAnalyzer is a utility class that takes a project dependency and attempts -56 * to discern if there is an associated CPE. It uses the evidence contained -57 * within the dependency to search the Lucene index. -58 * -59 * @author Jeremy Long -60 */ -61 public class CPEAnalyzer implements Analyzer { -62 -63 /** -64 * The Logger. -65 */ -66 private static final Logger LOGGER = LoggerFactory.getLogger(CPEAnalyzer.class); -67 /** -68 * The maximum number of query results to return. -69 */ -70 static final int MAX_QUERY_RESULTS = 25; -71 /** -72 * The weighting boost to give terms when constructing the Lucene query. -73 */ -74 static final String WEIGHTING_BOOST = "^5"; -75 /** -76 * A string representation of a regular expression defining characters -77 * utilized within the CPE Names. -78 */ -79 static final String CLEANSE_CHARACTER_RX = "[^A-Za-z0-9 ._-]"; -80 /** -81 * A string representation of a regular expression used to remove all but -82 * alpha characters. -83 */ -84 static final String CLEANSE_NONALPHA_RX = "[^A-Za-z]*"; -85 /** -86 * The additional size to add to a new StringBuilder to account for extra -87 * data that will be written into the string. -88 */ -89 static final int STRING_BUILDER_BUFFER = 20; -90 /** -91 * The CPE in memory index. -92 */ -93 private CpeMemoryIndex cpe; -94 /** -95 * The CVE Database. -96 */ -97 private CveDB cve; -98 -99 /** -100 * The URL to perform a search of the NVD CVE data at NIST. -101 */ -102 public static final String NVD_SEARCH_URL = "https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=%s"; -103 -104 /** -105 * Returns the name of this analyzer. -106 * -107 * @return the name of this analyzer. -108 */ -109 @Override -110 public String getName() { -111 return "CPE Analyzer"; -112 } -113 -114 /** -115 * Returns the analysis phase that this analyzer should run in. -116 * -117 * @return the analysis phase that this analyzer should run in. -118 */ -119 @Override -120 public AnalysisPhase getAnalysisPhase() { -121 return AnalysisPhase.IDENTIFIER_ANALYSIS; -122 } -123 -124 /** -125 * Creates the CPE Lucene Index. -126 * -127 * @throws InitializationException is thrown if there is an issue opening -128 * the index. -129 */ -130 @Override -131 public void initialize() throws InitializationException { -132 try { -133 this.open(); -134 } catch (IOException ex) { -135 LOGGER.debug("Exception initializing the Lucene Index", ex); -136 throw new InitializationException("An exception occurred initializing the Lucene Index", ex); -137 } catch (DatabaseException ex) { -138 LOGGER.debug("Exception accessing the database", ex); -139 throw new InitializationException("An exception occurred accessing the database", ex); -140 } -141 } -142 -143 /** -144 * Opens the data source. -145 * -146 * @throws IOException when the Lucene directory to be queried does not -147 * exist or is corrupt. -148 * @throws DatabaseException when the database throws an exception. This -149 * usually occurs when the database is in use by another process. -150 */ -151 public void open() throws IOException, DatabaseException { -152 if (!isOpen()) { -153 cve = new CveDB(); -154 cve.open(); -155 cpe = CpeMemoryIndex.getInstance(); -156 try { -157 LOGGER.info("Creating the CPE Index"); -158 final long creationStart = System.currentTimeMillis(); -159 cpe.open(cve); -160 LOGGER.info("CPE Index Created ({} ms)", System.currentTimeMillis() - creationStart); -161 } catch (IndexException ex) { -162 LOGGER.debug("IndexException", ex); -163 throw new DatabaseException(ex); -164 } -165 } -166 } -167 -168 /** -169 * Closes the data sources. -170 */ -171 @Override -172 public void close() { -173 if (cpe != null) { -174 cpe.close(); -175 cpe = null; -176 } -177 if (cve != null) { -178 cve.close(); -179 cve = null; -180 } -181 } -182 -183 public boolean isOpen() { -184 return cpe != null && cpe.isOpen(); -185 } -186 -187 /** -188 * Searches the data store of CPE entries, trying to identify the CPE for -189 * the given dependency based on the evidence contained within. The -190 * dependency passed in is updated with any identified CPE values. -191 * -192 * @param dependency the dependency to search for CPE entries on. -193 * @throws CorruptIndexException is thrown when the Lucene index is corrupt. -194 * @throws IOException is thrown when an IOException occurs. -195 * @throws ParseException is thrown when the Lucene query cannot be parsed. -196 */ -197 protected void determineCPE(Dependency dependency) throws CorruptIndexException, IOException, ParseException { -198 //TODO test dojo-war against this. we shold get dojo-toolkit:dojo-toolkit AND dojo-toolkit:toolkit -199 String vendors = ""; -200 String products = ""; -201 for (Confidence confidence : Confidence.values()) { -202 if (dependency.getVendorEvidence().contains(confidence)) { -203 vendors = addEvidenceWithoutDuplicateTerms(vendors, dependency.getVendorEvidence(), confidence); -204 LOGGER.debug("vendor search: {}", vendors); -205 } -206 if (dependency.getProductEvidence().contains(confidence)) { -207 products = addEvidenceWithoutDuplicateTerms(products, dependency.getProductEvidence(), confidence); -208 LOGGER.debug("product search: {}", products); -209 } -210 if (!vendors.isEmpty() && !products.isEmpty()) { -211 final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getVendorEvidence().getWeighting(), -212 dependency.getProductEvidence().getWeighting()); -213 if (entries == null) { -214 continue; -215 } -216 boolean identifierAdded = false; -217 for (IndexEntry e : entries) { -218 LOGGER.debug("Verifying entry: {}", e); -219 if (verifyEntry(e, dependency)) { -220 final String vendor = e.getVendor(); -221 final String product = e.getProduct(); -222 LOGGER.debug("identified vendor/product: {}/{}", vendor, product); -223 identifierAdded |= determineIdentifiers(dependency, vendor, product, confidence); -224 } -225 } -226 if (identifierAdded) { -227 break; -228 } -229 } -230 } -231 } -232 -233 /** -234 * Returns the text created by concatenating the text and the values from -235 * the EvidenceCollection (filtered for a specific confidence). This -236 * attempts to prevent duplicate terms from being added.<br/<br/> Note, if -237 * the evidence is longer then 200 characters it will be truncated. -238 * -239 * @param text the base text. -240 * @param ec an EvidenceCollection -241 * @param confidenceFilter a Confidence level to filter the evidence by. -242 * @return the new evidence text -243 */ -244 private String addEvidenceWithoutDuplicateTerms(final String text, final EvidenceCollection ec, Confidence confidenceFilter) { -245 final String txt = (text == null) ? "" : text; -246 final StringBuilder sb = new StringBuilder(txt.length() + (20 * ec.size())); -247 sb.append(' ').append(txt).append(' '); -248 for (Evidence e : ec.iterator(confidenceFilter)) { -249 String value = e.getValue(); -250 -251 //hack to get around the fact that lucene does a really good job of recognizing domains and not -252 // splitting them. TODO - put together a better lucene analyzer specific to the domain. -253 if (value.startsWith("http://")) { -254 value = value.substring(7).replaceAll("\\.", " "); -255 } -256 if (value.startsWith("https://")) { -257 value = value.substring(8).replaceAll("\\.", " "); -258 } -259 if (sb.indexOf(" " + value + " ") < 0) { -260 sb.append(value).append(' '); -261 } -262 } -263 return sb.toString().trim(); -264 } -265 -266 /** -267 * <p> -268 * Searches the Lucene CPE index to identify possible CPE entries associated -269 * with the supplied vendor, product, and version.</p> -270 * -271 * <p> -272 * If either the vendorWeightings or productWeightings lists have been -273 * populated this data is used to add weighting factors to the search.</p> -274 * -275 * @param vendor the text used to search the vendor field -276 * @param product the text used to search the product field -277 * @param vendorWeightings a list of strings to use to add weighting factors -278 * to the vendor field -279 * @param productWeightings Adds a list of strings that will be used to add -280 * weighting factors to the product search -281 * @return a list of possible CPE values -282 */ -283 protected List<IndexEntry> searchCPE(String vendor, String product, -284 Set<String> vendorWeightings, Set<String> productWeightings) { -285 -286 final List<IndexEntry> ret = new ArrayList<IndexEntry>(MAX_QUERY_RESULTS); -287 -288 final String searchString = buildSearch(vendor, product, vendorWeightings, productWeightings); -289 if (searchString == null) { -290 return ret; -291 } -292 try { -293 final TopDocs docs = cpe.search(searchString, MAX_QUERY_RESULTS); -294 for (ScoreDoc d : docs.scoreDocs) { -295 if (d.score >= 0.08) { -296 final Document doc = cpe.getDocument(d.doc); -297 final IndexEntry entry = new IndexEntry(); -298 entry.setVendor(doc.get(Fields.VENDOR)); -299 entry.setProduct(doc.get(Fields.PRODUCT)); -300 entry.setSearchScore(d.score); -301 if (!ret.contains(entry)) { -302 ret.add(entry); -303 } -304 } -305 } -306 return ret; -307 } catch (ParseException ex) { -308 LOGGER.warn("An error occurred querying the CPE data. See the log for more details."); -309 LOGGER.info("Unable to parse: {}", searchString, ex); -310 } catch (IOException ex) { -311 LOGGER.warn("An error occurred reading CPE data. See the log for more details."); -312 LOGGER.info("IO Error with search string: {}", searchString, ex); -313 } -314 return null; -315 } -316 -317 /** -318 * <p> -319 * Builds a Lucene search string by properly escaping data and constructing -320 * a valid search query.</p> -321 * -322 * <p> -323 * If either the possibleVendor or possibleProducts lists have been -324 * populated this data is used to add weighting factors to the search string -325 * generated.</p> -326 * -327 * @param vendor text to search the vendor field -328 * @param product text to search the product field -329 * @param vendorWeighting a list of strings to apply to the vendor to boost -330 * the terms weight -331 * @param productWeightings a list of strings to apply to the product to -332 * boost the terms weight -333 * @return the Lucene query -334 */ -335 protected String buildSearch(String vendor, String product, -336 Set<String> vendorWeighting, Set<String> productWeightings) { -337 final String v = vendor; //.replaceAll("[^\\w\\d]", " "); -338 final String p = product; //.replaceAll("[^\\w\\d]", " "); -339 final StringBuilder sb = new StringBuilder(v.length() + p.length() -340 + Fields.PRODUCT.length() + Fields.VENDOR.length() + STRING_BUILDER_BUFFER); -341 -342 if (!appendWeightedSearch(sb, Fields.PRODUCT, p, productWeightings)) { -343 return null; -344 } -345 sb.append(" AND "); -346 if (!appendWeightedSearch(sb, Fields.VENDOR, v, vendorWeighting)) { -347 return null; -348 } -349 return sb.toString(); -350 } -351 -352 /** -353 * This method constructs a Lucene query for a given field. The searchText -354 * is split into separate words and if the word is within the list of -355 * weighted words then an additional weighting is applied to the term as it -356 * is appended into the query. -357 * -358 * @param sb a StringBuilder that the query text will be appended to. -359 * @param field the field within the Lucene index that the query is -360 * searching. -361 * @param searchText text used to construct the query. -362 * @param weightedText a list of terms that will be considered higher -363 * importance when searching. -364 * @return if the append was successful. -365 */ -366 private boolean appendWeightedSearch(StringBuilder sb, String field, String searchText, Set<String> weightedText) { -367 sb.append(' ').append(field).append(":( "); -368 -369 final String cleanText = cleanseText(searchText); -370 -371 if (cleanText.isEmpty()) { -372 return false; -373 } -374 -375 if (weightedText == null || weightedText.isEmpty()) { -376 LuceneUtils.appendEscapedLuceneQuery(sb, cleanText); -377 } else { -378 final StringTokenizer tokens = new StringTokenizer(cleanText); -379 while (tokens.hasMoreElements()) { -380 final String word = tokens.nextToken(); -381 StringBuilder temp = null; -382 for (String weighted : weightedText) { -383 final String weightedStr = cleanseText(weighted); -384 if (equalsIgnoreCaseAndNonAlpha(word, weightedStr)) { -385 temp = new StringBuilder(word.length() + 2); -386 LuceneUtils.appendEscapedLuceneQuery(temp, word); -387 temp.append(WEIGHTING_BOOST); -388 if (!word.equalsIgnoreCase(weightedStr)) { -389 temp.append(' '); -390 LuceneUtils.appendEscapedLuceneQuery(temp, weightedStr); -391 temp.append(WEIGHTING_BOOST); -392 } -393 break; -394 } -395 } -396 sb.append(' '); -397 if (temp == null) { -398 LuceneUtils.appendEscapedLuceneQuery(sb, word); -399 } else { -400 sb.append(temp); -401 } -402 } -403 } -404 sb.append(" ) "); -405 return true; -406 } -407 -408 /** -409 * Removes characters from the input text that are not used within the CPE -410 * index. -411 * -412 * @param text is the text to remove the characters from. -413 * @return the text having removed some characters. -414 */ -415 private String cleanseText(String text) { -416 return text.replaceAll(CLEANSE_CHARACTER_RX, " "); -417 } -418 -419 /** -420 * Compares two strings after lower casing them and removing the non-alpha -421 * characters. -422 * -423 * @param l string one to compare. -424 * @param r string two to compare. -425 * @return whether or not the two strings are similar. -426 */ -427 private boolean equalsIgnoreCaseAndNonAlpha(String l, String r) { -428 if (l == null || r == null) { -429 return false; -430 } -431 -432 final String left = l.replaceAll(CLEANSE_NONALPHA_RX, ""); -433 final String right = r.replaceAll(CLEANSE_NONALPHA_RX, ""); -434 return left.equalsIgnoreCase(right); -435 } -436 -437 /** -438 * Ensures that the CPE Identified matches the dependency. This validates -439 * that the product, vendor, and version information for the CPE are -440 * contained within the dependencies evidence. -441 * -442 * @param entry a CPE entry. -443 * @param dependency the dependency that the CPE entries could be for. -444 * @return whether or not the entry is valid. -445 */ -446 private boolean verifyEntry(final IndexEntry entry, final Dependency dependency) { -447 boolean isValid = false; -448 -449 //TODO - does this nullify some of the fuzzy matching that happens in the lucene search? -450 // for instance CPE some-component and in the evidence we have SomeComponent. -451 if (collectionContainsString(dependency.getProductEvidence(), entry.getProduct()) -452 && collectionContainsString(dependency.getVendorEvidence(), entry.getVendor())) { -453 //&& collectionContainsVersion(dependency.getVersionEvidence(), entry.getVersion()) -454 isValid = true; -455 } -456 return isValid; -457 } -458 -459 /** -460 * Used to determine if the EvidenceCollection contains a specific string. -461 * -462 * @param ec an EvidenceCollection -463 * @param text the text to search for -464 * @return whether or not the EvidenceCollection contains the string -465 */ -466 private boolean collectionContainsString(EvidenceCollection ec, String text) { -467 //TODO - likely need to change the split... not sure if this will work for CPE with special chars -468 if (text == null) { -469 return false; -470 } -471 final String[] words = text.split("[\\s_-]"); -472 final List<String> list = new ArrayList<String>(); -473 String tempWord = null; -474 for (String word : words) { -475 /* -476 single letter words should be concatenated with the next word. -477 so { "m", "core", "sample" } -> { "mcore", "sample" } -478 */ -479 if (tempWord != null) { -480 list.add(tempWord + word); -481 tempWord = null; -482 } else if (word.length() <= 2) { -483 tempWord = word; -484 } else { -485 list.add(word); -486 } -487 } -488 if (tempWord != null) { -489 if (!list.isEmpty()) { -490 final String tmp = list.get(list.size() - 1) + tempWord; -491 list.add(tmp); -492 } else { -493 list.add(tempWord); -494 } -495 } -496 if (list.isEmpty()) { -497 return false; -498 } -499 boolean contains = true; -500 for (String word : list) { -501 contains &= ec.containsUsedString(word); -502 } -503 return contains; -504 } -505 -506 /** -507 * Analyzes a dependency and attempts to determine if there are any CPE -508 * identifiers for this dependency. -509 * -510 * @param dependency The Dependency to analyze. -511 * @param engine The analysis engine -512 * @throws AnalysisException is thrown if there is an issue analyzing the -513 * dependency. -514 */ -515 @Override -516 public synchronized void analyze(Dependency dependency, Engine engine) throws AnalysisException { -517 try { -518 determineCPE(dependency); -519 } catch (CorruptIndexException ex) { -520 throw new AnalysisException("CPE Index is corrupt.", ex); -521 } catch (IOException ex) { -522 throw new AnalysisException("Failure opening the CPE Index.", ex); -523 } catch (ParseException ex) { -524 throw new AnalysisException("Unable to parse the generated Lucene query for this dependency.", ex); -525 } -526 } -527 -528 /** -529 * Retrieves a list of CPE values from the CveDB based on the vendor and -530 * product passed in. The list is then validated to find only CPEs that are -531 * valid for the given dependency. It is possible that the CPE identified is -532 * a best effort "guess" based on the vendor, product, and version -533 * information. -534 * -535 * @param dependency the Dependency being analyzed -536 * @param vendor the vendor for the CPE being analyzed -537 * @param product the product for the CPE being analyzed -538 * @param currentConfidence the current confidence being used during -539 * analysis -540 * @return <code>true</code> if an identifier was added to the dependency; -541 * otherwise <code>false</code> -542 * @throws UnsupportedEncodingException is thrown if UTF-8 is not supported -543 */ -544 protected boolean determineIdentifiers(Dependency dependency, String vendor, String product, -545 Confidence currentConfidence) throws UnsupportedEncodingException { -546 final Set<VulnerableSoftware> cpes = cve.getCPEs(vendor, product); -547 DependencyVersion bestGuess = new DependencyVersion("-"); -548 Confidence bestGuessConf = null; -549 boolean hasBroadMatch = false; -550 final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>(); -551 -552 //TODO the following algorithm incorrectly identifies things as a lower version -553 // if there lower confidence evidence when the current (highest) version number -554 // is newer then anything in the NVD. -555 for (Confidence conf : Confidence.values()) { -556 for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) { -557 final DependencyVersion evVer = DependencyVersionUtil.parseVersion(evidence.getValue()); -558 if (evVer == null) { -559 continue; -560 } -561 for (VulnerableSoftware vs : cpes) { -562 DependencyVersion dbVer; -563 if (vs.getUpdate() != null && !vs.getUpdate().isEmpty()) { -564 dbVer = DependencyVersionUtil.parseVersion(vs.getVersion() + '.' + vs.getUpdate()); -565 } else { -566 dbVer = DependencyVersionUtil.parseVersion(vs.getVersion()); -567 } -568 if (dbVer == null) { //special case, no version specified - everything is vulnerable -569 hasBroadMatch = true; -570 final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8")); -571 final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.BROAD_MATCH, conf); -572 collected.add(match); -573 } else if (evVer.equals(dbVer)) { //yeah! exact match -574 final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8")); -575 final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf); -576 collected.add(match); -577 -578 //TODO the following isn't quite right is it? need to think about this guessing game a bit more. -579 } else if (evVer.getVersionParts().size() <= dbVer.getVersionParts().size() -580 && evVer.matchesAtLeastThreeLevels(dbVer)) { -581 if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) { -582 if (bestGuess.getVersionParts().size() < dbVer.getVersionParts().size()) { -583 bestGuess = dbVer; -584 bestGuessConf = conf; -585 } -586 } -587 } -588 } -589 if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) { -590 if (bestGuess.getVersionParts().size() < evVer.getVersionParts().size()) { -591 bestGuess = evVer; -592 bestGuessConf = conf; -593 } -594 } -595 } -596 } -597 final String cpeName = String.format("cpe:/a:%s:%s:%s", vendor, product, bestGuess.toString()); -598 String url = null; -599 if (hasBroadMatch) { //if we have a broad match we can add the URL to the best guess. -600 final String cpeUrlName = String.format("cpe:/a:%s:%s", vendor, product); -601 url = String.format(NVD_SEARCH_URL, URLEncoder.encode(cpeUrlName, "UTF-8")); -602 } -603 if (bestGuessConf == null) { -604 bestGuessConf = Confidence.LOW; -605 } -606 final IdentifierMatch match = new IdentifierMatch("cpe", cpeName, url, IdentifierConfidence.BEST_GUESS, bestGuessConf); -607 collected.add(match); -608 -609 Collections.sort(collected); -610 final IdentifierConfidence bestIdentifierQuality = collected.get(0).getConfidence(); -611 final Confidence bestEvidenceQuality = collected.get(0).getEvidenceConfidence(); -612 boolean identifierAdded = false; -613 for (IdentifierMatch m : collected) { -614 if (bestIdentifierQuality.equals(m.getConfidence()) -615 && bestEvidenceQuality.equals(m.getEvidenceConfidence())) { -616 final Identifier i = m.getIdentifier(); -617 if (bestIdentifierQuality == IdentifierConfidence.BEST_GUESS) { -618 i.setConfidence(Confidence.LOW); -619 } else { -620 i.setConfidence(bestEvidenceQuality); -621 } -622 dependency.addIdentifier(i); -623 identifierAdded = true; -624 } -625 } -626 return identifierAdded; -627 } -628 -629 /** -630 * The confidence whether the identifier is an exact match, or a best guess. -631 */ -632 private enum IdentifierConfidence { -633 -634 /** -635 * An exact match for the CPE. -636 */ -637 EXACT_MATCH, -638 /** -639 * A best guess for the CPE. -640 */ -641 BEST_GUESS, -642 /** -643 * The entire vendor/product group must be added (without a guess at -644 * version) because there is a CVE with a VS that only specifies -645 * vendor/product. -646 */ -647 BROAD_MATCH -648 } -649 -650 /** -651 * A simple object to hold an identifier and carry information about the -652 * confidence in the identifier. -653 */ -654 private static class IdentifierMatch implements Comparable<IdentifierMatch> { -655 -656 /** -657 * Constructs an IdentifierMatch. -658 * -659 * @param type the type of identifier (such as CPE) -660 * @param value the value of the identifier -661 * @param url the URL of the identifier -662 * @param identifierConfidence the confidence in the identifier: best -663 * guess or exact match -664 * @param evidenceConfidence the confidence of the evidence used to find -665 * the identifier -666 */ -667 IdentifierMatch(String type, String value, String url, IdentifierConfidence identifierConfidence, Confidence evidenceConfidence) { -668 this.identifier = new Identifier(type, value, url); -669 this.confidence = identifierConfidence; -670 this.evidenceConfidence = evidenceConfidence; -671 } -672 //<editor-fold defaultstate="collapsed" desc="Property implementations: evidenceConfidence, confidence, identifier"> -673 /** -674 * The confidence in the evidence used to identify this match. -675 */ -676 private Confidence evidenceConfidence; -677 -678 /** -679 * Get the value of evidenceConfidence -680 * -681 * @return the value of evidenceConfidence -682 */ -683 public Confidence getEvidenceConfidence() { -684 return evidenceConfidence; -685 } -686 -687 /** -688 * Set the value of evidenceConfidence -689 * -690 * @param evidenceConfidence new value of evidenceConfidence -691 */ -692 public void setEvidenceConfidence(Confidence evidenceConfidence) { -693 this.evidenceConfidence = evidenceConfidence; -694 } -695 /** -696 * The confidence whether this is an exact match, or a best guess. -697 */ -698 private IdentifierConfidence confidence; -699 -700 /** -701 * Get the value of confidence. -702 * -703 * @return the value of confidence -704 */ -705 public IdentifierConfidence getConfidence() { -706 return confidence; -707 } -708 -709 /** -710 * Set the value of confidence. -711 * -712 * @param confidence new value of confidence -713 */ -714 public void setConfidence(IdentifierConfidence confidence) { -715 this.confidence = confidence; -716 } -717 /** -718 * The CPE identifier. -719 */ -720 private Identifier identifier; -721 -722 /** -723 * Get the value of identifier. -724 * -725 * @return the value of identifier -726 */ -727 public Identifier getIdentifier() { -728 return identifier; -729 } -730 -731 /** -732 * Set the value of identifier. -733 * -734 * @param identifier new value of identifier -735 */ -736 public void setIdentifier(Identifier identifier) { -737 this.identifier = identifier; -738 } -739 //</editor-fold> -740 //<editor-fold defaultstate="collapsed" desc="Standard implementations of toString, hashCode, and equals"> -741 -742 /** -743 * Standard toString() implementation. -744 * -745 * @return the string representation of the object -746 */ -747 @Override -748 public String toString() { -749 return "IdentifierMatch{" + "evidenceConfidence=" + evidenceConfidence -750 + ", confidence=" + confidence + ", identifier=" + identifier + '}'; -751 } -752 -753 /** -754 * Standard hashCode() implementation. -755 * -756 * @return the hashCode -757 */ -758 @Override -759 public int hashCode() { -760 int hash = 5; -761 hash = 97 * hash + (this.evidenceConfidence != null ? this.evidenceConfidence.hashCode() : 0); -762 hash = 97 * hash + (this.confidence != null ? this.confidence.hashCode() : 0); -763 hash = 97 * hash + (this.identifier != null ? this.identifier.hashCode() : 0); -764 return hash; -765 } -766 -767 /** -768 * Standard equals implementation. -769 * -770 * @param obj the object to compare -771 * @return true if the objects are equal, otherwise false -772 */ -773 @Override -774 public boolean equals(Object obj) { -775 if (obj == null) { -776 return false; -777 } -778 if (getClass() != obj.getClass()) { -779 return false; -780 } -781 final IdentifierMatch other = (IdentifierMatch) obj; -782 if (this.evidenceConfidence != other.evidenceConfidence) { -783 return false; -784 } -785 if (this.confidence != other.confidence) { -786 return false; -787 } -788 if (this.identifier != other.identifier && (this.identifier == null || !this.identifier.equals(other.identifier))) { -789 return false; -790 } -791 return true; -792 } -793 //</editor-fold> -794 -795 /** -796 * Standard implementation of compareTo that compares identifier -797 * confidence, evidence confidence, and then the identifier. -798 * -799 * @param o the IdentifierMatch to compare to -800 * @return the natural ordering of IdentifierMatch -801 */ -802 @Override -803 public int compareTo(IdentifierMatch o) { -804 int conf = this.confidence.compareTo(o.confidence); -805 if (conf == 0) { -806 conf = this.evidenceConfidence.compareTo(o.evidenceConfidence); -807 if (conf == 0) { -808 conf = identifier.compareTo(o.identifier); -809 } -810 } -811 return conf; -812 } -813 } -814 } +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"); +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 }
    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 3fc3de35e..886f0d5d1 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CentralAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CentralAnalyzer.html @@ -237,23 +237,24 @@ 229 LOGGER.warn("Unable to download pom.xml for {} from Central; " 230 + "this could result in undetected CPE/CVEs.", dependency.getFileName()); 231 } finally { -232 if (pomFile != null && !FileUtils.deleteQuietly(pomFile)) { -233 pomFile.deleteOnExit(); -234 } -235 } -236 } -237 -238 } -239 } catch (IllegalArgumentException iae) { -240 LOGGER.info("invalid sha1-hash on {}", dependency.getFileName()); -241 } catch (FileNotFoundException fnfe) { -242 LOGGER.debug("Artifact not found in repository: '{}", dependency.getFileName()); -243 } catch (IOException ioe) { -244 LOGGER.debug("Could not connect to Central search", ioe); -245 errorFlag = true; -246 } -247 } -248 } +232 if (pomFile != null && pomFile.exists() && !FileUtils.deleteQuietly(pomFile)) { +233 LOGGER.debug("Failed to delete temporary pom file {}", pomFile.toString()); +234 pomFile.deleteOnExit(); +235 } +236 } +237 } +238 +239 } +240 } catch (IllegalArgumentException iae) { +241 LOGGER.info("invalid sha1-hash on {}", dependency.getFileName()); +242 } catch (FileNotFoundException fnfe) { +243 LOGGER.debug("Artifact not found in repository: '{}", dependency.getFileName()); +244 } catch (IOException ioe) { +245 LOGGER.debug("Could not connect to Central search", ioe); +246 errorFlag = true; +247 } +248 } +249 }
    diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CocoaPodsAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CocoaPodsAnalyzer.html new file mode 100644 index 000000000..7327e372c --- /dev/null +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CocoaPodsAnalyzer.html @@ -0,0 +1,218 @@ + + + +CocoaPodsAnalyzer 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 IBM Corporation. All Rights Reserved.
    +17   */
    +18  package org.owasp.dependencycheck.analyzer;
    +19  
    +20  import java.io.File;
    +21  import java.io.FileFilter;
    +22  import java.io.IOException;
    +23  import java.nio.charset.Charset;
    +24  import java.util.regex.Matcher;
    +25  import java.util.regex.Pattern;
    +26  
    +27  import org.apache.commons.io.FileUtils;
    +28  import org.owasp.dependencycheck.Engine;
    +29  import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
    +30  import org.owasp.dependencycheck.dependency.Confidence;
    +31  import org.owasp.dependencycheck.dependency.Dependency;
    +32  import org.owasp.dependencycheck.dependency.EvidenceCollection;
    +33  import org.owasp.dependencycheck.utils.FileFilterBuilder;
    +34  import org.owasp.dependencycheck.utils.Settings;
    +35  
    +36  /**
    +37   * This analyzer is used to analyze SWIFT and Objective-C packages by collecting
    +38   * information from .podspec files. CocoaPods dependency manager see
    +39   * https://cocoapods.org/.
    +40   *
    +41   * @author Bianca Jiang (https://twitter.com/biancajiang)
    +42   */
    +43  @Experimental
    +44  public class CocoaPodsAnalyzer extends AbstractFileTypeAnalyzer {
    +45  
    +46      /**
    +47       * The logger.
    +48       */
    +49  //    private static final Logger LOGGER = LoggerFactory.getLogger(CocoaPodsAnalyzer.class);
    +50      /**
    +51       * The name of the analyzer.
    +52       */
    +53      private static final String ANALYZER_NAME = "CocoaPods Package Analyzer";
    +54  
    +55      /**
    +56       * The phase that this analyzer is intended to run in.
    +57       */
    +58      private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
    +59  
    +60      /**
    +61       * The file name to scan.
    +62       */
    +63      public static final String PODSPEC = "podspec";
    +64      /**
    +65       * Filter that detects files named "*.podspec".
    +66       */
    +67      private static final FileFilter PODSPEC_FILTER = FileFilterBuilder.newInstance().addExtensions(PODSPEC).build();
    +68  
    +69      /**
    +70       * The capture group #1 is the block variable. e.g. "Pod::Spec.new do
    +71       * |spec|"
    +72       */
    +73      private static final Pattern PODSPEC_BLOCK_PATTERN = Pattern.compile("Pod::Spec\\.new\\s+?do\\s+?\\|(.+?)\\|");
    +74  
    +75      /**
    +76       * Returns the FileFilter
    +77       *
    +78       * @return the FileFilter
    +79       */
    +80      @Override
    +81      protected FileFilter getFileFilter() {
    +82          return PODSPEC_FILTER;
    +83      }
    +84  
    +85      @Override
    +86      protected void initializeFileTypeAnalyzer() {
    +87          // NO-OP
    +88      }
    +89  
    +90      /**
    +91       * Returns the name of the analyzer.
    +92       *
    +93       * @return the name of the analyzer.
    +94       */
    +95      @Override
    +96      public String getName() {
    +97          return ANALYZER_NAME;
    +98      }
    +99  
    +100     /**
    +101      * Returns the phase that the analyzer is intended to run in.
    +102      *
    +103      * @return the phase that the analyzer is intended to run in.
    +104      */
    +105     @Override
    +106     public AnalysisPhase getAnalysisPhase() {
    +107         return ANALYSIS_PHASE;
    +108     }
    +109 
    +110     /**
    +111      * Returns the key used in the properties file to reference the analyzer's
    +112      * enabled property.
    +113      *
    +114      * @return the analyzer's enabled property setting key
    +115      */
    +116     @Override
    +117     protected String getAnalyzerEnabledSettingKey() {
    +118         return Settings.KEYS.ANALYZER_COCOAPODS_ENABLED;
    +119     }
    +120 
    +121     @Override
    +122     protected void analyzeFileType(Dependency dependency, Engine engine)
    +123             throws AnalysisException {
    +124 
    +125         String contents;
    +126         try {
    +127             contents = FileUtils.readFileToString(dependency.getActualFile(), Charset.defaultCharset());
    +128         } catch (IOException e) {
    +129             throw new AnalysisException(
    +130                     "Problem occurred while reading dependency file.", e);
    +131         }
    +132         final Matcher matcher = PODSPEC_BLOCK_PATTERN.matcher(contents);
    +133         if (matcher.find()) {
    +134             contents = contents.substring(matcher.end());
    +135             final String blockVariable = matcher.group(1);
    +136 
    +137             final EvidenceCollection vendor = dependency.getVendorEvidence();
    +138             final EvidenceCollection product = dependency.getProductEvidence();
    +139             final EvidenceCollection version = dependency.getVersionEvidence();
    +140 
    +141             final String name = addStringEvidence(product, contents, blockVariable, "name", "name", Confidence.HIGHEST);
    +142             if (!name.isEmpty()) {
    +143                 vendor.addEvidence(PODSPEC, "name_project", name, Confidence.HIGHEST);
    +144             }
    +145             addStringEvidence(product, contents, blockVariable, "summary", "summary", Confidence.HIGHEST);
    +146 
    +147             addStringEvidence(vendor, contents, blockVariable, "author", "authors?", Confidence.HIGHEST);
    +148             addStringEvidence(vendor, contents, blockVariable, "homepage", "homepage", Confidence.HIGHEST);
    +149             addStringEvidence(vendor, contents, blockVariable, "license", "licen[cs]es?", Confidence.HIGHEST);
    +150 
    +151             addStringEvidence(version, contents, blockVariable, "version", "version", Confidence.HIGHEST);
    +152         }
    +153 
    +154         setPackagePath(dependency);
    +155     }
    +156 
    +157     /**
    +158      * Extracts evidence from the contents and adds it to the given evidence
    +159      * collection.
    +160      *
    +161      * @param evidences the evidence collection to update
    +162      * @param contents the text to extract evidence from
    +163      * @param blockVariable the block variable within the content to search for
    +164      * @param field the name of the field being searched for
    +165      * @param fieldPattern the field pattern within the contents to search for
    +166      * @param confidence the confidence level of the evidence if found
    +167      * @return the string that was added as evidence
    +168      */
    +169     private String addStringEvidence(EvidenceCollection evidences, String contents,
    +170             String blockVariable, String field, String fieldPattern, Confidence confidence) {
    +171         String value = "";
    +172 
    +173         //capture array value between [ ]
    +174         final Matcher arrayMatcher = Pattern.compile(
    +175                 String.format("\\s*?%s\\.%s\\s*?=\\s*?\\{\\s*?(.*?)\\s*?\\}", blockVariable, fieldPattern),
    +176                 Pattern.CASE_INSENSITIVE).matcher(contents);
    +177         if (arrayMatcher.find()) {
    +178             value = arrayMatcher.group(1);
    +179         } else { //capture single value between quotes
    +180             final Matcher matcher = Pattern.compile(
    +181                     String.format("\\s*?%s\\.%s\\s*?=\\s*?(['\"])(.*?)\\1", blockVariable, fieldPattern),
    +182                     Pattern.CASE_INSENSITIVE).matcher(contents);
    +183             if (matcher.find()) {
    +184                 value = matcher.group(2);
    +185             }
    +186         }
    +187         if (value.length() > 0) {
    +188             evidences.addEvidence(PODSPEC, field, value, confidence);
    +189         }
    +190         return value;
    +191     }
    +192 
    +193     /**
    +194      * Sets the package path on the given dependency.
    +195      *
    +196      * @param dep the dependency to update
    +197      */
    +198     private void setPackagePath(Dependency dep) {
    +199         final File file = new File(dep.getFilePath());
    +200         final String parent = file.getParent();
    +201         if (parent != null) {
    +202             dep.setPackagePath(parent);
    +203         }
    +204     }
    +205 }
    +
    +
    + + + 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 b8b973dd7..0ab088c9a 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.html @@ -125,393 +125,446 @@ 117 final ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex()); 118 while (subIterator.hasNext()) { 119 final Dependency nextDependency = subIterator.next(); -120 if (hashesMatch(dependency, nextDependency) && !containedInWar(dependency.getFilePath()) -121 && !containedInWar(nextDependency.getFilePath())) { -122 if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) { -123 mergeDependencies(dependency, nextDependency, dependenciesToRemove); -124 } else { -125 mergeDependencies(nextDependency, dependency, dependenciesToRemove); -126 break; //since we merged into the next dependency - skip forward to the next in mainIterator -127 } -128 } else if (isShadedJar(dependency, nextDependency)) { -129 if (dependency.getFileName().toLowerCase().endsWith("pom.xml")) { -130 mergeDependencies(nextDependency, dependency, dependenciesToRemove); -131 nextDependency.getRelatedDependencies().remove(dependency); -132 break; -133 } else { -134 mergeDependencies(dependency, nextDependency, dependenciesToRemove); -135 dependency.getRelatedDependencies().remove(nextDependency); -136 } -137 } else if (cpeIdentifiersMatch(dependency, nextDependency) -138 && hasSameBasePath(dependency, nextDependency) -139 && fileNameMatch(dependency, nextDependency)) { -140 if (isCore(dependency, nextDependency)) { -141 mergeDependencies(dependency, nextDependency, dependenciesToRemove); -142 } else { -143 mergeDependencies(nextDependency, dependency, dependenciesToRemove); -144 break; //since we merged into the next dependency - skip forward to the next in mainIterator -145 } -146 } else if (isSameRubyGem(dependency, nextDependency)) { -147 final Dependency main = getMainGemspecDependency(dependency, nextDependency); +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) { 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 } -155 } -156 } -157 } -158 //removing dependencies here as ensuring correctness and avoiding ConcurrentUpdateExceptions -159 // was difficult because of the inner iterator. -160 engine.getDependencies().removeAll(dependenciesToRemove); -161 } -162 } -163 -164 /** -165 * Adds the relatedDependency to the dependency's related dependencies. -166 * -167 * @param dependency the main dependency -168 * @param relatedDependency a collection of dependencies to be removed from -169 * the main analysis loop, this is the source of dependencies to remove -170 * @param dependenciesToRemove a collection of dependencies that will be -171 * removed from the main analysis loop, this function adds to this -172 * collection -173 */ -174 private void mergeDependencies(final Dependency dependency, final Dependency relatedDependency, final Set<Dependency> dependenciesToRemove) { -175 dependency.addRelatedDependency(relatedDependency); -176 final Iterator<Dependency> i = relatedDependency.getRelatedDependencies().iterator(); -177 while (i.hasNext()) { -178 dependency.addRelatedDependency(i.next()); -179 i.remove(); -180 } -181 if (dependency.getSha1sum().equals(relatedDependency.getSha1sum())) { -182 dependency.addAllProjectReferences(relatedDependency.getProjectReferences()); -183 } -184 dependenciesToRemove.add(relatedDependency); -185 } -186 -187 /** -188 * Attempts to trim a maven repo to a common base path. This is typically -189 * [drive]\[repo_location]\repository\[path1]\[path2]. -190 * -191 * @param path the path to trim -192 * @return a string representing the base path. -193 */ -194 private String getBaseRepoPath(final String path) { -195 int pos = path.indexOf("repository" + File.separator) + 11; -196 if (pos < 0) { -197 return path; -198 } -199 int tmp = path.indexOf(File.separator, pos); -200 if (tmp <= 0) { -201 return path; -202 } -203 if (tmp > 0) { -204 pos = tmp + 1; +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 tmp = path.indexOf(File.separator, pos); -207 if (tmp > 0) { -208 pos = tmp + 1; +206 int tmp = path.indexOf(File.separator, pos); +207 if (tmp <= 0) { +208 return path; 209 } -210 return path.substring(0, pos); -211 } -212 -213 /** -214 * Returns true if the file names (and version if it exists) of the two -215 * dependencies are sufficiently similar. -216 * -217 * @param dependency1 a dependency2 to compare -218 * @param dependency2 a dependency2 to compare -219 * @return true if the identifiers in the two supplied dependencies are -220 * equal -221 */ -222 private boolean fileNameMatch(Dependency dependency1, Dependency dependency2) { -223 if (dependency1 == null || dependency1.getFileName() == null -224 || dependency2 == null || dependency2.getFileName() == null) { -225 return false; -226 } -227 final String fileName1 = dependency1.getActualFile().getName(); -228 final String fileName2 = dependency2.getActualFile().getName(); -229 -230 //version check -231 final DependencyVersion version1 = DependencyVersionUtil.parseVersion(fileName1); -232 final DependencyVersion version2 = DependencyVersionUtil.parseVersion(fileName2); -233 if (version1 != null && version2 != null && !version1.equals(version2)) { -234 return false; -235 } +210 if (tmp > 0) { +211 pos = tmp + 1; +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 //filename check -238 final Matcher match1 = STARTING_TEXT_PATTERN.matcher(fileName1); -239 final Matcher match2 = STARTING_TEXT_PATTERN.matcher(fileName2); -240 if (match1.find() && match2.find()) { -241 return match1.group().equals(match2.group()); +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 return false; -245 } -246 -247 /** -248 * Returns true if the CPE identifiers in the two supplied dependencies are -249 * equal. -250 * -251 * @param dependency1 a dependency2 to compare -252 * @param dependency2 a dependency2 to compare -253 * @return true if the identifiers in the two supplied dependencies are -254 * equal -255 */ -256 private boolean cpeIdentifiersMatch(Dependency dependency1, Dependency dependency2) { -257 if (dependency1 == null || dependency1.getIdentifiers() == null -258 || dependency2 == null || dependency2.getIdentifiers() == null) { -259 return false; -260 } -261 boolean matches = false; -262 int cpeCount1 = 0; -263 int cpeCount2 = 0; -264 for (Identifier i : dependency1.getIdentifiers()) { -265 if ("cpe".equals(i.getType())) { -266 cpeCount1 += 1; -267 } -268 } -269 for (Identifier i : dependency2.getIdentifiers()) { -270 if ("cpe".equals(i.getType())) { -271 cpeCount2 += 1; -272 } -273 } -274 if (cpeCount1 > 0 && cpeCount1 == cpeCount2) { -275 for (Identifier i : dependency1.getIdentifiers()) { -276 if ("cpe".equals(i.getType())) { -277 matches |= dependency2.getIdentifiers().contains(i); -278 if (!matches) { -279 break; -280 } -281 } -282 } -283 } -284 LOGGER.debug("IdentifiersMatch={} ({}, {})", matches, dependency1.getFileName(), dependency2.getFileName()); -285 return matches; -286 } -287 -288 /** -289 * Determines if the two dependencies have the same base path. -290 * -291 * @param dependency1 a Dependency object -292 * @param dependency2 a Dependency object -293 * @return true if the base paths of the dependencies are identical -294 */ -295 private boolean hasSameBasePath(Dependency dependency1, Dependency dependency2) { -296 if (dependency1 == null || dependency2 == null) { -297 return false; -298 } -299 final File lFile = new File(dependency1.getFilePath()); -300 String left = lFile.getParent(); -301 final File rFile = new File(dependency2.getFilePath()); -302 String right = rFile.getParent(); -303 if (left == null) { -304 return right == null; +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) { +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; 305 } -306 if (left.equalsIgnoreCase(right)) { -307 return true; -308 } -309 if (left.matches(".*[/\\\\]repository[/\\\\].*") && right.matches(".*[/\\\\]repository[/\\\\].*")) { -310 left = getBaseRepoPath(left); -311 right = getBaseRepoPath(right); -312 } -313 if (left.equalsIgnoreCase(right)) { -314 return true; -315 } -316 //new code -317 for (Dependency child : dependency2.getRelatedDependencies()) { -318 if (hasSameBasePath(dependency1, child)) { -319 return true; -320 } -321 } -322 return false; -323 } -324 -325 /** -326 * Bundling Ruby gems that are identified from different .gemspec files but -327 * denote the same package path. This happens when Ruby bundler installs an -328 * application's dependencies by running "bundle install". -329 * -330 * @param dependency1 dependency to compare -331 * @param dependency2 dependency to compare -332 * @return true if the the dependencies being analyzed appear to be the -333 * same; otherwise false -334 */ -335 private boolean isSameRubyGem(Dependency dependency1, Dependency dependency2) { -336 if (dependency1 == null || dependency2 == null -337 || !dependency1.getFileName().endsWith(".gemspec") -338 || !dependency2.getFileName().endsWith(".gemspec") -339 || dependency1.getPackagePath() == null -340 || dependency2.getPackagePath() == null) { -341 return false; -342 } -343 if (dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath())) { -344 return true; -345 } -346 -347 return false; -348 } -349 -350 /** -351 * Ruby gems installed by "bundle install" can have zero or more *.gemspec -352 * files, all of which have the same packagePath and should be grouped. If -353 * one of these gemspec is from <parent>/specifications/*.gemspec, because -354 * it is a stub with fully resolved gem meta-data created by Ruby bundler, -355 * this dependency should be the main one. Otherwise, use dependency2 as -356 * main. -357 * -358 * This method returns null if any dependency is not from *.gemspec, or the -359 * two do not have the same packagePath. In this case, they should not be -360 * grouped. -361 * -362 * @param dependency1 dependency to compare -363 * @param dependency2 dependency to compare -364 * @return the main dependency; or null if a gemspec is not included in the -365 * analysis -366 */ -367 private Dependency getMainGemspecDependency(Dependency dependency1, Dependency dependency2) { -368 if (isSameRubyGem(dependency1, dependency2)) { -369 final File lFile = dependency1.getActualFile(); -370 final File left = lFile.getParentFile(); -371 if (left != null && left.getName().equalsIgnoreCase("specifications")) { -372 return dependency1; -373 } -374 return dependency2; -375 } -376 return null; -377 } -378 -379 /** -380 * This is likely a very broken attempt at determining if the 'left' -381 * dependency is the 'core' library in comparison to the 'right' library. -382 * -383 * @param left the dependency to test -384 * @param right the dependency to test against -385 * @return a boolean indicating whether or not the left dependency should be -386 * considered the "core" version. -387 */ -388 boolean isCore(Dependency left, Dependency right) { -389 final String leftName = left.getFileName().toLowerCase(); -390 final String rightName = right.getFileName().toLowerCase(); -391 -392 final boolean returnVal; -393 if (!rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") -394 || rightName.contains("core") && !leftName.contains("core") -395 || rightName.contains("kernel") && !leftName.contains("kernel")) { -396 returnVal = false; -397 } else if (rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && !leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") -398 || !rightName.contains("core") && leftName.contains("core") -399 || !rightName.contains("kernel") && leftName.contains("kernel")) { -400 returnVal = true; -401 // } else if (leftName.matches(".*struts2\\-core.*") && rightName.matches(".*xwork\\-core.*")) { -402 // returnVal = true; -403 // } else if (rightName.matches(".*struts2\\-core.*") && leftName.matches(".*xwork\\-core.*")) { -404 // returnVal = false; -405 } else { -406 /* -407 * considered splitting the names up and comparing the components, -408 * but decided that the file name length should be sufficient as the -409 * "core" component, if this follows a normal naming protocol should -410 * be shorter: -411 * axis2-saaj-1.4.1.jar -412 * axis2-1.4.1.jar <----- -413 * axis2-kernel-1.4.1.jar -414 */ -415 returnVal = leftName.length() <= rightName.length(); -416 } -417 LOGGER.debug("IsCore={} ({}, {})", returnVal, left.getFileName(), right.getFileName()); -418 return returnVal; -419 } -420 -421 /** -422 * Compares the SHA1 hashes of two dependencies to determine if they are -423 * equal. -424 * -425 * @param dependency1 a dependency object to compare -426 * @param dependency2 a dependency object to compare -427 * @return true if the sha1 hashes of the two dependencies match; otherwise -428 * false -429 */ -430 private boolean hashesMatch(Dependency dependency1, Dependency dependency2) { -431 if (dependency1 == null || dependency2 == null || dependency1.getSha1sum() == null || dependency2.getSha1sum() == null) { -432 return false; -433 } -434 return dependency1.getSha1sum().equals(dependency2.getSha1sum()); -435 } -436 -437 /** -438 * Determines if the jar is shaded and the created pom.xml identified the -439 * same CPE as the jar - if so, the pom.xml dependency should be removed. -440 * -441 * @param dependency a dependency to check -442 * @param nextDependency another dependency to check -443 * @return true if on of the dependencies is a pom.xml and the identifiers -444 * between the two collections match; otherwise false -445 */ -446 private boolean isShadedJar(Dependency dependency, Dependency nextDependency) { -447 final String mainName = dependency.getFileName().toLowerCase(); -448 final String nextName = nextDependency.getFileName().toLowerCase(); -449 if (mainName.endsWith(".jar") && nextName.endsWith("pom.xml")) { -450 return dependency.getIdentifiers().containsAll(nextDependency.getIdentifiers()); -451 } else if (nextName.endsWith(".jar") && mainName.endsWith("pom.xml")) { -452 return nextDependency.getIdentifiers().containsAll(dependency.getIdentifiers()); -453 } -454 return false; -455 } -456 -457 /** -458 * Determines which path is shortest; if path lengths are equal then we use -459 * compareTo of the string method to determine if the first path is smaller. -460 * -461 * @param left the first path to compare -462 * @param right the second path to compare -463 * @return <code>true</code> if the leftPath is the shortest; otherwise -464 * <code>false</code> -465 */ -466 protected boolean firstPathIsShortest(String left, String right) { -467 final String leftPath = left.replace('\\', '/'); -468 final String rightPath = right.replace('\\', '/'); -469 -470 final int leftCount = countChar(leftPath, '/'); -471 final int rightCount = countChar(rightPath, '/'); -472 if (leftCount == rightCount) { -473 return leftPath.compareTo(rightPath) <= 0; -474 } else { -475 return leftCount < rightCount; -476 } -477 } -478 -479 /** -480 * Counts the number of times the character is present in the string. -481 * -482 * @param string the string to count the characters in -483 * @param c the character to count -484 * @return the number of times the character is present in the string -485 */ -486 private int countChar(String string, char c) { -487 int count = 0; -488 final int max = string.length(); -489 for (int i = 0; i < max; i++) { -490 if (c == string.charAt(i)) { -491 count++; -492 } -493 } -494 return count; -495 } -496 -497 /** -498 * Checks if the given file path is contained within a war or ear file. -499 * -500 * @param filePath the file path to check -501 * @return true if the path contains '.war\' or '.ear\'. -502 */ -503 private boolean containedInWar(String filePath) { -504 return filePath == null ? false : filePath.matches(".*\\.(ear|war)[\\\\/].*"); -505 } -506 } +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 +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. +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> +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; +428 } +429 return null; +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. +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 }
    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 623b7e3ac..026d40df0 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.html @@ -78,52 +78,54 @@ 70 /** 71 * Python init files 72 */ -73 private static final NameFileFilter IGNORED_FILES = new NameFileFilter(new String[]{ -74 "__init__.py", -75 "__init__.pyc", -76 "__init__.pyo", -77 }); -78 -79 /** -80 * Collects information about the file name. -81 * -82 * @param dependency the dependency to analyze. -83 * @param engine the engine that is scanning the dependencies -84 * @throws AnalysisException is thrown if there is an error reading the JAR -85 * file. -86 */ -87 @Override -88 public void analyze(Dependency dependency, Engine engine) throws AnalysisException { -89 -90 //strip any path information that may get added by ArchiveAnalyzer, etc. -91 final File f = dependency.getActualFile(); -92 final String fileName = FilenameUtils.removeExtension(f.getName()); -93 -94 //add version evidence -95 final DependencyVersion version = DependencyVersionUtil.parseVersion(fileName); -96 if (version != null) { -97 // If the version number is just a number like 2 or 23, reduce the confidence -98 // a shade. This should hopefully correct for cases like log4j.jar or -99 // struts2-core.jar -100 if (version.getVersionParts() == null || version.getVersionParts().size() < 2) { -101 dependency.getVersionEvidence().addEvidence("file", "name", -102 version.toString(), Confidence.MEDIUM); -103 } else { -104 dependency.getVersionEvidence().addEvidence("file", "version", -105 version.toString(), Confidence.HIGHEST); -106 } -107 dependency.getVersionEvidence().addEvidence("file", "name", -108 fileName, Confidence.MEDIUM); -109 } -110 -111 if (!IGNORED_FILES.accept(f)) { -112 dependency.getProductEvidence().addEvidence("file", "name", -113 fileName, Confidence.HIGH); -114 dependency.getVendorEvidence().addEvidence("file", "name", -115 fileName, Confidence.HIGH); -116 } -117 } -118 } +73 //CSOFF: WhitespaceAfter +74 private static final NameFileFilter IGNORED_FILES = new NameFileFilter(new String[]{ +75 "__init__.py", +76 "__init__.pyc", +77 "__init__.pyo",}); +78 //CSON: WhitespaceAfter +79 +80 /** +81 * Collects information about the file name. +82 * +83 * @param dependency the dependency to analyze. +84 * @param engine the engine that is scanning the dependencies +85 * @throws AnalysisException is thrown if there is an error reading the JAR +86 * file. +87 */ +88 @Override +89 public void analyze(Dependency dependency, Engine engine) throws AnalysisException { +90 +91 //strip any path information that may get added by ArchiveAnalyzer, etc. +92 final File f = dependency.getActualFile(); +93 final String fileName = FilenameUtils.removeExtension(f.getName()); +94 +95 //add version evidence +96 final DependencyVersion version = DependencyVersionUtil.parseVersion(fileName); +97 final String packageName = DependencyVersionUtil.parsePreVersion(fileName); +98 if (version != null) { +99 // If the version number is just a number like 2 or 23, reduce the confidence +100 // a shade. This should hopefully correct for cases like log4j.jar or +101 // struts2-core.jar +102 if (version.getVersionParts() == null || version.getVersionParts().size() < 2) { +103 dependency.getVersionEvidence().addEvidence("file", "version", +104 version.toString(), Confidence.MEDIUM); +105 } else { +106 dependency.getVersionEvidence().addEvidence("file", "version", +107 version.toString(), Confidence.HIGHEST); +108 } +109 dependency.getVersionEvidence().addEvidence("file", "name", +110 packageName, Confidence.MEDIUM); +111 } +112 +113 if (!IGNORED_FILES.accept(f)) { +114 dependency.getProductEvidence().addEvidence("file", "name", +115 packageName, Confidence.HIGH); +116 dependency.getVendorEvidence().addEvidence("file", "name", +117 packageName, Confidence.HIGH); +118 } +119 } +120 }
    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 3cd496f97..0871b68a1 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/HintAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/HintAnalyzer.html @@ -162,203 +162,213 @@ 154 for (Evidence e : hint.getAddProduct()) { 155 dependency.getProductEvidence().addEvidence(e); 156 } -157 } -158 } -159 -160 final Iterator<Evidence> itr = dependency.getVendorEvidence().iterator(); -161 final List<Evidence> newEntries = new ArrayList<Evidence>(); -162 while (itr.hasNext()) { -163 final Evidence e = itr.next(); -164 for (VendorDuplicatingHintRule dhr : hints.getVendorDuplicatingHintRules()) { -165 if (dhr.getValue().equalsIgnoreCase(e.getValue(false))) { -166 newEntries.add(new Evidence(e.getSource() + " (hint)", -167 e.getName(), dhr.getDuplicate(), e.getConfidence())); -168 } -169 } -170 } -171 for (Evidence e : newEntries) { -172 dependency.getVendorEvidence().addEvidence(e); +157 for (Evidence e : hint.getAddVersion()) { +158 dependency.getVersionEvidence().addEvidence(e); +159 } +160 } +161 } +162 +163 final Iterator<Evidence> itr = dependency.getVendorEvidence().iterator(); +164 final List<Evidence> newEntries = new ArrayList<Evidence>(); +165 while (itr.hasNext()) { +166 final Evidence e = itr.next(); +167 for (VendorDuplicatingHintRule dhr : hints.getVendorDuplicatingHintRules()) { +168 if (dhr.getValue().equalsIgnoreCase(e.getValue(false))) { +169 newEntries.add(new Evidence(e.getSource() + " (hint)", +170 e.getName(), dhr.getDuplicate(), e.getConfidence())); +171 } +172 } 173 } -174 -175 //<editor-fold defaultstate="collapsed" desc="Old implementation"> -176 /* -177 final Evidence springTest1 = new Evidence("Manifest", -178 "Implementation-Title", -179 "Spring Framework", -180 Confidence.HIGH); -181 -182 final Evidence springTest2 = new Evidence("Manifest", -183 "Implementation-Title", -184 "org.springframework.core", -185 Confidence.HIGH); -186 -187 final Evidence springTest3 = new Evidence("Manifest", -188 "Implementation-Title", -189 "spring-core", -190 Confidence.HIGH); -191 -192 final Evidence springTest4 = new Evidence("jar", -193 "package name", -194 "springframework", -195 Confidence.LOW); -196 -197 final Evidence springSecurityTest1 = new Evidence("Manifest", -198 "Bundle-Name", -199 "Spring Security Core", -200 Confidence.MEDIUM); -201 -202 final Evidence springSecurityTest2 = new Evidence("pom", -203 "artifactid", -204 "spring-security-core", -205 Confidence.HIGH); -206 -207 final Evidence symfony = new Evidence("composer.lock", -208 "vendor", -209 "symfony", -210 Confidence.HIGHEST); -211 -212 final Evidence zendframeworkVendor = new Evidence("composer.lock", -213 "vendor", -214 "zendframework", -215 Confidence.HIGHEST); -216 -217 final Evidence zendframeworkProduct = new Evidence("composer.lock", -218 "product", -219 "zendframework", -220 Confidence.HIGHEST); -221 -222 //springsource/vware problem -223 final Set<Evidence> product = dependency.getProductEvidence().getEvidence(); -224 final Set<Evidence> vendor = dependency.getVendorEvidence().getEvidence(); -225 -226 if (product.contains(springTest1) || product.contains(springTest2) || product.contains(springTest3) -227 || (dependency.getFileName().contains("spring") && product.contains(springTest4))) { -228 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource spring framework", Confidence.HIGH); -229 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "SpringSource", Confidence.HIGH); -230 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH); -231 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "pivotal", Confidence.HIGH); -232 } -233 -234 if (vendor.contains(springTest4)) { -235 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource_spring_framework", Confidence.HIGH); -236 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH); -237 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "pivotal", Confidence.HIGH); -238 } -239 -240 if (product.contains(springSecurityTest1) || product.contains(springSecurityTest2)) { -241 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource_spring_security", Confidence.HIGH); -242 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "SpringSource", Confidence.HIGH); -243 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH); -244 } -245 -246 if (vendor.contains(symfony)) { -247 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "sensiolabs", Confidence.HIGHEST); -248 } -249 -250 if (vendor.contains(zendframeworkVendor)) { -251 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "zend", Confidence.HIGHEST); -252 } -253 -254 if (product.contains(zendframeworkProduct)) { -255 dependency.getProductEvidence().addEvidence("hint analyzer", "vendor", "zend_framework", Confidence.HIGHEST); -256 } -257 -258 //sun/oracle problem -259 final Iterator<Evidence> itr = dependency.getVendorEvidence().iterator(); -260 final List<Evidence> newEntries = new ArrayList<Evidence>(); -261 while (itr.hasNext()) { -262 final Evidence e = itr.next(); -263 if ("sun".equalsIgnoreCase(e.getValue(false))) { -264 final Evidence newEvidence = new Evidence(e.getSource() + " (hint)", e.getName(), "oracle", e.getConfidence()); -265 newEntries.add(newEvidence); -266 } else if ("oracle".equalsIgnoreCase(e.getValue(false))) { -267 final Evidence newEvidence = new Evidence(e.getSource() + " (hint)", e.getName(), "sun", e.getConfidence()); +174 for (Evidence e : newEntries) { +175 dependency.getVendorEvidence().addEvidence(e); +176 } +177 +178 //<editor-fold defaultstate="collapsed" desc="Old implementation"> +179 /* +180 final Evidence springTest1 = new Evidence("Manifest", +181 "Implementation-Title", +182 "Spring Framework", +183 Confidence.HIGH); +184 +185 final Evidence springTest2 = new Evidence("Manifest", +186 "Implementation-Title", +187 "org.springframework.core", +188 Confidence.HIGH); +189 +190 final Evidence springTest3 = new Evidence("Manifest", +191 "Implementation-Title", +192 "spring-core", +193 Confidence.HIGH); +194 +195 final Evidence springTest4 = new Evidence("jar", +196 "package name", +197 "springframework", +198 Confidence.LOW); +199 +200 final Evidence springSecurityTest1 = new Evidence("Manifest", +201 "Bundle-Name", +202 "Spring Security Core", +203 Confidence.MEDIUM); +204 +205 final Evidence springSecurityTest2 = new Evidence("pom", +206 "artifactid", +207 "spring-security-core", +208 Confidence.HIGH); +209 +210 final Evidence symfony = new Evidence("composer.lock", +211 "vendor", +212 "symfony", +213 Confidence.HIGHEST); +214 +215 final Evidence zendframeworkVendor = new Evidence("composer.lock", +216 "vendor", +217 "zendframework", +218 Confidence.HIGHEST); +219 +220 final Evidence zendframeworkProduct = new Evidence("composer.lock", +221 "product", +222 "zendframework", +223 Confidence.HIGHEST); +224 +225 //springsource/vware problem +226 final Set<Evidence> product = dependency.getProductEvidence().getEvidence(); +227 final Set<Evidence> vendor = dependency.getVendorEvidence().getEvidence(); +228 +229 if (product.contains(springTest1) || product.contains(springTest2) || product.contains(springTest3) +230 || (dependency.getFileName().contains("spring") && product.contains(springTest4))) { +231 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource spring framework", Confidence.HIGH); +232 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "SpringSource", Confidence.HIGH); +233 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH); +234 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "pivotal", Confidence.HIGH); +235 } +236 +237 if (vendor.contains(springTest4)) { +238 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource_spring_framework", Confidence.HIGH); +239 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH); +240 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "pivotal", Confidence.HIGH); +241 } +242 +243 if (product.contains(springSecurityTest1) || product.contains(springSecurityTest2)) { +244 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource_spring_security", Confidence.HIGH); +245 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "SpringSource", Confidence.HIGH); +246 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH); +247 } +248 +249 if (vendor.contains(symfony)) { +250 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "sensiolabs", Confidence.HIGHEST); +251 } +252 +253 if (vendor.contains(zendframeworkVendor)) { +254 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "zend", Confidence.HIGHEST); +255 } +256 +257 if (product.contains(zendframeworkProduct)) { +258 dependency.getProductEvidence().addEvidence("hint analyzer", "vendor", "zend_framework", Confidence.HIGHEST); +259 } +260 +261 //sun/oracle problem +262 final Iterator<Evidence> itr = dependency.getVendorEvidence().iterator(); +263 final List<Evidence> newEntries = new ArrayList<Evidence>(); +264 while (itr.hasNext()) { +265 final Evidence e = itr.next(); +266 if ("sun".equalsIgnoreCase(e.getValue(false))) { +267 final Evidence newEvidence = new Evidence(e.getSource() + " (hint)", e.getName(), "oracle", e.getConfidence()); 268 newEntries.add(newEvidence); -269 } -270 } -271 for (Evidence e : newEntries) { -272 dependency.getVendorEvidence().addEvidence(e); +269 } else if ("oracle".equalsIgnoreCase(e.getValue(false))) { +270 final Evidence newEvidence = new Evidence(e.getSource() + " (hint)", e.getName(), "sun", e.getConfidence()); +271 newEntries.add(newEvidence); +272 } 273 } -274 */ -275 //</editor-fold> -276 } -277 -278 /** -279 * Loads the hint rules file. -280 * -281 * @throws HintParseException thrown if the XML cannot be parsed. -282 */ -283 private void loadHintRules() throws HintParseException { -284 final HintParser parser = new HintParser(); -285 File file = null; -286 try { -287 hints = parser.parseHints(this.getClass().getClassLoader().getResourceAsStream(HINT_RULE_FILE_NAME)); -288 } catch (HintParseException ex) { -289 LOGGER.error("Unable to parse the base hint data file"); -290 LOGGER.debug("Unable to parse the base hint data file", ex); -291 } catch (SAXException ex) { +274 for (Evidence e : newEntries) { +275 dependency.getVendorEvidence().addEvidence(e); +276 } +277 */ +278 //</editor-fold> +279 } +280 +281 /** +282 * Loads the hint rules file. +283 * +284 * @throws HintParseException thrown if the XML cannot be parsed. +285 */ +286 private void loadHintRules() throws HintParseException { +287 final HintParser parser = new HintParser(); +288 File file = null; +289 try { +290 hints = parser.parseHints(this.getClass().getClassLoader().getResourceAsStream(HINT_RULE_FILE_NAME)); +291 } catch (HintParseException ex) { 292 LOGGER.error("Unable to parse the base hint data file"); 293 LOGGER.debug("Unable to parse the base hint data file", ex); -294 } -295 final String filePath = Settings.getString(Settings.KEYS.HINTS_FILE); -296 if (filePath == null) { -297 return; -298 } -299 boolean deleteTempFile = false; -300 try { -301 final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE); -302 if (uriRx.matcher(filePath).matches()) { -303 deleteTempFile = true; -304 file = FileUtils.getTempFile("hint", "xml"); -305 final URL url = new URL(filePath); -306 try { -307 Downloader.fetchFile(url, file, false); -308 } catch (DownloadFailedException ex) { -309 Downloader.fetchFile(url, file, true); -310 } -311 } else { -312 file = new File(filePath); -313 if (!file.exists()) { -314 final InputStream fromClasspath = this.getClass().getClassLoader().getResourceAsStream(filePath); -315 if (fromClasspath != null) { -316 deleteTempFile = true; -317 file = FileUtils.getTempFile("hint", "xml"); -318 try { -319 org.apache.commons.io.FileUtils.copyInputStreamToFile(fromClasspath, file); -320 } catch (IOException ex) { -321 throw new HintParseException("Unable to locate suppressions file in classpath", ex); -322 } -323 } -324 } -325 } -326 -327 if (file != null) { -328 try { -329 final Hints newHints = parser.parseHints(file); -330 hints.getHintRules().addAll(newHints.getHintRules()); -331 hints.getVendorDuplicatingHintRules().addAll(newHints.getVendorDuplicatingHintRules()); -332 LOGGER.debug("{} hint rules were loaded.", hints.getHintRules().size()); -333 LOGGER.debug("{} duplicating hint rules were loaded.", hints.getVendorDuplicatingHintRules().size()); -334 } catch (HintParseException ex) { -335 LOGGER.warn("Unable to parse hint rule xml file '{}'", file.getPath()); -336 LOGGER.warn(ex.getMessage()); -337 LOGGER.debug("", ex); -338 throw ex; -339 } -340 } -341 } catch (DownloadFailedException ex) { -342 throw new HintParseException("Unable to fetch the configured hint file", ex); -343 } catch (MalformedURLException ex) { -344 throw new HintParseException("Configured hint file has an invalid URL", ex); -345 } catch (IOException ex) { -346 throw new HintParseException("Unable to create temp file for hints", ex); -347 } finally { -348 if (deleteTempFile && file != null) { -349 FileUtils.delete(file); +294 } catch (SAXException ex) { +295 LOGGER.error("Unable to parse the base hint data file"); +296 LOGGER.debug("Unable to parse the base hint data file", ex); +297 } +298 final String filePath = Settings.getString(Settings.KEYS.HINTS_FILE); +299 if (filePath == null) { +300 return; +301 } +302 boolean deleteTempFile = false; +303 try { +304 final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE); +305 if (uriRx.matcher(filePath).matches()) { +306 deleteTempFile = true; +307 file = FileUtils.getTempFile("hint", "xml"); +308 final URL url = new URL(filePath); +309 try { +310 Downloader.fetchFile(url, file, false); +311 } catch (DownloadFailedException ex) { +312 Downloader.fetchFile(url, file, true); +313 } +314 } else { +315 file = new File(filePath); +316 if (!file.exists()) { +317 InputStream fromClasspath = null; +318 try { +319 fromClasspath = this.getClass().getClassLoader().getResourceAsStream(filePath); +320 if (fromClasspath != null) { +321 deleteTempFile = true; +322 file = FileUtils.getTempFile("hint", "xml"); +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); +327 } +328 } +329 } finally { +330 if (fromClasspath != null) { +331 fromClasspath.close(); +332 } +333 } +334 } +335 } +336 +337 if (file != null) { +338 try { +339 final Hints newHints = parser.parseHints(file); +340 hints.getHintRules().addAll(newHints.getHintRules()); +341 hints.getVendorDuplicatingHintRules().addAll(newHints.getVendorDuplicatingHintRules()); +342 LOGGER.debug("{} hint rules were loaded.", hints.getHintRules().size()); +343 LOGGER.debug("{} duplicating hint rules were loaded.", hints.getVendorDuplicatingHintRules().size()); +344 } catch (HintParseException ex) { +345 LOGGER.warn("Unable to parse hint rule xml file '{}'", file.getPath()); +346 LOGGER.warn(ex.getMessage()); +347 LOGGER.debug("", ex); +348 throw ex; +349 } 350 } -351 } -352 } -353 } +351 } catch (DownloadFailedException ex) { +352 throw new HintParseException("Unable to fetch the configured hint file", ex); +353 } catch (MalformedURLException ex) { +354 throw new HintParseException("Configured hint file has an invalid URL", ex); +355 } catch (IOException ex) { +356 throw new HintParseException("Unable to create temp file for hints", ex); +357 } finally { +358 if (deleteTempFile && file != null) { +359 FileUtils.delete(file); +360 } +361 } +362 } +363 }
    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 197720596..21f77be2a 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/JarAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/JarAnalyzer.html @@ -333,396 +333,396 @@ 325 } else { 326 pom = PomUtils.readPom(externalPom); 327 } -328 pom.processProperties(pomProperties); -329 foundSomething |= setPomEvidence(dependency, pom, classes); -330 } -331 } catch (AnalysisException ex) { -332 LOGGER.warn("An error occurred while analyzing '{}'.", dependency.getActualFilePath()); -333 LOGGER.trace("", ex); -334 } -335 } -336 return foundSomething; -337 } -338 -339 /** -340 * Given a path to a pom.xml within a JarFile, this method attempts to load -341 * a sibling pom.properties if one exists. -342 * -343 * @param path the path to the pom.xml within the JarFile -344 * @param jar the JarFile to load the pom.properties from -345 * @return a Properties object or null if no pom.properties was found -346 * @throws IOException thrown if there is an exception reading the -347 * pom.properties -348 */ -349 private Properties retrievePomProperties(String path, final JarFile jar) throws IOException { -350 Properties pomProperties = null; -351 final String propPath = path.substring(0, path.length() - 7) + "pom.properies"; -352 final ZipEntry propEntry = jar.getEntry(propPath); -353 if (propEntry != null) { -354 Reader reader = null; -355 try { -356 reader = new InputStreamReader(jar.getInputStream(propEntry), "UTF-8"); -357 pomProperties = new Properties(); -358 pomProperties.load(reader); -359 LOGGER.debug("Read pom.properties: {}", propPath); -360 } finally { -361 if (reader != null) { -362 try { -363 reader.close(); -364 } catch (IOException ex) { -365 LOGGER.trace("close error", ex); -366 } -367 } -368 } -369 } -370 return pomProperties; -371 } -372 -373 /** -374 * Searches a JarFile for pom.xml entries and returns a listing of these -375 * entries. -376 * -377 * @param jar the JarFile to search -378 * @return a list of pom.xml entries -379 * @throws IOException thrown if there is an exception reading a JarEntry -380 */ -381 private List<String> retrievePomListing(final JarFile jar) throws IOException { -382 final List<String> pomEntries = new ArrayList<String>(); -383 final Enumeration<JarEntry> entries = jar.entries(); -384 while (entries.hasMoreElements()) { -385 final JarEntry entry = entries.nextElement(); -386 final String entryName = (new File(entry.getName())).getName().toLowerCase(); -387 if (!entry.isDirectory() && "pom.xml".equals(entryName)) { -388 LOGGER.trace("POM Entry found: {}", entry.getName()); -389 pomEntries.add(entry.getName()); -390 } -391 } -392 return pomEntries; -393 } -394 -395 /** -396 * Retrieves the specified POM from a jar file and converts it to a Model. -397 * -398 * @param path the path to the pom.xml file within the jar file -399 * @param jar the jar file to extract the pom from -400 * @param dependency the dependency being analyzed -401 * @return returns the POM object -402 * @throws AnalysisException is thrown if there is an exception extracting -403 * or parsing the POM {@link org.owasp.dependencycheck.xml.pom.Model} object -404 */ -405 private Model extractPom(String path, JarFile jar, Dependency dependency) throws AnalysisException { -406 InputStream input = null; -407 FileOutputStream fos = null; -408 final File tmpDir = getNextTempDirectory(); -409 final File file = new File(tmpDir, "pom.xml"); -410 try { -411 final ZipEntry entry = jar.getEntry(path); -412 input = jar.getInputStream(entry); -413 fos = new FileOutputStream(file); -414 IOUtils.copy(input, fos); -415 dependency.setActualFilePath(file.getAbsolutePath()); -416 } catch (IOException ex) { -417 LOGGER.warn("An error occurred reading '{}' from '{}'.", path, dependency.getFilePath()); -418 LOGGER.error("", ex); -419 } finally { -420 closeStream(fos); -421 closeStream(input); -422 } -423 return PomUtils.readPom(file); -424 } -425 -426 /** -427 * Silently closes an input stream ignoring errors. -428 * -429 * @param stream an input stream to close -430 */ -431 private void closeStream(InputStream stream) { -432 if (stream != null) { -433 try { -434 stream.close(); -435 } catch (IOException ex) { -436 LOGGER.trace("", ex); -437 } -438 } -439 } -440 -441 /** -442 * Silently closes an output stream ignoring errors. -443 * -444 * @param stream an output stream to close -445 */ -446 private void closeStream(OutputStream stream) { -447 if (stream != null) { -448 try { -449 stream.close(); -450 } catch (IOException ex) { -451 LOGGER.trace("", ex); -452 } -453 } -454 } -455 -456 /** -457 * Sets evidence from the pom on the supplied dependency. -458 * -459 * @param dependency the dependency to set data on -460 * @param pom the information from the pom -461 * @param classes a collection of ClassNameInformation - containing data -462 * about the fully qualified class names within the JAR file being analyzed -463 * @return true if there was evidence within the pom that we could use; -464 * otherwise false -465 */ -466 public static boolean setPomEvidence(Dependency dependency, Model pom, List<ClassNameInformation> classes) { -467 boolean foundSomething = false; -468 boolean addAsIdentifier = true; -469 if (pom == null) { -470 return foundSomething; -471 } -472 String groupid = pom.getGroupId(); -473 String parentGroupId = pom.getParentGroupId(); -474 String artifactid = pom.getArtifactId(); -475 String parentArtifactId = pom.getParentArtifactId(); -476 String version = pom.getVersion(); -477 String parentVersion = pom.getParentVersion(); -478 -479 if ("org.sonatype.oss".equals(parentGroupId) && "oss-parent".equals(parentArtifactId)) { -480 parentGroupId = null; -481 parentArtifactId = null; -482 parentVersion = null; -483 } -484 -485 if ((groupid == null || groupid.isEmpty()) && parentGroupId != null && !parentGroupId.isEmpty()) { -486 groupid = parentGroupId; -487 } -488 -489 final String originalGroupID = groupid; -490 if (groupid.startsWith("org.") || groupid.startsWith("com.")) { -491 groupid = groupid.substring(4); +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 if ((artifactid == null || artifactid.isEmpty()) && parentArtifactId != null && !parentArtifactId.isEmpty()) { -495 artifactid = parentArtifactId; -496 } -497 -498 final String originalArtifactID = artifactid; -499 if (artifactid.startsWith("org.") || artifactid.startsWith("com.")) { -500 artifactid = artifactid.substring(4); +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 if ((version == null || version.isEmpty()) && parentVersion != null && !parentVersion.isEmpty()) { -504 version = parentVersion; -505 } -506 -507 if (groupid != null && !groupid.isEmpty()) { -508 foundSomething = true; -509 dependency.getVendorEvidence().addEvidence("pom", "groupid", groupid, Confidence.HIGHEST); -510 dependency.getProductEvidence().addEvidence("pom", "groupid", groupid, Confidence.LOW); -511 addMatchingValues(classes, groupid, dependency.getVendorEvidence()); -512 addMatchingValues(classes, groupid, dependency.getProductEvidence()); -513 if (parentGroupId != null && !parentGroupId.isEmpty() && !parentGroupId.equals(groupid)) { -514 dependency.getVendorEvidence().addEvidence("pom", "parent-groupid", parentGroupId, Confidence.MEDIUM); -515 dependency.getProductEvidence().addEvidence("pom", "parent-groupid", parentGroupId, Confidence.LOW); -516 addMatchingValues(classes, parentGroupId, dependency.getVendorEvidence()); -517 addMatchingValues(classes, parentGroupId, dependency.getProductEvidence()); -518 } -519 } else { -520 addAsIdentifier = false; -521 } -522 -523 if (artifactid != null && !artifactid.isEmpty()) { -524 foundSomething = true; -525 dependency.getProductEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.HIGHEST); -526 dependency.getVendorEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.LOW); -527 addMatchingValues(classes, artifactid, dependency.getVendorEvidence()); -528 addMatchingValues(classes, artifactid, dependency.getProductEvidence()); -529 if (parentArtifactId != null && !parentArtifactId.isEmpty() && !parentArtifactId.equals(artifactid)) { -530 dependency.getProductEvidence().addEvidence("pom", "parent-artifactid", parentArtifactId, Confidence.MEDIUM); -531 dependency.getVendorEvidence().addEvidence("pom", "parent-artifactid", parentArtifactId, Confidence.LOW); -532 addMatchingValues(classes, parentArtifactId, dependency.getVendorEvidence()); -533 addMatchingValues(classes, parentArtifactId, dependency.getProductEvidence()); -534 } -535 } else { -536 addAsIdentifier = false; -537 } -538 -539 if (version != null && !version.isEmpty()) { -540 foundSomething = true; -541 dependency.getVersionEvidence().addEvidence("pom", "version", version, Confidence.HIGHEST); -542 if (parentVersion != null && !parentVersion.isEmpty() && !parentVersion.equals(version)) { -543 dependency.getVersionEvidence().addEvidence("pom", "parent-version", version, Confidence.LOW); -544 } -545 } else { -546 addAsIdentifier = false; -547 } -548 -549 if (addAsIdentifier) { -550 dependency.addIdentifier("maven", String.format("%s:%s:%s", originalGroupID, originalArtifactID, version), null, Confidence.HIGH); -551 } -552 -553 // org name -554 final String org = pom.getOrganization(); -555 if (org != null && !org.isEmpty()) { -556 dependency.getVendorEvidence().addEvidence("pom", "organization name", org, Confidence.HIGH); -557 dependency.getProductEvidence().addEvidence("pom", "organization name", org, Confidence.LOW); -558 addMatchingValues(classes, org, dependency.getVendorEvidence()); -559 addMatchingValues(classes, org, dependency.getProductEvidence()); -560 } -561 //pom name -562 final String pomName = pom.getName(); -563 if (pomName -564 != null && !pomName.isEmpty()) { -565 foundSomething = true; -566 dependency.getProductEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH); -567 dependency.getVendorEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH); -568 addMatchingValues(classes, pomName, dependency.getVendorEvidence()); -569 addMatchingValues(classes, pomName, dependency.getProductEvidence()); -570 } -571 -572 //Description -573 final String description = pom.getDescription(); -574 if (description != null && !description.isEmpty() && !description.startsWith("POM was created by")) { -575 foundSomething = true; -576 final String trimmedDescription = addDescription(dependency, description, "pom", "description"); -577 addMatchingValues(classes, trimmedDescription, dependency.getVendorEvidence()); -578 addMatchingValues(classes, trimmedDescription, dependency.getProductEvidence()); -579 } -580 -581 final String projectURL = pom.getProjectURL(); -582 if (projectURL != null && !projectURL.trim().isEmpty()) { -583 dependency.getVendorEvidence().addEvidence("pom", "url", projectURL, Confidence.HIGHEST); +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 extractLicense(pom, dependency); -587 return foundSomething; -588 } -589 -590 /** -591 * Analyzes the path information of the classes contained within the -592 * JarAnalyzer to try and determine possible vendor or product names. If any -593 * are found they are stored in the packageVendor and packageProduct -594 * hashSets. -595 * -596 * @param classNames a list of class names -597 * @param dependency a dependency to analyze -598 * @param addPackagesAsEvidence a flag indicating whether or not package -599 * names should be added as evidence. -600 */ -601 protected void analyzePackageNames(List<ClassNameInformation> classNames, -602 Dependency dependency, boolean addPackagesAsEvidence) { -603 final Map<String, Integer> vendorIdentifiers = new HashMap<String, Integer>(); -604 final Map<String, Integer> productIdentifiers = new HashMap<String, Integer>(); -605 analyzeFullyQualifiedClassNames(classNames, vendorIdentifiers, productIdentifiers); -606 -607 final int classCount = classNames.size(); -608 final EvidenceCollection vendor = dependency.getVendorEvidence(); -609 final EvidenceCollection product = dependency.getProductEvidence(); -610 -611 for (Map.Entry<String, Integer> entry : vendorIdentifiers.entrySet()) { -612 final float ratio = entry.getValue() / (float) classCount; -613 if (ratio > 0.5) { -614 //TODO remove weighting -615 vendor.addWeighting(entry.getKey()); -616 if (addPackagesAsEvidence && entry.getKey().length() > 1) { -617 vendor.addEvidence("jar", "package name", entry.getKey(), Confidence.LOW); -618 } -619 } -620 } -621 for (Map.Entry<String, Integer> entry : productIdentifiers.entrySet()) { -622 final float ratio = entry.getValue() / (float) classCount; -623 if (ratio > 0.5) { -624 product.addWeighting(entry.getKey()); -625 if (addPackagesAsEvidence && entry.getKey().length() > 1) { -626 product.addEvidence("jar", "package name", entry.getKey(), Confidence.LOW); -627 } -628 } -629 } -630 } -631 -632 /** -633 * <p> -634 * Reads the manifest from the JAR file and collects the entries. Some -635 * vendorKey entries are:</p> -636 * <ul><li>Implementation Title</li> -637 * <li>Implementation Version</li> <li>Implementation Vendor</li> -638 * <li>Implementation VendorId</li> <li>Bundle Name</li> <li>Bundle -639 * Version</li> <li>Bundle Vendor</li> <li>Bundle Description</li> <li>Main -640 * Class</li> </ul> -641 * However, all but a handful of specific entries are read in. -642 * -643 * @param dependency A reference to the dependency -644 * @param classInformation a collection of class information -645 * @return whether evidence was identified parsing the manifest -646 * @throws IOException if there is an issue reading the JAR file -647 */ -648 protected boolean parseManifest(Dependency dependency, List<ClassNameInformation> classInformation) throws IOException { -649 boolean foundSomething = false; -650 JarFile jar = null; -651 try { -652 jar = new JarFile(dependency.getActualFilePath()); -653 final Manifest manifest = jar.getManifest(); -654 if (manifest == null) { -655 if (!dependency.getFileName().toLowerCase().endsWith("-sources.jar") -656 && !dependency.getFileName().toLowerCase().endsWith("-javadoc.jar") -657 && !dependency.getFileName().toLowerCase().endsWith("-src.jar") -658 && !dependency.getFileName().toLowerCase().endsWith("-doc.jar")) { -659 LOGGER.debug("Jar file '{}' does not contain a manifest.", -660 dependency.getFileName()); -661 } -662 return false; -663 } -664 final EvidenceCollection vendorEvidence = dependency.getVendorEvidence(); -665 final EvidenceCollection productEvidence = dependency.getProductEvidence(); -666 final EvidenceCollection versionEvidence = dependency.getVersionEvidence(); -667 String source = "Manifest"; -668 String specificationVersion = null; -669 boolean hasImplementationVersion = false; -670 Attributes atts = manifest.getMainAttributes(); -671 for (Entry<Object, Object> entry : atts.entrySet()) { -672 String key = entry.getKey().toString(); -673 String value = atts.getValue(key); -674 if (HTML_DETECTION_PATTERN.matcher(value).find()) { -675 value = Jsoup.parse(value).text(); -676 } -677 if (IGNORE_VALUES.contains(value)) { -678 continue; -679 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_TITLE.toString())) { -680 foundSomething = true; -681 productEvidence.addEvidence(source, key, value, Confidence.HIGH); -682 addMatchingValues(classInformation, value, productEvidence); -683 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VERSION.toString())) { -684 hasImplementationVersion = true; +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 versionEvidence.addEvidence(source, key, value, Confidence.HIGH); -687 } else if ("specification-version".equalsIgnoreCase(key)) { -688 specificationVersion = key; -689 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) { +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 vendorEvidence.addEvidence(source, key, value, Confidence.HIGH); -692 addMatchingValues(classInformation, value, vendorEvidence); -693 } else if (key.equalsIgnoreCase(IMPLEMENTATION_VENDOR_ID)) { -694 foundSomething = true; -695 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -696 addMatchingValues(classInformation, value, vendorEvidence); -697 } else if (key.equalsIgnoreCase(BUNDLE_DESCRIPTION)) { -698 foundSomething = true; -699 addDescription(dependency, value, "manifest", key); -700 addMatchingValues(classInformation, value, productEvidence); -701 } else if (key.equalsIgnoreCase(BUNDLE_NAME)) { -702 foundSomething = true; -703 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -704 addMatchingValues(classInformation, value, productEvidence); -705 // //the following caused false positives. -706 // } else if (key.equalsIgnoreCase(BUNDLE_VENDOR)) { -707 // foundSomething = true; -708 // vendorEvidence.addEvidence(source, key, value, Confidence.HIGH); -709 // addMatchingValues(classInformation, value, vendorEvidence); -710 } else if (key.equalsIgnoreCase(BUNDLE_VERSION)) { -711 foundSomething = true; -712 versionEvidence.addEvidence(source, key, value, Confidence.HIGH); -713 } else if (key.equalsIgnoreCase(Attributes.Name.MAIN_CLASS.toString())) { -714 continue; -715 //skipping main class as if this has important information to add -716 // it will be added during class name analysis... if other fields -717 // have the information from the class name then they will get added... +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) 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 423630215..c2b44db91 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NexusAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NexusAnalyzer.html @@ -253,24 +253,25 @@ 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 && !FileUtils.deleteQuietly(pomFile)) { -249 pomFile.deleteOnExit(); -250 } -251 } -252 } -253 } catch (IllegalArgumentException iae) { -254 //dependency.addAnalysisException(new AnalysisException("Invalid SHA-1")); -255 LOGGER.info("invalid sha-1 hash on {}", dependency.getFileName()); -256 } catch (FileNotFoundException fnfe) { -257 //dependency.addAnalysisException(new AnalysisException("Artifact not found on repository")); -258 LOGGER.debug("Artifact not found in repository '{}'", dependency.getFileName()); -259 LOGGER.debug(fnfe.getMessage(), fnfe); -260 } catch (IOException ioe) { -261 //dependency.addAnalysisException(new AnalysisException("Could not connect to repository", ioe)); -262 LOGGER.debug("Could not connect to nexus repository", ioe); -263 } -264 } -265 } +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 }
    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 e9aefa0d9..21cf96edf 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/PythonDistributionAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/PythonDistributionAnalyzer.html @@ -32,9 +32,9 @@ 24 import java.io.FileNotFoundException; 25 import java.io.FilenameFilter; 26 import java.io.IOException; -27 import org.apache.commons.io.filefilter.NameFileFilter; -28 import org.apache.commons.io.filefilter.SuffixFileFilter; -29 import org.apache.commons.io.input.AutoCloseInputStream; +27 import java.io.InputStream; +28 import org.apache.commons.io.filefilter.NameFileFilter; +29 import org.apache.commons.io.filefilter.SuffixFileFilter; 30 import org.apache.commons.lang3.StringUtils; 31 import org.owasp.dependencycheck.Engine; 32 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; @@ -236,168 +236,180 @@ 228 throw new AnalysisException(ex); 229 } 230 -231 collectWheelMetadata( -232 dependency, -233 getMatchingFile(getMatchingFile(temp, folderFilter), -234 metadataFilter)); -235 } -236 -237 /** -238 * Makes sure a usable temporary directory is available. -239 * -240 * @throws InitializationException an AnalyzeException is thrown when the -241 * temp directory cannot be created -242 */ -243 @Override -244 protected void initializeFileTypeAnalyzer() throws InitializationException { -245 try { -246 final File baseDir = Settings.getTempDirectory(); -247 tempFileLocation = File.createTempFile("check", "tmp", baseDir); -248 if (!tempFileLocation.delete()) { -249 setEnabled(false); -250 final String msg = String.format( -251 "Unable to delete temporary file '%s'.", -252 tempFileLocation.getAbsolutePath()); -253 throw new InitializationException(msg); -254 } -255 if (!tempFileLocation.mkdirs()) { -256 setEnabled(false); -257 final String msg = String.format( -258 "Unable to create directory '%s'.", -259 tempFileLocation.getAbsolutePath()); -260 throw new InitializationException(msg); -261 } -262 } catch (IOException ex) { -263 setEnabled(false); -264 throw new InitializationException("Unable to create a temporary file", ex); -265 } -266 } -267 -268 /** -269 * Deletes any files extracted from the Wheel during analysis. -270 */ -271 @Override -272 public void close() { -273 if (tempFileLocation != null && tempFileLocation.exists()) { -274 LOGGER.debug("Attempting to delete temporary files"); -275 final boolean success = FileUtils.delete(tempFileLocation); -276 if (!success) { -277 LOGGER.warn( -278 "Failed to delete some temporary files, see the log for more details"); -279 } -280 } -281 } -282 -283 /** -284 * Gathers evidence from the METADATA file. -285 * -286 * @param dependency the dependency being analyzed -287 * @param file a reference to the manifest/properties file -288 */ -289 private static void collectWheelMetadata(Dependency dependency, File file) { -290 final InternetHeaders headers = getManifestProperties(file); -291 addPropertyToEvidence(headers, dependency.getVersionEvidence(), -292 "Version", Confidence.HIGHEST); -293 addPropertyToEvidence(headers, dependency.getProductEvidence(), "Name", -294 Confidence.HIGHEST); -295 final String url = headers.getHeader("Home-page", null); -296 final EvidenceCollection vendorEvidence = dependency -297 .getVendorEvidence(); -298 if (StringUtils.isNotBlank(url)) { -299 if (UrlStringUtils.isUrl(url)) { -300 vendorEvidence.addEvidence(METADATA, "vendor", url, -301 Confidence.MEDIUM); -302 } -303 } -304 addPropertyToEvidence(headers, vendorEvidence, "Author", Confidence.LOW); -305 final String summary = headers.getHeader("Summary", null); -306 if (StringUtils.isNotBlank(summary)) { -307 JarAnalyzer -308 .addDescription(dependency, summary, METADATA, "summary"); -309 } -310 } -311 -312 /** -313 * Adds a value to the evidence collection. -314 * -315 * @param headers the properties collection -316 * @param evidence the evidence collection to add the value -317 * @param property the property name -318 * @param confidence the confidence of the evidence -319 */ -320 private static void addPropertyToEvidence(InternetHeaders headers, -321 EvidenceCollection evidence, String property, Confidence confidence) { -322 final String value = headers.getHeader(property, null); -323 LOGGER.debug("Property: {}, Value: {}", property, value); -324 if (StringUtils.isNotBlank(value)) { -325 evidence.addEvidence(METADATA, property, value, confidence); -326 } -327 } -328 -329 /** -330 * Returns a list of files that match the given filter, this does not -331 * recursively scan the directory. -332 * -333 * @param folder the folder to filter -334 * @param filter the filter to apply to the files in the directory -335 * @return the list of Files in the directory that match the provided filter -336 */ -337 private static File getMatchingFile(File folder, FilenameFilter filter) { -338 File result = null; -339 final File[] matches = folder.listFiles(filter); -340 if (null != matches && 1 == matches.length) { -341 result = matches[0]; -342 } -343 return result; -344 } -345 -346 /** -347 * Reads the manifest entries from the provided file. -348 * -349 * @param manifest the manifest -350 * @return the manifest entries -351 */ -352 private static InternetHeaders getManifestProperties(File manifest) { -353 final InternetHeaders result = new InternetHeaders(); -354 if (null == manifest) { -355 LOGGER.debug("Manifest file not found."); -356 } else { -357 try { -358 result.load(new AutoCloseInputStream(new BufferedInputStream( -359 new FileInputStream(manifest)))); -360 } catch (MessagingException e) { -361 LOGGER.warn(e.getMessage(), e); -362 } catch (FileNotFoundException e) { -363 LOGGER.warn(e.getMessage(), e); -364 } -365 } -366 return result; -367 } -368 -369 /** -370 * Retrieves the next temporary destination directory for extracting an -371 * archive. -372 * -373 * @return a directory -374 * @throws AnalysisException thrown if unable to create temporary directory -375 */ -376 private File getNextTempDirectory() throws AnalysisException { -377 File directory; -378 -379 // getting an exception for some directories not being able to be -380 // created; might be because the directory already exists? -381 do { -382 dirCount += 1; -383 directory = new File(tempFileLocation, String.valueOf(dirCount)); -384 } while (directory.exists()); -385 if (!directory.mkdirs()) { -386 throw new AnalysisException(String.format( -387 "Unable to create temp directory '%s'.", -388 directory.getAbsolutePath())); -389 } -390 return directory; -391 } -392 } +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 }
    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 ac2dbd5cf..3cd157e12 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.html @@ -31,478 +31,486 @@ 23 import java.io.IOException; 24 import java.io.InputStreamReader; 25 import java.io.UnsupportedEncodingException; -26 import java.util.ArrayList; -27 import java.util.HashMap; -28 import java.util.List; -29 import java.util.Map; -30 import java.nio.charset.Charset; -31 import org.apache.commons.io.FileUtils; -32 import org.owasp.dependencycheck.Engine; -33 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; -34 import org.owasp.dependencycheck.data.nvdcve.CveDB; -35 import org.owasp.dependencycheck.dependency.Confidence; -36 import org.owasp.dependencycheck.dependency.Dependency; -37 import org.owasp.dependencycheck.dependency.Reference; -38 import org.owasp.dependencycheck.dependency.Vulnerability; -39 import org.owasp.dependencycheck.utils.FileFilterBuilder; -40 import org.owasp.dependencycheck.utils.Settings; -41 import org.slf4j.Logger; -42 import org.slf4j.LoggerFactory; -43 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; -44 import org.owasp.dependencycheck.exception.InitializationException; -45 -46 /** -47 * Used to analyze Ruby Bundler Gemspec.lock files utilizing the 3rd party -48 * bundle-audit tool. -49 * -50 * @author Dale Visser -51 */ -52 @Experimental -53 public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer { -54 -55 /** -56 * The logger. -57 */ -58 private static final Logger LOGGER = LoggerFactory.getLogger(RubyBundleAuditAnalyzer.class); -59 -60 /** -61 * The name of the analyzer. -62 */ -63 private static final String ANALYZER_NAME = "Ruby Bundle Audit Analyzer"; -64 -65 /** -66 * The phase that this analyzer is intended to run in. -67 */ -68 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.PRE_INFORMATION_COLLECTION; -69 /** -70 * The filter defining which files will be analyzed. -71 */ -72 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFilenames("Gemfile.lock").build(); -73 /** -74 * Name. -75 */ -76 public static final String NAME = "Name: "; -77 /** -78 * Version. -79 */ -80 public static final String VERSION = "Version: "; -81 /** -82 * Advisory. -83 */ -84 public static final String ADVISORY = "Advisory: "; -85 /** -86 * Criticality. -87 */ -88 public static final String CRITICALITY = "Criticality: "; -89 -90 /** -91 * The DAL. -92 */ -93 private CveDB cvedb; -94 -95 /** -96 * @return a filter that accepts files named Gemfile.lock -97 */ -98 @Override -99 protected FileFilter getFileFilter() { -100 return FILTER; -101 } -102 -103 /** -104 * Launch bundle-audit. -105 * -106 * @param folder directory that contains bundle audit -107 * @return a handle to the process -108 * @throws AnalysisException thrown when there is an issue launching bundle -109 * audit -110 */ -111 private Process launchBundleAudit(File folder) throws AnalysisException { -112 if (!folder.isDirectory()) { -113 throw new AnalysisException(String.format("%s should have been a directory.", folder.getAbsolutePath())); -114 } -115 final List<String> args = new ArrayList<String>(); -116 final String bundleAuditPath = Settings.getString(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH); -117 args.add(null == bundleAuditPath ? "bundle-audit" : bundleAuditPath); -118 args.add("check"); -119 args.add("--verbose"); -120 final ProcessBuilder builder = new ProcessBuilder(args); -121 builder.directory(folder); -122 try { -123 LOGGER.info("Launching: " + args + " from " + folder); -124 return builder.start(); -125 } catch (IOException ioe) { -126 throw new AnalysisException("bundle-audit failure", ioe); -127 } -128 } -129 -130 /** -131 * Initialize the analyzer. In this case, extract GrokAssembly.exe to a -132 * temporary location. -133 * -134 * @throws InitializationException if anything goes wrong -135 */ -136 @Override -137 public void initializeFileTypeAnalyzer() throws InitializationException { -138 try { -139 cvedb = new CveDB(); -140 cvedb.open(); -141 } catch (DatabaseException ex) { -142 LOGGER.warn("Exception opening the database"); -143 LOGGER.debug("error", ex); -144 setEnabled(false); -145 throw new InitializationException("Error connecting to the database", ex); -146 } -147 // Now, need to see if bundle-audit actually runs from this location. -148 Process process = null; -149 try { -150 process = launchBundleAudit(Settings.getTempDirectory()); -151 } catch (AnalysisException ae) { -152 -153 setEnabled(false); -154 cvedb.close(); -155 cvedb = null; -156 final String msg = String.format("Exception from bundle-audit process: %s. Disabling %s", ae.getCause(), ANALYZER_NAME); -157 throw new InitializationException(msg, ae); -158 } catch (IOException ex) { -159 setEnabled(false); -160 throw new InitializationException("Unable to create temporary file, the Ruby Bundle Audit Analyzer will be disabled", ex); -161 } -162 -163 final int exitValue; -164 try { -165 exitValue = process.waitFor(); -166 } catch (InterruptedException ex) { -167 setEnabled(false); -168 final String msg = String.format("Bundle-audit process was interupted. Disabling %s", ANALYZER_NAME); -169 throw new InitializationException(msg); -170 } -171 if (0 == exitValue) { -172 setEnabled(false); -173 final String msg = String.format("Unexpected exit code from bundle-audit process. Disabling %s: %s", ANALYZER_NAME, exitValue); -174 throw new InitializationException(msg); -175 } else { -176 BufferedReader reader = null; -177 try { -178 reader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8")); -179 if (!reader.ready()) { -180 LOGGER.warn("Bundle-audit error stream unexpectedly not ready. Disabling " + ANALYZER_NAME); -181 setEnabled(false); -182 throw new InitializationException("Bundle-audit error stream unexpectedly not ready."); -183 } else { -184 final String line = reader.readLine(); -185 if (line == null || !line.contains("Errno::ENOENT")) { -186 LOGGER.warn("Unexpected bundle-audit output. Disabling {}: {}", ANALYZER_NAME, line); -187 setEnabled(false); -188 throw new InitializationException("Unexpected bundle-audit output."); -189 } -190 } -191 } catch (UnsupportedEncodingException ex) { -192 setEnabled(false); -193 throw new InitializationException("Unexpected bundle-audit encoding.", ex); -194 } catch (IOException ex) { -195 setEnabled(false); -196 throw new InitializationException("Unable to read bundle-audit output.", ex); -197 } finally { -198 if (null != reader) { -199 try { -200 reader.close(); -201 } catch (IOException ex) { -202 LOGGER.debug("Error closing reader", ex); -203 } -204 } -205 } -206 } -207 -208 if (isEnabled()) { -209 LOGGER.info(ANALYZER_NAME + " is enabled. It is necessary to manually run \"bundle-audit update\" " -210 + "occasionally to keep its database up to date."); -211 } -212 } -213 -214 /** -215 * Returns the name of the analyzer. -216 * -217 * @return the name of the analyzer. -218 */ -219 @Override -220 public String getName() { -221 return ANALYZER_NAME; -222 } -223 -224 /** -225 * Returns the phase that the analyzer is intended to run in. -226 * -227 * @return the phase that the analyzer is intended to run in. -228 */ -229 @Override -230 public AnalysisPhase getAnalysisPhase() { -231 return ANALYSIS_PHASE; -232 } -233 -234 /** -235 * Returns the key used in the properties file to reference the analyzer's -236 * enabled property. -237 * -238 * @return the analyzer's enabled property setting key -239 */ -240 @Override -241 protected String getAnalyzerEnabledSettingKey() { -242 return Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED; -243 } -244 -245 /** -246 * If {@link #analyzeFileType(Dependency, Engine)} is called, then we have -247 * successfully initialized, and it will be necessary to disable -248 * {@link RubyGemspecAnalyzer}. -249 */ -250 private boolean needToDisableGemspecAnalyzer = true; -251 -252 /** -253 * Determines if the analyzer can analyze the given file type. -254 * -255 * @param dependency the dependency to determine if it can analyze -256 * @param engine the dependency-check engine -257 * @throws AnalysisException thrown if there is an analysis exception. -258 */ -259 @Override -260 protected void analyzeFileType(Dependency dependency, Engine engine) -261 throws AnalysisException { -262 if (needToDisableGemspecAnalyzer) { -263 boolean failed = true; -264 final String className = RubyGemspecAnalyzer.class.getName(); -265 for (FileTypeAnalyzer analyzer : engine.getFileTypeAnalyzers()) { -266 if (analyzer instanceof RubyBundlerAnalyzer) { -267 ((RubyBundlerAnalyzer) analyzer).setEnabled(false); -268 LOGGER.info("Disabled " + RubyBundlerAnalyzer.class.getName() + " to avoid noisy duplicate results."); -269 } else if (analyzer instanceof RubyGemspecAnalyzer) { -270 ((RubyGemspecAnalyzer) analyzer).setEnabled(false); -271 LOGGER.info("Disabled " + className + " to avoid noisy duplicate results."); -272 failed = false; -273 } -274 } -275 if (failed) { -276 LOGGER.warn("Did not find " + className + '.'); -277 } -278 needToDisableGemspecAnalyzer = false; -279 } -280 final File parentFile = dependency.getActualFile().getParentFile(); -281 final Process process = launchBundleAudit(parentFile); -282 try { -283 process.waitFor(); -284 } catch (InterruptedException ie) { -285 throw new AnalysisException("bundle-audit process interrupted", ie); -286 } -287 BufferedReader rdr = null; -288 BufferedReader errReader = null; -289 try { -290 errReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8")); -291 while (errReader.ready()) { -292 final String error = errReader.readLine(); -293 LOGGER.warn(error); -294 } -295 rdr = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8")); -296 processBundlerAuditOutput(dependency, engine, rdr); -297 } catch (IOException ioe) { -298 LOGGER.warn("bundle-audit failure", ioe); -299 } finally { -300 if (errReader != null) { -301 try { -302 errReader.close(); -303 } catch (IOException ioe) { -304 LOGGER.warn("bundle-audit close failure", ioe); -305 } -306 } -307 if (null != rdr) { -308 try { -309 rdr.close(); -310 } catch (IOException ioe) { -311 LOGGER.warn("bundle-audit close failure", ioe); -312 } -313 } -314 } -315 -316 } -317 -318 /** -319 * Processes the bundler audit output. -320 * -321 * @param original the dependency -322 * @param engine the dependency-check engine -323 * @param rdr the reader of the report -324 * @throws IOException thrown if the report cannot be read. -325 */ -326 private void processBundlerAuditOutput(Dependency original, Engine engine, BufferedReader rdr) throws IOException { -327 final String parentName = original.getActualFile().getParentFile().getName(); -328 final String fileName = original.getFileName(); -329 final String filePath = original.getFilePath(); -330 Dependency dependency = null; -331 Vulnerability vulnerability = null; -332 String gem = null; -333 final Map<String, Dependency> map = new HashMap<String, Dependency>(); -334 boolean appendToDescription = false; -335 while (rdr.ready()) { -336 final String nextLine = rdr.readLine(); -337 if (null == nextLine) { -338 break; -339 } else if (nextLine.startsWith(NAME)) { -340 appendToDescription = false; -341 gem = nextLine.substring(NAME.length()); -342 if (!map.containsKey(gem)) { -343 map.put(gem, createDependencyForGem(engine, parentName, fileName, filePath, gem)); -344 } -345 dependency = map.get(gem); -346 LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine)); -347 } else if (nextLine.startsWith(VERSION)) { -348 vulnerability = createVulnerability(parentName, dependency, gem, nextLine); -349 } else if (nextLine.startsWith(ADVISORY)) { -350 setVulnerabilityName(parentName, dependency, vulnerability, nextLine); -351 } else if (nextLine.startsWith(CRITICALITY)) { -352 addCriticalityToVulnerability(parentName, vulnerability, nextLine); -353 } else if (nextLine.startsWith("URL: ")) { -354 addReferenceToVulnerability(parentName, vulnerability, nextLine); -355 } else if (nextLine.startsWith("Description:")) { -356 appendToDescription = true; -357 if (null != vulnerability) { -358 vulnerability.setDescription("*** Vulnerability obtained from bundle-audit verbose report. " -359 + "Title link may not work. CPE below is guessed. CVSS score is estimated (-1.0 " -360 + " indicates unknown). See link below for full details. *** "); -361 } -362 } else if (appendToDescription) { +26 import java.nio.charset.Charset; +27 import java.util.ArrayList; +28 import java.util.HashMap; +29 import java.util.List; +30 import java.util.Map; +31 +32 import org.apache.commons.io.FileUtils; +33 import org.owasp.dependencycheck.Engine; +34 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; +35 import org.owasp.dependencycheck.data.nvdcve.CveDB; +36 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; +37 import org.owasp.dependencycheck.dependency.Confidence; +38 import org.owasp.dependencycheck.dependency.Dependency; +39 import org.owasp.dependencycheck.dependency.Reference; +40 import org.owasp.dependencycheck.dependency.Vulnerability; +41 import org.owasp.dependencycheck.exception.InitializationException; +42 import org.owasp.dependencycheck.utils.FileFilterBuilder; +43 import org.owasp.dependencycheck.utils.Settings; +44 import org.slf4j.Logger; +45 import org.slf4j.LoggerFactory; +46 +47 /** +48 * Used to analyze Ruby Bundler Gemspec.lock files utilizing the 3rd party +49 * bundle-audit tool. +50 * +51 * @author Dale Visser +52 */ +53 @Experimental +54 public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer { +55 +56 /** +57 * The logger. +58 */ +59 private static final Logger LOGGER = LoggerFactory.getLogger(RubyBundleAuditAnalyzer.class); +60 +61 /** +62 * The name of the analyzer. +63 */ +64 private static final String ANALYZER_NAME = "Ruby Bundle Audit Analyzer"; +65 +66 /** +67 * The phase that this analyzer is intended to run in. +68 */ +69 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.PRE_INFORMATION_COLLECTION; +70 /** +71 * The filter defining which files will be analyzed. +72 */ +73 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFilenames("Gemfile.lock").build(); +74 /** +75 * Name. +76 */ +77 public static final String NAME = "Name: "; +78 /** +79 * Version. +80 */ +81 public static final String VERSION = "Version: "; +82 /** +83 * Advisory. +84 */ +85 public static final String ADVISORY = "Advisory: "; +86 /** +87 * Criticality. +88 */ +89 public static final String CRITICALITY = "Criticality: "; +90 +91 /** +92 * The DAL. +93 */ +94 private CveDB cvedb; +95 +96 /** +97 * @return a filter that accepts files named Gemfile.lock +98 */ +99 @Override +100 protected FileFilter getFileFilter() { +101 return FILTER; +102 } +103 +104 /** +105 * Launch bundle-audit. +106 * +107 * @param folder directory that contains bundle audit +108 * @return a handle to the process +109 * @throws AnalysisException thrown when there is an issue launching bundle +110 * audit +111 */ +112 private Process launchBundleAudit(File folder) throws AnalysisException { +113 if (!folder.isDirectory()) { +114 throw new AnalysisException(String.format("%s should have been a directory.", folder.getAbsolutePath())); +115 } +116 final List<String> args = new ArrayList<String>(); +117 final String bundleAuditPath = Settings.getString(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH); +118 args.add(null == bundleAuditPath ? "bundle-audit" : bundleAuditPath); +119 args.add("check"); +120 args.add("--verbose"); +121 final ProcessBuilder builder = new ProcessBuilder(args); +122 builder.directory(folder); +123 try { +124 LOGGER.info("Launching: " + args + " from " + folder); +125 return builder.start(); +126 } catch (IOException ioe) { +127 throw new AnalysisException("bundle-audit failure", ioe); +128 } +129 } +130 +131 /** +132 * Initialize the analyzer. In this case, extract GrokAssembly.exe to a +133 * temporary location. +134 * +135 * @throws InitializationException if anything goes wrong +136 */ +137 @Override +138 public void initializeFileTypeAnalyzer() throws InitializationException { +139 try { +140 cvedb = new CveDB(); +141 cvedb.open(); +142 } catch (DatabaseException ex) { +143 LOGGER.warn("Exception opening the database"); +144 LOGGER.debug("error", ex); +145 setEnabled(false); +146 throw new InitializationException("Error connecting to the database", ex); +147 } +148 // Now, need to see if bundle-audit actually runs from this location. +149 Process process = null; +150 try { +151 process = launchBundleAudit(Settings.getTempDirectory()); +152 } catch (AnalysisException ae) { +153 +154 setEnabled(false); +155 cvedb.close(); +156 cvedb = null; +157 final String msg = String.format("Exception from bundle-audit process: %s. Disabling %s", ae.getCause(), ANALYZER_NAME); +158 throw new InitializationException(msg, ae); +159 } catch (IOException ex) { +160 setEnabled(false); +161 throw new InitializationException("Unable to create temporary file, the Ruby Bundle Audit Analyzer will be disabled", ex); +162 } +163 +164 final int exitValue; +165 try { +166 exitValue = process.waitFor(); +167 } catch (InterruptedException ex) { +168 setEnabled(false); +169 final String msg = String.format("Bundle-audit process was interupted. Disabling %s", ANALYZER_NAME); +170 throw new InitializationException(msg); +171 } +172 if (0 == exitValue) { +173 setEnabled(false); +174 final String msg = String.format("Unexpected exit code from bundle-audit process. Disabling %s: %s", ANALYZER_NAME, exitValue); +175 throw new InitializationException(msg); +176 } else { +177 BufferedReader reader = null; +178 try { +179 reader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8")); +180 if (!reader.ready()) { +181 LOGGER.warn("Bundle-audit error stream unexpectedly not ready. Disabling " + ANALYZER_NAME); +182 setEnabled(false); +183 throw new InitializationException("Bundle-audit error stream unexpectedly not ready."); +184 } else { +185 final String line = reader.readLine(); +186 if (line == null || !line.contains("Errno::ENOENT")) { +187 LOGGER.warn("Unexpected bundle-audit output. Disabling {}: {}", ANALYZER_NAME, line); +188 setEnabled(false); +189 throw new InitializationException("Unexpected bundle-audit output."); +190 } +191 } +192 } catch (UnsupportedEncodingException ex) { +193 setEnabled(false); +194 throw new InitializationException("Unexpected bundle-audit encoding.", ex); +195 } catch (IOException ex) { +196 setEnabled(false); +197 throw new InitializationException("Unable to read bundle-audit output.", ex); +198 } finally { +199 if (null != reader) { +200 try { +201 reader.close(); +202 } catch (IOException ex) { +203 LOGGER.debug("Error closing reader", ex); +204 } +205 } +206 } +207 } +208 +209 if (isEnabled()) { +210 LOGGER.info(ANALYZER_NAME + " is enabled. It is necessary to manually run \"bundle-audit update\" " +211 + "occasionally to keep its database up to date."); +212 } +213 } +214 +215 /** +216 * Returns the name of the analyzer. +217 * +218 * @return the name of the analyzer. +219 */ +220 @Override +221 public String getName() { +222 return ANALYZER_NAME; +223 } +224 +225 /** +226 * Returns the phase that the analyzer is intended to run in. +227 * +228 * @return the phase that the analyzer is intended to run in. +229 */ +230 @Override +231 public AnalysisPhase getAnalysisPhase() { +232 return ANALYSIS_PHASE; +233 } +234 +235 /** +236 * Returns the key used in the properties file to reference the analyzer's +237 * enabled property. +238 * +239 * @return the analyzer's enabled property setting key +240 */ +241 @Override +242 protected String getAnalyzerEnabledSettingKey() { +243 return Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED; +244 } +245 +246 /** +247 * If {@link #analyzeFileType(Dependency, Engine)} is called, then we have +248 * successfully initialized, and it will be necessary to disable +249 * {@link RubyGemspecAnalyzer}. +250 */ +251 private boolean needToDisableGemspecAnalyzer = true; +252 +253 /** +254 * Determines if the analyzer can analyze the given file type. +255 * +256 * @param dependency the dependency to determine if it can analyze +257 * @param engine the dependency-check engine +258 * @throws AnalysisException thrown if there is an analysis exception. +259 */ +260 @Override +261 protected void analyzeFileType(Dependency dependency, Engine engine) +262 throws AnalysisException { +263 if (needToDisableGemspecAnalyzer) { +264 boolean failed = true; +265 final String className = RubyGemspecAnalyzer.class.getName(); +266 for (FileTypeAnalyzer analyzer : engine.getFileTypeAnalyzers()) { +267 if (analyzer instanceof RubyBundlerAnalyzer) { +268 ((RubyBundlerAnalyzer) analyzer).setEnabled(false); +269 LOGGER.info("Disabled " + RubyBundlerAnalyzer.class.getName() + " to avoid noisy duplicate results."); +270 } else if (analyzer instanceof RubyGemspecAnalyzer) { +271 ((RubyGemspecAnalyzer) analyzer).setEnabled(false); +272 LOGGER.info("Disabled " + className + " to avoid noisy duplicate results."); +273 failed = false; +274 } +275 } +276 if (failed) { +277 LOGGER.warn("Did not find " + className + '.'); +278 } +279 needToDisableGemspecAnalyzer = false; +280 } +281 final File parentFile = dependency.getActualFile().getParentFile(); +282 final Process process = launchBundleAudit(parentFile); +283 final int exitValue; +284 try { +285 exitValue = process.waitFor(); +286 } catch (InterruptedException ie) { +287 throw new AnalysisException("bundle-audit process interrupted", ie); +288 } +289 if (exitValue != 0) { +290 final String msg = String.format("Unexpected exit code from bundle-audit process; exit code: %s", exitValue); +291 throw new AnalysisException(msg); +292 } +293 BufferedReader rdr = null; +294 BufferedReader errReader = null; +295 try { +296 errReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8")); +297 while (errReader.ready()) { +298 final String error = errReader.readLine(); +299 LOGGER.warn(error); +300 } +301 rdr = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8")); +302 processBundlerAuditOutput(dependency, engine, rdr); +303 } catch (IOException ioe) { +304 LOGGER.warn("bundle-audit failure", ioe); +305 } finally { +306 if (errReader != null) { +307 try { +308 errReader.close(); +309 } catch (IOException ioe) { +310 LOGGER.warn("bundle-audit close failure", ioe); +311 } +312 } +313 if (null != rdr) { +314 try { +315 rdr.close(); +316 } catch (IOException ioe) { +317 LOGGER.warn("bundle-audit close failure", ioe); +318 } +319 } +320 } +321 +322 } +323 +324 /** +325 * Processes the bundler audit output. +326 * +327 * @param original the dependency +328 * @param engine the dependency-check engine +329 * @param rdr the reader of the report +330 * @throws IOException thrown if the report cannot be read. +331 */ +332 private void processBundlerAuditOutput(Dependency original, Engine engine, BufferedReader rdr) throws IOException { +333 final String parentName = original.getActualFile().getParentFile().getName(); +334 final String fileName = original.getFileName(); +335 final String filePath = original.getFilePath(); +336 Dependency dependency = null; +337 Vulnerability vulnerability = null; +338 String gem = null; +339 final Map<String, Dependency> map = new HashMap<String, Dependency>(); +340 boolean appendToDescription = false; +341 while (rdr.ready()) { +342 final String nextLine = rdr.readLine(); +343 if (null == nextLine) { +344 break; +345 } else if (nextLine.startsWith(NAME)) { +346 appendToDescription = false; +347 gem = nextLine.substring(NAME.length()); +348 if (!map.containsKey(gem)) { +349 map.put(gem, createDependencyForGem(engine, parentName, fileName, filePath, gem)); +350 } +351 dependency = map.get(gem); +352 LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine)); +353 } else if (nextLine.startsWith(VERSION)) { +354 vulnerability = createVulnerability(parentName, dependency, gem, nextLine); +355 } else if (nextLine.startsWith(ADVISORY)) { +356 setVulnerabilityName(parentName, dependency, vulnerability, nextLine); +357 } else if (nextLine.startsWith(CRITICALITY)) { +358 addCriticalityToVulnerability(parentName, vulnerability, nextLine); +359 } else if (nextLine.startsWith("URL: ")) { +360 addReferenceToVulnerability(parentName, vulnerability, nextLine); +361 } else if (nextLine.startsWith("Description:")) { +362 appendToDescription = true; 363 if (null != vulnerability) { -364 vulnerability.setDescription(vulnerability.getDescription() + nextLine + "\n"); -365 } -366 } -367 } -368 } -369 -370 /** -371 * Sets the vulnerability name. -372 * -373 * @param parentName the parent name -374 * @param dependency the dependency -375 * @param vulnerability the vulnerability -376 * @param nextLine the line to parse -377 */ -378 private void setVulnerabilityName(String parentName, Dependency dependency, Vulnerability vulnerability, String nextLine) { -379 final String advisory = nextLine.substring((ADVISORY.length())); -380 if (null != vulnerability) { -381 vulnerability.setName(advisory); -382 } -383 if (null != dependency) { -384 dependency.getVulnerabilities().add(vulnerability); // needed to wait for vulnerability name to avoid NPE -385 } -386 LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine)); -387 } -388 -389 /** -390 * Adds a reference to the vulnerability. -391 * -392 * @param parentName the parent name -393 * @param vulnerability the vulnerability -394 * @param nextLine the line to parse -395 */ -396 private void addReferenceToVulnerability(String parentName, Vulnerability vulnerability, String nextLine) { -397 final String url = nextLine.substring(("URL: ").length()); -398 if (null != vulnerability) { -399 final Reference ref = new Reference(); -400 ref.setName(vulnerability.getName()); -401 ref.setSource("bundle-audit"); -402 ref.setUrl(url); -403 vulnerability.getReferences().add(ref); -404 } -405 LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine)); -406 } -407 -408 /** -409 * Adds the criticality to the vulnerability -410 * -411 * @param parentName the parent name -412 * @param vulnerability the vulnerability -413 * @param nextLine the line to parse -414 */ -415 private void addCriticalityToVulnerability(String parentName, Vulnerability vulnerability, String nextLine) { -416 if (null != vulnerability) { -417 final String criticality = nextLine.substring(CRITICALITY.length()).trim(); -418 float score = -1.0f; -419 Vulnerability v = null; -420 try { -421 v = cvedb.getVulnerability(vulnerability.getName()); -422 } catch (DatabaseException ex) { -423 LOGGER.debug("Unable to look up vulnerability {}", vulnerability.getName()); -424 } -425 if (v != null) { -426 score = v.getCvssScore(); -427 } else if ("High".equalsIgnoreCase(criticality)) { -428 score = 8.5f; -429 } else if ("Medium".equalsIgnoreCase(criticality)) { -430 score = 5.5f; -431 } else if ("Low".equalsIgnoreCase(criticality)) { -432 score = 2.0f; -433 } -434 vulnerability.setCvssScore(score); -435 } -436 LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine)); -437 } -438 -439 /** -440 * Creates a vulnerability. -441 * -442 * @param parentName the parent name -443 * @param dependency the dependency -444 * @param gem the gem name -445 * @param nextLine the line to parse -446 * @return the vulnerability -447 */ -448 private Vulnerability createVulnerability(String parentName, Dependency dependency, String gem, String nextLine) { -449 Vulnerability vulnerability = null; -450 if (null != dependency) { -451 final String version = nextLine.substring(VERSION.length()); -452 dependency.getVersionEvidence().addEvidence( -453 "bundler-audit", -454 "Version", -455 version, -456 Confidence.HIGHEST); -457 vulnerability = new Vulnerability(); // don't add to dependency until we have name set later -458 vulnerability.setMatchedCPE( -459 String.format("cpe:/a:%1$s_project:%1$s:%2$s::~~~ruby~~", gem, version), -460 null); -461 vulnerability.setCvssAccessVector("-"); -462 vulnerability.setCvssAccessComplexity("-"); -463 vulnerability.setCvssAuthentication("-"); -464 vulnerability.setCvssAvailabilityImpact("-"); -465 vulnerability.setCvssConfidentialityImpact("-"); -466 vulnerability.setCvssIntegrityImpact("-"); -467 } -468 LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine)); -469 return vulnerability; -470 } -471 -472 /** -473 * Creates the dependency based off of the gem. -474 * -475 * @param engine the engine used for scanning -476 * @param parentName the gem parent -477 * @param fileName the file name -478 * @param filePath the file path -479 * @param gem the gem name -480 * @return the dependency to add -481 * @throws IOException thrown if a temporary gem file could not be written -482 */ -483 private Dependency createDependencyForGem(Engine engine, String parentName, String fileName, String filePath, String gem) throws IOException { -484 final File gemFile = new File(Settings.getTempDirectory(), gem + "_Gemfile.lock"); -485 gemFile.createNewFile(); -486 final String displayFileName = String.format("%s%c%s:%s", parentName, File.separatorChar, fileName, gem); -487 -488 FileUtils.write(gemFile, displayFileName, Charset.defaultCharset()); // unique contents to avoid dependency bundling -489 final Dependency dependency = new Dependency(gemFile); -490 dependency.getProductEvidence().addEvidence("bundler-audit", "Name", gem, Confidence.HIGHEST); -491 dependency.setDisplayFileName(displayFileName); -492 dependency.setFileName(fileName); -493 dependency.setFilePath(filePath); -494 engine.getDependencies().add(dependency); -495 return dependency; -496 } -497 } +364 vulnerability.setDescription("*** Vulnerability obtained from bundle-audit verbose report. " +365 + "Title link may not work. CPE below is guessed. CVSS score is estimated (-1.0 " +366 + " indicates unknown). See link below for full details. *** "); +367 } +368 } else if (appendToDescription) { +369 if (null != vulnerability) { +370 vulnerability.setDescription(vulnerability.getDescription() + nextLine + "\n"); +371 } +372 } +373 } +374 } +375 +376 /** +377 * Sets the vulnerability name. +378 * +379 * @param parentName the parent name +380 * @param dependency the dependency +381 * @param vulnerability the vulnerability +382 * @param nextLine the line to parse +383 */ +384 private void setVulnerabilityName(String parentName, Dependency dependency, Vulnerability vulnerability, String nextLine) { +385 final String advisory = nextLine.substring((ADVISORY.length())); +386 if (null != vulnerability) { +387 vulnerability.setName(advisory); +388 } +389 if (null != dependency) { +390 dependency.getVulnerabilities().add(vulnerability); // needed to wait for vulnerability name to avoid NPE +391 } +392 LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine)); +393 } +394 +395 /** +396 * Adds a reference to the vulnerability. +397 * +398 * @param parentName the parent name +399 * @param vulnerability the vulnerability +400 * @param nextLine the line to parse +401 */ +402 private void addReferenceToVulnerability(String parentName, Vulnerability vulnerability, String nextLine) { +403 final String url = nextLine.substring(("URL: ").length()); +404 if (null != vulnerability) { +405 final Reference ref = new Reference(); +406 ref.setName(vulnerability.getName()); +407 ref.setSource("bundle-audit"); +408 ref.setUrl(url); +409 vulnerability.getReferences().add(ref); +410 } +411 LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine)); +412 } +413 +414 /** +415 * Adds the criticality to the vulnerability +416 * +417 * @param parentName the parent name +418 * @param vulnerability the vulnerability +419 * @param nextLine the line to parse +420 */ +421 private void addCriticalityToVulnerability(String parentName, Vulnerability vulnerability, String nextLine) { +422 if (null != vulnerability) { +423 final String criticality = nextLine.substring(CRITICALITY.length()).trim(); +424 float score = -1.0f; +425 Vulnerability v = null; +426 try { +427 v = cvedb.getVulnerability(vulnerability.getName()); +428 } catch (DatabaseException ex) { +429 LOGGER.debug("Unable to look up vulnerability {}", vulnerability.getName()); +430 } +431 if (v != null) { +432 score = v.getCvssScore(); +433 } else if ("High".equalsIgnoreCase(criticality)) { +434 score = 8.5f; +435 } else if ("Medium".equalsIgnoreCase(criticality)) { +436 score = 5.5f; +437 } else if ("Low".equalsIgnoreCase(criticality)) { +438 score = 2.0f; +439 } +440 vulnerability.setCvssScore(score); +441 } +442 LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine)); +443 } +444 +445 /** +446 * Creates a vulnerability. +447 * +448 * @param parentName the parent name +449 * @param dependency the dependency +450 * @param gem the gem name +451 * @param nextLine the line to parse +452 * @return the vulnerability +453 */ +454 private Vulnerability createVulnerability(String parentName, Dependency dependency, String gem, String nextLine) { +455 Vulnerability vulnerability = null; +456 if (null != dependency) { +457 final String version = nextLine.substring(VERSION.length()); +458 dependency.getVersionEvidence().addEvidence( +459 "bundler-audit", +460 "Version", +461 version, +462 Confidence.HIGHEST); +463 vulnerability = new Vulnerability(); // don't add to dependency until we have name set later +464 vulnerability.setMatchedCPE( +465 String.format("cpe:/a:%1$s_project:%1$s:%2$s::~~~ruby~~", gem, version), +466 null); +467 vulnerability.setCvssAccessVector("-"); +468 vulnerability.setCvssAccessComplexity("-"); +469 vulnerability.setCvssAuthentication("-"); +470 vulnerability.setCvssAvailabilityImpact("-"); +471 vulnerability.setCvssConfidentialityImpact("-"); +472 vulnerability.setCvssIntegrityImpact("-"); +473 } +474 LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine)); +475 return vulnerability; +476 } +477 +478 /** +479 * Creates the dependency based off of the gem. +480 * +481 * @param engine the engine used for scanning +482 * @param parentName the gem parent +483 * @param fileName the file name +484 * @param filePath the file path +485 * @param gem the gem name +486 * @return the dependency to add +487 * @throws IOException thrown if a temporary gem file could not be written +488 */ +489 private Dependency createDependencyForGem(Engine engine, String parentName, String fileName, String filePath, String gem) throws IOException { +490 final File gemFile = new File(Settings.getTempDirectory(), gem + "_Gemfile.lock"); +491 if (!gemFile.createNewFile()) { +492 throw new IOException("Unable to create temporary gem file"); +493 } +494 final String displayFileName = String.format("%s%c%s:%s", parentName, File.separatorChar, fileName, gem); +495 +496 FileUtils.write(gemFile, displayFileName, Charset.defaultCharset()); // unique contents to avoid dependency bundling +497 final Dependency dependency = new Dependency(gemFile); +498 dependency.getProductEvidence().addEvidence("bundler-audit", "Name", gem, Confidence.HIGHEST); +499 dependency.setDisplayFileName(displayFileName); +500 dependency.setFileName(fileName); +501 dependency.setFilePath(filePath); +502 engine.getDependencies().add(dependency); +503 return dependency; +504 } +505 }
    diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.html index b461d876a..8a3555149 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.html @@ -21,7 +21,7 @@ 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * -16 * Copyright (c) 2016 Bianca Jiang. All Rights Reserved. +16 * Copyright (c) 2016 IBM Corporation. All Rights Reserved. 17 */ 18 package org.owasp.dependencycheck.analyzer; 19 @@ -51,7 +51,7 @@ 43 * {@link RubyGemspecAnalyzer}, so it will enabled/disabled with 44 * {@link RubyGemspecAnalyzer}. 45 * -46 * @author Bianca Jiang (biancajiang@gmail.com) +46 * @author Bianca Jiang (https://twitter.com/biancajiang) 47 */ 48 @Experimental 49 public class RubyBundlerAnalyzer extends RubyGemspecAnalyzer { diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzer.html index c6a328761..30aa18927 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzer.html @@ -225,33 +225,36 @@ 217 return name.contains(VERSION_FILE_NAME); 218 } 219 }); -220 for (File f : matchingFiles) { -221 try { -222 final List<String> lines = FileUtils.readLines(f, Charset.defaultCharset()); -223 if (lines.size() == 1) { //TODO other checking? -224 final String value = lines.get(0).trim(); -225 versionEvidences.addEvidence(GEMSPEC, "version", value, Confidence.HIGH); -226 } -227 } catch (IOException e) { -228 LOGGER.debug("Error reading gemspec", e); -229 } -230 } -231 } -232 } -233 -234 /** -235 * Sets the package path on the dependency. -236 * -237 * @param dep the dependency to alter -238 */ -239 private void setPackagePath(Dependency dep) { -240 final File file = new File(dep.getFilePath()); -241 final String parent = file.getParent(); -242 if (parent != null) { -243 dep.setPackagePath(parent); -244 } -245 } -246 } +220 if (matchingFiles == null) { +221 return; +222 } +223 for (File f : matchingFiles) { +224 try { +225 final List<String> lines = FileUtils.readLines(f, Charset.defaultCharset()); +226 if (lines.size() == 1) { //TODO other checking? +227 final String value = lines.get(0).trim(); +228 versionEvidences.addEvidence(GEMSPEC, "version", value, Confidence.HIGH); +229 } +230 } catch (IOException e) { +231 LOGGER.debug("Error reading gemspec", e); +232 } +233 } +234 } +235 } +236 +237 /** +238 * Sets the package path on the dependency. +239 * +240 * @param dep the dependency to alter +241 */ +242 private void setPackagePath(Dependency dep) { +243 final File file = new File(dep.getFilePath()); +244 final String parent = file.getParent(); +245 if (parent != null) { +246 dep.setPackagePath(parent); +247 } +248 } +249 }
    diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/SwiftPackageManagerAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/SwiftPackageManagerAnalyzer.html new file mode 100644 index 000000000..8d1c90a44 --- /dev/null +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/SwiftPackageManagerAnalyzer.html @@ -0,0 +1,205 @@ + + + +SwiftPackageManagerAnalyzer 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 IBM Corporation. All Rights Reserved.
    +17   */
    +18  package org.owasp.dependencycheck.analyzer;
    +19  
    +20  import java.io.File;
    +21  import java.io.FileFilter;
    +22  import java.io.IOException;
    +23  import java.nio.charset.Charset;
    +24  import java.util.regex.Matcher;
    +25  import java.util.regex.Pattern;
    +26  
    +27  import org.apache.commons.io.FileUtils;
    +28  import org.owasp.dependencycheck.Engine;
    +29  import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
    +30  import org.owasp.dependencycheck.dependency.Confidence;
    +31  import org.owasp.dependencycheck.dependency.Dependency;
    +32  import org.owasp.dependencycheck.dependency.EvidenceCollection;
    +33  import org.owasp.dependencycheck.utils.FileFilterBuilder;
    +34  import org.owasp.dependencycheck.utils.Settings;
    +35  
    +36  /**
    +37   * This analyzer is used to analyze the SWIFT Package Manager
    +38   * (https://swift.org/package-manager/). It collects information about a package
    +39   * from Package.swift files.
    +40   *
    +41   * @author Bianca Jiang (https://twitter.com/biancajiang)
    +42   */
    +43  @Experimental
    +44  public class SwiftPackageManagerAnalyzer extends AbstractFileTypeAnalyzer {
    +45  
    +46      /**
    +47       * The name of the analyzer.
    +48       */
    +49      private static final String ANALYZER_NAME = "SWIFT Package Manager Analyzer";
    +50  
    +51      /**
    +52       * The phase that this analyzer is intended to run in.
    +53       */
    +54      private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
    +55  
    +56      /**
    +57       * The file name to scan.
    +58       */
    +59      public static final String SPM_FILE_NAME = "Package.swift";
    +60  
    +61      /**
    +62       * Filter that detects files named "package.json".
    +63       */
    +64      private static final FileFilter SPM_FILE_FILTER = FileFilterBuilder.newInstance().addFilenames(SPM_FILE_NAME).build();
    +65  
    +66      /**
    +67       * The capture group #1 is the block variable. e.g. "import
    +68       * PackageDescription let package = Package( name: "Gloss" )"
    +69       */
    +70      private static final Pattern SPM_BLOCK_PATTERN = Pattern.compile("let[^=]+=\\s*Package\\s*\\(\\s*([^)]*)\\s*\\)", Pattern.DOTALL);
    +71  
    +72      /**
    +73       * Returns the FileFilter
    +74       *
    +75       * @return the FileFilter
    +76       */
    +77      @Override
    +78      protected FileFilter getFileFilter() {
    +79          return SPM_FILE_FILTER;
    +80      }
    +81  
    +82      @Override
    +83      protected void initializeFileTypeAnalyzer() {
    +84          // NO-OP
    +85      }
    +86  
    +87      /**
    +88       * Returns the name of the analyzer.
    +89       *
    +90       * @return the name of the analyzer.
    +91       */
    +92      @Override
    +93      public String getName() {
    +94          return ANALYZER_NAME;
    +95      }
    +96  
    +97      /**
    +98       * Returns the phase that the analyzer is intended to run in.
    +99       *
    +100      * @return the phase that the analyzer is intended to run in.
    +101      */
    +102     @Override
    +103     public AnalysisPhase getAnalysisPhase() {
    +104         return ANALYSIS_PHASE;
    +105     }
    +106 
    +107     /**
    +108      * Returns the key used in the properties file to reference the analyzer's
    +109      * enabled property.
    +110      *
    +111      * @return the analyzer's enabled property setting key
    +112      */
    +113     @Override
    +114     protected String getAnalyzerEnabledSettingKey() {
    +115         return Settings.KEYS.ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED;
    +116     }
    +117 
    +118     @Override
    +119     protected void analyzeFileType(Dependency dependency, Engine engine)
    +120             throws AnalysisException {
    +121 
    +122         String contents;
    +123         try {
    +124             contents = FileUtils.readFileToString(dependency.getActualFile(), Charset.defaultCharset());
    +125         } catch (IOException e) {
    +126             throw new AnalysisException(
    +127                     "Problem occurred while reading dependency file.", e);
    +128         }
    +129         final Matcher matcher = SPM_BLOCK_PATTERN.matcher(contents);
    +130         if (matcher.find()) {
    +131             final String packageDescription = matcher.group(1);
    +132             if (packageDescription.isEmpty()) {
    +133                 return;
    +134             }
    +135 
    +136             final EvidenceCollection product = dependency.getProductEvidence();
    +137             final EvidenceCollection vendor = dependency.getVendorEvidence();
    +138 
    +139             //SPM is currently under development for SWIFT 3. Its current metadata includes package name and dependencies.
    +140             //Future interesting metadata: version, license, homepage, author, summary, etc.
    +141             final String name = addStringEvidence(product, packageDescription, "name", "name", Confidence.HIGHEST);
    +142             if (name != null && !name.isEmpty()) {
    +143                 vendor.addEvidence(SPM_FILE_NAME, "name_project", name, Confidence.HIGHEST);
    +144             }
    +145         }
    +146         setPackagePath(dependency);
    +147     }
    +148 
    +149     /**
    +150      * Extracts evidence from the package description and adds it to the given
    +151      * evidence collection.
    +152      *
    +153      * @param evidences the evidence collection to update
    +154      * @param packageDescription the text to extract evidence from
    +155      * @param field the name of the field being searched for
    +156      * @param fieldPattern the field pattern within the contents to search for
    +157      * @param confidence the confidence level of the evidence if found
    +158      * @return the string that was added as evidence
    +159      */
    +160     private String addStringEvidence(EvidenceCollection evidences,
    +161             String packageDescription, String field, String fieldPattern, Confidence confidence) {
    +162         String value = "";
    +163 
    +164         final Matcher matcher = Pattern.compile(
    +165                 String.format("%s *:\\s*\"([^\"]*)", fieldPattern), Pattern.DOTALL).matcher(packageDescription);
    +166         if (matcher.find()) {
    +167             value = matcher.group(1);
    +168         }
    +169 
    +170         if (value != null) {
    +171             value = value.trim();
    +172             if (value.length() > 0) {
    +173                 evidences.addEvidence(SPM_FILE_NAME, field, value, confidence);
    +174             }
    +175         }
    +176 
    +177         return value;
    +178     }
    +179 
    +180     /**
    +181      * Sets the package path on the given dependency.
    +182      *
    +183      * @param dep the dependency to update
    +184      */
    +185     private void setPackagePath(Dependency dep) {
    +186         final File file = new File(dep.getFilePath());
    +187         final String parent = file.getParent();
    +188         if (parent != null) {
    +189             dep.setPackagePath(parent);
    +190         }
    +191     }
    +192 }
    +
    +
    + + + 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 0974bb6db..7db4df437 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.2 Reference Package org.owasp.dependencycheck.analyzer.exception + Dependency-Check Core 1.4.3 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 260e8b673..80571f23e 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.2 Reference Package org.owasp.dependencycheck.analyzer.exception + Dependency-Check Core 1.4.3 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 e52763f9b..937c7a0ad 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.2 Reference Package org.owasp.dependencycheck.analyzer + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.analyzer @@ -53,6 +53,9 @@
  • ClassNameInformation +
  • +
  • + CocoaPodsAnalyzer
  • ComposerLockAnalyzer @@ -116,6 +119,9 @@
  • RubyGemspecAnalyzer +
  • +
  • + SwiftPackageManagerAnalyzer
  • VulnerabilitySuppressionAnalyzer 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 aabc604f4..bc76dfe4e 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.2 Reference Package org.owasp.dependencycheck.analyzer + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.analyzer @@ -99,6 +99,11 @@
  • + + + + + + - - - + - - - + - + - + - + - + - + - + - + - + - - - - - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - - + + - + - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - - - - + + + + - + - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - - - - - + + + - + - + - - - + + + - + - + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - +
    ClassNameInformation
    + CocoaPodsAnalyzer +
    @@ -204,6 +209,11 @@ RubyGemspecAnalyzer
    + SwiftPackageManagerAnalyzer +
    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 8687f3fb7..b7dba63dd 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 @@ -69,8 +69,8 @@ 61 /** 62 * Creates a NexusSearch for the given repository URL. 63 * -64 * @param rootURL the URL of the repository on which searches should execute. Only parameters are added to this (so it should -65 * end in /select) +64 * @param rootURL the URL of the repository on which searches should +65 * execute. Only parameters are added to this (so it should end in /select) 66 */ 67 public CentralSearch(URL rootURL) { 68 this.rootURL = rootURL; @@ -84,99 +84,96 @@ 76 } 77 78 /** -79 * Searches the configured Central URL for the given sha1 hash. If the artifact is found, a <code>MavenArtifact</code> is -80 * populated with the GAV. -81 * -82 * @param sha1 the SHA-1 hash string for which to search -83 * @return the populated Maven GAV. -84 * @throws IOException if it's unable to connect to the specified repository or if the specified artifact is not found. -85 */ -86 public List<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 } -90 -91 final URL url = new URL(rootURL + String.format("?q=1:\"%s\"&wt=xml", sha1)); -92 -93 LOGGER.debug("Searching Central url {}", url); +79 * Searches the configured Central URL for the given sha1 hash. If the +80 * artifact is found, a <code>MavenArtifact</code> is populated with the +81 * GAV. +82 * +83 * @param sha1 the SHA-1 hash string for which to search +84 * @return the populated Maven GAV. +85 * @throws IOException if it's unable to connect to the specified repository +86 * or if the specified artifact is not found. +87 */ +88 public List<MavenArtifact> searchSha1(String sha1) throws IOException { +89 if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) { +90 throw new IllegalArgumentException("Invalid SHA1 format"); +91 } +92 List<MavenArtifact> result = null; +93 final URL url = new URL(rootURL + String.format("?q=1:\"%s\"&wt=xml", sha1)); 94 -95 // Determine if we need to use a proxy. The rules: -96 // 1) If the proxy is set, AND the setting is set to true, use the proxy -97 // 2) Otherwise, don't use the proxy (either the proxy isn't configured, -98 // or proxy is specifically set to false) -99 final HttpURLConnection conn = URLConnectionFactory.createHttpURLConnection(url, useProxy); -100 -101 conn.setDoOutput(true); +95 LOGGER.debug("Searching Central url {}", url); +96 +97 // Determine if we need to use a proxy. The rules: +98 // 1) If the proxy is set, AND the setting is set to true, use the proxy +99 // 2) Otherwise, don't use the proxy (either the proxy isn't configured, +100 // or proxy is specifically set to false) +101 final HttpURLConnection conn = URLConnectionFactory.createHttpURLConnection(url, useProxy); 102 -103 // JSON would be more elegant, but there's not currently a dependency -104 // on JSON, so don't want to add one just for this -105 conn.addRequestProperty("Accept", "application/xml"); -106 conn.connect(); -107 -108 if (conn.getResponseCode() == 200) { -109 boolean missing = false; -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 numFound = xpath.evaluate("/response/result/@numFound", doc); -116 if ("0".equals(numFound)) { -117 missing = true; -118 } else { -119 final List<MavenArtifact> result = new ArrayList<MavenArtifact>(); -120 final NodeList docs = (NodeList) xpath.evaluate("/response/result/doc", doc, XPathConstants.NODESET); -121 for (int i = 0; i < docs.getLength(); i++) { -122 final String g = xpath.evaluate("./str[@name='g']", docs.item(i)); -123 LOGGER.trace("GroupId: {}", g); -124 final String a = xpath.evaluate("./str[@name='a']", docs.item(i)); -125 LOGGER.trace("ArtifactId: {}", a); -126 final String v = xpath.evaluate("./str[@name='v']", docs.item(i)); -127 NodeList atts = (NodeList) xpath.evaluate("./arr[@name='ec']/str", docs.item(i), XPathConstants.NODESET); -128 boolean pomAvailable = false; -129 boolean jarAvailable = false; -130 for (int x = 0; x < atts.getLength(); x++) { -131 final String tmp = xpath.evaluate(".", atts.item(x)); -132 if (".pom".equals(tmp)) { -133 pomAvailable = true; -134 } else if (".jar".equals(tmp)) { -135 jarAvailable = true; -136 } -137 } -138 -139 atts = (NodeList) xpath.evaluate("./arr[@name='tags']/str", docs.item(i), XPathConstants.NODESET); -140 boolean useHTTPS = false; -141 for (int x = 0; x < atts.getLength(); x++) { -142 final String tmp = xpath.evaluate(".", atts.item(x)); -143 if ("https".equals(tmp)) { -144 useHTTPS = true; -145 } -146 } -147 -148 LOGGER.trace("Version: {}", v); -149 result.add(new MavenArtifact(g, a, v, jarAvailable, pomAvailable, useHTTPS)); -150 } -151 -152 return result; -153 } -154 } catch (Throwable e) { -155 // Anything else is jacked up XML stuff that we really can't recover -156 // from well -157 throw new IOException(e.getMessage(), e); -158 } -159 -160 if (missing) { -161 throw new FileNotFoundException("Artifact not found in Central"); -162 } -163 } else { -164 LOGGER.debug("Could not connect to Central received response code: {} {}", -165 conn.getResponseCode(), conn.getResponseMessage()); -166 throw new IOException("Could not connect to Central"); -167 } -168 -169 return null; -170 } -171 } +103 conn.setDoOutput(true); +104 +105 // JSON would be more elegant, but there's not currently a dependency +106 // on JSON, so don't want to add one just for this +107 conn.addRequestProperty("Accept", "application/xml"); +108 conn.connect(); +109 +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 }
    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 be53e5492..118ce92d0 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.2 Reference Package org.owasp.dependencycheck.data.central + Dependency-Check Core 1.4.3 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 cbc47bbf6..fa8ea42f5 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.2 Reference Package org.owasp.dependencycheck.data.central + Dependency-Check Core 1.4.3 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 4c66e78c3..2bbd651de 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.2 Reference Package org.owasp.dependencycheck.data.composer + Dependency-Check Core 1.4.3 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 46563a804..77209fccf 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.2 Reference Package org.owasp.dependencycheck.data.composer + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.composer diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.html index ed2431682..d8fc2cfaf 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.html @@ -217,107 +217,110 @@ 209 210 final Set<Pair<String, String>> data = cve.getVendorProductList(); 211 for (Pair<String, String> pair : data) { -212 v.setStringValue(pair.getLeft()); -213 p.setStringValue(pair.getRight()); -214 indexWriter.addDocument(doc); -215 resetFieldAnalyzer(); -216 } -217 } catch (DatabaseException ex) { -218 LOGGER.debug("", ex); -219 throw new IndexException("Error reading CPE data", ex); -220 } -221 } catch (CorruptIndexException ex) { -222 throw new IndexException("Unable to close an in-memory index", ex); -223 } catch (IOException ex) { -224 throw new IndexException("Unable to close an in-memory index", ex); -225 } finally { -226 if (indexWriter != null) { -227 try { -228 try { -229 indexWriter.commit(); -230 } finally { -231 indexWriter.close(true); -232 } -233 } catch (CorruptIndexException ex) { -234 throw new IndexException("Unable to close an in-memory index", ex); -235 } catch (IOException ex) { -236 throw new IndexException("Unable to close an in-memory index", ex); -237 } -238 if (analyzer != null) { -239 analyzer.close(); +212 //todo figure out why there are null products +213 if (pair.getLeft() != null && pair.getRight() != null) { +214 v.setStringValue(pair.getLeft()); +215 p.setStringValue(pair.getRight()); +216 indexWriter.addDocument(doc); +217 resetFieldAnalyzer(); +218 } +219 } +220 } catch (DatabaseException ex) { +221 LOGGER.debug("", ex); +222 throw new IndexException("Error reading CPE data", ex); +223 } +224 } catch (CorruptIndexException ex) { +225 throw new IndexException("Unable to close an in-memory index", ex); +226 } catch (IOException ex) { +227 throw new IndexException("Unable to close an in-memory index", ex); +228 } finally { +229 if (indexWriter != null) { +230 try { +231 try { +232 indexWriter.commit(); +233 } finally { +234 indexWriter.close(true); +235 } +236 } catch (CorruptIndexException ex) { +237 throw new IndexException("Unable to close an in-memory index", ex); +238 } catch (IOException ex) { +239 throw new IndexException("Unable to close an in-memory index", ex); 240 } -241 } -242 } -243 } -244 -245 /** -246 * Resets the product and vendor field analyzers. -247 */ -248 private void resetFieldAnalyzer() { -249 if (productFieldAnalyzer != null) { -250 productFieldAnalyzer.clear(); -251 } -252 if (vendorFieldAnalyzer != null) { -253 vendorFieldAnalyzer.clear(); +241 if (analyzer != null) { +242 analyzer.close(); +243 } +244 } +245 } +246 } +247 +248 /** +249 * Resets the product and vendor field analyzers. +250 */ +251 private void resetFieldAnalyzer() { +252 if (productFieldAnalyzer != null) { +253 productFieldAnalyzer.clear(); 254 } -255 } -256 -257 /** -258 * Searches the index using the given search string. -259 * -260 * @param searchString the query text -261 * @param maxQueryResults the maximum number of documents to return -262 * @return the TopDocs found by the search -263 * @throws ParseException thrown when the searchString is invalid -264 * @throws IOException is thrown if there is an issue with the underlying -265 * Index -266 */ -267 public TopDocs search(String searchString, int maxQueryResults) throws ParseException, IOException { -268 if (searchString == null || searchString.trim().isEmpty()) { -269 throw new ParseException("Query is null or empty"); -270 } -271 LOGGER.debug(searchString); -272 final Query query = queryParser.parse(searchString); -273 return search(query, maxQueryResults); -274 } -275 -276 /** -277 * Searches the index using the given query. -278 * -279 * @param query the query used to search the index -280 * @param maxQueryResults the max number of results to return -281 * @return the TopDocs found be the query -282 * @throws CorruptIndexException thrown if the Index is corrupt -283 * @throws IOException thrown if there is an IOException -284 */ -285 public TopDocs search(Query query, int maxQueryResults) throws CorruptIndexException, IOException { -286 resetFieldAnalyzer(); -287 return indexSearcher.search(query, maxQueryResults); -288 } -289 -290 /** -291 * Retrieves a document from the Index. -292 * -293 * @param documentId the id of the document to retrieve -294 * @return the Document -295 * @throws IOException thrown if there is an IOException -296 */ -297 public Document getDocument(int documentId) throws IOException { -298 return indexSearcher.doc(documentId); -299 } -300 -301 /** -302 * Returns the number of CPE entries stored in the index. -303 * -304 * @return the number of CPE entries stored in the index -305 */ -306 public int numDocs() { -307 if (indexReader == null) { -308 return -1; -309 } -310 return indexReader.numDocs(); -311 } -312 } +255 if (vendorFieldAnalyzer != null) { +256 vendorFieldAnalyzer.clear(); +257 } +258 } +259 +260 /** +261 * Searches the index using the given search string. +262 * +263 * @param searchString the query text +264 * @param maxQueryResults the maximum number of documents to return +265 * @return the TopDocs found by the search +266 * @throws ParseException thrown when the searchString is invalid +267 * @throws IOException is thrown if there is an issue with the underlying +268 * Index +269 */ +270 public TopDocs search(String searchString, int maxQueryResults) throws ParseException, IOException { +271 if (searchString == null || searchString.trim().isEmpty()) { +272 throw new ParseException("Query is null or empty"); +273 } +274 LOGGER.debug(searchString); +275 final Query query = queryParser.parse(searchString); +276 return search(query, maxQueryResults); +277 } +278 +279 /** +280 * Searches the index using the given query. +281 * +282 * @param query the query used to search the index +283 * @param maxQueryResults the max number of results to return +284 * @return the TopDocs found be the query +285 * @throws CorruptIndexException thrown if the Index is corrupt +286 * @throws IOException thrown if there is an IOException +287 */ +288 public TopDocs search(Query query, int maxQueryResults) throws CorruptIndexException, IOException { +289 resetFieldAnalyzer(); +290 return indexSearcher.search(query, maxQueryResults); +291 } +292 +293 /** +294 * Retrieves a document from the Index. +295 * +296 * @param documentId the id of the document to retrieve +297 * @return the Document +298 * @throws IOException thrown if there is an IOException +299 */ +300 public Document getDocument(int documentId) throws IOException { +301 return indexSearcher.doc(documentId); +302 } +303 +304 /** +305 * Returns the number of CPE entries stored in the index. +306 * +307 * @return the number of CPE entries stored in the index +308 */ +309 public int numDocs() { +310 if (indexReader == null) { +311 return -1; +312 } +313 return indexReader.numDocs(); +314 } +315 }
    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 c8076f3ba..cd9c39350 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.2 Reference Package org.owasp.dependencycheck.data.cpe + Dependency-Check Core 1.4.3 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 d4aaad8c6..17e1a2016 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.2 Reference Package org.owasp.dependencycheck.data.cpe + Dependency-Check Core 1.4.3 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 272bab8e0..372d0b944 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.2 Reference Package org.owasp.dependencycheck.data.cwe + Dependency-Check Core 1.4.3 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 cd3d0ee09..07f6df814 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.2 Reference Package org.owasp.dependencycheck.data.cwe + Dependency-Check Core 1.4.3 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 4c22972e2..dbdb4b256 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.2 Reference Package org.owasp.dependencycheck.data.lucene + Dependency-Check Core 1.4.3 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 ebce5fc7a..c260699c2 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.2 Reference Package org.owasp.dependencycheck.data.lucene + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.lucene 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 f9c98c17b..23bb8a19d 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.2 Reference Package org.owasp.dependencycheck.data.nexus + Dependency-Check Core 1.4.3 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 d78004e0b..bb2853d20 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.2 Reference Package org.owasp.dependencycheck.data.nexus + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.nexus 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 135425a5d..997d8d324 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.2 Reference Package org.owasp.dependencycheck.data.nuget + Dependency-Check Core 1.4.3 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 3443e1fbd..becd19a0c 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.2 Reference Package org.owasp.dependencycheck.data.nuget + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.nuget diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/nvdcve/ConnectionFactory.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/nvdcve/ConnectionFactory.html index ed37e7d2b..7ac37a94a 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/nvdcve/ConnectionFactory.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/nvdcve/ConnectionFactory.html @@ -44,350 +44,371 @@ 36 import org.slf4j.LoggerFactory; 37 38 /** -39 * Loads the configured database driver and returns the database connection. If the embedded H2 database is used obtaining a -40 * connection will ensure the database file exists and that the appropriate table structure has been created. -41 * -42 * @author Jeremy Long -43 */ -44 public final class ConnectionFactory { -45 -46 /** -47 * The Logger. -48 */ -49 private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionFactory.class); -50 /** -51 * The version of the current DB Schema. -52 */ -53 public static final String DB_SCHEMA_VERSION = Settings.getString(Settings.KEYS.DB_VERSION); -54 /** -55 * Resource location for SQL file used to create the database schema. -56 */ -57 public static final String DB_STRUCTURE_RESOURCE = "data/initialize.sql"; -58 /** -59 * Resource location for SQL file used to create the database schema. -60 */ -61 public static final String DB_STRUCTURE_UPDATE_RESOURCE = "data/upgrade_%s.sql"; -62 /** -63 * The URL that discusses upgrading non-H2 databases. -64 */ -65 public static final String UPGRADE_HELP_URL = "http://jeremylong.github.io/DependencyCheck/data/upgrade.html"; -66 /** -67 * The database driver used to connect to the database. -68 */ -69 private static Driver driver = null; -70 /** -71 * The database connection string. -72 */ -73 private static String connectionString = null; -74 /** -75 * The username to connect to the database. -76 */ -77 private static String userName = null; -78 /** -79 * The password for the database. -80 */ -81 private static String password = null; -82 -83 /** -84 * Private constructor for this factory class; no instance is ever needed. -85 */ -86 private ConnectionFactory() { -87 } -88 -89 /** -90 * Initializes the connection factory. Ensuring that the appropriate drivers are loaded and that a connection can be made -91 * successfully. -92 * -93 * @throws DatabaseException thrown if we are unable to connect to the database -94 */ -95 public static synchronized void initialize() throws DatabaseException { -96 //this only needs to be called once. -97 if (connectionString != null) { -98 return; -99 } -100 Connection conn = null; -101 try { -102 //load the driver if necessary -103 final String driverName = Settings.getString(Settings.KEYS.DB_DRIVER_NAME, ""); -104 if (!driverName.isEmpty()) { //likely need to load the correct driver -105 LOGGER.debug("Loading driver: {}", driverName); -106 final String driverPath = Settings.getString(Settings.KEYS.DB_DRIVER_PATH, ""); -107 try { -108 if (!driverPath.isEmpty()) { -109 LOGGER.debug("Loading driver from: {}", driverPath); -110 driver = DriverLoader.load(driverName, driverPath); -111 } else { -112 driver = DriverLoader.load(driverName); -113 } -114 } catch (DriverLoadException ex) { -115 LOGGER.debug("Unable to load database driver", ex); -116 throw new DatabaseException("Unable to load database driver"); -117 } -118 } -119 userName = Settings.getString(Settings.KEYS.DB_USER, "dcuser"); -120 //yes, yes - hard-coded password - only if there isn't one in the properties file. -121 password = Settings.getString(Settings.KEYS.DB_PASSWORD, "DC-Pass1337!"); -122 try { -123 connectionString = Settings.getConnectionString( -124 Settings.KEYS.DB_CONNECTION_STRING, -125 Settings.KEYS.DB_FILE_NAME); -126 } catch (IOException ex) { -127 LOGGER.debug( -128 "Unable to retrieve the database connection string", ex); -129 throw new DatabaseException("Unable to retrieve the database connection string"); -130 } -131 boolean shouldCreateSchema = false; -132 try { -133 if (connectionString.startsWith("jdbc:h2:file:")) { //H2 -134 shouldCreateSchema = !h2DataFileExists(); -135 LOGGER.debug("Need to create DB Structure: {}", shouldCreateSchema); -136 } -137 } catch (IOException ioex) { -138 LOGGER.debug("Unable to verify database exists", ioex); -139 throw new DatabaseException("Unable to verify database exists"); -140 } -141 LOGGER.debug("Loading database connection"); -142 LOGGER.debug("Connection String: {}", connectionString); -143 LOGGER.debug("Database User: {}", userName); -144 -145 try { -146 conn = DriverManager.getConnection(connectionString, userName, password); -147 } catch (SQLException ex) { -148 if (ex.getMessage().contains("java.net.UnknownHostException") && connectionString.contains("AUTO_SERVER=TRUE;")) { -149 connectionString = connectionString.replace("AUTO_SERVER=TRUE;", ""); -150 try { -151 conn = DriverManager.getConnection(connectionString, userName, password); -152 Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString); -153 LOGGER.debug( -154 "Unable to start the database in server mode; reverting to single user mode"); -155 } catch (SQLException sqlex) { -156 LOGGER.debug("Unable to connect to the database", ex); -157 throw new DatabaseException("Unable to connect to the database"); -158 } -159 } else { -160 LOGGER.debug("Unable to connect to the database", ex); -161 throw new DatabaseException("Unable to connect to the database"); -162 } -163 } -164 -165 if (shouldCreateSchema) { -166 try { -167 createTables(conn); -168 } catch (DatabaseException dex) { -169 LOGGER.debug("", dex); -170 throw new DatabaseException("Unable to create the database structure"); -171 } -172 } -173 try { -174 ensureSchemaVersion(conn); -175 } catch (DatabaseException dex) { -176 LOGGER.debug("", dex); -177 throw new DatabaseException("Database schema does not match this version of dependency-check", dex); -178 } -179 } finally { -180 if (conn != null) { -181 try { -182 conn.close(); -183 } catch (SQLException ex) { -184 LOGGER.debug("An error occurred closing the connection", ex); -185 } -186 } -187 } -188 } -189 -190 /** -191 * Cleans up resources and unloads any registered database drivers. This needs to be called to ensure the driver is -192 * unregistered prior to the finalize method being called as during shutdown the class loader used to load the driver may be -193 * unloaded prior to the driver being de-registered. -194 */ -195 public static synchronized void cleanup() { -196 if (driver != null) { -197 try { -198 DriverManager.deregisterDriver(driver); -199 } catch (SQLException ex) { -200 LOGGER.debug("An error occurred unloading the database driver", ex); -201 } catch (Throwable unexpected) { -202 LOGGER.debug( -203 "An unexpected throwable occurred unloading the database driver", unexpected); -204 } -205 driver = null; -206 } -207 connectionString = null; -208 userName = null; -209 password = null; -210 } -211 -212 /** -213 * Constructs a new database connection object per the database configuration. -214 * -215 * @return a database connection object -216 * @throws DatabaseException thrown if there is an exception loading the database connection -217 */ -218 public static Connection getConnection() throws DatabaseException { -219 initialize(); -220 Connection conn = null; -221 try { -222 conn = DriverManager.getConnection(connectionString, userName, password); -223 } catch (SQLException ex) { -224 LOGGER.debug("", ex); -225 throw new DatabaseException("Unable to connect to the database"); -226 } -227 return conn; -228 } -229 -230 /** -231 * Determines if the H2 database file exists. If it does not exist then the data structure will need to be created. -232 * -233 * @return true if the H2 database file does not exist; otherwise false -234 * @throws IOException thrown if the data directory does not exist and cannot be created -235 */ -236 private static boolean h2DataFileExists() throws IOException { -237 final File dir = Settings.getDataDirectory(); -238 final String fileName = Settings.getString(Settings.KEYS.DB_FILE_NAME); -239 final File file = new File(dir, fileName); -240 return file.exists(); -241 } -242 -243 /** -244 * Creates the database structure (tables and indexes) to store the CVE data. -245 * -246 * @param conn the database connection -247 * @throws DatabaseException thrown if there is a Database Exception -248 */ -249 private static void createTables(Connection conn) throws DatabaseException { -250 LOGGER.debug("Creating database structure"); -251 InputStream is = null; -252 try { -253 is = ConnectionFactory.class.getClassLoader().getResourceAsStream(DB_STRUCTURE_RESOURCE); -254 final String dbStructure = IOUtils.toString(is, "UTF-8"); -255 -256 Statement statement = null; -257 try { -258 statement = conn.createStatement(); -259 statement.execute(dbStructure); -260 } catch (SQLException ex) { -261 LOGGER.debug("", ex); -262 throw new DatabaseException("Unable to create database statement", ex); -263 } finally { -264 DBUtils.closeStatement(statement); -265 } -266 } catch (IOException ex) { -267 throw new DatabaseException("Unable to create database schema", ex); -268 } finally { -269 IOUtils.closeQuietly(is); -270 } -271 } -272 -273 /** -274 * Updates the database schema by loading the upgrade script for the version specified. The intended use is that if the -275 * current schema version is 2.9 then we would call updateSchema(conn, "2.9"). This would load the upgrade_2.9.sql file and -276 * execute it against the database. The upgrade script must update the 'version' in the properties table. -277 * -278 * @param conn the database connection object -279 * @param appExpectedVersion the schema version that the application expects -280 * @param currentDbVersion the current schema version of the database -281 * @throws DatabaseException thrown if there is an exception upgrading the database schema -282 */ -283 private static void updateSchema(Connection conn, DependencyVersion appExpectedVersion, DependencyVersion currentDbVersion) -284 throws DatabaseException { -285 -286 final String databaseProductName; -287 try { -288 databaseProductName = conn.getMetaData().getDatabaseProductName(); -289 } catch (SQLException ex) { -290 throw new DatabaseException("Unable to get the database product name"); -291 } -292 if ("h2".equalsIgnoreCase(databaseProductName)) { -293 LOGGER.debug("Updating database structure"); -294 InputStream is = null; -295 String updateFile = null; -296 try { -297 updateFile = String.format(DB_STRUCTURE_UPDATE_RESOURCE, currentDbVersion.toString()); -298 is = ConnectionFactory.class.getClassLoader().getResourceAsStream(updateFile); -299 if (is == null) { -300 throw new DatabaseException(String.format("Unable to load update file '%s'", updateFile)); -301 } -302 final String dbStructureUpdate = IOUtils.toString(is, "UTF-8"); -303 -304 Statement statement = null; -305 try { -306 statement = conn.createStatement(); -307 final boolean success = statement.execute(dbStructureUpdate); -308 if (!success && statement.getUpdateCount() <= 0) { -309 throw new DatabaseException(String.format("Unable to upgrade the database schema to %s", -310 currentDbVersion.toString())); -311 } -312 } catch (SQLException ex) { -313 LOGGER.debug("", ex); -314 throw new DatabaseException("Unable to update database schema", ex); -315 } finally { -316 DBUtils.closeStatement(statement); -317 } -318 } catch (IOException ex) { -319 final String msg = String.format("Upgrade SQL file does not exist: %s", updateFile); -320 throw new DatabaseException(msg, ex); -321 } finally { -322 IOUtils.closeQuietly(is); -323 } -324 } else { -325 final int e0 = Integer.parseInt(appExpectedVersion.getVersionParts().get(0)); -326 final int c0 = Integer.parseInt(currentDbVersion.getVersionParts().get(0)); -327 final int e1 = Integer.parseInt(appExpectedVersion.getVersionParts().get(1)); -328 final int c1 = Integer.parseInt(currentDbVersion.getVersionParts().get(1)); -329 if (e0 == c0 && e1 < c1) { -330 LOGGER.warn("A new version of dependency-check is available; consider upgrading"); -331 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false); -332 } else if (e0 == c0 && e1 == c1) { -333 //do nothing - not sure how we got here, but just incase... -334 } else { -335 LOGGER.error("The database schema must be upgraded to use this version of dependency-check. Please see {} for more information.", -336 UPGRADE_HELP_URL); -337 throw new DatabaseException("Database schema is out of date"); -338 } -339 } -340 } -341 -342 /** -343 * Counter to ensure that calls to ensureSchemaVersion does not end up in an endless loop. -344 */ -345 private static int callDepth = 0; -346 -347 /** -348 * Uses the provided connection to check the specified schema version within the database. -349 * -350 * @param conn the database connection object -351 * @throws DatabaseException thrown if the schema version is not compatible with this version of dependency-check -352 */ -353 private static void ensureSchemaVersion(Connection conn) throws DatabaseException { -354 ResultSet rs = null; -355 PreparedStatement ps = null; -356 try { -357 //TODO convert this to use DatabaseProperties -358 ps = conn.prepareStatement("SELECT value FROM properties WHERE id = 'version'"); -359 rs = ps.executeQuery(); -360 if (rs.next()) { -361 final DependencyVersion appDbVersion = DependencyVersionUtil.parseVersion(DB_SCHEMA_VERSION); -362 final DependencyVersion db = DependencyVersionUtil.parseVersion(rs.getString(1)); -363 if (appDbVersion.compareTo(db) > 0) { -364 LOGGER.debug("Current Schema: {}", DB_SCHEMA_VERSION); -365 LOGGER.debug("DB Schema: {}", rs.getString(1)); -366 updateSchema(conn, appDbVersion, db); -367 if (++callDepth < 10) { -368 ensureSchemaVersion(conn); -369 } -370 } -371 } else { -372 throw new DatabaseException("Database schema is missing"); -373 } -374 } catch (SQLException ex) { -375 LOGGER.debug("", ex); -376 throw new DatabaseException("Unable to check the database schema version"); -377 } finally { -378 DBUtils.closeResultSet(rs); -379 DBUtils.closeStatement(ps); -380 } -381 } -382 } +39 * Loads the configured database driver and returns the database connection. If +40 * the embedded H2 database is used obtaining a connection will ensure the +41 * database file exists and that the appropriate table structure has been +42 * created. +43 * +44 * @author Jeremy Long +45 */ +46 public final class ConnectionFactory { +47 +48 /** +49 * The Logger. +50 */ +51 private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionFactory.class); +52 /** +53 * The version of the current DB Schema. +54 */ +55 public static final String DB_SCHEMA_VERSION = Settings.getString(Settings.KEYS.DB_VERSION); +56 /** +57 * Resource location for SQL file used to create the database schema. +58 */ +59 public static final String DB_STRUCTURE_RESOURCE = "data/initialize.sql"; +60 /** +61 * Resource location for SQL file used to create the database schema. +62 */ +63 public static final String DB_STRUCTURE_UPDATE_RESOURCE = "data/upgrade_%s.sql"; +64 /** +65 * The URL that discusses upgrading non-H2 databases. +66 */ +67 public static final String UPGRADE_HELP_URL = "http://jeremylong.github.io/DependencyCheck/data/upgrade.html"; +68 /** +69 * The database driver used to connect to the database. +70 */ +71 private static Driver driver = null; +72 /** +73 * The database connection string. +74 */ +75 private static String connectionString = null; +76 /** +77 * The username to connect to the database. +78 */ +79 private static String userName = null; +80 /** +81 * The password for the database. +82 */ +83 private static String password = null; +84 +85 /** +86 * Private constructor for this factory class; no instance is ever needed. +87 */ +88 private ConnectionFactory() { +89 } +90 +91 /** +92 * Initializes the connection factory. Ensuring that the appropriate drivers +93 * are loaded and that a connection can be made successfully. +94 * +95 * @throws DatabaseException thrown if we are unable to connect to the +96 * database +97 */ +98 public static void initialize() throws DatabaseException { +99 //this only needs to be called once. +100 if (connectionString != null) { +101 return; +102 } +103 Connection conn = null; +104 try { +105 //load the driver if necessary +106 final String driverName = Settings.getString(Settings.KEYS.DB_DRIVER_NAME, ""); +107 if (!driverName.isEmpty()) { //likely need to load the correct driver +108 LOGGER.debug("Loading driver: {}", driverName); +109 final String driverPath = Settings.getString(Settings.KEYS.DB_DRIVER_PATH, ""); +110 try { +111 if (!driverPath.isEmpty()) { +112 LOGGER.debug("Loading driver from: {}", driverPath); +113 driver = DriverLoader.load(driverName, driverPath); +114 } else { +115 driver = DriverLoader.load(driverName); +116 } +117 } catch (DriverLoadException ex) { +118 LOGGER.debug("Unable to load database driver", ex); +119 throw new DatabaseException("Unable to load database driver"); +120 } +121 } +122 userName = Settings.getString(Settings.KEYS.DB_USER, "dcuser"); +123 //yes, yes - hard-coded password - only if there isn't one in the properties file. +124 password = Settings.getString(Settings.KEYS.DB_PASSWORD, "DC-Pass1337!"); +125 try { +126 connectionString = Settings.getConnectionString( +127 Settings.KEYS.DB_CONNECTION_STRING, +128 Settings.KEYS.DB_FILE_NAME); +129 } catch (IOException ex) { +130 LOGGER.debug( +131 "Unable to retrieve the database connection string", ex); +132 throw new DatabaseException("Unable to retrieve the database connection string"); +133 } +134 boolean shouldCreateSchema = false; +135 try { +136 if (connectionString.startsWith("jdbc:h2:file:")) { //H2 +137 shouldCreateSchema = !h2DataFileExists(); +138 LOGGER.debug("Need to create DB Structure: {}", shouldCreateSchema); +139 } +140 } catch (IOException ioex) { +141 LOGGER.debug("Unable to verify database exists", ioex); +142 throw new DatabaseException("Unable to verify database exists"); +143 } +144 LOGGER.debug("Loading database connection"); +145 LOGGER.debug("Connection String: {}", connectionString); +146 LOGGER.debug("Database User: {}", userName); +147 +148 try { +149 conn = DriverManager.getConnection(connectionString, userName, password); +150 } catch (SQLException ex) { +151 if (ex.getMessage().contains("java.net.UnknownHostException") && connectionString.contains("AUTO_SERVER=TRUE;")) { +152 connectionString = connectionString.replace("AUTO_SERVER=TRUE;", ""); +153 try { +154 conn = DriverManager.getConnection(connectionString, userName, password); +155 Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString); +156 LOGGER.debug( +157 "Unable to start the database in server mode; reverting to single user mode"); +158 } catch (SQLException sqlex) { +159 LOGGER.debug("Unable to connect to the database", ex); +160 throw new DatabaseException("Unable to connect to the database"); +161 } +162 } else { +163 LOGGER.debug("Unable to connect to the database", ex); +164 throw new DatabaseException("Unable to connect to the database"); +165 } +166 } +167 +168 if (shouldCreateSchema) { +169 try { +170 createTables(conn); +171 } catch (DatabaseException dex) { +172 LOGGER.debug("", dex); +173 throw new DatabaseException("Unable to create the database structure"); +174 } +175 } +176 try { +177 ensureSchemaVersion(conn); +178 } catch (DatabaseException dex) { +179 LOGGER.debug("", dex); +180 throw new DatabaseException("Database schema does not match this version of dependency-check", dex); +181 } +182 } finally { +183 if (conn != null) { +184 try { +185 conn.close(); +186 } catch (SQLException ex) { +187 LOGGER.debug("An error occurred closing the connection", ex); +188 } +189 } +190 } +191 } +192 +193 /** +194 * Cleans up resources and unloads any registered database drivers. This +195 * needs to be called to ensure the driver is unregistered prior to the +196 * finalize method being called as during shutdown the class loader used to +197 * load the driver may be unloaded prior to the driver being de-registered. +198 */ +199 public static void cleanup() { +200 if (driver != null) { +201 try { +202 DriverManager.deregisterDriver(driver); +203 } catch (SQLException ex) { +204 LOGGER.debug("An error occurred unloading the database driver", ex); +205 } catch (Throwable unexpected) { +206 LOGGER.debug( +207 "An unexpected throwable occurred unloading the database driver", unexpected); +208 } +209 driver = null; +210 } +211 connectionString = null; +212 userName = null; +213 password = null; +214 } +215 +216 /** +217 * Constructs a new database connection object per the database +218 * configuration. +219 * +220 * @return a database connection object +221 * @throws DatabaseException thrown if there is an exception loading the +222 * database connection +223 */ +224 public static Connection getConnection() throws DatabaseException { +225 initialize(); +226 Connection conn = null; +227 try { +228 conn = DriverManager.getConnection(connectionString, userName, password); +229 } catch (SQLException ex) { +230 LOGGER.debug("", ex); +231 throw new DatabaseException("Unable to connect to the database"); +232 } +233 return conn; +234 } +235 +236 /** +237 * Determines if the H2 database file exists. If it does not exist then the +238 * data structure will need to be created. +239 * +240 * @return true if the H2 database file does not exist; otherwise false +241 * @throws IOException thrown if the data directory does not exist and +242 * cannot be created +243 */ +244 private static boolean h2DataFileExists() throws IOException { +245 final File dir = Settings.getDataDirectory(); +246 final String fileName = Settings.getString(Settings.KEYS.DB_FILE_NAME); +247 final File file = new File(dir, fileName); +248 return file.exists(); +249 } +250 +251 /** +252 * Creates the database structure (tables and indexes) to store the CVE +253 * data. +254 * +255 * @param conn the database connection +256 * @throws DatabaseException thrown if there is a Database Exception +257 */ +258 private static void createTables(Connection conn) throws DatabaseException { +259 LOGGER.debug("Creating database structure"); +260 InputStream is = null; +261 try { +262 is = ConnectionFactory.class.getClassLoader().getResourceAsStream(DB_STRUCTURE_RESOURCE); +263 final String dbStructure = IOUtils.toString(is, "UTF-8"); +264 +265 Statement statement = null; +266 try { +267 statement = conn.createStatement(); +268 statement.execute(dbStructure); +269 } catch (SQLException ex) { +270 LOGGER.debug("", ex); +271 throw new DatabaseException("Unable to create database statement", ex); +272 } finally { +273 DBUtils.closeStatement(statement); +274 } +275 } catch (IOException ex) { +276 throw new DatabaseException("Unable to create database schema", ex); +277 } finally { +278 IOUtils.closeQuietly(is); +279 } +280 } +281 +282 /** +283 * Updates the database schema by loading the upgrade script for the version +284 * specified. The intended use is that if the current schema version is 2.9 +285 * then we would call updateSchema(conn, "2.9"). This would load the +286 * upgrade_2.9.sql file and execute it against the database. The upgrade +287 * script must update the 'version' in the properties table. +288 * +289 * @param conn the database connection object +290 * @param appExpectedVersion the schema version that the application expects +291 * @param currentDbVersion the current schema version of the database +292 * @throws DatabaseException thrown if there is an exception upgrading the +293 * database schema +294 */ +295 private static void updateSchema(Connection conn, DependencyVersion appExpectedVersion, DependencyVersion currentDbVersion) +296 throws DatabaseException { +297 +298 final String databaseProductName; +299 try { +300 databaseProductName = conn.getMetaData().getDatabaseProductName(); +301 } catch (SQLException ex) { +302 throw new DatabaseException("Unable to get the database product name"); +303 } +304 if ("h2".equalsIgnoreCase(databaseProductName)) { +305 LOGGER.debug("Updating database structure"); +306 InputStream is = null; +307 String updateFile = null; +308 try { +309 updateFile = String.format(DB_STRUCTURE_UPDATE_RESOURCE, currentDbVersion.toString()); +310 is = ConnectionFactory.class.getClassLoader().getResourceAsStream(updateFile); +311 if (is == null) { +312 throw new DatabaseException(String.format("Unable to load update file '%s'", updateFile)); +313 } +314 final String dbStructureUpdate = IOUtils.toString(is, "UTF-8"); +315 +316 Statement statement = null; +317 try { +318 statement = conn.createStatement(); +319 final boolean success = statement.execute(dbStructureUpdate); +320 if (!success && statement.getUpdateCount() <= 0) { +321 throw new DatabaseException(String.format("Unable to upgrade the database schema to %s", +322 currentDbVersion.toString())); +323 } +324 } catch (SQLException ex) { +325 LOGGER.debug("", ex); +326 throw new DatabaseException("Unable to update database schema", ex); +327 } finally { +328 DBUtils.closeStatement(statement); +329 } +330 } catch (IOException ex) { +331 final String msg = String.format("Upgrade SQL file does not exist: %s", updateFile); +332 throw new DatabaseException(msg, ex); +333 } finally { +334 IOUtils.closeQuietly(is); +335 } +336 } else { +337 final int e0 = Integer.parseInt(appExpectedVersion.getVersionParts().get(0)); +338 final int c0 = Integer.parseInt(currentDbVersion.getVersionParts().get(0)); +339 final int e1 = Integer.parseInt(appExpectedVersion.getVersionParts().get(1)); +340 final int c1 = Integer.parseInt(currentDbVersion.getVersionParts().get(1)); +341 if (e0 == c0 && e1 < c1) { +342 LOGGER.warn("A new version of dependency-check is available; consider upgrading"); +343 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false); +344 } else if (e0 == c0 && e1 == c1) { +345 //do nothing - not sure how we got here, but just incase... +346 } else { +347 LOGGER.error("The database schema must be upgraded to use this version of dependency-check. Please see {} for more information.", +348 UPGRADE_HELP_URL); +349 throw new DatabaseException("Database schema is out of date"); +350 } +351 } +352 } +353 +354 /** +355 * Counter to ensure that calls to ensureSchemaVersion does not end up in an +356 * endless loop. +357 */ +358 private static int callDepth = 0; +359 +360 /** +361 * Uses the provided connection to check the specified schema version within +362 * the database. +363 * +364 * @param conn the database connection object +365 * @throws DatabaseException thrown if the schema version is not compatible +366 * with this version of dependency-check +367 */ +368 private static void ensureSchemaVersion(Connection conn) throws DatabaseException { +369 ResultSet rs = null; +370 PreparedStatement ps = null; +371 try { +372 //TODO convert this to use DatabaseProperties +373 ps = conn.prepareStatement("SELECT value FROM properties WHERE id = 'version'"); +374 rs = ps.executeQuery(); +375 if (rs.next()) { +376 final DependencyVersion appDbVersion = DependencyVersionUtil.parseVersion(DB_SCHEMA_VERSION); +377 if (appDbVersion == null) { +378 throw new DatabaseException("Invalid application database schema"); +379 } +380 final DependencyVersion db = DependencyVersionUtil.parseVersion(rs.getString(1)); +381 if (db == null) { +382 throw new DatabaseException("Invalid database schema"); +383 } +384 if (appDbVersion.compareTo(db) > 0) { +385 LOGGER.debug("Current Schema: {}", DB_SCHEMA_VERSION); +386 LOGGER.debug("DB Schema: {}", rs.getString(1)); +387 updateSchema(conn, appDbVersion, db); +388 if (++callDepth < 10) { +389 ensureSchemaVersion(conn); +390 } +391 } +392 } else { +393 throw new DatabaseException("Database schema is missing"); +394 } +395 } catch (SQLException ex) { +396 LOGGER.debug("", ex); +397 throw new DatabaseException("Unable to check the database schema version"); +398 } finally { +399 DBUtils.closeResultSet(rs); +400 DBUtils.closeStatement(ps); +401 } +402 } +403 }
    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 9fae88f80..1d4d2db7a 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 @@ -95,766 +95,768 @@ 87 open(); 88 try { 89 final String databaseProductName = conn.getMetaData().getDatabaseProductName(); -90 batchSupported = conn.getMetaData().supportsBatchUpdates(); -91 LOGGER.debug("Database dialect: {}", databaseProductName); -92 final Locale dbDialect = new Locale(databaseProductName); -93 statementBundle = ResourceBundle.getBundle("data/dbStatements", dbDialect); -94 } catch (SQLException se) { -95 LOGGER.warn("Problem loading database specific dialect!", se); -96 statementBundle = ResourceBundle.getBundle("data/dbStatements"); -97 } -98 databaseProperties = new DatabaseProperties(this); -99 } catch (DatabaseException ex) { -100 throw ex; -101 } -102 } -103 -104 /** -105 * Returns the database connection. -106 * -107 * @return the database connection -108 */ -109 protected Connection getConnection() { -110 return conn; -111 } -112 -113 /** -114 * Opens the database connection. If the database does not exist, it will -115 * create a new one. -116 * -117 * @throws DatabaseException thrown if there is an error opening the -118 * database connection -119 */ -120 public final void open() throws DatabaseException { -121 if (!isOpen()) { -122 conn = ConnectionFactory.getConnection(); -123 } -124 } -125 -126 /** -127 * Closes the DB4O database. Close should be called on this object when it -128 * is done being used. -129 */ -130 public void close() { -131 if (conn != null) { -132 try { -133 conn.close(); -134 } catch (SQLException ex) { -135 LOGGER.error("There was an error attempting to close the CveDB, see the log for more details."); -136 LOGGER.debug("", ex); -137 } catch (Throwable ex) { -138 LOGGER.error("There was an exception attempting to close the CveDB, see the log for more details."); -139 LOGGER.debug("", ex); -140 } -141 conn = null; -142 } -143 } -144 -145 /** -146 * Returns whether the database connection is open or closed. -147 * -148 * @return whether the database connection is open or closed -149 */ -150 public boolean isOpen() { -151 return conn != null; -152 } -153 -154 /** -155 * Commits all completed transactions. -156 * -157 * @throws SQLException thrown if a SQL Exception occurs -158 */ -159 public void commit() throws SQLException { -160 //temporary remove this as autocommit is on. -161 //if (conn != null) { -162 // conn.commit(); -163 //} -164 } -165 -166 /** -167 * Cleans up the object and ensures that "close" has been called. -168 * -169 * @throws Throwable thrown if there is a problem -170 */ -171 @Override -172 @SuppressWarnings("FinalizeDeclaration") -173 protected void finalize() throws Throwable { -174 LOGGER.debug("Entering finalize"); -175 close(); -176 super.finalize(); -177 } -178 /** -179 * Database properties object containing the 'properties' from the database -180 * table. -181 */ -182 private DatabaseProperties databaseProperties; -183 -184 /** -185 * Get the value of databaseProperties. -186 * -187 * @return the value of databaseProperties -188 */ -189 public DatabaseProperties getDatabaseProperties() { -190 return databaseProperties; -191 } -192 -193 /** -194 * Searches the CPE entries in the database and retrieves all entries for a -195 * given vendor and product combination. The returned list will include all -196 * versions of the product that are registered in the NVD CVE data. -197 * -198 * @param vendor the identified vendor name of the dependency being analyzed -199 * @param product the identified name of the product of the dependency being -200 * analyzed -201 * @return a set of vulnerable software -202 */ -203 public Set<VulnerableSoftware> getCPEs(String vendor, String product) { -204 final Set<VulnerableSoftware> cpe = new HashSet<VulnerableSoftware>(); -205 ResultSet rs = null; -206 PreparedStatement ps = null; -207 try { -208 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_CPE_ENTRIES")); -209 ps.setString(1, vendor); -210 ps.setString(2, product); -211 rs = ps.executeQuery(); -212 -213 while (rs.next()) { -214 final VulnerableSoftware vs = new VulnerableSoftware(); -215 vs.setCpe(rs.getString(1)); -216 cpe.add(vs); -217 } -218 } catch (SQLException ex) { -219 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details."); -220 LOGGER.debug("", ex); -221 } finally { -222 DBUtils.closeResultSet(rs); -223 DBUtils.closeStatement(ps); -224 } -225 return cpe; -226 } -227 -228 /** -229 * Returns the entire list of vendor/product combinations. -230 * -231 * @return the entire list of vendor/product combinations -232 * @throws DatabaseException thrown when there is an error retrieving the -233 * data from the DB -234 */ -235 public Set<Pair<String, String>> getVendorProductList() throws DatabaseException { -236 final Set<Pair<String, String>> data = new HashSet<Pair<String, String>>(); -237 ResultSet rs = null; -238 PreparedStatement ps = null; -239 try { -240 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_VENDOR_PRODUCT_LIST")); -241 rs = ps.executeQuery(); -242 while (rs.next()) { -243 data.add(new Pair<String, String>(rs.getString(1), rs.getString(2))); -244 } -245 } catch (SQLException ex) { -246 final String msg = "An unexpected SQL Exception occurred; please see the verbose log for more details."; -247 throw new DatabaseException(msg, ex); -248 } finally { -249 DBUtils.closeResultSet(rs); -250 DBUtils.closeStatement(ps); -251 } -252 return data; -253 } -254 -255 /** -256 * Returns a set of properties. -257 * -258 * @return the properties from the database -259 */ -260 Properties getProperties() { -261 final Properties prop = new Properties(); -262 PreparedStatement ps = null; -263 ResultSet rs = null; -264 try { -265 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_PROPERTIES")); -266 rs = ps.executeQuery(); -267 while (rs.next()) { -268 prop.setProperty(rs.getString(1), rs.getString(2)); -269 } -270 } catch (SQLException ex) { -271 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details."); -272 LOGGER.debug("", ex); -273 } finally { -274 DBUtils.closeStatement(ps); -275 DBUtils.closeResultSet(rs); -276 } -277 return prop; -278 } -279 -280 /** -281 * Saves a property to the database. -282 * -283 * @param key the property key -284 * @param value the property value -285 */ -286 void saveProperty(String key, String value) { -287 try { -288 try { -289 final PreparedStatement mergeProperty = getConnection().prepareStatement(statementBundle.getString("MERGE_PROPERTY")); -290 try { -291 mergeProperty.setString(1, key); -292 mergeProperty.setString(2, value); -293 mergeProperty.executeUpdate(); -294 } finally { -295 DBUtils.closeStatement(mergeProperty); -296 } -297 } catch (MissingResourceException mre) { -298 // No Merge statement, so doing an Update/Insert... -299 PreparedStatement updateProperty = null; -300 PreparedStatement insertProperty = null; -301 try { -302 updateProperty = getConnection().prepareStatement(statementBundle.getString("UPDATE_PROPERTY")); -303 updateProperty.setString(1, value); -304 updateProperty.setString(2, key); -305 if (updateProperty.executeUpdate() == 0) { -306 insertProperty = getConnection().prepareStatement(statementBundle.getString("INSERT_PROPERTY")); -307 insertProperty.setString(1, key); -308 insertProperty.setString(2, value); -309 insertProperty.executeUpdate(); -310 } -311 } finally { -312 DBUtils.closeStatement(updateProperty); -313 DBUtils.closeStatement(insertProperty); -314 } -315 } -316 } catch (SQLException ex) { -317 LOGGER.warn("Unable to save property '{}' with a value of '{}' to the database", key, value); -318 LOGGER.debug("", ex); -319 } -320 } -321 -322 /** -323 * Retrieves the vulnerabilities associated with the specified CPE. -324 * -325 * @param cpeStr the CPE name -326 * @return a list of Vulnerabilities -327 * @throws DatabaseException thrown if there is an exception retrieving data -328 */ -329 public List<Vulnerability> getVulnerabilities(String cpeStr) throws DatabaseException { -330 final VulnerableSoftware cpe = new VulnerableSoftware(); -331 try { -332 cpe.parseName(cpeStr); -333 } catch (UnsupportedEncodingException ex) { -334 LOGGER.trace("", ex); -335 } -336 final DependencyVersion detectedVersion = parseDependencyVersion(cpe); -337 final List<Vulnerability> vulnerabilities = new ArrayList<Vulnerability>(); -338 -339 PreparedStatement ps = null; -340 ResultSet rs = null; -341 try { -342 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_CVE_FROM_SOFTWARE")); -343 ps.setString(1, cpe.getVendor()); -344 ps.setString(2, cpe.getProduct()); -345 rs = ps.executeQuery(); -346 String currentCVE = ""; -347 -348 final Map<String, Boolean> vulnSoftware = new HashMap<String, Boolean>(); -349 while (rs.next()) { -350 final String cveId = rs.getString(1); -351 if (!currentCVE.equals(cveId)) { //check for match and add -352 final Entry<String, Boolean> matchedCPE = getMatchingSoftware(vulnSoftware, cpe.getVendor(), cpe.getProduct(), detectedVersion); -353 if (matchedCPE != null) { -354 final Vulnerability v = getVulnerability(currentCVE); -355 v.setMatchedCPE(matchedCPE.getKey(), matchedCPE.getValue() ? "Y" : null); -356 vulnerabilities.add(v); -357 } -358 vulnSoftware.clear(); -359 currentCVE = cveId; -360 } -361 -362 final String cpeId = rs.getString(2); -363 final String previous = rs.getString(3); -364 final Boolean p = previous != null && !previous.isEmpty(); -365 vulnSoftware.put(cpeId, p); -366 } -367 //remember to process the last set of CVE/CPE entries -368 final Entry<String, Boolean> matchedCPE = getMatchingSoftware(vulnSoftware, cpe.getVendor(), cpe.getProduct(), detectedVersion); -369 if (matchedCPE != null) { -370 final Vulnerability v = getVulnerability(currentCVE); -371 v.setMatchedCPE(matchedCPE.getKey(), matchedCPE.getValue() ? "Y" : null); -372 vulnerabilities.add(v); -373 } -374 } catch (SQLException ex) { -375 throw new DatabaseException("Exception retrieving vulnerability for " + cpeStr, ex); -376 } finally { -377 DBUtils.closeResultSet(rs); -378 DBUtils.closeStatement(ps); -379 } -380 return vulnerabilities; -381 } -382 -383 /** -384 * Gets a vulnerability for the provided CVE. -385 * -386 * @param cve the CVE to lookup -387 * @return a vulnerability object -388 * @throws DatabaseException if an exception occurs -389 */ -390 public Vulnerability getVulnerability(String cve) throws DatabaseException { -391 PreparedStatement psV = null; -392 PreparedStatement psR = null; -393 PreparedStatement psS = null; -394 ResultSet rsV = null; -395 ResultSet rsR = null; -396 ResultSet rsS = null; -397 Vulnerability vuln = null; -398 -399 try { -400 psV = getConnection().prepareStatement(statementBundle.getString("SELECT_VULNERABILITY")); -401 psV.setString(1, cve); -402 rsV = psV.executeQuery(); -403 if (rsV.next()) { -404 vuln = new Vulnerability(); -405 vuln.setName(cve); -406 vuln.setDescription(rsV.getString(2)); -407 String cwe = rsV.getString(3); -408 if (cwe != null) { -409 final String name = CweDB.getCweName(cwe); -410 if (name != null) { -411 cwe += ' ' + name; -412 } -413 } -414 final int cveId = rsV.getInt(1); -415 vuln.setCwe(cwe); -416 vuln.setCvssScore(rsV.getFloat(4)); -417 vuln.setCvssAccessVector(rsV.getString(5)); -418 vuln.setCvssAccessComplexity(rsV.getString(6)); -419 vuln.setCvssAuthentication(rsV.getString(7)); -420 vuln.setCvssConfidentialityImpact(rsV.getString(8)); -421 vuln.setCvssIntegrityImpact(rsV.getString(9)); -422 vuln.setCvssAvailabilityImpact(rsV.getString(10)); -423 -424 psR = getConnection().prepareStatement(statementBundle.getString("SELECT_REFERENCES")); -425 psR.setInt(1, cveId); -426 rsR = psR.executeQuery(); -427 while (rsR.next()) { -428 vuln.addReference(rsR.getString(1), rsR.getString(2), rsR.getString(3)); -429 } -430 psS = getConnection().prepareStatement(statementBundle.getString("SELECT_SOFTWARE")); -431 psS.setInt(1, cveId); -432 rsS = psS.executeQuery(); -433 while (rsS.next()) { -434 final String cpe = rsS.getString(1); -435 final String prevVersion = rsS.getString(2); -436 if (prevVersion == null) { -437 vuln.addVulnerableSoftware(cpe); -438 } else { -439 vuln.addVulnerableSoftware(cpe, prevVersion); -440 } -441 } -442 } -443 } catch (SQLException ex) { -444 throw new DatabaseException("Error retrieving " + cve, ex); -445 } finally { -446 DBUtils.closeResultSet(rsV); -447 DBUtils.closeResultSet(rsR); -448 DBUtils.closeResultSet(rsS); -449 DBUtils.closeStatement(psV); -450 DBUtils.closeStatement(psR); -451 DBUtils.closeStatement(psS); -452 } -453 return vuln; -454 } -455 -456 /** -457 * Updates the vulnerability within the database. If the vulnerability does -458 * not exist it will be added. -459 * -460 * @param vuln the vulnerability to add to the database -461 * @throws DatabaseException is thrown if the database -462 */ -463 public void updateVulnerability(Vulnerability vuln) throws DatabaseException { -464 PreparedStatement selectVulnerabilityId = null; -465 PreparedStatement deleteVulnerability = null; -466 PreparedStatement deleteReferences = null; -467 PreparedStatement deleteSoftware = null; -468 PreparedStatement updateVulnerability = null; -469 PreparedStatement insertVulnerability = null; -470 PreparedStatement insertReference = null; -471 PreparedStatement selectCpeId = null; -472 PreparedStatement insertCpe = null; -473 PreparedStatement insertSoftware = null; -474 -475 try { -476 selectVulnerabilityId = getConnection().prepareStatement(statementBundle.getString("SELECT_VULNERABILITY_ID")); -477 deleteVulnerability = getConnection().prepareStatement(statementBundle.getString("DELETE_VULNERABILITY")); -478 deleteReferences = getConnection().prepareStatement(statementBundle.getString("DELETE_REFERENCE")); -479 deleteSoftware = getConnection().prepareStatement(statementBundle.getString("DELETE_SOFTWARE")); -480 updateVulnerability = getConnection().prepareStatement(statementBundle.getString("UPDATE_VULNERABILITY")); -481 final String[] ids = {"id"}; -482 insertVulnerability = getConnection().prepareStatement(statementBundle.getString("INSERT_VULNERABILITY"), -483 //Statement.RETURN_GENERATED_KEYS); -484 ids); -485 insertReference = getConnection().prepareStatement(statementBundle.getString("INSERT_REFERENCE")); -486 selectCpeId = getConnection().prepareStatement(statementBundle.getString("SELECT_CPE_ID")); -487 insertCpe = getConnection().prepareStatement(statementBundle.getString("INSERT_CPE"), -488 //Statement.RETURN_GENERATED_KEYS); -489 ids); -490 insertSoftware = getConnection().prepareStatement(statementBundle.getString("INSERT_SOFTWARE")); -491 int vulnerabilityId = 0; -492 selectVulnerabilityId.setString(1, vuln.getName()); -493 ResultSet rs = selectVulnerabilityId.executeQuery(); -494 if (rs.next()) { -495 vulnerabilityId = rs.getInt(1); -496 // first delete any existing vulnerability info. We don't know what was updated. yes, slower but atm easier. -497 deleteReferences.setInt(1, vulnerabilityId); -498 deleteReferences.execute(); -499 deleteSoftware.setInt(1, vulnerabilityId); -500 deleteSoftware.execute(); -501 } -502 DBUtils.closeResultSet(rs); -503 rs = null; -504 -505 if (vulnerabilityId != 0) { -506 if (vuln.getDescription().contains("** REJECT **")) { -507 deleteVulnerability.setInt(1, vulnerabilityId); -508 deleteVulnerability.executeUpdate(); -509 } else { -510 updateVulnerability.setString(1, vuln.getDescription()); -511 updateVulnerability.setString(2, vuln.getCwe()); -512 updateVulnerability.setFloat(3, vuln.getCvssScore()); -513 updateVulnerability.setString(4, vuln.getCvssAccessVector()); -514 updateVulnerability.setString(5, vuln.getCvssAccessComplexity()); -515 updateVulnerability.setString(6, vuln.getCvssAuthentication()); -516 updateVulnerability.setString(7, vuln.getCvssConfidentialityImpact()); -517 updateVulnerability.setString(8, vuln.getCvssIntegrityImpact()); -518 updateVulnerability.setString(9, vuln.getCvssAvailabilityImpact()); -519 updateVulnerability.setInt(10, vulnerabilityId); -520 updateVulnerability.executeUpdate(); -521 } -522 } else { -523 insertVulnerability.setString(1, vuln.getName()); -524 insertVulnerability.setString(2, vuln.getDescription()); -525 insertVulnerability.setString(3, vuln.getCwe()); -526 insertVulnerability.setFloat(4, vuln.getCvssScore()); -527 insertVulnerability.setString(5, vuln.getCvssAccessVector()); -528 insertVulnerability.setString(6, vuln.getCvssAccessComplexity()); -529 insertVulnerability.setString(7, vuln.getCvssAuthentication()); -530 insertVulnerability.setString(8, vuln.getCvssConfidentialityImpact()); -531 insertVulnerability.setString(9, vuln.getCvssIntegrityImpact()); -532 insertVulnerability.setString(10, vuln.getCvssAvailabilityImpact()); -533 insertVulnerability.execute(); -534 try { -535 rs = insertVulnerability.getGeneratedKeys(); -536 rs.next(); -537 vulnerabilityId = rs.getInt(1); -538 } catch (SQLException ex) { -539 final String msg = String.format("Unable to retrieve id for new vulnerability for '%s'", vuln.getName()); -540 throw new DatabaseException(msg, ex); -541 } finally { -542 DBUtils.closeResultSet(rs); -543 rs = null; -544 } -545 } -546 -547 for (Reference r : vuln.getReferences()) { -548 insertReference.setInt(1, vulnerabilityId); -549 insertReference.setString(2, r.getName()); -550 insertReference.setString(3, r.getUrl()); -551 insertReference.setString(4, r.getSource()); -552 -553 if (batchSupported) { -554 insertReference.addBatch(); -555 } else { -556 insertReference.execute(); -557 } -558 } -559 -560 if (batchSupported) { -561 insertReference.executeBatch(); -562 } -563 -564 for (VulnerableSoftware s : vuln.getVulnerableSoftware()) { -565 int cpeProductId = 0; -566 selectCpeId.setString(1, s.getName()); -567 try { -568 rs = selectCpeId.executeQuery(); -569 if (rs.next()) { -570 cpeProductId = rs.getInt(1); -571 } -572 } catch (SQLException ex) { -573 throw new DatabaseException("Unable to get primary key for new cpe: " + s.getName(), ex); -574 } finally { -575 DBUtils.closeResultSet(rs); -576 rs = null; -577 } -578 -579 if (cpeProductId == 0) { -580 insertCpe.setString(1, s.getName()); -581 insertCpe.setString(2, s.getVendor()); -582 insertCpe.setString(3, s.getProduct()); -583 insertCpe.executeUpdate(); -584 cpeProductId = DBUtils.getGeneratedKey(insertCpe); -585 } -586 if (cpeProductId == 0) { -587 throw new DatabaseException("Unable to retrieve cpeProductId - no data returned"); -588 } -589 -590 insertSoftware.setInt(1, vulnerabilityId); -591 insertSoftware.setInt(2, cpeProductId); -592 -593 if (s.getPreviousVersion() == null) { -594 insertSoftware.setNull(3, java.sql.Types.VARCHAR); -595 } else { -596 insertSoftware.setString(3, s.getPreviousVersion()); -597 } -598 if (batchSupported) { -599 insertSoftware.addBatch(); -600 } else { -601 try { -602 insertSoftware.execute(); -603 } catch (SQLException ex) { -604 if (ex.getMessage().contains("Duplicate entry")) { -605 final String msg = String.format("Duplicate software key identified in '%s:%s'", vuln.getName(), s.getName()); -606 LOGGER.debug(msg, ex); -607 } else { -608 throw ex; -609 } -610 } -611 } -612 } -613 if (batchSupported) { -614 insertSoftware.executeBatch(); -615 } -616 } catch (SQLException ex) { -617 final String msg = String.format("Error updating '%s'", vuln.getName()); -618 LOGGER.debug(msg, ex); -619 throw new DatabaseException(msg, ex); -620 } finally { -621 DBUtils.closeStatement(selectVulnerabilityId); -622 DBUtils.closeStatement(deleteReferences); -623 DBUtils.closeStatement(deleteSoftware); -624 DBUtils.closeStatement(updateVulnerability); -625 DBUtils.closeStatement(deleteVulnerability); -626 DBUtils.closeStatement(insertVulnerability); -627 DBUtils.closeStatement(insertReference); -628 DBUtils.closeStatement(selectCpeId); -629 DBUtils.closeStatement(insertCpe); -630 DBUtils.closeStatement(insertSoftware); -631 } -632 } -633 -634 /** -635 * Checks to see if data exists so that analysis can be performed. -636 * -637 * @return <code>true</code> if data exists; otherwise <code>false</code> -638 */ -639 public boolean dataExists() { -640 Statement cs = null; -641 ResultSet rs = null; -642 try { -643 cs = conn.createStatement(); -644 rs = cs.executeQuery("SELECT COUNT(*) records FROM cpeEntry"); -645 if (rs.next()) { -646 if (rs.getInt(1) > 0) { -647 return true; -648 } -649 } -650 } catch (SQLException ex) { -651 String dd; -652 try { -653 dd = Settings.getDataDirectory().getAbsolutePath(); -654 } catch (IOException ex1) { -655 dd = Settings.getString(Settings.KEYS.DATA_DIRECTORY); -656 } -657 LOGGER.error("Unable to access the local database.\n\nEnsure that '{}' is a writable directory. " -658 + "If the problem persist try deleting the files in '{}' and running {} again. If the problem continues, please " -659 + "create a log file (see documentation at http://jeremylong.github.io/DependencyCheck/) and open a ticket at " -660 + "https://github.com/jeremylong/DependencyCheck/issues and include the log file.\n\n", -661 dd, dd, Settings.getString(Settings.KEYS.APPLICATION_VAME)); -662 LOGGER.debug("", ex); -663 } finally { -664 DBUtils.closeResultSet(rs); -665 DBUtils.closeStatement(cs); -666 } -667 return false; -668 } -669 -670 /** -671 * It is possible that orphaned rows may be generated during database -672 * updates. This should be called after all updates have been completed to -673 * ensure orphan entries are removed. -674 */ -675 public void cleanupDatabase() { -676 PreparedStatement ps = null; -677 try { -678 ps = getConnection().prepareStatement(statementBundle.getString("CLEANUP_ORPHANS")); -679 if (ps != null) { -680 ps.executeUpdate(); -681 } -682 } catch (SQLException ex) { -683 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details."); -684 LOGGER.debug("", ex); -685 } finally { -686 DBUtils.closeStatement(ps); -687 } -688 } -689 -690 /** -691 * Determines if the given identifiedVersion is affected by the given cpeId -692 * and previous version flag. A non-null, non-empty string passed to the -693 * previous version argument indicates that all previous versions are -694 * affected. -695 * -696 * @param vendor the vendor of the dependency being analyzed -697 * @param product the product name of the dependency being analyzed -698 * @param vulnerableSoftware a map of the vulnerable software with a boolean -699 * indicating if all previous versions are affected -700 * @param identifiedVersion the identified version of the dependency being -701 * analyzed -702 * @return true if the identified version is affected, otherwise false -703 */ -704 Entry<String, Boolean> getMatchingSoftware(Map<String, Boolean> vulnerableSoftware, String vendor, String product, -705 DependencyVersion identifiedVersion) { -706 -707 final boolean isVersionTwoADifferentProduct = "apache".equals(vendor) && "struts".equals(product); +90 LOGGER.debug("Database dialect: {}", databaseProductName); +91 final Locale dbDialect = new Locale(databaseProductName); +92 statementBundle = ResourceBundle.getBundle("data/dbStatements", dbDialect); +93 if ("mysql".equalsIgnoreCase(databaseProductName)) { +94 batchSupported = false; +95 } +96 } catch (SQLException se) { +97 LOGGER.warn("Problem loading database specific dialect!", se); +98 statementBundle = ResourceBundle.getBundle("data/dbStatements"); +99 } +100 databaseProperties = new DatabaseProperties(this); +101 } catch (DatabaseException ex) { +102 throw ex; +103 } +104 } +105 +106 /** +107 * Returns the database connection. +108 * +109 * @return the database connection +110 */ +111 protected Connection getConnection() { +112 return conn; +113 } +114 +115 /** +116 * Opens the database connection. If the database does not exist, it will +117 * create a new one. +118 * +119 * @throws DatabaseException thrown if there is an error opening the +120 * database connection +121 */ +122 public final void open() throws DatabaseException { +123 if (!isOpen()) { +124 conn = ConnectionFactory.getConnection(); +125 } +126 } +127 +128 /** +129 * Closes the DB4O database. Close should be called on this object when it +130 * is done being used. +131 */ +132 public void close() { +133 if (conn != null) { +134 try { +135 conn.close(); +136 } catch (SQLException ex) { +137 LOGGER.error("There was an error attempting to close the CveDB, see the log for more details."); +138 LOGGER.debug("", ex); +139 } catch (Throwable ex) { +140 LOGGER.error("There was an exception attempting to close the CveDB, see the log for more details."); +141 LOGGER.debug("", ex); +142 } +143 conn = null; +144 } +145 } +146 +147 /** +148 * Returns whether the database connection is open or closed. +149 * +150 * @return whether the database connection is open or closed +151 */ +152 public boolean isOpen() { +153 return conn != null; +154 } +155 +156 /** +157 * Commits all completed transactions. +158 * +159 * @throws SQLException thrown if a SQL Exception occurs +160 */ +161 public void commit() throws SQLException { +162 //temporary remove this as autocommit is on. +163 //if (conn != null) { +164 // conn.commit(); +165 //} +166 } +167 +168 /** +169 * Cleans up the object and ensures that "close" has been called. +170 * +171 * @throws Throwable thrown if there is a problem +172 */ +173 @Override +174 @SuppressWarnings("FinalizeDeclaration") +175 protected void finalize() throws Throwable { +176 LOGGER.debug("Entering finalize"); +177 close(); +178 super.finalize(); +179 } +180 /** +181 * Database properties object containing the 'properties' from the database +182 * table. +183 */ +184 private DatabaseProperties databaseProperties; +185 +186 /** +187 * Get the value of databaseProperties. +188 * +189 * @return the value of databaseProperties +190 */ +191 public DatabaseProperties getDatabaseProperties() { +192 return databaseProperties; +193 } +194 +195 /** +196 * Searches the CPE entries in the database and retrieves all entries for a +197 * given vendor and product combination. The returned list will include all +198 * versions of the product that are registered in the NVD CVE data. +199 * +200 * @param vendor the identified vendor name of the dependency being analyzed +201 * @param product the identified name of the product of the dependency being +202 * analyzed +203 * @return a set of vulnerable software +204 */ +205 public Set<VulnerableSoftware> getCPEs(String vendor, String product) { +206 final Set<VulnerableSoftware> cpe = new HashSet<VulnerableSoftware>(); +207 ResultSet rs = null; +208 PreparedStatement ps = null; +209 try { +210 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_CPE_ENTRIES")); +211 ps.setString(1, vendor); +212 ps.setString(2, product); +213 rs = ps.executeQuery(); +214 +215 while (rs.next()) { +216 final VulnerableSoftware vs = new VulnerableSoftware(); +217 vs.setCpe(rs.getString(1)); +218 cpe.add(vs); +219 } +220 } catch (SQLException ex) { +221 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details."); +222 LOGGER.debug("", ex); +223 } finally { +224 DBUtils.closeResultSet(rs); +225 DBUtils.closeStatement(ps); +226 } +227 return cpe; +228 } +229 +230 /** +231 * Returns the entire list of vendor/product combinations. +232 * +233 * @return the entire list of vendor/product combinations +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 { +238 final Set<Pair<String, String>> data = new HashSet<Pair<String, String>>(); +239 ResultSet rs = null; +240 PreparedStatement ps = null; +241 try { +242 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_VENDOR_PRODUCT_LIST")); +243 rs = ps.executeQuery(); +244 while (rs.next()) { +245 data.add(new Pair<String, String>(rs.getString(1), rs.getString(2))); +246 } +247 } catch (SQLException ex) { +248 final String msg = "An unexpected SQL Exception occurred; please see the verbose log for more details."; +249 throw new DatabaseException(msg, ex); +250 } finally { +251 DBUtils.closeResultSet(rs); +252 DBUtils.closeStatement(ps); +253 } +254 return data; +255 } +256 +257 /** +258 * Returns a set of properties. +259 * +260 * @return the properties from the database +261 */ +262 Properties getProperties() { +263 final Properties prop = new Properties(); +264 PreparedStatement ps = null; +265 ResultSet rs = null; +266 try { +267 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_PROPERTIES")); +268 rs = ps.executeQuery(); +269 while (rs.next()) { +270 prop.setProperty(rs.getString(1), rs.getString(2)); +271 } +272 } catch (SQLException ex) { +273 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details."); +274 LOGGER.debug("", ex); +275 } finally { +276 DBUtils.closeStatement(ps); +277 DBUtils.closeResultSet(rs); +278 } +279 return prop; +280 } +281 +282 /** +283 * Saves a property to the database. +284 * +285 * @param key the property key +286 * @param value the property value +287 */ +288 void saveProperty(String key, String value) { +289 try { +290 try { +291 final PreparedStatement mergeProperty = getConnection().prepareStatement(statementBundle.getString("MERGE_PROPERTY")); +292 try { +293 mergeProperty.setString(1, key); +294 mergeProperty.setString(2, value); +295 mergeProperty.executeUpdate(); +296 } finally { +297 DBUtils.closeStatement(mergeProperty); +298 } +299 } catch (MissingResourceException mre) { +300 // No Merge statement, so doing an Update/Insert... +301 PreparedStatement updateProperty = null; +302 PreparedStatement insertProperty = null; +303 try { +304 updateProperty = getConnection().prepareStatement(statementBundle.getString("UPDATE_PROPERTY")); +305 updateProperty.setString(1, value); +306 updateProperty.setString(2, key); +307 if (updateProperty.executeUpdate() == 0) { +308 insertProperty = getConnection().prepareStatement(statementBundle.getString("INSERT_PROPERTY")); +309 insertProperty.setString(1, key); +310 insertProperty.setString(2, value); +311 insertProperty.executeUpdate(); +312 } +313 } finally { +314 DBUtils.closeStatement(updateProperty); +315 DBUtils.closeStatement(insertProperty); +316 } +317 } +318 } catch (SQLException ex) { +319 LOGGER.warn("Unable to save property '{}' with a value of '{}' to the database", key, value); +320 LOGGER.debug("", ex); +321 } +322 } +323 +324 /** +325 * Retrieves the vulnerabilities associated with the specified CPE. +326 * +327 * @param cpeStr the CPE name +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 { +332 final VulnerableSoftware cpe = new VulnerableSoftware(); +333 try { +334 cpe.parseName(cpeStr); +335 } catch (UnsupportedEncodingException ex) { +336 LOGGER.trace("", ex); +337 } +338 final DependencyVersion detectedVersion = parseDependencyVersion(cpe); +339 final List<Vulnerability> vulnerabilities = new ArrayList<Vulnerability>(); +340 +341 PreparedStatement ps = null; +342 ResultSet rs = null; +343 try { +344 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_CVE_FROM_SOFTWARE")); +345 ps.setString(1, cpe.getVendor()); +346 ps.setString(2, cpe.getProduct()); +347 rs = ps.executeQuery(); +348 String currentCVE = ""; +349 +350 final Map<String, Boolean> vulnSoftware = new HashMap<String, Boolean>(); +351 while (rs.next()) { +352 final String cveId = rs.getString(1); +353 if (!currentCVE.equals(cveId)) { //check for match and add +354 final Entry<String, Boolean> matchedCPE = getMatchingSoftware(vulnSoftware, cpe.getVendor(), cpe.getProduct(), detectedVersion); +355 if (matchedCPE != null) { +356 final Vulnerability v = getVulnerability(currentCVE); +357 v.setMatchedCPE(matchedCPE.getKey(), matchedCPE.getValue() ? "Y" : null); +358 vulnerabilities.add(v); +359 } +360 vulnSoftware.clear(); +361 currentCVE = cveId; +362 } +363 +364 final String cpeId = rs.getString(2); +365 final String previous = rs.getString(3); +366 final Boolean p = previous != null && !previous.isEmpty(); +367 vulnSoftware.put(cpeId, p); +368 } +369 //remember to process the last set of CVE/CPE entries +370 final Entry<String, Boolean> matchedCPE = getMatchingSoftware(vulnSoftware, cpe.getVendor(), cpe.getProduct(), detectedVersion); +371 if (matchedCPE != null) { +372 final Vulnerability v = getVulnerability(currentCVE); +373 v.setMatchedCPE(matchedCPE.getKey(), matchedCPE.getValue() ? "Y" : null); +374 vulnerabilities.add(v); +375 } +376 } catch (SQLException ex) { +377 throw new DatabaseException("Exception retrieving vulnerability for " + cpeStr, ex); +378 } finally { +379 DBUtils.closeResultSet(rs); +380 DBUtils.closeStatement(ps); +381 } +382 return vulnerabilities; +383 } +384 +385 /** +386 * Gets a vulnerability for the provided CVE. +387 * +388 * @param cve the CVE to lookup +389 * @return a vulnerability object +390 * @throws DatabaseException if an exception occurs +391 */ +392 public Vulnerability getVulnerability(String cve) throws DatabaseException { +393 PreparedStatement psV = null; +394 PreparedStatement psR = null; +395 PreparedStatement psS = null; +396 ResultSet rsV = null; +397 ResultSet rsR = null; +398 ResultSet rsS = null; +399 Vulnerability vuln = null; +400 +401 try { +402 psV = getConnection().prepareStatement(statementBundle.getString("SELECT_VULNERABILITY")); +403 psV.setString(1, cve); +404 rsV = psV.executeQuery(); +405 if (rsV.next()) { +406 vuln = new Vulnerability(); +407 vuln.setName(cve); +408 vuln.setDescription(rsV.getString(2)); +409 String cwe = rsV.getString(3); +410 if (cwe != null) { +411 final String name = CweDB.getCweName(cwe); +412 if (name != null) { +413 cwe += ' ' + name; +414 } +415 } +416 final int cveId = rsV.getInt(1); +417 vuln.setCwe(cwe); +418 vuln.setCvssScore(rsV.getFloat(4)); +419 vuln.setCvssAccessVector(rsV.getString(5)); +420 vuln.setCvssAccessComplexity(rsV.getString(6)); +421 vuln.setCvssAuthentication(rsV.getString(7)); +422 vuln.setCvssConfidentialityImpact(rsV.getString(8)); +423 vuln.setCvssIntegrityImpact(rsV.getString(9)); +424 vuln.setCvssAvailabilityImpact(rsV.getString(10)); +425 +426 psR = getConnection().prepareStatement(statementBundle.getString("SELECT_REFERENCES")); +427 psR.setInt(1, cveId); +428 rsR = psR.executeQuery(); +429 while (rsR.next()) { +430 vuln.addReference(rsR.getString(1), rsR.getString(2), rsR.getString(3)); +431 } +432 psS = getConnection().prepareStatement(statementBundle.getString("SELECT_SOFTWARE")); +433 psS.setInt(1, cveId); +434 rsS = psS.executeQuery(); +435 while (rsS.next()) { +436 final String cpe = rsS.getString(1); +437 final String prevVersion = rsS.getString(2); +438 if (prevVersion == null) { +439 vuln.addVulnerableSoftware(cpe); +440 } else { +441 vuln.addVulnerableSoftware(cpe, prevVersion); +442 } +443 } +444 } +445 } catch (SQLException ex) { +446 throw new DatabaseException("Error retrieving " + cve, ex); +447 } finally { +448 DBUtils.closeResultSet(rsV); +449 DBUtils.closeResultSet(rsR); +450 DBUtils.closeResultSet(rsS); +451 DBUtils.closeStatement(psV); +452 DBUtils.closeStatement(psR); +453 DBUtils.closeStatement(psS); +454 } +455 return vuln; +456 } +457 +458 /** +459 * Updates the vulnerability within the database. If the vulnerability does +460 * not exist it will be added. +461 * +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 { +466 PreparedStatement selectVulnerabilityId = null; +467 PreparedStatement deleteVulnerability = null; +468 PreparedStatement deleteReferences = null; +469 PreparedStatement deleteSoftware = null; +470 PreparedStatement updateVulnerability = null; +471 PreparedStatement insertVulnerability = null; +472 PreparedStatement insertReference = null; +473 PreparedStatement selectCpeId = null; +474 PreparedStatement insertCpe = null; +475 PreparedStatement insertSoftware = null; +476 +477 try { +478 selectVulnerabilityId = getConnection().prepareStatement(statementBundle.getString("SELECT_VULNERABILITY_ID")); +479 deleteVulnerability = getConnection().prepareStatement(statementBundle.getString("DELETE_VULNERABILITY")); +480 deleteReferences = getConnection().prepareStatement(statementBundle.getString("DELETE_REFERENCE")); +481 deleteSoftware = getConnection().prepareStatement(statementBundle.getString("DELETE_SOFTWARE")); +482 updateVulnerability = getConnection().prepareStatement(statementBundle.getString("UPDATE_VULNERABILITY")); +483 final String[] ids = {"id"}; +484 insertVulnerability = getConnection().prepareStatement(statementBundle.getString("INSERT_VULNERABILITY"), +485 //Statement.RETURN_GENERATED_KEYS); +486 ids); +487 insertReference = getConnection().prepareStatement(statementBundle.getString("INSERT_REFERENCE")); +488 selectCpeId = getConnection().prepareStatement(statementBundle.getString("SELECT_CPE_ID")); +489 insertCpe = getConnection().prepareStatement(statementBundle.getString("INSERT_CPE"), +490 //Statement.RETURN_GENERATED_KEYS); +491 ids); +492 insertSoftware = getConnection().prepareStatement(statementBundle.getString("INSERT_SOFTWARE")); +493 int vulnerabilityId = 0; +494 selectVulnerabilityId.setString(1, vuln.getName()); +495 ResultSet rs = selectVulnerabilityId.executeQuery(); +496 if (rs.next()) { +497 vulnerabilityId = rs.getInt(1); +498 // first delete any existing vulnerability info. We don't know what was updated. yes, slower but atm easier. +499 deleteReferences.setInt(1, vulnerabilityId); +500 deleteReferences.execute(); +501 deleteSoftware.setInt(1, vulnerabilityId); +502 deleteSoftware.execute(); +503 } +504 DBUtils.closeResultSet(rs); +505 rs = null; +506 +507 if (vulnerabilityId != 0) { +508 if (vuln.getDescription().contains("** REJECT **")) { +509 deleteVulnerability.setInt(1, vulnerabilityId); +510 deleteVulnerability.executeUpdate(); +511 } else { +512 updateVulnerability.setString(1, vuln.getDescription()); +513 updateVulnerability.setString(2, vuln.getCwe()); +514 updateVulnerability.setFloat(3, vuln.getCvssScore()); +515 updateVulnerability.setString(4, vuln.getCvssAccessVector()); +516 updateVulnerability.setString(5, vuln.getCvssAccessComplexity()); +517 updateVulnerability.setString(6, vuln.getCvssAuthentication()); +518 updateVulnerability.setString(7, vuln.getCvssConfidentialityImpact()); +519 updateVulnerability.setString(8, vuln.getCvssIntegrityImpact()); +520 updateVulnerability.setString(9, vuln.getCvssAvailabilityImpact()); +521 updateVulnerability.setInt(10, vulnerabilityId); +522 updateVulnerability.executeUpdate(); +523 } +524 } else { +525 insertVulnerability.setString(1, vuln.getName()); +526 insertVulnerability.setString(2, vuln.getDescription()); +527 insertVulnerability.setString(3, vuln.getCwe()); +528 insertVulnerability.setFloat(4, vuln.getCvssScore()); +529 insertVulnerability.setString(5, vuln.getCvssAccessVector()); +530 insertVulnerability.setString(6, vuln.getCvssAccessComplexity()); +531 insertVulnerability.setString(7, vuln.getCvssAuthentication()); +532 insertVulnerability.setString(8, vuln.getCvssConfidentialityImpact()); +533 insertVulnerability.setString(9, vuln.getCvssIntegrityImpact()); +534 insertVulnerability.setString(10, vuln.getCvssAvailabilityImpact()); +535 insertVulnerability.execute(); +536 try { +537 rs = insertVulnerability.getGeneratedKeys(); +538 rs.next(); +539 vulnerabilityId = rs.getInt(1); +540 } catch (SQLException ex) { +541 final String msg = String.format("Unable to retrieve id for new vulnerability for '%s'", vuln.getName()); +542 throw new DatabaseException(msg, ex); +543 } finally { +544 DBUtils.closeResultSet(rs); +545 rs = null; +546 } +547 } +548 +549 for (Reference r : vuln.getReferences()) { +550 insertReference.setInt(1, vulnerabilityId); +551 insertReference.setString(2, r.getName()); +552 insertReference.setString(3, r.getUrl()); +553 insertReference.setString(4, r.getSource()); +554 +555 if (batchSupported) { +556 insertReference.addBatch(); +557 } else { +558 insertReference.execute(); +559 } +560 } +561 +562 if (batchSupported) { +563 insertReference.executeBatch(); +564 } +565 +566 for (VulnerableSoftware s : vuln.getVulnerableSoftware()) { +567 int cpeProductId = 0; +568 selectCpeId.setString(1, s.getName()); +569 try { +570 rs = selectCpeId.executeQuery(); +571 if (rs.next()) { +572 cpeProductId = rs.getInt(1); +573 } +574 } catch (SQLException ex) { +575 throw new DatabaseException("Unable to get primary key for new cpe: " + s.getName(), ex); +576 } finally { +577 DBUtils.closeResultSet(rs); +578 rs = null; +579 } +580 +581 if (cpeProductId == 0) { +582 insertCpe.setString(1, s.getName()); +583 insertCpe.setString(2, s.getVendor()); +584 insertCpe.setString(3, s.getProduct()); +585 insertCpe.executeUpdate(); +586 cpeProductId = DBUtils.getGeneratedKey(insertCpe); +587 } +588 if (cpeProductId == 0) { +589 throw new DatabaseException("Unable to retrieve cpeProductId - no data returned"); +590 } +591 +592 insertSoftware.setInt(1, vulnerabilityId); +593 insertSoftware.setInt(2, cpeProductId); +594 +595 if (s.getPreviousVersion() == null) { +596 insertSoftware.setNull(3, java.sql.Types.VARCHAR); +597 } else { +598 insertSoftware.setString(3, s.getPreviousVersion()); +599 } +600 if (batchSupported) { +601 insertSoftware.addBatch(); +602 } else { +603 try { +604 insertSoftware.execute(); +605 } catch (SQLException ex) { +606 if (ex.getMessage().contains("Duplicate entry")) { +607 final String msg = String.format("Duplicate software key identified in '%s:%s'", vuln.getName(), s.getName()); +608 LOGGER.debug(msg, ex); +609 } else { +610 throw ex; +611 } +612 } +613 } +614 } +615 if (batchSupported) { +616 insertSoftware.executeBatch(); +617 } +618 } catch (SQLException ex) { +619 final String msg = String.format("Error updating '%s'", vuln.getName()); +620 LOGGER.debug(msg, ex); +621 throw new DatabaseException(msg, ex); +622 } finally { +623 DBUtils.closeStatement(selectVulnerabilityId); +624 DBUtils.closeStatement(deleteReferences); +625 DBUtils.closeStatement(deleteSoftware); +626 DBUtils.closeStatement(updateVulnerability); +627 DBUtils.closeStatement(deleteVulnerability); +628 DBUtils.closeStatement(insertVulnerability); +629 DBUtils.closeStatement(insertReference); +630 DBUtils.closeStatement(selectCpeId); +631 DBUtils.closeStatement(insertCpe); +632 DBUtils.closeStatement(insertSoftware); +633 } +634 } +635 +636 /** +637 * Checks to see if data exists so that analysis can be performed. +638 * +639 * @return <code>true</code> if data exists; otherwise <code>false</code> +640 */ +641 public boolean dataExists() { +642 Statement cs = null; +643 ResultSet rs = null; +644 try { +645 cs = conn.createStatement(); +646 rs = cs.executeQuery("SELECT COUNT(*) records FROM cpeEntry"); +647 if (rs.next()) { +648 if (rs.getInt(1) > 0) { +649 return true; +650 } +651 } +652 } catch (SQLException ex) { +653 String dd; +654 try { +655 dd = Settings.getDataDirectory().getAbsolutePath(); +656 } catch (IOException ex1) { +657 dd = Settings.getString(Settings.KEYS.DATA_DIRECTORY); +658 } +659 LOGGER.error("Unable to access the local database.\n\nEnsure that '{}' is a writable directory. " +660 + "If the problem persist try deleting the files in '{}' and running {} again. If the problem continues, please " +661 + "create a log file (see documentation at http://jeremylong.github.io/DependencyCheck/) and open a ticket at " +662 + "https://github.com/jeremylong/DependencyCheck/issues and include the log file.\n\n", +663 dd, dd, Settings.getString(Settings.KEYS.APPLICATION_NAME)); +664 LOGGER.debug("", ex); +665 } finally { +666 DBUtils.closeResultSet(rs); +667 DBUtils.closeStatement(cs); +668 } +669 return false; +670 } +671 +672 /** +673 * It is possible that orphaned rows may be generated during database +674 * updates. This should be called after all updates have been completed to +675 * ensure orphan entries are removed. +676 */ +677 public void cleanupDatabase() { +678 PreparedStatement ps = null; +679 try { +680 ps = getConnection().prepareStatement(statementBundle.getString("CLEANUP_ORPHANS")); +681 if (ps != null) { +682 ps.executeUpdate(); +683 } +684 } catch (SQLException ex) { +685 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details."); +686 LOGGER.debug("", ex); +687 } finally { +688 DBUtils.closeStatement(ps); +689 } +690 } +691 +692 /** +693 * Determines if the given identifiedVersion is affected by the given cpeId +694 * and previous version flag. A non-null, non-empty string passed to the +695 * previous version argument indicates that all previous versions are +696 * affected. +697 * +698 * @param vendor the vendor of the dependency being analyzed +699 * @param product the product name of the dependency being analyzed +700 * @param vulnerableSoftware a map of the vulnerable software with a boolean +701 * indicating if all previous versions are affected +702 * @param identifiedVersion the identified version of the dependency being +703 * analyzed +704 * @return true if the identified version is affected, otherwise false +705 */ +706 Entry<String, Boolean> getMatchingSoftware(Map<String, Boolean> vulnerableSoftware, String vendor, String product, +707 DependencyVersion identifiedVersion) { 708 -709 final Set<String> majorVersionsAffectingAllPrevious = new HashSet<String>(); -710 final boolean matchesAnyPrevious = identifiedVersion == null || "-".equals(identifiedVersion.toString()); -711 String majorVersionMatch = null; -712 for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) { -713 final DependencyVersion v = parseDependencyVersion(entry.getKey()); -714 if (v == null || "-".equals(v.toString())) { //all versions -715 return entry; -716 } -717 if (entry.getValue()) { -718 if (matchesAnyPrevious) { -719 return entry; -720 } -721 if (identifiedVersion != null && identifiedVersion.getVersionParts().get(0).equals(v.getVersionParts().get(0))) { -722 majorVersionMatch = v.getVersionParts().get(0); -723 } -724 majorVersionsAffectingAllPrevious.add(v.getVersionParts().get(0)); -725 } -726 } -727 if (matchesAnyPrevious) { -728 return null; -729 } -730 -731 final boolean canSkipVersions = majorVersionMatch != null && majorVersionsAffectingAllPrevious.size() > 1; -732 //yes, we are iterating over this twice. The first time we are skipping versions those that affect all versions -733 //then later we process those that affect all versions. This could be done with sorting... -734 for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) { -735 if (!entry.getValue()) { -736 final DependencyVersion v = parseDependencyVersion(entry.getKey()); -737 //this can't dereference a null 'majorVersionMatch' as canSkipVersions accounts for this. -738 if (canSkipVersions && !majorVersionMatch.equals(v.getVersionParts().get(0))) { -739 continue; -740 } -741 //this can't dereference a null 'identifiedVersion' because if it was null we would have exited -742 //in the above loop or just after loop (if matchesAnyPrevious return null). -743 if (identifiedVersion.equals(v)) { -744 return entry; -745 } -746 } -747 } -748 for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) { -749 if (entry.getValue()) { -750 final DependencyVersion v = parseDependencyVersion(entry.getKey()); -751 //this can't dereference a null 'majorVersionMatch' as canSkipVersions accounts for this. -752 if (canSkipVersions && !majorVersionMatch.equals(v.getVersionParts().get(0))) { -753 continue; -754 } -755 //this can't dereference a null 'identifiedVersion' because if it was null we would have exited -756 //in the above loop or just after loop (if matchesAnyPrevious return null). -757 if (entry.getValue() && identifiedVersion.compareTo(v) <= 0) { -758 if (!(isVersionTwoADifferentProduct && !identifiedVersion.getVersionParts().get(0).equals(v.getVersionParts().get(0)))) { -759 return entry; -760 } -761 } -762 } -763 } -764 return null; -765 } -766 -767 /** -768 * Parses the version (including revision) from a CPE identifier. If no -769 * version is identified then a '-' is returned. -770 * -771 * @param cpeStr a cpe identifier -772 * @return a dependency version -773 */ -774 private DependencyVersion parseDependencyVersion(String cpeStr) { -775 final VulnerableSoftware cpe = new VulnerableSoftware(); -776 try { -777 cpe.parseName(cpeStr); -778 } catch (UnsupportedEncodingException ex) { -779 //never going to happen. -780 LOGGER.trace("", ex); -781 } -782 return parseDependencyVersion(cpe); -783 } -784 -785 /** -786 * Takes a CPE and parses out the version number. If no version is -787 * identified then a '-' is returned. -788 * -789 * @param cpe a cpe object -790 * @return a dependency version -791 */ -792 private DependencyVersion parseDependencyVersion(VulnerableSoftware cpe) { -793 final DependencyVersion cpeVersion; -794 if (cpe.getVersion() != null && !cpe.getVersion().isEmpty()) { -795 final String versionText; -796 if (cpe.getUpdate() != null && !cpe.getUpdate().isEmpty()) { -797 versionText = String.format("%s.%s", cpe.getVersion(), cpe.getUpdate()); -798 } else { -799 versionText = cpe.getVersion(); -800 } -801 cpeVersion = DependencyVersionUtil.parseVersion(versionText); -802 } else { -803 cpeVersion = new DependencyVersion("-"); -804 } -805 return cpeVersion; -806 } -807 -808 /** -809 * This method is only referenced in unused code. -810 * -811 * Deletes unused dictionary entries from the database. -812 */ -813 public void deleteUnusedCpe() { -814 PreparedStatement ps = null; -815 try { -816 ps = getConnection().prepareStatement(statementBundle.getString("DELETE_UNUSED_DICT_CPE")); -817 ps.executeUpdate(); -818 } catch (SQLException ex) { -819 LOGGER.error("Unable to delete CPE dictionary entries", ex); -820 } finally { -821 DBUtils.closeStatement(ps); -822 } -823 } -824 -825 /** -826 * This method is only referenced in unused code and will likely break on -827 * MySQL if ever used due to the MERGE statement. -828 * -829 * Merges CPE entries into the database. +709 final boolean isVersionTwoADifferentProduct = "apache".equals(vendor) && "struts".equals(product); +710 +711 final Set<String> majorVersionsAffectingAllPrevious = new HashSet<String>(); +712 final boolean matchesAnyPrevious = identifiedVersion == null || "-".equals(identifiedVersion.toString()); +713 String majorVersionMatch = null; +714 for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) { +715 final DependencyVersion v = parseDependencyVersion(entry.getKey()); +716 if (v == null || "-".equals(v.toString())) { //all versions +717 return entry; +718 } +719 if (entry.getValue()) { +720 if (matchesAnyPrevious) { +721 return entry; +722 } +723 if (identifiedVersion != null && identifiedVersion.getVersionParts().get(0).equals(v.getVersionParts().get(0))) { +724 majorVersionMatch = v.getVersionParts().get(0); +725 } +726 majorVersionsAffectingAllPrevious.add(v.getVersionParts().get(0)); +727 } +728 } +729 if (matchesAnyPrevious) { +730 return null; +731 } +732 +733 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 for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) { +737 if (!entry.getValue()) { +738 final DependencyVersion v = parseDependencyVersion(entry.getKey()); +739 //this can't dereference a null 'majorVersionMatch' as canSkipVersions accounts for this. +740 if (canSkipVersions && !majorVersionMatch.equals(v.getVersionParts().get(0))) { +741 continue; +742 } +743 //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 if (identifiedVersion.equals(v)) { +746 return entry; +747 } +748 } +749 } +750 for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) { +751 if (entry.getValue()) { +752 final DependencyVersion v = parseDependencyVersion(entry.getKey()); +753 //this can't dereference a null 'majorVersionMatch' as canSkipVersions accounts for this. +754 if (canSkipVersions && !majorVersionMatch.equals(v.getVersionParts().get(0))) { +755 continue; +756 } +757 //this can't dereference a null 'identifiedVersion' because if it was null we would have exited +758 //in the above loop or just after loop (if matchesAnyPrevious return null). +759 if (entry.getValue() && identifiedVersion.compareTo(v) <= 0) { +760 if (!(isVersionTwoADifferentProduct && !identifiedVersion.getVersionParts().get(0).equals(v.getVersionParts().get(0)))) { +761 return entry; +762 } +763 } +764 } +765 } +766 return null; +767 } +768 +769 /** +770 * Parses the version (including revision) from a CPE identifier. If no +771 * version is identified then a '-' is returned. +772 * +773 * @param cpeStr a cpe identifier +774 * @return a dependency version +775 */ +776 private DependencyVersion parseDependencyVersion(String cpeStr) { +777 final VulnerableSoftware cpe = new VulnerableSoftware(); +778 try { +779 cpe.parseName(cpeStr); +780 } catch (UnsupportedEncodingException ex) { +781 //never going to happen. +782 LOGGER.trace("", ex); +783 } +784 return parseDependencyVersion(cpe); +785 } +786 +787 /** +788 * Takes a CPE and parses out the version number. If no version is +789 * identified then a '-' is returned. +790 * +791 * @param cpe a cpe object +792 * @return a dependency version +793 */ +794 private DependencyVersion parseDependencyVersion(VulnerableSoftware cpe) { +795 final DependencyVersion cpeVersion; +796 if (cpe.getVersion() != null && !cpe.getVersion().isEmpty()) { +797 final String versionText; +798 if (cpe.getUpdate() != null && !cpe.getUpdate().isEmpty()) { +799 versionText = String.format("%s.%s", cpe.getVersion(), cpe.getUpdate()); +800 } else { +801 versionText = cpe.getVersion(); +802 } +803 cpeVersion = DependencyVersionUtil.parseVersion(versionText); +804 } else { +805 cpeVersion = new DependencyVersion("-"); +806 } +807 return cpeVersion; +808 } +809 +810 /** +811 * This method is only referenced in unused code. +812 * +813 * Deletes unused dictionary entries from the database. +814 */ +815 public void deleteUnusedCpe() { +816 PreparedStatement ps = null; +817 try { +818 ps = getConnection().prepareStatement(statementBundle.getString("DELETE_UNUSED_DICT_CPE")); +819 ps.executeUpdate(); +820 } catch (SQLException ex) { +821 LOGGER.error("Unable to delete CPE dictionary entries", ex); +822 } finally { +823 DBUtils.closeStatement(ps); +824 } +825 } +826 +827 /** +828 * This method is only referenced in unused code and will likely break on +829 * MySQL if ever used due to the MERGE statement. 830 * -831 * @param cpe the CPE identifier -832 * @param vendor the CPE vendor -833 * @param product the CPE product -834 */ -835 public void addCpe(String cpe, String vendor, String product) { -836 PreparedStatement ps = null; -837 try { -838 ps = getConnection().prepareStatement(statementBundle.getString("ADD_DICT_CPE")); -839 ps.setString(1, cpe); -840 ps.setString(2, vendor); -841 ps.setString(3, product); -842 ps.executeUpdate(); -843 } catch (SQLException ex) { -844 LOGGER.error("Unable to add CPE dictionary entry", ex); -845 } finally { -846 DBUtils.closeStatement(ps); -847 } -848 } -849 } +831 * Merges CPE entries into the database. +832 * +833 * @param cpe the CPE identifier +834 * @param vendor the CPE vendor +835 * @param product the CPE product +836 */ +837 public void addCpe(String cpe, String vendor, String product) { +838 PreparedStatement ps = null; +839 try { +840 ps = getConnection().prepareStatement(statementBundle.getString("ADD_DICT_CPE")); +841 ps.setString(1, cpe); +842 ps.setString(2, vendor); +843 ps.setString(3, product); +844 ps.executeUpdate(); +845 } catch (SQLException ex) { +846 LOGGER.error("Unable to add CPE dictionary entry", ex); +847 } finally { +848 DBUtils.closeStatement(ps); +849 } +850 } +851 }
    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 b0d2aecee..32bb11201 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.2 Reference Package org.owasp.dependencycheck.data.nvdcve + Dependency-Check Core 1.4.3 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 2ca21ca60..afcb19c07 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.2 Reference Package org.owasp.dependencycheck.data.nvdcve + Dependency-Check Core 1.4.3 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 19eb152fa..7a0aec0a8 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 @@ -166,46 +166,48 @@ 158 final String originalPath = file.getPath(); 159 final File gzip = new File(originalPath + ".gz"); 160 if (gzip.isFile() && !gzip.delete()) { -161 gzip.deleteOnExit(); -162 } -163 if (!file.renameTo(gzip)) { -164 throw new IOException("Unable to rename '" + file.getPath() + "'"); -165 } -166 final File newfile = new File(originalPath); -167 -168 final byte[] buffer = new byte[4096]; -169 -170 GZIPInputStream cin = null; -171 FileOutputStream out = null; -172 try { -173 cin = new GZIPInputStream(new FileInputStream(gzip)); -174 out = new FileOutputStream(newfile); -175 -176 int len; -177 while ((len = cin.read(buffer)) > 0) { -178 out.write(buffer, 0, len); -179 } -180 } finally { -181 if (cin != null) { -182 try { -183 cin.close(); -184 } catch (IOException ex) { -185 LOGGER.trace("ignore", ex); -186 } -187 } -188 if (out != null) { -189 try { -190 out.close(); -191 } catch (IOException ex) { -192 LOGGER.trace("ignore", ex); -193 } -194 } -195 if (gzip.isFile()) { -196 FileUtils.deleteQuietly(gzip); -197 } -198 } -199 } -200 } +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); +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 } +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 }
    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 756ce7202..1edd3a333 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 @@ -228,11 +228,11 @@ 220 return releaseVersion.trim(); 221 } 222 } catch (MalformedURLException ex) { -223 LOGGER.debug("Unable to retrieve current release version of dependency-check", ex); +223 LOGGER.debug("Unable to retrieve current release version of dependency-check - malformed url?"); 224 } catch (URLConnectionFailureException ex) { -225 LOGGER.debug("Unable to retrieve current release version of dependency-check", ex); +225 LOGGER.debug("Unable to retrieve current release version of dependency-check - connection failed"); 226 } catch (IOException ex) { -227 LOGGER.debug("Unable to retrieve current release version of dependency-check", ex); +227 LOGGER.debug("Unable to retrieve current release version of dependency-check - i/o exception"); 228 } finally { 229 if (conn != null) { 230 conn.disconnect(); diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/NvdCveUpdater.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/NvdCveUpdater.html index 3ec41ca83..54578b575 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/NvdCveUpdater.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/NvdCveUpdater.html @@ -85,10 +85,10 @@ 77 } 78 if (autoUpdate && checkUpdate()) { 79 final UpdateableNvdCve updateable = getUpdatesNeeded(); -80 getProperties().save(DatabaseProperties.LAST_CHECKED, Long.toString(System.currentTimeMillis())); -81 if (updateable.isUpdateNeeded()) { -82 performUpdate(updateable); -83 } +80 if (updateable.isUpdateNeeded()) { +81 performUpdate(updateable); +82 } +83 getProperties().save(DatabaseProperties.LAST_CHECKED, Long.toString(System.currentTimeMillis())); 84 } 85 } catch (MalformedURLException ex) { 86 throw new UpdateException("NVD CVE properties files contain an invalid URL, unable to update the data to use the most current data.", ex); @@ -164,200 +164,193 @@ 156 * @throws UpdateException is thrown if there is an error updating the 157 * database 158 */ -159 public void performUpdate(UpdateableNvdCve updateable) throws UpdateException { +159 private void performUpdate(UpdateableNvdCve updateable) throws UpdateException { 160 int maxUpdates = 0; -161 try { -162 for (NvdCveInfo cve : updateable) { -163 if (cve.getNeedsUpdate()) { -164 maxUpdates += 1; -165 } -166 } -167 if (maxUpdates <= 0) { -168 return; -169 } -170 if (maxUpdates > 3) { -171 LOGGER.info("NVD CVE requires several updates; this could take a couple of minutes."); -172 } -173 if (maxUpdates > 0) { -174 openDataStores(); -175 } -176 -177 final int poolSize = (MAX_THREAD_POOL_SIZE < maxUpdates) ? MAX_THREAD_POOL_SIZE : maxUpdates; -178 -179 final ExecutorService downloadExecutors = Executors.newFixedThreadPool(poolSize); -180 final ExecutorService processExecutor = Executors.newSingleThreadExecutor(); -181 final Set<Future<Future<ProcessTask>>> downloadFutures = new HashSet<Future<Future<ProcessTask>>>(maxUpdates); -182 for (NvdCveInfo cve : updateable) { -183 if (cve.getNeedsUpdate()) { -184 final DownloadTask call = new DownloadTask(cve, processExecutor, getCveDB(), Settings.getInstance()); -185 downloadFutures.add(downloadExecutors.submit(call)); -186 } -187 } -188 downloadExecutors.shutdown(); -189 -190 //next, move the future future processTasks to just future processTasks -191 final Set<Future<ProcessTask>> processFutures = new HashSet<Future<ProcessTask>>(maxUpdates); -192 for (Future<Future<ProcessTask>> future : downloadFutures) { -193 Future<ProcessTask> task = null; -194 try { -195 task = future.get(); -196 } catch (InterruptedException ex) { -197 downloadExecutors.shutdownNow(); -198 processExecutor.shutdownNow(); -199 -200 LOGGER.debug("Thread was interrupted during download", ex); -201 throw new UpdateException("The download was interrupted", ex); -202 } catch (ExecutionException ex) { -203 downloadExecutors.shutdownNow(); -204 processExecutor.shutdownNow(); -205 -206 LOGGER.debug("Thread was interrupted during download execution", ex); -207 throw new UpdateException("The execution of the download was interrupted", ex); -208 } -209 if (task == null) { -210 downloadExecutors.shutdownNow(); -211 processExecutor.shutdownNow(); -212 LOGGER.debug("Thread was interrupted during download"); -213 throw new UpdateException("The download was interrupted; unable to complete the update"); -214 } else { -215 processFutures.add(task); -216 } -217 } -218 -219 for (Future<ProcessTask> future : processFutures) { -220 try { -221 final ProcessTask task = future.get(); -222 if (task.getException() != null) { -223 throw task.getException(); -224 } -225 } catch (InterruptedException ex) { -226 processExecutor.shutdownNow(); -227 LOGGER.debug("Thread was interrupted during processing", ex); -228 throw new UpdateException(ex); -229 } catch (ExecutionException ex) { -230 processExecutor.shutdownNow(); -231 LOGGER.debug("Execution Exception during process", ex); -232 throw new UpdateException(ex); -233 } finally { -234 processExecutor.shutdown(); -235 } -236 } -237 -238 if (maxUpdates >= 1) { //ensure the modified file date gets written (we may not have actually updated it) -239 getProperties().save(updateable.get(MODIFIED)); -240 LOGGER.info("Begin database maintenance."); -241 getCveDB().cleanupDatabase(); -242 LOGGER.info("End database maintenance."); -243 } -244 } finally { -245 closeDataStores(); -246 } -247 } -248 -249 /** -250 * Determines if the index needs to be updated. This is done by fetching the -251 * NVD CVE meta data and checking the last update date. If the data needs to -252 * be refreshed this method will return the NvdCveUrl for the files that -253 * need to be updated. -254 * -255 * @return the collection of files that need to be updated -256 * @throws MalformedURLException is thrown if the URL for the NVD CVE Meta -257 * data is incorrect -258 * @throws DownloadFailedException is thrown if there is an error. -259 * downloading the NVD CVE download data file -260 * @throws UpdateException Is thrown if there is an issue with the last -261 * updated properties file -262 */ -263 protected final UpdateableNvdCve getUpdatesNeeded() throws MalformedURLException, DownloadFailedException, UpdateException { -264 UpdateableNvdCve updates = null; -265 try { -266 updates = retrieveCurrentTimestampsFromWeb(); -267 } catch (InvalidDataException ex) { -268 final String msg = "Unable to retrieve valid timestamp from nvd cve downloads page"; -269 LOGGER.debug(msg, ex); -270 throw new DownloadFailedException(msg, ex); -271 } catch (InvalidSettingException ex) { -272 LOGGER.debug("Invalid setting found when retrieving timestamps", ex); -273 throw new DownloadFailedException("Invalid settings", ex); -274 } -275 -276 if (updates == null) { -277 throw new DownloadFailedException("Unable to retrieve the timestamps of the currently published NVD CVE data"); -278 } -279 if (!getProperties().isEmpty()) { -280 try { -281 final long lastUpdated = Long.parseLong(getProperties().getProperty(DatabaseProperties.LAST_UPDATED, "0")); -282 final long now = System.currentTimeMillis(); -283 final int days = Settings.getInt(Settings.KEYS.CVE_MODIFIED_VALID_FOR_DAYS, 7); -284 if (lastUpdated == updates.getTimeStamp(MODIFIED)) { -285 updates.clear(); //we don't need to update anything. -286 } else if (DateUtil.withinDateRange(lastUpdated, now, days)) { -287 for (NvdCveInfo entry : updates) { -288 if (MODIFIED.equals(entry.getId())) { -289 entry.setNeedsUpdate(true); -290 } else { -291 entry.setNeedsUpdate(false); -292 } -293 } -294 } else { //we figure out which of the several XML files need to be downloaded. -295 for (NvdCveInfo entry : updates) { -296 if (MODIFIED.equals(entry.getId())) { -297 entry.setNeedsUpdate(true); -298 } else { -299 long currentTimestamp = 0; -300 try { -301 currentTimestamp = Long.parseLong(getProperties().getProperty(DatabaseProperties.LAST_UPDATED_BASE -302 + entry.getId(), "0")); -303 } catch (NumberFormatException ex) { -304 LOGGER.debug("Error parsing '{}' '{}' from nvdcve.lastupdated", -305 DatabaseProperties.LAST_UPDATED_BASE, entry.getId(), ex); -306 } -307 if (currentTimestamp == entry.getTimestamp()) { -308 entry.setNeedsUpdate(false); -309 } -310 } -311 } -312 } -313 } catch (NumberFormatException ex) { -314 LOGGER.warn("An invalid schema version or timestamp exists in the data.properties file."); -315 LOGGER.debug("", ex); -316 } -317 } -318 return updates; -319 } -320 -321 /** -322 * Retrieves the timestamps from the NVD CVE meta data file. -323 * -324 * @return the timestamp from the currently published nvdcve downloads page -325 * @throws MalformedURLException thrown if the URL for the NVD CCE Meta data -326 * is incorrect. -327 * @throws DownloadFailedException thrown if there is an error downloading -328 * the nvd cve meta data file -329 * @throws InvalidDataException thrown if there is an exception parsing the -330 * timestamps -331 * @throws InvalidSettingException thrown if the settings are invalid -332 */ -333 private UpdateableNvdCve retrieveCurrentTimestampsFromWeb() -334 throws MalformedURLException, DownloadFailedException, InvalidDataException, InvalidSettingException { -335 -336 final UpdateableNvdCve updates = new UpdateableNvdCve(); -337 updates.add(MODIFIED, Settings.getString(Settings.KEYS.CVE_MODIFIED_20_URL), -338 Settings.getString(Settings.KEYS.CVE_MODIFIED_12_URL), -339 false); -340 -341 final int start = Settings.getInt(Settings.KEYS.CVE_START_YEAR); -342 final int end = Calendar.getInstance().get(Calendar.YEAR); -343 final String baseUrl20 = Settings.getString(Settings.KEYS.CVE_SCHEMA_2_0); -344 final String baseUrl12 = Settings.getString(Settings.KEYS.CVE_SCHEMA_1_2); -345 for (int i = start; i <= end; i++) { -346 updates.add(Integer.toString(i), String.format(baseUrl20, i), -347 String.format(baseUrl12, i), -348 true); -349 } -350 return updates; -351 } -352 } +161 for (NvdCveInfo cve : updateable) { +162 if (cve.getNeedsUpdate()) { +163 maxUpdates += 1; +164 } +165 } +166 if (maxUpdates <= 0) { +167 return; +168 } +169 if (maxUpdates > 3) { +170 LOGGER.info("NVD CVE requires several updates; this could take a couple of minutes."); +171 } +172 +173 final int poolSize = (MAX_THREAD_POOL_SIZE < maxUpdates) ? MAX_THREAD_POOL_SIZE : maxUpdates; +174 +175 final ExecutorService downloadExecutors = Executors.newFixedThreadPool(poolSize); +176 final ExecutorService processExecutor = Executors.newSingleThreadExecutor(); +177 final Set<Future<Future<ProcessTask>>> downloadFutures = new HashSet<Future<Future<ProcessTask>>>(maxUpdates); +178 for (NvdCveInfo cve : updateable) { +179 if (cve.getNeedsUpdate()) { +180 final DownloadTask call = new DownloadTask(cve, processExecutor, getCveDB(), Settings.getInstance()); +181 downloadFutures.add(downloadExecutors.submit(call)); +182 } +183 } +184 downloadExecutors.shutdown(); +185 +186 //next, move the future future processTasks to just future processTasks +187 final Set<Future<ProcessTask>> processFutures = new HashSet<Future<ProcessTask>>(maxUpdates); +188 for (Future<Future<ProcessTask>> future : downloadFutures) { +189 Future<ProcessTask> task = null; +190 try { +191 task = future.get(); +192 } catch (InterruptedException ex) { +193 downloadExecutors.shutdownNow(); +194 processExecutor.shutdownNow(); +195 +196 LOGGER.debug("Thread was interrupted during download", ex); +197 throw new UpdateException("The download was interrupted", ex); +198 } catch (ExecutionException ex) { +199 downloadExecutors.shutdownNow(); +200 processExecutor.shutdownNow(); +201 +202 LOGGER.debug("Thread was interrupted during download execution", ex); +203 throw new UpdateException("The execution of the download was interrupted", ex); +204 } +205 if (task == null) { +206 downloadExecutors.shutdownNow(); +207 processExecutor.shutdownNow(); +208 LOGGER.debug("Thread was interrupted during download"); +209 throw new UpdateException("The download was interrupted; unable to complete the update"); +210 } else { +211 processFutures.add(task); +212 } +213 } +214 +215 for (Future<ProcessTask> future : processFutures) { +216 try { +217 final ProcessTask task = future.get(); +218 if (task.getException() != null) { +219 throw task.getException(); +220 } +221 } catch (InterruptedException ex) { +222 processExecutor.shutdownNow(); +223 LOGGER.debug("Thread was interrupted during processing", ex); +224 throw new UpdateException(ex); +225 } catch (ExecutionException ex) { +226 processExecutor.shutdownNow(); +227 LOGGER.debug("Execution Exception during process", ex); +228 throw new UpdateException(ex); +229 } finally { +230 processExecutor.shutdown(); +231 } +232 } +233 +234 if (maxUpdates >= 1) { //ensure the modified file date gets written (we may not have actually updated it) +235 getProperties().save(updateable.get(MODIFIED)); +236 LOGGER.info("Begin database maintenance."); +237 getCveDB().cleanupDatabase(); +238 LOGGER.info("End database maintenance."); +239 } +240 } +241 +242 /** +243 * Determines if the index needs to be updated. This is done by fetching the +244 * NVD CVE meta data and checking the last update date. If the data needs to +245 * be refreshed this method will return the NvdCveUrl for the files that +246 * need to be updated. +247 * +248 * @return the collection of files that need to be updated +249 * @throws MalformedURLException is thrown if the URL for the NVD CVE Meta +250 * data is incorrect +251 * @throws DownloadFailedException is thrown if there is an error. +252 * downloading the NVD CVE download data file +253 * @throws UpdateException Is thrown if there is an issue with the last +254 * updated properties file +255 */ +256 protected final UpdateableNvdCve getUpdatesNeeded() throws MalformedURLException, DownloadFailedException, UpdateException { +257 UpdateableNvdCve updates = null; +258 try { +259 updates = retrieveCurrentTimestampsFromWeb(); +260 } catch (InvalidDataException ex) { +261 final String msg = "Unable to retrieve valid timestamp from nvd cve downloads page"; +262 LOGGER.debug(msg, ex); +263 throw new DownloadFailedException(msg, ex); +264 } catch (InvalidSettingException ex) { +265 LOGGER.debug("Invalid setting found when retrieving timestamps", ex); +266 throw new DownloadFailedException("Invalid settings", ex); +267 } +268 +269 if (updates == null) { +270 throw new DownloadFailedException("Unable to retrieve the timestamps of the currently published NVD CVE data"); +271 } +272 if (!getProperties().isEmpty()) { +273 try { +274 final long lastUpdated = Long.parseLong(getProperties().getProperty(DatabaseProperties.LAST_UPDATED, "0")); +275 final long now = System.currentTimeMillis(); +276 final int days = Settings.getInt(Settings.KEYS.CVE_MODIFIED_VALID_FOR_DAYS, 7); +277 if (lastUpdated == updates.getTimeStamp(MODIFIED)) { +278 updates.clear(); //we don't need to update anything. +279 } else if (DateUtil.withinDateRange(lastUpdated, now, days)) { +280 for (NvdCveInfo entry : updates) { +281 if (MODIFIED.equals(entry.getId())) { +282 entry.setNeedsUpdate(true); +283 } else { +284 entry.setNeedsUpdate(false); +285 } +286 } +287 } else { //we figure out which of the several XML files need to be downloaded. +288 for (NvdCveInfo entry : updates) { +289 if (MODIFIED.equals(entry.getId())) { +290 entry.setNeedsUpdate(true); +291 } else { +292 long currentTimestamp = 0; +293 try { +294 currentTimestamp = Long.parseLong(getProperties().getProperty(DatabaseProperties.LAST_UPDATED_BASE +295 + entry.getId(), "0")); +296 } catch (NumberFormatException ex) { +297 LOGGER.debug("Error parsing '{}' '{}' from nvdcve.lastupdated", +298 DatabaseProperties.LAST_UPDATED_BASE, entry.getId(), ex); +299 } +300 if (currentTimestamp == entry.getTimestamp()) { +301 entry.setNeedsUpdate(false); +302 } +303 } +304 } +305 } +306 } catch (NumberFormatException ex) { +307 LOGGER.warn("An invalid schema version or timestamp exists in the data.properties file."); +308 LOGGER.debug("", ex); +309 } +310 } +311 return updates; +312 } +313 +314 /** +315 * Retrieves the timestamps from the NVD CVE meta data file. +316 * +317 * @return the timestamp from the currently published nvdcve downloads page +318 * @throws MalformedURLException thrown if the URL for the NVD CCE Meta data +319 * is incorrect. +320 * @throws DownloadFailedException thrown if there is an error downloading +321 * the nvd cve meta data file +322 * @throws InvalidDataException thrown if there is an exception parsing the +323 * timestamps +324 * @throws InvalidSettingException thrown if the settings are invalid +325 */ +326 private UpdateableNvdCve retrieveCurrentTimestampsFromWeb() +327 throws MalformedURLException, DownloadFailedException, InvalidDataException, InvalidSettingException { +328 +329 final UpdateableNvdCve updates = new UpdateableNvdCve(); +330 updates.add(MODIFIED, Settings.getString(Settings.KEYS.CVE_MODIFIED_20_URL), +331 Settings.getString(Settings.KEYS.CVE_MODIFIED_12_URL), +332 false); +333 +334 final int start = Settings.getInt(Settings.KEYS.CVE_START_YEAR); +335 final int end = Calendar.getInstance().get(Calendar.YEAR); +336 final String baseUrl20 = Settings.getString(Settings.KEYS.CVE_SCHEMA_2_0); +337 final String baseUrl12 = Settings.getString(Settings.KEYS.CVE_SCHEMA_1_2); +338 for (int i = start; i <= end; i++) { +339 updates.add(Integer.toString(i), String.format(baseUrl20, i), +340 String.format(baseUrl12, i), +341 true); +342 } +343 return updates; +344 } +345 }
    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 11e04fcaa..b7e43b555 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.2 Reference Package org.owasp.dependencycheck.data.update.cpe + Dependency-Check Core 1.4.3 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 26db8b0e6..e1c6da995 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.2 Reference Package org.owasp.dependencycheck.data.update.cpe + Dependency-Check Core 1.4.3 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 57b992737..3af3b09a8 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.2 Reference Package org.owasp.dependencycheck.data.update.exception + Dependency-Check Core 1.4.3 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 77ce80767..a104f3f14 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.2 Reference Package org.owasp.dependencycheck.data.update.exception + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.update.exception diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/nvd/DownloadTask.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/nvd/DownloadTask.html index 480cf5e9e..45696f125 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/nvd/DownloadTask.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/nvd/DownloadTask.html @@ -63,269 +63,261 @@ 55 * @param nvdCveInfo the NVD CVE info 56 * @param processor the processor service to submit the downloaded files to 57 * @param cveDB the CVE DB to use to store the vulnerability data -58 * @param settings a reference to the global settings object; this is necessary so that when the thread is started the -59 * dependencies have a correct reference to the global settings. -60 * @throws UpdateException thrown if temporary files could not be created -61 */ -62 public DownloadTask(NvdCveInfo nvdCveInfo, ExecutorService processor, CveDB cveDB, Settings settings) throws UpdateException { -63 this.nvdCveInfo = nvdCveInfo; -64 this.processorService = processor; -65 this.cveDB = cveDB; -66 this.settings = settings; -67 -68 final File file1; -69 final File file2; -70 -71 try { -72 file1 = File.createTempFile("cve" + nvdCveInfo.getId() + '_', ".xml", Settings.getTempDirectory()); -73 file2 = File.createTempFile("cve_1_2_" + nvdCveInfo.getId() + '_', ".xml", Settings.getTempDirectory()); -74 } catch (IOException ex) { -75 throw new UpdateException("Unable to create temporary files", ex); -76 } -77 this.first = file1; -78 this.second = file2; -79 -80 } -81 /** -82 * The CVE DB to use when processing the files. -83 */ -84 private final CveDB cveDB; -85 /** -86 * The processor service to pass the results of the download to. -87 */ -88 private final ExecutorService processorService; -89 /** -90 * The NVD CVE Meta Data. -91 */ -92 private NvdCveInfo nvdCveInfo; -93 /** -94 * A reference to the global settings object. -95 */ -96 private final Settings settings; -97 -98 /** -99 * Get the value of nvdCveInfo. -100 * -101 * @return the value of nvdCveInfo -102 */ -103 public NvdCveInfo getNvdCveInfo() { -104 return nvdCveInfo; -105 } -106 -107 /** -108 * Set the value of nvdCveInfo. -109 * -110 * @param nvdCveInfo new value of nvdCveInfo -111 */ -112 public void setNvdCveInfo(NvdCveInfo nvdCveInfo) { -113 this.nvdCveInfo = nvdCveInfo; -114 } -115 /** -116 * a file. -117 */ -118 private File first; -119 -120 /** -121 * Get the value of first. -122 * -123 * @return the value of first -124 */ -125 public File getFirst() { -126 return first; -127 } -128 -129 /** -130 * Set the value of first. -131 * -132 * @param first new value of first -133 */ -134 public void setFirst(File first) { -135 this.first = first; -136 } -137 /** -138 * a file. -139 */ -140 private File second; -141 -142 /** -143 * Get the value of second. -144 * -145 * @return the value of second -146 */ -147 public File getSecond() { -148 return second; -149 } -150 -151 /** -152 * Set the value of second. -153 * -154 * @param second new value of second -155 */ -156 public void setSecond(File second) { -157 this.second = second; -158 } -159 -160 @Override -161 public Future<ProcessTask> call() throws Exception { -162 try { -163 Settings.setInstance(settings); -164 final URL url1 = new URL(nvdCveInfo.getUrl()); -165 final URL url2 = new URL(nvdCveInfo.getOldSchemaVersionUrl()); -166 LOGGER.info("Download Started for NVD CVE - {}", nvdCveInfo.getId()); -167 final long startDownload = System.currentTimeMillis(); -168 try { -169 Downloader.fetchFile(url1, first); -170 Downloader.fetchFile(url2, second); -171 } catch (DownloadFailedException ex) { -172 LOGGER.warn("Download Failed for NVD CVE - {}\nSome CVEs may not be reported.", nvdCveInfo.getId()); -173 if (Settings.getString(Settings.KEYS.PROXY_SERVER) == null) { -174 LOGGER.info( -175 "If you are behind a proxy you may need to configure dependency-check to use the proxy."); -176 } -177 LOGGER.debug("", ex); -178 return null; -179 } -180 if (url1.toExternalForm().endsWith(".xml.gz") && !isXml(first)) { -181 extractGzip(first); -182 } -183 if (url2.toExternalForm().endsWith(".xml.gz") && !isXml(second)) { -184 extractGzip(second); -185 } -186 -187 LOGGER.info("Download Complete for NVD CVE - {} ({} ms)", nvdCveInfo.getId(), -188 System.currentTimeMillis() - startDownload); -189 if (this.processorService == null) { -190 return null; -191 } -192 final ProcessTask task = new ProcessTask(cveDB, this, settings); -193 return this.processorService.submit(task); -194 -195 } catch (Throwable ex) { -196 LOGGER.warn("An exception occurred downloading NVD CVE - {}\nSome CVEs may not be reported.", nvdCveInfo.getId()); -197 LOGGER.debug("Download Task Failed", ex); -198 } finally { -199 Settings.cleanup(false); -200 } -201 return null; -202 } -203 -204 /** -205 * Attempts to delete the files that were downloaded. -206 */ -207 public void cleanup() { -208 boolean deleted = false; -209 try { -210 if (first != null && first.exists()) { -211 deleted = first.delete(); -212 } -213 } finally { -214 if (first != null && (first.exists() || !deleted)) { -215 first.deleteOnExit(); -216 } -217 } -218 try { -219 deleted = false; -220 if (second != null && second.exists()) { -221 deleted = second.delete(); -222 } -223 } finally { -224 if (second != null && (second.exists() || !deleted)) { -225 second.deleteOnExit(); -226 } -227 } -228 } -229 -230 /** -231 * Checks the file header to see if it is an XML file. -232 * -233 * @param file the file to check -234 * @return true if the file is XML -235 */ -236 public static boolean isXml(File file) { -237 if (file == null || !file.isFile()) { -238 return false; -239 } -240 InputStream is = null; -241 try { -242 is = new FileInputStream(file); -243 -244 final byte[] buf = new byte[5]; -245 int read = 0; -246 try { -247 read = is.read(buf); -248 } catch (IOException ex) { -249 return false; -250 } -251 return read == 5 -252 && buf[0] == '<' -253 && (buf[1] == '?') -254 && (buf[2] == 'x' || buf[2] == 'X') -255 && (buf[3] == 'm' || buf[3] == 'M') -256 && (buf[4] == 'l' || buf[4] == 'L'); -257 } catch (FileNotFoundException ex) { -258 return false; -259 } finally { -260 if (is != null) { -261 try { -262 is.close(); -263 } catch (IOException ex) { -264 LOGGER.debug("Error closing stream", ex); -265 } -266 } -267 } -268 } -269 -270 /** -271 * Extracts the file contained in a gzip archive. The extracted file is placed in the exact same path as the file specified. -272 * -273 * @param file the archive file -274 * @throws FileNotFoundException thrown if the file does not exist -275 * @throws IOException thrown if there is an error extracting the file. -276 */ -277 private void extractGzip(File file) throws FileNotFoundException, IOException { -278 final String originalPath = file.getPath(); -279 final File gzip = new File(originalPath + ".gz"); -280 if (gzip.isFile() && !gzip.delete()) { -281 gzip.deleteOnExit(); -282 } -283 if (!file.renameTo(gzip)) { -284 throw new IOException("Unable to rename '" + file.getPath() + "'"); -285 } -286 final File newfile = new File(originalPath); -287 -288 final byte[] buffer = new byte[4096]; -289 -290 GZIPInputStream cin = null; -291 FileOutputStream out = null; -292 try { -293 cin = new GZIPInputStream(new FileInputStream(gzip)); -294 out = new FileOutputStream(newfile); -295 -296 int len; -297 while ((len = cin.read(buffer)) > 0) { -298 out.write(buffer, 0, len); -299 } -300 } finally { -301 if (cin != null) { -302 try { -303 cin.close(); -304 } catch (IOException ex) { -305 LOGGER.trace("ignore", ex); -306 } -307 } -308 if (out != null) { -309 try { -310 out.close(); -311 } catch (IOException ex) { -312 LOGGER.trace("ignore", ex); -313 } -314 } -315 if (gzip.isFile()) { -316 FileUtils.deleteQuietly(gzip); -317 } -318 } -319 } -320 } +58 * @param settings a reference to the global settings object; this is +59 * necessary so that when the thread is started the dependencies have a +60 * correct reference to the global settings. +61 * @throws UpdateException thrown if temporary files could not be created +62 */ +63 public DownloadTask(NvdCveInfo nvdCveInfo, ExecutorService processor, CveDB cveDB, Settings settings) throws UpdateException { +64 this.nvdCveInfo = nvdCveInfo; +65 this.processorService = processor; +66 this.cveDB = cveDB; +67 this.settings = settings; +68 +69 final File file1; +70 final File file2; +71 +72 try { +73 file1 = File.createTempFile("cve" + nvdCveInfo.getId() + '_', ".xml", Settings.getTempDirectory()); +74 file2 = File.createTempFile("cve_1_2_" + nvdCveInfo.getId() + '_', ".xml", Settings.getTempDirectory()); +75 } catch (IOException ex) { +76 throw new UpdateException("Unable to create temporary files", ex); +77 } +78 this.first = file1; +79 this.second = file2; +80 +81 } +82 /** +83 * The CVE DB to use when processing the files. +84 */ +85 private final CveDB cveDB; +86 /** +87 * The processor service to pass the results of the download to. +88 */ +89 private final ExecutorService processorService; +90 /** +91 * The NVD CVE Meta Data. +92 */ +93 private NvdCveInfo nvdCveInfo; +94 /** +95 * A reference to the global settings object. +96 */ +97 private final Settings settings; +98 +99 /** +100 * Get the value of nvdCveInfo. +101 * +102 * @return the value of nvdCveInfo +103 */ +104 public NvdCveInfo getNvdCveInfo() { +105 return nvdCveInfo; +106 } +107 +108 /** +109 * Set the value of nvdCveInfo. +110 * +111 * @param nvdCveInfo new value of nvdCveInfo +112 */ +113 public void setNvdCveInfo(NvdCveInfo nvdCveInfo) { +114 this.nvdCveInfo = nvdCveInfo; +115 } +116 /** +117 * a file. +118 */ +119 private File first; +120 +121 /** +122 * Get the value of first. +123 * +124 * @return the value of first +125 */ +126 public File getFirst() { +127 return first; +128 } +129 +130 /** +131 * Set the value of first. +132 * +133 * @param first new value of first +134 */ +135 public void setFirst(File first) { +136 this.first = first; +137 } +138 /** +139 * a file. +140 */ +141 private File second; +142 +143 /** +144 * Get the value of second. +145 * +146 * @return the value of second +147 */ +148 public File getSecond() { +149 return second; +150 } +151 +152 /** +153 * Set the value of second. +154 * +155 * @param second new value of second +156 */ +157 public void setSecond(File second) { +158 this.second = second; +159 } +160 +161 @Override +162 public Future<ProcessTask> call() throws Exception { +163 try { +164 Settings.setInstance(settings); +165 final URL url1 = new URL(nvdCveInfo.getUrl()); +166 final URL url2 = new URL(nvdCveInfo.getOldSchemaVersionUrl()); +167 LOGGER.info("Download Started for NVD CVE - {}", nvdCveInfo.getId()); +168 final long startDownload = System.currentTimeMillis(); +169 try { +170 Downloader.fetchFile(url1, first); +171 Downloader.fetchFile(url2, second); +172 } catch (DownloadFailedException ex) { +173 LOGGER.warn("Download Failed for NVD CVE - {}\nSome CVEs may not be reported.", nvdCveInfo.getId()); +174 if (Settings.getString(Settings.KEYS.PROXY_SERVER) == null) { +175 LOGGER.info( +176 "If you are behind a proxy you may need to configure dependency-check to use the proxy."); +177 } +178 LOGGER.debug("", ex); +179 return null; +180 } +181 if (url1.toExternalForm().endsWith(".xml.gz") && !isXml(first)) { +182 extractGzip(first); +183 } +184 if (url2.toExternalForm().endsWith(".xml.gz") && !isXml(second)) { +185 extractGzip(second); +186 } +187 +188 LOGGER.info("Download Complete for NVD CVE - {} ({} ms)", nvdCveInfo.getId(), +189 System.currentTimeMillis() - startDownload); +190 if (this.processorService == null) { +191 return null; +192 } +193 final ProcessTask task = new ProcessTask(cveDB, this, settings); +194 return this.processorService.submit(task); +195 +196 } catch (Throwable ex) { +197 LOGGER.warn("An exception occurred downloading NVD CVE - {}\nSome CVEs may not be reported.", nvdCveInfo.getId()); +198 LOGGER.debug("Download Task Failed", ex); +199 } finally { +200 Settings.cleanup(false); +201 } +202 return null; +203 } +204 +205 /** +206 * Attempts to delete the files that were downloaded. +207 */ +208 public void cleanup() { +209 if (first != null && first.exists() && first.delete()) { +210 LOGGER.debug("Failed to delete first temporary file {}", second.toString()); +211 first.deleteOnExit(); +212 } +213 if (second != null && second.exists() && !second.delete()) { +214 LOGGER.debug("Failed to delete second temporary file {}", second.toString()); +215 second.deleteOnExit(); +216 } +217 } +218 +219 /** +220 * Checks the file header to see if it is an XML file. +221 * +222 * @param file the file to check +223 * @return true if the file is XML +224 */ +225 public static boolean isXml(File file) { +226 if (file == null || !file.isFile()) { +227 return false; +228 } +229 InputStream is = null; +230 try { +231 is = new FileInputStream(file); +232 +233 final byte[] buf = new byte[5]; +234 int read = 0; +235 try { +236 read = is.read(buf); +237 } catch (IOException ex) { +238 return false; +239 } +240 return read == 5 +241 && buf[0] == '<' +242 && (buf[1] == '?') +243 && (buf[2] == 'x' || buf[2] == 'X') +244 && (buf[3] == 'm' || buf[3] == 'M') +245 && (buf[4] == 'l' || buf[4] == 'L'); +246 } catch (FileNotFoundException ex) { +247 return false; +248 } finally { +249 if (is != null) { +250 try { +251 is.close(); +252 } catch (IOException ex) { +253 LOGGER.debug("Error closing stream", ex); +254 } +255 } +256 } +257 } +258 +259 /** +260 * Extracts the file contained in a gzip archive. The extracted file is +261 * placed in the exact same path as the file specified. +262 * +263 * @param file the archive file +264 * @throws FileNotFoundException thrown if the file does not exist +265 * @throws IOException thrown if there is an error extracting the file. +266 */ +267 private void extractGzip(File file) throws FileNotFoundException, IOException { +268 final String originalPath = file.getPath(); +269 final File gzip = new File(originalPath + ".gz"); +270 if (gzip.isFile() && !gzip.delete()) { +271 LOGGER.debug("Failed to delete initial temporary file when extracting 'gz' {}", gzip.toString()); +272 gzip.deleteOnExit(); +273 } +274 if (!file.renameTo(gzip)) { +275 throw new IOException("Unable to rename '" + file.getPath() + "'"); +276 } +277 final File newfile = new File(originalPath); +278 +279 final byte[] buffer = new byte[4096]; +280 +281 GZIPInputStream cin = null; +282 FileOutputStream out = null; +283 try { +284 cin = new GZIPInputStream(new FileInputStream(gzip)); +285 out = new FileOutputStream(newfile); +286 +287 int len; +288 while ((len = cin.read(buffer)) > 0) { +289 out.write(buffer, 0, len); +290 } +291 } finally { +292 if (cin != null) { +293 try { +294 cin.close(); +295 } catch (IOException ex) { +296 LOGGER.trace("ignore", ex); +297 } +298 } +299 if (out != null) { +300 try { +301 out.close(); +302 } catch (IOException ex) { +303 LOGGER.trace("ignore", ex); +304 } +305 } +306 if (gzip.isFile() && !FileUtils.deleteQuietly(gzip)) { +307 LOGGER.debug("Failed to delete temporary file when extracting 'gz' {}", gzip.toString()); +308 gzip.deleteOnExit(); +309 } +310 } +311 } +312 }
    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 47e4839a7..c1f7615ba 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.2 Reference Package org.owasp.dependencycheck.data.update.nvd + Dependency-Check Core 1.4.3 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 e06fc753c..9438d807a 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.2 Reference Package org.owasp.dependencycheck.data.update.nvd + Dependency-Check Core 1.4.3 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 7d8e31f62..6d7293b91 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.2 Reference Package org.owasp.dependencycheck.data.update + Dependency-Check Core 1.4.3 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 19b61ad8b..052b9887a 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.2 Reference Package org.owasp.dependencycheck.data.update + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.update diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/dependency/Reference.html b/dependency-check-core/xref/org/owasp/dependencycheck/dependency/Reference.html index 2230c6e7a..3d956b3b4 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/dependency/Reference.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/dependency/Reference.html @@ -26,144 +26,137 @@ 18 package org.owasp.dependencycheck.dependency; 19 20 import java.io.Serializable; -21 -22 /** -23 * An external reference for a vulnerability. This contains a name, URL, and a -24 * source. -25 * -26 * @author Jeremy Long -27 */ -28 public class Reference implements Serializable, Comparable<Reference> { -29 -30 /** -31 * the serial version uid. -32 */ -33 private static final long serialVersionUID = -3444464824563008021L; -34 /** -35 * The name of the reference. -36 */ -37 private String name; -38 -39 /** -40 * Get the value of name. -41 * -42 * @return the value of name -43 */ -44 public String getName() { -45 return name; -46 } -47 -48 /** -49 * Set the value of name. -50 * -51 * @param name new value of name -52 */ -53 public void setName(String name) { -54 this.name = name; -55 } -56 /** -57 * the url for the reference. -58 */ -59 private String url; -60 -61 /** -62 * Get the value of url. -63 * -64 * @return the value of url -65 */ -66 public String getUrl() { -67 return url; -68 } -69 -70 /** -71 * Set the value of url. -72 * -73 * @param url new value of url -74 */ -75 public void setUrl(String url) { -76 this.url = url; -77 } -78 /** -79 * the source of the reference. -80 */ -81 private String source; -82 -83 /** -84 * Get the value of source. -85 * -86 * @return the value of source -87 */ -88 public String getSource() { -89 return source; -90 } -91 -92 /** -93 * Set the value of source. -94 * -95 * @param source new value of source -96 */ -97 public void setSource(String source) { -98 this.source = source; -99 } -100 -101 @Override -102 public String toString() { -103 return "Reference: { name='" + this.name + "', url='" + this.url + "', source='" + this.source + "' }"; -104 } -105 -106 @Override -107 public boolean equals(Object obj) { -108 if (obj == null) { -109 return false; -110 } -111 if (getClass() != obj.getClass()) { -112 return false; -113 } -114 final Reference other = (Reference) obj; -115 if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) { -116 return false; -117 } -118 if ((this.url == null) ? (other.url != null) : !this.url.equals(other.url)) { -119 return false; -120 } -121 if ((this.source == null) ? (other.source != null) : !this.source.equals(other.source)) { -122 return false; -123 } -124 return true; -125 } -126 -127 @Override -128 public int hashCode() { -129 int hash = 5; -130 hash = 67 * hash + (this.name != null ? this.name.hashCode() : 0); -131 hash = 67 * hash + (this.url != null ? this.url.hashCode() : 0); -132 hash = 67 * hash + (this.source != null ? this.source.hashCode() : 0); -133 return hash; -134 } -135 -136 /** -137 * Implementation of the comparable interface. -138 * -139 * @param o the Reference being compared -140 * @return an integer indicating the ordering of the two objects -141 */ -142 @Override -143 public int compareTo(Reference o) { -144 if (source.equals(o.source)) { -145 if (name.equals(o.name)) { -146 if (url.equals(o.url)) { -147 return 0; //they are equal -148 } else { -149 return url.compareTo(o.url); -150 } -151 } else { -152 return name.compareTo(o.name); -153 } -154 } else { -155 return source.compareTo(o.source); -156 } -157 } -158 } +21 import org.apache.commons.lang3.builder.CompareToBuilder; +22 +23 /** +24 * An external reference for a vulnerability. This contains a name, URL, and a +25 * source. +26 * +27 * @author Jeremy Long +28 */ +29 public class Reference implements Serializable, Comparable<Reference> { +30 +31 /** +32 * the serial version uid. +33 */ +34 private static final long serialVersionUID = -3444464824563008021L; +35 /** +36 * The name of the reference. +37 */ +38 private String name; +39 +40 /** +41 * Get the value of name. +42 * +43 * @return the value of name +44 */ +45 public String getName() { +46 return name; +47 } +48 +49 /** +50 * Set the value of name. +51 * +52 * @param name new value of name +53 */ +54 public void setName(String name) { +55 this.name = name; +56 } +57 /** +58 * the url for the reference. +59 */ +60 private String url; +61 +62 /** +63 * Get the value of url. +64 * +65 * @return the value of url +66 */ +67 public String getUrl() { +68 return url; +69 } +70 +71 /** +72 * Set the value of url. +73 * +74 * @param url new value of url +75 */ +76 public void setUrl(String url) { +77 this.url = url; +78 } +79 /** +80 * the source of the reference. +81 */ +82 private String source; +83 +84 /** +85 * Get the value of source. +86 * +87 * @return the value of source +88 */ +89 public String getSource() { +90 return source; +91 } +92 +93 /** +94 * Set the value of source. +95 * +96 * @param source new value of source +97 */ +98 public void setSource(String source) { +99 this.source = source; +100 } +101 +102 @Override +103 public String toString() { +104 return "Reference: { name='" + this.name + "', url='" + this.url + "', source='" + this.source + "' }"; +105 } +106 +107 @Override +108 public boolean equals(Object obj) { +109 if (obj == null) { +110 return false; +111 } +112 if (getClass() != obj.getClass()) { +113 return false; +114 } +115 final Reference other = (Reference) obj; +116 if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) { +117 return false; +118 } +119 if ((this.url == null) ? (other.url != null) : !this.url.equals(other.url)) { +120 return false; +121 } +122 if ((this.source == null) ? (other.source != null) : !this.source.equals(other.source)) { +123 return false; +124 } +125 return true; +126 } +127 +128 @Override +129 public int hashCode() { +130 int hash = 5; +131 hash = 67 * hash + (this.name != null ? this.name.hashCode() : 0); +132 hash = 67 * hash + (this.url != null ? this.url.hashCode() : 0); +133 hash = 67 * hash + (this.source != null ? this.source.hashCode() : 0); +134 return hash; +135 } +136 +137 /** +138 * Implementation of the comparable interface. +139 * +140 * @param o the Reference being compared +141 * @return an integer indicating the ordering of the two objects +142 */ +143 @Override +144 public int compareTo(Reference o) { +145 return new CompareToBuilder() +146 .append(source, o.source) +147 .append(name, o.name) +148 .append(url, o.url) +149 .toComparison(); +150 } +151 }
    diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/dependency/Vulnerability.html b/dependency-check-core/xref/org/owasp/dependencycheck/dependency/Vulnerability.html index fe0cd852f..64c9527b8 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/dependency/Vulnerability.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/dependency/Vulnerability.html @@ -29,447 +29,453 @@ 21 import java.util.Set; 22 import java.util.SortedSet; 23 import java.util.TreeSet; -24 -25 /** -26 * Contains the information about a vulnerability. -27 * -28 * @author Jeremy Long -29 */ -30 public class Vulnerability implements Serializable, Comparable<Vulnerability> { -31 -32 /** -33 * The serial version uid. -34 */ -35 private static final long serialVersionUID = 307319490326651052L; -36 -37 /** -38 * The name of the vulnerability. -39 */ -40 private String name; -41 -42 /** -43 * Get the value of name. -44 * -45 * @return the value of name -46 */ -47 public String getName() { -48 return name; -49 } -50 -51 /** -52 * Set the value of name. -53 * -54 * @param name new value of name -55 */ -56 public void setName(String name) { -57 this.name = name; -58 } -59 /** -60 * the description of the vulnerability. -61 */ -62 private String description; -63 -64 /** -65 * Get the value of description. -66 * -67 * @return the value of description -68 */ -69 public String getDescription() { -70 return description; -71 } -72 -73 /** -74 * Set the value of description. -75 * -76 * @param description new value of description -77 */ -78 public void setDescription(String description) { -79 this.description = description; -80 } -81 /** -82 * References for this vulnerability. -83 */ -84 private SortedSet<Reference> references = new TreeSet<Reference>(); -85 -86 /** -87 * Get the value of references. -88 * -89 * @return the value of references -90 */ -91 public Set<Reference> getReferences() { -92 return references; -93 } -94 -95 /** -96 * Set the value of references. -97 * -98 * @param references new value of references -99 */ -100 public void setReferences(SortedSet<Reference> references) { -101 this.references = references; -102 } -103 -104 /** -105 * Adds a reference to the references collection. -106 * -107 * @param ref a reference for the vulnerability -108 */ -109 public void addReference(Reference ref) { -110 this.references.add(ref); -111 } -112 -113 /** -114 * Adds a reference. -115 * -116 * @param referenceSource the source of the reference -117 * @param referenceName the referenceName of the reference -118 * @param referenceUrl the url of the reference -119 */ -120 public void addReference(String referenceSource, String referenceName, String referenceUrl) { -121 final Reference ref = new Reference(); -122 ref.setSource(referenceSource); -123 ref.setName(referenceName); -124 ref.setUrl(referenceUrl); -125 this.references.add(ref); -126 } -127 /** -128 * A set of vulnerable software. -129 */ -130 private SortedSet<VulnerableSoftware> vulnerableSoftware = new TreeSet<VulnerableSoftware>(); -131 -132 /** -133 * Get the value of vulnerableSoftware. -134 * -135 * @return the value of vulnerableSoftware -136 */ -137 public Set<VulnerableSoftware> getVulnerableSoftware() { -138 return vulnerableSoftware; -139 } -140 -141 /** -142 * Set the value of vulnerableSoftware. -143 * -144 * @param vulnerableSoftware new value of vulnerableSoftware -145 */ -146 public void setVulnerableSoftware(SortedSet<VulnerableSoftware> vulnerableSoftware) { -147 this.vulnerableSoftware = vulnerableSoftware; -148 } -149 -150 /** -151 * Adds an entry for vulnerable software. -152 * -153 * @param cpe string representation of a CPE entry -154 * @return if the add succeeded -155 */ -156 public boolean addVulnerableSoftware(String cpe) { -157 return addVulnerableSoftware(cpe, null); -158 } -159 -160 /** -161 * Adds an entry for vulnerable software. -162 * -163 * @param cpe string representation of a cpe -164 * @param previousVersion the previous version (previousVersion - cpe would be considered vulnerable) -165 * @return if the add succeeded -166 */ -167 public boolean addVulnerableSoftware(String cpe, String previousVersion) { -168 final VulnerableSoftware vs = new VulnerableSoftware(); -169 vs.setCpe(cpe); -170 if (previousVersion != null) { -171 vs.setPreviousVersion(previousVersion); -172 } -173 return updateVulnerableSoftware(vs); -174 } -175 -176 /** -177 * Adds or updates a vulnerable software entry. -178 * -179 * @param vulnSoftware the vulnerable software -180 * @return if the update succeeded -181 */ -182 public boolean updateVulnerableSoftware(VulnerableSoftware vulnSoftware) { -183 if (vulnerableSoftware.contains(vulnSoftware)) { -184 vulnerableSoftware.remove(vulnSoftware); -185 } -186 return vulnerableSoftware.add(vulnSoftware); -187 } -188 /** -189 * The CWE for the vulnerability. -190 */ -191 private String cwe; -192 -193 /** -194 * Get the value of cwe. -195 * -196 * @return the value of cwe -197 */ -198 public String getCwe() { -199 return cwe; -200 } -201 -202 /** -203 * Set the value of cwe. -204 * -205 * @param cwe new value of cwe -206 */ -207 public void setCwe(String cwe) { -208 this.cwe = cwe; -209 } -210 /** -211 * CVSS Score. -212 */ -213 private float cvssScore; -214 -215 /** -216 * Get the value of cvssScore. -217 * -218 * @return the value of cvssScore -219 */ -220 public float getCvssScore() { -221 return cvssScore; -222 } -223 -224 /** -225 * Set the value of cvssScore. -226 * -227 * @param cvssScore new value of cvssScore -228 */ -229 public void setCvssScore(float cvssScore) { -230 this.cvssScore = cvssScore; -231 } -232 /** -233 * CVSS Access Vector. -234 */ -235 private String cvssAccessVector; -236 -237 /** -238 * Get the value of cvssAccessVector. -239 * -240 * @return the value of cvssAccessVector -241 */ -242 public String getCvssAccessVector() { -243 return cvssAccessVector; -244 } -245 -246 /** -247 * Set the value of cvssAccessVector. -248 * -249 * @param cvssAccessVector new value of cvssAccessVector -250 */ -251 public void setCvssAccessVector(String cvssAccessVector) { -252 this.cvssAccessVector = cvssAccessVector; -253 } -254 /** -255 * CVSS Access Complexity. -256 */ -257 private String cvssAccessComplexity; -258 -259 /** -260 * Get the value of cvssAccessComplexity. -261 * -262 * @return the value of cvssAccessComplexity -263 */ -264 public String getCvssAccessComplexity() { -265 return cvssAccessComplexity; -266 } -267 -268 /** -269 * Set the value of cvssAccessComplexity. -270 * -271 * @param cvssAccessComplexity new value of cvssAccessComplexity -272 */ -273 public void setCvssAccessComplexity(String cvssAccessComplexity) { -274 this.cvssAccessComplexity = cvssAccessComplexity; -275 } -276 /** -277 * CVSS Authentication. -278 */ -279 private String cvssAuthentication; -280 -281 /** -282 * Get the value of cvssAuthentication. -283 * -284 * @return the value of cvssAuthentication -285 */ -286 public String getCvssAuthentication() { -287 return cvssAuthentication; -288 } -289 -290 /** -291 * Set the value of cvssAuthentication. -292 * -293 * @param cvssAuthentication new value of cvssAuthentication -294 */ -295 public void setCvssAuthentication(String cvssAuthentication) { -296 this.cvssAuthentication = cvssAuthentication; -297 } -298 /** -299 * CVSS Confidentiality Impact. -300 */ -301 private String cvssConfidentialityImpact; -302 -303 /** -304 * Get the value of cvssConfidentialityImpact. -305 * -306 * @return the value of cvssConfidentialityImpact -307 */ -308 public String getCvssConfidentialityImpact() { -309 return cvssConfidentialityImpact; -310 } -311 -312 /** -313 * Set the value of cvssConfidentialityImpact. -314 * -315 * @param cvssConfidentialityImpact new value of cvssConfidentialityImpact -316 */ -317 public void setCvssConfidentialityImpact(String cvssConfidentialityImpact) { -318 this.cvssConfidentialityImpact = cvssConfidentialityImpact; -319 } -320 /** -321 * CVSS Integrity Impact. -322 */ -323 private String cvssIntegrityImpact; -324 -325 /** -326 * Get the value of cvssIntegrityImpact. -327 * -328 * @return the value of cvssIntegrityImpact -329 */ -330 public String getCvssIntegrityImpact() { -331 return cvssIntegrityImpact; -332 } -333 -334 /** -335 * Set the value of cvssIntegrityImpact. -336 * -337 * @param cvssIntegrityImpact new value of cvssIntegrityImpact -338 */ -339 public void setCvssIntegrityImpact(String cvssIntegrityImpact) { -340 this.cvssIntegrityImpact = cvssIntegrityImpact; -341 } -342 /** -343 * CVSS Availability Impact. -344 */ -345 private String cvssAvailabilityImpact; -346 -347 /** -348 * Get the value of cvssAvailabilityImpact. -349 * -350 * @return the value of cvssAvailabilityImpact -351 */ -352 public String getCvssAvailabilityImpact() { -353 return cvssAvailabilityImpact; -354 } -355 -356 /** -357 * Set the value of cvssAvailabilityImpact. -358 * -359 * @param cvssAvailabilityImpact new value of cvssAvailabilityImpact -360 */ -361 public void setCvssAvailabilityImpact(String cvssAvailabilityImpact) { -362 this.cvssAvailabilityImpact = cvssAvailabilityImpact; -363 } -364 -365 @Override -366 public boolean equals(Object obj) { -367 if (obj == null) { -368 return false; -369 } -370 if (getClass() != obj.getClass()) { -371 return false; -372 } -373 final Vulnerability other = (Vulnerability) obj; -374 if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) { -375 return false; -376 } -377 return true; -378 } -379 -380 @Override -381 public int hashCode() { -382 int hash = 5; -383 hash = 41 * hash + (this.name != null ? this.name.hashCode() : 0); -384 return hash; -385 } -386 -387 @Override -388 public String toString() { -389 final StringBuilder sb = new StringBuilder("Vulnerability "); -390 sb.append(this.name); -391 sb.append("\nReferences:\n"); -392 for (Reference reference : this.references) { -393 sb.append("=> "); -394 sb.append(reference); -395 sb.append("\n"); -396 } -397 sb.append("\nSoftware:\n"); -398 for (VulnerableSoftware software : this.vulnerableSoftware) { -399 sb.append("=> "); -400 sb.append(software); -401 sb.append("\n"); -402 } -403 return sb.toString(); -404 } -405 /** -406 * Compares two vulnerabilities. -407 * -408 * @param v a vulnerability to be compared -409 * @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than -410 * the specified vulnerability -411 */ -412 @Override -413 public int compareTo(Vulnerability v) { -414 return v.getName().compareTo(this.getName()); -415 } -416 -417 /** -418 * The CPE id that caused this vulnerability to be flagged. -419 */ -420 private String matchedCPE; -421 /** -422 * Whether or not all previous versions were affected. -423 */ -424 private String matchedAllPreviousCPE; -425 -426 /** -427 * Sets the CPE that caused this vulnerability to be flagged. -428 * -429 * @param cpeId a CPE identifier -430 * @param previous a flag indicating whether or not all previous versions were affected (any non-null value is -431 * considered true) -432 */ -433 public void setMatchedCPE(String cpeId, String previous) { -434 matchedCPE = cpeId; -435 matchedAllPreviousCPE = previous; -436 } -437 -438 /** -439 * Get the value of matchedCPE. -440 * -441 * @return the value of matchedCPE -442 */ -443 public String getMatchedCPE() { -444 return matchedCPE; -445 } -446 -447 /** -448 * Get the value of matchedAllPreviousCPE. -449 * -450 * @return the value of matchedAllPreviousCPE -451 */ -452 public String getMatchedAllPreviousCPE() { -453 return matchedAllPreviousCPE; -454 } -455 -456 /** -457 * Determines whether or not matchedAllPreviousCPE has been set. -458 * -459 * @return true if matchedAllPreviousCPE is not null; otherwise false -460 */ -461 public boolean hasMatchedAllPreviousCPE() { -462 return matchedAllPreviousCPE != null; -463 } -464 } +24 import org.apache.commons.lang3.builder.CompareToBuilder; +25 +26 /** +27 * Contains the information about a vulnerability. +28 * +29 * @author Jeremy Long +30 */ +31 public class Vulnerability implements Serializable, Comparable<Vulnerability> { +32 +33 /** +34 * The serial version uid. +35 */ +36 private static final long serialVersionUID = 307319490326651052L; +37 +38 /** +39 * The name of the vulnerability. +40 */ +41 private String name; +42 +43 /** +44 * Get the value of name. +45 * +46 * @return the value of name +47 */ +48 public String getName() { +49 return name; +50 } +51 +52 /** +53 * Set the value of name. +54 * +55 * @param name new value of name +56 */ +57 public void setName(String name) { +58 this.name = name; +59 } +60 /** +61 * the description of the vulnerability. +62 */ +63 private String description; +64 +65 /** +66 * Get the value of description. +67 * +68 * @return the value of description +69 */ +70 public String getDescription() { +71 return description; +72 } +73 +74 /** +75 * Set the value of description. +76 * +77 * @param description new value of description +78 */ +79 public void setDescription(String description) { +80 this.description = description; +81 } +82 /** +83 * References for this vulnerability. +84 */ +85 private SortedSet<Reference> references = new TreeSet<Reference>(); +86 +87 /** +88 * Get the value of references. +89 * +90 * @return the value of references +91 */ +92 public Set<Reference> getReferences() { +93 return references; +94 } +95 +96 /** +97 * Set the value of references. +98 * +99 * @param references new value of references +100 */ +101 public void setReferences(SortedSet<Reference> references) { +102 this.references = references; +103 } +104 +105 /** +106 * Adds a reference to the references collection. +107 * +108 * @param ref a reference for the vulnerability +109 */ +110 public void addReference(Reference ref) { +111 this.references.add(ref); +112 } +113 +114 /** +115 * Adds a reference. +116 * +117 * @param referenceSource the source of the reference +118 * @param referenceName the referenceName of the reference +119 * @param referenceUrl the url of the reference +120 */ +121 public void addReference(String referenceSource, String referenceName, String referenceUrl) { +122 final Reference ref = new Reference(); +123 ref.setSource(referenceSource); +124 ref.setName(referenceName); +125 ref.setUrl(referenceUrl); +126 this.references.add(ref); +127 } +128 /** +129 * A set of vulnerable software. +130 */ +131 private SortedSet<VulnerableSoftware> vulnerableSoftware = new TreeSet<VulnerableSoftware>(); +132 +133 /** +134 * Get the value of vulnerableSoftware. +135 * +136 * @return the value of vulnerableSoftware +137 */ +138 public Set<VulnerableSoftware> getVulnerableSoftware() { +139 return vulnerableSoftware; +140 } +141 +142 /** +143 * Set the value of vulnerableSoftware. +144 * +145 * @param vulnerableSoftware new value of vulnerableSoftware +146 */ +147 public void setVulnerableSoftware(SortedSet<VulnerableSoftware> vulnerableSoftware) { +148 this.vulnerableSoftware = vulnerableSoftware; +149 } +150 +151 /** +152 * Adds an entry for vulnerable software. +153 * +154 * @param cpe string representation of a CPE entry +155 * @return if the add succeeded +156 */ +157 public boolean addVulnerableSoftware(String cpe) { +158 return addVulnerableSoftware(cpe, null); +159 } +160 +161 /** +162 * Adds an entry for vulnerable software. +163 * +164 * @param cpe string representation of a cpe +165 * @param previousVersion the previous version (previousVersion - cpe would +166 * be considered vulnerable) +167 * @return if the add succeeded +168 */ +169 public boolean addVulnerableSoftware(String cpe, String previousVersion) { +170 final VulnerableSoftware vs = new VulnerableSoftware(); +171 vs.setCpe(cpe); +172 if (previousVersion != null) { +173 vs.setPreviousVersion(previousVersion); +174 } +175 return updateVulnerableSoftware(vs); +176 } +177 +178 /** +179 * Adds or updates a vulnerable software entry. +180 * +181 * @param vulnSoftware the vulnerable software +182 * @return if the update succeeded +183 */ +184 public boolean updateVulnerableSoftware(VulnerableSoftware vulnSoftware) { +185 if (vulnerableSoftware.contains(vulnSoftware)) { +186 vulnerableSoftware.remove(vulnSoftware); +187 } +188 return vulnerableSoftware.add(vulnSoftware); +189 } +190 /** +191 * The CWE for the vulnerability. +192 */ +193 private String cwe; +194 +195 /** +196 * Get the value of cwe. +197 * +198 * @return the value of cwe +199 */ +200 public String getCwe() { +201 return cwe; +202 } +203 +204 /** +205 * Set the value of cwe. +206 * +207 * @param cwe new value of cwe +208 */ +209 public void setCwe(String cwe) { +210 this.cwe = cwe; +211 } +212 /** +213 * CVSS Score. +214 */ +215 private float cvssScore; +216 +217 /** +218 * Get the value of cvssScore. +219 * +220 * @return the value of cvssScore +221 */ +222 public float getCvssScore() { +223 return cvssScore; +224 } +225 +226 /** +227 * Set the value of cvssScore. +228 * +229 * @param cvssScore new value of cvssScore +230 */ +231 public void setCvssScore(float cvssScore) { +232 this.cvssScore = cvssScore; +233 } +234 /** +235 * CVSS Access Vector. +236 */ +237 private String cvssAccessVector; +238 +239 /** +240 * Get the value of cvssAccessVector. +241 * +242 * @return the value of cvssAccessVector +243 */ +244 public String getCvssAccessVector() { +245 return cvssAccessVector; +246 } +247 +248 /** +249 * Set the value of cvssAccessVector. +250 * +251 * @param cvssAccessVector new value of cvssAccessVector +252 */ +253 public void setCvssAccessVector(String cvssAccessVector) { +254 this.cvssAccessVector = cvssAccessVector; +255 } +256 /** +257 * CVSS Access Complexity. +258 */ +259 private String cvssAccessComplexity; +260 +261 /** +262 * Get the value of cvssAccessComplexity. +263 * +264 * @return the value of cvssAccessComplexity +265 */ +266 public String getCvssAccessComplexity() { +267 return cvssAccessComplexity; +268 } +269 +270 /** +271 * Set the value of cvssAccessComplexity. +272 * +273 * @param cvssAccessComplexity new value of cvssAccessComplexity +274 */ +275 public void setCvssAccessComplexity(String cvssAccessComplexity) { +276 this.cvssAccessComplexity = cvssAccessComplexity; +277 } +278 /** +279 * CVSS Authentication. +280 */ +281 private String cvssAuthentication; +282 +283 /** +284 * Get the value of cvssAuthentication. +285 * +286 * @return the value of cvssAuthentication +287 */ +288 public String getCvssAuthentication() { +289 return cvssAuthentication; +290 } +291 +292 /** +293 * Set the value of cvssAuthentication. +294 * +295 * @param cvssAuthentication new value of cvssAuthentication +296 */ +297 public void setCvssAuthentication(String cvssAuthentication) { +298 this.cvssAuthentication = cvssAuthentication; +299 } +300 /** +301 * CVSS Confidentiality Impact. +302 */ +303 private String cvssConfidentialityImpact; +304 +305 /** +306 * Get the value of cvssConfidentialityImpact. +307 * +308 * @return the value of cvssConfidentialityImpact +309 */ +310 public String getCvssConfidentialityImpact() { +311 return cvssConfidentialityImpact; +312 } +313 +314 /** +315 * Set the value of cvssConfidentialityImpact. +316 * +317 * @param cvssConfidentialityImpact new value of cvssConfidentialityImpact +318 */ +319 public void setCvssConfidentialityImpact(String cvssConfidentialityImpact) { +320 this.cvssConfidentialityImpact = cvssConfidentialityImpact; +321 } +322 /** +323 * CVSS Integrity Impact. +324 */ +325 private String cvssIntegrityImpact; +326 +327 /** +328 * Get the value of cvssIntegrityImpact. +329 * +330 * @return the value of cvssIntegrityImpact +331 */ +332 public String getCvssIntegrityImpact() { +333 return cvssIntegrityImpact; +334 } +335 +336 /** +337 * Set the value of cvssIntegrityImpact. +338 * +339 * @param cvssIntegrityImpact new value of cvssIntegrityImpact +340 */ +341 public void setCvssIntegrityImpact(String cvssIntegrityImpact) { +342 this.cvssIntegrityImpact = cvssIntegrityImpact; +343 } +344 /** +345 * CVSS Availability Impact. +346 */ +347 private String cvssAvailabilityImpact; +348 +349 /** +350 * Get the value of cvssAvailabilityImpact. +351 * +352 * @return the value of cvssAvailabilityImpact +353 */ +354 public String getCvssAvailabilityImpact() { +355 return cvssAvailabilityImpact; +356 } +357 +358 /** +359 * Set the value of cvssAvailabilityImpact. +360 * +361 * @param cvssAvailabilityImpact new value of cvssAvailabilityImpact +362 */ +363 public void setCvssAvailabilityImpact(String cvssAvailabilityImpact) { +364 this.cvssAvailabilityImpact = cvssAvailabilityImpact; +365 } +366 +367 @Override +368 public boolean equals(Object obj) { +369 if (obj == null) { +370 return false; +371 } +372 if (getClass() != obj.getClass()) { +373 return false; +374 } +375 final Vulnerability other = (Vulnerability) obj; +376 if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) { +377 return false; +378 } +379 return true; +380 } +381 +382 @Override +383 public int hashCode() { +384 int hash = 5; +385 hash = 41 * hash + (this.name != null ? this.name.hashCode() : 0); +386 return hash; +387 } +388 +389 @Override +390 public String toString() { +391 final StringBuilder sb = new StringBuilder("Vulnerability "); +392 sb.append(this.name); +393 sb.append("\nReferences:\n"); +394 for (Reference reference : this.references) { +395 sb.append("=> "); +396 sb.append(reference); +397 sb.append("\n"); +398 } +399 sb.append("\nSoftware:\n"); +400 for (VulnerableSoftware software : this.vulnerableSoftware) { +401 sb.append("=> "); +402 sb.append(software); +403 sb.append("\n"); +404 } +405 return sb.toString(); +406 } +407 +408 /** +409 * Compares two vulnerabilities. +410 * +411 * @param v a vulnerability to be compared +412 * @return a negative integer, zero, or a positive integer as this object is +413 * less than, equal to, or greater than the specified vulnerability +414 */ +415 @Override +416 public int compareTo(Vulnerability v) { +417 return new CompareToBuilder() +418 .append(this.name, v.name) +419 .toComparison(); +420 //return v.getName().compareTo(this.getName()); +421 } +422 +423 /** +424 * The CPE id that caused this vulnerability to be flagged. +425 */ +426 private String matchedCPE; +427 /** +428 * Whether or not all previous versions were affected. +429 */ +430 private String matchedAllPreviousCPE; +431 +432 /** +433 * Sets the CPE that caused this vulnerability to be flagged. +434 * +435 * @param cpeId a CPE identifier +436 * @param previous a flag indicating whether or not all previous versions +437 * were affected (any non-null value is considered true) +438 */ +439 public void setMatchedCPE(String cpeId, String previous) { +440 matchedCPE = cpeId; +441 matchedAllPreviousCPE = previous; +442 } +443 +444 /** +445 * Get the value of matchedCPE. +446 * +447 * @return the value of matchedCPE +448 */ +449 public String getMatchedCPE() { +450 return matchedCPE; +451 } +452 +453 /** +454 * Get the value of matchedAllPreviousCPE. +455 * +456 * @return the value of matchedAllPreviousCPE +457 */ +458 public String getMatchedAllPreviousCPE() { +459 return matchedAllPreviousCPE; +460 } +461 +462 /** +463 * Determines whether or not matchedAllPreviousCPE has been set. +464 * +465 * @return true if matchedAllPreviousCPE is not null; otherwise false +466 */ +467 public boolean hasMatchedAllPreviousCPE() { +468 return matchedAllPreviousCPE != null; +469 } +470 }
    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 c959cd748..61451b600 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.2 Reference Package org.owasp.dependencycheck.dependency + Dependency-Check Core 1.4.3 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 f32ec399a..bb56a57a2 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.2 Reference Package org.owasp.dependencycheck.dependency + Dependency-Check Core 1.4.3 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 cdb8e053d..05272f763 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/exception/ExceptionCollection.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/exception/ExceptionCollection.html @@ -98,128 +98,141 @@ 90 this.exceptions.add(exceptions); 91 this.fatal = fatal; 92 } -93 /** -94 * Instantiates a new exception collection. -95 * -96 * @param msg the exception message -97 * @param exception a list of exceptions -98 */ -99 public ExceptionCollection(String msg, Throwable exception) { -100 super(msg); -101 this.exceptions = new ArrayList<Throwable>(); -102 this.exceptions.add(exception); -103 this.fatal = false; -104 } -105 -106 /** -107 * Instantiates a new exception collection. -108 */ -109 public ExceptionCollection() { -110 super(); -111 this.exceptions = new ArrayList<Throwable>(); -112 } -113 /** -114 * The serial version uid. -115 */ -116 private static final long serialVersionUID = 1L; -117 -118 /** -119 * A collection of exceptions. -120 */ -121 private List<Throwable> exceptions; -122 -123 /** -124 * Get the value of exceptions. -125 * -126 * @return the value of exceptions -127 */ -128 public List<Throwable> getExceptions() { -129 return exceptions; -130 } -131 -132 /** -133 * Adds an exception to the collection. -134 * -135 * @param ex the exception to add -136 */ -137 public void addException(Throwable ex) { -138 this.exceptions.add(ex); -139 } -140 -141 /** -142 * Adds an exception to the collection. -143 * -144 * @param ex the exception to add -145 * @param fatal flag indicating if this is a fatal error -146 */ -147 public void addException(Throwable ex, boolean fatal) { -148 addException(ex); -149 this.fatal = fatal; -150 } -151 -152 /** -153 * Flag indicating if a fatal exception occurred that would prevent the -154 * attempt at completing the analysis even if exceptions occurred. -155 */ -156 private boolean fatal = false; -157 -158 /** -159 * Get the value of fatal. -160 * -161 * @return the value of fatal -162 */ -163 public boolean isFatal() { -164 return fatal; -165 } -166 -167 /** -168 * Set the value of fatal. -169 * -170 * @param fatal new value of fatal -171 */ -172 public void setFatal(boolean fatal) { -173 this.fatal = fatal; -174 } -175 -176 /** -177 * Prints the stack trace. -178 * -179 * @param s the writer to print to -180 */ -181 @Override -182 public void printStackTrace(PrintWriter s) { -183 s.println("Multiple Exceptions Occured"); -184 super.printStackTrace(s); -185 for (Throwable t : this.exceptions) { -186 s.println("Next Exception:"); -187 t.printStackTrace(s); -188 } -189 } -190 -191 /** -192 * Prints the stack trace. -193 * -194 * @param s the stream to write the stack trace to -195 */ -196 @Override -197 public void printStackTrace(PrintStream s) { -198 s.println("Multiple Exceptions Occured"); -199 super.printStackTrace(s); -200 for (Throwable t : this.exceptions) { -201 s.println("Next Exception:"); -202 t.printStackTrace(s); -203 } -204 } -205 -206 /** -207 * Prints the stack trace to standard error. -208 */ -209 @Override -210 public void printStackTrace() { -211 this.printStackTrace(System.err); -212 } -213 -214 } +93 +94 /** +95 * Instantiates a new exception collection. +96 * +97 * @param msg the exception message +98 * @param exception a list of exceptions +99 */ +100 public ExceptionCollection(String msg, Throwable exception) { +101 super(msg); +102 this.exceptions = new ArrayList<Throwable>(); +103 this.exceptions.add(exception); +104 this.fatal = false; +105 } +106 +107 /** +108 * Instantiates a new exception collection. +109 */ +110 public ExceptionCollection() { +111 super(); +112 this.exceptions = new ArrayList<Throwable>(); +113 } +114 /** +115 * The serial version uid. +116 */ +117 private static final long serialVersionUID = 1L; +118 +119 /** +120 * A collection of exceptions. +121 */ +122 private List<Throwable> exceptions; +123 +124 /** +125 * Get the value of exceptions. +126 * +127 * @return the value of exceptions +128 */ +129 public List<Throwable> getExceptions() { +130 return exceptions; +131 } +132 +133 /** +134 * Adds an exception to the collection. +135 * +136 * @param ex the exception to add +137 */ +138 public void addException(Throwable ex) { +139 this.exceptions.add(ex); +140 } +141 +142 /** +143 * Adds an exception to the collection. +144 * +145 * @param ex the exception to add +146 * @param fatal flag indicating if this is a fatal error +147 */ +148 public void addException(Throwable ex, boolean fatal) { +149 addException(ex); +150 this.fatal = fatal; +151 } +152 +153 /** +154 * Flag indicating if a fatal exception occurred that would prevent the +155 * attempt at completing the analysis even if exceptions occurred. +156 */ +157 private boolean fatal = false; +158 +159 /** +160 * Get the value of fatal. +161 * +162 * @return the value of fatal +163 */ +164 public boolean isFatal() { +165 return fatal; +166 } +167 +168 /** +169 * Set the value of fatal. +170 * +171 * @param fatal new value of fatal +172 */ +173 public void setFatal(boolean fatal) { +174 this.fatal = fatal; +175 } +176 +177 /** +178 * Prints the stack trace. +179 * +180 * @param s the writer to print to +181 */ +182 @Override +183 public void printStackTrace(PrintWriter s) { +184 s.println("Multiple Exceptions Occured"); +185 super.printStackTrace(s); +186 for (Throwable t : this.exceptions) { +187 s.println("Next Exception:"); +188 t.printStackTrace(s); +189 } +190 } +191 +192 /** +193 * Prints the stack trace. +194 * +195 * @param s the stream to write the stack trace to +196 */ +197 @Override +198 public void printStackTrace(PrintStream s) { +199 s.println("Multiple Exceptions Occurred"); +200 super.printStackTrace(s); +201 for (Throwable t : this.exceptions) { +202 s.println("Next Exception:"); +203 t.printStackTrace(s); +204 } +205 } +206 +207 /** +208 * Returns the error message, including the message from all contained +209 * exceptions. +210 * +211 * @return the error message +212 */ +213 @Override +214 public String getMessage() { +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:"); +219 } else { +220 sb.append(msg); +221 } +222 for (Throwable t : this.exceptions) { +223 sb.append("\n\t").append(t.getMessage()); +224 } +225 return sb.toString(); +226 } +227 }
    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 761d461c2..a407701bb 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.2 Reference Package org.owasp.dependencycheck.exception + Dependency-Check Core 1.4.3 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 b017c6fe1..86a3e7dac 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.2 Reference Package org.owasp.dependencycheck.exception + Dependency-Check Core 1.4.3 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 86e05522f..e68c36ddd 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.2 Reference Package org.owasp.dependencycheck + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck 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 6a1128b52..f2b1081d9 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.2 Reference Package org.owasp.dependencycheck + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck 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 0d70e4ea7..3c6d7a48c 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.2 Reference Package org.owasp.dependencycheck.reporting + Dependency-Check Core 1.4.3 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 8c4eb48a2..ea6ad70c5 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.2 Reference Package org.owasp.dependencycheck.reporting + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.reporting diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/utils/DependencyVersionUtil.html b/dependency-check-core/xref/org/owasp/dependencycheck/utils/DependencyVersionUtil.html index 786752621..8619c2cf6 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/utils/DependencyVersionUtil.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/utils/DependencyVersionUtil.html @@ -32,78 +32,114 @@ 24 25 /** 26 * <p> -27 * A utility class to extract version numbers from file names (or other strings containing version numbers.</p> -28 * -29 * @author Jeremy Long -30 */ -31 public final class DependencyVersionUtil { -32 -33 /** -34 * Regular expression to extract version numbers from file names. -35 */ -36 private static final Pattern RX_VERSION = Pattern.compile("\\d+(\\.\\d{1,6})+(\\.?([_-](release|beta|alpha|\\d+)|[a-zA-Z_-]{1,3}\\d{0,8}))?"); -37 /** -38 * Regular expression to extract a single version number without periods. This is a last ditch effort just to check in case we -39 * are missing a version number using the previous regex. -40 */ -41 private static final Pattern RX_SINGLE_VERSION = Pattern.compile("\\d+(\\.?([_-](release|beta|alpha)|[a-zA-Z_-]{1,3}\\d{1,8}))?"); -42 -43 /** -44 * Private constructor for utility class. -45 */ -46 private DependencyVersionUtil() { -47 } -48 -49 /** -50 * <p> -51 * A utility class to extract version numbers from file names (or other strings containing version numbers.</p> -52 * <pre> -53 * Example: -54 * Give the file name: library-name-1.4.1r2-release.jar -55 * This function would return: 1.4.1.r2</pre> -56 * -57 * @param text the text being analyzed -58 * @return a DependencyVersion containing the version -59 */ -60 public static DependencyVersion parseVersion(String text) { -61 if (text == null) { -62 return null; -63 } -64 //'-' is a special case used within the CVE entries, just include it as the version. -65 if ("-".equals(text)) { -66 final DependencyVersion dv = new DependencyVersion(); -67 final List<String> list = new ArrayList<String>(); -68 list.add(text); -69 dv.setVersionParts(list); -70 return dv; -71 } -72 String version = null; -73 Matcher matcher = RX_VERSION.matcher(text); -74 if (matcher.find()) { -75 version = matcher.group(); -76 } -77 //throw away the results if there are two things that look like version numbers -78 if (matcher.find()) { -79 return null; -80 } -81 if (version == null) { -82 matcher = RX_SINGLE_VERSION.matcher(text); -83 if (matcher.find()) { -84 version = matcher.group(); -85 } else { -86 return null; -87 } -88 //throw away the results if there are two things that look like version numbers -89 if (matcher.find()) { -90 return null; -91 } -92 } -93 if (version != null && version.endsWith("-py2") && version.length() > 4) { -94 version = version.substring(0, version.length() - 4); -95 } -96 return new DependencyVersion(version); -97 } -98 } +27 * A utility class to extract version numbers from file names (or other strings +28 * containing version numbers.</p> +29 * +30 * @author Jeremy Long +31 */ +32 public final class DependencyVersionUtil { +33 +34 /** +35 * Regular expression to extract version numbers from file names. +36 */ +37 private static final Pattern RX_VERSION = Pattern.compile("\\d+(\\.\\d{1,6})+(\\.?([_-](release|beta|alpha|\\d+)|[a-zA-Z_-]{1,3}\\d{0,8}))?"); +38 /** +39 * Regular expression to extract a single version number without periods. +40 * This is a last ditch effort just to check in case we are missing a +41 * version number using the previous regex. +42 */ +43 private static final Pattern RX_SINGLE_VERSION = Pattern.compile("\\d+(\\.?([_-](release|beta|alpha)|[a-zA-Z_-]{1,3}\\d{1,8}))?"); +44 +45 /** +46 * Regular expression to extract the part before the version numbers if +47 * there are any based on RX_VERSION. In most cases, this part represents a +48 * more accurate name. +49 */ +50 private static final Pattern RX_PRE_VERSION = Pattern.compile("^(.+)[_-](\\d+\\.\\d{1,6})+"); +51 +52 /** +53 * Private constructor for utility class. +54 */ +55 private DependencyVersionUtil() { +56 } +57 +58 /** +59 * <p> +60 * A utility class to extract version numbers from file names (or other +61 * strings containing version numbers.</p> +62 * <pre> +63 * Example: +64 * Give the file name: library-name-1.4.1r2-release.jar +65 * This function would return: 1.4.1.r2</pre> +66 * +67 * @param text the text being analyzed +68 * @return a DependencyVersion containing the version +69 */ +70 public static DependencyVersion parseVersion(String text) { +71 if (text == null) { +72 return null; +73 } +74 //'-' is a special case used within the CVE entries, just include it as the version. +75 if ("-".equals(text)) { +76 final DependencyVersion dv = new DependencyVersion(); +77 final List<String> list = new ArrayList<String>(); +78 list.add(text); +79 dv.setVersionParts(list); +80 return dv; +81 } +82 String version = null; +83 Matcher matcher = RX_VERSION.matcher(text); +84 if (matcher.find()) { +85 version = matcher.group(); +86 } +87 //throw away the results if there are two things that look like version numbers +88 if (matcher.find()) { +89 return null; +90 } +91 if (version == null) { +92 matcher = RX_SINGLE_VERSION.matcher(text); +93 if (matcher.find()) { +94 version = matcher.group(); +95 } else { +96 return null; +97 } +98 //throw away the results if there are two things that look like version numbers +99 if (matcher.find()) { +100 return null; +101 } +102 } +103 if (version != null && version.endsWith("-py2") && version.length() > 4) { +104 version = version.substring(0, version.length() - 4); +105 } +106 return new DependencyVersion(version); +107 } +108 +109 /** +110 * <p> +111 * A utility class to extract the part before version numbers from file +112 * names (or other strings containing version numbers. In most cases, this +113 * part represents a more accurate name than the full file name.</p> +114 * <pre> +115 * Example: +116 * Give the file name: library-name-1.4.1r2-release.jar +117 * This function would return: library-name</pre> +118 * +119 * @param text the text being analyzed +120 * @return the part before the version numbers if any, otherwise return the +121 * text itself. +122 */ +123 public static String parsePreVersion(String text) { +124 if (parseVersion(text) == null) { +125 return text; +126 } +127 +128 final Matcher matcher = RX_PRE_VERSION.matcher(text); +129 if (matcher.find()) { +130 return matcher.group(1); +131 } +132 return text; +133 } +134 }
    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 8a182419c..90e99a4d0 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.2 Reference Package org.owasp.dependencycheck.utils + Dependency-Check Core 1.4.3 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 0c5f1900a..bcaf3ed01 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.2 Reference Package org.owasp.dependencycheck.utils + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.utils diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/xml/hints/HintHandler.html b/dependency-check-core/xref/org/owasp/dependencycheck/xml/hints/HintHandler.html index f09cdc53b..943e12b74 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/xml/hints/HintHandler.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/xml/hints/HintHandler.html @@ -70,159 +70,176 @@ 62 */ 63 private static final String DUPLICATE = "duplicate"; 64 /** -65 * Attribute name. +65 * Attribute value. 66 */ 67 private static final String VENDOR = "vendor"; 68 /** -69 * Attribute name. +69 * Attribute value. 70 */ -71 private static final String CONFIDENCE = "confidence"; +71 private static final String PRODUCT = "product"; 72 /** -73 * Attribute name. +73 * Attribute value. 74 */ -75 private static final String VALUE = "value"; +75 private static final String VERSION = "version"; 76 /** 77 * Attribute name. 78 */ -79 private static final String NAME = "name"; +79 private static final String CONFIDENCE = "confidence"; 80 /** 81 * Attribute name. 82 */ -83 private static final String SOURCE = "source"; +83 private static final String VALUE = "value"; 84 /** 85 * Attribute name. 86 */ -87 private static final String TYPE = "type"; +87 private static final String NAME = "name"; 88 /** 89 * Attribute name. 90 */ -91 private static final String CASE_SENSITIVE = "caseSensitive"; +91 private static final String SOURCE = "source"; 92 /** 93 * Attribute name. 94 */ -95 private static final String REGEX = "regex"; +95 private static final String TYPE = "type"; 96 /** 97 * Attribute name. 98 */ -99 private static final String CONTAINS = "contains"; -100 //</editor-fold> -101 -102 /** -103 * The list of hint rules. -104 */ -105 private final List<HintRule> hintRules = new ArrayList<HintRule>(); -106 -107 /** -108 * Returns the list of hint rules. -109 * -110 * @return the value of hintRules -111 */ -112 public List<HintRule> getHintRules() { -113 return hintRules; -114 } -115 -116 /** -117 * The list of vendor duplicating hint rules. -118 */ -119 private final List<VendorDuplicatingHintRule> vendorDuplicatingHintRules = new ArrayList<VendorDuplicatingHintRule>(); -120 -121 /** -122 * Returns the list of vendor duplicating hint rules. -123 * -124 * @return the list of vendor duplicating hint rules -125 */ -126 public List<VendorDuplicatingHintRule> getVendorDuplicatingHintRules() { -127 return vendorDuplicatingHintRules; -128 } -129 -130 /** -131 * The current rule being read. -132 */ -133 private HintRule rule; -134 /** -135 * The current state of the parent node (to differentiate between 'add' and -136 * 'given'). -137 */ -138 private boolean inAddNode = false; -139 -140 /** -141 * Handles the start element event. -142 * -143 * @param uri the uri of the element being processed -144 * @param localName the local name of the element being processed -145 * @param qName the qName of the element being processed -146 * @param attr the attributes of the element being processed -147 * @throws SAXException thrown if there is an exception processing -148 */ -149 @Override -150 public void startElement(String uri, String localName, String qName, Attributes attr) throws SAXException { -151 if (HINT.equals(qName)) { -152 rule = new HintRule(); -153 } else if (ADD.equals(qName)) { -154 inAddNode = true; -155 } else if (GIVEN.equals(qName)) { -156 inAddNode = false; -157 } else if (EVIDENCE.equals(qName)) { -158 final String hintType = attr.getValue(TYPE); -159 if (VENDOR.equals(hintType)) { -160 if (inAddNode) { -161 rule.addAddVendor(attr.getValue(SOURCE), -162 attr.getValue(NAME), -163 attr.getValue(VALUE), -164 Confidence.valueOf(attr.getValue(CONFIDENCE))); -165 } else { -166 rule.addGivenVendor(attr.getValue(SOURCE), -167 attr.getValue(NAME), -168 attr.getValue(VALUE), -169 Confidence.valueOf(attr.getValue(CONFIDENCE))); -170 } -171 } else if (inAddNode) { -172 rule.addAddProduct(attr.getValue(SOURCE), -173 attr.getValue(NAME), -174 attr.getValue(VALUE), -175 Confidence.valueOf(attr.getValue(CONFIDENCE))); -176 } else { -177 rule.addGivenProduct(attr.getValue(SOURCE), -178 attr.getValue(NAME), -179 attr.getValue(VALUE), -180 Confidence.valueOf(attr.getValue(CONFIDENCE))); -181 } -182 } else if (FILE_NAME.equals(qName)) { -183 final PropertyType pt = new PropertyType(); -184 pt.setValue(attr.getValue(CONTAINS)); -185 if (attr.getLength() > 0) { -186 final String regex = attr.getValue(REGEX); -187 if (regex != null) { -188 pt.setRegex(Boolean.parseBoolean(regex)); -189 } -190 final String caseSensitive = attr.getValue(CASE_SENSITIVE); -191 if (caseSensitive != null) { -192 pt.setCaseSensitive(Boolean.parseBoolean(caseSensitive)); -193 } -194 } -195 rule.addFilename(pt); -196 } else if (VENDOR_DUPLICATING_RULE.equals(qName)) { -197 vendorDuplicatingHintRules.add(new VendorDuplicatingHintRule(attr.getValue(VALUE), attr.getValue(DUPLICATE))); -198 } -199 } -200 -201 /** -202 * Handles the end element event. -203 * -204 * @param uri the element's URI -205 * @param localName the local name -206 * @param qName the qualified name -207 * @throws SAXException thrown if there is an exception processing the -208 * element -209 */ -210 @Override -211 public void endElement(String uri, String localName, String qName) throws SAXException { -212 if (HINT.equals(qName) && rule != null) { -213 hintRules.add(rule); -214 rule = null; +99 private static final String CASE_SENSITIVE = "caseSensitive"; +100 /** +101 * Attribute name. +102 */ +103 private static final String REGEX = "regex"; +104 /** +105 * Attribute name. +106 */ +107 private static final String CONTAINS = "contains"; +108 //</editor-fold> +109 +110 /** +111 * The list of hint rules. +112 */ +113 private final List<HintRule> hintRules = new ArrayList<HintRule>(); +114 +115 /** +116 * Returns the list of hint rules. +117 * +118 * @return the value of hintRules +119 */ +120 public List<HintRule> getHintRules() { +121 return hintRules; +122 } +123 +124 /** +125 * The list of vendor duplicating hint rules. +126 */ +127 private final List<VendorDuplicatingHintRule> vendorDuplicatingHintRules = new ArrayList<VendorDuplicatingHintRule>(); +128 +129 /** +130 * Returns the list of vendor duplicating hint rules. +131 * +132 * @return the list of vendor duplicating hint rules +133 */ +134 public List<VendorDuplicatingHintRule> getVendorDuplicatingHintRules() { +135 return vendorDuplicatingHintRules; +136 } +137 +138 /** +139 * The current rule being read. +140 */ +141 private HintRule rule; +142 /** +143 * The current state of the parent node (to differentiate between 'add' and +144 * 'given'). +145 */ +146 private boolean inAddNode = false; +147 +148 /** +149 * Handles the start element event. +150 * +151 * @param uri the uri of the element being processed +152 * @param localName the local name of the element being processed +153 * @param qName the qName of the element being processed +154 * @param attr the attributes of the element being processed +155 * @throws SAXException thrown if there is an exception processing +156 */ +157 @Override +158 public void startElement(String uri, String localName, String qName, Attributes attr) throws SAXException { +159 if (HINT.equals(qName)) { +160 rule = new HintRule(); +161 } else if (ADD.equals(qName)) { +162 inAddNode = true; +163 } else if (GIVEN.equals(qName)) { +164 inAddNode = false; +165 } else if (EVIDENCE.equals(qName)) { +166 final String hintType = attr.getValue(TYPE); +167 if (VENDOR.equals(hintType)) { +168 if (inAddNode) { +169 rule.addAddVendor(attr.getValue(SOURCE), +170 attr.getValue(NAME), +171 attr.getValue(VALUE), +172 Confidence.valueOf(attr.getValue(CONFIDENCE))); +173 } else { +174 rule.addGivenVendor(attr.getValue(SOURCE), +175 attr.getValue(NAME), +176 attr.getValue(VALUE), +177 Confidence.valueOf(attr.getValue(CONFIDENCE))); +178 } +179 } else if (PRODUCT.equals(hintType)) { +180 if (inAddNode) { +181 rule.addAddProduct(attr.getValue(SOURCE), +182 attr.getValue(NAME), +183 attr.getValue(VALUE), +184 Confidence.valueOf(attr.getValue(CONFIDENCE))); +185 } else { +186 rule.addGivenProduct(attr.getValue(SOURCE), +187 attr.getValue(NAME), +188 attr.getValue(VALUE), +189 Confidence.valueOf(attr.getValue(CONFIDENCE))); +190 } +191 } else if (VERSION.equals(hintType)) { +192 if (inAddNode) { +193 rule.addAddVersion(attr.getValue(SOURCE), +194 attr.getValue(NAME), +195 attr.getValue(VALUE), +196 Confidence.valueOf(attr.getValue(CONFIDENCE))); +197 } +198 } +199 } else if (FILE_NAME.equals(qName)) { +200 final PropertyType pt = new PropertyType(); +201 pt.setValue(attr.getValue(CONTAINS)); +202 if (attr.getLength() > 0) { +203 final String regex = attr.getValue(REGEX); +204 if (regex != null) { +205 pt.setRegex(Boolean.parseBoolean(regex)); +206 } +207 final String caseSensitive = attr.getValue(CASE_SENSITIVE); +208 if (caseSensitive != null) { +209 pt.setCaseSensitive(Boolean.parseBoolean(caseSensitive)); +210 } +211 } +212 rule.addFilename(pt); +213 } else if (VENDOR_DUPLICATING_RULE.equals(qName)) { +214 vendorDuplicatingHintRules.add(new VendorDuplicatingHintRule(attr.getValue(VALUE), attr.getValue(DUPLICATE))); 215 } 216 } -217 } +217 +218 /** +219 * Handles the end element event. +220 * +221 * @param uri the element's URI +222 * @param localName the local name +223 * @param qName the qualified name +224 * @throws SAXException thrown if there is an exception processing the +225 * element +226 */ +227 @Override +228 public void endElement(String uri, String localName, String qName) throws SAXException { +229 if (HINT.equals(qName) && rule != null) { +230 hintRules.add(rule); +231 rule = null; +232 } +233 } +234 }
    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 ca18ae491..7ffb4ffda 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 @@ -72,7 +72,7 @@ 64 /** 65 * The schema for the hint XML files. 66 */ -67 private static final String HINT_SCHEMA = "schema/dependency-hint.1.0.xsd"; +67 private static final String HINT_SCHEMA = "schema/dependency-hint.1.1.xsd"; 68 69 /** 70 * Parses the given XML file and returns a list of the hints contained. @@ -112,46 +112,55 @@ 104 * @throws SAXException thrown if the XML cannot be parsed 105 */ 106 public Hints parseHints(InputStream inputStream) throws HintParseException, SAXException { -107 try { -108 final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream(HINT_SCHEMA); -109 final HintHandler handler = new HintHandler(); -110 final SAXParserFactory factory = SAXParserFactory.newInstance(); -111 factory.setNamespaceAware(true); -112 factory.setValidating(true); -113 final SAXParser saxParser = factory.newSAXParser(); -114 saxParser.setProperty(HintParser.JAXP_SCHEMA_LANGUAGE, HintParser.W3C_XML_SCHEMA); -115 saxParser.setProperty(HintParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); -116 final XMLReader xmlReader = saxParser.getXMLReader(); -117 xmlReader.setErrorHandler(new HintErrorHandler()); -118 xmlReader.setContentHandler(handler); -119 -120 final Reader reader = new InputStreamReader(inputStream, "UTF-8"); -121 final InputSource in = new InputSource(reader); -122 -123 xmlReader.parse(in); -124 final Hints hints = new Hints(); -125 hints.setHintRules(handler.getHintRules()); -126 hints.setVendorDuplicatingHintRules(handler.getVendorDuplicatingHintRules()); -127 return hints; -128 } catch (ParserConfigurationException ex) { -129 LOGGER.debug("", ex); -130 throw new HintParseException(ex); -131 } catch (SAXException ex) { -132 if (ex.getMessage().contains("Cannot find the declaration of element 'hints'.")) { -133 throw ex; -134 } else { -135 LOGGER.debug("", ex); -136 throw new HintParseException(ex); -137 } -138 } catch (FileNotFoundException ex) { -139 LOGGER.debug("", ex); -140 throw new HintParseException(ex); -141 } catch (IOException ex) { -142 LOGGER.debug("", ex); -143 throw new HintParseException(ex); -144 } -145 } -146 } +107 InputStream schemaStream = null; +108 try { +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 }
    diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/xml/hints/HintRule.html b/dependency-check-core/xref/org/owasp/dependencycheck/xml/hints/HintRule.html index c17ba93e9..dfe9c38a7 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/xml/hints/HintRule.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/xml/hints/HintRule.html @@ -94,78 +94,103 @@ 86 private final List<Evidence> givenVendor = new ArrayList<Evidence>(); 87 88 /** -89 * Adds a given vendors to the list of evidence to matched. -90 * -91 * @param source the source of the evidence -92 * @param name the name of the evidence -93 * @param value the value of the evidence -94 * @param confidence the confidence of the evidence -95 */ -96 public void addGivenVendor(String source, String name, String value, Confidence confidence) { -97 givenVendor.add(new Evidence(source, name, value, confidence)); -98 } -99 -100 /** -101 * Get the value of givenVendor. -102 * -103 * @return the value of givenVendor +89 * The list of product evidence to add. +90 */ +91 private final List<Evidence> addProduct = new ArrayList<Evidence>(); +92 /** +93 * The list of version evidence to add. +94 */ +95 private final List<Evidence> addVersion = new ArrayList<Evidence>(); +96 +97 /** +98 * Adds a given vendors to the list of evidence to matched. +99 * +100 * @param source the source of the evidence +101 * @param name the name of the evidence +102 * @param value the value of the evidence +103 * @param confidence the confidence of the evidence 104 */ -105 public List<Evidence> getGivenVendor() { -106 return givenVendor; +105 public void addGivenVendor(String source, String name, String value, Confidence confidence) { +106 givenVendor.add(new Evidence(source, name, value, confidence)); 107 } 108 109 /** -110 * The list of product evidence to add. -111 */ -112 private final List<Evidence> addProduct = new ArrayList<Evidence>(); -113 -114 /** -115 * Adds a given product to the list of evidence to add when matched. -116 * -117 * @param source the source of the evidence -118 * @param name the name of the evidence -119 * @param value the value of the evidence -120 * @param confidence the confidence of the evidence -121 */ -122 public void addAddProduct(String source, String name, String value, Confidence confidence) { -123 addProduct.add(new Evidence(source, name, value, confidence)); -124 } -125 -126 /** -127 * Get the value of addProduct. -128 * -129 * @return the value of addProduct -130 */ -131 public List<Evidence> getAddProduct() { -132 return addProduct; -133 } -134 -135 /** -136 * The list of vendor hints to add. -137 */ -138 private final List<Evidence> addVendor = new ArrayList<Evidence>(); -139 -140 /** -141 * Adds a given vendor to the list of evidence to add when matched. -142 * -143 * @param source the source of the evidence -144 * @param name the name of the evidence -145 * @param value the value of the evidence -146 * @param confidence the confidence of the evidence -147 */ -148 public void addAddVendor(String source, String name, String value, Confidence confidence) { -149 addVendor.add(new Evidence(source, name, value, confidence)); -150 } -151 -152 /** -153 * Get the value of addVendor. -154 * -155 * @return the value of addVendor -156 */ -157 public List<Evidence> getAddVendor() { -158 return addVendor; -159 } -160 } +110 * Get the value of givenVendor. +111 * +112 * @return the value of givenVendor +113 */ +114 public List<Evidence> getGivenVendor() { +115 return givenVendor; +116 } +117 +118 /** +119 * Adds a given product to the list of evidence to add when matched. +120 * +121 * @param source the source of the evidence +122 * @param name the name of the evidence +123 * @param value the value of the evidence +124 * @param confidence the confidence of the evidence +125 */ +126 public void addAddProduct(String source, String name, String value, Confidence confidence) { +127 addProduct.add(new Evidence(source, name, value, confidence)); +128 } +129 +130 /** +131 * Get the value of addProduct. +132 * +133 * @return the value of addProduct +134 */ +135 public List<Evidence> getAddProduct() { +136 return addProduct; +137 } +138 +139 /** +140 * Adds a given version to the list of evidence to add when matched. +141 * +142 * @param source the source of the evidence +143 * @param name the name of the evidence +144 * @param value the value of the evidence +145 * @param confidence the confidence of the evidence +146 */ +147 public void addAddVersion(String source, String name, String value, Confidence confidence) { +148 addVersion.add(new Evidence(source, name, value, confidence)); +149 } +150 +151 /** +152 * Get the value of addVersion. +153 * +154 * @return the value of addVersion +155 */ +156 public List<Evidence> getAddVersion() { +157 return addVersion; +158 } +159 +160 /** +161 * The list of vendor hints to add. +162 */ +163 private final List<Evidence> addVendor = new ArrayList<Evidence>(); +164 +165 /** +166 * Adds a given vendor to the list of evidence to add when matched. +167 * +168 * @param source the source of the evidence +169 * @param name the name of the evidence +170 * @param value the value of the evidence +171 * @param confidence the confidence of the evidence +172 */ +173 public void addAddVendor(String source, String name, String value, Confidence confidence) { +174 addVendor.add(new Evidence(source, name, value, confidence)); +175 } +176 +177 /** +178 * Get the value of addVendor. +179 * +180 * @return the value of addVendor +181 */ +182 public List<Evidence> getAddVendor() { +183 return addVendor; +184 } +185 }
    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 aa07f7f60..d3276ca69 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.2 Reference Package org.owasp.dependencycheck.xml.hints + Dependency-Check Core 1.4.3 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 4d24c2706..cf7481c87 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.2 Reference Package org.owasp.dependencycheck.xml.hints + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.xml.hints diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/xml/pom/PomUtils.html b/dependency-check-core/xref/org/owasp/dependencycheck/xml/pom/PomUtils.html index 534ba81f2..aadfe5987 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/xml/pom/PomUtils.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/xml/pom/PomUtils.html @@ -56,74 +56,82 @@ 48 * 49 * @param file the pom.xml file 50 * @return returns a -51 * @throws AnalysisException is thrown if there is an exception extracting or parsing the POM {@link Model} object -52 */ -53 public static Model readPom(File file) throws AnalysisException { -54 Model model = null; +51 * @throws AnalysisException is thrown if there is an exception extracting +52 * or parsing the POM {@link Model} object +53 */ +54 public static Model readPom(File file) throws AnalysisException { 55 try { 56 final PomParser parser = new PomParser(); -57 model = parser.parse(file); -58 } catch (PomParseException ex) { -59 LOGGER.warn("Unable to parse pom '{}'", file.getPath()); -60 LOGGER.debug("", ex); -61 throw new AnalysisException(ex); -62 } catch (IOException ex) { -63 LOGGER.warn("Unable to parse pom '{}'(IO Exception)", file.getPath()); +57 final Model model = parser.parse(file); +58 if (model == null) { +59 throw new AnalysisException(String.format("Unable to parse pom '%s'", file.getPath())); +60 } +61 return model; +62 } catch (PomParseException ex) { +63 LOGGER.warn("Unable to parse pom '{}'", file.getPath()); 64 LOGGER.debug("", ex); 65 throw new AnalysisException(ex); -66 } catch (Throwable ex) { -67 LOGGER.warn("Unexpected error during parsing of the pom '{}'", file.getPath()); +66 } catch (IOException ex) { +67 LOGGER.warn("Unable to parse pom '{}'(IO Exception)", file.getPath()); 68 LOGGER.debug("", ex); 69 throw new AnalysisException(ex); -70 } -71 return model; -72 } -73 -74 /** -75 * Retrieves the specified POM from a jar file and converts it to a Model. -76 * -77 * @param path the path to the pom.xml file within the jar file -78 * @param jar the jar file to extract the pom from -79 * @return returns a -80 * @throws AnalysisException is thrown if there is an exception extracting or parsing the POM {@link Model} object -81 */ -82 public static Model readPom(String path, JarFile jar) throws AnalysisException { -83 final ZipEntry entry = jar.getEntry(path); -84 Model model = null; -85 if (entry != null) { //should never be null -86 try { -87 final PomParser parser = new PomParser(); -88 model = parser.parse(jar.getInputStream(entry)); -89 LOGGER.debug("Read POM {}", path); -90 } catch (SecurityException ex) { -91 LOGGER.warn("Unable to parse pom '{}' in jar '{}'; invalid signature", path, jar.getName()); -92 LOGGER.debug("", ex); -93 throw new AnalysisException(ex); -94 } catch (IOException ex) { -95 LOGGER.warn("Unable to parse pom '{}' in jar '{}' (IO Exception)", path, jar.getName()); -96 LOGGER.debug("", ex); -97 throw new AnalysisException(ex); -98 } catch (Throwable ex) { -99 LOGGER.warn("Unexpected error during parsing of the pom '{}' in jar '{}'", path, jar.getName()); -100 LOGGER.debug("", ex); -101 throw new AnalysisException(ex); -102 } -103 } -104 return model; -105 } -106 -107 /** -108 * Reads in the pom file and adds elements as evidence to the given dependency. -109 * -110 * @param dependency the dependency being analyzed -111 * @param pomFile the pom file to read -112 * @throws AnalysisException is thrown if there is an exception parsing the pom -113 */ -114 public static void analyzePOM(Dependency dependency, File pomFile) throws AnalysisException { -115 final Model pom = PomUtils.readPom(pomFile); -116 JarAnalyzer.setPomEvidence(dependency, pom, null); -117 } -118 } +70 } catch (Throwable ex) { +71 LOGGER.warn("Unexpected error during parsing of the pom '{}'", file.getPath()); +72 LOGGER.debug("", ex); +73 throw new AnalysisException(ex); +74 } +75 } +76 +77 /** +78 * Retrieves the specified POM from a jar file and converts it to a Model. +79 * +80 * @param path the path to the pom.xml file within the jar file +81 * @param jar the jar file to extract the pom from +82 * @return returns a +83 * @throws AnalysisException is thrown if there is an exception extracting +84 * or parsing the POM {@link Model} object +85 */ +86 public static Model readPom(String path, JarFile jar) throws AnalysisException { +87 final ZipEntry entry = jar.getEntry(path); +88 Model model = null; +89 if (entry != null) { //should never be null +90 try { +91 final PomParser parser = new PomParser(); +92 model = parser.parse(jar.getInputStream(entry)); +93 if (model == null) { +94 throw new AnalysisException(String.format("Unable to parse pom '%s/%s'", jar.getName(), path)); +95 } +96 } catch (SecurityException ex) { +97 LOGGER.warn("Unable to parse pom '{}' in jar '{}'; invalid signature", path, jar.getName()); +98 LOGGER.debug("", ex); +99 throw new AnalysisException(ex); +100 } catch (IOException ex) { +101 LOGGER.warn("Unable to parse pom '{}' in jar '{}' (IO Exception)", path, jar.getName()); +102 LOGGER.debug("", ex); +103 throw new AnalysisException(ex); +104 } catch (Throwable ex) { +105 LOGGER.warn("Unexpected error during parsing of the pom '{}' in jar '{}'", path, jar.getName()); +106 LOGGER.debug("", ex); +107 throw new AnalysisException(ex); +108 } +109 } +110 return model; +111 } +112 +113 /** +114 * Reads in the pom file and adds elements as evidence to the given +115 * dependency. +116 * +117 * @param dependency the dependency being analyzed +118 * @param pomFile the pom file to read +119 * @throws AnalysisException is thrown if there is an exception parsing the +120 * pom +121 */ +122 public static void analyzePOM(Dependency dependency, File pomFile) throws AnalysisException { +123 final Model pom = PomUtils.readPom(pomFile); +124 JarAnalyzer.setPomEvidence(dependency, pom, null); +125 } +126 }
    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 29c700458..59f55f9bc 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.2 Reference Package org.owasp.dependencycheck.xml.pom + Dependency-Check Core 1.4.3 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 dc84132a0..45879868a 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.2 Reference Package org.owasp.dependencycheck.xml.pom + Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.xml.pom diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/xml/suppression/SuppressionErrorHandler.html b/dependency-check-core/xref/org/owasp/dependencycheck/xml/suppression/SuppressionErrorHandler.html index c9387de53..2bce126c7 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/xml/suppression/SuppressionErrorHandler.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/xml/suppression/SuppressionErrorHandler.html @@ -25,84 +25,82 @@ 17 */ 18 package org.owasp.dependencycheck.xml.suppression; 19 -20 import org.slf4j.Logger; -21 import org.slf4j.LoggerFactory; -22 import org.xml.sax.ErrorHandler; -23 import org.xml.sax.SAXException; -24 import org.xml.sax.SAXParseException; -25 -26 /** -27 * An XML parsing error handler. -28 * -29 * @author Jeremy Long -30 */ -31 public class SuppressionErrorHandler implements ErrorHandler { -32 -33 /** -34 * The logger. -35 */ -36 private static final Logger LOGGER = LoggerFactory.getLogger(SuppressionErrorHandler.class); -37 -38 /** -39 * Builds a prettier exception message. -40 * -41 * @param ex the SAXParseException -42 * @return an easier to read exception message -43 */ -44 private String getPrettyParseExceptionInfo(SAXParseException ex) { +20 import org.xml.sax.ErrorHandler; +21 import org.xml.sax.SAXException; +22 import org.xml.sax.SAXParseException; +23 +24 /** +25 * An XML parsing error handler. +26 * +27 * @author Jeremy Long +28 */ +29 public class SuppressionErrorHandler implements ErrorHandler { +30 +31 /** +32 * The logger. +33 */ +34 //private static final Logger LOGGER = LoggerFactory.getLogger(SuppressionErrorHandler.class); +35 +36 /** +37 * Builds a prettier exception message. +38 * +39 * @param ex the SAXParseException +40 * @return an easier to read exception message +41 */ +42 private String getPrettyParseExceptionInfo(SAXParseException ex) { +43 +44 final StringBuilder sb = new StringBuilder(); 45 -46 final StringBuilder sb = new StringBuilder(); -47 -48 if (ex.getSystemId() != null) { -49 sb.append("systemId=").append(ex.getSystemId()).append(", "); -50 } -51 if (ex.getPublicId() != null) { -52 sb.append("publicId=").append(ex.getPublicId()).append(", "); -53 } -54 if (ex.getLineNumber() > 0) { -55 sb.append("Line=").append(ex.getLineNumber()); -56 } -57 if (ex.getColumnNumber() > 0) { -58 sb.append(", Column=").append(ex.getColumnNumber()); -59 } -60 sb.append(": ").append(ex.getMessage()); -61 -62 return sb.toString(); -63 } -64 -65 /** -66 * Logs warnings. -67 * -68 * @param ex the warning to log -69 * @throws SAXException is never thrown -70 */ -71 @Override -72 public void warning(SAXParseException ex) throws SAXException { -73 //LOGGER.debug("", ex); -74 } -75 -76 /** -77 * Handles errors. -78 * -79 * @param ex the error to handle -80 * @throws SAXException is always thrown -81 */ -82 @Override -83 public void error(SAXParseException ex) throws SAXException { -84 throw new SAXException(getPrettyParseExceptionInfo(ex)); -85 } -86 -87 /** -88 * Handles fatal exceptions. -89 * -90 * @param ex a fatal exception -91 * @throws SAXException is always -92 */ -93 @Override -94 public void fatalError(SAXParseException ex) throws SAXException { -95 throw new SAXException(getPrettyParseExceptionInfo(ex)); -96 } -97 } +46 if (ex.getSystemId() != null) { +47 sb.append("systemId=").append(ex.getSystemId()).append(", "); +48 } +49 if (ex.getPublicId() != null) { +50 sb.append("publicId=").append(ex.getPublicId()).append(", "); +51 } +52 if (ex.getLineNumber() > 0) { +53 sb.append("Line=").append(ex.getLineNumber()); +54 } +55 if (ex.getColumnNumber() > 0) { +56 sb.append(", Column=").append(ex.getColumnNumber()); +57 } +58 sb.append(": ").append(ex.getMessage()); +59 +60 return sb.toString(); +61 } +62 +63 /** +64 * Logs warnings. +65 * +66 * @param ex the warning to log +67 * @throws SAXException is never thrown +68 */ +69 @Override +70 public void warning(SAXParseException ex) throws SAXException { +71 //LOGGER.debug("", ex); +72 } +73 +74 /** +75 * Handles errors. +76 * +77 * @param ex the error to handle +78 * @throws SAXException is always thrown +79 */ +80 @Override +81 public void error(SAXParseException ex) throws SAXException { +82 throw new SAXException(getPrettyParseExceptionInfo(ex)); +83 } +84 +85 /** +86 * Handles fatal exceptions. +87 * +88 * @param ex a fatal exception +89 * @throws SAXException is always +90 */ +91 @Override +92 public void fatalError(SAXParseException ex) throws SAXException { +93 throw new SAXException(getPrettyParseExceptionInfo(ex)); +94 } +95 }
    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 1981f2df2..584dfa251 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 @@ -129,88 +129,106 @@ 121 * @throws SAXException thrown if the XML cannot be parsed 122 */ 123 public List<SuppressionRule> parseSuppressionRules(InputStream inputStream) throws SuppressionParseException, SAXException { -124 try { -125 final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream(SUPPRESSION_SCHEMA); -126 final SuppressionHandler handler = new SuppressionHandler(); -127 final SAXParserFactory factory = SAXParserFactory.newInstance(); -128 factory.setNamespaceAware(true); -129 factory.setValidating(true); -130 final SAXParser saxParser = factory.newSAXParser(); -131 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA); -132 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); -133 final XMLReader xmlReader = saxParser.getXMLReader(); -134 xmlReader.setErrorHandler(new SuppressionErrorHandler()); -135 xmlReader.setContentHandler(handler); -136 -137 final Reader reader = new InputStreamReader(inputStream, "UTF-8"); -138 final InputSource in = new InputSource(reader); -139 //in.setEncoding("UTF-8"); -140 -141 xmlReader.parse(in); -142 -143 return handler.getSuppressionRules(); -144 } catch (ParserConfigurationException ex) { -145 LOGGER.debug("", ex); -146 throw new SuppressionParseException(ex); -147 } catch (SAXException ex) { -148 if (ex.getMessage().contains("Cannot find the declaration of element 'suppressions'.")) { -149 throw ex; -150 } else { -151 LOGGER.debug("", ex); -152 throw new SuppressionParseException(ex); -153 } -154 } catch (FileNotFoundException ex) { -155 LOGGER.debug("", ex); -156 throw new SuppressionParseException(ex); -157 } catch (IOException ex) { -158 LOGGER.debug("", ex); -159 throw new SuppressionParseException(ex); -160 } -161 } -162 -163 /** -164 * Parses the given XML stream and returns a list of the suppression rules -165 * contained. -166 * -167 * @param inputStream an InputStream containing suppression rues -168 * @return a list of suppression rules -169 * @throws SuppressionParseException if the XML cannot be parsed -170 */ -171 private List<SuppressionRule> parseOldSuppressionRules(InputStream inputStream) throws SuppressionParseException { -172 try { -173 final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream(OLD_SUPPRESSION_SCHEMA); -174 final SuppressionHandler handler = new SuppressionHandler(); -175 final SAXParserFactory factory = SAXParserFactory.newInstance(); -176 factory.setNamespaceAware(true); -177 factory.setValidating(true); -178 final SAXParser saxParser = factory.newSAXParser(); -179 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA); -180 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); -181 final XMLReader xmlReader = saxParser.getXMLReader(); -182 xmlReader.setErrorHandler(new SuppressionErrorHandler()); -183 xmlReader.setContentHandler(handler); -184 -185 final Reader reader = new InputStreamReader(inputStream, "UTF-8"); -186 final InputSource in = new InputSource(reader); -187 -188 xmlReader.parse(in); -189 -190 return handler.getSuppressionRules(); -191 } catch (ParserConfigurationException ex) { -192 LOGGER.debug("", ex); -193 throw new SuppressionParseException(ex); -194 } catch (SAXException ex) { -195 LOGGER.debug("", ex); -196 throw new SuppressionParseException(ex); -197 } catch (FileNotFoundException ex) { -198 LOGGER.debug("", ex); -199 throw new SuppressionParseException(ex); -200 } catch (IOException ex) { -201 LOGGER.debug("", ex); -202 throw new SuppressionParseException(ex); -203 } -204 } -205 } +124 InputStream schemaStream = null; +125 try { +126 schemaStream = this.getClass().getClassLoader().getResourceAsStream(SUPPRESSION_SCHEMA); +127 final SuppressionHandler handler = new SuppressionHandler(); +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 }
    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 19d4350d7..5c3fa0c2d 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.2 Reference Package org.owasp.dependencycheck.xml.suppression + Dependency-Check Core 1.4.3 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 cb5896a36..e9a452f38 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.2 Reference Package org.owasp.dependencycheck.xml.suppression + Dependency-Check Core 1.4.3 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 83937d241..6199e9f5a 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.2 Reference + Dependency-Check Core 1.4.3 Reference diff --git a/dependency-check-core/xref/overview-summary.html b/dependency-check-core/xref/overview-summary.html index f8b6c49f5..7ae7797b0 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.2 Reference + Dependency-Check Core 1.4.3 Reference @@ -24,7 +24,7 @@ -

    Dependency-Check Core 1.4.2 Reference

    +

    Dependency-Check Core 1.4.3 Reference

    diff --git a/dependency-check-gradle/configuration-purge.html b/dependency-check-gradle/configuration-purge.html index be17941da..81f99e375 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 @@
  • Tasks
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/dependency-check-gradle/configuration-update.html b/dependency-check-gradle/configuration-update.html index 1aefa7664..0ea2019d0 100644 --- a/dependency-check-gradle/configuration-update.html +++ b/dependency-check-gradle/configuration-update.html @@ -1,13 +1,13 @@ - + dependency-check – Tasks @@ -59,9 +59,9 @@
  • Tasks
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/dependency-check-gradle/configuration.html b/dependency-check-gradle/configuration.html index a8f275f90..f082b6399 100644 --- a/dependency-check-gradle/configuration.html +++ b/dependency-check-gradle/configuration.html @@ -1,13 +1,13 @@ - + dependency-check – Tasks @@ -59,9 +59,9 @@
  • Tasks
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • @@ -335,6 +335,24 @@ + + + + + + + + + + + + + + + + + +
     
    skipConfigurations A list of configurations that will be skipped. This is mutually exclusive with the scanConfigurations property. [] which means no configuration is skipped.
    scanConfigurations A list of configurations that will be scanned, all other configurations are skipped. This is mutually exclusive with the skipConfigurations property. [] which implicitly means all configurations get scanned.
    diff --git a/dependency-check-gradle/index.html b/dependency-check-gradle/index.html index de4d955a6..24b3132b3 100644 --- a/dependency-check-gradle/index.html +++ b/dependency-check-gradle/index.html @@ -1,13 +1,13 @@ - + dependency-check – Usage @@ -59,9 +59,9 @@
  • Usage
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • @@ -236,7 +236,7 @@ mavenCentral() } dependencies { - classpath 'org.owasp:dependency-check-gradle:1.4.2' + classpath 'org.owasp:dependency-check-gradle:1.4.3' } } diff --git a/dependency-check-jenkins/index.html b/dependency-check-jenkins/index.html index 870bb6b8a..22b09f5bb 100644 --- a/dependency-check-jenkins/index.html +++ b/dependency-check-jenkins/index.html @@ -1,13 +1,13 @@ - + dependency-check – Dependency-Check Jenkins Plugin @@ -59,9 +59,9 @@
  • Dependency-Check Jenkins Plugin
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/dependency-check-maven/aggregate-mojo.html b/dependency-check-maven/aggregate-mojo.html index b0cb9aad3..597dc3771 100644 --- a/dependency-check-maven/aggregate-mojo.html +++ b/dependency-check-maven/aggregate-mojo.html @@ -1,13 +1,13 @@ - + dependency-check-maven – dependency-check:aggregate @@ -52,7 +52,7 @@ @@ -155,7 +155,7 @@

    Full name:

    -

    org.owasp:dependency-check-maven:1.4.2:aggregate

    +

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

    Description:

    @@ -169,6 +169,8 @@ vulnerabilities.
  • Requires a Maven project to be executed.
  • +
  • Executes as an aggregator plugin.
  • +
  • Requires dependency resolution of artifacts in scope: compile+runtime.
  • Binds by default to the lifecycle phase: verify.
  • diff --git a/dependency-check-maven/apidocs/allclasses-frame.html b/dependency-check-maven/apidocs/allclasses-frame.html index 111968e9d..c141604ec 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.2 API) - +All Classes (Dependency-Check Maven Plugin 1.4.3 API) + diff --git a/dependency-check-maven/apidocs/allclasses-noframe.html b/dependency-check-maven/apidocs/allclasses-noframe.html index fbdfe9441..c76cbada7 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.2 API) - +All Classes (Dependency-Check Maven Plugin 1.4.3 API) + diff --git a/dependency-check-maven/apidocs/constant-values.html b/dependency-check-maven/apidocs/constant-values.html index e4664896b..8139b828c 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.2 API) - +Constant Field Values (Dependency-Check Maven Plugin 1.4.3 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 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -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 4a145632f..3abada450 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.2 API) - +org.owasp.dependencycheck.maven (Dependency-Check Maven Plugin 1.4.3 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-maven/apidocs/org/owasp/dependencycheck/maven/slf4j/package-summary.html b/dependency-check-maven/apidocs/org/owasp/dependencycheck/maven/slf4j/package-summary.html index 75e6ea027..b56b07e9d 100644 --- a/dependency-check-maven/apidocs/org/owasp/dependencycheck/maven/slf4j/package-summary.html +++ b/dependency-check-maven/apidocs/org/owasp/dependencycheck/maven/slf4j/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.maven.slf4j (Dependency-Check Maven Plugin 1.4.2 API) - +org.owasp.dependencycheck.maven.slf4j (Dependency-Check Maven Plugin 1.4.3 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-maven/apidocs/org/slf4j/impl/package-summary.html b/dependency-check-maven/apidocs/org/slf4j/impl/package-summary.html index 06be805c9..a55b32bce 100644 --- a/dependency-check-maven/apidocs/org/slf4j/impl/package-summary.html +++ b/dependency-check-maven/apidocs/org/slf4j/impl/package-summary.html @@ -2,10 +2,10 @@ - + -org.slf4j.impl (Dependency-Check Maven Plugin 1.4.2 API) - +org.slf4j.impl (Dependency-Check Maven Plugin 1.4.3 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-maven/apidocs/overview-summary.html b/dependency-check-maven/apidocs/overview-summary.html index 87817aba6..1af76ac67 100644 --- a/dependency-check-maven/apidocs/overview-summary.html +++ b/dependency-check-maven/apidocs/overview-summary.html @@ -2,10 +2,10 @@ - + -Overview (Dependency-Check Maven Plugin 1.4.2 API) - +Overview (Dependency-Check Maven Plugin 1.4.3 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ - + diff --git a/dependency-check-maven/cobertura/frame-summary-org.owasp.dependencycheck.maven.slf4j.html b/dependency-check-maven/cobertura/frame-summary-org.owasp.dependencycheck.maven.slf4j.html index 954ee71f1..ba0486aff 100644 --- a/dependency-check-maven/cobertura/frame-summary-org.owasp.dependencycheck.maven.slf4j.html +++ b/dependency-check-maven/cobertura/frame-summary-org.owasp.dependencycheck.maven.slf4j.html @@ -39,6 +39,6 @@ var classTable = new SortableTable(document.getElementById("classResults"), ["String", "Percentage", "Percentage", "FormattedNumber"]); classTable.sort(0); - + diff --git a/dependency-check-maven/cobertura/frame-summary-org.slf4j.impl.html b/dependency-check-maven/cobertura/frame-summary-org.slf4j.impl.html index ef033105b..3b902b821 100644 --- a/dependency-check-maven/cobertura/frame-summary-org.slf4j.impl.html +++ b/dependency-check-maven/cobertura/frame-summary-org.slf4j.impl.html @@ -37,6 +37,6 @@ var classTable = new SortableTable(document.getElementById("classResults"), ["String", "Percentage", "Percentage", "FormattedNumber"]); classTable.sort(0); - + diff --git a/dependency-check-maven/cobertura/frame-summary.html b/dependency-check-maven/cobertura/frame-summary.html index 692ef4015..f4cee4298 100644 --- a/dependency-check-maven/cobertura/frame-summary.html +++ b/dependency-check-maven/cobertura/frame-summary.html @@ -16,8 +16,8 @@ - - + + @@ -27,6 +27,6 @@ var packageTable = new SortableTable(document.getElementById("packageResults"), ["String", "Number", "Percentage", "Percentage", "FormattedNumber"]); packageTable.sort(0); - + 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 82723f7d3..65aa9a848 100644 --- a/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.AggregateMojo.html +++ b/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.AggregateMojo.html @@ -12,7 +12,7 @@
     
    Package # Classes Line Coverage Branch Coverage Complexity
    All Packages10
    2%
    25/958
    0%
    3/542
    3.992
    org.owasp.dependencycheck.maven7
    0%
    0/803
    0%
    0/482
    4.975
    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
    - +
    Classes in this File Line Coverage Branch Coverage Complexity
    AggregateMojo
    0%
    0/160
    0%
    0/114
    8
    AggregateMojo
    0%
    0/118
    0%
    0/88
    8.857
     
    @@ -60,567 +60,423 @@
     21  
     import java.io.IOException;
     22  
     import java.util.ArrayList;
     23  
     import java.util.Collections;
     24  
     23  
     import java.util.HashSet;
     25  
     import java.util.List;
     26  
     24  
     import java.util.Locale;
     27  
     25  
     import java.util.Set;
     28  
     26  
     import org.apache.maven.plugin.MojoExecutionException;
     29  
     27  
     import org.apache.maven.plugin.MojoFailureException;
     30  
     28  
     import org.apache.maven.plugins.annotations.LifecyclePhase;
     31  
     29  
     import org.apache.maven.plugins.annotations.Mojo;
     32  
     30  
     import org.apache.maven.plugins.annotations.Parameter;
     33  
     31  
     import org.apache.maven.plugins.annotations.ResolutionScope;
     34  
     32  
     import org.apache.maven.project.MavenProject;
     35  
     import org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer;
     36  
     import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
     37  
     33  
     import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
     38  
     import org.owasp.dependencycheck.dependency.Dependency;
     39  
     34  
     import org.owasp.dependencycheck.exception.ExceptionCollection;
     40  
     35  
     import org.owasp.dependencycheck.exception.ReportException;
     41  
     36  
     import org.owasp.dependencycheck.utils.Settings;
     42  
     37  
     
     43  
     38  
     /**
     44  
     39  
      * Maven Plugin that checks project dependencies and the dependencies of all
     45  
     40  
      * child modules to see if they have any known published vulnerabilities.
     46  
     41  
      *
     47  
     42  
      * @author Jeremy Long
     48  
     43  
      */
     49  
     44  
     @Mojo(
     50  
     45  
             name = "aggregate",
     51  
     46  
             defaultPhase = LifecyclePhase.VERIFY,
     52  
             /*aggregator = true,*/
     53  
     47  
             aggregator = true,
     48  
             threadSafe = false,
     54  
     49  
             requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME,
     55  
     50  
             requiresOnline = true
     56  
     51  
     )
     57  0
     public class AggregateMojo extends BaseDependencyCheckMojo {
     58  
     52  0
     public class AggregateMojo extends BaseDependencyCheckMojo {
     53  
     
     59  
     54  
         /**
     60  
          * The key to store aggregate exception in the root Maven execution context.
     61  
          */
     62  
         private static final String AGGREGATE_EXCEPTIONS = "AggregateExceptions";
     63  
     
     64  
         /**
     65  
     55  
          * Executes the aggregate dependency-check goal. This runs dependency-check
     66  
     56  
          * and generates the subsequent reports.
     67  
     57  
          *
     68  
     58  
          * @throws MojoExecutionException thrown if there is ane exception running
     69  
     59  
          * the mojo
     70  
     60  
          * @throws MojoFailureException thrown if dependency-check is configured to
     71  
     61  
          * fail the build
     72  
     62  
          */
     73  
     63  
         @Override
     74  
     64  
         public void runCheck() throws MojoExecutionException, MojoFailureException {
     75  0
             final MavenEngine engine = generateDataFile();
     76  0
             if (engine == null) {
     77  0
                 return;
     78  
     65  0
             final MavenEngine engine = loadEngine();
     66  0
             if (engine == null) {
     67  0
                 return;
     68  
             }
     79  
     69  
     
     80  0
             if (getProject() == getLastProject()) {
     70  0
             ExceptionCollection exCol = scanArtifacts(getProject(), engine);
     71  
     
     72  0
             for (MavenProject childProject : getDescendants(this.getProject())) {
     73  0
                 final ExceptionCollection ex = scanArtifacts(childProject, engine);
     74  0
                 if (ex != null) {
     75  0
                     if (exCol == null) {
     76  0
                         exCol = ex;
     77  
                     }
     78  0
                     exCol.getExceptions().addAll(ex.getExceptions());
     79  0
                     if (ex.isFatal()) {
     80  0
                         exCol.setFatal(true);
     81  
                 //ensure that the .ser file was created for each.
     82  0
                 for (MavenProject current : getReactorProjects()) {
     83  0
                     final File dataFile = getDataFile(current);
     84  0
                     if (dataFile == null && !skipProject(current)) { //dc was never run on this project. write the ser to the target.
     85  0
                         getLog().error(String.format("Module '%s' did not execute dependency-check; an attempt will be made to perform "
     86  0
                                 + "the check but dependencies may be missed resulting in false negatives.", current.getName()));
     87  0
                         generateDataFile(engine, current);
     88  
                     }
     89  0
                 }
     90  0
                 for (MavenProject current : getReactorProjects()) {
     91  0
                     List<Dependency> dependencies = readDataFile(current);
     92  0
                     if (dependencies == null) {
     93  0
                         dependencies = new ArrayList<Dependency>();
     94  
                     }
     95  0
                     final Set<MavenProject> childProjects = getDescendants(current);
     96  0
                     for (MavenProject reportOn : childProjects) {
     97  0
                         final List<Dependency> childDeps = readDataFile(reportOn);
     98  0
                         if (childDeps != null && !childDeps.isEmpty()) {
     99  0
                             if (getLog().isDebugEnabled()) {
     100  0
                                 getLog().debug(String.format("Adding %d dependencies from %s", childDeps.size(), reportOn.getName()));
     101  
                             }
     102  0
                             dependencies.addAll(childDeps);
     103  0
                         } else if (getLog().isDebugEnabled()) {
     104  0
                             getLog().debug(String.format("No dependencies read for %s", reportOn.getName()));
     105  
                         }
     106  0
                     }
     107  0
                     engine.getDependencies().clear();
     108  0
                     engine.getDependencies().addAll(dependencies);
     109  0
                     final DependencyBundlingAnalyzer bundler = new DependencyBundlingAnalyzer();
     110  
                     try {
     111  0
                         if (getLog().isDebugEnabled()) {
     112  0
                             getLog().debug(String.format("Dependency count pre-bundler: %s", engine.getDependencies().size()));
     113  
                         }
     114  0
                         bundler.analyze(null, engine);
     115  0
                         if (getLog().isDebugEnabled()) {
     116  0
                             getLog().debug(String.format("Dependency count post-bundler: %s", engine.getDependencies().size()));
     117  
                         }
     118  0
                     } catch (AnalysisException ex) {
     119  0
                         getLog().warn("An error occurred grouping the dependencies; duplicate entries may exist in the report", ex);
     120  0
                         getLog().debug("Bundling Exception", ex);
     121  0
                     }
     122  
     
     123  0
                     File outputDir = getCorrectOutputDirectory(current);
     124  0
                     if (outputDir == null) {
     125  
                         //in some regards we shouldn't be writting this, but we are anyway.
     126  
                         //we shouldn't write this because nothing is configured to generate this report.
     127  0
                         outputDir = new File(current.getBuild().getDirectory());
     128  
                     }
     129  
                     try {
     130  0
                         writeReports(engine, current, outputDir);
     131  0
                     } catch (ReportException ex) {
     132  0
                         ExceptionCollection exCol = (ExceptionCollection) engine.getExecutionRoot().getContextValue(AGGREGATE_EXCEPTIONS);
     133  0
                         if (exCol == null) {
     134  0
                             exCol = new ExceptionCollection("Error writing aggregate report", ex);
     135  
                         } else {
     136  0
                             exCol.addException(ex);
     137  
                         }
     138  0
                         if (this.isFailOnError()) {
     139  0
                             throw new MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol);
     140  
                         } else {
     141  0
                             getLog().debug("One or more exceptions occured during dependency-check analysis", exCol);
     142  
                         }
     143  0
                     }
     144  0
                 }
     145  
             }
     146  0
             engine.cleanup();
     147  0
             Settings.cleanup();
     148  0
         }
     149  
     
     150  
         /**
     151  
          * Gets the last project in the reactor - taking into account skipped
     152  
          * projects.
     153  
          *
     154  
          * @return the last project in the reactor
     155  
          */
     156  
         private MavenProject getLastProject() {
     157  0
             for (int x = getReactorProjects().size() - 1; x >= 0; x--) {
     158  0
                 final MavenProject p = getReactorProjects().get(x);
     159  0
                 if (!skipProject(p)) {
     160  0
                     return p;
     161  
     82  
                 }
     162  
             }
     163  0
             return null;
     164  
         }
     165  
     83  0
             }
     84  
     
     166  
     85  
             try {
     86  0
                 engine.analyzeDependencies();
     87  0
             } catch (ExceptionCollection ex) {
     88  0
                 if (exCol == null) {
     89  0
                     exCol = ex;
     90  0
                 } else if (ex.isFatal()) {
     91  0
                     exCol.setFatal(true);
     92  0
                     exCol.getExceptions().addAll(ex.getExceptions());
     93  
                 }
     94  0
                 if (exCol.isFatal()) {
     95  0
                     final String msg = String.format("Fatal exception(s) analyzing %s", getProject().getName());
     96  0
                     if (this.isFailOnError()) {
     97  0
                         throw new MojoExecutionException(msg, exCol);
     98  
                     }
     99  0
                     getLog().error(msg);
     100  0
                     if (getLog().isDebugEnabled()) {
     101  0
                         getLog().debug(exCol);
     102  
                     }
     103  0
                     return;
     104  
                 } else {
     105  0
                     final String msg = String.format("Exception(s) analyzing %s", getProject().getName());
     106  0
                     if (getLog().isDebugEnabled()) {
     107  0
                         getLog().debug(msg, exCol);
     108  
                     }
     109  
                 }
     110  0
             }
     111  0
             File outputDir = getCorrectOutputDirectory(this.getProject());
     112  0
             if (outputDir == null) {
     113  
                 //in some regards we shouldn't be writting this, but we are anyway.
     114  
                 //we shouldn't write this because nothing is configured to generate this report.
     115  0
                 outputDir = new File(this.getProject().getBuild().getDirectory());
     116  
             }
     117  
             try {
     118  0
                 writeReports(engine, this.getProject(), outputDir);
     119  0
             } catch (ReportException ex) {
     120  0
                 if (exCol == null) {
     121  0
                     exCol = new ExceptionCollection("Error writing aggregate report", ex);
     122  
                 } else {
     123  0
                     exCol.addException(ex);
     124  
                 }
     125  0
                 if (this.isFailOnError()) {
     126  0
                     throw new MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol);
     127  
                 } else {
     128  0
                     getLog().debug("One or more exceptions occured during dependency-check analysis", exCol);
     129  
                 }
     130  0
             }
     131  0
             showSummary(this.getProject(), engine.getDependencies());
     132  0
             checkForFailure(engine.getDependencies());
     133  0
             engine.cleanup();
     134  0
             Settings.cleanup();
     135  0
         }
     136  
     
     137  
         /**
     167  
          * Tests if the project is being skipped in the Maven site report.
     168  
     138  
          * Returns a set containing all the descendant projects of the given
     139  
          * project.
     140  
          *
     169  
          * @param project a project in the reactor
     170  
          * @return true if the project is skipped; otherwise false
     171  
     141  
          * @param project the project for which all descendants will be returned
     142  
          * @return the set of descendant projects
     143  
          */
     172  
         private boolean skipProject(MavenProject project) {
     173  0
             final String skip = (String) project.getProperties().get("maven.site.skip");
     174  0
             return "true".equalsIgnoreCase(skip) && isGeneratingSite();
     175  
         }
     144  
         protected Set<MavenProject> getDescendants(MavenProject project) {
     145  0
             if (project == null) {
     146  0
                 return Collections.emptySet();
     147  
             }
     148  0
             final Set<MavenProject> descendants = new HashSet<MavenProject>();
     149  0
             int size = 0;
     150  0
             if (getLog().isDebugEnabled()) {
     151  0
                 getLog().debug(String.format("Collecting descendants of %s", project.getName()));
     152  
             }
     153  0
             for (String m : project.getModules()) {
     154  0
                 for (MavenProject mod : getReactorProjects()) {
     155  
                     try {
     156  0
                         File mpp = new File(project.getBasedir(), m);
     157  0
                         mpp = mpp.getCanonicalFile();
     158  0
                         if (mpp.compareTo(mod.getBasedir()) == 0 && descendants.add(mod)
     159  0
                                 && getLog().isDebugEnabled()) {
     160  0
                             getLog().debug(String.format("Decendent module %s added", mod.getName()));
     161  
     
     162  
                         }
     163  0
                     } catch (IOException ex) {
     164  0
                         if (getLog().isDebugEnabled()) {
     165  0
                             getLog().debug("Unable to determine module path", ex);
     166  
                         }
     167  0
                     }
     168  0
                 }
     169  0
             }
     170  
             do {
     171  0
                 size = descendants.size();
     172  0
                 for (MavenProject p : getReactorProjects()) {
     173  0
                     if (project.equals(p.getParent()) || descendants.contains(p.getParent())) {
     174  0
                         if (descendants.add(p) && getLog().isDebugEnabled()) {
     175  0
                             getLog().debug(String.format("Decendent %s added", p.getName()));
     176  
     
     177  
         /**
     178  
          * Returns a set containing all the descendant projects of the given
     179  
          * project.
     180  
          *
     181  
          * @param project the project for which all descendants will be returned
     182  
          * @return the set of descendant projects
                         }
     178  0
                         for (MavenProject modTest : getReactorProjects()) {
     179  0
                             if (p.getModules() != null && p.getModules().contains(modTest.getName())
     180  0
                                     && descendants.add(modTest)
     181  0
                                     && getLog().isDebugEnabled()) {
     182  0
                                 getLog().debug(String.format("Decendent %s added", modTest.getName()));
     183  
          */
     184  
         protected Set<MavenProject> getDescendants(MavenProject project) {
     185  0
             if (project == null) {
     186  0
                 return Collections.emptySet();
     187  
             }
     188  0
             final Set<MavenProject> descendants = new HashSet<MavenProject>();
     189  0
             int size = 0;
     190  0
             if (getLog().isDebugEnabled()) {
     191  0
                 getLog().debug(String.format("Collecting descendants of %s", project.getName()));
     192  
             }
     193  0
             for (String m : project.getModules()) {
     194  0
                 for (MavenProject mod : getReactorProjects()) {
     195  
                     try {
     196  0
                         File mpp = new File(project.getBasedir(), m);
     197  0
                         mpp = mpp.getCanonicalFile();
     198  0
                         if (mpp.compareTo(mod.getBasedir()) == 0 && descendants.add(mod)
     199  0
                                 && getLog().isDebugEnabled()) {
     200  0
                             getLog().debug(String.format("Decendent module %s added", mod.getName()));
     201  
     
     202  
                         }
     203  0
                     } catch (IOException ex) {
     204  0
                         if (getLog().isDebugEnabled()) {
     205  0
                             getLog().debug("Unable to determine module path", ex);
     206  
                         }
     207  0
                     }
     208  0
                 }
     209  0
             }
     210  
             do {
     211  0
                 size = descendants.size();
     212  0
                 for (MavenProject p : getReactorProjects()) {
     213  0
                     if (project.equals(p.getParent()) || descendants.contains(p.getParent())) {
     214  0
                         if (descendants.add(p) && getLog().isDebugEnabled()) {
     215  0
                             getLog().debug(String.format("Decendent %s added", p.getName()));
     216  
     
     217  
                         }
     218  0
                         for (MavenProject modTest : getReactorProjects()) {
     219  0
                             if (p.getModules() != null && p.getModules().contains(modTest.getName())
     220  0
                                     && descendants.add(modTest)
     221  0
                                     && getLog().isDebugEnabled()) {
     222  0
                                 getLog().debug(String.format("Decendent %s added", modTest.getName()));
     223  
                             }
     224  0
                         }
     225  
     184  0
                         }
     185  
                     }
     226  0
                     final Set<MavenProject> addedDescendants = new HashSet<MavenProject>();
     227  0
                     for (MavenProject dec : descendants) {
     228  0
                         for (String mod : dec.getModules()) {
     229  
     186  0
                     final Set<MavenProject> addedDescendants = new HashSet<MavenProject>();
     187  0
                     for (MavenProject dec : descendants) {
     188  0
                         for (String mod : dec.getModules()) {
     189  
                             try {
     230  0
                                 File mpp = new File(dec.getBasedir(), mod);
     231  0
                                 mpp = mpp.getCanonicalFile();
     232  0
                                 if (mpp.compareTo(p.getBasedir()) == 0) {
     233  0
                                     addedDescendants.add(p);
     234  
     190  0
                                 File mpp = new File(dec.getBasedir(), mod);
     191  0
                                 mpp = mpp.getCanonicalFile();
     192  0
                                 if (mpp.compareTo(p.getBasedir()) == 0) {
     193  0
                                     addedDescendants.add(p);
     194  
                                 }
     235  0
                             } catch (IOException ex) {
     236  0
                                 if (getLog().isDebugEnabled()) {
     237  0
                                     getLog().debug("Unable to determine module path", ex);
     238  
     195  0
                             } catch (IOException ex) {
     196  0
                                 if (getLog().isDebugEnabled()) {
     197  0
                                     getLog().debug("Unable to determine module path", ex);
     198  
                                 }
     239  0
                             }
     240  0
                         }
     241  0
                     }
     242  0
                     for (MavenProject addedDescendant : addedDescendants) {
     243  0
                         if (descendants.add(addedDescendant) && getLog().isDebugEnabled()) {
     244  0
                             getLog().debug(String.format("Decendent module %s added", addedDescendant.getName()));
     245  
     199  0
                             }
     200  0
                         }
     201  0
                     }
     202  0
                     for (MavenProject addedDescendant : addedDescendants) {
     203  0
                         if (descendants.add(addedDescendant) && getLog().isDebugEnabled()) {
     204  0
                             getLog().debug(String.format("Decendent module %s added", addedDescendant.getName()));
     205  
                         }
     246  0
                     }
     247  0
                 }
     248  0
             } while (size != 0 && size != descendants.size());
     249  0
             if (getLog().isDebugEnabled()) {
     250  0
                 getLog().debug(String.format("%s has %d children", project, descendants.size()));
     251  
     206  0
                     }
     207  0
                 }
     208  0
             } while (size != 0 && size != descendants.size());
     209  0
             if (getLog().isDebugEnabled()) {
     210  0
                 getLog().debug(String.format("%s has %d children", project, descendants.size()));
     211  
             }
     252  0
             return descendants;
     253  
     212  0
             return descendants;
     213  
         }
     254  
     214  
     
     255  
     215  
         /**
     256  
     216  
          * Test if the project has pom packaging
     257  
     217  
          *
     258  
     218  
          * @param mavenProject Project to test
     259  
     219  
          * @return <code>true</code> if it has a pom packaging; otherwise
     260  
     220  
          * <code>false</code>
     261  
     221  
          */
     262  
     222  
         protected boolean isMultiModule(MavenProject mavenProject) {
     263  0
             return "pom".equals(mavenProject.getPackaging());
     264  
     223  0
             return "pom".equals(mavenProject.getPackaging());
     224  
         }
     265  
     225  
     
     266  
     226  
         /**
     267  
          * Initializes the engine, runs a scan, and writes the serialized
     268  
          * dependencies to disk.
     269  
     227  
          * Initializes the engine.
     228  
          *
     270  
     229  
          * @return the MavenEngine used to execute dependency-check
     271  
     230  
          * @throws MojoExecutionException thrown if there is an exception running
     272  
          * the mojo
     273  
     231  
          * the Mojo
     232  
          * @throws MojoFailureException thrown if dependency-check is configured to
     274  
     233  
          * fail the build if severe CVEs are identified.
     275  
     234  
          */
     276  
         protected MavenEngine generateDataFile() throws MojoExecutionException, MojoFailureException {
     277  0
             MavenEngine engine = null;
     278  
     235  
         protected MavenEngine loadEngine() throws MojoExecutionException, MojoFailureException {
     236  0
             MavenEngine engine = null;
     237  
             try {
     279  0
                 engine = initializeEngine();
     280  0
             } catch (DatabaseException ex) {
     281  0
                 if (getLog().isDebugEnabled()) {
     282  0
                     getLog().debug("Database connection error", ex);
     283  
     238  0
                 engine = initializeEngine();
     239  0
             } catch (DatabaseException ex) {
     240  0
                 if (getLog().isDebugEnabled()) {
     241  0
                     getLog().debug("Database connection error", ex);
     242  
                 }
     284  0
                 final String msg = "An exception occured connecting to the local database. Please see the log file for more details.";
     285  0
                 if (this.isFailOnError()) {
     286  0
                     throw new MojoExecutionException(msg, ex);
     287  
     243  0
                 final String msg = "An exception occured 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  
                 }
     288  0
                 getLog().error(msg, ex);
     289  0
                 return null;
     290  0
             }
     291  0
             return generateDataFile(engine, getProject());
     292  
     247  0
                 getLog().error(msg, ex);
     248  0
             }
     249  0
             return engine;
     250  
         }
     293  
     251  
     
     294  
         /**
     295  
          * Runs dependency-check's MavenEngine and writes the serialized
     296  
          * dependencies to disk.
     297  
          *
     298  
          * @param engine the MavenEngine to use when scanning.
     299  
          * @param project the project to scan and generate the data file for
     300  
          * @return the MavenEngine used to execute dependency-check
     301  
          * @throws MojoExecutionException thrown if there is an exception running
     302  
          * the mojo
     303  
          * @throws MojoFailureException thrown if dependency-check is configured to
     304  
          * fail the build if severe CVEs are identified.
     305  
          */
     306  
         protected MavenEngine generateDataFile(MavenEngine engine, MavenProject project) throws MojoExecutionException, MojoFailureException {
     307  0
             if (getLog().isDebugEnabled()) {
     308  0
                 getLog().debug(String.format("Begin Scanning: %s", project.getName()));
     309  
             }
     310  0
             engine.getDependencies().clear();
     311  0
             engine.resetFileTypeAnalyzers();
     312  0
             scanArtifacts(project, engine);
     313  
             try {
     314  0
                 engine.analyzeDependencies();
     315  0
             } catch (ExceptionCollection ex) {
     316  0
                 ExceptionCollection col = (ExceptionCollection) engine.getExecutionRoot().getContextValue(AGGREGATE_EXCEPTIONS);
     317  0
                 if (col == null) {
     318  0
                     col = ex;
     319  0
                 } else if (ex.isFatal()) {
     320  0
                     col.setFatal(true);
     321  0
                     col.getExceptions().addAll(ex.getExceptions());
     322  
                 }
     323  0
                 if (col.isFatal()) {
     324  0
                     final String msg = String.format("Fatal exception(s) analyzing %s", project.getName());
     325  0
                     if (this.isFailOnError()) {
     326  0
                         throw new MojoExecutionException(msg, ex);
     327  
                     }
     328  0
                     getLog().error(msg, col);
     329  0
                     return null;
     330  
                 } else {
     331  0
                     final String msg = String.format("Exception(s) analyzing %s", project.getName());
     332  0
                     if (getLog().isDebugEnabled()) {
     333  0
                         getLog().debug(msg, ex);
     334  
                     }
     335  0
                     engine.getExecutionRoot().setContextValue(AGGREGATE_EXCEPTIONS, col);
     336  
                 }
     337  0
             }
     338  0
             final File target = new File(project.getBuild().getDirectory());
     339  0
             writeDataFile(project, target, engine.getDependencies());
     340  0
             showSummary(project, engine.getDependencies());
     341  0
             checkForFailure(engine.getDependencies());
     342  0
             return engine;
     343  
         }
     344  
     
     345  
     252  
         @Override
     346  
     253  
         public boolean canGenerateReport() {
     347  0
             return true; //aggregate always returns true for now - we can look at a more complicated/acurate solution later
     348  
     254  0
             return true; //aggregate always returns true for now - we can look at a more complicated/acurate solution later
     255  
         }
     349  
     256  
     
     350  
     257  
         /**
     351  
     258  
          * The name of the report in the site.
     352  
     259  
          */
     353  0
         @SuppressWarnings("CanBeFinal")
     354  
     260  0
         @SuppressWarnings("CanBeFinal")
     261  
         @Parameter(property = "name", defaultValue = "dependency-check:aggregate", required = true)
     355  
     262  
         private String name = "dependency-check:aggregate";
     356  
     263  
     
     357  
     264  
         /**
     358  
     265  
          * Returns the report name.
     359  
     266  
          *
     360  
     267  
          * @param locale the location
     361  
     268  
          * @return the report name
     362  
     269  
          */
     363  
     270  
         @Override
     364  
     271  
         public String getName(Locale locale) {
     365  0
             return name;
     366  
     272  0
             return name;
     273  
         }
     367  
     274  
     
     368  
     275  
         /**
     369  
     276  
          * Gets the description of the Dependency-Check report to be displayed in
     370  
     277  
          * the Maven Generated Reports page.
     371  
     278  
          *
     372  
     279  
          * @param locale The Locale to get the description for
     373  
     280  
          * @return the description
     374  
     281  
          */
     375  
     282  
         @Override
     376  
     283  
         public String getDescription(Locale locale) {
     377  0
             return "Generates an aggregate report of all child Maven projects providing details on any "
     378  
     284  0
             return "Generates an aggregate report of all child Maven projects providing details on any "
     285  
                     + "published vulnerabilities within project dependencies. This report is a best "
     379  
     286  
                     + "effort and may contain false positives and false negatives.";
     380  
     287  
         }
     381  
     288  
     }
    - + 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 692d47714..c19cf306b 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/312
    0%
    0/158
    4.438
    BaseDependencyCheckMojo
    0%
    0/349
    0%
    0/174
    4.667
     
    @@ -76,7 +76,7 @@
     29  
     import java.util.Locale;
     30  
     import org.apache.maven.artifact.Artifact;
     import org.eclipse.aether.artifact.Artifact;
     31  
     import org.apache.maven.doxia.sink.Sink;
     32  
     41  
     import org.apache.maven.settings.Server;
     42  
     import org.owasp.dependencycheck.data.nexus.MavenArtifact;
     import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
     43  
     import org.owasp.dependencycheck.data.nvdcve.CveDB;
     import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException;
     44  
     import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
     import org.apache.maven.shared.dependency.graph.DependencyNode;
     45  
     import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
     import org.eclipse.aether.RepositorySystem;
     46  
     import org.owasp.dependencycheck.dependency.Confidence;
     import org.eclipse.aether.RepositorySystemSession;
     47  
     import org.owasp.dependencycheck.dependency.Dependency;
     import org.eclipse.aether.artifact.DefaultArtifact;
     48  
     import org.owasp.dependencycheck.dependency.Identifier;
     import org.eclipse.aether.repository.RemoteRepository;
     49  
     import org.owasp.dependencycheck.dependency.Vulnerability;
     import org.eclipse.aether.resolution.ArtifactRequest;
     50  
     import org.owasp.dependencycheck.exception.ReportException;
     import org.eclipse.aether.resolution.ArtifactResolutionException;
     51  
     import org.owasp.dependencycheck.reporting.ReportGenerator;
     import org.eclipse.aether.resolution.ArtifactResult;
     52  
     import org.owasp.dependencycheck.utils.ExpectedOjectInputStream;
     import org.owasp.dependencycheck.data.nexus.MavenArtifact;
     53  
     import org.owasp.dependencycheck.utils.Settings;
     import org.owasp.dependencycheck.data.nvdcve.CveDB;
     54  
     import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher;
     import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
     55  
     import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
     import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
     56  
     import org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException;
     import org.owasp.dependencycheck.dependency.Confidence;
     57  
     
     import org.owasp.dependencycheck.dependency.Dependency;
     58  
     /**
     import org.owasp.dependencycheck.dependency.Identifier;
     59  
      *
     import org.owasp.dependencycheck.dependency.Vulnerability;
     60  
      * @author Jeremy Long
     import org.owasp.dependencycheck.exception.ExceptionCollection;
     61  
      */
     62  0
     public abstract class BaseDependencyCheckMojo extends AbstractMojo implements MavenReport {
     import org.owasp.dependencycheck.exception.ReportException;
     62  
     import org.owasp.dependencycheck.reporting.ReportGenerator;
     63  
     
     import org.owasp.dependencycheck.utils.ExpectedOjectInputStream;
     64  
         //<editor-fold defaultstate="collapsed" desc="Private fields">
     import org.owasp.dependencycheck.utils.Settings;
     65  
         /**
     import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher;
     66  
          * The properties file location.
     import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
     67  
          */
     import org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException;
     68  
         private static final String PROPERTIES_FILE = "mojo.properties";
     
     69  
         /**
     /**
     70  
          * System specific new line character.
      *
     71  
          */
     72  0
         private static final String NEW_LINE = System.getProperty("line.separator", "\n").intern();
     73  
         //</editor-fold>
      * @author Jeremy Long
     72  
      */
     73  0
     public abstract class BaseDependencyCheckMojo extends AbstractMojo implements MavenReport {
     74  
         // <editor-fold defaultstate="collapsed" desc="Maven bound parameters and components">
     
     75  
         /**
         //<editor-fold defaultstate="collapsed" desc="Private fields">
     76  
          * Sets whether or not the external report format should be used.
         /**
     77  
          */
          * The properties file location.
     78  
         @Parameter(property = "metaFileName", defaultValue = "dependency-check.ser", required = true)
          */
     79  
         private String dataFileName;
         private static final String PROPERTIES_FILE = "mojo.properties";
     80  
         /**
     81  
          * Sets whether or not the external report format should be used.
          * System specific new line character.
     82  
          */
     83  
         @Parameter(property = "failOnError", defaultValue = "true", required = true)
     83  0
         private static final String NEW_LINE = System.getProperty("line.separator", "\n").intern();
     84  
         private boolean failOnError;
         //</editor-fold>
     85  
     
         // <editor-fold defaultstate="collapsed" desc="Maven bound parameters and components">
     86  
         /**
     87  
          * Returns if the mojo should fail the build if an exception occurs.
          * Sets whether or not the external report format should be used.
     88  
          *
          */
     89  
          * @return whether or not the mojo should fail the build
         @Parameter(property = "metaFileName", defaultValue = "dependency-check.ser", required = true)
     90  
          */
         private String dataFileName;
     91  
         protected boolean isFailOnError() {
     92  0
             return failOnError;
         /**
     92  
          * Sets whether or not the external report format should be used.
     93  
         }
          */
     94  
     
         @Parameter(property = "failOnError", defaultValue = "true", required = true)
     95  
         /**
         private boolean failOnError;
     96  
          * The Maven Project Object.
     
     97  
          */
     98  
         @Parameter(property = "project", required = true, readonly = true)
     99  
         private MavenProject project;
     100  
         /**
     98  
          * Returns if the mojo should fail the build if an exception occurs.
     99  
          *
     100  
          * @return whether or not the mojo should fail the build
     101  
          * List of Maven project of the current build
     102  
          */
     103  
         @Parameter(readonly = true, required = true, property = "reactorProjects")
     102  
         protected boolean isFailOnError() {
     103  0
             return failOnError;
     104  
         private List<MavenProject> reactorProjects;
         }
     105  
     
     106  
         /**
     107  
          * The output directory. This generally maps to "target".
          * The Maven Project Object.
     108  
          */
     109  
         @Parameter(defaultValue = "${project.build.directory}", required = true)
         @Parameter(property = "project", required = true, readonly = true)
     110  
         private File outputDirectory;
         private MavenProject project;
     111  
         /**
     112  
          * Specifies the destination directory for the generated Dependency-Check
          * List of Maven project of the current build
     113  
          * report. This generally maps to "target/site".
          */
     114  
          */
         @Parameter(readonly = true, required = true, property = "reactorProjects")
     115  
         @Parameter(property = "project.reporting.outputDirectory", required = true)
         private List<MavenProject> reactorProjects;
     116  
         private File reportOutputDirectory;
         /**
     117  
         /**
          * The entry point to Aether, i.e. the component doing all the work.
     118  
          * Specifies if the build should be failed if a CVSS score above a specified
          */
     119  
          * level is identified. The default is 11 which means since the CVSS scores
         @Component
     120  
          * are 0-10, by default the build will never fail.
         private RepositorySystem repoSystem;
     121  
          */
     122  0
         @SuppressWarnings("CanBeFinal")
     
     122  
         /**
     123  
         @Parameter(property = "failBuildOnCVSS", defaultValue = "11", required = true)
          * The current repository/network configuration of Maven.
     124  
         private float failBuildOnCVSS = 11;
          */
     125  
         /**
         @Parameter(defaultValue = "${repositorySystemSession}", readonly = true)
     126  
          * Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not
         private RepositorySystemSession repoSession;
     127  
          * recommended that this be turned to false. Default is true.
     
     128  
          */
         /**
     129  
         @Parameter(property = "autoUpdate")
          * The project's remote repositories to use for the resolution of plug-ins
     130  
         private Boolean autoUpdate;
          * and their dependencies.
     131  
         /**
          */
     132  
          * Sets whether Experimental analyzers are enabled. Default is false.
         @Parameter(defaultValue = "${project.remotePluginRepositories}", readonly = true)
     133  
          */
         private List<RemoteRepository> remoteRepos;
     134  
         @Parameter(property = "enableExperimental")
     
     135  
         private Boolean enableExperimental;
         /**
     136  
         /**
          * Component within Maven to build the dependency graph.
     137  
          * Generate aggregate reports in multi-module projects.
          */
     138  
          *
         @Component
     139  
          * @deprecated use the aggregate goal instead
         private DependencyGraphBuilder dependencyGraphBuilder;
     140  
          */
     
     141  
         @Parameter(property = "aggregate")
     142  
         @Deprecated
     143  
         private Boolean aggregate;
     144  
         /**
     145  
          * The report format to be generated (HTML, XML, VULN, ALL). This
     146  
          * configuration option has no affect if using this within the Site plug-in
     147  
          * unless the externalReport is set to true. Default is HTML.
     148  
     142  
          * The output directory. This generally maps to "target".
     143  
          */
     144  
         @Parameter(defaultValue = "${project.build.directory}", required = true)
     145  
         private File outputDirectory;
     146  
         /**
     147  
          * Specifies the destination directory for the generated Dependency-Check
     148  
          * report. This generally maps to "target/site".
     149  
          */
     149  0
         @SuppressWarnings("CanBeFinal")
     150  
         @Parameter(property = "format", defaultValue = "HTML", required = true)
         @Parameter(property = "project.reporting.outputDirectory", required = true)
     151  
         private String format = "HTML";
         private File reportOutputDirectory;
     152  
         /**
     153  
          * The Maven settings.
          * Specifies if the build should be failed if a CVSS score above a specified
     154  
          */
          * level is identified. The default is 11 which means since the CVSS scores
     155  
         @Parameter(property = "mavenSettings", defaultValue = "${settings}", required = false)
          * are 0-10, by default the build will never fail.
     156  
         private org.apache.maven.settings.Settings mavenSettings;
     157  
     
          */
     157  0
         @SuppressWarnings("CanBeFinal")
     158  
         /**
         @Parameter(property = "failBuildOnCVSS", defaultValue = "11", required = true)
     159  
          * The maven settings proxy id.
         private float failBuildOnCVSS = 11;
     160  
          */
         /**
     161  
         @Parameter(property = "mavenSettingsProxyId", required = false)
          * Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not
     162  
         private String mavenSettingsProxyId;
          * recommended that this be turned to false. Default is true.
     163  
     
          */
     164  
         /**
         @Parameter(property = "autoUpdate")
     165  
          * The Connection Timeout.
         private Boolean autoUpdate;
     166  
          */
         /**
     167  
         @Parameter(property = "connectionTimeout", defaultValue = "", required = false)
          * Sets whether Experimental analyzers are enabled. Default is false.
     168  
         private String connectionTimeout;
          */
     169  
         /**
         @Parameter(property = "enableExperimental")
     170  
          * The path to the suppression file.
         private Boolean enableExperimental;
     171  
          */
         /**
     172  
         @Parameter(property = "suppressionFile", defaultValue = "", required = false)
          * Generate aggregate reports in multi-module projects.
     173  
         private String suppressionFile;
          *
     174  
         /**
          * @deprecated use the aggregate goal instead
     175  
          * Flag indicating whether or not to show a summary in the output.
     176  
          */
     177  0
         @SuppressWarnings("CanBeFinal")
     176  
         @Parameter(property = "aggregate")
     177  
         @Deprecated
     178  
         @Parameter(property = "showSummary", defaultValue = "true", required = false)
         private Boolean aggregate;
     179  
         private boolean showSummary = true;
     180  
     
     181  
         /**
     180  
          * The report format to be generated (HTML, XML, VULN, ALL). This
     181  
          * configuration option has no affect if using this within the Site plug-in
     182  
          * Whether or not the Jar Analyzer is enabled.
          * unless the externalReport is set to true. Default is HTML.
     183  
          */
     184  
         @Parameter(property = "jarAnalyzerEnabled", required = false)
     184  0
         @SuppressWarnings("CanBeFinal")
     185  
         private Boolean jarAnalyzerEnabled;
         @Parameter(property = "format", defaultValue = "HTML", required = true)
     186  
     
         private String format = "HTML";
     187  
         /**
     188  
          * Whether or not the Archive Analyzer is enabled.
          * The Maven settings.
     189  
          */
     190  
         @Parameter(property = "archiveAnalyzerEnabled", required = false)
         @Parameter(property = "mavenSettings", defaultValue = "${settings}", required = false)
     191  
         private Boolean archiveAnalyzerEnabled;
         private org.apache.maven.settings.Settings mavenSettings;
     192  
     
     193  
         /**
     194  
          * Sets whether the Python Distribution Analyzer will be used.
          * The maven settings proxy id.
     195  
          */
     196  
         @Parameter(property = "pyDistributionAnalyzerEnabled", required = false)
         @Parameter(property = "mavenSettingsProxyId", required = false)
     197  
         private Boolean pyDistributionAnalyzerEnabled;
         private String mavenSettingsProxyId;
     198  
         /**
     
     199  
          * Sets whether the Python Package Analyzer will be used.
         /**
     200  
          */
          * The Connection Timeout.
     201  
         @Parameter(property = "pyPackageAnalyzerEnabled", required = false)
          */
     202  
         private Boolean pyPackageAnalyzerEnabled;
         @Parameter(property = "connectionTimeout", defaultValue = "", required = false)
     203  
         /**
         private String connectionTimeout;
     204  
          * Sets whether the Ruby Gemspec Analyzer will be used.
         /**
     205  
          */
          * The path to the suppression file.
     206  
         @Parameter(property = "rubygemsAnalyzerEnabled", required = false)
          */
     207  
         private Boolean rubygemsAnalyzerEnabled;
         @Parameter(property = "suppressionFile", defaultValue = "", required = false)
     208  
         /**
         private String suppressionFile;
     209  
          * Sets whether or not the openssl Analyzer should be used.
         /**
     210  
          */
          * Flag indicating whether or not to show a summary in the output.
     211  
         @Parameter(property = "opensslAnalyzerEnabled", required = false)
     212  
         private Boolean opensslAnalyzerEnabled;
          */
     212  0
         @SuppressWarnings("CanBeFinal")
     213  
         /**
         @Parameter(property = "showSummary", defaultValue = "true", required = false)
     214  
          * Sets whether or not the CMake Analyzer should be used.
         private boolean showSummary = true;
     215  
          */
     
     216  
         @Parameter(property = "cmakeAnalyzerEnabled", required = false)
         /**
     217  
         private Boolean cmakeAnalyzerEnabled;
          * Whether or not the Jar Analyzer is enabled.
     218  
         /**
          */
     219  
          * Sets whether or not the autoconf Analyzer should be used.
         @Parameter(property = "jarAnalyzerEnabled", required = false)
     220  
          */
         private Boolean jarAnalyzerEnabled;
     221  
         @Parameter(property = "autoconfAnalyzerEnabled", required = false)
     
     222  
         private Boolean autoconfAnalyzerEnabled;
     223  
         /**
     223  
          * Whether or not the Archive Analyzer is enabled.
     224  
          * Sets whether or not the PHP Composer Lock File Analyzer should be used.
     225  
          */
     225  
         @Parameter(property = "archiveAnalyzerEnabled", required = false)
     226  
         @Parameter(property = "composerAnalyzerEnabled", required = false)
         private Boolean archiveAnalyzerEnabled;
     227  
         private Boolean composerAnalyzerEnabled;
     
     228  
         /**
     229  
          * Sets whether or not the Node.js Analyzer should be used.
          * Sets whether the Python Distribution Analyzer will be used.
     230  
          */
     231  
         @Parameter(property = "nodeAnalyzerEnabled", required = false)
         @Parameter(property = "pyDistributionAnalyzerEnabled", required = false)
     232  
         private Boolean nodeAnalyzerEnabled;
         private Boolean pyDistributionAnalyzerEnabled;
     233  
     
         /**
     234  
         /**
          * Sets whether the Python Package Analyzer will be used.
     235  
          * Whether or not the .NET Assembly Analyzer is enabled.
          */
     236  
          */
         @Parameter(property = "pyPackageAnalyzerEnabled", required = false)
     237  
         @Parameter(property = "assemblyAnalyzerEnabled", required = false)
         private Boolean pyPackageAnalyzerEnabled;
     238  
         private Boolean assemblyAnalyzerEnabled;
         /**
     239  
     
          * Sets whether the Ruby Gemspec Analyzer will be used.
     240  
         /**
          */
     241  
          * Whether or not the .NET Nuspec Analyzer is enabled.
         @Parameter(property = "rubygemsAnalyzerEnabled", required = false)
     242  
          */
         private Boolean rubygemsAnalyzerEnabled;
     243  
         @Parameter(property = "nuspecAnalyzerEnabled", required = false)
         /**
     244  
         private Boolean nuspecAnalyzerEnabled;
          * Sets whether or not the openssl Analyzer should be used.
     245  
     
          */
     246  
         /**
         @Parameter(property = "opensslAnalyzerEnabled", required = false)
     247  
          * Whether or not the Central Analyzer is enabled.
         private Boolean opensslAnalyzerEnabled;
     248  
          */
     249  
         @Parameter(property = "centralAnalyzerEnabled", required = false)
     250  
         private Boolean centralAnalyzerEnabled;
     251  
     
     252  
         /**
     253  
          * Whether or not the Nexus Analyzer is enabled.
     254  
     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  
         @Parameter(property = "nexusAnalyzerEnabled", required = false)
          */
     256  
         private Boolean nexusAnalyzerEnabled;
         @Parameter(property = "autoconfAnalyzerEnabled", required = false)
     257  
     
         private Boolean autoconfAnalyzerEnabled;
     258  
         /**
     259  
          * The URL of a Nexus server's REST API end point
          * Sets whether or not the PHP Composer Lock File Analyzer should be used.
     260  
          * (http://domain/nexus/service/local).
          */
     261  
          */
         @Parameter(property = "composerAnalyzerEnabled", required = false)
     262  
         @Parameter(property = "nexusUrl", required = false)
         private Boolean composerAnalyzerEnabled;
     263  
         private String nexusUrl;
     264  
         /**
     264  
          * Sets whether or not the Node.js Analyzer should be used.
     265  
          * Whether or not the configured proxy is used to connect to Nexus.
     266  
          */
     266  
         @Parameter(property = "nodeAnalyzerEnabled", required = false)
     267  
         @Parameter(property = "nexusUsesProxy", required = false)
         private Boolean nodeAnalyzerEnabled;
     268  
         private Boolean nexusUsesProxy;
     
     269  
         /**
     270  
          * The database connection string.
          * Whether or not the .NET Assembly Analyzer is enabled.
     271  
          */
     272  
         @Parameter(property = "connectionString", defaultValue = "", required = false)
         @Parameter(property = "assemblyAnalyzerEnabled", required = false)
     273  
         private String connectionString;
         private Boolean assemblyAnalyzerEnabled;
     274  
     
     275  
         /**
     276  
          * Returns the connection string.
          * Whether or not the .NET Nuspec Analyzer is enabled.
     277  
          *
          */
     278  
          * @return the connection string
         @Parameter(property = "nuspecAnalyzerEnabled", required = false)
     279  
          */
         private Boolean nuspecAnalyzerEnabled;
     280  
         protected String getConnectionString() {
     281  0
             return connectionString;
     
     281  
         /**
     282  
         }
          * Whether or not the Central Analyzer is enabled.
     283  
         /**
          */
     284  
          * The database driver name. An example would be org.h2.Driver.
         @Parameter(property = "centralAnalyzerEnabled", required = false)
     285  
          */
         private Boolean centralAnalyzerEnabled;
     286  
         @Parameter(property = "databaseDriverName", defaultValue = "", required = false)
     
     287  
         private String databaseDriverName;
     288  
         /**
     288  
          * Whether or not the Nexus Analyzer is enabled.
     289  
          * The path to the database driver if it is not on the class path.
     290  
          */
     290  
         @Parameter(property = "nexusAnalyzerEnabled", required = false)
     291  
         @Parameter(property = "databaseDriverPath", defaultValue = "", required = false)
         private Boolean nexusAnalyzerEnabled;
     292  
         private String databaseDriverPath;
     
     293  
         /**
     294  
          * The server id in the settings.xml; used to retrieve encrypted passwords
          * The URL of a Nexus server's REST API end point
     295  
          * from the settings.xml.
          * (http://domain/nexus/service/local).
     296  
          */
     297  
         @Parameter(property = "serverId", defaultValue = "", required = false)
         @Parameter(property = "nexusUrl", required = false)
     298  
         private String serverId;
         private String nexusUrl;
     299  
         /**
     300  
          * A reference to the settings.xml settings.
          * Whether or not the configured proxy is used to connect to Nexus.
     301  
          */
     302  
         @Parameter(defaultValue = "${settings}", readonly = true, required = true)
         @Parameter(property = "nexusUsesProxy", required = false)
     303  
         private org.apache.maven.settings.Settings settingsXml;
         private Boolean nexusUsesProxy;
     304  
         /**
     305  
          * The security dispatcher that can decrypt passwords in the settings.xml.
          * The database connection string.
     306  
          */
     307  
         @Component(role = SecDispatcher.class, hint = "default")
         @Parameter(property = "connectionString", defaultValue = "", required = false)
     308  
         private SecDispatcher securityDispatcher;
         private String connectionString;
     309  
         /**
     
     310  
          * The database user name.
         /**
     311  
          */
          * Returns the connection string.
     312  
         @Parameter(property = "databaseUser", defaultValue = "", required = false)
          *
     313  
         private String databaseUser;
          * @return the connection string
     314  
         /**
          */
     315  
          * The password to use when connecting to the database.
     316  
          */
         protected String getConnectionString() {
     316  0
             return connectionString;
     317  
         @Parameter(property = "databasePassword", defaultValue = "", required = false)
         }
     318  
         private String databasePassword;
         /**
     319  
         /**
          * The database driver name. An example would be org.h2.Driver.
     320  
          * A comma-separated list of file extensions to add to analysis next to jar,
          */
     321  
          * zip, ....
         @Parameter(property = "databaseDriverName", defaultValue = "", required = false)
     322  
          */
         private String databaseDriverName;
     323  
         @Parameter(property = "zipExtensions", required = false)
         /**
     324  
         private String zipExtensions;
          * The path to the database driver if it is not on the class path.
     325  
         /**
          */
     326  
          * Skip Dependency Check altogether.
         @Parameter(property = "databaseDriverPath", defaultValue = "", required = false)
     327  
          */
     328  0
         @SuppressWarnings("CanBeFinal")
         private String databaseDriverPath;
     328  
         /**
     329  
         @Parameter(property = "dependency-check.skip", defaultValue = "false", required = false)
          * The server id in the settings.xml; used to retrieve encrypted passwords
     330  
         private boolean skip = false;
          * from the settings.xml.
     331  
         /**
          */
     332  
          * Skip Analysis for Test Scope Dependencies.
         @Parameter(property = "serverId", defaultValue = "", required = false)
     333  
          */
     334  0
         @SuppressWarnings("CanBeFinal")
         private String serverId;
     334  
         /**
     335  
         @Parameter(property = "skipTestScope", defaultValue = "true", required = false)
          * A reference to the settings.xml settings.
     336  
         private boolean skipTestScope = true;
          */
     337  
         /**
         @Parameter(defaultValue = "${settings}", readonly = true, required = true)
     338  
          * Skip Analysis for Runtime Scope Dependencies.
         private org.apache.maven.settings.Settings settingsXml;
     339  
          */
     340  0
         @SuppressWarnings("CanBeFinal")
     341  
         @Parameter(property = "skipRuntimeScope", defaultValue = "false", required = false)
     342  
         private boolean skipRuntimeScope = false;
     343  
         /**
     344  
          * Skip Analysis for Provided Scope Dependencies.
     345  
     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  
          */
     346  0
         @SuppressWarnings("CanBeFinal")
     347  
         @Parameter(property = "skipProvidedScope", defaultValue = "false", required = false)
         @Parameter(property = "databaseUser", defaultValue = "", required = false)
     348  
         private boolean skipProvidedScope = false;
         private String databaseUser;
     349  
         /**
     350  
          * The data directory, hold DC SQL DB.
          * The password to use when connecting to the database.
     351  
          */
     352  
         @Parameter(property = "dataDirectory", defaultValue = "", required = false)
         @Parameter(property = "databasePassword", defaultValue = "", required = false)
     353  
         private String dataDirectory;
         private String databasePassword;
     354  
         /**
     355  
          * Data Mirror URL for CVE 1.2.
          * A comma-separated list of file extensions to add to analysis next to jar,
     356  
          */
          * zip, ....
     357  
         @Parameter(property = "cveUrl12Modified", defaultValue = "", required = false)
          */
     358  
         private String cveUrl12Modified;
         @Parameter(property = "zipExtensions", required = false)
     359  
         /**
         private String zipExtensions;
     360  
          * Data Mirror URL for CVE 2.0.
         /**
     361  
          */
          * Skip Dependency Check altogether.
     362  
         @Parameter(property = "cveUrl20Modified", defaultValue = "", required = false)
     363  
         private String cveUrl20Modified;
          */
     363  0
         @SuppressWarnings("CanBeFinal")
     364  
         /**
         @Parameter(property = "dependency-check.skip", defaultValue = "false", required = false)
     365  
          * Base Data Mirror URL for CVE 1.2.
         private boolean skip = false;
     366  
          */
         /**
     367  
         @Parameter(property = "cveUrl12Base", defaultValue = "", required = false)
          * Skip Analysis for Test Scope Dependencies.
     368  
         private String cveUrl12Base;
     369  
         /**
          */
     369  0
         @SuppressWarnings("CanBeFinal")
     370  
          * Data Mirror URL for CVE 2.0.
         @Parameter(property = "skipTestScope", defaultValue = "true", required = false)
     371  
          */
         private boolean skipTestScope = true;
     372  
         @Parameter(property = "cveUrl20Base", defaultValue = "", required = false)
         /**
     373  
         private String cveUrl20Base;
          * Skip Analysis for Runtime Scope Dependencies.
     374  
         /**
     375  
          * Optionally skip excessive CVE update checks for a designated duration in
          */
     375  0
         @SuppressWarnings("CanBeFinal")
     376  
          * hours.
         @Parameter(property = "skipRuntimeScope", defaultValue = "false", required = false)
     377  
          */
         private boolean skipRuntimeScope = false;
     378  
         @Parameter(property = "cveValidForHours", defaultValue = "", required = false)
         /**
     379  
         private Integer cveValidForHours;
          * Skip Analysis for Provided Scope Dependencies.
     380  
     
     381  
         /**
     382  
          * The path to mono for .NET Assembly analysis on non-windows systems.
     383  
          */
     381  0
         @SuppressWarnings("CanBeFinal")
     382  
         @Parameter(property = "skipProvidedScope", defaultValue = "false", required = false)
     383  
         private boolean skipProvidedScope = false;
     384  
         @Parameter(property = "pathToMono", defaultValue = "", required = false)
     385  
         private String pathToMono;
     386  
     
     387  
         /**
     385  
          * The data directory, hold DC SQL DB.
     386  
          */
     387  
         @Parameter(property = "dataDirectory", defaultValue = "", required = false)
     388  
          * The Proxy URL.
         private String dataDirectory;
     389  
          *
         /**
     390  
          * @deprecated Please use mavenSettings instead
          * Data Mirror URL for CVE 1.2.
     391  
          */
     392  0
         @SuppressWarnings("CanBeFinal")
     392  
         @Parameter(property = "cveUrl12Modified", defaultValue = "", required = false)
     393  
         @Parameter(property = "proxyUrl", defaultValue = "", required = false)
         private String cveUrl12Modified;
     394  
         @Deprecated
         /**
     395  
         private String proxyUrl = null;
          * Data Mirror URL for CVE 2.0.
     396  
         /**
          */
     397  
          * Sets whether or not the external report format should be used.
         @Parameter(property = "cveUrl20Modified", defaultValue = "", required = false)
     398  
          *
         private String cveUrl20Modified;
     399  
          * @deprecated the internal report is no longer supported
         /**
     400  
          * Base Data Mirror URL for CVE 1.2.
     401  
          */
     401  0
         @SuppressWarnings("CanBeFinal")
     402  
         @Parameter(property = "externalReport")
         @Parameter(property = "cveUrl12Base", defaultValue = "", required = false)
     403  
         @Deprecated
         private String cveUrl12Base;
     404  
         private String externalReport = null;
         /**
     405  
         // </editor-fold>
          * Data Mirror URL for CVE 2.0.
     406  
         //<editor-fold defaultstate="collapsed" desc="Base Maven implementation">
          */
     407  
     
         @Parameter(property = "cveUrl20Base", defaultValue = "", required = false)
     408  
         /**
         private String cveUrl20Base;
     409  
          * Executes dependency-check.
         /**
     410  
          *
          * Optionally skip excessive CVE update checks for a designated duration in
     411  
          * @throws MojoExecutionException thrown if there is an exception executing
          * hours.
     412  
          * the mojo
          */
     413  
          * @throws MojoFailureException thrown if dependency-check failed the build
         @Parameter(property = "cveValidForHours", defaultValue = "", required = false)
     414  
          */
         private Integer cveValidForHours;
     415  
         @Override
     
     416  
         public void execute() throws MojoExecutionException, MojoFailureException {
     417  0
             generatingSite = false;
     418  0
             if (skip) {
     419  0
                 getLog().info("Skipping " + getName(Locale.US));
         /**
     417  
          * The path to mono for .NET Assembly analysis on non-windows systems.
     418  
          */
     419  
         @Parameter(property = "pathToMono", defaultValue = "", required = false)
     420  
             } else {
     421  0
                 validateAggregate();
     422  0
                 project.setContextValue(getOutputDirectoryContextKey(), this.outputDirectory);
     423  0
                 runCheck();
         private String pathToMono;
     421  
     
     422  
         /**
     423  
          * The Proxy URL.
     424  
             }
     425  0
         }
          *
     425  
          * @deprecated Please use mavenSettings instead
     426  
     
     427  
         /**
          */
     427  0
         @SuppressWarnings("CanBeFinal")
     428  
          * Checks if the aggregate configuration parameter has been set to true. If
         @Parameter(property = "proxyUrl", defaultValue = "", required = false)
     429  
          * it has a MojoExecutionException is thrown because the aggregate
     430  
          * configuration parameter is no longer supported.
     431  
          *
     432  
          * @throws MojoExecutionException thrown if aggregate is set to true
     433  
          */
     434  
         private void validateAggregate() throws MojoExecutionException {
     435  0
             if (aggregate != null && aggregate) {
     436  0
                 final String msg = "Aggregate configuration detected - as of dependency-check 1.2.8 this no longer supported. "
     437  
                         + "Please use the aggregate goal instead.";
     438  0
                 throw new MojoExecutionException(msg);
     439  
             }
     440  0
         }
     441  
     
     442  
         /**
     443  
          * Generates the Dependency-Check Site Report.
     444  
          *
     445  
          * @param sink the sink to write the report to
     446  
          * @param locale the locale to use when generating the report
     447  
          * @throws MavenReportException if a maven report exception occurs
     448  
          * @deprecated use
     449  
          * {@link #generate(org.apache.maven.doxia.sink.Sink, java.util.Locale)}
     450  
          * instead.
     451  
          */
     452  
         @Override
     453  
         @Deprecated
     454  
         public final void generate(@SuppressWarnings("deprecation") org.codehaus.doxia.sink.Sink sink, Locale locale) throws MavenReportException {
     455  0
             generate((Sink) sink, locale);
     456  0
         }
     457  
     
     458  
     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  0
         @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  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  
          * A flag indicating whether or not the maven site is being generated.
     460  
          */
     461  0
         private boolean generatingSite = false;
             }
     460  0
         }
     461  
     
     462  
     
         /**
     463  
         /**
          * Checks if the aggregate configuration parameter has been set to true. If
     464  
          * Returns true if the Maven site is being generated.
          * it has a MojoExecutionException is thrown because the aggregate
     465  
          *
          * configuration parameter is no longer supported.
     466  
          * @return true if the Maven site is being generated
          *
     467  
          */
          * @throws MojoExecutionException thrown if aggregate is set to true
     468  
         protected boolean isGeneratingSite() {
     469  0
             return generatingSite;
     470  
         }
     471  
     
          */
     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  
         /**
     473  
          * Generates the Dependency-Check Site Report.
                         + "Please use the aggregate goal instead.";
     473  0
                 throw new MojoExecutionException(msg);
     474  
          *
     475  
          * @param sink the sink to write the report to
             }
     475  0
         }
     476  
          * @param locale the locale to use when generating the report
     
     477  
          * @throws MavenReportException if a maven report exception occurs
         /**
     478  
          */
          * Generates the Dependency-Check Site Report.
     479  
         public void generate(Sink sink, Locale locale) throws MavenReportException {
     480  0
             generatingSite = true;
          *
     480  
          * @param sink the sink to write the report to
     481  
             try {
     482  0
                 validateAggregate();
     483  0
             } catch (MojoExecutionException ex) {
     484  0
                 throw new MavenReportException(ex.getMessage());
     485  0
             }
     486  0
             project.setContextValue(getOutputDirectoryContextKey(), getReportOutputDirectory());
          * @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  
             try {
     488  0
                 runCheck();
     489  0
             } catch (MojoExecutionException ex) {
     490  0
                 throw new MavenReportException(ex.getMessage(), ex);
     491  0
             } catch (MojoFailureException ex) {
     492  0
                 getLog().warn("Vulnerabilities were identifies that exceed the CVSS threshold for failing the build");
     493  0
             }
     494  0
         }
         @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  
     
     493  
         /**
     494  
          * A flag indicating whether or not the maven site is being generated.
     495  
     
     496  
         /**
          */
     496  0
         private boolean generatingSite = false;
     497  
          * Returns the correct output directory depending on if a site is being
     
     498  
          * executed or not.
         /**
     499  
          *
          * Returns true if the Maven site is being generated.
     500  
          * @return the directory to write the report(s)
          *
     501  
          * @throws MojoExecutionException thrown if there is an error loading the
          * @return true if the Maven site is being generated
     502  
          * file path
          */
     503  
          */
     504  
         protected File getCorrectOutputDirectory() throws MojoExecutionException {
     505  0
             return getCorrectOutputDirectory(this.project);
         protected boolean isGeneratingSite() {
     504  0
             return generatingSite;
     505  
         }
     506  
         }
     
     507  
     
         /**
     508  
         /**
          * Generates the Dependency-Check Site Report.
     509  
          * Returns the correct output directory depending on if a site is being
          *
     510  
          * executed or not.
          * @param sink the sink to write the report to
     511  
          *
          * @param locale the locale to use when generating the report
     512  
          * @param current the Maven project to get the output directory from
          * @throws MavenReportException if a maven report exception occurs
     513  
          * @return the directory to write the report(s)
          */
     514  
          */
     515  
         protected File getCorrectOutputDirectory(MavenProject current) {
     516  0
             final Object obj = current.getContextValue(getOutputDirectoryContextKey());
     517  0
             if (obj != null && obj instanceof File) {
     518  0
                 return (File) obj;
     519  
             }
     520  0
             File target = new File(current.getBuild().getDirectory());
     521  0
             if (target.getParentFile() != null && "target".equals(target.getParentFile().getName())) {
     522  0
                 target = target.getParentFile();
     523  
             }
     524  0
             return target;
     525  
         }
     526  
     
     527  
         /**
     528  
          * Returns the correct output directory depending on if a site is being
     529  
          * executed or not.
         public void generate(Sink sink, Locale locale) throws MavenReportException {
     515  0
             generatingSite = true;
     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  
          * @param current the Maven project to get the output directory from
         /**
     532  
          * @return the directory to write the report(s)
          * Returns the correct output directory depending on if a site is being
     533  
          */
          * executed or not.
     534  
         protected File getDataFile(MavenProject current) {
     535  0
             if (getLog().isDebugEnabled()) {
     536  0
                 getLog().debug(String.format("Getting data filefor %s using key '%s'", current.getName(), getDataFileContextKey()));
          *
     535  
          * @return the directory to write the report(s)
     536  
          * @throws MojoExecutionException thrown if there is an error loading the
     537  
             }
     538  0
             final Object obj = current.getContextValue(getDataFileContextKey());
     539  0
             if (obj != null) {
     540  0
                 if (obj instanceof String) {
     541  0
                     final File f = new File((String) obj);
     542  0
                     return f;
          * file path
     538  
          */
     539  
         protected File getCorrectOutputDirectory() throws MojoExecutionException {
     540  0
             return getCorrectOutputDirectory(this.project);
     541  
         }
     542  
     
     543  
                 }
     544  0
             } else if (getLog().isDebugEnabled()) {
     545  0
                 getLog().debug("Context value not found");
         /**
     544  
          * Returns the correct output directory depending on if a site is being
     545  
          * executed or not.
     546  
             }
     547  0
             return null;
          *
     547  
          * @param current the Maven project to get the output directory from
     548  
         }
          * @return the directory to write the report(s)
     549  
     
          */
     550  
         /**
     551  
          * Scans the project's artifacts and adds them to the engine's dependency
     552  
          * list.
     553  
          *
         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  
          * @param project the project to scan the dependencies of
     555  
          * @param engine the engine to use to scan the dependencies
     556  
          */
     557  
         protected void scanArtifacts(MavenProject project, MavenEngine engine) {
     558  0
             for (Artifact a : project.getArtifacts()) {
     559  0
                 if (excludeFromScan(a)) {
     560  0
                     continue;
             }
     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  
          * 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  0
             if (getLog().isDebugEnabled()) {
     571  0
                 getLog().debug(String.format("Getting data filefor %s using key '%s'", current.getName(), getDataFileContextKey()));
     572  
             }
     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  
                 }
     562  0
                 final List<Dependency> deps = engine.scan(a.getFile().getAbsoluteFile());
     563  0
                 if (deps != null) {
     564  0
                     if (deps.size() == 1) {
     565  0
                         final Dependency d = deps.get(0);
     566  0
                         if (d != null) {
     567  0
                             final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion());
     568  0
                             d.addAsEvidence("pom", ma, Confidence.HIGHEST);
     569  0
                             d.addProjectReference(project.getName());
     570  0
                             if (getLog().isDebugEnabled()) {
     571  0
                                 getLog().debug(String.format("Adding project reference %s on dependency %s", project.getName(),
     572  0
                                         d.getDisplayFileName()));
     573  
                             }
     574  
                         }
     575  0
                     } else if (getLog().isDebugEnabled()) {
     576  0
                         final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s:%s:%s'",
     577  0
                                 a.getGroupId(), a.getArtifactId(), a.getVersion());
     578  0
                         getLog().debug(msg);
     579  
                     }
     580  
                 }
     581  0
             }
     582  0
         }
     579  0
             } else if (getLog().isDebugEnabled()) {
     580  0
                 getLog().debug("Context value not found");
     581  
             }
     582  0
             return null;
     583  
     
         }
     584  
         /**
     
     585  
          * Executes the dependency-check scan and generates the necassary report.
         /**
     586  
          *
          * Scans the project's artifacts and adds them to the engine's dependency
     587  
          * @throws MojoExecutionException thrown if there is an exception running
          * list.
     588  
          * the scan
          *
     589  
          * @throws MojoFailureException thrown if dependency-check is configured to
          * @param project the project to scan the dependencies of
     590  
          * fail the build
          * @param engine the engine to use to scan the dependencies
     591  
          */
          * @return a collection of exceptions that may have occurred while resolving
     592  
         public abstract void runCheck() throws MojoExecutionException, MojoFailureException;
          * and scanning the dependencies
     593  
     
          */
     594  
         /**
         protected ExceptionCollection scanArtifacts(MavenProject project, MavenEngine engine) {
     595  
          * Sets the Reporting output directory.
             // <editor-fold defaultstate="collapsed" desc="old implementation">
     596  
          *
             /*
     597  
          * @param directory the output directory
                 for (Artifact a : project.getArtifacts()) {
     598  
          */
                 if (excludeFromScan(a)) {
     599  
         @Override
                 continue;
     600  
         public void setReportOutputDirectory(File directory) {
     601  0
             reportOutputDirectory = directory;
     602  0
         }
                 }
     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  
          * Returns the report output directory.
                 if (d != null) {
     606  
          *
                 final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion());
     607  
          * @return the report output directory
                 d.addAsEvidence("pom", ma, Confidence.HIGHEST);
     608  
          */
                 d.addProjectReference(project.getName());
     609  
         @Override
                 if (getLog().isDebugEnabled()) {
     610  
         public File getReportOutputDirectory() {
     611  0
             return reportOutputDirectory;
                 getLog().debug(String.format("Adding project reference %s on dependency %s", project.getName(),
     611  
                 d.getDisplayFileName()));
     612  
         }
                 }
     613  
     
                 }
     614  
         /**
                 } else if (getLog().isDebugEnabled()) {
     615  
          * Returns the output directory.
                 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  
          * @return the output directory
                 getLog().debug(msg);
     618  
          */
                 }
     619  
         public File getOutputDirectory() {
     620  0
             return outputDirectory;
                 }
     620  
                 }
     621  
         }
              */
     622  
     
             // </editor-fold>
     623  
         /**
     624  
          * Returns whether this is an external report. This method always returns
     625  
          * true.
     626  
          *
     627  
          * @return <code>true</code>
     628  
          */
     629  
         @Override
             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);
     630  
         public final boolean isExternalReport() {
     631  0
             return true;
     632  
             }
     631  
         }
     633  
     632  
     
     634  
     633  
         /**
     634  
          * Resolves the projects artifacts using Aether and scans the resulting
     635  
          * Returns the output name.
          * dependencies.
     636  
          *
     637  
          * @return the output name
          * @param engine the core dependency-check engine
     638  
          */
          * @param project the project being scanned
     639  
         @Override
          * @param nodes the list of dependency nodes, generally obtained via the
     640  
         public String getOutputName() {
     641  0
             if ("HTML".equalsIgnoreCase(this.format) || "ALL".equalsIgnoreCase(this.format)) {
     642  0
                 return "dependency-check-report";
     643  0
             } else if ("XML".equalsIgnoreCase(this.format)) {
     644  0
                 return "dependency-check-report.xml#";
     645  0
             } else if ("VULN".equalsIgnoreCase(this.format)) {
     646  0
                 return "dependency-check-vulnerability";
     647  
             } else {
     648  0
                 getLog().warn("Unknown report format used during site generation.");
     649  0
                 return "dependency-check-report";
          * 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  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;
     650  
             }
     651  
         }
     652  
     
     653  
         /**
                 }
     651  0
                 final ArtifactRequest request = new ArtifactRequest();
     652  0
                 request.setArtifact(new DefaultArtifact(dependencyNode.getArtifact().getId()));
     653  0
                 request.setRepositories(remoteRepos);
     654  
          * Returns the category name.
     655  
          *
     656  
          * @return the category name
     657  
          */
     658  
         @Override
     659  
         public String getCategoryName() {
     660  0
             return MavenReport.CATEGORY_PROJECT_REPORTS;
     661  
         }
     662  
         //</editor-fold>
     663  
     
     664  
         /**
     665  
          * Initializes a new <code>MavenEngine</code> that can be used for scanning.
     666  
          *
     667  
          * @return a newly instantiated <code>MavenEngine</code>
     668  
          * @throws DatabaseException thrown if there is a database exception
                 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  
         protected MavenEngine initializeEngine() throws DatabaseException {
     671  0
             populateSettings();
     672  0
             return new MavenEngine(this.project,
     673  
                     this.reactorProjects);
     674  
         }
     675  
     
                                 }
     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
                             }
     676  
         /**
     677  
          * Takes the properties supplied and updates the dependency-check settings.
     678  
          * Additionally, this sets the system properties required to change the
     679  
          * proxy url, port, and connection timeout.
     680  
          */
                         } 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  
         protected void populateSettings() {
     682  0
             Settings.initialize();
     683  0
             InputStream mojoProperties = null;
     684  
             try {
     685  0
                 mojoProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
     686  0
                 Settings.mergeProperties(mojoProperties);
     687  0
             } catch (IOException ex) {
     688  0
                 getLog().warn("Unable to load the dependency-check ant task.properties file.");
     689  0
                 if (getLog().isDebugEnabled()) {
     690  0
                     getLog().debug("", ex);
     691  
                 }
     692  
             } finally {
     693  0
                 if (mojoProperties != null) {
     694  
                     try {
     695  0
                         mojoProperties.close();
     696  0
                     } catch (IOException ex) {
     697  0
                         if (getLog().isDebugEnabled()) {
     698  0
                             getLog().debug("", ex);
     699  
                         }
     700  0
                     }
     701  
                 }
     702  
             }
     703  0
             Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate);
     704  
     
     705  0
             Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental);
     706  
     
     707  0
             if (externalReport != null) {
     708  0
                 getLog().warn("The 'externalReport' option was set; this configuration option has been removed. "
     709  
                         + "Please update the dependency-check-maven plugin's configuration");
     710  
             }
     711  
     
     712  0
             if (proxyUrl != null && !proxyUrl.isEmpty()) {
     713  0
                 getLog().warn("Deprecated configuration detected, proxyUrl will be ignored; use the maven settings " + "to configure the proxy instead");
     714  
             }
     715  0
             final Proxy proxy = getMavenProxy();
     716  0
             if (proxy != null) {
     717  0
                 Settings.setString(Settings.KEYS.PROXY_SERVER, proxy.getHost());
     718  0
                 Settings.setString(Settings.KEYS.PROXY_PORT, Integer.toString(proxy.getPort()));
     719  0
                 final String userName = proxy.getUsername();
     720  0
                 final String password = proxy.getPassword();
     721  0
                 Settings.setStringIfNotNull(Settings.KEYS.PROXY_USERNAME, userName);
     722  0
                 Settings.setStringIfNotNull(Settings.KEYS.PROXY_PASSWORD, password);
     723  0
                 Settings.setStringIfNotNull(Settings.KEYS.PROXY_NON_PROXY_HOSTS, proxy.getNonProxyHosts());
     724  
             }
     725  
     
     726  0
             Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
     727  0
             Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
     728  
     
     729  
             //File Type Analyzer Settings
     730  0
             Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled);
     731  0
             Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled);
     732  0
             Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled);
     733  0
             Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled);
     734  0
             Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
     735  0
             Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy);
     736  0
             Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled);
     737  0
             Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled);
     738  0
             Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions);
     739  0
             Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
     740  
     
     741  0
             Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, pyDistributionAnalyzerEnabled);
     742  0
             Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, pyPackageAnalyzerEnabled);
     743  0
             Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, rubygemsAnalyzerEnabled);
     744  0
             Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, opensslAnalyzerEnabled);
     745  0
             Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CMAKE_ENABLED, cmakeAnalyzerEnabled);
     746  0
             Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, autoconfAnalyzerEnabled);
     747  0
             Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, composerAnalyzerEnabled);
     748  0
             Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, nodeAnalyzerEnabled);
     749  
     
     750  
             //Database configuration
     751  0
             Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
     752  0
             Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
     753  0
             Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
     754  
     
     755  0
             if (databaseUser == null && databasePassword == null && serverId != null) {
     756  0
                 final Server server = settingsXml.getServer(serverId);
     757  0
                 if (server != null) {
     758  0
                     databaseUser = server.getUsername();
     759  
                     try {
     760  
                         //The following fix was copied from:
     761  
                         //   https://github.com/bsorrentino/maven-confluence-plugin/blob/master/maven-confluence-reporting-plugin/src/main/java/org/bsc/maven/confluence/plugin/AbstractBaseConfluenceMojo.java
     762  
                         //
     763  
                         // FIX to resolve
     764  
                         // org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException:
     765  
                         // java.io.FileNotFoundException: ~/.settings-security.xml (No such file or directory)
     766  
                         //
     767  0
                         if (securityDispatcher instanceof DefaultSecDispatcher) {
     768  0
                             ((DefaultSecDispatcher) securityDispatcher).setConfigurationFile("~/.m2/settings-security.xml");
     769  
                         }
     770  
     
     771  0
                         databasePassword = securityDispatcher.decrypt(server.getPassword());
     772  0
                     } catch (SecDispatcherException ex) {
     773  0
                         if (ex.getCause() instanceof FileNotFoundException
     774  0
                                 || (ex.getCause() != null && ex.getCause().getCause() instanceof FileNotFoundException)) {
     775  
                             //maybe its not encrypted?
     776  0
                             final String tmp = server.getPassword();
     777  0
                             if (tmp.startsWith("{") && tmp.endsWith("}")) {
     778  0
                                 getLog().error(String.format(
     779  
                                         "Unable to decrypt the server password for server id '%s' in settings.xml%n\tCause: %s",
     780  0
                                         serverId, ex.getMessage()));
     781  
                             } else {
     782  0
                                 databasePassword = tmp;
     783  
                             }
     784  0
                         } else {
     785  0
                             getLog().error(String.format(
     786  
                                     "Unable to decrypt the server password for server id '%s' in settings.xml%n\tCause: %s",
     787  0
                                     serverId, ex.getMessage()));
     788  
     682  0
                             getLog().error(msg);
     683  0
                             for (Exception ex : result.getExceptions()) {
     684  0
                                 exCol.addException(ex);
     685  0
                             }
     686  
                         }
     789  0
                     }
     790  
                 } else {
     791  0
                     getLog().error(String.format("Server '%s' not found in the settings.xml file", serverId));
     792  
                 }
     793  
             }
     794  
     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();
     693  
                         }
     694  0
                         for (Exception ex : result.getExceptions()) {
     695  0
                             exCol.addException(ex);
     696  0
                         }
     697  
                     }
     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  
     
     795  0
             Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser);
     796  0
             Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword);
     797  0
             Settings.setStringIfNotEmpty(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
     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
     722  
          */
     723  
         @Override
     724  
         public void setReportOutputDirectory(File directory) {
     725  0
             reportOutputDirectory = directory;
     726  0
         }
     727  
     
     728  
         /**
     729  
          * Returns the report output directory.
     730  
          *
     731  
          * @return the report output directory
     732  
          */
     733  
         @Override
     734  
         public File getReportOutputDirectory() {
     735  0
             return reportOutputDirectory;
     736  
         }
     737  
     
     738  
         /**
     739  
          * Returns the output directory.
     740  
          *
     741  
          * @return the output directory
     742  
          */
     743  
         public File getOutputDirectory() {
     744  0
             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  0
             return true;
     756  
         }
     757  
     
     758  
         /**
     759  
          * Returns the output name.
     760  
          *
     761  
          * @return the output name
     762  
          */
     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  
         /**
     778  
          * Returns the category name.
     779  
          *
     780  
          * @return the category name
     781  
          */
     782  
         @Override
     783  
         public String getCategoryName() {
     784  0
             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  0
             populateSettings();
     796  0
             return new MavenEngine(this.project, this.reactorProjects);
     797  
         }
     798  
     
     799  0
             Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified);
     800  0
             Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified);
     801  0
             Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base);
     802  0
             Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base);
     803  0
             Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours);
     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  
     
     805  0
         }
     806  
     
         protected void populateSettings() {
     805  0
             Settings.initialize();
     806  0
             InputStream mojoProperties = null;
     807  
         /**
     808  
          * Returns the maven proxy.
     809  
          *
     810  
          * @return the maven proxy
     811  
          */
     812  
         private Proxy getMavenProxy() {
     813  0
             if (mavenSettings != null) {
     814  0
                 final List<Proxy> proxies = mavenSettings.getProxies();
     815  0
                 if (proxies != null && !proxies.isEmpty()) {
     816  0
                     if (mavenSettingsProxyId != null) {
     817  0
                         for (Proxy proxy : proxies) {
     818  0
                             if (mavenSettingsProxyId.equalsIgnoreCase(proxy.getId())) {
     819  0
                                 return proxy;
     820  
                             }
     821  0
                         }
     822  0
                     } else if (proxies.size() == 1) {
     823  0
                         return proxies.get(0);
     824  
                     } else {
     825  0
                         getLog().warn("Multiple proxy definitions exist in the Maven settings. In the dependency-check "
     826  
                                 + "configuration set the mavenSettingsProxyId so that the correct proxy will be used.");
     827  0
                         throw new IllegalStateException("Ambiguous proxy definition");
     828  
                     }
     829  
             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);
     814  
                 }
     830  
     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
                     }
     824  
                 }
     825  
             }
     831  0
             return null;
     826  0
             Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate);
     827  
     
     828  0
             Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental);
     829  
     
     830  0
             if (externalReport != null) {
     831  0
                 getLog().warn("The 'externalReport' option was set; this configuration option has been removed. "
     832  
         }
                         + "Please update the dependency-check-maven plugin's configuration");
     833  
     
             }
     834  
         /**
     835  
          * Tests is the artifact should be included in the scan (i.e. is the
     836  
          * dependency in a scope that is being scanned).
     
     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  
          * @param a the Artifact to test
     839  
          * @return <code>true</code> if the artifact is in an excluded scope;
     840  
          * otherwise <code>false</code>
     841  
          */
     842  
         protected boolean excludeFromScan(Artifact a) {
     843  0
             if (skipTestScope && Artifact.SCOPE_TEST.equals(a.getScope())) {
     844  0
                 return true;
     845  
             }
     846  0
             if (skipProvidedScope && Artifact.SCOPE_PROVIDED.equals(a.getScope())) {
     847  0
                 return true;
     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  
             }
     849  0
             if (skipRuntimeScope && !Artifact.SCOPE_RUNTIME.equals(a.getScope())) {
     850  0
                 return true;
     
     849  0
             Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
     850  0
             Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
     851  
             }
     852  0
             return false;
     853  
         }
     854  
     
     855  
         /**
     856  
          * Returns a reference to the current project. This method is used instead
     857  
          * of auto-binding the project via component annotation in concrete
     858  
          * implementations of this. If the child has a
     859  
          * <code>@Component MavenProject project;</code> defined then the abstract
     860  
          * class (i.e. this class) will not have access to the current project (just
     861  
          * the way Maven works with the binding).
     862  
          *
     852  
             //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  
          * @return returns a reference to the current project
     864  
          */
     865  
         protected MavenProject getProject() {
     866  0
             return project;
     867  
         }
     868  
     
     869  
         /**
     870  
          * Returns the list of Maven Projects in this build.
     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  
          * @return the list of Maven Projects in this build
     
     873  
          */
     874  
         protected List<MavenProject> getReactorProjects() {
     875  0
             return reactorProjects;
     876  
         }
             //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  
         /**
     879  
          * Returns the report format.
     880  
          *
     881  
          * @return the report format
     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  
         protected String getFormat() {
     884  0
             return format;
                         //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  
          * Generates the reports for a given dependency-check engine.
                         // java.io.FileNotFoundException: ~/.settings-security.xml (No such file or directory)
     889  
          *
     890  
          * @param engine a dependency-check engine
     891  
          * @param p the Maven project
                         //
     890  0
                         if (securityDispatcher instanceof DefaultSecDispatcher) {
     891  0
                             ((DefaultSecDispatcher) securityDispatcher).setConfigurationFile("~/.m2/settings-security.xml");
     892  
          * @param outputDir the directory path to write the report(s)
                         }
     893  
          * @throws ReportException thrown if there is an error writing the report
     894  
          */
     895  
         protected void writeReports(MavenEngine engine, MavenProject p, File outputDir) throws ReportException {
     896  0
             DatabaseProperties prop = null;
     897  0
             CveDB cve = null;
     
     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  
             try {
     899  0
                 cve = new CveDB();
     900  0
                 cve.open();
     901  0
                 prop = cve.getDatabaseProperties();
     902  0
             } catch (DatabaseException ex) {
     903  0
                 if (getLog().isDebugEnabled()) {
     904  0
                     getLog().debug("Unable to retrieve DB Properties", ex);
     905  
                 }
     906  
             } finally {
     907  0
                 if (cve != null) {
     908  0
                     cve.close();
     909  
                 }
     910  
             }
     911  0
             final ReportGenerator r = new ReportGenerator(p.getName(), engine.getDependencies(), engine.getAnalyzers(), prop);
     912  
             try {
     913  0
                 r.generateReports(outputDir.getAbsolutePath(), format);
     914  0
             } catch (ReportException ex) {
     915  0
                 final String msg = String.format("Error generating the report for %s", p.getName());
     916  0
                 throw new ReportException(msg, ex);
     917  0
             }
     918  
     
     919  0
         }
     920  
     
     921  
         //<editor-fold defaultstate="collapsed" desc="Methods to fail build or show summary">
     922  
         /**
     923  
          * Checks to see if a vulnerability has been identified with a CVSS score
     924  
          * that is above the threshold set in the configuration.
     925  
          *
     926  
          * @param dependencies the list of dependency objects
     927  
          * @throws MojoFailureException thrown if a CVSS score is found that is
     928  
          * higher then the threshold set
     929  
          */
     930  
         protected void checkForFailure(List<Dependency> dependencies) throws MojoFailureException {
     931  0
             if (failBuildOnCVSS <= 10) {
     932  0
                 final StringBuilder ids = new StringBuilder();
     933  0
                 for (Dependency d : dependencies) {
     934  0
                     boolean addName = true;
     935  0
                     for (Vulnerability v : d.getVulnerabilities()) {
     936  0
                         if (v.getCvssScore() >= failBuildOnCVSS) {
     937  0
                             if (addName) {
     938  0
                                 addName = false;
     939  0
                                 ids.append(NEW_LINE).append(d.getFileName()).append(": ");
     940  0
                                 ids.append(v.getName());
     941  
                             //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 {
     942  0
                                 ids.append(", ").append(v.getName());
     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  
                         }
     912  0
                     }
     913  
                 } else {
     914  0
                     getLog().error(String.format("Server '%s' not found in the settings.xml file", serverId));
     915  
                 }
     916  
             }
     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);
     921  
     
     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
         }
     929  
     
     930  
         /**
     931  
          * Returns the maven proxy.
     932  
          *
     933  
          * @return the maven proxy
     934  
          */
     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;
     943  
                             }
     944  
                         }
     945  0
                     }
     946  0
                 }
     947  0
                 if (ids.length() > 0) {
     948  0
                     final String msg = String.format("%n%nDependency-Check Failure:%n"
     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  
                             + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n"
     950  0
                             + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString());
     951  0
                     throw new MojoFailureException(msg);
                                 + "configuration set the mavenSettingsProxyId so that the correct proxy will be used.");
     950  0
                         throw new IllegalStateException("Ambiguous proxy definition");
     951  
                     }
     952  
                 }
     953  
             }
     954  0
         }
     954  0
             return null;
     955  
     
         }
     956  
         /**
     957  
          * Generates a warning message listing a summary of dependencies and their
     958  
          * associated CPE and CVE entries.
     959  
          *
     960  
          * @param mp the Maven project for which the summary is shown
     961  
          * @param dependencies a list of dependency objects
     962  
          */
     963  
         protected void showSummary(MavenProject mp, List<Dependency> dependencies) {
     964  0
             if (showSummary) {
     965  0
                 final StringBuilder summary = new StringBuilder();
     966  0
                 for (Dependency d : dependencies) {
     967  0
                     boolean firstEntry = true;
     968  0
                     final StringBuilder ids = new StringBuilder();
     969  0
                     for (Vulnerability v : d.getVulnerabilities()) {
     970  0
                         if (firstEntry) {
     971  0
                             firstEntry = false;
     972  
                         } else {
     973  0
                             ids.append(", ");
     974  
                         }
     975  0
                         ids.append(v.getName());
     976  0
                     }
     977  0
                     if (ids.length() > 0) {
     978  0
                         summary.append(d.getFileName()).append(" (");
     979  0
                         firstEntry = true;
     980  0
                         for (Identifier id : d.getIdentifiers()) {
     981  0
                             if (firstEntry) {
     982  0
                                 firstEntry = false;
     983  
                             } else {
     984  0
                                 summary.append(", ");
     985  
                             }
     986  0
                             summary.append(id.getValue());
     987  0
                         }
     988  0
                         summary.append(") : ").append(ids).append(NEW_LINE);
     989  
                     }
     990  0
                 }
     991  0
                 if (summary.length() > 0) {
     992  0
                     final String msg = String.format("%n%n" + "One or more dependencies were identified with known vulnerabilities in %s:%n%n%s"
     993  0
                             + "%n%nSee the dependency-check report for more details.%n%n", mp.getName(), summary.toString());
     994  0
                     getLog().warn(msg);
     995  
                 }
     996  
             }
     997  0
         }
     998  
     
     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  0
             if (skipTestScope && org.apache.maven.artifact.Artifact.SCOPE_TEST.equals(scope)) {
     967  0
                 return true;
     968  
             }
     969  0
             if (skipProvidedScope && org.apache.maven.artifact.Artifact.SCOPE_PROVIDED.equals(scope)) {
     970  0
                 return true;
     971  
             }
     972  0
             if (skipRuntimeScope && !org.apache.maven.artifact.Artifact.SCOPE_RUNTIME.equals(scope)) {
     973  0
                 return true;
     974  
             }
     975  0
             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  0
             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  0
             return reactorProjects;
     999  
         //</editor-fold>
         }
     1000  
         //<editor-fold defaultstate="collapsed" desc="Methods to read/write the serialized data file">
     
     1001  
         /**
     1002  
          * Returns the key used to store the path to the data file that is saved by
          * Returns the report format.
     1003  
          * <code>writeDataFile()</code>. This key is used in the
          *
     1004  
          * <code>MavenProject.(set|get)ContextValue</code>.
          * @return the report format
     1005  
          *
          */
     1006  
          * @return the key used to store the path to the data file
     1007  
          */
         protected String getFormat() {
     1007  0
             return format;
     1008  
         protected String getDataFileContextKey() {
     1009  0
             return "dependency-check-path-" + dataFileName;
         }
     1009  
     
     1010  
         }
         /**
     1011  
     
          * Generates the reports for a given dependency-check engine.
     1012  
         /**
          *
     1013  
          * Returns the key used to store the path to the output directory. When
          * @param engine a dependency-check engine
     1014  
          * generating the report in the <code>executeAggregateReport()</code> the
          * @param p the Maven project
     1015  
          * output directory should be obtained by using this key.
          * @param outputDir the directory path to write the report(s)
     1016  
          *
          * @throws ReportException thrown if there is an error writing the report
     1017  
          * @return the key used to store the path to the output directory
          */
     1018  
          */
     1019  
         protected String getOutputDirectoryContextKey() {
     1020  0
             return "dependency-output-dir-" + dataFileName;
         protected void writeReports(MavenEngine engine, MavenProject p, File outputDir) throws ReportException {
     1019  0
             DatabaseProperties prop = null;
     1020  0
             CveDB cve = null;
     1021  
         }
     1022  
     
     1023  
         /**
     1024  
          * Writes the scan data to disk. This is used to serialize the scan data
     1025  
          * between the "check" and "aggregate" phase.
     1026  
          *
     1027  
          * @param mp the mMven project for which the data file was created
             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 writeTo the directory to write the data file
                 }
     1029  
          * @param dependencies the list of dependencies to serialize
     1030  
          */
     1031  
         protected void writeDataFile(MavenProject mp, File writeTo, List<Dependency> dependencies) {
             } finally {
     1030  0
                 if (cve != null) {
     1031  0
                     cve.close();
     1032  
             File file;
                 }
     1033  
             //check to see if this was already written out
     1034  0
             if (mp.getContextValue(this.getDataFileContextKey()) == null) {
     1035  0
                 if (writeTo == null) {
     1036  0
                     file = new File(mp.getBuild().getDirectory());
     1037  0
                     file = new File(file, dataFileName);
     1038  
                 } else {
     1039  0
                     file = new File(writeTo, dataFileName);
     1040  
                 }
     1041  0
                 final File parent = file.getParentFile();
     1042  0
                 if (!parent.isDirectory() && !parent.mkdirs()) {
     1043  0
                     getLog().error(String.format("Directory '%s' does not exist and cannot be created; unable to write data file.",
     1044  0
                             parent.getAbsolutePath()));
     1045  
                 }
     1046  
     
     1047  0
                 ObjectOutputStream out = null;
     1048  
                 try {
     1049  0
                     if (dependencies != null) {
     1050  0
                         out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
     1051  0
                         out.writeObject(dependencies);
     1052  
                     }
     1053  0
                     if (getLog().isDebugEnabled()) {
     1054  0
                         getLog().debug(String.format("Serialized data file written to '%s' for %s, referenced by key %s",
     1055  0
                                 file.getAbsolutePath(), mp.getName(), this.getDataFileContextKey()));
     1056  
                     }
     1057  0
                     mp.setContextValue(this.getDataFileContextKey(), file.getAbsolutePath());
     1058  0
                 } catch (IOException ex) {
     1059  0
                     getLog().warn("Unable to create data file used for report aggregation; "
     1060  
                             + "if report aggregation is being used the results may be incomplete.");
     1061  0
                     if (getLog().isDebugEnabled()) {
     1062  0
                         getLog().debug(ex.getMessage(), ex);
     1063  
                     }
     1064  
                 } finally {
     1065  0
                     if (out != null) {
     1066  
                         try {
     1067  0
                             out.close();
     1068  0
                         } catch (IOException ex) {
     1069  0
                             if (getLog().isDebugEnabled()) {
     1070  0
                                 getLog().debug("ignore", ex);
     1071  
                             }
     1072  0
                         }
     1073  
                     }
     1074  
                 }
     1075  
             }
     1076  0
         }
     1077  
     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
             }
     1041  
     
     1078  
     1042  0
         }
     1043  
     
     1044  
         //<editor-fold defaultstate="collapsed" desc="Methods to fail build or show summary">
     1045  
         /**
     1079  
          * Reads the serialized scan data from disk. This is used to serialize the
     1080  
          * scan data between the "check" and "aggregate" phase.
     1081  
     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  
          * @param project the Maven project to read the data file from
          *
     1083  
          * @return a <code>MavenEngine</code> object populated with dependencies if
          * @param mp the Maven project for which the summary is shown
     1084  
          * the serialized data file exists; otherwise <code>null</code> is returned
          * @param dependencies a list of dependency objects
     1085  
          */
     1086  
         protected List<Dependency> readDataFile(MavenProject project) {
     1087  0
             final Object oPath = project.getContextValue(this.getDataFileContextKey());
     1088  0
             if (oPath == null) {
     1089  0
                 return null;
     1090  
             }
     1091  0
             List<Dependency> ret = null;
     1092  0
             final String path = (String) oPath;
     1093  
             //ObjectInputStream ois = null;
     1094  0
             ExpectedOjectInputStream ois = null;
         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  
             try {
     1096  
                 //ois = new ObjectInputStream(new FileInputStream(path));
     1097  0
                 ois = new ExpectedOjectInputStream(new FileInputStream(path),
     1098  
                         "java.util.ArrayList",
     1099  
                         "java.util.HashSet",
     1100  
                         "java.util.TreeSet",
     1101  
                         "java.lang.AbstractSet",
     1102  
                         "java.lang.AbstractCollection",
     1103  
                         "java.lang.Enum",
     1104  
                         "org.owasp.dependencycheck.dependency.Confidence",
     1105  
                         "org.owasp.dependencycheck.dependency.Dependency",
                         } 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  
                         "org.owasp.dependencycheck.dependency.Evidence",
     1107  
                         "org.owasp.dependencycheck.dependency.EvidenceCollection",
                             } else {
     1107  0
                                 summary.append(", ");
     1108  
                         "org.owasp.dependencycheck.dependency.Identifier",
     1109  
                         "org.owasp.dependencycheck.dependency.Reference",
     1110  
                         "org.owasp.dependencycheck.dependency.Vulnerability",
     1111  
                         "org.owasp.dependencycheck.dependency.VulnerabilityComparator",
                             }
     1109  0
                             summary.append(id.getValue());
     1110  0
                         }
     1111  0
                         summary.append(") : ").append(ids).append(NEW_LINE);
     1112  
                         "org.owasp.dependencycheck.dependency.VulnerableSoftware",
     1113  
                         "org.owasp.dependencycheck.data.cpe.IndexEntry");
     1114  
                 @SuppressWarnings("unchecked")
     1115  0
                 final List<Dependency> depList = (List<Dependency>) ois.readObject();
     1116  0
                 ret = depList;
     1117  0
             } catch (FileNotFoundException ex) {
                     }
     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  
                 //TODO fix logging
     1119  0
                 getLog().error("", ex);
     1120  0
             } catch (IOException ex) {
     1121  0
                 getLog().error("", ex);
     1122  0
             } catch (ClassNotFoundException ex) {
     1123  0
                 getLog().error("", ex);
     1124  
             } finally {
     1125  0
                 if (ois != null) {
     1126  
                     try {
     1127  0
                         ois.close();
     1128  0
                     } catch (IOException ex) {
     1129  0
                         getLog().error("", ex);
     1130  0
                     }
     1131  
                 }
     1132  
     1119  
             }
     1133  0
             return ret;
     1134  
         }
     1135  
     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  
     
     1260  
     }
    - + 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 a98e018a2..93804a910 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/48
    0%
    0/28
    6
    CheckMojo
    0%
    0/47
    0%
    0/28
    6
     
    @@ -128,7 +128,7 @@
         public boolean canGenerateReport() {
     56  0
             boolean isCapable = false;
     57  0
             for (Artifact a : getProject().getArtifacts()) {
    -  58  0
                 if (!excludeFromScan(a)) {
    +  58  0
                 if (!excludeFromScan(a.getScope())) {
     59  0
                     isCapable = true;
     60  0
                     break;
     61   @@ -178,119 +178,118 @@  88  0
                 getLog().error(msg);
     89  0
             }
     90  0
             if (engine != null) {
    -  91  0
                 scanArtifacts(getProject(), engine);
    +  91  0
                 ExceptionCollection exCol = scanArtifacts(getProject(), engine);
     92  0
                 if (engine.getDependencies().isEmpty()) {
     93  0
                     getLog().info("No dependencies were identified that could be analyzed by dependency-check");
     94  
                 } else {
    -  95  0
                     ExceptionCollection exCol = null;
    -  96   +  95  
                     try {
    -  97  0
                         engine.analyzeDependencies();
    -  98  0
                     } catch (ExceptionCollection ex) {
    -  99  0
                         if (this.isFailOnError() && ex.isFatal()) {
    -  100  0
                             throw new MojoExecutionException("One or more exceptions occured during analysis", ex);
    -  101   +  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);
    +  100  
                         }
    -  102  0
                         exCol = ex;
    -  103  0
                     }
    -  104  0
                     if (exCol == null || !exCol.isFatal()) {
    -  105   +  101  0
                         exCol = ex;
    +  102  0
                     }
    +  103  0
                     if (exCol == null || !exCol.isFatal()) {
    +  104  
                         try {
    -  106  0
                             writeReports(engine, getProject(), getCorrectOutputDirectory());
    -  107  0
                         } catch (ReportException ex) {
    -  108  0
                             if (this.isFailOnError()) {
    -  109  0
                                 if (exCol != null) {
    -  110  0
                                     exCol.addException(ex);
    -  111   +  105  0
                             writeReports(engine, getProject(), getCorrectOutputDirectory());
    +  106  0
                         } catch (ReportException ex) {
    +  107  0
                             if (this.isFailOnError()) {
    +  108  0
                                 if (exCol != null) {
    +  109  0
                                     exCol.addException(ex);
    +  110  
                                 } else {
    -  112  0
                                     exCol = new ExceptionCollection("Unable to write the dependency-check report", ex);
    -  113   +  111  0
                                     exCol = new ExceptionCollection("Unable to write the dependency-check report", ex);
    +  112  
                                 }
    -  114   +  113  
                             }
    -  115  0
                         }
    -  116  0
                         writeDataFile(getProject(), null, engine.getDependencies());
    -  117  0
                         showSummary(getProject(), engine.getDependencies());
    -  118  0
                         checkForFailure(engine.getDependencies());
    -  119  0
                         if (exCol != null && this.isFailOnError()) {
    -  120  0
                             throw new MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol);
    -  121   +  114  0
                         }
    +  115  0
                         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);
    +  120  
                         }
    -  122   +  121  
                     }
    -  123   +  122  
                 }
    -  124  0
                 engine.cleanup();
    -  125   +  123  0
                 engine.cleanup();
    +  124  
             }
    -  126  0
             Settings.cleanup();
    -  127  0
         }
    +  125  0
             Settings.cleanup();
    +  126  0
         }
    +  127   +
     
     128   -
     
    +
         /**
     129   -
         /**
    -  130  
          * The name of the report in the site.
    -  131   +  130  
          */
    -  132  0
         @SuppressWarnings("CanBeFinal")
    -  133   +  131  0
         @SuppressWarnings("CanBeFinal")
    +  132  
         @Parameter(property = "name", defaultValue = "dependency-check", required = true)
    -  134   +  133  
         private String name = "dependency-check";
    +  134   +
     
     135   -
     
    +
         /**
     136   -
         /**
    -  137  
          * Returns the report name.
    +  137   +
          *
     138   -
          *
    -  139  
          * @param locale the location
    -  140   +  139  
          * @return the report name
    +  140   +
          */
     141   -
          */
    +
         @Override
     142   -
         @Override
    -  143  
         public String getName(Locale locale) {
    -  144  0
             return name;
    +  143  0
             return name;
    +  144   +
         }
     145   -
         }
    +
     
     146   -
     
    -  147  
         /**
    -  148   +  147  
          * Gets the description of the Dependency-Check report to be displayed in
    -  149   +  148  
          * the Maven Generated Reports page.
    -  150   +  149  
          *
    -  151   +  150  
          * @param locale The Locale to get the description for
    -  152   +  151  
          * @return the description
    -  153   +  152  
          */
    -  154   +  153  
         @Override
    -  155   +  154  
         public String getDescription(Locale locale) {
    -  156  0
             return "Generates a report providing details on any published vulnerabilities within project dependencies. "
    -  157   +  155  0
             return "Generates a report providing details on any published vulnerabilities within project dependencies. "
    +  156  
                     + "This report is a best effort and may contain false positives and false negatives.";
    -  158   +  157  
         }
    -  159   +  158  
     
    -  160   +  159  
     }
    - + 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 066cdad4f..50fa47a62 100644 --- a/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.HelpMojo.html +++ b/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.HelpMojo.html @@ -770,6 +770,6 @@
     }
    - + 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 c9e1d1a2f..cadafd591 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 9f066b9cb..08ef1af31 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 8eb7f95c3..18161461b 100644 --- a/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.UpdateMojo.html +++ b/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.UpdateMojo.html @@ -223,6 +223,6 @@
     }
    - + diff --git a/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.slf4j.MavenLoggerAdapter.html b/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.slf4j.MavenLoggerAdapter.html index dd78d4f8b..d0acc8d71 100644 --- a/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.slf4j.MavenLoggerAdapter.html +++ b/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.slf4j.MavenLoggerAdapter.html @@ -131,14 +131,14 @@
         @Override
     60  
         public void trace(String msg) {
    -  61  1
             if (log != null) {
    +  61  3
             if (log != null) {
     62  0
                 log.debug(msg);
     63  
             } else {
    -  64  1
                 System.out.println(msg);
    +  64  3
                 System.out.println(msg);
     65  
             }
    -  66  1
         }
    +  66  3
         }
     67  
     
     68   @@ -218,14 +218,14 @@
         @Override
     117  
         public void debug(String msg) {
    -  118  4
             if (log != null) {
    +  118  8
             if (log != null) {
     119  0
                 log.debug(msg);
     120  
             } else {
    -  121  4
                 System.out.println(msg);
    +  121  8
                 System.out.println(msg);
     122  
             }
    -  123  4
         }
    +  123  8
         }
     124  
     
     125   @@ -551,6 +551,6 @@
     }
    - + diff --git a/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.slf4j.MavenLoggerFactory.html b/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.slf4j.MavenLoggerFactory.html index 485dc01a8..8b21552fd 100644 --- a/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.slf4j.MavenLoggerFactory.html +++ b/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.slf4j.MavenLoggerFactory.html @@ -127,6 +127,6 @@
     }
    - + diff --git a/dependency-check-maven/cobertura/org.slf4j.impl.StaticLoggerBinder.html b/dependency-check-maven/cobertura/org.slf4j.impl.StaticLoggerBinder.html index fddf7cce5..d3695a973 100644 --- a/dependency-check-maven/cobertura/org.slf4j.impl.StaticLoggerBinder.html +++ b/dependency-check-maven/cobertura/org.slf4j.impl.StaticLoggerBinder.html @@ -232,6 +232,6 @@
     }
    - + diff --git a/dependency-check-maven/configuration.html b/dependency-check-maven/configuration.html index f0707ad78..83c0060d6 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 @@ diff --git a/dependency-check-maven/dependency-analysis.html b/dependency-check-maven/dependency-analysis.html index 6db611958..8696f6f6b 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.2 +1.4.3 compile jar @@ -261,7 +261,7 @@ org.owasp dependency-check-utils -1.4.2 +1.4.3 compile jar @@ -315,6 +315,14 @@ jar false +org.apache.maven.shared +maven-dependency-tree +2.2 +compile + +jar +false + org.jmockit jmockit 1.24 @@ -322,7 +330,7 @@ jar false - + org.apache.maven.plugin-testing maven-plugin-testing-harness 3.3.0 @@ -330,7 +338,7 @@ jar false - + junit junit 4.12 @@ -341,7 +349,7 @@

    Used but undeclared dependencies

    - + @@ -349,7 +357,7 @@ - + @@ -357,6 +365,14 @@ + + + + + + + + diff --git a/dependency-check-maven/dependency-updates-report.html b/dependency-check-maven/dependency-updates-report.html index 82755f5c2..ce2ebea0e 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 @@ - + @@ -252,15 +252,15 @@ - + - + -
    GroupId ArtifactId VersionClassifier Type Optional
    org.slf4j slf4j-api 1.7.21 jar false
    org.eclipse.aetheraether-api1.0.2.v20150114compilejarfalse
    org.apache.maven maven-model
    # of dependencies using the latest version available25
    23
    # 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 update0
    1
    # of dependencies where the next version available is a minor version update7
    8
    # of dependencies where the next version available is a major version update1
    +2

    Dependency Management

    @@ -325,7 +325,7 @@ - + @@ -333,7 +333,7 @@ - + @@ -529,7 +529,7 @@ - + @@ -538,7 +538,7 @@ - + @@ -553,6 +553,18 @@ + + + + + + + + + + + + @@ -564,7 +576,7 @@ - + @@ -576,7 +588,7 @@ - + @@ -588,7 +600,7 @@ - + @@ -600,7 +612,7 @@ - + @@ -612,7 +624,7 @@ - + @@ -624,7 +636,7 @@ - + @@ -636,7 +648,7 @@ - + @@ -648,7 +660,7 @@ - + @@ -663,7 +675,7 @@

    Dependencies

    1.4.177
    com.sun.mail mailapi 1.5.5 jar 1.5.6
    org.apache.maven.plugin-tools maven-plugin-annotations 3.4jar 3.5
    org.apache.maven.sharedmaven-dependency-tree2.2jar3.0
    org.apache.velocity velocity
    org.glassfish javax.json
    org.hamcrest hamcrest-core
    org.jmockit jmockit 1.25
    org.jsoup jsoup
    org.slf4j slf4j-api
    org.slf4j slf4j-simple
    org.sonatype.plexus plexus-sec-dispatcher
    Status Group Id Artifact Id
    - + @@ -675,11 +687,23 @@ - + - + + + + + + + + + + + + + @@ -688,18 +712,6 @@ - - - - - - - - - - - - @@ -717,25 +729,25 @@

    ch.qos.logback:logback-classic

    Status Group Id Artifact IdNext Incremental Next Minor Next Major
    org.owasp dependency-check-core1.4.21.4.3compilejar
    org.owaspdependency-check-utils1.4.3 compile jar
    org.owaspdependency-check-utils1.4.2compilejar
    Status Group Id Artifact Id
    - + - + - + - + - + - + - +
    Status  No newer versions available.
    Group Id ch.qos.logback
    Artifact Id logback-classic
    Current Version 1.1.7
    Scope
    Classifier
    Type jar
    @@ -818,7 +830,7 @@ - + @@ -836,7 +848,10 @@ -
    Status No newer versions available.
     There is at least one newer incremental version available. Incremental updates are typically passive.
    Group Id com.sun.mail
    Typejar
    +jar + +Newer versions +1.5.6 Next Incremental

    commons-cli:commons-cli

    @@ -1061,7 +1076,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.lucene:lucene-core

    @@ -1088,7 +1103,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.lucene:lucene-queryparser

    @@ -1115,7 +1130,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.lucene:lucene-test-framework

    @@ -1142,7 +1157,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.maven:maven-core

    @@ -1244,7 +1259,7 @@
    - + @@ -1262,7 +1277,10 @@ -
    Status No newer versions available.
     There is at least one newer minor version available. Minor updates are sometimes passive.
    Group Id org.apache.maven.plugin-tools
    Typejar
    +jar + +Newer versions +3.5 Next Minor

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

    @@ -1288,6 +1306,33 @@
    Type jar
    +

    org.apache.maven.shared:maven-dependency-tree

    + + + + + + + + + + + + + + + + + + + + + + + + +
    Status There is at least one newer major version available. Major updates are rarely passive.
    Group Idorg.apache.maven.shared
    Artifact Idmaven-dependency-tree
    Current Version2.2
    Scope
    Classifier
    Typejar
    Newer versions3.0 Next Major
    +

    org.apache.velocity:velocity

    @@ -1385,7 +1430,7 @@ -
    jar
    Newer versions1.25 Next Minor
    +1.25 Next Minor
    1.26
    1.27 Latest Minor

    org.jsoup:jsoup

    @@ -1424,7 +1469,7 @@ - + @@ -1448,7 +1493,7 @@ - + diff --git a/dependency-check-maven/findbugs.html b/dependency-check-maven/findbugs.html index 90bf5ee82..06a743941 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 @@ diff --git a/dependency-check-maven/help-mojo.html b/dependency-check-maven/help-mojo.html index eb4eed6bc..453718592 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.2:help

    +

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

    Description:

    diff --git a/dependency-check-maven/index.html b/dependency-check-maven/index.html index 3da02ab8a..dc0f2d26c 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 @@ @@ -163,7 +163,7 @@ <plugin> <groupId>org.owasp</groupId> <artifactId>dependency-check-maven</artifactId> - <version>1.4.2</version> + <version>1.4.3</version> <executions> <execution> <goals> @@ -193,7 +193,7 @@ <plugin> <groupId>org.owasp</groupId> <artifactId>dependency-check-maven</artifactId> - <version>1.4.2</version> + <version>1.4.3</version> <reportSets> <reportSet> <reports> @@ -223,7 +223,7 @@ <plugin> <groupId>org.owasp</groupId> <artifactId>dependency-check-maven</artifactId> - <version>1.4.2</version> + <version>1.4.3</version> <configuration> <failBuildOnCVSS>8</failBuildOnCVSS> </configuration> @@ -256,7 +256,7 @@ <plugin> <groupId>org.owasp</groupId> <artifactId>dependency-check-maven</artifactId> - <version>1.4.2</version> + <version>1.4.3</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.2</version> + <version>1.4.3</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.2</version> + <version>1.4.3</version> <executions> <execution> <goals> diff --git a/dependency-check-maven/integration.html b/dependency-check-maven/integration.html index df329bac3..cfc4e9cd8 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 b440e4d15..bfdfa116b 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 ead3757c5..8eb17df6c 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 b8e26dee9..d2ca2b677 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 906023619..b7d5ad8eb 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 @@ @@ -299,7 +299,7 @@ have any known published vulnerabilities.
    dependency-check-core
    Current Version1.4.2
    1.4.3
    Scope compile
    dependency-check-utils
    Current Version1.4.2
    1.4.3
    Scope compile
    <plugin> <groupId>org.owasp</groupId> <artifactId>dependency-check-maven</artifactId> - <version>1.4.2</version> + <version>1.4.3</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.2</version> + <version>1.4.3</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.2</version> + <version>1.4.3</version> </plugin> ... </plugins> diff --git a/dependency-check-maven/plugin-updates-report.html b/dependency-check-maven/plugin-updates-report.html index 39340baf3..7887ce529 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 @@ diff --git a/dependency-check-maven/pmd.html b/dependency-check-maven/pmd.html index 33f103af2..a06b11df1 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. -774
    +897 diff --git a/dependency-check-maven/project-info.html b/dependency-check-maven/project-info.html index 28c1de9f6..48e1f8459 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 35432b2ee..ee18b2287 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 7595cf962..5fb857130 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.2 +1.4.3 Type maven-plugin diff --git a/dependency-check-maven/purge-mojo.html b/dependency-check-maven/purge-mojo.html index bc7272f9b..69ee01173 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.2:purge

    +

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

    Description:

    diff --git a/dependency-check-maven/source-repository.html b/dependency-check-maven/source-repository.html index 70e300903..5cb65077c 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 6c9123c61..a2f737f90 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.636
    +0.354

    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.636
    +0.354

    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.636

    +0.354

    Test Cases

    [Summary] [Package List] [Test Cases]

    @@ -326,7 +326,7 @@ function toggleDisplay(elementId) { testScanArtifacts -0

    +0.015
    diff --git a/dependency-check-maven/taglist.html b/dependency-check-maven/taglist.html index 66fae20d6..b84688b0b 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 @@ @@ -247,25 +247,19 @@ Tag strings used by tag class Todo Work -2 +1 todo, FIXME

    Each tag is detailed below:

    Todo Work

    -

    Number of occurrences found in the code: 2

    +

    Number of occurrences found in the code: 1

    - - - - - - -
    org.owasp.dependencycheck.maven.BaseDependencyCheckMojo Line
    fix logging1118
    org.owasp.dependencycheck.maven.BaseDependencyCheckMojoTestLine
    get this to work under JDK 1.866
    +1241 diff --git a/dependency-check-maven/team-list.html b/dependency-check-maven/team-list.html index 940d77421..e58aa7bb9 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 fdd494c45..fd8ce1734 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.2:update-only

    +

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

    Description:

    diff --git a/dependency-check-maven/xref-test/index.html b/dependency-check-maven/xref-test/index.html index c8670889a..35f4c3952 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.2 Reference + Dependency-Check Maven Plugin 1.4.3 Reference diff --git a/dependency-check-maven/xref-test/org/owasp/dependencycheck/maven/BaseDependencyCheckMojoTest.html b/dependency-check-maven/xref-test/org/owasp/dependencycheck/maven/BaseDependencyCheckMojoTest.html index 030c6a7d6..521a7e41d 100644 --- a/dependency-check-maven/xref-test/org/owasp/dependencycheck/maven/BaseDependencyCheckMojoTest.html +++ b/dependency-check-maven/xref-test/org/owasp/dependencycheck/maven/BaseDependencyCheckMojoTest.html @@ -41,97 +41,102 @@ 33 import org.apache.maven.project.MavenProject; 34 import static org.junit.Assert.assertFalse; 35 import static org.junit.Assert.assertTrue; -36 import org.junit.Test; -37 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; -38 import org.owasp.dependencycheck.utils.InvalidSettingException; -39 import org.owasp.dependencycheck.utils.Settings; -40 -41 /** -42 * -43 * @author Jeremy Long -44 */ -45 public class BaseDependencyCheckMojoTest extends BaseTest { -46 -47 /** -48 * Checks if the test can be run. The test in this class fail, presumable due to jmockit, if the JDK is 1.8+. -49 * -50 * @return true if the JDK is below 1.8. -51 */ -52 public boolean canRun() { -53 String version = System.getProperty("java.version"); -54 int length = version.indexOf('.', version.indexOf('.') + 1); -55 version = version.substring(0, length); -56 -57 double v = Double.parseDouble(version); -58 return v == 1.7; -59 } -60 -61 /** -62 * Test of scanArtifacts method, of class BaseDependencyCheckMojo. -63 */ -64 @Test -65 public void testScanArtifacts() throws DatabaseException, InvalidSettingException { -66 //TODO get this to work under JDK 1.8 -67 if (canRun()) { -68 MavenProject project = new MockUp<MavenProject>() { -69 @Mock -70 public Set<Artifact> getArtifacts() { -71 Set<Artifact> artifacts = new HashSet<Artifact>(); -72 Artifact a = new ArtifactStub(); -73 try { -74 File file = new File(Test.class.getProtectionDomain().getCodeSource().getLocation().toURI()); -75 a.setFile(file); -76 artifacts.add(a); -77 } catch (URISyntaxException ex) { -78 Logger.getLogger(BaseDependencyCheckMojoTest.class.getName()).log(Level.SEVERE, null, ex); -79 } -80 //File file = new File(this.getClass().getClassLoader().getResource("daytrader-ear-2.1.7.ear").getPath()); -81 -82 return artifacts; -83 } -84 -85 @Mock -86 public String getName() { -87 return "test-project"; -88 } -89 }.getMockInstance(); -90 -91 boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE); -92 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false); -93 MavenEngine engine = new MavenEngine(null, null); -94 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate); -95 -96 assertTrue(engine.getDependencies().isEmpty()); -97 BaseDependencyCheckMojoImpl instance = new BaseDependencyCheckMojoImpl(); -98 instance.scanArtifacts(project, engine); -99 assertFalse(engine.getDependencies().isEmpty()); -100 engine.cleanup(); -101 } -102 } -103 -104 public class BaseDependencyCheckMojoImpl extends BaseDependencyCheckMojo { -105 -106 @Override -107 public void runCheck() throws MojoExecutionException, MojoFailureException { -108 throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. -109 } +36 import org.junit.Assume; +37 import org.junit.Test; +38 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; +39 import org.owasp.dependencycheck.utils.InvalidSettingException; +40 import org.owasp.dependencycheck.utils.Settings; +41 +42 /** +43 * +44 * @author Jeremy Long +45 */ +46 public class BaseDependencyCheckMojoTest extends BaseTest { +47 +48 /** +49 * Checks if the test can be run. The test in this class fail, presumable +50 * due to jmockit, if the JDK is 1.8+. +51 * +52 * @return true if the JDK is below 1.8. +53 */ +54 public boolean canRun() { +55 String version = System.getProperty("java.version"); +56 int length = version.indexOf('.', version.indexOf('.') + 1); +57 version = version.substring(0, length); +58 +59 double v = Double.parseDouble(version); +60 return v == 1.7; +61 } +62 +63 /** +64 * Test of scanArtifacts method, of class BaseDependencyCheckMojo. +65 */ +66 @Test +67 public void testScanArtifacts() throws DatabaseException, InvalidSettingException { +68 if (canRun()) { +69 MavenProject project = new MockUp<MavenProject>() { +70 @Mock +71 public Set<Artifact> getArtifacts() { +72 Set<Artifact> artifacts = new HashSet<Artifact>(); +73 Artifact a = new ArtifactStub(); +74 try { +75 File file = new File(Test.class.getProtectionDomain().getCodeSource().getLocation().toURI()); +76 a.setFile(file); +77 artifacts.add(a); +78 } catch (URISyntaxException ex) { +79 Logger.getLogger(BaseDependencyCheckMojoTest.class.getName()).log(Level.SEVERE, null, ex); +80 } +81 //File file = new File(this.getClass().getClassLoader().getResource("daytrader-ear-2.1.7.ear").getPath()); +82 +83 return artifacts; +84 } +85 +86 @Mock +87 public String getName() { +88 return "test-project"; +89 } +90 }.getMockInstance(); +91 +92 boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE); +93 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false); +94 MavenEngine engine = new MavenEngine(null, null); +95 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate); +96 +97 assertTrue(engine.getDependencies().isEmpty()); +98 BaseDependencyCheckMojoImpl instance = new BaseDependencyCheckMojoImpl(); +99 try { //the mock above fails under some JDKs +100 instance.scanArtifacts(project, engine); +101 } catch (NullPointerException ex) { +102 Assume.assumeNoException(ex); +103 } +104 assertFalse(engine.getDependencies().isEmpty()); +105 engine.cleanup(); +106 } +107 } +108 +109 public class BaseDependencyCheckMojoImpl extends BaseDependencyCheckMojo { 110 111 @Override -112 public String getName(Locale locale) { -113 return "test implementation"; +112 public void runCheck() throws MojoExecutionException, MojoFailureException { +113 throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. 114 } 115 116 @Override -117 public String getDescription(Locale locale) { +117 public String getName(Locale locale) { 118 return "test implementation"; 119 } 120 121 @Override -122 public boolean canGenerateReport() { -123 throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. +122 public String getDescription(Locale locale) { +123 return "test implementation"; 124 } -125 } -126 } +125 +126 @Override +127 public boolean canGenerateReport() { +128 throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. +129 } +130 } +131 }
    diff --git a/dependency-check-maven/xref-test/org/owasp/dependencycheck/maven/BaseTest.html b/dependency-check-maven/xref-test/org/owasp/dependencycheck/maven/BaseTest.html index a0defad9f..cab12c95c 100644 --- a/dependency-check-maven/xref-test/org/owasp/dependencycheck/maven/BaseTest.html +++ b/dependency-check-maven/xref-test/org/owasp/dependencycheck/maven/BaseTest.html @@ -25,34 +25,49 @@ 17 */ 18 package org.owasp.dependencycheck.maven; 19 -20 import java.io.InputStream; -21 import org.junit.AfterClass; -22 import org.junit.BeforeClass; -23 import org.owasp.dependencycheck.utils.Settings; -24 -25 /** -26 * -27 * @author Jeremy Long -28 */ -29 public class BaseTest { -30 -31 /** -32 * The properties file location. -33 */ -34 public static final String PROPERTIES_FILE = "mojo.properties"; -35 -36 @BeforeClass -37 public static void setUpClass() throws Exception { -38 Settings.initialize(); -39 InputStream mojoProperties = BaseTest.class.getClassLoader().getResourceAsStream(BaseTest.PROPERTIES_FILE); -40 Settings.mergeProperties(mojoProperties); -41 } -42 -43 @AfterClass -44 public static void tearDownClass() throws Exception { -45 Settings.cleanup(true); -46 } -47 } +20 import java.io.IOException; +21 import java.io.InputStream; +22 import java.util.logging.Level; +23 import java.util.logging.Logger; +24 import org.junit.AfterClass; +25 import org.junit.BeforeClass; +26 import org.owasp.dependencycheck.utils.Settings; +27 +28 /** +29 * +30 * @author Jeremy Long +31 */ +32 public class BaseTest { +33 +34 /** +35 * The properties file location. +36 */ +37 public static final String PROPERTIES_FILE = "mojo.properties"; +38 +39 @BeforeClass +40 public static void setUpClass() throws Exception { +41 Settings.initialize(); +42 InputStream mojoProperties = null; +43 try { +44 mojoProperties = BaseTest.class.getClassLoader().getResourceAsStream(BaseTest.PROPERTIES_FILE); +45 Settings.mergeProperties(mojoProperties); +46 } finally { +47 if (mojoProperties != null) { +48 try { +49 mojoProperties.close(); +50 } catch (IOException ex) { +51 Logger.getLogger(BaseTest.class.getName()).log(Level.SEVERE, null, ex); +52 } +53 } +54 } +55 +56 } +57 +58 @AfterClass +59 public static void tearDownClass() throws Exception { +60 Settings.cleanup(true); +61 } +62 }
    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 73d2702f4..5d43458b4 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.2 Reference Package org.owasp.dependencycheck.maven + Dependency-Check Maven Plugin 1.4.3 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 9cd96733e..14de4149a 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.2 Reference Package org.owasp.dependencycheck.maven + Dependency-Check Maven Plugin 1.4.3 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 5c34377a7..ac70d26af 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.2 Reference + Dependency-Check Maven Plugin 1.4.3 Reference diff --git a/dependency-check-maven/xref-test/overview-summary.html b/dependency-check-maven/xref-test/overview-summary.html index 111abb945..84884c7cb 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.2 Reference + Dependency-Check Maven Plugin 1.4.3 Reference @@ -24,7 +24,7 @@ -

    Dependency-Check Maven Plugin 1.4.2 Reference

    +

    Dependency-Check Maven Plugin 1.4.3 Reference

    diff --git a/dependency-check-maven/xref/index.html b/dependency-check-maven/xref/index.html index c8670889a..35f4c3952 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.2 Reference + Dependency-Check Maven Plugin 1.4.3 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 16feec78c..0614078b2 100644 --- a/dependency-check-maven/xref/org/owasp/dependencycheck/maven/AggregateMojo.html +++ b/dependency-check-maven/xref/org/owasp/dependencycheck/maven/AggregateMojo.html @@ -27,366 +27,273 @@ 1920import java.io.File; 21import java.io.IOException; -22import java.util.ArrayList; -23import java.util.Collections; -24import java.util.HashSet; -25import java.util.List; -26import java.util.Locale; -27import java.util.Set; -28import org.apache.maven.plugin.MojoExecutionException; -29import org.apache.maven.plugin.MojoFailureException; -30import org.apache.maven.plugins.annotations.LifecyclePhase; -31import org.apache.maven.plugins.annotations.Mojo; -32import org.apache.maven.plugins.annotations.Parameter; -33import org.apache.maven.plugins.annotations.ResolutionScope; -34import org.apache.maven.project.MavenProject; -35import org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer; -36import org.owasp.dependencycheck.analyzer.exception.AnalysisException; -37import org.owasp.dependencycheck.data.nvdcve.DatabaseException; -38import org.owasp.dependencycheck.dependency.Dependency; -39import org.owasp.dependencycheck.exception.ExceptionCollection; -40import org.owasp.dependencycheck.exception.ReportException; -41import org.owasp.dependencycheck.utils.Settings; -42 -43/** -44 * Maven Plugin that checks project dependencies and the dependencies of all -45 * child modules to see if they have any known published vulnerabilities. -46 * -47 * @author Jeremy Long -48 */ -49 @Mojo( -50 name = "aggregate", -51 defaultPhase = LifecyclePhase.VERIFY, -52/*aggregator = true,*/ -53 threadSafe = false, -54 requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, -55 requiresOnline = true -56 ) -57publicclassAggregateMojoextendsBaseDependencyCheckMojo { -58 -59/** -60 * The key to store aggregate exception in the root Maven execution context. -61 */ -62privatestaticfinal String AGGREGATE_EXCEPTIONS = "AggregateExceptions"; -63 -64/** -65 * Executes the aggregate dependency-check goal. This runs dependency-check -66 * and generates the subsequent reports. -67 * -68 * @throws MojoExecutionException thrown if there is ane exception running -69 * the mojo -70 * @throws MojoFailureException thrown if dependency-check is configured to -71 * fail the build -72 */ -73 @Override -74publicvoid runCheck() throws MojoExecutionException, MojoFailureException { -75finalMavenEngine engine = generateDataFile(); -76if (engine == null) { -77return; -78 } -79 -80if (getProject() == getLastProject()) { -81//ensure that the .ser file was created for each. -82for (MavenProject current : getReactorProjects()) { -83final File dataFile = getDataFile(current); -84if (dataFile == null && !skipProject(current)) { //dc was never run on this project. write the ser to the target. -85 getLog().error(String.format("Module '%s' did not execute dependency-check; an attempt will be made to perform " -86 + "the check but dependencies may be missed resulting in false negatives.", current.getName())); -87 generateDataFile(engine, current); -88 } -89 } -90for (MavenProject current : getReactorProjects()) { -91 List<Dependency> dependencies = readDataFile(current); -92if (dependencies == null) { -93 dependencies = new ArrayList<Dependency>(); -94 } -95final Set<MavenProject> childProjects = getDescendants(current); -96for (MavenProject reportOn : childProjects) { -97final List<Dependency> childDeps = readDataFile(reportOn); -98if (childDeps != null && !childDeps.isEmpty()) { -99if (getLog().isDebugEnabled()) { -100 getLog().debug(String.format("Adding %d dependencies from %s", childDeps.size(), reportOn.getName())); -101 } -102 dependencies.addAll(childDeps); -103 } elseif (getLog().isDebugEnabled()) { -104 getLog().debug(String.format("No dependencies read for %s", reportOn.getName())); -105 } -106 } -107 engine.getDependencies().clear(); -108 engine.getDependencies().addAll(dependencies); -109final DependencyBundlingAnalyzer bundler = new DependencyBundlingAnalyzer(); -110try { -111if (getLog().isDebugEnabled()) { -112 getLog().debug(String.format("Dependency count pre-bundler: %s", engine.getDependencies().size())); -113 } -114 bundler.analyze(null, engine); -115if (getLog().isDebugEnabled()) { -116 getLog().debug(String.format("Dependency count post-bundler: %s", engine.getDependencies().size())); -117 } -118 } catch (AnalysisException ex) { -119 getLog().warn("An error occurred grouping the dependencies; duplicate entries may exist in the report", ex); -120 getLog().debug("Bundling Exception", ex); -121 } -122 -123 File outputDir = getCorrectOutputDirectory(current); -124if (outputDir == null) { -125//in some regards we shouldn't be writting this, but we are anyway. -126//we shouldn't write this because nothing is configured to generate this report. -127 outputDir = new File(current.getBuild().getDirectory()); -128 } -129try { -130 writeReports(engine, current, outputDir); -131 } catch (ReportException ex) { -132 ExceptionCollection exCol = (ExceptionCollection) engine.getExecutionRoot().getContextValue(AGGREGATE_EXCEPTIONS); -133if (exCol == null) { -134 exCol = new ExceptionCollection("Error writing aggregate report", ex); -135 } else { -136 exCol.addException(ex); -137 } -138if (this.isFailOnError()) { -139thrownew MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol); -140 } else { -141 getLog().debug("One or more exceptions occured during dependency-check analysis", exCol); -142 } -143 } -144 } -145 } -146 engine.cleanup(); -147 Settings.cleanup(); -148 } -149 -150/** -151 * Gets the last project in the reactor - taking into account skipped -152 * projects. -153 * -154 * @return the last project in the reactor -155 */ -156private MavenProject getLastProject() { -157for (int x = getReactorProjects().size() - 1; x >= 0; x--) { -158final MavenProject p = getReactorProjects().get(x); -159if (!skipProject(p)) { -160return p; -161 } -162 } -163returnnull; -164 } -165 -166/** -167 * Tests if the project is being skipped in the Maven site report. -168 * -169 * @param project a project in the reactor -170 * @return true if the project is skipped; otherwise false -171 */ -172privateboolean skipProject(MavenProject project) { -173final String skip = (String) project.getProperties().get("maven.site.skip"); -174return"true".equalsIgnoreCase(skip) && isGeneratingSite(); -175 } +22import java.util.Collections; +23import java.util.HashSet; +24import java.util.Locale; +25import java.util.Set; +26import org.apache.maven.plugin.MojoExecutionException; +27import org.apache.maven.plugin.MojoFailureException; +28import org.apache.maven.plugins.annotations.LifecyclePhase; +29import org.apache.maven.plugins.annotations.Mojo; +30import org.apache.maven.plugins.annotations.Parameter; +31import org.apache.maven.plugins.annotations.ResolutionScope; +32import org.apache.maven.project.MavenProject; +33import org.owasp.dependencycheck.data.nvdcve.DatabaseException; +34import org.owasp.dependencycheck.exception.ExceptionCollection; +35import org.owasp.dependencycheck.exception.ReportException; +36import org.owasp.dependencycheck.utils.Settings; +37 +38/** +39 * Maven Plugin that checks project dependencies and the dependencies of all +40 * child modules to see if they have any known published vulnerabilities. +41 * +42 * @author Jeremy Long +43 */ +44 @Mojo( +45 name = "aggregate", +46 defaultPhase = LifecyclePhase.VERIFY, +47 aggregator = true, +48 threadSafe = false, +49 requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, +50 requiresOnline = true +51 ) +52publicclassAggregateMojoextendsBaseDependencyCheckMojo { +53 +54/** +55 * Executes the aggregate dependency-check goal. This runs dependency-check +56 * and generates the subsequent reports. +57 * +58 * @throws MojoExecutionException thrown if there is ane exception running +59 * the mojo +60 * @throws MojoFailureException thrown if dependency-check is configured to +61 * fail the build +62 */ +63 @Override +64publicvoid runCheck() throws MojoExecutionException, MojoFailureException { +65finalMavenEngine engine = loadEngine(); +66if (engine == null) { +67return; +68 } +69 +70 ExceptionCollection exCol = scanArtifacts(getProject(), engine); +71 +72for (MavenProject childProject : getDescendants(this.getProject())) { +73final ExceptionCollection ex = scanArtifacts(childProject, engine); +74if (ex != null) { +75if (exCol == null) { +76 exCol = ex; +77 } +78 exCol.getExceptions().addAll(ex.getExceptions()); +79if (ex.isFatal()) { +80 exCol.setFatal(true); +81 } +82 } +83 } +84 +85try { +86 engine.analyzeDependencies(); +87 } catch (ExceptionCollection ex) { +88if (exCol == null) { +89 exCol = ex; +90 } elseif (ex.isFatal()) { +91 exCol.setFatal(true); +92 exCol.getExceptions().addAll(ex.getExceptions()); +93 } +94if (exCol.isFatal()) { +95final String msg = String.format("Fatal exception(s) analyzing %s", getProject().getName()); +96if (this.isFailOnError()) { +97thrownew MojoExecutionException(msg, exCol); +98 } +99 getLog().error(msg); +100if (getLog().isDebugEnabled()) { +101 getLog().debug(exCol); +102 } +103return; +104 } else { +105final String msg = String.format("Exception(s) analyzing %s", getProject().getName()); +106if (getLog().isDebugEnabled()) { +107 getLog().debug(msg, exCol); +108 } +109 } +110 } +111 File outputDir = getCorrectOutputDirectory(this.getProject()); +112if (outputDir == null) { +113//in some regards we shouldn't be writting this, but we are anyway. +114//we shouldn't write this because nothing is configured to generate this report. +115 outputDir = new File(this.getProject().getBuild().getDirectory()); +116 } +117try { +118 writeReports(engine, this.getProject(), outputDir); +119 } catch (ReportException ex) { +120if (exCol == null) { +121 exCol = new ExceptionCollection("Error writing aggregate report", ex); +122 } else { +123 exCol.addException(ex); +124 } +125if (this.isFailOnError()) { +126thrownew MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol); +127 } else { +128 getLog().debug("One or more exceptions occured during dependency-check analysis", exCol); +129 } +130 } +131 showSummary(this.getProject(), engine.getDependencies()); +132 checkForFailure(engine.getDependencies()); +133 engine.cleanup(); +134 Settings.cleanup(); +135 } +136 +137/** +138 * Returns a set containing all the descendant projects of the given +139 * project. +140 * +141 * @param project the project for which all descendants will be returned +142 * @return the set of descendant projects +143 */ +144protected Set<MavenProject> getDescendants(MavenProject project) { +145if (project == null) { +146return Collections.emptySet(); +147 } +148final Set<MavenProject> descendants = new HashSet<MavenProject>(); +149int size = 0; +150if (getLog().isDebugEnabled()) { +151 getLog().debug(String.format("Collecting descendants of %s", project.getName())); +152 } +153for (String m : project.getModules()) { +154for (MavenProject mod : getReactorProjects()) { +155try { +156 File mpp = new File(project.getBasedir(), m); +157 mpp = mpp.getCanonicalFile(); +158if (mpp.compareTo(mod.getBasedir()) == 0 && descendants.add(mod) +159 && getLog().isDebugEnabled()) { +160 getLog().debug(String.format("Decendent module %s added", mod.getName())); +161 +162 } +163 } catch (IOException ex) { +164if (getLog().isDebugEnabled()) { +165 getLog().debug("Unable to determine module path", ex); +166 } +167 } +168 } +169 } +170do { +171 size = descendants.size(); +172for (MavenProject p : getReactorProjects()) { +173if (project.equals(p.getParent()) || descendants.contains(p.getParent())) { +174if (descendants.add(p) && getLog().isDebugEnabled()) { +175 getLog().debug(String.format("Decendent %s added", p.getName())); 176 -177/** -178 * Returns a set containing all the descendant projects of the given -179 * project. -180 * -181 * @param project the project for which all descendants will be returned -182 * @return the set of descendant projects -183 */ -184protected Set<MavenProject> getDescendants(MavenProject project) { -185if (project == null) { -186return Collections.emptySet(); -187 } -188final Set<MavenProject> descendants = new HashSet<MavenProject>(); -189int size = 0; -190if (getLog().isDebugEnabled()) { -191 getLog().debug(String.format("Collecting descendants of %s", project.getName())); -192 } -193for (String m : project.getModules()) { -194for (MavenProject mod : getReactorProjects()) { -195try { -196 File mpp = new File(project.getBasedir(), m); -197 mpp = mpp.getCanonicalFile(); -198if (mpp.compareTo(mod.getBasedir()) == 0 && descendants.add(mod) -199 && getLog().isDebugEnabled()) { -200 getLog().debug(String.format("Decendent module %s added", mod.getName())); -201 -202 } -203 } catch (IOException ex) { -204if (getLog().isDebugEnabled()) { -205 getLog().debug("Unable to determine module path", ex); -206 } -207 } -208 } -209 } -210do { -211 size = descendants.size(); -212for (MavenProject p : getReactorProjects()) { -213if (project.equals(p.getParent()) || descendants.contains(p.getParent())) { -214if (descendants.add(p) && getLog().isDebugEnabled()) { -215 getLog().debug(String.format("Decendent %s added", p.getName())); -216 -217 } -218for (MavenProject modTest : getReactorProjects()) { -219if (p.getModules() != null && p.getModules().contains(modTest.getName()) -220 && descendants.add(modTest) -221 && getLog().isDebugEnabled()) { -222 getLog().debug(String.format("Decendent %s added", modTest.getName())); -223 } -224 } -225 } -226final Set<MavenProject> addedDescendants = new HashSet<MavenProject>(); -227for (MavenProject dec : descendants) { -228for (String mod : dec.getModules()) { -229try { -230 File mpp = new File(dec.getBasedir(), mod); -231 mpp = mpp.getCanonicalFile(); -232if (mpp.compareTo(p.getBasedir()) == 0) { -233 addedDescendants.add(p); -234 } -235 } catch (IOException ex) { -236if (getLog().isDebugEnabled()) { -237 getLog().debug("Unable to determine module path", ex); -238 } -239 } -240 } -241 } -242for (MavenProject addedDescendant : addedDescendants) { -243if (descendants.add(addedDescendant) && getLog().isDebugEnabled()) { -244 getLog().debug(String.format("Decendent module %s added", addedDescendant.getName())); -245 } -246 } -247 } -248 } while (size != 0 && size != descendants.size()); -249if (getLog().isDebugEnabled()) { -250 getLog().debug(String.format("%s has %d children", project, descendants.size())); -251 } -252return descendants; -253 } -254 -255/** -256 * Test if the project has pom packaging -257 * -258 * @param mavenProject Project to test -259 * @return <code>true</code> if it has a pom packaging; otherwise -260 * <code>false</code> -261 */ -262protectedboolean isMultiModule(MavenProject mavenProject) { -263return"pom".equals(mavenProject.getPackaging()); -264 } -265 -266/** -267 * Initializes the engine, runs a scan, and writes the serialized -268 * dependencies to disk. -269 * -270 * @return the MavenEngine used to execute dependency-check -271 * @throws MojoExecutionException thrown if there is an exception running -272 * the mojo -273 * @throws MojoFailureException thrown if dependency-check is configured to -274 * fail the build if severe CVEs are identified. -275 */ -276protectedMavenEngine generateDataFile() throws MojoExecutionException, MojoFailureException { -277MavenEngine engine = null; -278try { -279 engine = initializeEngine(); -280 } catch (DatabaseException ex) { -281if (getLog().isDebugEnabled()) { -282 getLog().debug("Database connection error", ex); -283 } -284final String msg = "An exception occured connecting to the local database. Please see the log file for more details."; -285if (this.isFailOnError()) { -286thrownew MojoExecutionException(msg, ex); -287 } -288 getLog().error(msg, ex); -289returnnull; -290 } -291return generateDataFile(engine, getProject()); -292 } -293 -294/** -295 * Runs dependency-check's MavenEngine and writes the serialized -296 * dependencies to disk. -297 * -298 * @param engine the MavenEngine to use when scanning. -299 * @param project the project to scan and generate the data file for -300 * @return the MavenEngine used to execute dependency-check -301 * @throws MojoExecutionException thrown if there is an exception running -302 * the mojo -303 * @throws MojoFailureException thrown if dependency-check is configured to -304 * fail the build if severe CVEs are identified. -305 */ -306protectedMavenEngine generateDataFile(MavenEngine engine, MavenProject project) throws MojoExecutionException, MojoFailureException { -307if (getLog().isDebugEnabled()) { -308 getLog().debug(String.format("Begin Scanning: %s", project.getName())); -309 } -310 engine.getDependencies().clear(); -311 engine.resetFileTypeAnalyzers(); -312 scanArtifacts(project, engine); -313try { -314 engine.analyzeDependencies(); -315 } catch (ExceptionCollection ex) { -316 ExceptionCollection col = (ExceptionCollection) engine.getExecutionRoot().getContextValue(AGGREGATE_EXCEPTIONS); -317if (col == null) { -318 col = ex; -319 } elseif (ex.isFatal()) { -320 col.setFatal(true); -321 col.getExceptions().addAll(ex.getExceptions()); -322 } -323if (col.isFatal()) { -324final String msg = String.format("Fatal exception(s) analyzing %s", project.getName()); -325if (this.isFailOnError()) { -326thrownew MojoExecutionException(msg, ex); -327 } -328 getLog().error(msg, col); -329returnnull; -330 } else { -331final String msg = String.format("Exception(s) analyzing %s", project.getName()); -332if (getLog().isDebugEnabled()) { -333 getLog().debug(msg, ex); -334 } -335 engine.getExecutionRoot().setContextValue(AGGREGATE_EXCEPTIONS, col); -336 } -337 } -338final File target = new File(project.getBuild().getDirectory()); -339 writeDataFile(project, target, engine.getDependencies()); -340 showSummary(project, engine.getDependencies()); -341 checkForFailure(engine.getDependencies()); -342return engine; -343 } -344 -345 @Override -346publicboolean canGenerateReport() { -347returntrue; //aggregate always returns true for now - we can look at a more complicated/acurate solution later -348 } -349 -350/** -351 * The name of the report in the site. -352 */ -353 @SuppressWarnings("CanBeFinal") -354 @Parameter(property = "name", defaultValue = "dependency-check:aggregate", required = true) -355private String name = "dependency-check:aggregate"; -356 -357/** -358 * Returns the report name. -359 * -360 * @param locale the location -361 * @return the report name -362 */ -363 @Override -364public String getName(Locale locale) { -365return name; -366 } -367 -368/** -369 * Gets the description of the Dependency-Check report to be displayed in -370 * the Maven Generated Reports page. -371 * -372 * @param locale The Locale to get the description for -373 * @return the description -374 */ -375 @Override -376public String getDescription(Locale locale) { -377return"Generates an aggregate report of all child Maven projects providing details on any " -378 + "published vulnerabilities within project dependencies. This report is a best " -379 + "effort and may contain false positives and false negatives."; -380 } -381 } +177 } +178for (MavenProject modTest : getReactorProjects()) { +179if (p.getModules() != null && p.getModules().contains(modTest.getName()) +180 && descendants.add(modTest) +181 && getLog().isDebugEnabled()) { +182 getLog().debug(String.format("Decendent %s added", modTest.getName())); +183 } +184 } +185 } +186final Set<MavenProject> addedDescendants = new HashSet<MavenProject>(); +187for (MavenProject dec : descendants) { +188for (String mod : dec.getModules()) { +189try { +190 File mpp = new File(dec.getBasedir(), mod); +191 mpp = mpp.getCanonicalFile(); +192if (mpp.compareTo(p.getBasedir()) == 0) { +193 addedDescendants.add(p); +194 } +195 } catch (IOException ex) { +196if (getLog().isDebugEnabled()) { +197 getLog().debug("Unable to determine module path", ex); +198 } +199 } +200 } +201 } +202for (MavenProject addedDescendant : addedDescendants) { +203if (descendants.add(addedDescendant) && getLog().isDebugEnabled()) { +204 getLog().debug(String.format("Decendent module %s added", addedDescendant.getName())); +205 } +206 } +207 } +208 } while (size != 0 && size != descendants.size()); +209if (getLog().isDebugEnabled()) { +210 getLog().debug(String.format("%s has %d children", project, descendants.size())); +211 } +212return descendants; +213 } +214 +215/** +216 * Test if the project has pom packaging +217 * +218 * @param mavenProject Project to test +219 * @return <code>true</code> if it has a pom packaging; otherwise +220 * <code>false</code> +221 */ +222protectedboolean isMultiModule(MavenProject mavenProject) { +223return"pom".equals(mavenProject.getPackaging()); +224 } +225 +226/** +227 * Initializes the engine. +228 * +229 * @return the MavenEngine used to execute dependency-check +230 * @throws MojoExecutionException thrown if there is an exception running +231 * the Mojo +232 * @throws MojoFailureException thrown if dependency-check is configured to +233 * fail the build if severe CVEs are identified. +234 */ +235protectedMavenEngine loadEngine() throws MojoExecutionException, MojoFailureException { +236MavenEngine engine = null; +237try { +238 engine = initializeEngine(); +239 } catch (DatabaseException ex) { +240if (getLog().isDebugEnabled()) { +241 getLog().debug("Database connection error", ex); +242 } +243final String msg = "An exception occured connecting to the local database. Please see the log file for more details."; +244if (this.isFailOnError()) { +245thrownew MojoExecutionException(msg, ex); +246 } +247 getLog().error(msg, ex); +248 } +249return engine; +250 } +251 +252 @Override +253publicboolean canGenerateReport() { +254returntrue; //aggregate always returns true for now - we can look at a more complicated/acurate solution later +255 } +256 +257/** +258 * The name of the report in the site. +259 */ +260 @SuppressWarnings("CanBeFinal") +261 @Parameter(property = "name", defaultValue = "dependency-check:aggregate", required = true) +262private String name = "dependency-check:aggregate"; +263 +264/** +265 * Returns the report name. +266 * +267 * @param locale the location +268 * @return the report name +269 */ +270 @Override +271public String getName(Locale locale) { +272return name; +273 } +274 +275/** +276 * Gets the description of the Dependency-Check report to be displayed in +277 * the Maven Generated Reports page. +278 * +279 * @param locale The Locale to get the description for +280 * @return the description +281 */ +282 @Override +283public String getDescription(Locale locale) { +284return"Generates an aggregate report of all child Maven projects providing details on any " +285 + "published vulnerabilities within project dependencies. This report is a best " +286 + "effort and may contain false positives and false negatives."; +287 } +288 }
    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 72887c849..a55dc16f6 100644 --- a/dependency-check-maven/xref/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.html +++ b/dependency-check-maven/xref/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.html @@ -35,7 +35,7 @@ 27import java.io.ObjectOutputStream; 28import java.util.List; 29import java.util.Locale; -30import org.apache.maven.artifact.Artifact; +30import org.eclipse.aether.artifact.Artifact; 31import org.apache.maven.doxia.sink.Sink; 32import org.apache.maven.plugin.AbstractMojo; 33import org.apache.maven.plugin.MojoExecutionException; @@ -47,1101 +47,1225 @@ 39import org.apache.maven.reporting.MavenReportException; 40import org.apache.maven.settings.Proxy; 41import org.apache.maven.settings.Server; -42import org.owasp.dependencycheck.data.nexus.MavenArtifact; -43import org.owasp.dependencycheck.data.nvdcve.CveDB; -44import org.owasp.dependencycheck.data.nvdcve.DatabaseException; -45import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties; -46import org.owasp.dependencycheck.dependency.Confidence; -47import org.owasp.dependencycheck.dependency.Dependency; -48import org.owasp.dependencycheck.dependency.Identifier; -49import org.owasp.dependencycheck.dependency.Vulnerability; -50import org.owasp.dependencycheck.exception.ReportException; -51import org.owasp.dependencycheck.reporting.ReportGenerator; -52import org.owasp.dependencycheck.utils.ExpectedOjectInputStream; -53import org.owasp.dependencycheck.utils.Settings; -54import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher; -55import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher; -56import org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException; -57 -58/** -59 * -60 * @author Jeremy Long -61 */ -62publicabstractclassBaseDependencyCheckMojoextends AbstractMojo implements MavenReport { -63 -64//<editor-fold defaultstate="collapsed" desc="Private fields"> -65/** -66 * The properties file location. -67 */ -68privatestaticfinal String PROPERTIES_FILE = "mojo.properties"; -69/** -70 * System specific new line character. -71 */ -72privatestaticfinal String NEW_LINE = System.getProperty("line.separator", "\n").intern(); -73//</editor-fold> -74// <editor-fold defaultstate="collapsed" desc="Maven bound parameters and components"> -75/** -76 * Sets whether or not the external report format should be used. -77 */ -78 @Parameter(property = "metaFileName", defaultValue = "dependency-check.ser", required = true) -79private String dataFileName; +42import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder; +43import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException; +44import org.apache.maven.shared.dependency.graph.DependencyNode; +45import org.eclipse.aether.RepositorySystem; +46import org.eclipse.aether.RepositorySystemSession; +47import org.eclipse.aether.artifact.DefaultArtifact; +48import org.eclipse.aether.repository.RemoteRepository; +49import org.eclipse.aether.resolution.ArtifactRequest; +50import org.eclipse.aether.resolution.ArtifactResolutionException; +51import org.eclipse.aether.resolution.ArtifactResult; +52import org.owasp.dependencycheck.data.nexus.MavenArtifact; +53import org.owasp.dependencycheck.data.nvdcve.CveDB; +54import org.owasp.dependencycheck.data.nvdcve.DatabaseException; +55import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties; +56import org.owasp.dependencycheck.dependency.Confidence; +57import org.owasp.dependencycheck.dependency.Dependency; +58import org.owasp.dependencycheck.dependency.Identifier; +59import org.owasp.dependencycheck.dependency.Vulnerability; +60import org.owasp.dependencycheck.exception.ExceptionCollection; +61import org.owasp.dependencycheck.exception.ReportException; +62import org.owasp.dependencycheck.reporting.ReportGenerator; +63import org.owasp.dependencycheck.utils.ExpectedOjectInputStream; +64import org.owasp.dependencycheck.utils.Settings; +65import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher; +66import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher; +67import org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException; +68 +69/** +70 * +71 * @author Jeremy Long +72 */ +73publicabstractclassBaseDependencyCheckMojoextends AbstractMojo implements MavenReport { +74 +75//<editor-fold defaultstate="collapsed" desc="Private fields"> +76/** +77 * The properties file location. +78 */ +79privatestaticfinal String PROPERTIES_FILE = "mojo.properties"; 80/** -81 * Sets whether or not the external report format should be used. +81 * System specific new line character.82 */ -83 @Parameter(property = "failOnError", defaultValue = "true", required = true) -84privateboolean failOnError; -85 +83privatestaticfinal String NEW_LINE = System.getProperty("line.separator", "\n").intern(); +84//</editor-fold> +85// <editor-fold defaultstate="collapsed" desc="Maven bound parameters and components">86/** -87 * Returns if the mojo should fail the build if an exception occurs. -88 * -89 * @return whether or not the mojo should fail the build -90 */ -91protectedboolean isFailOnError() { -92return failOnError; -93 } -94 -95/** -96 * The Maven Project Object. -97 */ -98 @Parameter(property = "project", required = true, readonly = true) -99private MavenProject project; -100/** -101 * List of Maven project of the current build -102 */ -103 @Parameter(readonly = true, required = true, property = "reactorProjects") -104private List<MavenProject> reactorProjects; +87 * Sets whether or not the external report format should be used. +88 */ +89 @Parameter(property = "metaFileName", defaultValue = "dependency-check.ser", required = true) +90private String dataFileName; +91/** +92 * Sets whether or not the external report format should be used. +93 */ +94 @Parameter(property = "failOnError", defaultValue = "true", required = true) +95privateboolean failOnError; +96 +97/** +98 * Returns if the mojo should fail the build if an exception occurs. +99 * +100 * @return whether or not the mojo should fail the build +101 */ +102protectedboolean isFailOnError() { +103return failOnError; +104 } 105106/** -107 * The output directory. This generally maps to "target". +107 * The Maven Project Object.108 */ -109 @Parameter(defaultValue = "${project.build.directory}", required = true) -110private File outputDirectory; +109 @Parameter(property = "project", required = true, readonly = true) +110private MavenProject project; 111/** -112 * Specifies the destination directory for the generated Dependency-Check -113 * report. This generally maps to "target/site". -114 */ -115 @Parameter(property = "project.reporting.outputDirectory", required = true) -116private File reportOutputDirectory; -117/** -118 * Specifies if the build should be failed if a CVSS score above a specified -119 * level is identified. The default is 11 which means since the CVSS scores -120 * are 0-10, by default the build will never fail. -121 */ -122 @SuppressWarnings("CanBeFinal") -123 @Parameter(property = "failBuildOnCVSS", defaultValue = "11", required = true) -124privatefloat failBuildOnCVSS = 11; -125/** -126 * Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not -127 * recommended that this be turned to false. Default is true. -128 */ -129 @Parameter(property = "autoUpdate") -130private Boolean autoUpdate; -131/** -132 * Sets whether Experimental analyzers are enabled. Default is false. -133 */ -134 @Parameter(property = "enableExperimental") -135private Boolean enableExperimental; -136/** -137 * Generate aggregate reports in multi-module projects. -138 * -139 * @deprecated use the aggregate goal instead -140 */ -141 @Parameter(property = "aggregate") -142 @Deprecated -143private Boolean aggregate; -144/** -145 * The report format to be generated (HTML, XML, VULN, ALL). This -146 * configuration option has no affect if using this within the Site plug-in -147 * unless the externalReport is set to true. Default is HTML. -148 */ -149 @SuppressWarnings("CanBeFinal") -150 @Parameter(property = "format", defaultValue = "HTML", required = true) -151private String format = "HTML"; +112 * List of Maven project of the current build +113 */ +114 @Parameter(readonly = true, required = true, property = "reactorProjects") +115private List<MavenProject> reactorProjects; +116/** +117 * The entry point to Aether, i.e. the component doing all the work. +118 */ +119 @Component +120private RepositorySystem repoSystem; +121 +122/** +123 * The current repository/network configuration of Maven. +124 */ +125 @Parameter(defaultValue = "${repositorySystemSession}", readonly = true) +126private RepositorySystemSession repoSession; +127 +128/** +129 * The project's remote repositories to use for the resolution of plug-ins +130 * and their dependencies. +131 */ +132 @Parameter(defaultValue = "${project.remotePluginRepositories}", readonly = true) +133private List<RemoteRepository> remoteRepos; +134 +135/** +136 * Component within Maven to build the dependency graph. +137 */ +138 @Component +139private DependencyGraphBuilder dependencyGraphBuilder; +140 +141/** +142 * The output directory. This generally maps to "target". +143 */ +144 @Parameter(defaultValue = "${project.build.directory}", required = true) +145private File outputDirectory; +146/** +147 * Specifies the destination directory for the generated Dependency-Check +148 * report. This generally maps to "target/site". +149 */ +150 @Parameter(property = "project.reporting.outputDirectory", required = true) +151private File reportOutputDirectory; 152/** -153 * The Maven settings. -154 */ -155 @Parameter(property = "mavenSettings", defaultValue = "${settings}", required = false) -156private org.apache.maven.settings.Settings mavenSettings; -157 -158/** -159 * The maven settings proxy id. -160 */ -161 @Parameter(property = "mavenSettingsProxyId", required = false) -162private String mavenSettingsProxyId; -163 -164/** -165 * The Connection Timeout. -166 */ -167 @Parameter(property = "connectionTimeout", defaultValue = "", required = false) -168private String connectionTimeout; -169/** -170 * The path to the suppression file. -171 */ -172 @Parameter(property = "suppressionFile", defaultValue = "", required = false) -173private String suppressionFile; -174/** -175 * Flag indicating whether or not to show a summary in the output. -176 */ -177 @SuppressWarnings("CanBeFinal") -178 @Parameter(property = "showSummary", defaultValue = "true", required = false) -179privateboolean showSummary = true; -180 -181/** -182 * Whether or not the Jar Analyzer is enabled. +153 * Specifies if the build should be failed if a CVSS score above a specified +154 * level is identified. The default is 11 which means since the CVSS scores +155 * are 0-10, by default the build will never fail. +156 */ +157 @SuppressWarnings("CanBeFinal") +158 @Parameter(property = "failBuildOnCVSS", defaultValue = "11", required = true) +159privatefloat failBuildOnCVSS = 11; +160/** +161 * Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not +162 * recommended that this be turned to false. Default is true. +163 */ +164 @Parameter(property = "autoUpdate") +165private Boolean autoUpdate; +166/** +167 * Sets whether Experimental analyzers are enabled. Default is false. +168 */ +169 @Parameter(property = "enableExperimental") +170private Boolean enableExperimental; +171/** +172 * Generate aggregate reports in multi-module projects. +173 * +174 * @deprecated use the aggregate goal instead +175 */ +176 @Parameter(property = "aggregate") +177 @Deprecated +178private Boolean aggregate; +179/** +180 * The report format to be generated (HTML, XML, VULN, ALL). This +181 * configuration option has no affect if using this within the Site plug-in +182 * unless the externalReport is set to true. Default is HTML.183 */ -184 @Parameter(property = "jarAnalyzerEnabled", required = false) -185private Boolean jarAnalyzerEnabled; -186 +184 @SuppressWarnings("CanBeFinal") +185 @Parameter(property = "format", defaultValue = "HTML", required = true) +186private String format = "HTML"; 187/** -188 * Whether or not the Archive Analyzer is enabled. +188 * The Maven settings.189 */ -190 @Parameter(property = "archiveAnalyzerEnabled", required = false) -191private Boolean archiveAnalyzerEnabled; +190 @Parameter(property = "mavenSettings", defaultValue = "${settings}", required = false) +191private org.apache.maven.settings.Settings mavenSettings; 192193/** -194 * Sets whether the Python Distribution Analyzer will be used. +194 * The maven settings proxy id.195 */ -196 @Parameter(property = "pyDistributionAnalyzerEnabled", required = false) -197private Boolean pyDistributionAnalyzerEnabled; -198/** -199 * Sets whether the Python Package Analyzer will be used. -200 */ -201 @Parameter(property = "pyPackageAnalyzerEnabled", required = false) -202private Boolean pyPackageAnalyzerEnabled; -203/** -204 * Sets whether the Ruby Gemspec Analyzer will be used. -205 */ -206 @Parameter(property = "rubygemsAnalyzerEnabled", required = false) -207private Boolean rubygemsAnalyzerEnabled; -208/** -209 * Sets whether or not the openssl Analyzer should be used. -210 */ -211 @Parameter(property = "opensslAnalyzerEnabled", required = false) -212private Boolean opensslAnalyzerEnabled; -213/** -214 * Sets whether or not the CMake Analyzer should be used. -215 */ -216 @Parameter(property = "cmakeAnalyzerEnabled", required = false) -217private Boolean cmakeAnalyzerEnabled; -218/** -219 * Sets whether or not the autoconf Analyzer should be used. -220 */ -221 @Parameter(property = "autoconfAnalyzerEnabled", required = false) -222private Boolean autoconfAnalyzerEnabled; -223/** -224 * Sets whether or not the PHP Composer Lock File Analyzer should be used. -225 */ -226 @Parameter(property = "composerAnalyzerEnabled", required = false) -227private Boolean composerAnalyzerEnabled; +196 @Parameter(property = "mavenSettingsProxyId", required = false) +197private String mavenSettingsProxyId; +198 +199/** +200 * The Connection Timeout. +201 */ +202 @Parameter(property = "connectionTimeout", defaultValue = "", required = false) +203private String connectionTimeout; +204/** +205 * The path to the suppression file. +206 */ +207 @Parameter(property = "suppressionFile", defaultValue = "", required = false) +208private 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) +214privateboolean showSummary = true; +215 +216/** +217 * Whether or not the Jar Analyzer is enabled. +218 */ +219 @Parameter(property = "jarAnalyzerEnabled", required = false) +220private Boolean jarAnalyzerEnabled; +221 +222/** +223 * Whether or not the Archive Analyzer is enabled. +224 */ +225 @Parameter(property = "archiveAnalyzerEnabled", required = false) +226private Boolean archiveAnalyzerEnabled; +227228/** -229 * Sets whether or not the Node.js Analyzer should be used. +229 * Sets whether the Python Distribution Analyzer will be used.230 */ -231 @Parameter(property = "nodeAnalyzerEnabled", required = false) -232private Boolean nodeAnalyzerEnabled; -233 -234/** -235 * Whether or not the .NET Assembly Analyzer is enabled. -236 */ -237 @Parameter(property = "assemblyAnalyzerEnabled", required = false) -238private Boolean assemblyAnalyzerEnabled; -239 -240/** -241 * Whether or not the .NET Nuspec Analyzer is enabled. -242 */ -243 @Parameter(property = "nuspecAnalyzerEnabled", required = false) -244private Boolean nuspecAnalyzerEnabled; -245 -246/** -247 * Whether or not the Central Analyzer is enabled. -248 */ -249 @Parameter(property = "centralAnalyzerEnabled", required = false) -250private Boolean centralAnalyzerEnabled; -251 -252/** -253 * Whether or not the Nexus Analyzer is enabled. -254 */ -255 @Parameter(property = "nexusAnalyzerEnabled", required = false) -256private Boolean nexusAnalyzerEnabled; -257 +231 @Parameter(property = "pyDistributionAnalyzerEnabled", required = false) +232private Boolean pyDistributionAnalyzerEnabled; +233/** +234 * Sets whether the Python Package Analyzer will be used. +235 */ +236 @Parameter(property = "pyPackageAnalyzerEnabled", required = false) +237private Boolean pyPackageAnalyzerEnabled; +238/** +239 * Sets whether the Ruby Gemspec Analyzer will be used. +240 */ +241 @Parameter(property = "rubygemsAnalyzerEnabled", required = false) +242private Boolean rubygemsAnalyzerEnabled; +243/** +244 * Sets whether or not the openssl Analyzer should be used. +245 */ +246 @Parameter(property = "opensslAnalyzerEnabled", required = false) +247private Boolean opensslAnalyzerEnabled; +248/** +249 * Sets whether or not the CMake Analyzer should be used. +250 */ +251 @Parameter(property = "cmakeAnalyzerEnabled", required = false) +252private Boolean cmakeAnalyzerEnabled; +253/** +254 * Sets whether or not the autoconf Analyzer should be used. +255 */ +256 @Parameter(property = "autoconfAnalyzerEnabled", required = false) +257private Boolean autoconfAnalyzerEnabled; 258/** -259 * The URL of a Nexus server's REST API end point -260 * (http://domain/nexus/service/local). -261 */ -262 @Parameter(property = "nexusUrl", required = false) -263private String nexusUrl; -264/** -265 * Whether or not the configured proxy is used to connect to Nexus. -266 */ -267 @Parameter(property = "nexusUsesProxy", required = false) -268private Boolean nexusUsesProxy; +259 * Sets whether or not the PHP Composer Lock File Analyzer should be used. +260 */ +261 @Parameter(property = "composerAnalyzerEnabled", required = false) +262private Boolean composerAnalyzerEnabled; +263/** +264 * Sets whether or not the Node.js Analyzer should be used. +265 */ +266 @Parameter(property = "nodeAnalyzerEnabled", required = false) +267private Boolean nodeAnalyzerEnabled; +268269/** -270 * The database connection string. +270 * Whether or not the .NET Assembly Analyzer is enabled.271 */ -272 @Parameter(property = "connectionString", defaultValue = "", required = false) -273private String connectionString; +272 @Parameter(property = "assemblyAnalyzerEnabled", required = false) +273private Boolean assemblyAnalyzerEnabled; 274275/** -276 * Returns the connection string. -277 * -278 * @return the connection string -279 */ -280protected String getConnectionString() { -281return connectionString; -282 } -283/** -284 * The database driver name. An example would be org.h2.Driver. -285 */ -286 @Parameter(property = "databaseDriverName", defaultValue = "", required = false) -287private String databaseDriverName; -288/** -289 * The path to the database driver if it is not on the class path. -290 */ -291 @Parameter(property = "databaseDriverPath", defaultValue = "", required = false) -292private String databaseDriverPath; +276 * Whether or not the .NET Nuspec Analyzer is enabled. +277 */ +278 @Parameter(property = "nuspecAnalyzerEnabled", required = false) +279private Boolean nuspecAnalyzerEnabled; +280 +281/** +282 * Whether or not the Central Analyzer is enabled. +283 */ +284 @Parameter(property = "centralAnalyzerEnabled", required = false) +285private Boolean centralAnalyzerEnabled; +286 +287/** +288 * Whether or not the Nexus Analyzer is enabled. +289 */ +290 @Parameter(property = "nexusAnalyzerEnabled", required = false) +291private Boolean nexusAnalyzerEnabled; +292293/** -294 * The server id in the settings.xml; used to retrieve encrypted passwords -295 * from the settings.xml. +294 * The URL of a Nexus server's REST API end point +295 * (http://domain/nexus/service/local).296 */ -297 @Parameter(property = "serverId", defaultValue = "", required = false) -298private String serverId; +297 @Parameter(property = "nexusUrl", required = false) +298private String nexusUrl; 299/** -300 * A reference to the settings.xml settings. +300 * Whether or not the configured proxy is used to connect to Nexus.301 */ -302 @Parameter(defaultValue = "${settings}", readonly = true, required = true) -303private org.apache.maven.settings.Settings settingsXml; +302 @Parameter(property = "nexusUsesProxy", required = false) +303private Boolean nexusUsesProxy; 304/** -305 * The security dispatcher that can decrypt passwords in the settings.xml. +305 * The database connection string.306 */ -307 @Component(role = SecDispatcher.class, hint = "default") -308private SecDispatcher securityDispatcher; -309/** -310 * The database user name. -311 */ -312 @Parameter(property = "databaseUser", defaultValue = "", required = false) -313private String databaseUser; -314/** -315 * The password to use when connecting to the database. -316 */ -317 @Parameter(property = "databasePassword", defaultValue = "", required = false) -318private String databasePassword; -319/** -320 * A comma-separated list of file extensions to add to analysis next to jar, -321 * zip, .... -322 */ -323 @Parameter(property = "zipExtensions", required = false) -324private String zipExtensions; -325/** -326 * Skip Dependency Check altogether. -327 */ -328 @SuppressWarnings("CanBeFinal") -329 @Parameter(property = "dependency-check.skip", defaultValue = "false", required = false) -330privateboolean skip = false; -331/** -332 * Skip Analysis for Test Scope Dependencies. -333 */ -334 @SuppressWarnings("CanBeFinal") -335 @Parameter(property = "skipTestScope", defaultValue = "true", required = false) -336privateboolean skipTestScope = true; -337/** -338 * Skip Analysis for Runtime Scope Dependencies. -339 */ -340 @SuppressWarnings("CanBeFinal") -341 @Parameter(property = "skipRuntimeScope", defaultValue = "false", required = false) -342privateboolean skipRuntimeScope = false; -343/** -344 * Skip Analysis for Provided Scope Dependencies. -345 */ -346 @SuppressWarnings("CanBeFinal") -347 @Parameter(property = "skipProvidedScope", defaultValue = "false", required = false) -348privateboolean skipProvidedScope = false; +307 @Parameter(property = "connectionString", defaultValue = "", required = false) +308private String connectionString; +309 +310/** +311 * Returns the connection string. +312 * +313 * @return the connection string +314 */ +315protected String getConnectionString() { +316return connectionString; +317 } +318/** +319 * The database driver name. An example would be org.h2.Driver. +320 */ +321 @Parameter(property = "databaseDriverName", defaultValue = "", required = false) +322private 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) +327private 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) +333private String serverId; +334/** +335 * A reference to the settings.xml settings. +336 */ +337 @Parameter(defaultValue = "${settings}", readonly = true, required = true) +338private 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") +343private SecDispatcher securityDispatcher; +344/** +345 * The database user name. +346 */ +347 @Parameter(property = "databaseUser", defaultValue = "", required = false) +348private String databaseUser; 349/** -350 * The data directory, hold DC SQL DB. +350 * The password to use when connecting to the database.351 */ -352 @Parameter(property = "dataDirectory", defaultValue = "", required = false) -353private String dataDirectory; +352 @Parameter(property = "databasePassword", defaultValue = "", required = false) +353private String databasePassword; 354/** -355 * Data Mirror URL for CVE 1.2. -356 */ -357 @Parameter(property = "cveUrl12Modified", defaultValue = "", required = false) -358private String cveUrl12Modified; -359/** -360 * Data Mirror URL for CVE 2.0. -361 */ -362 @Parameter(property = "cveUrl20Modified", defaultValue = "", required = false) -363private String cveUrl20Modified; -364/** -365 * Base Data Mirror URL for CVE 1.2. -366 */ -367 @Parameter(property = "cveUrl12Base", defaultValue = "", required = false) -368private String cveUrl12Base; -369/** -370 * Data Mirror URL for CVE 2.0. -371 */ -372 @Parameter(property = "cveUrl20Base", defaultValue = "", required = false) -373private String cveUrl20Base; -374/** -375 * Optionally skip excessive CVE update checks for a designated duration in -376 * hours. -377 */ -378 @Parameter(property = "cveValidForHours", defaultValue = "", required = false) -379private Integer cveValidForHours; -380 -381/** -382 * The path to mono for .NET Assembly analysis on non-windows systems. -383 */ -384 @Parameter(property = "pathToMono", defaultValue = "", required = false) -385private String pathToMono; -386 -387/** -388 * The Proxy URL. -389 * -390 * @deprecated Please use mavenSettings instead +355 * A comma-separated list of file extensions to add to analysis next to jar, +356 * zip, .... +357 */ +358 @Parameter(property = "zipExtensions", required = false) +359private String zipExtensions; +360/** +361 * Skip Dependency Check altogether. +362 */ +363 @SuppressWarnings("CanBeFinal") +364 @Parameter(property = "dependency-check.skip", defaultValue = "false", required = false) +365privateboolean skip = false; +366/** +367 * Skip Analysis for Test Scope Dependencies. +368 */ +369 @SuppressWarnings("CanBeFinal") +370 @Parameter(property = "skipTestScope", defaultValue = "true", required = false) +371privateboolean skipTestScope = true; +372/** +373 * Skip Analysis for Runtime Scope Dependencies. +374 */ +375 @SuppressWarnings("CanBeFinal") +376 @Parameter(property = "skipRuntimeScope", defaultValue = "false", required = false) +377privateboolean skipRuntimeScope = false; +378/** +379 * Skip Analysis for Provided Scope Dependencies. +380 */ +381 @SuppressWarnings("CanBeFinal") +382 @Parameter(property = "skipProvidedScope", defaultValue = "false", required = false) +383privateboolean skipProvidedScope = false; +384/** +385 * The data directory, hold DC SQL DB. +386 */ +387 @Parameter(property = "dataDirectory", defaultValue = "", required = false) +388private String dataDirectory; +389/** +390 * Data Mirror URL for CVE 1.2.391 */ -392 @SuppressWarnings("CanBeFinal") -393 @Parameter(property = "proxyUrl", defaultValue = "", required = false) -394 @Deprecated -395private String proxyUrl = null; -396/** -397 * Sets whether or not the external report format should be used. -398 * -399 * @deprecated the internal report is no longer supported -400 */ -401 @SuppressWarnings("CanBeFinal") -402 @Parameter(property = "externalReport") -403 @Deprecated -404private String externalReport = null; -405// </editor-fold> -406//<editor-fold defaultstate="collapsed" desc="Base Maven implementation"> -407 -408/** -409 * Executes dependency-check. -410 * -411 * @throws MojoExecutionException thrown if there is an exception executing -412 * the mojo -413 * @throws MojoFailureException thrown if dependency-check failed the build -414 */ -415 @Override -416publicvoid execute() throws MojoExecutionException, MojoFailureException { -417 generatingSite = false; -418if (skip) { -419 getLog().info("Skipping " + getName(Locale.US)); -420 } else { -421 validateAggregate(); -422 project.setContextValue(getOutputDirectoryContextKey(), this.outputDirectory); -423 runCheck(); -424 } -425 } -426 -427/** -428 * Checks if the aggregate configuration parameter has been set to true. If -429 * it has a MojoExecutionException is thrown because the aggregate -430 * configuration parameter is no longer supported. -431 * -432 * @throws MojoExecutionException thrown if aggregate is set to true -433 */ -434privatevoid validateAggregate() throws MojoExecutionException { -435if (aggregate != null && aggregate) { -436final String msg = "Aggregate configuration detected - as of dependency-check 1.2.8 this no longer supported. " -437 + "Please use the aggregate goal instead."; -438thrownew MojoExecutionException(msg); -439 } -440 } -441 -442/** -443 * Generates the Dependency-Check Site Report. -444 * -445 * @param sink the sink to write the report to -446 * @param locale the locale to use when generating the report -447 * @throws MavenReportException if a maven report exception occurs -448 * @deprecated use -449 * {@link #generate(org.apache.maven.doxia.sink.Sink, java.util.Locale)} -450 * instead. -451 */ -452 @Override -453 @Deprecated -454publicfinalvoid generate(@SuppressWarnings("deprecation") org.codehaus.doxia.sink.Sink sink, Locale locale) throws MavenReportException { -455 generate((Sink) sink, locale); -456 } -457 -458/** -459 * A flag indicating whether or not the maven site is being generated. -460 */ -461privateboolean generatingSite = false; -462 -463/** -464 * Returns true if the Maven site is being generated. -465 * -466 * @return true if the Maven site is being generated -467 */ -468protectedboolean isGeneratingSite() { -469return generatingSite; -470 } -471 -472/** -473 * Generates the Dependency-Check Site Report. -474 * -475 * @param sink the sink to write the report to -476 * @param locale the locale to use when generating the report -477 * @throws MavenReportException if a maven report exception occurs -478 */ -479publicvoid generate(Sink sink, Locale locale) throws MavenReportException { -480 generatingSite = true; -481try { -482 validateAggregate(); -483 } catch (MojoExecutionException ex) { -484thrownew MavenReportException(ex.getMessage()); -485 } -486 project.setContextValue(getOutputDirectoryContextKey(), getReportOutputDirectory()); -487try { -488 runCheck(); -489 } catch (MojoExecutionException ex) { -490thrownew MavenReportException(ex.getMessage(), ex); -491 } catch (MojoFailureException ex) { -492 getLog().warn("Vulnerabilities were identifies that exceed the CVSS threshold for failing the build"); -493 } -494 } -495 -496/** -497 * Returns the correct output directory depending on if a site is being -498 * executed or not. -499 * -500 * @return the directory to write the report(s) -501 * @throws MojoExecutionException thrown if there is an error loading the -502 * file path -503 */ -504protected File getCorrectOutputDirectory() throws MojoExecutionException { -505return getCorrectOutputDirectory(this.project); -506 } -507 -508/** -509 * Returns the correct output directory depending on if a site is being -510 * executed or not. -511 * -512 * @param current the Maven project to get the output directory from -513 * @return the directory to write the report(s) -514 */ -515protected File getCorrectOutputDirectory(MavenProject current) { -516final Object obj = current.getContextValue(getOutputDirectoryContextKey()); -517if (obj != null && obj instanceof File) { -518return (File) obj; -519 } -520 File target = new File(current.getBuild().getDirectory()); -521if (target.getParentFile() != null && "target".equals(target.getParentFile().getName())) { -522 target = target.getParentFile(); -523 } -524return target; -525 } -526 -527/** -528 * Returns the correct output directory depending on if a site is being -529 * executed or not. -530 * -531 * @param current the Maven project to get the output directory from -532 * @return the directory to write the report(s) -533 */ -534protected File getDataFile(MavenProject current) { -535if (getLog().isDebugEnabled()) { -536 getLog().debug(String.format("Getting data filefor %s using key '%s'", current.getName(), getDataFileContextKey())); -537 } -538final Object obj = current.getContextValue(getDataFileContextKey()); -539if (obj != null) { -540if (obj instanceof String) { -541final File f = new File((String) obj); -542return f; -543 } -544 } elseif (getLog().isDebugEnabled()) { -545 getLog().debug("Context value not found"); -546 } -547returnnull; -548 } -549 -550/** -551 * Scans the project's artifacts and adds them to the engine's dependency -552 * list. -553 * -554 * @param project the project to scan the dependencies of -555 * @param engine the engine to use to scan the dependencies -556 */ -557protectedvoid scanArtifacts(MavenProject project, MavenEngine engine) { -558for (Artifact a : project.getArtifacts()) { -559if (excludeFromScan(a)) { -560continue; -561 } -562final List<Dependency> deps = engine.scan(a.getFile().getAbsoluteFile()); -563if (deps != null) { -564if (deps.size() == 1) { -565final Dependency d = deps.get(0); -566if (d != null) { -567final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion()); -568 d.addAsEvidence("pom", ma, Confidence.HIGHEST); -569 d.addProjectReference(project.getName()); -570if (getLog().isDebugEnabled()) { -571 getLog().debug(String.format("Adding project reference %s on dependency %s", project.getName(), -572 d.getDisplayFileName())); -573 } -574 } -575 } elseif (getLog().isDebugEnabled()) { -576final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s:%s:%s'", -577 a.getGroupId(), a.getArtifactId(), a.getVersion()); -578 getLog().debug(msg); -579 } -580 } +392 @Parameter(property = "cveUrl12Modified", defaultValue = "", required = false) +393private String cveUrl12Modified; +394/** +395 * Data Mirror URL for CVE 2.0. +396 */ +397 @Parameter(property = "cveUrl20Modified", defaultValue = "", required = false) +398private String cveUrl20Modified; +399/** +400 * Base Data Mirror URL for CVE 1.2. +401 */ +402 @Parameter(property = "cveUrl12Base", defaultValue = "", required = false) +403private String cveUrl12Base; +404/** +405 * Data Mirror URL for CVE 2.0. +406 */ +407 @Parameter(property = "cveUrl20Base", defaultValue = "", required = false) +408private 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) +414private Integer cveValidForHours; +415 +416/** +417 * The path to mono for .NET Assembly analysis on non-windows systems. +418 */ +419 @Parameter(property = "pathToMono", defaultValue = "", required = false) +420private 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 +430private 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 +439private 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 +451publicvoid execute() throws MojoExecutionException, MojoFailureException { +452 generatingSite = false; +453if (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 */ +469privatevoid validateAggregate() throws MojoExecutionException { +470if (aggregate != null && aggregate) { +471final String msg = "Aggregate configuration detected - as of dependency-check 1.2.8 this no longer supported. " +472 + "Please use the aggregate goal instead."; +473thrownew 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 +489publicfinalvoid 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 */ +496privateboolean 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 +502 */ +503protectedboolean isGeneratingSite() { +504return 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 */ +514publicvoid generate(Sink sink, Locale locale) throws MavenReportException { +515 generatingSite = true; +516try { +517 validateAggregate(); +518 } catch (MojoExecutionException ex) { +519thrownew MavenReportException(ex.getMessage()); +520 } +521 project.setContextValue(getOutputDirectoryContextKey(), getReportOutputDirectory()); +522try { +523 runCheck(); +524 } catch (MojoExecutionException ex) { +525thrownew 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 */ +539protected File getCorrectOutputDirectory() throws MojoExecutionException { +540return 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 */ +550protected File getCorrectOutputDirectory(MavenProject current) { +551final Object obj = current.getContextValue(getOutputDirectoryContextKey()); +552if (obj != null && obj instanceof File) { +553return (File) obj; +554 } +555 File target = new File(current.getBuild().getDirectory()); +556if (target.getParentFile() != null && "target".equals(target.getParentFile().getName())) { +557 target = target.getParentFile(); +558 } +559return 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 */ +569protected File getDataFile(MavenProject current) { +570if (getLog().isDebugEnabled()) { +571 getLog().debug(String.format("Getting data filefor %s using key '%s'", current.getName(), getDataFileContextKey())); +572 } +573final Object obj = current.getContextValue(getDataFileContextKey()); +574if (obj != null) { +575if (obj instanceof String) { +576final File f = new File((String) obj); +577return f; +578 } +579 } elseif (getLog().isDebugEnabled()) { +580 getLog().debug("Context value not found"); 581 } -582 } -583 -584/** -585 * Executes the dependency-check scan and generates the necassary report. -586 * -587 * @throws MojoExecutionException thrown if there is an exception running -588 * the scan -589 * @throws MojoFailureException thrown if dependency-check is configured to -590 * fail the build -591 */ -592publicabstractvoid runCheck() throws MojoExecutionException, MojoFailureException; -593 -594/** -595 * Sets the Reporting output directory. -596 * -597 * @param directory the output directory -598 */ -599 @Override -600publicvoid setReportOutputDirectory(File directory) { -601 reportOutputDirectory = directory; -602 } -603 -604/** -605 * Returns the report output directory. -606 * -607 * @return the report output directory -608 */ -609 @Override -610public File getReportOutputDirectory() { -611return reportOutputDirectory; -612 } -613 -614/** -615 * Returns the output directory. -616 * -617 * @return the output directory -618 */ -619public File getOutputDirectory() { -620return outputDirectory; -621 } -622 -623/** -624 * Returns whether this is an external report. This method always returns -625 * true. -626 * -627 * @return <code>true</code> -628 */ -629 @Override -630publicfinalboolean isExternalReport() { -631returntrue; -632 } -633 -634/** -635 * Returns the output name. +582returnnull; +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 */ +594protected 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 } +619 } +620 } +621 */ +622// </editor-fold> +623try { +624final DependencyNode dn = dependencyGraphBuilder.buildDependencyGraph(project, null, reactorProjects); +625return collectDependencies(engine, project, dn.getChildren()); +626 } catch (DependencyGraphBuilderException ex) { +627final String msg = String.format("Unable to build dependency graph on project %s", project.getName()); +628 getLog().debug(msg, ex); +629returnnew ExceptionCollection(msg, ex); +630 } +631 } +632 +633/** +634 * Resolves the projects artifacts using Aether and scans the resulting +635 * dependencies.636 * -637 * @return the output name -638 */ -639 @Override -640public String getOutputName() { -641if ("HTML".equalsIgnoreCase(this.format) || "ALL".equalsIgnoreCase(this.format)) { -642return"dependency-check-report"; -643 } elseif ("XML".equalsIgnoreCase(this.format)) { -644return"dependency-check-report.xml#"; -645 } elseif ("VULN".equalsIgnoreCase(this.format)) { -646return"dependency-check-vulnerability"; -647 } else { -648 getLog().warn("Unknown report format used during site generation."); -649return"dependency-check-report"; -650 } -651 } -652 -653/** -654 * Returns the category name. -655 * -656 * @return the category name -657 */ -658 @Override -659public String getCategoryName() { -660return MavenReport.CATEGORY_PROJECT_REPORTS; -661 } -662//</editor-fold> -663 -664/** -665 * Initializes a new <code>MavenEngine</code> that can be used for scanning. -666 * -667 * @return a newly instantiated <code>MavenEngine</code> -668 * @throws DatabaseException thrown if there is a database exception -669 */ -670protectedMavenEngine initializeEngine() throws DatabaseException { -671 populateSettings(); -672returnnewMavenEngine(this.project, -673this.reactorProjects); -674 } -675 -676/** -677 * Takes the properties supplied and updates the dependency-check settings. -678 * Additionally, this sets the system properties required to change the -679 * proxy url, port, and connection timeout. -680 */ -681protectedvoid populateSettings() { -682 Settings.initialize(); -683 InputStream mojoProperties = null; -684try { -685 mojoProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE); -686 Settings.mergeProperties(mojoProperties); -687 } catch (IOException ex) { -688 getLog().warn("Unable to load the dependency-check ant task.properties file."); -689if (getLog().isDebugEnabled()) { -690 getLog().debug("", ex); -691 } -692 } finally { -693if (mojoProperties != null) { -694try { -695 mojoProperties.close(); -696 } catch (IOException ex) { -697if (getLog().isDebugEnabled()) { -698 getLog().debug("", ex); -699 } -700 } -701 } -702 } -703 Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate); -704 -705 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental); -706 -707if (externalReport != null) { -708 getLog().warn("The 'externalReport' option was set; this configuration option has been removed. " -709 + "Please update the dependency-check-maven plugin's configuration"); -710 } -711 -712if (proxyUrl != null && !proxyUrl.isEmpty()) { -713 getLog().warn("Deprecated configuration detected, proxyUrl will be ignored; use the maven settings " + "to configure the proxy instead"); -714 } -715final Proxy proxy = getMavenProxy(); -716if (proxy != null) { -717 Settings.setString(Settings.KEYS.PROXY_SERVER, proxy.getHost()); -718 Settings.setString(Settings.KEYS.PROXY_PORT, Integer.toString(proxy.getPort())); -719final String userName = proxy.getUsername(); -720final String password = proxy.getPassword(); -721 Settings.setStringIfNotNull(Settings.KEYS.PROXY_USERNAME, userName); -722 Settings.setStringIfNotNull(Settings.KEYS.PROXY_PASSWORD, password); -723 Settings.setStringIfNotNull(Settings.KEYS.PROXY_NON_PROXY_HOSTS, proxy.getNonProxyHosts()); -724 } -725 -726 Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout); -727 Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); -728 -729//File Type Analyzer Settings -730 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled); -731 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled); -732 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled); -733 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled); -734 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); -735 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy); -736 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled); -737 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled); -738 Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions); -739 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); -740 -741 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, pyDistributionAnalyzerEnabled); -742 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, pyPackageAnalyzerEnabled); -743 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, rubygemsAnalyzerEnabled); -744 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, opensslAnalyzerEnabled); -745 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CMAKE_ENABLED, cmakeAnalyzerEnabled); -746 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, autoconfAnalyzerEnabled); -747 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, composerAnalyzerEnabled); -748 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, nodeAnalyzerEnabled); -749 -750//Database configuration -751 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName); -752 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath); -753 Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString); -754 -755if (databaseUser == null && databasePassword == null && serverId != null) { -756final Server server = settingsXml.getServer(serverId); -757if (server != null) { -758 databaseUser = server.getUsername(); -759try { -760//The following fix was copied from: -761// https://github.com/bsorrentino/maven-confluence-plugin/blob/master/maven-confluence-reporting-plugin/src/main/java/org/bsc/maven/confluence/plugin/AbstractBaseConfluenceMojo.java -762// -763// FIX to resolve -764// org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException: -765// java.io.FileNotFoundException: ~/.settings-security.xml (No such file or directory) -766// -767if (securityDispatcher instanceof DefaultSecDispatcher) { -768 ((DefaultSecDispatcher) securityDispatcher).setConfigurationFile("~/.m2/settings-security.xml"); -769 } -770 -771 databasePassword = securityDispatcher.decrypt(server.getPassword()); -772 } catch (SecDispatcherException ex) { -773if (ex.getCause() instanceof FileNotFoundException -774 || (ex.getCause() != null && ex.getCause().getCause() instanceof FileNotFoundException)) { -775//maybe its not encrypted? -776final String tmp = server.getPassword(); -777if (tmp.startsWith("{") && tmp.endsWith("}")) { -778 getLog().error(String.format( -779"Unable to decrypt the server password for server id '%s' in settings.xml%n\tCause: %s", -780 serverId, ex.getMessage())); -781 } else { -782 databasePassword = tmp; -783 } -784 } else { -785 getLog().error(String.format( -786"Unable to decrypt the server password for server id '%s' in settings.xml%n\tCause: %s", -787 serverId, ex.getMessage())); -788 } -789 } -790 } else { -791 getLog().error(String.format("Server '%s' not found in the settings.xml file", serverId)); -792 } -793 } -794 -795 Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser); -796 Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword); -797 Settings.setStringIfNotEmpty(Settings.KEYS.DATA_DIRECTORY, dataDirectory); +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 */ +644private ExceptionCollection collectDependencies(MavenEngine engine, MavenProject project, List<DependencyNode> nodes) { +645 ExceptionCollection exCol = null; +646for (DependencyNode dependencyNode : nodes) { +647 exCol = collectDependencies(engine, project, dependencyNode.getChildren()); +648if (excludeFromScan(dependencyNode.getArtifact().getScope())) { +649continue; +650 } +651final ArtifactRequest request = new ArtifactRequest(); +652 request.setArtifact(new DefaultArtifact(dependencyNode.getArtifact().getId())); +653 request.setRepositories(remoteRepos); +654try { +655final ArtifactResult result = repoSystem.resolveArtifact(repoSession, request); +656if (result.isResolved() && result.getArtifact() != null && result.getArtifact().getFile() != null) { +657final List<Dependency> deps = engine.scan(result.getArtifact().getFile().getAbsoluteFile()); +658if (deps != null) { +659if (deps.size() == 1) { +660final Dependency d = deps.get(0); +661if (d != null) { +662final Artifact a = result.getArtifact(); +663final 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()); +666if (getLog().isDebugEnabled()) { +667 getLog().debug(String.format("Adding project reference %s on dependency %s", +668 project.getName(), d.getDisplayFileName())); +669 } +670 } +671 } elseif (getLog().isDebugEnabled()) { +672final 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 { +677final String msg = String.format("Error resolving '%s' in project %s", +678 dependencyNode.getArtifact().getId(), project.getName()); +679if (exCol == null) { +680 exCol = new ExceptionCollection(); +681 } +682 getLog().error(msg); +683for (Exception ex : result.getExceptions()) { +684 exCol.addException(ex); +685 } +686 } +687 } else { +688final String msg = String.format("Unable to resolve '%s' in project %s", +689 dependencyNode.getArtifact().getId(), project.getName()); +690 getLog().debug(msg); +691if (exCol == null) { +692 exCol = new ExceptionCollection(); +693 } +694for (Exception ex : result.getExceptions()) { +695 exCol.addException(ex); +696 } +697 } +698 } catch (ArtifactResolutionException ex) { +699if (exCol == null) { +700 exCol = new ExceptionCollection(); +701 } +702 exCol.addException(ex); +703 } +704 } +705return 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 */ +716publicabstractvoid runCheck() throws MojoExecutionException, MojoFailureException; +717 +718/** +719 * Sets the Reporting output directory. +720 * +721 * @param directory the output directory +722 */ +723 @Override +724publicvoid 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 +734public File getReportOutputDirectory() { +735return reportOutputDirectory; +736 } +737 +738/** +739 * Returns the output directory. +740 * +741 * @return the output directory +742 */ +743public File getOutputDirectory() { +744return 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 +754publicfinalboolean isExternalReport() { +755returntrue; +756 } +757 +758/** +759 * Returns the output name. +760 * +761 * @return the output name +762 */ +763 @Override +764public String getOutputName() { +765if ("HTML".equalsIgnoreCase(this.format) || "ALL".equalsIgnoreCase(this.format)) { +766return"dependency-check-report"; +767 } elseif ("XML".equalsIgnoreCase(this.format)) { +768return"dependency-check-report.xml#"; +769 } elseif ("VULN".equalsIgnoreCase(this.format)) { +770return"dependency-check-vulnerability"; +771 } else { +772 getLog().warn("Unknown report format used during site generation."); +773return"dependency-check-report"; +774 } +775 } +776 +777/** +778 * Returns the category name. +779 * +780 * @return the category name +781 */ +782 @Override +783public String getCategoryName() { +784return 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 */ +794protectedMavenEngine initializeEngine() throws DatabaseException { +795 populateSettings(); +796returnnewMavenEngine(this.project, this.reactorProjects); +797 } 798 -799 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified); -800 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified); -801 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base); -802 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base); -803 Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours); -804 -805 } -806 -807/** -808 * Returns the maven proxy. -809 * -810 * @return the maven proxy -811 */ -812private Proxy getMavenProxy() { -813if (mavenSettings != null) { -814final List<Proxy> proxies = mavenSettings.getProxies(); -815if (proxies != null && !proxies.isEmpty()) { -816if (mavenSettingsProxyId != null) { -817for (Proxy proxy : proxies) { -818if (mavenSettingsProxyId.equalsIgnoreCase(proxy.getId())) { -819return proxy; -820 } -821 } -822 } elseif (proxies.size() == 1) { -823return proxies.get(0); -824 } else { -825 getLog().warn("Multiple proxy definitions exist in the Maven settings. In the dependency-check " -826 + "configuration set the mavenSettingsProxyId so that the correct proxy will be used."); -827thrownew IllegalStateException("Ambiguous proxy definition"); -828 } -829 } -830 } -831returnnull; -832 } -833 -834/** -835 * Tests is the artifact should be included in the scan (i.e. is the -836 * dependency in a scope that is being scanned). -837 * -838 * @param a the Artifact to test -839 * @return <code>true</code> if the artifact is in an excluded scope; -840 * otherwise <code>false</code> -841 */ -842protectedboolean excludeFromScan(Artifact a) { -843if (skipTestScope && Artifact.SCOPE_TEST.equals(a.getScope())) { -844returntrue; -845 } -846if (skipProvidedScope && Artifact.SCOPE_PROVIDED.equals(a.getScope())) { -847returntrue; -848 } -849if (skipRuntimeScope && !Artifact.SCOPE_RUNTIME.equals(a.getScope())) { -850returntrue; -851 } -852return false; -853 } -854 -855/** -856 * Returns a reference to the current project. This method is used instead -857 * of auto-binding the project via component annotation in concrete -858 * implementations of this. If the child has a -859 * <code>@Component MavenProject project;</code> defined then the abstract -860 * class (i.e. this class) will not have access to the current project (just -861 * the way Maven works with the binding). -862 * -863 * @return returns a reference to the current project -864 */ -865protected MavenProject getProject() { -866return project; -867 } -868 -869/** -870 * Returns the list of Maven Projects in this build. -871 * -872 * @return the list of Maven Projects in this build -873 */ -874protected List<MavenProject> getReactorProjects() { -875return reactorProjects; -876 } +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 */ +804protectedvoid populateSettings() { +805 Settings.initialize(); +806 InputStream mojoProperties = null; +807try { +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."); +812if (getLog().isDebugEnabled()) { +813 getLog().debug("", ex); +814 } +815 } finally { +816if (mojoProperties != null) { +817try { +818 mojoProperties.close(); +819 } catch (IOException ex) { +820if (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 +830if (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 } +834 +835if (proxyUrl != null && !proxyUrl.isEmpty()) { +836 getLog().warn("Deprecated configuration detected, proxyUrl will be ignored; use the maven settings " + "to configure the proxy instead"); +837 } +838final Proxy proxy = getMavenProxy(); +839if (proxy != null) { +840 Settings.setString(Settings.KEYS.PROXY_SERVER, proxy.getHost()); +841 Settings.setString(Settings.KEYS.PROXY_PORT, Integer.toString(proxy.getPort())); +842final String userName = proxy.getUsername(); +843final 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/** -879 * Returns the report format. -880 * -881 * @return the report format -882 */ -883protected String getFormat() { -884return format; -885 } -886 -887/** -888 * Generates the reports for a given dependency-check engine. -889 * -890 * @param engine a dependency-check engine -891 * @param p the Maven project -892 * @param outputDir the directory path to write the report(s) -893 * @throws ReportException thrown if there is an error writing the report -894 */ -895protectedvoid writeReports(MavenEngine engine, MavenProject p, File outputDir) throws ReportException { -896 DatabaseProperties prop = null; -897 CveDB cve = null; -898try { -899 cve = new CveDB(); -900 cve.open(); -901 prop = cve.getDatabaseProperties(); -902 } catch (DatabaseException ex) { -903if (getLog().isDebugEnabled()) { -904 getLog().debug("Unable to retrieve DB Properties", ex); -905 } -906 } finally { -907if (cve != null) { -908 cve.close(); -909 } -910 } -911final ReportGenerator r = new ReportGenerator(p.getName(), engine.getDependencies(), engine.getAnalyzers(), prop); -912try { -913 r.generateReports(outputDir.getAbsolutePath(), format); -914 } catch (ReportException ex) { -915final String msg = String.format("Error generating the report for %s", p.getName()); -916thrownew ReportException(msg, ex); -917 } -918 -919 } -920 -921//<editor-fold defaultstate="collapsed" desc="Methods to fail build or show summary"> -922/** -923 * Checks to see if a vulnerability has been identified with a CVSS score -924 * that is above the threshold set in the configuration. -925 * -926 * @param dependencies the list of dependency objects -927 * @throws MojoFailureException thrown if a CVSS score is found that is -928 * higher then the threshold set -929 */ -930protectedvoid checkForFailure(List<Dependency> dependencies) throws MojoFailureException { -931if (failBuildOnCVSS <= 10) { -932final StringBuilder ids = new StringBuilder(); -933for (Dependency d : dependencies) { -934boolean addName = true; -935for (Vulnerability v : d.getVulnerabilities()) { -936if (v.getCvssScore() >= failBuildOnCVSS) { -937if (addName) { -938 addName = false; -939 ids.append(NEW_LINE).append(d.getFileName()).append(": "); -940 ids.append(v.getName()); -941 } else { -942 ids.append(", ").append(v.getName()); +878if (databaseUser == null && databasePassword == null && serverId != null) { +879final Server server = settingsXml.getServer(serverId); +880if (server != null) { +881 databaseUser = server.getUsername(); +882try { +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// +890if (securityDispatcher instanceof DefaultSecDispatcher) { +891 ((DefaultSecDispatcher) securityDispatcher).setConfigurationFile("~/.m2/settings-security.xml"); +892 } +893 +894 databasePassword = securityDispatcher.decrypt(server.getPassword()); +895 } catch (SecDispatcherException ex) { +896if (ex.getCause() instanceof FileNotFoundException +897 || (ex.getCause() != null && ex.getCause().getCause() instanceof FileNotFoundException)) { +898//maybe its not encrypted? +899final String tmp = server.getPassword(); +900if (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 } +929 +930/** +931 * Returns the maven proxy. +932 * +933 * @return the maven proxy +934 */ +935private Proxy getMavenProxy() { +936if (mavenSettings != null) { +937final List<Proxy> proxies = mavenSettings.getProxies(); +938if (proxies != null && !proxies.isEmpty()) { +939if (mavenSettingsProxyId != null) { +940for (Proxy proxy : proxies) { +941if (mavenSettingsProxyId.equalsIgnoreCase(proxy.getId())) { +942return proxy; 943 } 944 } -945 } -946 } -947if (ids.length() > 0) { -948final String msg = String.format("%n%nDependency-Check Failure:%n" -949 + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n" -950 + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString()); -951thrownew MojoFailureException(msg); +945 } elseif (proxies.size() == 1) { +946return 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."); +950thrownew IllegalStateException("Ambiguous proxy definition"); +951 } 952 } 953 } -954 } -955 -956/** -957 * Generates a warning message listing a summary of dependencies and their -958 * associated CPE and CVE entries. -959 * -960 * @param mp the Maven project for which the summary is shown -961 * @param dependencies a list of dependency objects -962 */ -963protectedvoid showSummary(MavenProject mp, List<Dependency> dependencies) { -964if (showSummary) { -965final StringBuilder summary = new StringBuilder(); -966for (Dependency d : dependencies) { -967boolean firstEntry = true; -968final StringBuilder ids = new StringBuilder(); -969for (Vulnerability v : d.getVulnerabilities()) { -970if (firstEntry) { -971 firstEntry = false; -972 } else { -973 ids.append(", "); -974 } -975 ids.append(v.getName()); -976 } -977if (ids.length() > 0) { -978 summary.append(d.getFileName()).append(" ("); -979 firstEntry = true; -980for (Identifier id : d.getIdentifiers()) { -981if (firstEntry) { -982 firstEntry = false; -983 } else { -984 summary.append(", "); -985 } -986 summary.append(id.getValue()); -987 } -988 summary.append(") : ").append(ids).append(NEW_LINE); -989 } -990 } -991if (summary.length() > 0) { -992final String msg = String.format("%n%n" + "One or more dependencies were identified with known vulnerabilities in %s:%n%n%s" -993 + "%n%nSee the dependency-check report for more details.%n%n", mp.getName(), summary.toString()); -994 getLog().warn(msg); -995 } -996 } -997 } -998 -999//</editor-fold> -1000//<editor-fold defaultstate="collapsed" desc="Methods to read/write the serialized data file"> +954returnnull; +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 */ +965protectedboolean excludeFromScan(String scope) { +966if (skipTestScope && org.apache.maven.artifact.Artifact.SCOPE_TEST.equals(scope)) { +967returntrue; +968 } +969if (skipProvidedScope && org.apache.maven.artifact.Artifact.SCOPE_PROVIDED.equals(scope)) { +970returntrue; +971 } +972if (skipRuntimeScope && !org.apache.maven.artifact.Artifact.SCOPE_RUNTIME.equals(scope)) { +973returntrue; +974 } +975return 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 */ +988protected MavenProject getProject() { +989return 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 */ +997protected List<MavenProject> getReactorProjects() { +998return reactorProjects; +999 } +10001001/** -1002 * Returns the key used to store the path to the data file that is saved by -1003 * <code>writeDataFile()</code>. This key is used in the -1004 * <code>MavenProject.(set|get)ContextValue</code>. -1005 * -1006 * @return the key used to store the path to the data file -1007 */ -1008protected String getDataFileContextKey() { -1009return"dependency-check-path-" + dataFileName; -1010 } -1011 -1012/** -1013 * Returns the key used to store the path to the output directory. When -1014 * generating the report in the <code>executeAggregateReport()</code> the -1015 * output directory should be obtained by using this key. -1016 * -1017 * @return the key used to store the path to the output directory -1018 */ -1019protected String getOutputDirectoryContextKey() { -1020return"dependency-output-dir-" + dataFileName; -1021 } -1022 -1023/** -1024 * Writes the scan data to disk. This is used to serialize the scan data -1025 * between the "check" and "aggregate" phase. -1026 * -1027 * @param mp the mMven project for which the data file was created -1028 * @param writeTo the directory to write the data file -1029 * @param dependencies the list of dependencies to serialize -1030 */ -1031protectedvoid writeDataFile(MavenProject mp, File writeTo, List<Dependency> dependencies) { -1032 File file; -1033//check to see if this was already written out -1034if (mp.getContextValue(this.getDataFileContextKey()) == null) { -1035if (writeTo == null) { -1036 file = new File(mp.getBuild().getDirectory()); -1037 file = new File(file, dataFileName); -1038 } else { -1039 file = new File(writeTo, dataFileName); -1040 } -1041final File parent = file.getParentFile(); -1042if (!parent.isDirectory() && !parent.mkdirs()) { -1043 getLog().error(String.format("Directory '%s' does not exist and cannot be created; unable to write data file.", -1044 parent.getAbsolutePath())); -1045 } -1046 -1047 ObjectOutputStream out = null; -1048try { -1049if (dependencies != null) { -1050 out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file))); -1051 out.writeObject(dependencies); -1052 } -1053if (getLog().isDebugEnabled()) { -1054 getLog().debug(String.format("Serialized data file written to '%s' for %s, referenced by key %s", -1055 file.getAbsolutePath(), mp.getName(), this.getDataFileContextKey())); -1056 } -1057 mp.setContextValue(this.getDataFileContextKey(), file.getAbsolutePath()); -1058 } catch (IOException ex) { -1059 getLog().warn("Unable to create data file used for report aggregation; " -1060 + "if report aggregation is being used the results may be incomplete."); -1061if (getLog().isDebugEnabled()) { -1062 getLog().debug(ex.getMessage(), ex); -1063 } -1064 } finally { -1065if (out != null) { -1066try { -1067 out.close(); -1068 } catch (IOException ex) { -1069if (getLog().isDebugEnabled()) { -1070 getLog().debug("ignore", ex); -1071 } -1072 } -1073 } -1074 } -1075 } -1076 } -1077 -1078/** -1079 * Reads the serialized scan data from disk. This is used to serialize the -1080 * scan data between the "check" and "aggregate" phase. -1081 * -1082 * @param project the Maven project to read the data file from -1083 * @return a <code>MavenEngine</code> object populated with dependencies if -1084 * the serialized data file exists; otherwise <code>null</code> is returned +1002 * Returns the report format. +1003 * +1004 * @return the report format +1005 */ +1006protected String getFormat() { +1007return 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 */ +1018protectedvoid writeReports(MavenEngine engine, MavenProject p, File outputDir) throws ReportException { +1019 DatabaseProperties prop = null; +1020 CveDB cve = null; +1021try { +1022 cve = new CveDB(); +1023 cve.open(); +1024 prop = cve.getDatabaseProperties(); +1025 } catch (DatabaseException ex) { +1026if (getLog().isDebugEnabled()) { +1027 getLog().debug("Unable to retrieve DB Properties", ex); +1028 } +1029 } finally { +1030if (cve != null) { +1031 cve.close(); +1032 } +1033 } +1034final ReportGenerator r = new ReportGenerator(p.getName(), engine.getDependencies(), engine.getAnalyzers(), prop); +1035try { +1036 r.generateReports(outputDir.getAbsolutePath(), format); +1037 } catch (ReportException ex) { +1038final String msg = String.format("Error generating the report for %s", p.getName()); +1039thrownew 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 */ +1053protectedvoid checkForFailure(List<Dependency> dependencies) throws MojoFailureException { +1054if (failBuildOnCVSS <= 10) { +1055final StringBuilder ids = new StringBuilder(); +1056for (Dependency d : dependencies) { +1057boolean addName = true; +1058for (Vulnerability v : d.getVulnerabilities()) { +1059if (v.getCvssScore() >= failBuildOnCVSS) { +1060if (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 } +1070if (ids.length() > 0) { +1071final 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()); +1074thrownew 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 objects1085 */ -1086protected List<Dependency> readDataFile(MavenProject project) { -1087final Object oPath = project.getContextValue(this.getDataFileContextKey()); -1088if (oPath == null) { -1089returnnull; -1090 } -1091 List<Dependency> ret = null; -1092final String path = (String) oPath; -1093//ObjectInputStream ois = null; -1094 ExpectedOjectInputStream ois = null; -1095try { -1096//ois = new ObjectInputStream(new FileInputStream(path)); -1097 ois = new ExpectedOjectInputStream(new FileInputStream(path), -1098"java.util.ArrayList", -1099"java.util.HashSet", -1100"java.util.TreeSet", -1101"java.lang.AbstractSet", -1102"java.lang.AbstractCollection", -1103"java.lang.Enum", -1104"org.owasp.dependencycheck.dependency.Confidence", -1105"org.owasp.dependencycheck.dependency.Dependency", -1106"org.owasp.dependencycheck.dependency.Evidence", -1107"org.owasp.dependencycheck.dependency.EvidenceCollection", -1108"org.owasp.dependencycheck.dependency.Identifier", -1109"org.owasp.dependencycheck.dependency.Reference", -1110"org.owasp.dependencycheck.dependency.Vulnerability", -1111"org.owasp.dependencycheck.dependency.VulnerabilityComparator", -1112"org.owasp.dependencycheck.dependency.VulnerableSoftware", -1113"org.owasp.dependencycheck.data.cpe.IndexEntry"); -1114 @SuppressWarnings("unchecked") -1115final List<Dependency> depList = (List<Dependency>) ois.readObject(); -1116 ret = depList; -1117 } catch (FileNotFoundException ex) { -1118//TODO fix logging -1119 getLog().error("", ex); -1120 } catch (IOException ex) { -1121 getLog().error("", ex); -1122 } catch (ClassNotFoundException ex) { -1123 getLog().error("", ex); -1124 } finally { -1125if (ois != null) { -1126try { -1127 ois.close(); -1128 } catch (IOException ex) { -1129 getLog().error("", ex); -1130 } -1131 } -1132 } -1133return ret; -1134 } -1135//</editor-fold> -1136 } +1086protectedvoid showSummary(MavenProject mp, List<Dependency> dependencies) { +1087if (showSummary) { +1088final StringBuilder summary = new StringBuilder(); +1089for (Dependency d : dependencies) { +1090boolean firstEntry = true; +1091final StringBuilder ids = new StringBuilder(); +1092for (Vulnerability v : d.getVulnerabilities()) { +1093if (firstEntry) { +1094 firstEntry = false; +1095 } else { +1096 ids.append(", "); +1097 } +1098 ids.append(v.getName()); +1099 } +1100if (ids.length() > 0) { +1101 summary.append(d.getFileName()).append(" ("); +1102 firstEntry = true; +1103for (Identifier id : d.getIdentifiers()) { +1104if (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 } +1114if (summary.length() > 0) { +1115final 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 */ +1131protected String getDataFileContextKey() { +1132return"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 */ +1142protected String getOutputDirectoryContextKey() { +1143return"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 */ +1154protectedvoid writeDataFile(MavenProject mp, File writeTo, List<Dependency> dependencies) { +1155 File file; +1156//check to see if this was already written out +1157if (mp.getContextValue(this.getDataFileContextKey()) == null) { +1158if (writeTo == null) { +1159 file = new File(mp.getBuild().getDirectory()); +1160 file = new File(file, dataFileName); +1161 } else { +1162 file = new File(writeTo, dataFileName); +1163 } +1164final File parent = file.getParentFile(); +1165if (!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; +1171try { +1172if (dependencies != null) { +1173 out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file))); +1174 out.writeObject(dependencies); +1175 } +1176if (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."); +1184if (getLog().isDebugEnabled()) { +1185 getLog().debug(ex.getMessage(), ex); +1186 } +1187 } finally { +1188if (out != null) { +1189try { +1190 out.close(); +1191 } catch (IOException ex) { +1192if (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 */ +1209protected List<Dependency> readDataFile(MavenProject project) { +1210final Object oPath = project.getContextValue(this.getDataFileContextKey()); +1211if (oPath == null) { +1212returnnull; +1213 } +1214 List<Dependency> ret = null; +1215final String path = (String) oPath; +1216//ObjectInputStream ois = null; +1217 ExpectedOjectInputStream ois = null; +1218try { +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") +1238final 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 { +1248if (ois != null) { +1249try { +1250 ois.close(); +1251 } catch (IOException ex) { +1252 getLog().error("", ex); +1253 } +1254 } +1255 } +1256return ret; +1257 } +1258//</editor-fold> +1259 +1260 }
    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 9139db03e..d9b68af3d 100644 --- a/dependency-check-maven/xref/org/owasp/dependencycheck/maven/CheckMojo.html +++ b/dependency-check-maven/xref/org/owasp/dependencycheck/maven/CheckMojo.html @@ -63,7 +63,7 @@ 55publicboolean canGenerateReport() { 56boolean isCapable = false; 57for (Artifact a : getProject().getArtifacts()) { -58if (!excludeFromScan(a)) { +58if (!excludeFromScan(a.getScope())) { 59 isCapable = true; 60break; 61 } @@ -96,76 +96,75 @@ 88 getLog().error(msg); 89 } 90if (engine != null) { -91 scanArtifacts(getProject(), engine); +91 ExceptionCollection exCol = scanArtifacts(getProject(), engine); 92if (engine.getDependencies().isEmpty()) { 93 getLog().info("No dependencies were identified that could be analyzed by dependency-check"); 94 } else { -95 ExceptionCollection exCol = null; -96try { -97 engine.analyzeDependencies(); -98 } catch (ExceptionCollection ex) { -99if (this.isFailOnError() && ex.isFatal()) { -100thrownew MojoExecutionException("One or more exceptions occured during analysis", ex); -101 } -102 exCol = ex; -103 } -104if (exCol == null || !exCol.isFatal()) { -105try { -106 writeReports(engine, getProject(), getCorrectOutputDirectory()); -107 } catch (ReportException ex) { -108if (this.isFailOnError()) { -109if (exCol != null) { -110 exCol.addException(ex); -111 } else { -112 exCol = new ExceptionCollection("Unable to write the dependency-check report", ex); -113 } -114 } -115 } -116 writeDataFile(getProject(), null, engine.getDependencies()); -117 showSummary(getProject(), engine.getDependencies()); -118 checkForFailure(engine.getDependencies()); -119if (exCol != null && this.isFailOnError()) { -120thrownew MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol); -121 } -122 } -123 } -124 engine.cleanup(); -125 } -126 Settings.cleanup(); -127 } -128 -129/** -130 * The name of the report in the site. -131 */ -132 @SuppressWarnings("CanBeFinal") -133 @Parameter(property = "name", defaultValue = "dependency-check", required = true) -134private String name = "dependency-check"; -135 -136/** -137 * Returns the report name. -138 * -139 * @param locale the location -140 * @return the report name -141 */ -142 @Override -143public String getName(Locale locale) { -144return name; -145 } -146 -147/** -148 * Gets the description of the Dependency-Check report to be displayed in -149 * the Maven Generated Reports page. -150 * -151 * @param locale The Locale to get the description for -152 * @return the description -153 */ -154 @Override -155public String getDescription(Locale locale) { -156return"Generates a report providing details on any published vulnerabilities within project dependencies. " -157 + "This report is a best effort and may contain false positives and false negatives."; -158 } -159 -160 } +95try { +96 engine.analyzeDependencies(); +97 } catch (ExceptionCollection ex) { +98if (this.isFailOnError() && ex.isFatal()) { +99thrownew MojoExecutionException("One or more exceptions occured during analysis", ex); +100 } +101 exCol = ex; +102 } +103if (exCol == null || !exCol.isFatal()) { +104try { +105 writeReports(engine, getProject(), getCorrectOutputDirectory()); +106 } catch (ReportException ex) { +107if (this.isFailOnError()) { +108if (exCol != null) { +109 exCol.addException(ex); +110 } else { +111 exCol = new ExceptionCollection("Unable to write the dependency-check report", ex); +112 } +113 } +114 } +115 writeDataFile(getProject(), null, engine.getDependencies()); +116 showSummary(getProject(), engine.getDependencies()); +117 checkForFailure(engine.getDependencies()); +118if (exCol != null && this.isFailOnError()) { +119thrownew MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol); +120 } +121 } +122 } +123 engine.cleanup(); +124 } +125 Settings.cleanup(); +126 } +127 +128/** +129 * The name of the report in the site. +130 */ +131 @SuppressWarnings("CanBeFinal") +132 @Parameter(property = "name", defaultValue = "dependency-check", required = true) +133private String name = "dependency-check"; +134 +135/** +136 * Returns the report name. +137 * +138 * @param locale the location +139 * @return the report name +140 */ +141 @Override +142public String getName(Locale locale) { +143return name; +144 } +145 +146/** +147 * Gets the description of the Dependency-Check report to be displayed in +148 * the Maven Generated Reports page. +149 * +150 * @param locale The Locale to get the description for +151 * @return the description +152 */ +153 @Override +154public String getDescription(Locale locale) { +155return"Generates a report providing details on any published vulnerabilities within project dependencies. " +156 + "This report is a best effort and may contain false positives and false negatives."; +157 } +158 +159 }
    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 6996bd345..2bf11144a 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.2 Reference Package org.owasp.dependencycheck.maven + Dependency-Check Maven Plugin 1.4.3 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 9b36b300c..82f460dea 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.2 Reference Package org.owasp.dependencycheck.maven + Dependency-Check Maven Plugin 1.4.3 Reference Package org.owasp.dependencycheck.maven diff --git a/dependency-check-maven/xref/org/owasp/dependencycheck/maven/slf4j/package-frame.html b/dependency-check-maven/xref/org/owasp/dependencycheck/maven/slf4j/package-frame.html index 1382db0f0..36a3ed9e4 100644 --- a/dependency-check-maven/xref/org/owasp/dependencycheck/maven/slf4j/package-frame.html +++ b/dependency-check-maven/xref/org/owasp/dependencycheck/maven/slf4j/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Maven Plugin 1.4.2 Reference Package org.owasp.dependencycheck.maven.slf4j + Dependency-Check Maven Plugin 1.4.3 Reference Package org.owasp.dependencycheck.maven.slf4j diff --git a/dependency-check-maven/xref/org/owasp/dependencycheck/maven/slf4j/package-summary.html b/dependency-check-maven/xref/org/owasp/dependencycheck/maven/slf4j/package-summary.html index 76c5f8a77..a79893f16 100644 --- a/dependency-check-maven/xref/org/owasp/dependencycheck/maven/slf4j/package-summary.html +++ b/dependency-check-maven/xref/org/owasp/dependencycheck/maven/slf4j/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Maven Plugin 1.4.2 Reference Package org.owasp.dependencycheck.maven.slf4j + Dependency-Check Maven Plugin 1.4.3 Reference Package org.owasp.dependencycheck.maven.slf4j diff --git a/dependency-check-maven/xref/org/slf4j/impl/package-frame.html b/dependency-check-maven/xref/org/slf4j/impl/package-frame.html index 518b29fff..e4cc2b81a 100644 --- a/dependency-check-maven/xref/org/slf4j/impl/package-frame.html +++ b/dependency-check-maven/xref/org/slf4j/impl/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Maven Plugin 1.4.2 Reference Package org.slf4j.impl + Dependency-Check Maven Plugin 1.4.3 Reference Package org.slf4j.impl diff --git a/dependency-check-maven/xref/org/slf4j/impl/package-summary.html b/dependency-check-maven/xref/org/slf4j/impl/package-summary.html index 2aefe5e2e..695d9f157 100644 --- a/dependency-check-maven/xref/org/slf4j/impl/package-summary.html +++ b/dependency-check-maven/xref/org/slf4j/impl/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Maven Plugin 1.4.2 Reference Package org.slf4j.impl + Dependency-Check Maven Plugin 1.4.3 Reference Package org.slf4j.impl diff --git a/dependency-check-maven/xref/overview-frame.html b/dependency-check-maven/xref/overview-frame.html index 8f0bd2d6b..fb886b2e5 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.2 Reference + Dependency-Check Maven Plugin 1.4.3 Reference diff --git a/dependency-check-maven/xref/overview-summary.html b/dependency-check-maven/xref/overview-summary.html index 4db770908..112f89128 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.2 Reference + Dependency-Check Maven Plugin 1.4.3 Reference @@ -24,7 +24,7 @@ -

    Dependency-Check Maven Plugin 1.4.2 Reference

    +

    Dependency-Check Maven Plugin 1.4.3 Reference

    diff --git a/dependency-check-utils/apidocs/allclasses-frame.html b/dependency-check-utils/apidocs/allclasses-frame.html index b27af7476..5f6d87a77 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.2 API) - +All Classes (Dependency-Check Utils 1.4.3 API) + diff --git a/dependency-check-utils/apidocs/allclasses-noframe.html b/dependency-check-utils/apidocs/allclasses-noframe.html index f6b807c3c..ec01d0317 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.2 API) - +All Classes (Dependency-Check Utils 1.4.3 API) + diff --git a/dependency-check-utils/apidocs/constant-values.html b/dependency-check-utils/apidocs/constant-values.html index 684e68228..4d38b9491 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.2 API) - +Constant Field Values (Dependency-Check Utils 1.4.3 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,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 @@ 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 8b424852f..beac1c3a6 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.2 API) - +org.owasp.dependencycheck.utils (Dependency-Check Utils 1.4.3 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 d03af4595..90941d2a8 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
    23%
    136/579
    19%
    37/194
    2.857
    org.owasp.dependencycheck.utils13
    23%
    136/579
    19%
    37/194
    2.857
    All Packages13
    24%
    136/557
    19%
    37/190
    2.833
    org.owasp.dependencycheck.utils13
    24%
    136/557
    19%
    37/190
    2.833
    - + 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 479893e89..d79bd82cb 100644 --- a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.Checksum.html +++ b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.Checksum.html @@ -134,12 +134,12 @@
          */
     60  
         public static byte[] getChecksum(String algorithm, File file) throws NoSuchAlgorithmException, IOException {
    -  61  5
             MessageDigest digest = MessageDigest.getInstance(algorithm);
    +  61  5
             final MessageDigest digest = MessageDigest.getInstance(algorithm);
     62  4
             FileInputStream fis = null;
     63  
             try {
     64  4
                 fis = new FileInputStream(file);
    -  65  3
                 FileChannel ch = fis.getChannel();
    +  65  3
                 final FileChannel ch = fis.getChannel();
     66  3
                 long remainingToRead = file.length();
     67  3
                 long start = 0;
     68  6
                 while (remainingToRead > 0) {
    @@ -154,7 +154,7 @@  75  3
                         remainingToRead = 0;
     76  
                     }
    -  77  3
                     MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, start, amountToRead);
    +  77  3
                     final MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, start, amountToRead);
     78  3
                     digest.update(byteBuffer);
     79  3
                     start += amountToRead;
     80  3
                 }
    @@ -194,7 +194,7 @@
          */
     101  
         public static String getMD5Checksum(File file) throws IOException, NoSuchAlgorithmException {
    -  102  1
             byte[] b = getChecksum("MD5", file);
    +  102  1
             final byte[] b = getChecksum("MD5", file);
     103  1
             return getHex(b);
     104  
         }
    @@ -218,7 +218,7 @@
          */
     114  
         public static String getSHA1Checksum(File file) throws IOException, NoSuchAlgorithmException {
    -  115  1
             byte[] b = getChecksum("SHA1", file);
    +  115  1
             final byte[] b = getChecksum("SHA1", file);
     116  1
             return getHex(b);
     117  
         }
    @@ -272,6 +272,6 @@
     }
    - + 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 91f8792ee..57632895c 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 7a22c1583..7ab67b881 100644 --- a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.Downloader.html +++ b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.Downloader.html @@ -494,11 +494,11 @@  302  
          */
     303   -
         protected static void checkForCommonExceptionTypes(IOException ex) throws DownloadFailedException {
    +
         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 = String.format("Unable to resolve domain '%s'", cause.getMessage());
    +  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   @@ -571,6 +571,6 @@
     }
    - + 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 28021cd52..78f2f0628 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 d673467da..c0514c183 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 83166717c..99c052cfb 100644 --- a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.FileUtils.html +++ b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.FileUtils.html @@ -70,158 +70,160 @@  26  
     import java.util.UUID;
     27   -
     
    +
     import org.apache.commons.lang3.SystemUtils;
     28   -
     /**
    +
     
     29   -
      * A collection of utilities for processing information about files.
    +
     /**
     30   -
      *
    +
      * A collection of utilities for processing information about files.
     31   -
      * @author Jeremy Long
    +
      *
     32   -
      */
    +
      * @author Jeremy Long
     33   -
     public final class FileUtils {
    +
      */
     34   -
     
    +
     public final class FileUtils {
     35   -
         /**
    +
     
     36   -
          * The logger.
    +
         /**
     37   +
          * The logger.
    +  38  
          */
    -  38  1
         private static final Logger LOGGER = LoggerFactory.getLogger(FileUtils.class);
    -  39   -
         /**
    +  39  1
         private static final Logger LOGGER = LoggerFactory.getLogger(FileUtils.class);
     40   -
          * Bit bucket for non-Windows systems
    +
         /**
     41   -
          */
    +
          * Bit bucket for non-Windows systems
     42   -
         private static final String BIT_BUCKET_UNIX = "/dev/null";
    +
          */
     43   -
     
    +
         private static final String BIT_BUCKET_UNIX = "/dev/null";
     44   -
         /**
    +
     
     45   -
          * Bit bucket for Windows systems (yes, only one 'L')
    +
         /**
     46   -
          */
    +
          * Bit bucket for Windows systems (yes, only one 'L')
     47   -
         private static final String BIT_BUCKET_WIN = "NUL";
    +
          */
     48   -
     
    +
         private static final String BIT_BUCKET_WIN = "NUL";
     49   -
         /**
    +
     
     50   -
          * Private constructor for a utility class.
    +
         /**
     51   +
          * Private constructor for a utility class.
    +  52  
          */
    -  52  0
         private FileUtils() {
    -  53  0
         }
    -  54   -
     
    +  53  0
         private FileUtils() {
    +  54  0
         }
     55   -
         /**
    +
     
     56   -
          * Returns the (lowercase) file extension for a specified file.
    +
         /**
     57   -
          *
    +
          * Returns the (lowercase) file extension for a specified file.
     58   -
          * @param fileName the file name to retrieve the file extension from.
    +
          *
     59   -
          * @return the file extension.
    +
          * @param fileName the file name to retrieve the file extension from.
     60   -
          */
    +
          * @return the file extension.
     61   +
          */
    +  62  
         public static String getFileExtension(String fileName) {
    -  62  3
             final String fileExt = FilenameUtils.getExtension(fileName);
    -  63  3
             return null == fileExt || fileExt.isEmpty() ? null : fileExt.toLowerCase();
    -  64   -
         }
    +  63  3
             final String fileExt = FilenameUtils.getExtension(fileName);
    +  64  3
             return null == fileExt || fileExt.isEmpty() ? null : fileExt.toLowerCase();
     65   -
     
    +
         }
     66   -
         /**
    +
     
     67   -
          * Deletes a file. If the File is a directory it will recursively delete the contents.
    +
         /**
     68   -
          *
    +
          * Deletes a file. If the File is a directory it will recursively delete the contents.
     69   -
          * @param file the File to delete
    +
          *
     70   -
          * @return true if the file was deleted successfully, otherwise false
    +
          * @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) {
    -  73  3
             final boolean success = org.apache.commons.io.FileUtils.deleteQuietly(file);
    -  74  3
             if (!success) {
    -  75  0
                 LOGGER.debug("Failed to delete file: {}; attempting to delete on exit.", file.getPath());
    -  76  0
                 file.deleteOnExit();
    -  77   +  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  
             }
    -  78  3
             return success;
    -  79   -
         }
    +  79  3
             return success;
     80   -
     
    +
         }
     81   -
         /**
    -  82   -
          * Generates a new temporary file name that is guaranteed to be unique.
    -  83   -
          *
    -  84   -
          * @param prefix the prefix for the file name to generate
    -  85   -
          * @param extension the extension of the generated file name
    -  86   -
          * @return a temporary File
    -  87   -
          * @throws java.io.IOException thrown if the temporary folder could not be created
    -  88   -
          */
    -  89   -
         public static File getTempFile(String prefix, String extension) throws IOException {
    -  90  0
             final File dir = Settings.getTempDirectory();
    -  91  0
             final String tempFileName = String.format("%s%s.%s", prefix, UUID.randomUUID().toString(), extension);
    -  92  0
             final File tempFile = new File(dir, tempFileName);
    -  93  0
             if (tempFile.exists()) {
    -  94  0
                 return getTempFile(prefix, extension);
    -  95   -
             }
    -  96  0
             return tempFile;
    -  97   -
         }
    -  98  
     
    -  99   +  82  
         /**
    -  100   -
          * Return the bit bucket for the OS. '/dev/null' for Unix and 'NUL' for Windows
    -  101   +  83   +
          * Generates a new temporary file name that is guaranteed to be unique.
    +  84  
          *
    -  102   -
          * @return a String containing the bit bucket
    -  103   +  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  
          */
    -  104   -
         public static String getBitBucket() {
    -  105  0
             if (System.getProperty("os.name").startsWith("Windows")) {
    -  106  0
                 return BIT_BUCKET_WIN;
    -  107   -
             } else {
    -  108  0
                 return BIT_BUCKET_UNIX;
    -  109   +  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  
             }
    -  110   +  97  0
             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  0
             if (SystemUtils.IS_OS_WINDOWS) {
    +  107  0
                 return BIT_BUCKET_WIN;
    +  108   +
             } else {
    +  109  0
                 return BIT_BUCKET_UNIX;
    +  110   +
             }
     111   +
         }
    +  112  
     }
    - + 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 39a4f8f8b..ba93242f3 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 dfe30d962..fcad99863 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/84
    0%
    0/10
    1.625
    SSLSocketFactoryEx
    0%
    0/62
    0%
    0/6
    1.4
     
    @@ -167,7 +167,7 @@
         @Override
     80  
         public String[] getDefaultCipherSuites() {
    -  81  0
             return Arrays.copyOf(ciphers, ciphers.length);
    +  81  0
             return sslCtxt.getSocketFactory().getDefaultCipherSuites();
     82  
         }
     83   @@ -186,7 +186,7 @@
         @Override
     90  
         public String[] getSupportedCipherSuites() {
    -  91  0
             return Arrays.copyOf(ciphers, ciphers.length);
    +  91  0
             return sslCtxt.getSocketFactory().getSupportedCipherSuites();
     92  
         }
     93   @@ -254,457 +254,287 @@  126  
     
     127  0
             ss.setEnabledProtocols(protocols);
    -  128  0
             ss.setEnabledCipherSuites(ciphers);
    -  129   +  128  
     
    -  130  0
             return ss;
    +  129  0
             return ss;
    +  130   +
         }
     131   -
         }
    +
     
     132   -
     
    +
         /**
     133   -
         /**
    +
          * Creates a new SSL Socket.
     134   -
          * Creates a new SSL Socket.
    +
          *
     135   -
          *
    -  136  
          * @param address the address to connect to
    -  137   +  136  
          * @param port the port number
    -  138   +  137  
          * @param localAddress the local address
    +  138   +
          * @param localPort the local port
     139   -
          * @param localPort the local port
    +
          * @return the SSL Socket
     140   -
          * @return the SSL Socket
    +
          * @throws IOException thrown if the creation fails
     141   -
          * @throws IOException thrown if the creation fails
    +
          */
     142   -
          */
    +
         @Override
     143   -
         @Override
    -  144  
         public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
    -  145  0
             final SSLSocketFactory factory = sslCtxt.getSocketFactory();
    -  146  0
             final SSLSocket ss = (SSLSocket) factory.createSocket(address, port, localAddress, localPort);
    -  147   +  144  0
             final SSLSocketFactory factory = sslCtxt.getSocketFactory();
    +  145  0
             final SSLSocket ss = (SSLSocket) factory.createSocket(address, port, localAddress, localPort);
    +  146  
     
    -  148  0
             ss.setEnabledProtocols(protocols);
    -  149  0
             ss.setEnabledCipherSuites(ciphers);
    +  147  0
             ss.setEnabledProtocols(protocols);
    +  148   +
     
    +  149  0
             return ss;
     150   -
     
    -  151  0
             return ss;
    -  152  
         }
    -  153   +  151  
     
    -  154   +  152  
         /**
    -  155   +  153  
          * Creates a new SSL Socket.
    -  156   +  154  
          *
    -  157   +  155  
          * @param host the host to connect to
    -  158   +  156  
          * @param port the port to connect to
    -  159   +  157  
          * @param localHost the local host
    -  160   +  158  
          * @param localPort the local port
    -  161   +  159  
          * @return the SSL Socket
    -  162   +  160  
          * @throws IOException thrown if the creation fails
    -  163   +  161  
          */
    -  164   +  162  
         @Override
    -  165   +  163  
         public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
    -  166  0
             final SSLSocketFactory factory = sslCtxt.getSocketFactory();
    -  167  0
             final SSLSocket ss = (SSLSocket) factory.createSocket(host, port, localHost, localPort);
    +  164  0
             final SSLSocketFactory factory = sslCtxt.getSocketFactory();
    +  165  0
             final SSLSocket ss = (SSLSocket) factory.createSocket(host, port, localHost, localPort);
    +  166   +
     
    +  167  0
             ss.setEnabledProtocols(protocols);
     168  
     
    -  169  0
             ss.setEnabledProtocols(protocols);
    -  170  0
             ss.setEnabledCipherSuites(ciphers);
    +  169  0
             return ss;
    +  170   +
         }
     171  
     
    -  172  0
             return ss;
    +  172   +
         /**
     173   -
         }
    +
          * Creates a new SSL Socket.
     174   -
     
    +
          *
     175   -
         /**
    +
          * @param host the host to connect to
     176   -
          * Creates a new SSL Socket.
    +
          * @param port the port to connect to
     177   -
          *
    +
          * @return the SSL Socket
     178   -
          * @param host the host to connect to
    +
          * @throws IOException thrown if the creation fails
     179   -
          * @param port the port to connect to
    +
          */
     180   -
          * @return the SSL Socket
    +
         @Override
     181   -
          * @throws IOException thrown if the creation fails
    -  182   -
          */
    -  183   -
         @Override
    -  184  
         public Socket createSocket(InetAddress host, int port) throws IOException {
    -  185  0
             final SSLSocketFactory factory = sslCtxt.getSocketFactory();
    -  186  0
             final SSLSocket ss = (SSLSocket) factory.createSocket(host, port);
    -  187   +  182  0
             final SSLSocketFactory factory = sslCtxt.getSocketFactory();
    +  183  0
             final SSLSocket ss = (SSLSocket) factory.createSocket(host, port);
    +  184   +
     
    +  185  0
             ss.setEnabledProtocols(protocols);
    +  186   +
     
    +  187  0
             return ss;
    +  188   +
         }
    +  189  
     
    -  188  0
             ss.setEnabledProtocols(protocols);
    -  189  0
             ss.setEnabledCipherSuites(ciphers);
     190   -
     
    -  191  0
             return ss;
    -  192   -
         }
    -  193   -
     
    -  194  
         /**
    -  195   +  191  
          * Creates a new SSL Socket.
    -  196   +  192  
          *
    -  197   +  193  
          * @param host the host to connect to
    -  198   +  194  
          * @param port the port to connect to
    -  199   +  195  
          * @return the SSL Socket
    -  200   +  196  
          * @throws IOException thrown if the creation fails
    -  201   +  197  
          */
    -  202   +  198  
         @Override
    -  203   +  199  
         public Socket createSocket(String host, int port) throws IOException {
    -  204  0
             final SSLSocketFactory factory = sslCtxt.getSocketFactory();
    -  205  0
             final SSLSocket ss = (SSLSocket) factory.createSocket(host, port);
    +  200  0
             final SSLSocketFactory factory = sslCtxt.getSocketFactory();
    +  201  0
             final SSLSocket ss = (SSLSocket) factory.createSocket(host, port);
    +  202   +
     
    +  203  0
             ss.setEnabledProtocols(protocols);
    +  204   +
     
    +  205  0
             return ss;
     206   -
     
    -  207  0
             ss.setEnabledProtocols(protocols);
    -  208  0
             ss.setEnabledCipherSuites(ciphers);
    -  209   -
     
    -  210  0
             return ss;
    -  211  
         }
    -  212   +  207  
     
    -  213   +  208  
         /**
    -  214   +  209  
          * Initializes the SSL Socket Factory Extension.
    -  215   +  210  
          *
    -  216   +  211  
          * @param km the key managers
    -  217   +  212  
          * @param tm the trust managers
    -  218   +  213  
          * @param random the secure random number generator
    -  219   +  214  
          * @throws NoSuchAlgorithmException thrown when an algorithm is not
    -  220   +  215  
          * supported
    -  221   +  216  
          * @throws KeyManagementException thrown if initialization fails
    -  222   +  217  
          */
    -  223   +  218  
         private void initSSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random)
    -  224   +  219  
                 throws NoSuchAlgorithmException, KeyManagementException {
    -  225  0
             sslCtxt = SSLContext.getInstance("TLS");
    -  226  0
             sslCtxt.init(km, tm, random);
    +  220  0
             sslCtxt = SSLContext.getInstance("TLS");
    +  221  0
             sslCtxt.init(km, tm, random);
    +  222   +
     
    +  223  0
             protocols = getProtocolList();
    +  224  0
         }
    +  225   +
     
    +  226   +
         /**
     227   -
     
    -  228  0
             protocols = getProtocolList();
    -  229  0
             ciphers = getCipherList();
    -  230  0
         }
    -  231   -
     
    -  232   -
         /**
    -  233  
          * Initializes the SSL Socket Factory Extension.
    -  234   +  228  
          *
    -  235   +  229  
          * @param ctx the SSL context
    -  236   +  230  
          * @throws NoSuchAlgorithmException thrown when an algorithm is not
    -  237   +  231  
          * supported
    -  238   +  232  
          * @throws KeyManagementException thrown if initialization fails
    -  239   +  233  
          */
    -  240   +  234  
         private void initSSLSocketFactoryEx(SSLContext ctx)
    -  241   +  235  
                 throws NoSuchAlgorithmException, KeyManagementException {
    -  242  0
             sslCtxt = ctx;
    -  243   +  236  0
             sslCtxt = ctx;
    +  237  0
             protocols = getProtocolList();
    +  238  0
         }
    +  239  
     
    -  244  0
             protocols = getProtocolList();
    -  245  0
             ciphers = getCipherList();
    -  246  0
         }
    -  247   -
     
    -  248   +  240  
         /**
    -  249   +  241  
          * Returns the protocol list.
    -  250   +  242  
          *
    -  251   +  243  
          * @return the protocol list
    -  252   +  244  
          */
    -  253   +  245  
         protected String[] getProtocolList() {
    -  254  0
             final String[] preferredProtocols = {"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"};
    -  255  0
             String[] availableProtocols = null;
    -  256   +  246  0
             final String[] preferredProtocols = {"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"};
    +  247  0
             String[] availableProtocols = null;
    +  248  
     
    -  257  0
             SSLSocket socket = null;
    -  258   +  249  0
             SSLSocket socket = null;
    +  250  
     
    -  259   +  251  
             try {
    -  260  0
                 final SSLSocketFactory factory = sslCtxt.getSocketFactory();
    -  261  0
                 socket = (SSLSocket) factory.createSocket();
    -  262   +  252  0
                 final SSLSocketFactory factory = sslCtxt.getSocketFactory();
    +  253  0
                 socket = (SSLSocket) factory.createSocket();
    +  254  
     
    -  263  0
                 availableProtocols = socket.getSupportedProtocols();
    -  264  0
                 Arrays.sort(availableProtocols);
    -  265  0
             } catch (Exception ex) {
    -  266  0
                 LOGGER.debug("Error getting protocol list, using TLSv1", ex);
    -  267  0
                 return new String[]{"TLSv1"};
    -  268   +  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 {
    -  269  0
                 if (socket != null) {
    -  270   +  261  0
                 if (socket != null) {
    +  262  
                     try {
    -  271  0
                         socket.close();
    -  272  0
                     } catch (IOException ex) {
    -  273  0
                         LOGGER.trace("Error closing socket", ex);
    -  274  0
                     }
    +  263  0
                         socket.close();
    +  264  0
                     } catch (IOException ex) {
    +  265  0
                         LOGGER.trace("Error closing socket", ex);
    +  266  0
                     }
    +  267   +
                 }
    +  268   +
             }
    +  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  
                 }
     276  
             }
     277  
     
    -  278  0
             final List<String> aa = new ArrayList<String>();
    -  279  0
             for (String preferredProtocol : preferredProtocols) {
    -  280  0
                 final int idx = Arrays.binarySearch(availableProtocols, preferredProtocol);
    -  281  0
                 if (idx >= 0) {
    -  282  0
                     aa.add(preferredProtocol);
    -  283   -
                 }
    -  284   -
             }
    -  285   -
     
    -  286  0
             return aa.toArray(new String[0]);
    -  287   +  278  0
             return aa.toArray(new String[0]);
    +  279  
         }
    -  288   +  280  
     
    -  289   +  281  
         /**
    -  290   -
          * Returns the cipher list.
    -  291   -
          *
    -  292   -
          * @return the cipher list
    -  293   -
          */
    -  294   -
         protected String[] getCipherList() {
    -  295  0
             final String[] preferredCiphers = {
    -  296   -
                 // *_CHACHA20_POLY1305 are 3x to 4x faster than existing cipher suites.
    -  297   -
                 //   http://googleonlinesecurity.blogspot.com/2014/04/speeding-up-and-strengthening-https.html
    -  298   -
                 // Use them if available. Normative names can be found at (TLS spec depends on IPSec spec):
    -  299   -
                 //   http://tools.ietf.org/html/draft-nir-ipsecme-chacha20-poly1305-01
    -  300   -
                 //   http://tools.ietf.org/html/draft-mavrogiannopoulos-chacha-tls-02
    -  301   -
                 "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
    -  302   -
                 "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
    -  303   -
                 "TLS_ECDHE_ECDSA_WITH_CHACHA20_SHA",
    -  304   -
                 "TLS_ECDHE_RSA_WITH_CHACHA20_SHA",
    -  305   -
                 "TLS_DHE_RSA_WITH_CHACHA20_POLY1305",
    -  306   -
                 "TLS_RSA_WITH_CHACHA20_POLY1305",
    -  307   -
                 "TLS_DHE_RSA_WITH_CHACHA20_SHA",
    -  308   -
                 "TLS_RSA_WITH_CHACHA20_SHA",
    -  309   -
                 // Done with bleeding edge, back to TLS v1.2 and below
    -  310   -
                 "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
    -  311   -
                 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
    -  312   -
                 "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
    -  313   -
                 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
    -  314   -
                 "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
    -  315   -
                 "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
    -  316   -
                 "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
    -  317   -
                 "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
    -  318   -
                 // TLS v1.0 (with some SSLv3 interop)
    -  319   -
                 "TLS_DHE_RSA_WITH_AES_256_CBC_SHA384",
    -  320   -
                 "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
    -  321   -
                 "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
    -  322   -
                 "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
    -  323   -
                 "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
    -  324   -
                 "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
    -  325   -
                 "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA",
    -  326   -
                 "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA",
    -  327   -
                 // RSA key transport sucks, but they are needed as a fallback.
    -  328   -
                 // For example, microsoft.com fails under all versions of TLS
    -  329   -
                 // if they are not included. If only TLS 1.0 is available at
    -  330   -
                 // the client, then google.com will fail too. TLS v1.3 is
    -  331   -
                 // trying to deprecate them, so it will be interesteng to see
    -  332   -
                 // what happens.
    -  333   -
                 "TLS_RSA_WITH_AES_256_CBC_SHA256",
    -  334   -
                 "TLS_RSA_WITH_AES_256_CBC_SHA",
    -  335   -
                 "TLS_RSA_WITH_AES_128_CBC_SHA256",
    -  336   -
                 "TLS_RSA_WITH_AES_128_CBC_SHA",
    -  337   -
             };
    -  338   -
     
    -  339   -
             String[] availableCiphers;
    -  340   -
     
    -  341   -
             try {
    -  342  0
                 final SSLSocketFactory factory = sslCtxt.getSocketFactory();
    -  343  0
                 availableCiphers = factory.getSupportedCipherSuites();
    -  344  0
                 Arrays.sort(availableCiphers);
    -  345  0
             } catch (Exception e) {
    -  346  0
                 LOGGER.debug("Error retrieving ciphers", e);
    -  347  0
                 return new String[]{
    -  348   -
                     "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
    -  349   -
                     "TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
    -  350   -
                     "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
    -  351   -
                     "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
    -  352   -
                     "TLS_RSA_WITH_AES_256_CBC_SHA256",
    -  353   -
                     "TLS_RSA_WITH_AES_256_CBC_SHA",
    -  354   -
                     "TLS_RSA_WITH_AES_128_CBC_SHA256",
    -  355   -
                     "TLS_RSA_WITH_AES_128_CBC_SHA",
    -  356   -
                     "TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
    -  357   -
                 };
    -  358  0
             }
    -  359   -
     
    -  360  0
             final List<String> aa = new ArrayList<String>();
    -  361  0
             for (String preferredCipher : preferredCiphers) {
    -  362  0
                 final int idx = Arrays.binarySearch(availableCiphers, preferredCipher);
    -  363  0
                 if (idx >= 0) {
    -  364  0
                     aa.add(preferredCipher);
    -  365   -
                 }
    -  366   -
             }
    -  367   -
     
    -  368  0
             aa.add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV");
    -  369   -
     
    -  370  0
             return aa.toArray(new String[0]);
    -  371   -
         }
    -  372   -
     
    -  373   -
         /**
    -  374   +  282  
          * The SSL context.
    -  375   +  283  
          */
    -  376   +  284  
         private SSLContext sslCtxt;
    -  377   +  285  
         /**
    -  378   -
          * The cipher suites.
    -  379   -
          */
    -  380   -
         private String[] ciphers;
    -  381   -
         /**
    -  382   +  286  
          * The protocols.
    -  383   +  287  
          */
    -  384   +  288  
         private String[] protocols;
    -  385   +  289  
     }
    - + 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 b25fc89a5..226127016 100644 --- a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.Settings.html +++ b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.Settings.html @@ -131,7 +131,7 @@  57  
              */
     58   -
             public static final String APPLICATION_VAME = "application.name";
    +
             public static final String APPLICATION_NAME = "application.name";
     59  
             /**
     60   @@ -599,210 +599,212 @@  291  
             /**
     292   -
              * The properties key for the Central search URL.
    +
              * The properties key for whether the cocoapods analyzer is enabled.
     293  
              */
     294   -
             public static final String ANALYZER_CENTRAL_URL = "analyzer.central.url";
    +
             public static final String ANALYZER_COCOAPODS_ENABLED = "analyzer.cocoapods.enabled";
     295  
             /**
     296   -
              * The path to mono, if available.
    +
              * The properties key for whether the SWIFT package manager analyzer is enabled.
     297  
              */
     298   -
             public static final String ANALYZER_ASSEMBLY_MONO_PATH = "analyzer.assembly.mono.path";
    +
             public static final String ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED = "analyzer.swift.package.manager.enabled";
     299  
             /**
     300   -
              * The path to bundle-audit, if available.
    +
              * The properties key for the Central search URL.
     301  
              */
     302   -
             public static final String ANALYZER_BUNDLE_AUDIT_PATH = "analyzer.bundle.audit.path";
    +
             public static final String ANALYZER_CENTRAL_URL = "analyzer.central.url";
     303  
             /**
     304   -
              * The additional configured zip file extensions, if available.
    +
              * The path to mono, if available.
     305  
              */
     306   -
             public static final String ADDITIONAL_ZIP_EXTENSIONS = "extensions.zip";
    +
             public static final String ANALYZER_ASSEMBLY_MONO_PATH = "analyzer.assembly.mono.path";
     307  
             /**
     308   -
              * The key to obtain the path to the VFEED data file.
    +
              * The path to bundle-audit, if available.
     309  
              */
     310   -
             public static final String VFEED_DATA_FILE = "vfeed.data_file";
    +
             public static final String ANALYZER_BUNDLE_AUDIT_PATH = "analyzer.bundle.audit.path";
     311  
             /**
     312   -
              * The key to obtain the VFEED connection string.
    +
              * The additional configured zip file extensions, if available.
     313  
              */
     314   -
             public static final String VFEED_CONNECTION_STRING = "vfeed.connection_string";
    +
             public static final String ADDITIONAL_ZIP_EXTENSIONS = "extensions.zip";
     315   -
     
    +
             /**
     316   -
             /**
    +
              * The key to obtain the path to the VFEED data file.
     317   -
              * The key to obtain the base download URL for the VFeed data file.
    +
              */
     318   -
              */
    +
             public static final String VFEED_DATA_FILE = "vfeed.data_file";
     319   -
             public static final String VFEED_DOWNLOAD_URL = "vfeed.download_url";
    -  320  
             /**
    +  320   +
              * The key to obtain the VFEED connection string.
     321   -
              * The key to obtain the download file name for the VFeed data.
    -  322  
              */
    +  322   +
             public static final String VFEED_CONNECTION_STRING = "vfeed.connection_string";
     323   -
             public static final String VFEED_DOWNLOAD_FILE = "vfeed.download_file";
    +
     
     324  
             /**
     325   -
              * The key to obtain the VFeed update status.
    +
              * The key to obtain the base download URL for the VFeed data file.
     326  
              */
     327   -
             public static final String VFEED_UPDATE_STATUS = "vfeed.update_status";
    +
             public static final String VFEED_DOWNLOAD_URL = "vfeed.download_url";
     328   -
     
    -  329  
             /**
    +  329   +
              * The key to obtain the download file name for the VFeed data.
     330   -
              * The HTTP request method for query last modified date.
    -  331  
              */
    +  331   +
             public static final String VFEED_DOWNLOAD_FILE = "vfeed.download_file";
     332   -
             public static final String DOWNLOADER_QUICK_QUERY_TIMESTAMP = "downloader.quick.query.timestamp";
    +
             /**
     333   -
         }
    +
              * The key to obtain the VFeed update status.
     334   -
         //</editor-fold>
    +
              */
     335   -
     
    +
             public static final String VFEED_UPDATE_STATUS = "vfeed.update_status";
     336   -
         /**
    +
     
     337   -
          * The logger.
    +
             /**
     338   -
          */
    -  339  1
         private static final Logger LOGGER = LoggerFactory.getLogger(Settings.class);
    +
              * The HTTP request method for query last modified date.
    +  339   +
              */
     340   -
         /**
    +
             public static final String DOWNLOADER_QUICK_QUERY_TIMESTAMP = "downloader.quick.query.timestamp";
     341   -
          * The properties file location.
    +
         }
     342   -
          */
    +
         //</editor-fold>
     343   -
         private static final String PROPERTIES_FILE = "dependencycheck.properties";
    +
     
     344  
         /**
     345   -
          * Thread local settings.
    +
          * The logger.
     346  
          */
    -  347  1
         private static final ThreadLocal<Settings> LOCAL_SETTINGS = new ThreadLocal<Settings>();
    +  347  1
         private static final Logger LOGGER = LoggerFactory.getLogger(Settings.class);
     348  
         /**
     349   -
          * The properties.
    +
          * The properties file location.
     350  
          */
    -  351  2
         private Properties props = null;
    +  351   +
         private static final String PROPERTIES_FILE = "dependencycheck.properties";
     352   -
     
    -  353  
         /**
    +  353   +
          * Thread local settings.
     354   -
          * Private constructor for the Settings class. This class loads the
    -  355   -
          * properties files.
    +
          */
    +  355  1
         private static final ThreadLocal<Settings> LOCAL_SETTINGS = new ThreadLocal<Settings>();
     356   -
          *
    +
         /**
     357   -
          * @param propertiesFilePath the path to the base properties file to load
    +
          * The properties.
     358  
          */
    -  359  2
         private Settings(String propertiesFilePath) {
    -  360  2
             InputStream in = null;
    -  361  2
             props = new Properties();
    +  359  2
         private Properties props = null;
    +  360   +
     
    +  361   +
         /**
     362   -
             try {
    -  363  2
                 in = this.getClass().getClassLoader().getResourceAsStream(propertiesFilePath);
    -  364  2
                 props.load(in);
    -  365  0
             } catch (IOException ex) {
    -  366  0
                 LOGGER.error("Unable to load default settings.");
    -  367  0
                 LOGGER.debug("", ex);
    -  368   -
             } finally {
    -  369  2
                 if (in != null) {
    -  370   -
                     try {
    -  371  2
                         in.close();
    -  372  0
                     } catch (IOException ex) {
    -  373  0
                         LOGGER.trace("", ex);
    -  374  2
                     }
    -  375   -
                 }
    -  376   -
             }
    -  377  2
             logProperties("Properties loaded", props);
    -  378  2
         }
    -  379   -
     
    -  380   -
         /**
    -  381   -
          * Initializes the thread local settings object. Note, to use the settings
    -  382   -
          * object you must call this method. However, you must also call
    -  383   -
          * Settings.cleanup() to properly release resources.
    -  384   -
          */
    -  385   -
         public static void initialize() {
    -  386  2
             LOCAL_SETTINGS.set(new Settings(PROPERTIES_FILE));
    -  387  2
         }
    -  388   -
     
    -  389   -
         /**
    -  390   -
          * Initializes the thread local settings object. Note, to use the settings
    -  391   -
          * object you must call this method. However, you must also call
    -  392   -
          * Settings.cleanup() to properly release resources.
    -  393   +
          * Private constructor for the Settings class. This class loads the
    +  363   +
          * properties files.
    +  364  
          *
    -  394   +  365  
          * @param propertiesFilePath the path to the base properties file to load
    -  395   +  366  
          */
    -  396   -
         public static void initialize(String propertiesFilePath) {
    -  397  0
             LOCAL_SETTINGS.set(new Settings(propertiesFilePath));
    -  398  0
         }
    -  399   +  367  2
         private Settings(String propertiesFilePath) {
    +  368  2
             InputStream in = null;
    +  369  2
             props = new Properties();
    +  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  
     
    -  400   +  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   -
          * Cleans up resources to prevent memory leaks.
    -  402  
          *
    +  402   +
          * @param propertiesFilePath the path to the base properties file to load
     403  
          */
     404   -
         public static void cleanup() {
    -  405  0
             cleanup(true);
    +
         public static void initialize(String propertiesFilePath) {
    +  405  0
             LOCAL_SETTINGS.set(new Settings(propertiesFilePath));
     406  0
         }
     407  
     
    @@ -813,885 +815,899 @@  410  
          *
     411   -
          * @param deleteTemporary flag indicating whether any temporary directories
    +
          */
     412   -
          * generated should be removed
    -  413   -
          */
    -  414   -
         public static void cleanup(boolean deleteTemporary) {
    -  415  2
             if (deleteTemporary && tempDirectory != null && tempDirectory.exists()) {
    -  416  2
                 FileUtils.delete(tempDirectory);
    -  417  2
                 if (tempDirectory.exists()) {
    +
         public static void cleanup() {
    +  413  0
             cleanup(true);
    +  414  0
         }
    +  415   +
     
    +  416   +
         /**
    +  417   +
          * Cleans up resources to prevent memory leaks.
     418   -
                     try {
    -  419  0
                         Thread.sleep(2000);
    -  420  0
                     } catch (InterruptedException ex) {
    -  421  0
                         LOGGER.trace("ignore", ex);
    -  422  0
                     }
    -  423  0
                     FileUtils.delete(tempDirectory);
    -  424   -
                 }
    -  425   -
             }
    +
          *
    +  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()) {
     426   -
             try {
    -  427  2
                 LOCAL_SETTINGS.remove();
    -  428  0
             } catch (Throwable ex) {
    -  429  0
                 LOGGER.debug("Error cleaning up Settings", ex);
    -  430  2
             }
    -  431  2
         }
    +
                     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   -
         /**
    +
             }
     434   -
          * Gets the underlying instance of the Settings object.
    -  435   -
          *
    -  436   -
          * @return the Settings object
    -  437   -
          */
    -  438   -
         public static Settings getInstance() {
    -  439  0
             return LOCAL_SETTINGS.get();
    +
             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   -
         }
    +
     
     441   -
     
    +
         /**
     442   -
         /**
    +
          * Gets the underlying instance of the Settings object.
     443   -
          * Sets the instance of the Settings object to use in this thread.
    +
          *
     444   -
          *
    +
          * @return the Settings object
     445   -
          * @param instance the instance of the settings object to use in this thread
    +
          */
     446   -
          */
    -  447   -
         public static void setInstance(Settings instance) {
    -  448  0
             LOCAL_SETTINGS.set(instance);
    -  449  0
         }
    -  450   -
     
    -  451   -
         /**
    -  452   -
          * Logs the properties. This will not log any properties that contain
    -  453   -
          * 'password' in the key.
    -  454   -
          *
    -  455   -
          * @param header the header to print with the log message
    -  456   -
          * @param properties the properties to log
    -  457   -
          */
    -  458   -
         private static void logProperties(String header, Properties properties) {
    -  459  3
             if (LOGGER.isDebugEnabled()) {
    -  460  0
                 final StringWriter sw = new StringWriter();
    -  461  0
                 PrintWriter pw = null;
    -  462   -
                 try {
    -  463  0
                     pw = new PrintWriter(sw);
    -  464  0
                     pw.format("%s:%n%n", header);
    -  465  0
                     final Enumeration<?> e = properties.propertyNames();
    -  466  0
                     while (e.hasMoreElements()) {
    -  467  0
                         final String key = (String) e.nextElement();
    -  468  0
                         if (key.contains("password")) {
    -  469  0
                             pw.format("%s='*****'%n", key);
    -  470   -
                         } else {
    -  471  0
                             final String value = properties.getProperty(key);
    -  472  0
                             if (value != null) {
    -  473  0
                                 pw.format("%s='%s'%n", key, value);
    -  474   -
                             }
    -  475   -
                         }
    -  476  0
                     }
    -  477  0
                     pw.flush();
    -  478  0
                     LOGGER.debug(sw.toString());
    -  479   -
                 } finally {
    -  480  0
                     if (pw != null) {
    -  481  0
                         pw.close();
    -  482   -
                     }
    -  483   -
                 }
    -  484   -
     
    -  485   -
             }
    -  486  3
         }
    -  487   -
     
    -  488   -
         /**
    -  489   -
          * Sets a property value.
    -  490   -
          *
    -  491   -
          * @param key the key for the property
    -  492   -
          * @param value the value for the property
    -  493   -
          */
    -  494   -
         public static void setString(String key, String value) {
    -  495  8
             LOCAL_SETTINGS.get().props.setProperty(key, value);
    -  496  8
             LOGGER.debug("Setting: {}='{}'", key, value);
    -  497  8
         }
    -  498   -
     
    -  499   -
         /**
    -  500   -
          * Sets a property value only if the value is not null.
    -  501   -
          *
    -  502   -
          * @param key the key for the property
    -  503   -
          * @param value the value for the property
    -  504   -
          */
    -  505   -
         public static void setStringIfNotNull(String key, String value) {
    -  506  1
             if (null != value) {
    -  507  0
                 setString(key, value);
    -  508   -
             }
    -  509  1
         }
    -  510   -
     
    -  511   -
         /**
    -  512   -
          * Sets a property value only if the value is not null and not empty.
    -  513   -
          *
    -  514   -
          * @param key the key for the property
    -  515   -
          * @param value the value for the property
    -  516   -
          */
    -  517   -
         public static void setStringIfNotEmpty(String key, String value) {
    -  518  1
             if (null != value && !value.isEmpty()) {
    -  519  0
                 setString(key, value);
    -  520   -
             }
    -  521  1
         }
    -  522   -
     
    -  523   -
         /**
    -  524   -
          * Sets a property value.
    -  525   -
          *
    -  526   -
          * @param key the key for the property
    -  527   -
          * @param value the value for the property
    -  528   -
          */
    -  529   -
         public static void setBoolean(String key, boolean value) {
    -  530  0
             setString(key, Boolean.toString(value));
    -  531  0
         }
    -  532   -
     
    -  533   -
         /**
    -  534   -
          * Sets a property value only if the value is not null.
    -  535   -
          *
    -  536   -
          * @param key the key for the property
    -  537   -
          * @param value the value for the property
    -  538   -
          */
    -  539   -
         public static void setBooleanIfNotNull(String key, Boolean value) {
    -  540  0
             if (null != value) {
    -  541  0
                 setBoolean(key, value);
    -  542   -
             }
    -  543  0
         }
    -  544   -
     
    -  545   -
         /**
    -  546   -
          * Sets a property value.
    -  547   -
          *
    -  548   -
          * @param key the key for the property
    -  549   -
          * @param value the value for the property
    -  550   -
          */
    -  551   -
         public static void setInt(String key, int value) {
    -  552  0
             LOCAL_SETTINGS.get().props.setProperty(key, String.valueOf(value));
    -  553  0
             LOGGER.debug("Setting: {}='{}'", key, value);
    -  554  0
         }
    -  555   -
     
    -  556   -
         /**
    -  557   -
          * Sets a property value only if the value is not null.
    -  558   -
          *
    -  559   -
          * @param key the key for the property
    -  560   -
          * @param value the value for the property
    -  561   -
          */
    -  562   -
         public static void setIntIfNotNull(String key, Integer value) {
    -  563  0
             if (null != value) {
    -  564  0
                 setInt(key, value);
    -  565   -
             }
    -  566  0
         }
    -  567   -
     
    -  568   -
         /**
    -  569   -
          * Merges a new properties file into the current properties. This method
    -  570   -
          * allows for the loading of a user provided properties file.<br><br>
    -  571   -
          * <b>Note</b>: even if using this method - system properties will be loaded
    -  572   -
          * before properties loaded from files.
    -  573   -
          *
    -  574   -
          * @param filePath the path to the properties file to merge.
    -  575   -
          * @throws FileNotFoundException is thrown when the filePath points to a
    -  576   -
          * non-existent file
    -  577   -
          * @throws IOException is thrown when there is an exception loading/merging
    -  578   -
          * the properties
    -  579   -
          */
    -  580   -
         public static void mergeProperties(File filePath) throws FileNotFoundException, IOException {
    -  581  0
             FileInputStream fis = null;
    -  582   -
             try {
    -  583  0
                 fis = new FileInputStream(filePath);
    -  584  0
                 mergeProperties(fis);
    -  585   -
             } finally {
    -  586  0
                 if (fis != null) {
    -  587   -
                     try {
    -  588  0
                         fis.close();
    -  589  0
                     } catch (IOException ex) {
    -  590  0
                         LOGGER.trace("close error", ex);
    -  591  0
                     }
    -  592   -
                 }
    -  593   -
             }
    -  594  0
         }
    -  595   -
     
    -  596   -
         /**
    -  597   -
          * Merges a new properties file into the current properties. This method
    -  598   -
          * allows for the loading of a user provided properties file.<br><br>
    -  599   -
          * Note: even if using this method - system properties will be loaded before
    -  600   -
          * properties loaded from files.
    -  601   -
          *
    -  602   -
          * @param filePath the path to the properties file to merge.
    -  603   -
          * @throws FileNotFoundException is thrown when the filePath points to a
    -  604   -
          * non-existent file
    -  605   -
          * @throws IOException is thrown when there is an exception loading/merging
    -  606   -
          * the properties
    -  607   -
          */
    -  608   -
         public static void mergeProperties(String filePath) throws FileNotFoundException, IOException {
    -  609  1
             FileInputStream fis = null;
    -  610   -
             try {
    -  611  1
                 fis = new FileInputStream(filePath);
    -  612  1
                 mergeProperties(fis);
    -  613   -
             } finally {
    -  614  1
                 if (fis != null) {
    -  615   -
                     try {
    -  616  1
                         fis.close();
    -  617  0
                     } catch (IOException ex) {
    -  618  0
                         LOGGER.trace("close error", ex);
    -  619  1
                     }
    -  620   -
                 }
    -  621   -
             }
    -  622  1
         }
    -  623   -
     
    -  624   -
         /**
    -  625   -
          * Merges a new properties file into the current properties. This method
    -  626   -
          * allows for the loading of a user provided properties file.<br><br>
    -  627   -
          * <b>Note</b>: even if using this method - system properties will be loaded
    -  628   -
          * before properties loaded from files.
    -  629   -
          *
    -  630   -
          * @param stream an Input Stream pointing at a properties file to merge
    -  631   -
          * @throws IOException is thrown when there is an exception loading/merging
    -  632   -
          * the properties
    -  633   -
          */
    -  634   -
         public static void mergeProperties(InputStream stream) throws IOException {
    -  635  1
             LOCAL_SETTINGS.get().props.load(stream);
    -  636  1
             logProperties("Properties updated via merge", LOCAL_SETTINGS.get().props);
    -  637  1
         }
    -  638   -
     
    -  639   -
         /**
    -  640   -
          * Returns a value from the properties file as a File object. If the value
    -  641   -
          * was specified as a system property or passed in via the -Dprop=value
    -  642   -
          * argument - this method will return the value from the system properties
    -  643   -
          * before the values in the contained configuration file.
    -  644   -
          *
    -  645   -
          * @param key the key to lookup within the properties file
    -  646   -
          * @return the property from the properties file converted to a File object
    -  647   -
          */
    -  648   -
         public static File getFile(String key) {
    -  649  0
             final String file = getString(key);
    -  650  0
             if (file == null) {
    -  651  0
                 return null;
    -  652   -
             }
    -  653  0
             return new File(file);
    -  654   +
         public static Settings getInstance() {
    +  447  0
             return LOCAL_SETTINGS.get();
    +  448  
         }
    -  655   +  449  
     
    -  656   +  450  
         /**
    -  657   -
          * Returns a value from the properties file as a File object. If the value
    -  658   -
          * was specified as a system property or passed in via the -Dprop=value
    -  659   -
          * argument - this method will return the value from the system properties
    -  660   -
          * before the values in the contained configuration file.
    -  661   +  451   +
          * Sets the instance of the Settings object to use in this thread.
    +  452  
          *
    -  662   -
          * This method will check the configured base directory and will use this as
    -  663   -
          * the base of the file path. Additionally, if the base directory begins
    -  664   -
          * with a leading "[JAR]\" sequence with the path to the folder containing
    -  665   -
          * the JAR file containing this class.
    -  666   -
          *
    -  667   -
          * @param key the key to lookup within the properties file
    -  668   -
          * @return the property from the properties file converted to a File object
    -  669   +  453   +
          * @param instance the instance of the settings object to use in this thread
    +  454  
          */
    -  670   -
         protected static File getDataFile(String key) {
    -  671  2
             final String file = getString(key);
    -  672  2
             LOGGER.debug("Settings.getDataFile() - file: '{}'", file);
    -  673  2
             if (file == null) {
    -  674  0
                 return null;
    -  675   +  455   +
         public static void setInstance(Settings instance) {
    +  456  0
             LOCAL_SETTINGS.set(instance);
    +  457  0
         }
    +  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  3
             if (LOGGER.isDebugEnabled()) {
    +  468  0
                 final StringWriter sw = new StringWriter();
    +  469  0
                 PrintWriter pw = null;
    +  470   +
                 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   +
                         } else {
    +  479  0
                             final String value = properties.getProperty(key);
    +  480  0
                             if (value != null) {
    +  481  0
                                 pw.format("%s='%s'%n", key, value);
    +  482   +
                             }
    +  483   +
                         }
    +  484  0
                     }
    +  485  0
                     pw.flush();
    +  486  0
                     LOGGER.debug(sw.toString());
    +  487   +
                 } finally {
    +  488  0
                     if (pw != null) {
    +  489  0
                         pw.close();
    +  490   +
                     }
    +  491   +
                 }
    +  492   +
     
    +  493  
             }
    -  676  2
             if (file.startsWith("[JAR]")) {
    -  677  0
                 LOGGER.debug("Settings.getDataFile() - transforming filename");
    -  678  0
                 final File jarPath = getJarPath();
    -  679  0
                 LOGGER.debug("Settings.getDataFile() - jar file: '{}'", jarPath.toString());
    -  680  0
                 final File retVal = new File(jarPath, file.substring(6));
    -  681  0
                 LOGGER.debug("Settings.getDataFile() - returning: '{}'", retVal.toString());
    -  682  0
                 return retVal;
    +  494  3
         }
    +  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  8
             LOCAL_SETTINGS.get().props.setProperty(key, value);
    +  504  8
             LOGGER.debug("Setting: {}='{}'", key, value);
    +  505  8
         }
    +  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  1
             if (null != value) {
    +  515  0
                 setString(key, value);
    +  516   +
             }
    +  517  1
         }
    +  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  1
             if (null != value && !value.isEmpty()) {
    +  527  0
                 setString(key, value);
    +  528   +
             }
    +  529  1
         }
    +  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  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   +
          *
    +  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  0
             LOCAL_SETTINGS.get().props.setProperty(key, String.valueOf(value));
    +  561  0
             LOGGER.debug("Setting: {}='{}'", key, value);
    +  562  0
         }
    +  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  0
             if (null != value) {
    +  572  0
                 setInt(key, value);
    +  573   +
             }
    +  574  0
         }
    +  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  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   +
          * 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  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
             return new File(file);
    -  685   -
         }
    -  686   -
     
    -  687   -
         /**
    -  688   -
          * Attempts to retrieve the folder containing the Jar file containing the
    -  689   -
          * Settings class.
    -  690   -
          *
    +  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   -
          * @return a File object
    -  692   -
          */
    -  693   -
         private static File getJarPath() {
    -  694  0
             final String jarPath = Settings.class.getProtectionDomain().getCodeSource().getLocation().getPath();
    -  695  0
             String decodedPath = ".";
    -  696   -
             try {
    -  697  0
                 decodedPath = URLDecoder.decode(jarPath, "UTF-8");
    -  698  0
             } catch (UnsupportedEncodingException ex) {
    -  699  0
                 LOGGER.trace("", ex);
    -  700  0
             }
    -  701   -
     
    -  702  0
             final File path = new File(decodedPath);
    -  703  0
             if (path.getName().toLowerCase().endsWith(".jar")) {
    -  704  0
                 return path.getParentFile();
    -  705   -
             } else {
    -  706  0
                 return new File(".");
    -  707  
             }
    -  708   +  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   +
             try {
    +  705  0
                 decodedPath = URLDecoder.decode(jarPath, "UTF-8");
    +  706  0
             } catch (UnsupportedEncodingException ex) {
    +  707  0
                 LOGGER.trace("", ex);
    +  708  0
             }
     709  
     
    -  710   -
         /**
    -  711   -
          * Returns a value from the properties file. If the value was specified as a
    -  712   -
          * system property or passed in via the -Dprop=value argument - this method
    +  710  0
             final File path = new File(decodedPath);
    +  711  0
             if (path.getName().toLowerCase().endsWith(".jar")) {
    +  712  0
                 return path.getParentFile();
     713   -
          * will return the value from the system properties before the values in the
    -  714   -
          * contained configuration file.
    +
             } else {
    +  714  0
                 return new File(".");
     715   -
          *
    +
             }
     716   -
          * @param key the key to lookup within the properties file
    +
         }
     717   -
          * @param defaultValue the default value for the requested property
    +
     
     718   -
          * @return the property from the properties file
    +
         /**
     719   -
          */
    -  720   -
         public static String getString(String key, String defaultValue) {
    -  721  6
             final String str = System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key, defaultValue));
    -  722  6
             return str;
    -  723   -
         }
    -  724   -
     
    -  725   -
         /**
    -  726   -
          * A reference to the temporary directory; used incase it needs to be
    -  727   -
          * deleted during cleanup.
    -  728   -
          */
    -  729  1
         private static File tempDirectory = null;
    -  730   -
     
    -  731   -
         /**
    -  732   -
          * Returns the temporary directory.
    -  733   -
          *
    -  734   -
          * @return the temporary directory
    -  735   -
          * @throws java.io.IOException thrown if the temporary directory does not
    -  736   -
          * exist and cannot be created
    -  737   -
          */
    -  738   -
         public static File getTempDirectory() throws IOException {
    -  739  2
             final File tmpDir = new File(Settings.getString(Settings.KEYS.TEMP_DIRECTORY, System.getProperty("java.io.tmpdir")), "dctemp");
    -  740  2
             if (!tmpDir.exists() && !tmpDir.mkdirs()) {
    -  741  0
                 final String msg = String.format("Unable to make a temporary folder '%s'", tmpDir.getPath());
    -  742  0
                 throw new IOException(msg);
    -  743   -
             }
    -  744  2
             tempDirectory = tmpDir;
    -  745  2
             return tmpDir;
    -  746   -
         }
    -  747   -
     
    -  748   -
         /**
    -  749  
          * Returns a value from the properties file. If the value was specified as a
    -  750   +  720  
          * system property or passed in via the -Dprop=value argument - this method
    -  751   +  721  
          * will return the value from the system properties before the values in the
    -  752   +  722  
          * contained configuration file.
    -  753   +  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  6
             final String str = System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key, defaultValue));
    +  730  6
             return str;
    +  731   +
         }
    +  732   +
     
    +  733   +
         /**
    +  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   +
          *
    +  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  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);
    +  751   +
             }
    +  752  2
             tempDirectory = tmpDir;
    +  753  2
             return tmpDir;
     754   -
          * @param key the key to lookup within the properties file
    +
         }
     755   -
          * @return the property from the properties file
    +
     
     756   -
          */
    +
         /**
     757   -
         public static String getString(String key) {
    -  758  19
             return System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key));
    +
          * 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   -
          * Removes a property from the local properties collection. This is mainly
    +
          * @param key the key to lookup within the properties file
     763   -
          * used in test cases.
    +
          * @return the property from the properties file
     764   -
          *
    +
          */
     765   -
          * @param key the property key to remove
    -  766   -
          */
    +
         public static String getString(String key) {
    +  766  19
             return System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key));
     767   -
         public static void removeProperty(String key) {
    -  768  1
             LOCAL_SETTINGS.get().props.remove(key);
    -  769  1
         }
    +
         }
    +  768   +
     
    +  769   +
         /**
     770   -
     
    +
          * Removes a property from the local properties collection. This is mainly
     771   -
         /**
    +
          * used in test cases.
     772   -
          * Returns an int value from the properties file. If the value was specified
    +
          *
     773   -
          * as a system property or passed in via the -Dprop=value argument - this
    +
          * @param key the property key to remove
     774   -
          * method will return the value from the system properties before the values
    +
          */
     775   -
          * in the contained configuration file.
    -  776   -
          *
    -  777   -
          * @param key the key to lookup within the properties file
    +
         public static void removeProperty(String key) {
    +  776  1
             LOCAL_SETTINGS.get().props.remove(key);
    +  777  1
         }
     778   -
          * @return the property from the properties file
    +
     
     779   -
          * @throws InvalidSettingException is thrown if there is an error retrieving
    +
         /**
     780   -
          * the setting
    -  781   -
          */
    -  782   -
         public static int getInt(String key) throws InvalidSettingException {
    -  783   -
             try {
    -  784  1
                 return Integer.parseInt(Settings.getString(key));
    -  785  0
             } catch (NumberFormatException ex) {
    -  786  0
                 throw new InvalidSettingException("Could not convert property '" + key + "' to an int.", ex);
    -  787   -
             }
    -  788   -
         }
    -  789   -
     
    -  790   -
         /**
    -  791  
          * Returns an int value from the properties file. If the value was specified
    -  792   +  781  
          * as a system property or passed in via the -Dprop=value argument - this
    -  793   +  782  
          * method will return the value from the system properties before the values
    -  794   +  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  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);
     795   -
          *
    +
             }
     796   -
          * @param key the key to lookup within the properties file
    +
         }
     797   -
          * @param defaultValue the default value to return
    +
     
     798   -
          * @return the property from the properties file or the defaultValue if the
    +
         /**
     799   -
          * property does not exist or cannot be converted to an integer
    +
          * Returns an int value from the properties file. If the value was specified
     800   -
          */
    -  801   -
         public static int getInt(String key, int defaultValue) {
    -  802   -
             int value;
    -  803   -
             try {
    -  804  1
                 value = Integer.parseInt(Settings.getString(key));
    -  805  1
             } catch (NumberFormatException ex) {
    -  806  1
                 if (!Settings.getString(key, "").isEmpty()) {
    -  807  1
                     LOGGER.debug("Could not convert property '{}={}' to an int; using {} instead.", key, Settings.getString(key), defaultValue);
    -  808   -
                 }
    -  809  1
                 value = defaultValue;
    -  810  0
             }
    -  811  1
             return value;
    -  812   -
         }
    -  813   -
     
    -  814   -
         /**
    -  815   -
          * Returns a long value from the properties file. If the value was specified
    -  816  
          * as a system property or passed in via the -Dprop=value argument - this
    -  817   +  801  
          * method will return the value from the system properties before the values
    -  818   +  802  
          * in the contained configuration file.
    -  819   +  803  
          *
    -  820   +  804  
          * @param key the key to lookup within the properties file
    -  821   -
          * @return the property from the properties file
    -  822   -
          * @throws InvalidSettingException is thrown if there is an error retrieving
    -  823   -
          * the setting
    -  824   +  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  
          */
    -  825   -
         public static long getLong(String key) throws InvalidSettingException {
    -  826   +  809   +
         public static int getInt(String key, int defaultValue) {
    +  810   +
             int value;
    +  811  
             try {
    -  827  1
                 return Long.parseLong(Settings.getString(key));
    -  828  0
             } catch (NumberFormatException ex) {
    -  829  0
                 throw new InvalidSettingException("Could not convert property '" + key + "' to a long.", ex);
    +  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   +
                 }
    +  817  1
                 value = defaultValue;
    +  818  0
             }
    +  819  1
             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   -
          * Returns a boolean value from the properties file. If the value was
    -  835   -
          * specified as a system property or passed in via the
    -  836   -
          * <code>-Dprop=value</code> argument this method will return the value from
    -  837   -
          * the system properties before the values in the contained configuration
    +
             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);
     838   -
          * file.
    -  839   -
          *
    -  840   -
          * @param key the key to lookup within the properties file
    -  841   -
          * @return the property from the properties file
    -  842   -
          * @throws InvalidSettingException is thrown if there is an error retrieving
    -  843   -
          * the setting
    -  844   -
          */
    -  845   -
         public static boolean getBoolean(String key) throws InvalidSettingException {
    -  846  1
             return Boolean.parseBoolean(Settings.getString(key));
    -  847   -
         }
    -  848   -
     
    -  849   -
         /**
    -  850   -
          * Returns a boolean value from the properties file. If the value was
    -  851   -
          * specified as a system property or passed in via the
    -  852   -
          * <code>-Dprop=value</code> argument this method will return the value from
    -  853   -
          * the system properties before the values in the contained configuration
    -  854   -
          * file.
    -  855   -
          *
    -  856   -
          * @param key the key to lookup within the properties file
    -  857   -
          * @param defaultValue the default value to return if the setting does not
    -  858   -
          * exist
    -  859   -
          * @return the property from the properties file
    -  860   -
          * @throws InvalidSettingException is thrown if there is an error retrieving
    -  861   -
          * the setting
    -  862   -
          */
    -  863   -
         public static boolean getBoolean(String key, boolean defaultValue) throws InvalidSettingException {
    -  864  1
             return Boolean.parseBoolean(Settings.getString(key, Boolean.toString(defaultValue)));
    -  865   -
         }
    -  866   -
     
    -  867   -
         /**
    -  868   -
          * Returns a connection string from the configured properties. If the
    -  869   -
          * connection string contains a %s, this method will determine the 'data'
    -  870   -
          * directory and replace the %s with the path to the data directory. If the
    -  871   -
          * data directory does not exists it will be created.
    -  872   -
          *
    -  873   -
          * @param connectionStringKey the property file key for the connection
    -  874   -
          * string
    -  875   -
          * @param dbFileNameKey the settings key for the db filename
    -  876   -
          * @return the connection string
    -  877   -
          * @throws IOException thrown the data directory cannot be created
    -  878   -
          * @throws InvalidSettingException thrown if there is an invalid setting
    -  879   -
          */
    -  880   -
         public static String getConnectionString(String connectionStringKey, String dbFileNameKey)
    -  881   -
                 throws IOException, InvalidSettingException {
    -  882  2
             final String connStr = Settings.getString(connectionStringKey);
    -  883  2
             if (connStr == null) {
    -  884  1
                 final String msg = String.format("Invalid properties file; %s is missing.", connectionStringKey);
    -  885  1
                 throw new InvalidSettingException(msg);
    -  886  
             }
    -  887  1
             if (connStr.contains("%s")) {
    -  888  1
                 final File directory = getDataDirectory();
    -  889  1
                 String fileName = null;
    -  890  1
                 if (dbFileNameKey != null) {
    -  891  1
                     fileName = Settings.getString(dbFileNameKey);
    -  892   -
                 }
    -  893  1
                 if (fileName == null) {
    -  894  0
                     final String msg = String.format("Invalid properties file to get a file based connection string; '%s' must be defined.",
    -  895   -
                             dbFileNameKey);
    -  896  0
                     throw new InvalidSettingException(msg);
    -  897   -
                 }
    -  898  1
                 if (connStr.startsWith("jdbc:h2:file:") && fileName.endsWith(".h2.db")) {
    -  899  1
                     fileName = fileName.substring(0, fileName.length() - 6);
    +  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  1
             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  1
             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  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   +
             }
    +  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  
                 }
    -  901   -
                 // yes, for H2 this path won't actually exists - but this is sufficient to get the value needed
    -  902  1
                 final File dbFile = new File(directory, fileName);
    -  903  1
                 final String cString = String.format(connStr, dbFile.getCanonicalPath());
    -  904  1
                 LOGGER.debug("Connection String: '{}'", cString);
    -  905  1
                 return cString;
    -  906   -
             }
    -  907  0
             return connStr;
    +  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   +
                             dbFileNameKey);
    +  904  0
                     throw new InvalidSettingException(msg);
    +  905   +
                 }
    +  906  1
                 if (connStr.startsWith("jdbc:h2:file:") && fileName.endsWith(".h2.db")) {
    +  907  1
                     fileName = fileName.substring(0, fileName.length() - 6);
     908   -
         }
    +
                 }
     909   -
     
    -  910   -
         /**
    -  911   -
          * Retrieves the directory that the JAR file exists in so that we can ensure
    -  912   -
          * we always use a common data directory for the embedded H2 database. This
    -  913   -
          * is public solely for some unit tests; otherwise this should be private.
    +
                 // 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   -
          *
    -  915   -
          * @return the data directory to store data files
    -  916   -
          * @throws IOException is thrown if an IOException occurs of course...
    -  917   -
          */
    -  918   -
         public static File getDataDirectory() throws IOException {
    -  919  1
             final File path = Settings.getDataFile(Settings.KEYS.DATA_DIRECTORY);
    -  920  1
             if (path.exists() || path.mkdirs()) {
    -  921  1
                 return path;
    -  922  
             }
    -  923  0
             throw new IOException(String.format("Unable to create the data directory '%s'", path.getAbsolutePath()));
    -  924   +  915  0
             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  1
             final File path = Settings.getDataFile(Settings.KEYS.DATA_DIRECTORY);
    +  928  1
             if (path.exists() || path.mkdirs()) {
    +  929  1
                 return path;
    +  930   +
             }
    +  931  0
             throw new IOException(String.format("Unable to create the data directory '%s'", path.getAbsolutePath()));
    +  932   +
         }
    +  933  
     }
    - + 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 98050befb..bf5f16eab 100644 --- a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.URLConnectionFactory.html +++ b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.URLConnectionFactory.html @@ -79,282 +79,284 @@  30  
     import java.net.URL;
     31   -
     import java.security.KeyManagementException;
    +
     import java.net.URLConnection;
     32   -
     import java.security.NoSuchAlgorithmException;
    +
     import java.security.KeyManagementException;
     33   -
     import javax.net.ssl.HttpsURLConnection;
    +
     import java.security.NoSuchAlgorithmException;
     34   -
     import org.slf4j.Logger;
    +
     import javax.net.ssl.HttpsURLConnection;
     35   -
     import org.slf4j.LoggerFactory;
    +
     import org.slf4j.Logger;
     36   -
     
    +
     import org.slf4j.LoggerFactory;
     37   -
     /**
    +
     
     38   -
      * A URLConnection Factory to create new connections. This encapsulates several
    +
     /**
     39   -
      * configuration checks to ensure that the connection uses the correct proxy
    +
      * A URLConnection Factory to create new connections. This encapsulates several
     40   -
      * settings.
    +
      * configuration checks to ensure that the connection uses the correct proxy
     41   -
      *
    +
      * settings.
     42   -
      * @author Jeremy Long
    +
      *
     43   -
      */
    +
      * @author Jeremy Long
     44   -
     public final class URLConnectionFactory {
    +
      */
     45   -
     
    +
     public final class URLConnectionFactory {
     46   -
         /**
    +
     
     47   -
          * The logger.
    +
         /**
     48   +
          * The logger.
    +  49  
          */
    -  49  0
         private static final Logger LOGGER = LoggerFactory.getLogger(URLConnectionFactory.class);
    -  50   -
     
    +  50  0
         private static final Logger LOGGER = LoggerFactory.getLogger(URLConnectionFactory.class);
     51   -
         /**
    +
     
     52   -
          * Private constructor for this factory.
    +
         /**
     53   +
          * Private constructor for this factory.
    +  54  
          */
    -  54  0
         private URLConnectionFactory() {
    -  55  0
         }
    -  56   -
     
    +  55  0
         private URLConnectionFactory() {
    +  56  0
         }
     57   -
         /**
    +
     
     58   -
          * Utility method to create an HttpURLConnection. If the application is
    +
         /**
     59   -
          * configured to use a proxy this method will retrieve the proxy settings
    +
          * Utility method to create an HttpURLConnection. If the application is
     60   -
          * and use them when setting up the connection.
    +
          * configured to use a proxy this method will retrieve the proxy settings
     61   -
          *
    +
          * and use them when setting up the connection.
     62   -
          * @param url the url to connect to
    +
          *
     63   -
          * @return an HttpURLConnection
    -  64   -
          * @throws URLConnectionFailureException thrown if there is an exception
    -  65   -
          */
    -  66   -
         @SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE", justification = "Just being extra safe")
    -  67   -
         public static HttpURLConnection createHttpURLConnection(URL url) throws URLConnectionFailureException {
    -  68  0
             HttpURLConnection conn = null;
    -  69  0
             final String proxyUrl = Settings.getString(Settings.KEYS.PROXY_SERVER);
    -  70   -
     
    -  71   -
             try {
    -  72  0
                 if (proxyUrl != null && !matchNonProxy(url)) {
    -  73  0
                     final int proxyPort = Settings.getInt(Settings.KEYS.PROXY_PORT);
    -  74  0
                     final SocketAddress address = new InetSocketAddress(proxyUrl, proxyPort);
    -  75   -
     
    -  76  0
                     final String username = Settings.getString(Settings.KEYS.PROXY_USERNAME);
    -  77  0
                     final String password = Settings.getString(Settings.KEYS.PROXY_PASSWORD);
    -  78   -
     
    -  79  0
                     if (username != null && password != null) {
    -  80  0
                         final Authenticator auth = new Authenticator() {
    -  81   -
                             @Override
    -  82   -
                             public PasswordAuthentication getPasswordAuthentication() {
    -  83  0
                                 if (getRequestorType().equals(Authenticator.RequestorType.PROXY)) {
    -  84  0
                                     return new PasswordAuthentication(username, password.toCharArray());
    -  85   -
                                 }
    -  86  0
                                 return super.getPasswordAuthentication();
    -  87   -
                             }
    -  88   -
                         };
    -  89  0
                         Authenticator.setDefault(auth);
    -  90   -
                     }
    -  91   -
     
    -  92  0
                     final Proxy proxy = new Proxy(Proxy.Type.HTTP, address);
    -  93  0
                     conn = (HttpURLConnection) url.openConnection(proxy);
    -  94  0
                 } else {
    -  95  0
                     conn = (HttpURLConnection) url.openConnection();
    -  96   -
                 }
    -  97  0
                 final int timeout = Settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 10000);
    -  98  0
                 conn.setConnectTimeout(timeout);
    -  99  0
                 conn.setInstanceFollowRedirects(true);
    -  100  0
             } catch (IOException ex) {
    -  101  0
                 if (conn != null) {
    -  102   -
                     try {
    -  103  0
                         conn.disconnect();
    -  104   -
                     } finally {
    -  105  0
                         conn = null;
    -  106  0
                     }
    -  107   -
                 }
    -  108  0
                 throw new URLConnectionFailureException("Error getting connection.", ex);
    -  109  0
             }
    -  110  0
             configureTLS(url, conn);
    -  111  0
             return conn;
    -  112   -
         }
    -  113   -
     
    -  114   -
         /**
    -  115   -
          * Check if hostname matches nonProxy settings
    -  116   -
          *
    -  117  
          * @param url the url to connect to
    -  118   -
          * @return matching result. true: match nonProxy
    -  119   -
          */
    -  120   -
         private static boolean matchNonProxy(final URL url) {
    -  121  0
             final String host = url.getHost();
    -  122   -
     
    -  123   -
             // code partially from org.apache.maven.plugins.site.AbstractDeployMojo#getProxyInfo
    -  124  0
             final String nonProxyHosts = Settings.getString(Settings.KEYS.PROXY_NON_PROXY_HOSTS);
    -  125  0
             if (null != nonProxyHosts) {
    -  126  0
                 final String[] nonProxies = nonProxyHosts.split("(,)|(;)|(\\|)");
    -  127  0
                 for (final String nonProxyHost : nonProxies) {
    -  128   -
                     //if ( StringUtils.contains( nonProxyHost, "*" ) )
    -  129  0
                     if (null != nonProxyHost && nonProxyHost.contains("*")) {
    -  130   -
                         // Handle wildcard at the end, beginning or middle of the nonProxyHost
    -  131  0
                         final int pos = nonProxyHost.indexOf('*');
    -  132  0
                         final String nonProxyHostPrefix = nonProxyHost.substring(0, pos);
    -  133  0
                         final String nonProxyHostSuffix = nonProxyHost.substring(pos + 1);
    -  134   -
                         // prefix*
    -  135  0
                         if (!StringUtils.isEmpty(nonProxyHostPrefix) && host.startsWith(nonProxyHostPrefix) && StringUtils.isEmpty(nonProxyHostSuffix)) {
    -  136  0
                             return true;
    -  137   -
                         }
    -  138   -
                         // *suffix
    -  139  0
                         if (StringUtils.isEmpty(nonProxyHostPrefix) && !StringUtils.isEmpty(nonProxyHostSuffix) && host.endsWith(nonProxyHostSuffix)) {
    -  140  0
                             return true;
    -  141   -
                         }
    -  142   -
                         // prefix*suffix
    -  143  0
                         if (!StringUtils.isEmpty(nonProxyHostPrefix) && host.startsWith(nonProxyHostPrefix) && !StringUtils.isEmpty(nonProxyHostSuffix)
    -  144  0
                                 && host.endsWith(nonProxyHostSuffix)) {
    -  145  0
                             return true;
    -  146   -
                         }
    -  147  0
                     } else if (host.equals(nonProxyHost)) {
    -  148  0
                         return true;
    -  149   -
                     }
    -  150   -
                 }
    -  151   -
             }
    -  152  0
             return false;
    -  153   -
         }
    -  154   -
     
    -  155   -
         /**
    -  156   -
          * Utility method to create an HttpURLConnection. The use of a proxy here is
    -  157   -
          * optional as there may be cases where a proxy is configured but we don't
    -  158   -
          * want to use it (for example, if there's an internal repository
    -  159   -
          * configured)
    -  160   -
          *
    -  161   -
          * @param url the URL to connect to
    -  162   -
          * @param proxy whether to use the proxy (if configured)
    -  163   -
          * @return a newly constructed HttpURLConnection
    -  164   +  64   +
          * @return an HttpURLConnection
    +  65  
          * @throws URLConnectionFailureException thrown if there is an exception
    -  165   +  66  
          */
    -  166   -
         public static HttpURLConnection createHttpURLConnection(URL url, boolean proxy) throws URLConnectionFailureException {
    -  167  0
             if (proxy) {
    -  168  0
                 return createHttpURLConnection(url);
    -  169   -
             }
    -  170  0
             HttpURLConnection conn = null;
    -  171   -
             try {
    -  172  0
                 conn = (HttpURLConnection) url.openConnection();
    -  173  0
                 final int timeout = Settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 10000);
    -  174  0
                 conn.setConnectTimeout(timeout);
    -  175  0
                 conn.setInstanceFollowRedirects(true);
    -  176  0
             } catch (IOException ioe) {
    -  177  0
                 throw new URLConnectionFailureException("Error getting connection.", ioe);
    -  178  0
             }
    -  179  0
             configureTLS(url, conn);
    -  180  0
             return conn;
    -  181   -
         }
    -  182   +  67   +
         @SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE", justification = "Just being extra safe")
    +  68   +
         public static HttpURLConnection createHttpURLConnection(URL url) throws URLConnectionFailureException {
    +  69  0
             HttpURLConnection conn = null;
    +  70  0
             final String proxyUrl = Settings.getString(Settings.KEYS.PROXY_SERVER);
    +  71  
     
    -  183   +  72   +
             try {
    +  73  0
                 if (proxyUrl != null && !matchNonProxy(url)) {
    +  74  0
                     final int proxyPort = Settings.getInt(Settings.KEYS.PROXY_PORT);
    +  75  0
                     final SocketAddress address = new InetSocketAddress(proxyUrl, proxyPort);
    +  76   +
     
    +  77  0
                     final String username = Settings.getString(Settings.KEYS.PROXY_USERNAME);
    +  78  0
                     final String password = Settings.getString(Settings.KEYS.PROXY_PASSWORD);
    +  79   +
     
    +  80  0
                     if (username != null && password != null) {
    +  81  0
                         final Authenticator auth = new Authenticator() {
    +  82   +
                             @Override
    +  83   +
                             public PasswordAuthentication getPasswordAuthentication() {
    +  84  0
                                 if (getRequestorType().equals(Authenticator.RequestorType.PROXY)) {
    +  85  0
                                     return new PasswordAuthentication(username, password.toCharArray());
    +  86   +
                                 }
    +  87  0
                                 return super.getPasswordAuthentication();
    +  88   +
                             }
    +  89   +
                         };
    +  90  0
                         Authenticator.setDefault(auth);
    +  91   +
                     }
    +  92   +
     
    +  93  0
                     final Proxy proxy = new Proxy(Proxy.Type.HTTP, address);
    +  94  0
                     conn = (HttpURLConnection) url.openConnection(proxy);
    +  95  0
                 } else {
    +  96  0
                     conn = (HttpURLConnection) url.openConnection();
    +  97   +
                 }
    +  98  0
                 final int timeout = Settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 10000);
    +  99  0
                 conn.setConnectTimeout(timeout);
    +  100  0
                 conn.setInstanceFollowRedirects(true);
    +  101  0
             } catch (IOException ex) {
    +  102  0
                 if (conn != null) {
    +  103   +
                     try {
    +  104  0
                         conn.disconnect();
    +  105   +
                     } finally {
    +  106  0
                         conn = null;
    +  107  0
                     }
    +  108   +
                 }
    +  109  0
                 throw new URLConnectionFailureException("Error getting connection.", ex);
    +  110  0
             }
    +  111  0
             configureTLS(url, conn);
    +  112  0
             return conn;
    +  113   +
         }
    +  114   +
     
    +  115  
         /**
    -  184   -
          * If the protocol is HTTPS, this will configure the cipher suites so that
    -  185   -
          * connections can be made to the NVD, and others, using older versions of
    -  186   -
          * Java.
    -  187   +  116   +
          * Check if hostname matches nonProxy settings
    +  117  
          *
    -  188   -
          * @param url the URL
    -  189   -
          * @param conn the connection
    -  190   +  118   +
          * @param url the url to connect to
    +  119   +
          * @return matching result. true: match nonProxy
    +  120  
          */
    -  191   -
         private static void configureTLS(URL url, HttpURLConnection conn) {
    -  192  0
             if ("https".equals(url.getProtocol())) {
    -  193   -
                 try {
    -  194  0
                     final HttpsURLConnection secCon = (HttpsURLConnection) conn;
    -  195  0
                     final SSLSocketFactoryEx factory = new SSLSocketFactoryEx();
    -  196  0
                     secCon.setSSLSocketFactory(factory);
    -  197  0
                 } catch (NoSuchAlgorithmException ex) {
    -  198  0
                     LOGGER.debug("Unsupported algorithm in SSLSocketFactoryEx", ex);
    -  199  0
                 } catch (KeyManagementException ex) {
    -  200  0
                     LOGGER.debug("Key mnagement eception in SSLSocketFactoryEx", ex);
    -  201  0
                 }
    -  202   +  121   +
         private static boolean matchNonProxy(final URL url) {
    +  122  0
             final String host = url.getHost();
    +  123   +
     
    +  124   +
             // code partially from org.apache.maven.plugins.site.AbstractDeployMojo#getProxyInfo
    +  125  0
             final String nonProxyHosts = Settings.getString(Settings.KEYS.PROXY_NON_PROXY_HOSTS);
    +  126  0
             if (null != nonProxyHosts) {
    +  127  0
                 final String[] nonProxies = nonProxyHosts.split("(,)|(;)|(\\|)");
    +  128  0
                 for (final String nonProxyHost : nonProxies) {
    +  129   +
                     //if ( StringUtils.contains( nonProxyHost, "*" ) )
    +  130  0
                     if (null != nonProxyHost && nonProxyHost.contains("*")) {
    +  131   +
                         // Handle wildcard at the end, beginning or middle of the nonProxyHost
    +  132  0
                         final int pos = nonProxyHost.indexOf('*');
    +  133  0
                         final String nonProxyHostPrefix = nonProxyHost.substring(0, pos);
    +  134  0
                         final String nonProxyHostSuffix = nonProxyHost.substring(pos + 1);
    +  135   +
                         // prefix*
    +  136  0
                         if (!StringUtils.isEmpty(nonProxyHostPrefix) && host.startsWith(nonProxyHostPrefix) && StringUtils.isEmpty(nonProxyHostSuffix)) {
    +  137  0
                             return true;
    +  138   +
                         }
    +  139   +
                         // *suffix
    +  140  0
                         if (StringUtils.isEmpty(nonProxyHostPrefix) && !StringUtils.isEmpty(nonProxyHostSuffix) && host.endsWith(nonProxyHostSuffix)) {
    +  141  0
                             return true;
    +  142   +
                         }
    +  143   +
                         // prefix*suffix
    +  144  0
                         if (!StringUtils.isEmpty(nonProxyHostPrefix) && host.startsWith(nonProxyHostPrefix) && !StringUtils.isEmpty(nonProxyHostSuffix)
    +  145  0
                                 && host.endsWith(nonProxyHostSuffix)) {
    +  146  0
                             return true;
    +  147   +
                         }
    +  148  0
                     } else if (host.equals(nonProxyHost)) {
    +  149  0
                         return true;
    +  150   +
                     }
    +  151   +
                 }
    +  152  
             }
    -  203  0
         }
    -  204   +  153  0
             return false;
    +  154   +
         }
    +  155   +
     
    +  156   +
         /**
    +  157   +
          * Utility method to create an HttpURLConnection. The use of a proxy here is
    +  158   +
          * optional as there may be cases where a proxy is configured but we don't
    +  159   +
          * want to use it (for example, if there's an internal repository
    +  160   +
          * configured)
    +  161   +
          *
    +  162   +
          * @param url the URL to connect to
    +  163   +
          * @param proxy whether to use the proxy (if configured)
    +  164   +
          * @return a newly constructed HttpURLConnection
    +  165   +
          * @throws URLConnectionFailureException thrown if there is an exception
    +  166   +
          */
    +  167   +
         public static HttpURLConnection createHttpURLConnection(URL url, boolean proxy) throws URLConnectionFailureException {
    +  168  0
             if (proxy) {
    +  169  0
                 return createHttpURLConnection(url);
    +  170   +
             }
    +  171  0
             HttpURLConnection conn = null;
    +  172   +
             try {
    +  173  0
                 conn = (HttpURLConnection) url.openConnection();
    +  174  0
                 final int timeout = Settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 10000);
    +  175  0
                 conn.setConnectTimeout(timeout);
    +  176  0
                 conn.setInstanceFollowRedirects(true);
    +  177  0
             } catch (IOException ioe) {
    +  178  0
                 throw new URLConnectionFailureException("Error getting connection.", ioe);
    +  179  0
             }
    +  180  0
             configureTLS(url, conn);
    +  181  0
             return conn;
    +  182   +
         }
    +  183   +
     
    +  184   +
         /**
    +  185   +
          * If the protocol is HTTPS, this will configure the cipher suites so that
    +  186   +
          * connections can be made to the NVD, and others, using older versions of
    +  187   +
          * Java.
    +  188   +
          *
    +  189   +
          * @param url the URL
    +  190   +
          * @param conn the connection
    +  191   +
          */
    +  192   +
         private static void configureTLS(URL url, URLConnection conn) {
    +  193  0
             if ("https".equals(url.getProtocol())) {
    +  194   +
                 try {
    +  195  0
                     final HttpsURLConnection secCon = (HttpsURLConnection) conn;
    +  196  0
                     final SSLSocketFactoryEx factory = new SSLSocketFactoryEx();
    +  197  0
                     secCon.setSSLSocketFactory(factory);
    +  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);
    +  202  0
                 }
    +  203   +
             }
    +  204  0
         }
    +  205  
     }
    - + 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 a16e65c90..e78bcda88 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 8dd56ae26..08e166ed1 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 - +
  • @@ -168,13 +168,6 @@ Checkstyle
  • - -
  • - - - - PMD -
  • diff --git a/dependency-check-utils/dependency-updates-report.html b/dependency-check-utils/dependency-updates-report.html index 6ed2406d4..4df223a06 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 - +
  • @@ -168,13 +168,6 @@ Checkstyle
  • - -
  • - - - - PMD -
  • @@ -222,7 +215,7 @@ # of dependencies using the latest version available -23 +21 # of dependencies where the next version available is smaller than an incremental version update @@ -230,15 +223,15 @@ # of dependencies where the next version available is an incremental version update -0 +1 # of dependencies where the next version available is a minor version update -7 +8 # of dependencies where the next version available is a major version update -1 +2

    Dependency Management

    @@ -303,7 +296,7 @@ - + @@ -311,7 +304,7 @@ - + @@ -507,7 +500,7 @@ - + @@ -516,7 +509,7 @@ - + @@ -531,6 +524,18 @@ + + + + + + + + + + + + @@ -542,7 +547,7 @@ - + @@ -554,7 +559,7 @@ - + @@ -566,7 +571,7 @@ - + @@ -578,7 +583,7 @@ - + @@ -590,7 +595,7 @@ - + @@ -602,7 +607,7 @@ - + @@ -614,7 +619,7 @@ - + @@ -626,7 +631,7 @@ - + @@ -647,25 +652,25 @@

    ch.qos.logback:logback-classic

    1.4.177
    com.sun.mail mailapi 1.5.5 jar 1.5.6
    org.apache.maven.plugin-tools maven-plugin-annotations 3.4jar 3.5
    org.apache.maven.sharedmaven-dependency-tree2.2jar3.0
    org.apache.velocity velocity
    org.glassfish javax.json
    org.hamcrest hamcrest-core
    org.jmockit jmockit 1.25
    org.jsoup jsoup
    org.slf4j slf4j-api
    org.slf4j slf4j-simple
    org.sonatype.plexus plexus-sec-dispatcher
    Status Group Id Artifact Id
    - + - + - + - + - + - + - +
    Status  No newer versions available.
    Group Id ch.qos.logback
    Artifact Id logback-classic
    Current Version 1.1.7
    Scope
    Classifier
    Type jar
    @@ -748,7 +753,7 @@ - + @@ -766,7 +771,10 @@ -
    Status No newer versions available.
     There is at least one newer incremental version available. Incremental updates are typically passive.
    Group Id com.sun.mail
    Typejar
    +jar + +Newer versions +1.5.6 Next Incremental

    commons-cli:commons-cli

    @@ -991,7 +999,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.lucene:lucene-core

    @@ -1018,7 +1026,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.lucene:lucene-queryparser

    @@ -1045,7 +1053,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.lucene:lucene-test-framework

    @@ -1072,7 +1080,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.maven:maven-core

    @@ -1174,7 +1182,7 @@
    - + @@ -1192,7 +1200,10 @@ -
    Status No newer versions available.
     There is at least one newer minor version available. Minor updates are sometimes passive.
    Group Id org.apache.maven.plugin-tools
    Typejar
    +jar + +Newer versions +3.5 Next Minor

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

    @@ -1218,6 +1229,33 @@
    Type jar
    +

    org.apache.maven.shared:maven-dependency-tree

    + + + + + + + + + + + + + + + + + + + + + + + + +
    Status There is at least one newer major version available. Major updates are rarely passive.
    Group Idorg.apache.maven.shared
    Artifact Idmaven-dependency-tree
    Current Version2.2
    Scope
    Classifier
    Typejar
    Newer versions3.0 Next Major
    +

    org.apache.velocity:velocity

    @@ -1315,7 +1353,7 @@ -
    jar
    Newer versions1.25 Next Minor
    +1.25 Next Minor
    1.26
    1.27 Latest Minor

    org.jsoup:jsoup

    diff --git a/dependency-check-utils/findbugs.html b/dependency-check-utils/findbugs.html index b0b53c089..2b2ee1a69 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 - +
  • @@ -168,13 +168,6 @@ Checkstyle
  • - -
  • - - - - PMD -
  • diff --git a/dependency-check-utils/index.html b/dependency-check-utils/index.html index 609797ade..ae00bf05b 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 - +
  • diff --git a/dependency-check-utils/integration.html b/dependency-check-utils/integration.html index 592c68299..9bd97a14a 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 @@
  • - +
  • diff --git a/dependency-check-utils/issue-tracking.html b/dependency-check-utils/issue-tracking.html index ee91b4ada..520923975 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 @@
  • - +
  • diff --git a/dependency-check-utils/license.html b/dependency-check-utils/license.html index 67e0a4a22..b942bf3d7 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 @@
  • - +
  • diff --git a/dependency-check-utils/mail-lists.html b/dependency-check-utils/mail-lists.html index 4488e4581..a90511589 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 @@
  • - +
  • diff --git a/dependency-check-utils/plugin-updates-report.html b/dependency-check-utils/plugin-updates-report.html index 19d7d6cae..4e2caea57 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
  • - +
  • @@ -168,13 +168,6 @@ Checkstyle
  • - -
  • - - - - PMD -
  • diff --git a/dependency-check-utils/project-info.html b/dependency-check-utils/project-info.html index e82713fbf..a206d3e56 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 @@ - +
  • diff --git a/dependency-check-utils/project-reports.html b/dependency-check-utils/project-reports.html index 2ac76b177..e76522e74 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
  • - +
  • Project Reports @@ -168,13 +168,6 @@ Checkstyle
  • - -
  • - - - - PMD -
  • @@ -256,10 +249,7 @@ - - - -
    Provides details of the plugins used by this project which have newer versions available.
    CheckstyleReport on coding style conventions.
    PMDVerification of coding rules.
    +Report on coding style conventions. diff --git a/dependency-check-utils/project-summary.html b/dependency-check-utils/project-summary.html index d83387741..fa3e33106 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 @@ - +
  • @@ -223,7 +223,7 @@ dependency-check-utils Version -1.4.2 +1.4.3 Type jar diff --git a/dependency-check-utils/source-repository.html b/dependency-check-utils/source-repository.html index a76e26af5..9d4e204f0 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 @@
  • - +
  • diff --git a/dependency-check-utils/surefire-report.html b/dependency-check-utils/surefire-report.html index bbf1559cf..21d9c41d2 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
  • - +
  • @@ -168,13 +168,6 @@ Checkstyle
  • - -
  • - - - - PMD -
  • @@ -251,7 +244,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.602
    +0.689

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


    Package List

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

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

    org.owasp.dependencycheck.utils

    @@ -294,7 +287,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.401 +0.492 DownloaderTest @@ -303,7 +296,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.016 +0 ExpectedOjectInputStreamTest @@ -312,7 +305,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.069 +0.079 FileUtilsTest @@ -321,7 +314,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.116 +0.115 SettingsTest @@ -330,7 +323,7 @@ function toggleDisplay(elementId) { 0 0 100% -0

    +0.003

    Test Cases

    [Summary] [Package List] [Test Cases]

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

    DownloaderTest

    @@ -374,11 +367,11 @@ function toggleDisplay(elementId) { - + -
    testResolveClassException0.052
    0.078
    testResolveClass0
    +0.001

    FileUtilsTest

    @@ -389,7 +382,7 @@ function toggleDisplay(elementId) { -
    testDelete0.116
    +0.114

    SettingsTest

    @@ -404,7 +397,7 @@ function toggleDisplay(elementId) { - + diff --git a/dependency-check-utils/taglist.html b/dependency-check-utils/taglist.html index 9b86e0ba1..22c40db9d 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 - +
  • @@ -168,13 +168,6 @@ Checkstyle
  • - -
  • - - - - PMD -
  • diff --git a/dependency-check-utils/team-list.html b/dependency-check-utils/team-list.html index b4d6e9ebd..e20560ad4 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 @@ - +
  • diff --git a/dependency-check-utils/xref-test/index.html b/dependency-check-utils/xref-test/index.html index adfc4bb8d..1635bc815 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.2 Reference + Dependency-Check Utils 1.4.3 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 abb58428d..8ac1facc1 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.2 Reference Package org.owasp.dependencycheck.utils + Dependency-Check Utils 1.4.3 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 c3c566952..ad19c5d8f 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.2 Reference Package org.owasp.dependencycheck.utils + Dependency-Check Utils 1.4.3 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 516fe62e9..46b9088ae 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.2 Reference + Dependency-Check Utils 1.4.3 Reference diff --git a/dependency-check-utils/xref-test/overview-summary.html b/dependency-check-utils/xref-test/overview-summary.html index 02e2a205c..b43685082 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.2 Reference + Dependency-Check Utils 1.4.3 Reference @@ -24,7 +24,7 @@ -

    Dependency-Check Utils 1.4.2 Reference

    +

    Dependency-Check Utils 1.4.3 Reference

  • testMergeProperties_String0
    0.001
    testGetDataFile
    diff --git a/dependency-check-utils/xref/index.html b/dependency-check-utils/xref/index.html index adfc4bb8d..1635bc815 100644 --- a/dependency-check-utils/xref/index.html +++ b/dependency-check-utils/xref/index.html @@ -4,7 +4,7 @@ - Dependency-Check Utils 1.4.2 Reference + Dependency-Check Utils 1.4.3 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 d670894e2..1ca6881e7 100644 --- a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/Checksum.html +++ b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/Checksum.html @@ -66,11 +66,11 @@ 58 * @throws NoSuchAlgorithmException when an algorithm is specified that does not exist59 */60publicstatic byte[] getChecksum(String algorithm, File file) throws NoSuchAlgorithmException, IOException { -61 MessageDigest digest = MessageDigest.getInstance(algorithm); +61final MessageDigest digest = MessageDigest.getInstance(algorithm); 62 FileInputStream fis = null; 63try { 64 fis = new FileInputStream(file); -65 FileChannel ch = fis.getChannel(); +65final FileChannel ch = fis.getChannel(); 66long remainingToRead = file.length(); 67long start = 0; 68while (remainingToRead > 0) { @@ -82,7 +82,7 @@ 74 amountToRead = remainingToRead; 75 remainingToRead = 0; 76 } -77 MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, start, amountToRead); +77final MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, start, amountToRead); 78 digest.update(byteBuffer); 79 start += amountToRead; 80 } @@ -107,7 +107,7 @@ 99 * @throws NoSuchAlgorithmException when the MD5 algorithm is not available100 */101publicstatic String getMD5Checksum(File file) throws IOException, NoSuchAlgorithmException { -102 byte[] b = getChecksum("MD5", file); +102final byte[] b = getChecksum("MD5", file); 103return getHex(b); 104 } 105 @@ -120,7 +120,7 @@ 112 * @throws NoSuchAlgorithmException when the SHA1 algorithm is not available113 */114publicstatic String getSHA1Checksum(File file) throws IOException, NoSuchAlgorithmException { -115 byte[] b = getChecksum("SHA1", file); +115final byte[] b = getChecksum("SHA1", file); 116return getHex(b); 117 } 118/** 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 1b5a46416..1be66e97c 100644 --- a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/Downloader.html +++ b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/Downloader.html @@ -308,11 +308,11 @@ 300 * @throws DownloadFailedException a wrapper exception that contains the301 * original exception as the cause302 */ -303protectedstaticvoid checkForCommonExceptionTypes(IOException ex) throws DownloadFailedException { +303protectedstaticsynchronizedvoid checkForCommonExceptionTypes(IOException ex) throws DownloadFailedException { 304 Throwable cause = ex; 305while (cause != null) { 306if (cause instanceof java.net.UnknownHostException) { -307final String msg = String.format("Unable to resolve domain '%s'", cause.getMessage()); +307final String msg = format("Unable to resolve domain '%s'", cause.getMessage()); 308 LOGGER.error(msg); 309thrownewDownloadFailedException(msg); 310 } 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 df9af50bb..3c7a93528 100644 --- a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/FileUtils.html +++ b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/FileUtils.html @@ -32,91 +32,92 @@ 24import java.io.File; 25import java.io.IOException; 26import java.util.UUID; -27 -28/** -29 * A collection of utilities for processing information about files. -30 * -31 * @author Jeremy Long -32 */ -33publicfinalclassFileUtils { -34 -35/** -36 * The logger. -37 */ -38privatestaticfinal Logger LOGGER = LoggerFactory.getLogger(FileUtils.class); -39/** -40 * Bit bucket for non-Windows systems -41 */ -42privatestaticfinal String BIT_BUCKET_UNIX = "/dev/null"; -43 -44/** -45 * Bit bucket for Windows systems (yes, only one 'L') -46 */ -47privatestaticfinal String BIT_BUCKET_WIN = "NUL"; -48 -49/** -50 * Private constructor for a utility class. -51 */ -52privateFileUtils() { -53 } -54 -55/** -56 * Returns the (lowercase) file extension for a specified file. -57 * -58 * @param fileName the file name to retrieve the file extension from. -59 * @return the file extension. -60 */ -61publicstatic String getFileExtension(String fileName) { -62final String fileExt = FilenameUtils.getExtension(fileName); -63returnnull == fileExt || fileExt.isEmpty() ? null : fileExt.toLowerCase(); -64 } -65 -66/** -67 * Deletes a file. If the File is a directory it will recursively delete the contents. -68 * -69 * @param file the File to delete -70 * @return true if the file was deleted successfully, otherwise false -71 */ -72publicstaticboolean delete(File file) { -73finalboolean success = org.apache.commons.io.FileUtils.deleteQuietly(file); -74if (!success) { -75 LOGGER.debug("Failed to delete file: {}; attempting to delete on exit.", file.getPath()); -76 file.deleteOnExit(); -77 } -78return success; -79 } -80 -81/** -82 * Generates a new temporary file name that is guaranteed to be unique. -83 * -84 * @param prefix the prefix for the file name to generate -85 * @param extension the extension of the generated file name -86 * @return a temporary File -87 * @throws java.io.IOException thrown if the temporary folder could not be created -88 */ -89publicstatic File getTempFile(String prefix, String extension) throws IOException { -90final File dir = Settings.getTempDirectory(); -91final String tempFileName = String.format("%s%s.%s", prefix, UUID.randomUUID().toString(), extension); -92final File tempFile = new File(dir, tempFileName); -93if (tempFile.exists()) { -94return getTempFile(prefix, extension); -95 } -96return tempFile; -97 } -98 -99/** -100 * Return the bit bucket for the OS. '/dev/null' for Unix and 'NUL' for Windows -101 * -102 * @return a String containing the bit bucket -103 */ -104publicstatic String getBitBucket() { -105if (System.getProperty("os.name").startsWith("Windows")) { -106return BIT_BUCKET_WIN; -107 } else { -108return BIT_BUCKET_UNIX; -109 } -110 } -111 } +27import org.apache.commons.lang3.SystemUtils; +28 +29/** +30 * A collection of utilities for processing information about files. +31 * +32 * @author Jeremy Long +33 */ +34publicfinalclassFileUtils { +35 +36/** +37 * The logger. +38 */ +39privatestaticfinal Logger LOGGER = LoggerFactory.getLogger(FileUtils.class); +40/** +41 * Bit bucket for non-Windows systems +42 */ +43privatestaticfinal String BIT_BUCKET_UNIX = "/dev/null"; +44 +45/** +46 * Bit bucket for Windows systems (yes, only one 'L') +47 */ +48privatestaticfinal String BIT_BUCKET_WIN = "NUL"; +49 +50/** +51 * Private constructor for a utility class. +52 */ +53privateFileUtils() { +54 } +55 +56/** +57 * Returns the (lowercase) file extension for a specified file. +58 * +59 * @param fileName the file name to retrieve the file extension from. +60 * @return the file extension. +61 */ +62publicstatic String getFileExtension(String fileName) { +63final String fileExt = FilenameUtils.getExtension(fileName); +64returnnull == fileExt || fileExt.isEmpty() ? null : fileExt.toLowerCase(); +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 */ +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 }
    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 0c780ffa3..cd0018537 100644 --- a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.html +++ b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.html @@ -86,7 +86,7 @@ 78 */79 @Override 80public String[] getDefaultCipherSuites() { -81return Arrays.copyOf(ciphers, ciphers.length); +81return sslCtxt.getSocketFactory().getDefaultCipherSuites(); 82 } 8384/** @@ -96,7 +96,7 @@ 88 */89 @Override 90public String[] getSupportedCipherSuites() { -91return Arrays.copyOf(ciphers, ciphers.length); +91return sslCtxt.getSocketFactory().getSupportedCipherSuites(); 92 } 9394/** @@ -133,264 +133,168 @@ 125final SSLSocket ss = (SSLSocket) factory.createSocket(s, host, port, autoClose); 126127 ss.setEnabledProtocols(protocols); -128 ss.setEnabledCipherSuites(ciphers); -129 -130return ss; -131 } -132 -133/** -134 * Creates a new SSL Socket. -135 * -136 * @param address the address to connect to -137 * @param port the port number -138 * @param localAddress the local address -139 * @param localPort the local port -140 * @return the SSL Socket -141 * @throws IOException thrown if the creation fails -142 */ -143 @Override -144public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { -145final SSLSocketFactory factory = sslCtxt.getSocketFactory(); -146final SSLSocket ss = (SSLSocket) factory.createSocket(address, port, localAddress, localPort); -147 -148 ss.setEnabledProtocols(protocols); -149 ss.setEnabledCipherSuites(ciphers); -150 -151return ss; -152 } -153 -154/** -155 * Creates a new SSL Socket. -156 * -157 * @param host the host to connect to -158 * @param port the port to connect to -159 * @param localHost the local host -160 * @param localPort the local port -161 * @return the SSL Socket -162 * @throws IOException thrown if the creation fails -163 */ -164 @Override -165public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { -166final SSLSocketFactory factory = sslCtxt.getSocketFactory(); -167final SSLSocket ss = (SSLSocket) factory.createSocket(host, port, localHost, localPort); +128 +129return ss; +130 } +131 +132/** +133 * Creates a new SSL Socket. +134 * +135 * @param address the address to connect to +136 * @param port the port number +137 * @param localAddress the local address +138 * @param localPort the local port +139 * @return the SSL Socket +140 * @throws IOException thrown if the creation fails +141 */ +142 @Override +143public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { +144final SSLSocketFactory factory = sslCtxt.getSocketFactory(); +145final SSLSocket ss = (SSLSocket) factory.createSocket(address, port, localAddress, localPort); +146 +147 ss.setEnabledProtocols(protocols); +148 +149return ss; +150 } +151 +152/** +153 * Creates a new SSL Socket. +154 * +155 * @param host the host to connect to +156 * @param port the port to connect to +157 * @param localHost the local host +158 * @param localPort the local port +159 * @return the SSL Socket +160 * @throws IOException thrown if the creation fails +161 */ +162 @Override +163public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { +164final SSLSocketFactory factory = sslCtxt.getSocketFactory(); +165final SSLSocket ss = (SSLSocket) factory.createSocket(host, port, localHost, localPort); +166 +167 ss.setEnabledProtocols(protocols); 168 -169 ss.setEnabledProtocols(protocols); -170 ss.setEnabledCipherSuites(ciphers); +169return ss; +170 } 171 -172return ss; -173 } -174 -175/** -176 * Creates a new SSL Socket. -177 * -178 * @param host the host to connect to -179 * @param port the port to connect to -180 * @return the SSL Socket -181 * @throws IOException thrown if the creation fails -182 */ -183 @Override -184public Socket createSocket(InetAddress host, int port) throws IOException { -185final SSLSocketFactory factory = sslCtxt.getSocketFactory(); -186final SSLSocket ss = (SSLSocket) factory.createSocket(host, port); -187 -188 ss.setEnabledProtocols(protocols); -189 ss.setEnabledCipherSuites(ciphers); -190 -191return ss; -192 } -193 -194/** -195 * Creates a new SSL Socket. -196 * -197 * @param host the host to connect to -198 * @param port the port to connect to -199 * @return the SSL Socket -200 * @throws IOException thrown if the creation fails -201 */ -202 @Override -203public Socket createSocket(String host, int port) throws IOException { -204final SSLSocketFactory factory = sslCtxt.getSocketFactory(); -205final SSLSocket ss = (SSLSocket) factory.createSocket(host, port); -206 -207 ss.setEnabledProtocols(protocols); -208 ss.setEnabledCipherSuites(ciphers); -209 -210return ss; -211 } -212 -213/** -214 * Initializes the SSL Socket Factory Extension. -215 * -216 * @param km the key managers -217 * @param tm the trust managers -218 * @param random the secure random number generator -219 * @throws NoSuchAlgorithmException thrown when an algorithm is not -220 * supported -221 * @throws KeyManagementException thrown if initialization fails -222 */ -223privatevoid initSSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random) -224throws NoSuchAlgorithmException, KeyManagementException { -225 sslCtxt = SSLContext.getInstance("TLS"); -226 sslCtxt.init(km, tm, random); -227 -228 protocols = getProtocolList(); -229 ciphers = getCipherList(); -230 } -231 -232/** -233 * Initializes the SSL Socket Factory Extension. -234 * -235 * @param ctx the SSL context -236 * @throws NoSuchAlgorithmException thrown when an algorithm is not -237 * supported -238 * @throws KeyManagementException thrown if initialization fails -239 */ -240privatevoid initSSLSocketFactoryEx(SSLContext ctx) -241throws NoSuchAlgorithmException, KeyManagementException { -242 sslCtxt = ctx; -243 -244 protocols = getProtocolList(); -245 ciphers = getCipherList(); -246 } -247 -248/** -249 * Returns the protocol list. -250 * -251 * @return the protocol list -252 */ -253protected String[] getProtocolList() { -254final String[] preferredProtocols = {"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"}; -255 String[] availableProtocols = null; -256 -257 SSLSocket socket = null; -258 -259try { -260final SSLSocketFactory factory = sslCtxt.getSocketFactory(); -261 socket = (SSLSocket) factory.createSocket(); -262 -263 availableProtocols = socket.getSupportedProtocols(); -264 Arrays.sort(availableProtocols); -265 } catch (Exception ex) { -266 LOGGER.debug("Error getting protocol list, using TLSv1", ex); -267returnnew String[]{"TLSv1"}; -268 } finally { -269if (socket != null) { -270try { -271 socket.close(); -272 } catch (IOException ex) { -273 LOGGER.trace("Error closing socket", ex); -274 } +172/** +173 * Creates a new SSL Socket. +174 * +175 * @param host the host to connect to +176 * @param port the port to connect to +177 * @return the SSL Socket +178 * @throws IOException thrown if the creation fails +179 */ +180 @Override +181public Socket createSocket(InetAddress host, int port) throws IOException { +182final SSLSocketFactory factory = sslCtxt.getSocketFactory(); +183final SSLSocket ss = (SSLSocket) factory.createSocket(host, port); +184 +185 ss.setEnabledProtocols(protocols); +186 +187return ss; +188 } +189 +190/** +191 * Creates a new SSL Socket. +192 * +193 * @param host the host to connect to +194 * @param port the port to connect to +195 * @return the SSL Socket +196 * @throws IOException thrown if the creation fails +197 */ +198 @Override +199public Socket createSocket(String host, int port) throws IOException { +200final SSLSocketFactory factory = sslCtxt.getSocketFactory(); +201final SSLSocket ss = (SSLSocket) factory.createSocket(host, port); +202 +203 ss.setEnabledProtocols(protocols); +204 +205return ss; +206 } +207 +208/** +209 * Initializes the SSL Socket Factory Extension. +210 * +211 * @param km the key managers +212 * @param tm the trust managers +213 * @param random the secure random number generator +214 * @throws NoSuchAlgorithmException thrown when an algorithm is not +215 * supported +216 * @throws KeyManagementException thrown if initialization fails +217 */ +218privatevoid initSSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random) +219throws NoSuchAlgorithmException, KeyManagementException { +220 sslCtxt = SSLContext.getInstance("TLS"); +221 sslCtxt.init(km, tm, random); +222 +223 protocols = getProtocolList(); +224 } +225 +226/** +227 * Initializes the SSL Socket Factory Extension. +228 * +229 * @param ctx the SSL context +230 * @throws NoSuchAlgorithmException thrown when an algorithm is not +231 * supported +232 * @throws KeyManagementException thrown if initialization fails +233 */ +234privatevoid initSSLSocketFactoryEx(SSLContext ctx) +235throws NoSuchAlgorithmException, KeyManagementException { +236 sslCtxt = ctx; +237 protocols = getProtocolList(); +238 } +239 +240/** +241 * Returns the protocol list. +242 * +243 * @return the protocol list +244 */ +245protected String[] getProtocolList() { +246final String[] preferredProtocols = {"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"}; +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 -278final List<String> aa = new ArrayList<String>(); -279for (String preferredProtocol : preferredProtocols) { -280finalint idx = Arrays.binarySearch(availableProtocols, preferredProtocol); -281if (idx >= 0) { -282 aa.add(preferredProtocol); -283 } -284 } -285 -286return aa.toArray(new String[0]); -287 } -288 -289/** -290 * Returns the cipher list. -291 * -292 * @return the cipher list -293 */ -294protected String[] getCipherList() { -295final String[] preferredCiphers = { -296// *_CHACHA20_POLY1305 are 3x to 4x faster than existing cipher suites. -297// http://googleonlinesecurity.blogspot.com/2014/04/speeding-up-and-strengthening-https.html -298// Use them if available. Normative names can be found at (TLS spec depends on IPSec spec): -299// http://tools.ietf.org/html/draft-nir-ipsecme-chacha20-poly1305-01 -300// http://tools.ietf.org/html/draft-mavrogiannopoulos-chacha-tls-02 -301"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", -302"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", -303"TLS_ECDHE_ECDSA_WITH_CHACHA20_SHA", -304"TLS_ECDHE_RSA_WITH_CHACHA20_SHA", -305"TLS_DHE_RSA_WITH_CHACHA20_POLY1305", -306"TLS_RSA_WITH_CHACHA20_POLY1305", -307"TLS_DHE_RSA_WITH_CHACHA20_SHA", -308"TLS_RSA_WITH_CHACHA20_SHA", -309// Done with bleeding edge, back to TLS v1.2 and below -310"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", -311"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", -312"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", -313"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", -314"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", -315"TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", -316"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", -317"TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", -318// TLS v1.0 (with some SSLv3 interop) -319"TLS_DHE_RSA_WITH_AES_256_CBC_SHA384", -320"TLS_DHE_DSS_WITH_AES_256_CBC_SHA256", -321"TLS_DHE_RSA_WITH_AES_128_CBC_SHA", -322"TLS_DHE_DSS_WITH_AES_128_CBC_SHA", -323"TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", -324"TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", -325"SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA", -326"SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA", -327// RSA key transport sucks, but they are needed as a fallback. -328// For example, microsoft.com fails under all versions of TLS -329// if they are not included. If only TLS 1.0 is available at -330// the client, then google.com will fail too. TLS v1.3 is -331// trying to deprecate them, so it will be interesteng to see -332// what happens. -333"TLS_RSA_WITH_AES_256_CBC_SHA256", -334"TLS_RSA_WITH_AES_256_CBC_SHA", -335"TLS_RSA_WITH_AES_128_CBC_SHA256", -336"TLS_RSA_WITH_AES_128_CBC_SHA", -337 }; -338 -339 String[] availableCiphers; -340 -341try { -342final SSLSocketFactory factory = sslCtxt.getSocketFactory(); -343 availableCiphers = factory.getSupportedCipherSuites(); -344 Arrays.sort(availableCiphers); -345 } catch (Exception e) { -346 LOGGER.debug("Error retrieving ciphers", e); -347returnnew String[]{ -348"TLS_DHE_DSS_WITH_AES_128_CBC_SHA", -349"TLS_DHE_DSS_WITH_AES_256_CBC_SHA", -350"TLS_DHE_RSA_WITH_AES_128_CBC_SHA", -351"TLS_DHE_RSA_WITH_AES_256_CBC_SHA", -352"TLS_RSA_WITH_AES_256_CBC_SHA256", -353"TLS_RSA_WITH_AES_256_CBC_SHA", -354"TLS_RSA_WITH_AES_128_CBC_SHA256", -355"TLS_RSA_WITH_AES_128_CBC_SHA", -356"TLS_EMPTY_RENEGOTIATION_INFO_SCSV", -357 }; -358 } -359 -360final List<String> aa = new ArrayList<String>(); -361for (String preferredCipher : preferredCiphers) { -362finalint idx = Arrays.binarySearch(availableCiphers, preferredCipher); -363if (idx >= 0) { -364 aa.add(preferredCipher); -365 } -366 } -367 -368 aa.add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV"); -369 -370return aa.toArray(new String[0]); -371 } -372 -373/** -374 * The SSL context. -375 */ -376private SSLContext sslCtxt; -377/** -378 * The cipher suites. -379 */ -380private String[] ciphers; -381/** -382 * The protocols. -383 */ -384private String[] protocols; -385 } +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 }
    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 3dddd026c..db25a5eb5 100644 --- a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/Settings.html +++ b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/Settings.html @@ -63,7 +63,7 @@ 55/**56 * The key to obtain the application name.57 */ -58publicstaticfinal String APPLICATION_VAME = "application.name"; +58publicstaticfinal String APPLICATION_NAME = "application.name"; 59/**60 * The key to obtain the application version.61 */ @@ -297,640 +297,648 @@ 289 */290publicstaticfinal String ANALYZER_OPENSSL_ENABLED = "analyzer.openssl.enabled"; 291/** -292 * The properties key for the Central search URL. +292 * The properties key for whether the cocoapods analyzer is enabled.293 */ -294publicstaticfinal String ANALYZER_CENTRAL_URL = "analyzer.central.url"; +294publicstaticfinal String ANALYZER_COCOAPODS_ENABLED = "analyzer.cocoapods.enabled"; 295/** -296 * The path to mono, if available. +296 * The properties key for whether the SWIFT package manager analyzer is enabled.297 */ -298publicstaticfinal String ANALYZER_ASSEMBLY_MONO_PATH = "analyzer.assembly.mono.path"; +298publicstaticfinal String ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED = "analyzer.swift.package.manager.enabled"; 299/** -300 * The path to bundle-audit, if available. +300 * The properties key for the Central search URL.301 */ -302publicstaticfinal String ANALYZER_BUNDLE_AUDIT_PATH = "analyzer.bundle.audit.path"; +302publicstaticfinal String ANALYZER_CENTRAL_URL = "analyzer.central.url"; 303/** -304 * The additional configured zip file extensions, if available. +304 * The path to mono, if available.305 */ -306publicstaticfinal String ADDITIONAL_ZIP_EXTENSIONS = "extensions.zip"; +306publicstaticfinal String ANALYZER_ASSEMBLY_MONO_PATH = "analyzer.assembly.mono.path"; 307/** -308 * The key to obtain the path to the VFEED data file. +308 * The path to bundle-audit, if available.309 */ -310publicstaticfinal String VFEED_DATA_FILE = "vfeed.data_file"; +310publicstaticfinal String ANALYZER_BUNDLE_AUDIT_PATH = "analyzer.bundle.audit.path"; 311/** -312 * The key to obtain the VFEED connection string. +312 * The additional configured zip file extensions, if available.313 */ -314publicstaticfinal String VFEED_CONNECTION_STRING = "vfeed.connection_string"; -315 -316/** -317 * The key to obtain the base download URL for the VFeed data file. -318 */ -319publicstaticfinal String VFEED_DOWNLOAD_URL = "vfeed.download_url"; -320/** -321 * The key to obtain the download file name for the VFeed data. -322 */ -323publicstaticfinal String VFEED_DOWNLOAD_FILE = "vfeed.download_file"; +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"; +323324/** -325 * The key to obtain the VFeed update status. +325 * The key to obtain the base download URL for the VFeed data file.326 */ -327publicstaticfinal String VFEED_UPDATE_STATUS = "vfeed.update_status"; -328 -329/** -330 * The HTTP request method for query last modified date. -331 */ -332publicstaticfinal String DOWNLOADER_QUICK_QUERY_TIMESTAMP = "downloader.quick.query.timestamp"; -333 } -334//</editor-fold> -335 -336/** -337 * The logger. -338 */ -339privatestaticfinal Logger LOGGER = LoggerFactory.getLogger(Settings.class); -340/** -341 * The properties file location. -342 */ -343privatestaticfinal String PROPERTIES_FILE = "dependencycheck.properties"; +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> +343344/** -345 * Thread local settings. +345 * The logger.346 */ -347privatestaticfinal ThreadLocal<Settings> LOCAL_SETTINGS = new ThreadLocal<Settings>(); +347privatestaticfinal Logger LOGGER = LoggerFactory.getLogger(Settings.class); 348/** -349 * The properties. +349 * The properties file location.350 */ -351private Properties props = null; -352 -353/** -354 * Private constructor for the Settings class. This class loads the -355 * properties files. -356 * -357 * @param propertiesFilePath the path to the base properties file to load +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 */ -359privateSettings(String propertiesFilePath) { -360 InputStream in = null; -361 props = new Properties(); -362try { -363 in = this.getClass().getClassLoader().getResourceAsStream(propertiesFilePath); -364 props.load(in); -365 } catch (IOException ex) { -366 LOGGER.error("Unable to load default settings."); -367 LOGGER.debug("", ex); -368 } finally { -369if (in != null) { -370try { -371 in.close(); -372 } catch (IOException ex) { -373 LOGGER.trace("", ex); -374 } -375 } -376 } -377 logProperties("Properties loaded", props); -378 } -379 -380/** -381 * Initializes the thread local settings object. Note, to use the settings -382 * object you must call this method. However, you must also call -383 * Settings.cleanup() to properly release resources. -384 */ -385publicstaticvoid initialize() { -386 LOCAL_SETTINGS.set(newSettings(PROPERTIES_FILE)); -387 } -388 -389/** -390 * Initializes the thread local settings object. Note, to use the settings -391 * object you must call this method. However, you must also call -392 * Settings.cleanup() to properly release resources. -393 * -394 * @param propertiesFilePath the path to the base properties file to load -395 */ -396publicstaticvoid initialize(String propertiesFilePath) { -397 LOCAL_SETTINGS.set(newSettings(propertiesFilePath)); -398 } -399 -400/** -401 * Cleans up resources to prevent memory leaks. -402 * +359private Properties props = null; +360 +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 load403 */ -404publicstaticvoid cleanup() { -405 cleanup(true); +404publicstaticvoid initialize(String propertiesFilePath) { +405 LOCAL_SETTINGS.set(newSettings(propertiesFilePath)); 406 } 407408/**409 * Cleans up resources to prevent memory leaks.410 * -411 * @param deleteTemporary flag indicating whether any temporary directories -412 * generated should be removed -413 */ -414publicstaticvoid cleanup(boolean deleteTemporary) { -415if (deleteTemporary && tempDirectory != null && tempDirectory.exists()) { -416 FileUtils.delete(tempDirectory); -417if (tempDirectory.exists()) { -418try { -419 Thread.sleep(2000); -420 } catch (InterruptedException ex) { -421 LOGGER.trace("ignore", ex); -422 } -423 FileUtils.delete(tempDirectory); -424 } -425 } -426try { -427 LOCAL_SETTINGS.remove(); -428 } catch (Throwable ex) { -429 LOGGER.debug("Error cleaning up Settings", ex); -430 } -431 } -432 -433/** -434 * Gets the underlying instance of the Settings object. -435 * -436 * @return the Settings object -437 */ -438publicstaticSettings getInstance() { -439return LOCAL_SETTINGS.get(); -440 } -441 -442/** -443 * Sets the instance of the Settings object to use in this thread. -444 * -445 * @param instance the instance of the settings object to use in this thread -446 */ -447publicstaticvoid setInstance(Settings instance) { -448 LOCAL_SETTINGS.set(instance); -449 } -450 -451/** -452 * Logs the properties. This will not log any properties that contain -453 * 'password' in the key. -454 * -455 * @param header the header to print with the log message -456 * @param properties the properties to log -457 */ -458privatestaticvoid logProperties(String header, Properties properties) { -459if (LOGGER.isDebugEnabled()) { -460final StringWriter sw = new StringWriter(); -461 PrintWriter pw = null; -462try { -463 pw = new PrintWriter(sw); -464 pw.format("%s:%n%n", header); -465final Enumeration<?> e = properties.propertyNames(); -466while (e.hasMoreElements()) { -467final String key = (String) e.nextElement(); -468if (key.contains("password")) { -469 pw.format("%s='*****'%n", key); -470 } else { -471final String value = properties.getProperty(key); -472if (value != null) { -473 pw.format("%s='%s'%n", key, value); -474 } -475 } -476 } -477 pw.flush(); -478 LOGGER.debug(sw.toString()); -479 } finally { -480if (pw != null) { -481 pw.close(); -482 } -483 } -484 -485 } -486 } -487 -488/** -489 * Sets a property value. -490 * -491 * @param key the key for the property -492 * @param value the value for the property -493 */ -494publicstaticvoid setString(String key, String value) { -495 LOCAL_SETTINGS.get().props.setProperty(key, value); -496 LOGGER.debug("Setting: {}='{}'", key, value); -497 } -498 -499/** -500 * Sets a property value only if the value is not null. -501 * -502 * @param key the key for the property -503 * @param value the value for the property -504 */ -505publicstaticvoid setStringIfNotNull(String key, String value) { -506if (null != value) { -507 setString(key, value); -508 } -509 } -510 -511/** -512 * Sets a property value only if the value is not null and not empty. -513 * -514 * @param key the key for the property -515 * @param value the value for the property -516 */ -517publicstaticvoid setStringIfNotEmpty(String key, String value) { -518if (null != value && !value.isEmpty()) { -519 setString(key, value); -520 } -521 } -522 -523/** -524 * Sets a property value. -525 * -526 * @param key the key for the property -527 * @param value the value for the property -528 */ -529publicstaticvoid setBoolean(String key, boolean value) { -530 setString(key, Boolean.toString(value)); -531 } -532 -533/** -534 * Sets a property value only if the value is not null. -535 * -536 * @param key the key for the property -537 * @param value the value for the property -538 */ -539publicstaticvoid setBooleanIfNotNull(String key, Boolean value) { -540if (null != value) { -541 setBoolean(key, value); -542 } -543 } -544 -545/** -546 * Sets a property value. -547 * -548 * @param key the key for the property -549 * @param value the value for the property -550 */ -551publicstaticvoid setInt(String key, int value) { -552 LOCAL_SETTINGS.get().props.setProperty(key, String.valueOf(value)); -553 LOGGER.debug("Setting: {}='{}'", key, value); -554 } -555 -556/** -557 * Sets a property value only if the value is not null. -558 * -559 * @param key the key for the property -560 * @param value the value for the property -561 */ -562publicstaticvoid setIntIfNotNull(String key, Integer value) { -563if (null != value) { -564 setInt(key, value); -565 } -566 } -567 -568/** -569 * Merges a new properties file into the current properties. This method -570 * allows for the loading of a user provided properties file.<br><br> -571 * <b>Note</b>: even if using this method - system properties will be loaded -572 * before properties loaded from files. -573 * -574 * @param filePath the path to the properties file to merge. -575 * @throws FileNotFoundException is thrown when the filePath points to a -576 * non-existent file -577 * @throws IOException is thrown when there is an exception loading/merging -578 * the properties -579 */ -580publicstaticvoid mergeProperties(File filePath) throws FileNotFoundException, IOException { -581 FileInputStream fis = null; -582try { -583 fis = new FileInputStream(filePath); -584 mergeProperties(fis); -585 } finally { -586if (fis != null) { -587try { -588 fis.close(); -589 } catch (IOException ex) { -590 LOGGER.trace("close error", ex); -591 } -592 } -593 } -594 } -595 -596/** -597 * Merges a new properties file into the current properties. This method -598 * allows for the loading of a user provided properties file.<br><br> -599 * Note: even if using this method - system properties will be loaded before -600 * properties loaded from files. -601 * -602 * @param filePath the path to the properties file to merge. -603 * @throws FileNotFoundException is thrown when the filePath points to a -604 * non-existent file -605 * @throws IOException is thrown when there is an exception loading/merging -606 * the properties -607 */ -608publicstaticvoid mergeProperties(String filePath) throws FileNotFoundException, IOException { -609 FileInputStream fis = null; -610try { -611 fis = new FileInputStream(filePath); -612 mergeProperties(fis); -613 } finally { -614if (fis != null) { -615try { -616 fis.close(); -617 } catch (IOException ex) { -618 LOGGER.trace("close error", ex); -619 } -620 } -621 } -622 } -623 -624/** -625 * Merges a new properties file into the current properties. This method -626 * allows for the loading of a user provided properties file.<br><br> -627 * <b>Note</b>: even if using this method - system properties will be loaded -628 * before properties loaded from files. -629 * -630 * @param stream an Input Stream pointing at a properties file to merge -631 * @throws IOException is thrown when there is an exception loading/merging -632 * the properties -633 */ -634publicstaticvoid mergeProperties(InputStream stream) throws IOException { -635 LOCAL_SETTINGS.get().props.load(stream); -636 logProperties("Properties updated via merge", LOCAL_SETTINGS.get().props); -637 } -638 -639/** -640 * Returns a value from the properties file as a File object. If the value -641 * was specified as a system property or passed in via the -Dprop=value -642 * argument - this method will return the value from the system properties -643 * before the values in the contained configuration file. -644 * -645 * @param key the key to lookup within the properties file -646 * @return the property from the properties file converted to a File object -647 */ -648publicstatic File getFile(String key) { -649final String file = getString(key); -650if (file == null) { -651returnnull; -652 } -653returnnew File(file); -654 } -655 -656/** -657 * Returns a value from the properties file as a File object. If the value -658 * was specified as a system property or passed in via the -Dprop=value -659 * argument - this method will return the value from the system properties -660 * before the values in the contained configuration file. -661 * -662 * This method will check the configured base directory and will use this as -663 * the base of the file path. Additionally, if the base directory begins -664 * with a leading "[JAR]\" sequence with the path to the folder containing -665 * the JAR file containing this class. -666 * -667 * @param key the key to lookup within the properties file -668 * @return the property from the properties file converted to a File object -669 */ -670protectedstatic File getDataFile(String key) { -671final String file = getString(key); -672 LOGGER.debug("Settings.getDataFile() - file: '{}'", file); -673if (file == null) { -674returnnull; -675 } -676if (file.startsWith("[JAR]")) { -677 LOGGER.debug("Settings.getDataFile() - transforming filename"); -678final File jarPath = getJarPath(); -679 LOGGER.debug("Settings.getDataFile() - jar file: '{}'", jarPath.toString()); -680final File retVal = new File(jarPath, file.substring(6)); -681 LOGGER.debug("Settings.getDataFile() - returning: '{}'", retVal.toString()); -682return retVal; +411 */ +412publicstaticvoid cleanup() { +413 cleanup(true); +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 */ +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 } -684returnnew File(file); -685 } -686 -687/** -688 * Attempts to retrieve the folder containing the Jar file containing the -689 * Settings class. -690 * -691 * @return a File object -692 */ -693privatestatic File getJarPath() { -694final String jarPath = Settings.class.getProtectionDomain().getCodeSource().getLocation().getPath(); -695 String decodedPath = "."; -696try { -697 decodedPath = URLDecoder.decode(jarPath, "UTF-8"); -698 } catch (UnsupportedEncodingException ex) { -699 LOGGER.trace("", ex); -700 } -701 -702final File path = new File(decodedPath); -703if (path.getName().toLowerCase().endsWith(".jar")) { -704return path.getParentFile(); -705 } else { -706returnnew File("."); -707 } -708 } +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 -710/** -711 * Returns a value from the properties file. If the value was specified as a -712 * system property or passed in via the -Dprop=value argument - this method -713 * will return the value from the system properties before the values in the -714 * contained configuration file. -715 * -716 * @param key the key to lookup within the properties file -717 * @param defaultValue the default value for the requested property -718 * @return the property from the properties file -719 */ -720publicstatic String getString(String key, String defaultValue) { -721final String str = System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key, defaultValue)); -722return str; -723 } -724 -725/** -726 * A reference to the temporary directory; used incase it needs to be -727 * deleted during cleanup. -728 */ -729privatestatic File tempDirectory = null; -730 -731/** -732 * Returns the temporary directory. -733 * -734 * @return the temporary directory -735 * @throws java.io.IOException thrown if the temporary directory does not -736 * exist and cannot be created -737 */ -738publicstatic File getTempDirectory() throws IOException { -739final File tmpDir = new File(Settings.getString(Settings.KEYS.TEMP_DIRECTORY, System.getProperty("java.io.tmpdir")), "dctemp"); -740if (!tmpDir.exists() && !tmpDir.mkdirs()) { -741final String msg = String.format("Unable to make a temporary folder '%s'", tmpDir.getPath()); -742thrownew IOException(msg); -743 } -744 tempDirectory = tmpDir; -745return tmpDir; -746 } -747 -748/** -749 * Returns a value from the properties file. If the value was specified as a -750 * system property or passed in via the -Dprop=value argument - this method -751 * will return the value from the system properties before the values in the -752 * contained configuration file. -753 * -754 * @param key the key to lookup within the properties file -755 * @return the property from the properties file -756 */ -757publicstatic String getString(String key) { -758return System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key)); -759 } -760 -761/** -762 * Removes a property from the local properties collection. This is mainly -763 * used in test cases. -764 * -765 * @param key the property key to remove -766 */ -767publicstaticvoid removeProperty(String key) { -768 LOCAL_SETTINGS.get().props.remove(key); -769 } -770 -771/** -772 * Returns an int value from the properties file. If the value was specified -773 * as a system property or passed in via the -Dprop=value argument - this -774 * method will return the value from the system properties before the values -775 * in the contained configuration file. -776 * -777 * @param key the key to lookup within the properties file -778 * @return the property from the properties file -779 * @throws InvalidSettingException is thrown if there is an error retrieving -780 * the setting -781 */ -782publicstaticint getInt(String key) throws InvalidSettingException { -783try { -784return Integer.parseInt(Settings.getString(key)); -785 } catch (NumberFormatException ex) { -786thrownewInvalidSettingException("Could not convert property '" + key + "' to an int.", ex); -787 } -788 } -789 -790/** -791 * Returns an int value from the properties file. If the value was specified -792 * as a system property or passed in via the -Dprop=value argument - this -793 * method will return the value from the system properties before the values -794 * in the contained configuration file. -795 * -796 * @param key the key to lookup within the properties file -797 * @param defaultValue the default value to return -798 * @return the property from the properties file or the defaultValue if the -799 * property does not exist or cannot be converted to an integer -800 */ -801publicstaticint getInt(String key, int defaultValue) { -802int value; -803try { -804 value = Integer.parseInt(Settings.getString(key)); -805 } catch (NumberFormatException ex) { -806if (!Settings.getString(key, "").isEmpty()) { -807 LOGGER.debug("Could not convert property '{}={}' to an int; using {} instead.", key, Settings.getString(key), defaultValue); -808 } -809 value = defaultValue; -810 } -811return value; -812 } -813 -814/** -815 * Returns a long value from the properties file. If the value was specified -816 * as a system property or passed in via the -Dprop=value argument - this -817 * method will return the value from the system properties before the values -818 * in the contained configuration file. -819 * -820 * @param key the key to lookup within the properties file -821 * @return the property from the properties file -822 * @throws InvalidSettingException is thrown if there is an error retrieving -823 * the setting -824 */ -825publicstaticlong getLong(String key) throws InvalidSettingException { -826try { -827return Long.parseLong(Settings.getString(key)); -828 } catch (NumberFormatException ex) { -829thrownewInvalidSettingException("Could not convert property '" + key + "' to a long.", ex); -830 } -831 } -832 -833/** -834 * Returns a boolean value from the properties file. If the value was -835 * specified as a system property or passed in via the -836 * <code>-Dprop=value</code> argument this method will return the value from -837 * the system properties before the values in the contained configuration -838 * file. -839 * -840 * @param key the key to lookup within the properties file -841 * @return the property from the properties file -842 * @throws InvalidSettingException is thrown if there is an error retrieving -843 * the setting -844 */ -845publicstaticboolean getBoolean(String key) throws InvalidSettingException { -846return Boolean.parseBoolean(Settings.getString(key)); -847 } -848 -849/** -850 * Returns a boolean value from the properties file. If the value was -851 * specified as a system property or passed in via the -852 * <code>-Dprop=value</code> argument this method will return the value from -853 * the system properties before the values in the contained configuration -854 * file. -855 * -856 * @param key the key to lookup within the properties file -857 * @param defaultValue the default value to return if the setting does not -858 * exist -859 * @return the property from the properties file -860 * @throws InvalidSettingException is thrown if there is an error retrieving -861 * the setting -862 */ -863publicstaticboolean getBoolean(String key, boolean defaultValue) throws InvalidSettingException { -864return Boolean.parseBoolean(Settings.getString(key, Boolean.toString(defaultValue))); -865 } -866 -867/** -868 * Returns a connection string from the configured properties. If the -869 * connection string contains a %s, this method will determine the 'data' -870 * directory and replace the %s with the path to the data directory. If the -871 * data directory does not exists it will be created. -872 * -873 * @param connectionStringKey the property file key for the connection -874 * string -875 * @param dbFileNameKey the settings key for the db filename -876 * @return the connection string -877 * @throws IOException thrown the data directory cannot be created -878 * @throws InvalidSettingException thrown if there is an invalid setting -879 */ -880publicstatic String getConnectionString(String connectionStringKey, String dbFileNameKey) -881throws IOException, InvalidSettingException { -882final String connStr = Settings.getString(connectionStringKey); -883if (connStr == null) { -884final String msg = String.format("Invalid properties file; %s is missing.", connectionStringKey); -885thrownewInvalidSettingException(msg); -886 } -887if (connStr.contains("%s")) { -888final File directory = getDataDirectory(); -889 String fileName = null; -890if (dbFileNameKey != null) { -891 fileName = Settings.getString(dbFileNameKey); -892 } -893if (fileName == null) { -894final String msg = String.format("Invalid properties file to get a file based connection string; '%s' must be defined.", -895 dbFileNameKey); -896thrownewInvalidSettingException(msg); -897 } -898if (connStr.startsWith("jdbc:h2:file:") && fileName.endsWith(".h2.db")) { -899 fileName = fileName.substring(0, fileName.length() - 6); +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); +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 } -901// yes, for H2 this path won't actually exists - but this is sufficient to get the value needed -902final File dbFile = new File(directory, fileName); -903final String cString = String.format(connStr, dbFile.getCanonicalPath()); -904 LOGGER.debug("Connection String: '{}'", cString); -905return cString; -906 } -907return connStr; -908 } -909 -910/** -911 * Retrieves the directory that the JAR file exists in so that we can ensure -912 * we always use a common data directory for the embedded H2 database. This -913 * is public solely for some unit tests; otherwise this should be private. -914 * -915 * @return the data directory to store data files -916 * @throws IOException is thrown if an IOException occurs of course... -917 */ -918publicstatic File getDataDirectory() throws IOException { -919final File path = Settings.getDataFile(Settings.KEYS.DATA_DIRECTORY); -920if (path.exists() || path.mkdirs()) { -921return path; -922 } -923thrownew IOException(String.format("Unable to create the data directory '%s'", path.getAbsolutePath())); -924 } -925 } +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 }
    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 f38bcbe57..cbb6a4306 100644 --- a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/URLConnectionFactory.html +++ b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/URLConnectionFactory.html @@ -36,180 +36,181 @@ 28import java.net.Proxy; 29import java.net.SocketAddress; 30import java.net.URL; -31import java.security.KeyManagementException; -32import java.security.NoSuchAlgorithmException; -33import javax.net.ssl.HttpsURLConnection; -34import org.slf4j.Logger; -35import org.slf4j.LoggerFactory; -36 -37/** -38 * A URLConnection Factory to create new connections. This encapsulates several -39 * configuration checks to ensure that the connection uses the correct proxy -40 * settings. -41 * -42 * @author Jeremy Long -43 */ -44publicfinalclassURLConnectionFactory { -45 -46/** -47 * The logger. -48 */ -49privatestaticfinal Logger LOGGER = LoggerFactory.getLogger(URLConnectionFactory.class); -50 -51/** -52 * Private constructor for this factory. -53 */ -54privateURLConnectionFactory() { -55 } -56 -57/** -58 * Utility method to create an HttpURLConnection. If the application is -59 * configured to use a proxy this method will retrieve the proxy settings -60 * and use them when setting up the connection. -61 * -62 * @param url the url to connect to -63 * @return an HttpURLConnection -64 * @throws URLConnectionFailureException thrown if there is an exception -65 */ -66 @SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE", justification = "Just being extra safe") -67publicstatic HttpURLConnection createHttpURLConnection(URL url) throws URLConnectionFailureException { -68 HttpURLConnection conn = null; -69final String proxyUrl = Settings.getString(Settings.KEYS.PROXY_SERVER); -70 -71try { -72if (proxyUrl != null && !matchNonProxy(url)) { -73finalint proxyPort = Settings.getInt(Settings.KEYS.PROXY_PORT); -74final SocketAddress address = new InetSocketAddress(proxyUrl, proxyPort); -75 -76final String username = Settings.getString(Settings.KEYS.PROXY_USERNAME); -77final String password = Settings.getString(Settings.KEYS.PROXY_PASSWORD); -78 -79if (username != null && password != null) { -80final Authenticator auth = new Authenticator() { -81 @Override -82public PasswordAuthentication getPasswordAuthentication() { -83if (getRequestorType().equals(Authenticator.RequestorType.PROXY)) { -84returnnew PasswordAuthentication(username, password.toCharArray()); -85 } -86returnsuper.getPasswordAuthentication(); -87 } -88 }; -89 Authenticator.setDefault(auth); -90 } -91 -92final Proxy proxy = new Proxy(Proxy.Type.HTTP, address); -93 conn = (HttpURLConnection) url.openConnection(proxy); -94 } else { -95 conn = (HttpURLConnection) url.openConnection(); -96 } -97finalint timeout = Settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 10000); -98 conn.setConnectTimeout(timeout); -99 conn.setInstanceFollowRedirects(true); -100 } catch (IOException ex) { -101if (conn != null) { -102try { -103 conn.disconnect(); -104 } finally { -105 conn = null; -106 } -107 } -108thrownewURLConnectionFailureException("Error getting connection.", ex); -109 } -110 configureTLS(url, conn); -111return conn; -112 } -113 -114/** -115 * Check if hostname matches nonProxy settings -116 * -117 * @param url the url to connect to -118 * @return matching result. true: match nonProxy -119 */ -120privatestaticboolean matchNonProxy(final URL url) { -121final String host = url.getHost(); -122 -123// code partially from org.apache.maven.plugins.site.AbstractDeployMojo#getProxyInfo -124final String nonProxyHosts = Settings.getString(Settings.KEYS.PROXY_NON_PROXY_HOSTS); -125if (null != nonProxyHosts) { -126final String[] nonProxies = nonProxyHosts.split("(,)|(;)|(\\|)"); -127for (final String nonProxyHost : nonProxies) { -128//if ( StringUtils.contains( nonProxyHost, "*" ) ) -129if (null != nonProxyHost && nonProxyHost.contains("*")) { -130// Handle wildcard at the end, beginning or middle of the nonProxyHost -131finalint pos = nonProxyHost.indexOf('*'); -132final String nonProxyHostPrefix = nonProxyHost.substring(0, pos); -133final String nonProxyHostSuffix = nonProxyHost.substring(pos + 1); -134// prefix* -135if (!StringUtils.isEmpty(nonProxyHostPrefix) && host.startsWith(nonProxyHostPrefix) && StringUtils.isEmpty(nonProxyHostSuffix)) { -136returntrue; -137 } -138// *suffix -139if (StringUtils.isEmpty(nonProxyHostPrefix) && !StringUtils.isEmpty(nonProxyHostSuffix) && host.endsWith(nonProxyHostSuffix)) { -140returntrue; -141 } -142// prefix*suffix -143if (!StringUtils.isEmpty(nonProxyHostPrefix) && host.startsWith(nonProxyHostPrefix) && !StringUtils.isEmpty(nonProxyHostSuffix) -144 && host.endsWith(nonProxyHostSuffix)) { -145returntrue; -146 } -147 } elseif (host.equals(nonProxyHost)) { -148returntrue; -149 } -150 } -151 } -152return false; -153 } -154 -155/** -156 * Utility method to create an HttpURLConnection. The use of a proxy here is -157 * optional as there may be cases where a proxy is configured but we don't -158 * want to use it (for example, if there's an internal repository -159 * configured) -160 * -161 * @param url the URL to connect to -162 * @param proxy whether to use the proxy (if configured) -163 * @return a newly constructed HttpURLConnection -164 * @throws URLConnectionFailureException thrown if there is an exception -165 */ -166publicstatic HttpURLConnection createHttpURLConnection(URL url, boolean proxy) throws URLConnectionFailureException { -167if (proxy) { -168return createHttpURLConnection(url); -169 } -170 HttpURLConnection conn = null; -171try { -172 conn = (HttpURLConnection) url.openConnection(); -173finalint timeout = Settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 10000); -174 conn.setConnectTimeout(timeout); -175 conn.setInstanceFollowRedirects(true); -176 } catch (IOException ioe) { -177thrownewURLConnectionFailureException("Error getting connection.", ioe); -178 } -179 configureTLS(url, conn); -180return conn; -181 } -182 -183/** -184 * If the protocol is HTTPS, this will configure the cipher suites so that -185 * connections can be made to the NVD, and others, using older versions of -186 * Java. -187 * -188 * @param url the URL -189 * @param conn the connection -190 */ -191privatestaticvoid configureTLS(URL url, HttpURLConnection conn) { -192if ("https".equals(url.getProtocol())) { -193try { -194final HttpsURLConnection secCon = (HttpsURLConnection) conn; -195finalSSLSocketFactoryEx factory = newSSLSocketFactoryEx(); -196 secCon.setSSLSocketFactory(factory); -197 } catch (NoSuchAlgorithmException ex) { -198 LOGGER.debug("Unsupported algorithm in SSLSocketFactoryEx", ex); -199 } catch (KeyManagementException ex) { -200 LOGGER.debug("Key mnagement eception in SSLSocketFactoryEx", ex); -201 } -202 } -203 } -204 } +31import java.net.URLConnection; +32import java.security.KeyManagementException; +33import java.security.NoSuchAlgorithmException; +34import javax.net.ssl.HttpsURLConnection; +35import org.slf4j.Logger; +36import org.slf4j.LoggerFactory; +37 +38/** +39 * A URLConnection Factory to create new connections. This encapsulates several +40 * configuration checks to ensure that the connection uses the correct proxy +41 * settings. +42 * +43 * @author Jeremy Long +44 */ +45publicfinalclassURLConnectionFactory { +46 +47/** +48 * The logger. +49 */ +50privatestaticfinal Logger LOGGER = LoggerFactory.getLogger(URLConnectionFactory.class); +51 +52/** +53 * Private constructor for this factory. +54 */ +55privateURLConnectionFactory() { +56 } +57 +58/** +59 * Utility method to create an HttpURLConnection. If the application is +60 * configured to use a proxy this method will retrieve the proxy settings +61 * and use them when setting up the connection. +62 * +63 * @param url the url to connect to +64 * @return an HttpURLConnection +65 * @throws URLConnectionFailureException thrown if there is an exception +66 */ +67 @SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE", justification = "Just being extra safe") +68publicstatic HttpURLConnection createHttpURLConnection(URL url) throws URLConnectionFailureException { +69 HttpURLConnection conn = null; +70final String proxyUrl = Settings.getString(Settings.KEYS.PROXY_SERVER); +71 +72try { +73if (proxyUrl != null && !matchNonProxy(url)) { +74finalint proxyPort = Settings.getInt(Settings.KEYS.PROXY_PORT); +75final SocketAddress address = new InetSocketAddress(proxyUrl, proxyPort); +76 +77final String username = Settings.getString(Settings.KEYS.PROXY_USERNAME); +78final String password = Settings.getString(Settings.KEYS.PROXY_PASSWORD); +79 +80if (username != null && password != null) { +81final Authenticator auth = new Authenticator() { +82 @Override +83public PasswordAuthentication getPasswordAuthentication() { +84if (getRequestorType().equals(Authenticator.RequestorType.PROXY)) { +85returnnew PasswordAuthentication(username, password.toCharArray()); +86 } +87returnsuper.getPasswordAuthentication(); +88 } +89 }; +90 Authenticator.setDefault(auth); +91 } +92 +93final Proxy proxy = new Proxy(Proxy.Type.HTTP, address); +94 conn = (HttpURLConnection) url.openConnection(proxy); +95 } else { +96 conn = (HttpURLConnection) url.openConnection(); +97 } +98finalint timeout = Settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 10000); +99 conn.setConnectTimeout(timeout); +100 conn.setInstanceFollowRedirects(true); +101 } catch (IOException ex) { +102if (conn != null) { +103try { +104 conn.disconnect(); +105 } finally { +106 conn = null; +107 } +108 } +109thrownewURLConnectionFailureException("Error getting connection.", ex); +110 } +111 configureTLS(url, conn); +112return conn; +113 } +114 +115/** +116 * Check if hostname matches nonProxy settings +117 * +118 * @param url the url to connect to +119 * @return matching result. true: match nonProxy +120 */ +121privatestaticboolean matchNonProxy(final URL url) { +122final String host = url.getHost(); +123 +124// code partially from org.apache.maven.plugins.site.AbstractDeployMojo#getProxyInfo +125final String nonProxyHosts = Settings.getString(Settings.KEYS.PROXY_NON_PROXY_HOSTS); +126if (null != nonProxyHosts) { +127final String[] nonProxies = nonProxyHosts.split("(,)|(;)|(\\|)"); +128for (final String nonProxyHost : nonProxies) { +129//if ( StringUtils.contains( nonProxyHost, "*" ) ) +130if (null != nonProxyHost && nonProxyHost.contains("*")) { +131// Handle wildcard at the end, beginning or middle of the nonProxyHost +132finalint pos = nonProxyHost.indexOf('*'); +133final String nonProxyHostPrefix = nonProxyHost.substring(0, pos); +134final String nonProxyHostSuffix = nonProxyHost.substring(pos + 1); +135// prefix* +136if (!StringUtils.isEmpty(nonProxyHostPrefix) && host.startsWith(nonProxyHostPrefix) && StringUtils.isEmpty(nonProxyHostSuffix)) { +137returntrue; +138 } +139// *suffix +140if (StringUtils.isEmpty(nonProxyHostPrefix) && !StringUtils.isEmpty(nonProxyHostSuffix) && host.endsWith(nonProxyHostSuffix)) { +141returntrue; +142 } +143// prefix*suffix +144if (!StringUtils.isEmpty(nonProxyHostPrefix) && host.startsWith(nonProxyHostPrefix) && !StringUtils.isEmpty(nonProxyHostSuffix) +145 && host.endsWith(nonProxyHostSuffix)) { +146returntrue; +147 } +148 } elseif (host.equals(nonProxyHost)) { +149returntrue; +150 } +151 } +152 } +153return false; +154 } +155 +156/** +157 * Utility method to create an HttpURLConnection. The use of a proxy here is +158 * optional as there may be cases where a proxy is configured but we don't +159 * want to use it (for example, if there's an internal repository +160 * configured) +161 * +162 * @param url the URL to connect to +163 * @param proxy whether to use the proxy (if configured) +164 * @return a newly constructed HttpURLConnection +165 * @throws URLConnectionFailureException thrown if there is an exception +166 */ +167publicstatic HttpURLConnection createHttpURLConnection(URL url, boolean proxy) throws URLConnectionFailureException { +168if (proxy) { +169return createHttpURLConnection(url); +170 } +171 HttpURLConnection conn = null; +172try { +173 conn = (HttpURLConnection) url.openConnection(); +174finalint timeout = Settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 10000); +175 conn.setConnectTimeout(timeout); +176 conn.setInstanceFollowRedirects(true); +177 } catch (IOException ioe) { +178thrownewURLConnectionFailureException("Error getting connection.", ioe); +179 } +180 configureTLS(url, conn); +181return conn; +182 } +183 +184/** +185 * If the protocol is HTTPS, this will configure the cipher suites so that +186 * connections can be made to the NVD, and others, using older versions of +187 * Java. +188 * +189 * @param url the URL +190 * @param conn the connection +191 */ +192privatestaticvoid configureTLS(URL url, URLConnection conn) { +193if ("https".equals(url.getProtocol())) { +194try { +195final HttpsURLConnection secCon = (HttpsURLConnection) conn; +196finalSSLSocketFactoryEx factory = newSSLSocketFactoryEx(); +197 secCon.setSSLSocketFactory(factory); +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); +202 } +203 } +204 } +205 }
    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 38c8bc248..2c9a17aef 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.2 Reference Package org.owasp.dependencycheck.utils + Dependency-Check Utils 1.4.3 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 299b1fb50..91e9d572e 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.2 Reference Package org.owasp.dependencycheck.utils + Dependency-Check Utils 1.4.3 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 516fe62e9..46b9088ae 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.2 Reference + Dependency-Check Utils 1.4.3 Reference diff --git a/dependency-check-utils/xref/overview-summary.html b/dependency-check-utils/xref/overview-summary.html index 02e2a205c..b43685082 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.2 Reference + Dependency-Check Utils 1.4.3 Reference @@ -24,7 +24,7 @@ -

    Dependency-Check Utils 1.4.2 Reference

    +

    Dependency-Check Utils 1.4.3 Reference

    diff --git a/dependency-hint.1.1.xsd b/dependency-hint.1.1.xsd new file mode 100644 index 000000000..63390044a --- /dev/null +++ b/dependency-hint.1.1.xsd @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dependency-updates-report.html b/dependency-updates-report.html index 17950ebd0..0bc54cd94 100644 --- a/dependency-updates-report.html +++ b/dependency-updates-report.html @@ -1,13 +1,13 @@ - + dependency-check – Dependency Updates Report @@ -59,9 +59,9 @@
  • Dependency Updates Report
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • @@ -197,7 +197,7 @@ - + @@ -205,15 +205,15 @@ - + - + -
    # of dependencies using the latest version available23
    21
    # 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 update0
    1
    # of dependencies where the next version available is a minor version update7
    8
    # of dependencies where the next version available is a major version update1
    +2

    Dependency Management

    @@ -278,7 +278,7 @@ - + @@ -286,7 +286,7 @@ - + @@ -482,7 +482,7 @@ - + @@ -491,7 +491,7 @@ - + @@ -506,6 +506,18 @@ + + + + + + + + + + + + @@ -517,7 +529,7 @@ - + @@ -529,7 +541,7 @@ - + @@ -541,7 +553,7 @@ - + @@ -553,7 +565,7 @@ - + @@ -565,7 +577,7 @@ - + @@ -577,7 +589,7 @@ - + @@ -589,7 +601,7 @@ - + @@ -601,7 +613,7 @@ - + @@ -622,25 +634,25 @@

    ch.qos.logback:logback-classic

    1.4.177
    com.sun.mail mailapi 1.5.5 jar 1.5.6
    org.apache.maven.plugin-tools maven-plugin-annotations 3.4jar 3.5
    org.apache.maven.sharedmaven-dependency-tree2.2jar3.0
    org.apache.velocity velocity
    org.glassfish javax.json
    org.hamcrest hamcrest-core
    org.jmockit jmockit 1.25
    org.jsoup jsoup
    org.slf4j slf4j-api
    org.slf4j slf4j-simple
    org.sonatype.plexus plexus-sec-dispatcher
    Status Group Id Artifact Id
    - + - + - + - + - + - + - +
    Status  No newer versions available.
    Group Id ch.qos.logback
    Artifact Id logback-classic
    Current Version 1.1.7
    Scope
    Classifier
    Type jar
    @@ -723,7 +735,7 @@ - + @@ -741,7 +753,10 @@ -
    Status No newer versions available.
     There is at least one newer incremental version available. Incremental updates are typically passive.
    Group Id com.sun.mail
    Typejar
    +jar + +Newer versions +1.5.6 Next Incremental

    commons-cli:commons-cli

    @@ -966,7 +981,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.lucene:lucene-core

    @@ -993,7 +1008,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.lucene:lucene-queryparser

    @@ -1020,7 +1035,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.lucene:lucene-test-framework

    @@ -1047,7 +1062,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 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
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major

    org.apache.maven:maven-core

    @@ -1149,7 +1164,7 @@
    - + @@ -1167,7 +1182,10 @@ -
    Status No newer versions available.
     There is at least one newer minor version available. Minor updates are sometimes passive.
    Group Id org.apache.maven.plugin-tools
    Typejar
    +jar + +Newer versions +3.5 Next Minor

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

    @@ -1193,6 +1211,33 @@
    Type jar
    +

    org.apache.maven.shared:maven-dependency-tree

    + + + + + + + + + + + + + + + + + + + + + + + + +
    Status There is at least one newer major version available. Major updates are rarely passive.
    Group Idorg.apache.maven.shared
    Artifact Idmaven-dependency-tree
    Current Version2.2
    Scope
    Classifier
    Typejar
    Newer versions3.0 Next Major
    +

    org.apache.velocity:velocity

    @@ -1290,7 +1335,7 @@ -
    jar
    Newer versions1.25 Next Minor
    +1.25 Next Minor
    1.26
    1.27 Latest Minor

    org.jsoup:jsoup

    diff --git a/general/internals.html b/general/internals.html index fbe320327..33ee1dc1e 100644 --- a/general/internals.html +++ b/general/internals.html @@ -1,13 +1,13 @@ - + dependency-check – How does dependency-check work? @@ -59,9 +59,9 @@
  • How does dependency-check work?
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/general/scan_iso.html b/general/scan_iso.html index f534a51a2..65b0a8fec 100644 --- a/general/scan_iso.html +++ b/general/scan_iso.html @@ -1,13 +1,13 @@ - + dependency-check – How to Mount ISO Files for Scanning @@ -59,9 +59,9 @@
  • How to Mount ISO Files for Scanning
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/general/suppression.html b/general/suppression.html index 8113b54f4..01b8eb388 100644 --- a/general/suppression.html +++ b/general/suppression.html @@ -1,13 +1,13 @@ - + dependency-check – Suppressing False Positives @@ -59,9 +59,9 @@
  • Suppressing False Positives
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/general/thereport.html b/general/thereport.html index 472842498..190df99a2 100644 --- a/general/thereport.html +++ b/general/thereport.html @@ -1,13 +1,13 @@ - + dependency-check – How To Read The Reports @@ -59,9 +59,9 @@
  • How To Read The Reports
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/index.html b/index.html index bf0dc28ae..0b21233db 100644 --- a/index.html +++ b/index.html @@ -1,13 +1,13 @@ - + dependency-check – About @@ -59,9 +59,9 @@
  • About
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/integration.html b/integration.html index 843e2dd33..811d2f152 100644 --- a/integration.html +++ b/integration.html @@ -1,13 +1,13 @@ - + dependency-check – CI Management @@ -59,9 +59,9 @@
  • CI Management
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/issue-tracking.html b/issue-tracking.html index 3850df29e..965a31b8b 100644 --- a/issue-tracking.html +++ b/issue-tracking.html @@ -1,13 +1,13 @@ - + dependency-check – Issue Management @@ -59,9 +59,9 @@
  • Issue Management
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/license.html b/license.html index 2f701d6da..de7e68358 100644 --- a/license.html +++ b/license.html @@ -1,13 +1,13 @@ - + dependency-check – Project Licenses @@ -59,9 +59,9 @@
  • Project Licenses
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/mail-lists.html b/mail-lists.html index 16034b82b..ca953c48a 100644 --- a/mail-lists.html +++ b/mail-lists.html @@ -1,13 +1,13 @@ - + dependency-check – Project Mailing Lists @@ -59,9 +59,9 @@
  • Project Mailing Lists
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/modules.html b/modules.html index dd26e5483..160c6ed84 100644 --- a/modules.html +++ b/modules.html @@ -1,13 +1,13 @@ - + dependency-check – Modules @@ -59,9 +59,9 @@
  • Modules
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/plugin-updates-report.html b/plugin-updates-report.html index 134550c5e..59c39a499 100644 --- a/plugin-updates-report.html +++ b/plugin-updates-report.html @@ -1,13 +1,13 @@ - + dependency-check – Plugin Updates Report @@ -59,9 +59,9 @@
  • Plugin Updates Report
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/project-info.html b/project-info.html index 8d7428af5..f0a0b375e 100644 --- a/project-info.html +++ b/project-info.html @@ -1,13 +1,13 @@ - + dependency-check – Project Information @@ -59,9 +59,9 @@
  • Project Information
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/project-reports.html b/project-reports.html index 299e7e5d4..d9bfd11a8 100644 --- a/project-reports.html +++ b/project-reports.html @@ -1,13 +1,13 @@ - + dependency-check – Generated Reports @@ -59,9 +59,9 @@
  • Generated Reports
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/project-summary.html b/project-summary.html index fcf50868f..d945a4e53 100644 --- a/project-summary.html +++ b/project-summary.html @@ -1,13 +1,13 @@ - + dependency-check – Project Summary @@ -59,9 +59,9 @@
  • Project Summary
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • @@ -247,7 +247,7 @@ - +
    dependency-check-parent
    Version1.4.2
    1.4.3
    Type pom
    diff --git a/related.html b/related.html index 195363e22..3ca935a9f 100644 --- a/related.html +++ b/related.html @@ -1,13 +1,13 @@ - + dependency-check – Related Work @@ -59,9 +59,9 @@
  • Related Work
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/source-repository.html b/source-repository.html index be443dea5..d5f0acedb 100644 --- a/source-repository.html +++ b/source-repository.html @@ -1,13 +1,13 @@ - + dependency-check – Source Code Management @@ -59,9 +59,9 @@
  • Source Code Management
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/surefire-report.html b/surefire-report.html index c76c9679c..d45503975 100644 --- a/surefire-report.html +++ b/surefire-report.html @@ -1,13 +1,13 @@ - + dependency-check – Surefire Report @@ -59,9 +59,9 @@
  • Surefire Report
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/team-list.html b/team-list.html index 1df7e2840..5153b659c 100644 --- a/team-list.html +++ b/team-list.html @@ -1,13 +1,13 @@ - + dependency-check – Project Team @@ -59,9 +59,9 @@
  • Project Team
  • -
  • | Last Published: 2016-07-31
  • +
  • | Last Published: 2016-09-06
  • - Version: 1.4.2 + Version: 1.4.3
  • diff --git a/xref-test/allclasses-frame.html b/xref-test/allclasses-frame.html index 2cc3eb9bd..bc63b85cc 100644 --- a/xref-test/allclasses-frame.html +++ b/xref-test/allclasses-frame.html @@ -189,7 +189,7 @@ NvdCveInfoTest
  • - NvdCveUpdaterIntegrationTest + NvdCveUpdaterIntegrationTest
  • NvdCve_1_2_HandlerTest @@ -238,6 +238,9 @@
  • SuppressionRuleTest +
  • +
  • + SwiftAnalyzersTest
  • TokenPairConcatenatingFilterTest diff --git a/xref-test/index.html b/xref-test/index.html index e5cd82e24..b705ec2b8 100644 --- a/xref-test/index.html +++ b/xref-test/index.html @@ -4,7 +4,7 @@ - Dependency-Check 1.4.2 Reference + Dependency-Check 1.4.3 Reference diff --git a/xref-test/org/owasp/dependencycheck/analyzer/AssemblyAnalyzerTest.html b/xref-test/org/owasp/dependencycheck/analyzer/AssemblyAnalyzerTest.html index 5cf08bcba..0fe7f7832 100644 --- a/xref-test/org/owasp/dependencycheck/analyzer/AssemblyAnalyzerTest.html +++ b/xref-test/org/owasp/dependencycheck/analyzer/AssemblyAnalyzerTest.html @@ -32,161 +32,164 @@ 24 import static org.junit.Assert.fail; 25 import org.junit.Assume; 26 import static org.junit.Assume.assumeFalse; -27 import org.junit.Before; -28 import org.junit.Test; -29 import org.owasp.dependencycheck.BaseTest; -30 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; -31 import org.owasp.dependencycheck.dependency.Confidence; -32 import org.owasp.dependencycheck.dependency.Dependency; -33 import org.owasp.dependencycheck.dependency.Evidence; -34 import org.owasp.dependencycheck.exception.InitializationException; -35 import org.owasp.dependencycheck.utils.Settings; -36 import org.slf4j.Logger; -37 import org.slf4j.LoggerFactory; -38 -39 /** -40 * Tests for the AssemblyAnalyzer. -41 * -42 * @author colezlaw -43 * -44 */ -45 public class AssemblyAnalyzerTest extends BaseTest { -46 -47 private static final Logger LOGGER = LoggerFactory.getLogger(AssemblyAnalyzerTest.class); -48 -49 private static final String LOG_KEY = "org.slf4j.simpleLogger.org.owasp.dependencycheck.analyzer.AssemblyAnalyzer"; -50 -51 AssemblyAnalyzer analyzer; -52 -53 /** -54 * Sets up the analyzer. -55 * -56 * @throws Exception if anything goes sideways -57 */ -58 @Before -59 public void setUp() throws Exception { -60 try { -61 analyzer = new AssemblyAnalyzer(); -62 analyzer.accept(new File("test.dll")); // trick into "thinking it is active" -63 analyzer.initialize(); -64 } catch (Exception e) { -65 if (e.getMessage().contains("Could not execute .NET AssemblyAnalyzer")) { -66 LOGGER.warn("Exception setting up AssemblyAnalyzer. Tests will be incomplete"); -67 } else { +27 import static org.junit.Assume.assumeNotNull; +28 import org.junit.Before; +29 import org.junit.Test; +30 import org.owasp.dependencycheck.BaseTest; +31 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; +32 import org.owasp.dependencycheck.dependency.Confidence; +33 import org.owasp.dependencycheck.dependency.Dependency; +34 import org.owasp.dependencycheck.dependency.Evidence; +35 import org.owasp.dependencycheck.exception.InitializationException; +36 import org.owasp.dependencycheck.utils.Settings; +37 import org.slf4j.Logger; +38 import org.slf4j.LoggerFactory; +39 +40 /** +41 * Tests for the AssemblyAnalyzer. +42 * +43 * @author colezlaw +44 * +45 */ +46 public class AssemblyAnalyzerTest extends BaseTest { +47 +48 private static final Logger LOGGER = LoggerFactory.getLogger(AssemblyAnalyzerTest.class); +49 +50 private static final String LOG_KEY = "org.slf4j.simpleLogger.org.owasp.dependencycheck.analyzer.AssemblyAnalyzer"; +51 +52 AssemblyAnalyzer analyzer; +53 +54 /** +55 * Sets up the analyzer. +56 * +57 * @throws Exception if anything goes sideways +58 */ +59 @Before +60 public void setUp() throws Exception { +61 try { +62 analyzer = new AssemblyAnalyzer(); +63 analyzer.accept(new File("test.dll")); // trick into "thinking it is active" +64 analyzer.initialize(); +65 Assume.assumeTrue("Mono is not installed, skipping tests.", analyzer.buildArgumentList() == null); +66 } catch (Exception e) { +67 if (e.getMessage().contains("Could not execute .NET AssemblyAnalyzer")) { 68 LOGGER.warn("Exception setting up AssemblyAnalyzer. Tests will be incomplete"); -69 } -70 Assume.assumeNoException("Is mono installed? TESTS WILL BE INCOMPLETE", e); -71 } -72 } -73 -74 /** -75 * Tests to make sure the name is correct. -76 */ -77 @Test -78 public void testGetName() { -79 assertEquals("Assembly Analyzer", analyzer.getName()); -80 } -81 -82 @Test -83 public void testAnalysis() throws Exception { -84 //File f = new File(AssemblyAnalyzerTest.class.getClassLoader().getResource("GrokAssembly.exe").getPath()); -85 File f = BaseTest.getResourceAsFile(this, "GrokAssembly.exe"); -86 Dependency d = new Dependency(f); -87 analyzer.analyze(d, null); -88 boolean foundVendor = false; -89 for (Evidence e : d.getVendorEvidence().getEvidence("grokassembly", "vendor")) { -90 if ("OWASP".equals(e.getValue())) { -91 foundVendor = true; -92 } -93 } -94 assertTrue(foundVendor); -95 -96 boolean foundProduct = false; -97 for (Evidence e : d.getProductEvidence().getEvidence("grokassembly", "product")) { -98 if ("GrokAssembly".equals(e.getValue())) { -99 foundProduct = true; -100 } -101 } -102 assertTrue(foundProduct); -103 } -104 -105 @Test -106 public void testLog4Net() throws Exception { -107 //File f = new File(AssemblyAnalyzerTest.class.getClassLoader().getResource("log4net.dll").getPath()); -108 File f = BaseTest.getResourceAsFile(this, "log4net.dll"); -109 -110 Dependency d = new Dependency(f); -111 analyzer.analyze(d, null); -112 assertTrue(d.getVersionEvidence().getEvidence().contains(new Evidence("grokassembly", "version", "1.2.13.0", Confidence.HIGHEST))); -113 assertTrue(d.getVendorEvidence().getEvidence().contains(new Evidence("grokassembly", "vendor", "The Apache Software Foundation", Confidence.HIGH))); -114 assertTrue(d.getProductEvidence().getEvidence().contains(new Evidence("grokassembly", "product", "log4net", Confidence.HIGH))); -115 } -116 -117 @Test -118 public void testNonexistent() { -119 // Tweak the log level so the warning doesn't show in the console -120 String oldProp = System.getProperty(LOG_KEY, "info"); -121 //File f = new File(AssemblyAnalyzerTest.class.getClassLoader().getResource("log4net.dll").getPath()); -122 File f = BaseTest.getResourceAsFile(this, "log4net.dll"); -123 File test = new File(f.getParent(), "nonexistent.dll"); -124 Dependency d = new Dependency(test); -125 -126 try { -127 analyzer.analyze(d, null); -128 fail("Expected an AnalysisException"); -129 } catch (AnalysisException ae) { -130 assertEquals("File does not exist", ae.getMessage()); -131 } finally { -132 System.setProperty(LOG_KEY, oldProp); -133 } -134 } -135 -136 @Test -137 public void testWithSettingMono() throws Exception { +69 } else { +70 LOGGER.warn("Exception setting up AssemblyAnalyzer. Tests will be incomplete"); +71 } +72 Assume.assumeNoException("Is mono installed? TESTS WILL BE INCOMPLETE", e); +73 } +74 } +75 +76 /** +77 * Tests to make sure the name is correct. +78 */ +79 @Test +80 public void testGetName() { +81 assertEquals("Assembly Analyzer", analyzer.getName()); +82 } +83 +84 @Test +85 public void testAnalysis() throws Exception { +86 assumeNotNull(analyzer.buildArgumentList()); +87 File f = BaseTest.getResourceAsFile(this, "GrokAssembly.exe"); +88 Dependency d = new Dependency(f); +89 analyzer.analyze(d, null); +90 boolean foundVendor = false; +91 for (Evidence e : d.getVendorEvidence().getEvidence("grokassembly", "vendor")) { +92 if ("OWASP".equals(e.getValue())) { +93 foundVendor = true; +94 } +95 } +96 assertTrue(foundVendor); +97 +98 boolean foundProduct = false; +99 for (Evidence e : d.getProductEvidence().getEvidence("grokassembly", "product")) { +100 if ("GrokAssembly".equals(e.getValue())) { +101 foundProduct = true; +102 } +103 } +104 assertTrue(foundProduct); +105 } +106 +107 @Test +108 public void testLog4Net() throws Exception { +109 assumeNotNull(analyzer.buildArgumentList()); +110 File f = BaseTest.getResourceAsFile(this, "log4net.dll"); +111 +112 Dependency d = new Dependency(f); +113 analyzer.analyze(d, null); +114 assertTrue(d.getVersionEvidence().getEvidence().contains(new Evidence("grokassembly", "version", "1.2.13.0", Confidence.HIGHEST))); +115 assertTrue(d.getVendorEvidence().getEvidence().contains(new Evidence("grokassembly", "vendor", "The Apache Software Foundation", Confidence.HIGH))); +116 assertTrue(d.getProductEvidence().getEvidence().contains(new Evidence("grokassembly", "product", "log4net", Confidence.HIGH))); +117 } +118 +119 @Test +120 public void testNonexistent() { +121 assumeNotNull(analyzer.buildArgumentList()); +122 +123 // Tweak the log level so the warning doesn't show in the console +124 String oldProp = System.getProperty(LOG_KEY, "info"); +125 File f = BaseTest.getResourceAsFile(this, "log4net.dll"); +126 File test = new File(f.getParent(), "nonexistent.dll"); +127 Dependency d = new Dependency(test); +128 +129 try { +130 analyzer.analyze(d, null); +131 fail("Expected an AnalysisException"); +132 } catch (AnalysisException ae) { +133 assertEquals("File does not exist", ae.getMessage()); +134 } finally { +135 System.setProperty(LOG_KEY, oldProp); +136 } +137 } 138 -139 //This test doesn't work on Windows. -140 assumeFalse(System.getProperty("os.name").startsWith("Windows")); +139 @Test +140 public void testWithSettingMono() throws Exception { 141 -142 String oldValue = Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH); -143 // if oldValue is null, that means that neither the system property nor the setting has -144 // been set. If that's the case, then we have to make it such that when we recover, -145 // null still comes back. But you can't put a null value in a HashMap, so we have to set -146 // the system property rather than the setting. -147 if (oldValue == null) { -148 System.setProperty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, "/yooser/bine/mono"); -149 } else { -150 Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, "/yooser/bine/mono"); -151 } -152 -153 String oldProp = System.getProperty(LOG_KEY, "info"); -154 try { -155 // Tweak the logging to swallow the warning when testing -156 System.setProperty(LOG_KEY, "error"); -157 // Have to make a NEW analyzer because during setUp, it would have gotten the correct one -158 AssemblyAnalyzer aanalyzer = new AssemblyAnalyzer(); -159 aanalyzer.accept(new File("test.dll")); // trick into "thinking it is active" -160 aanalyzer.initialize(); -161 fail("Expected an InitializationException"); -162 } catch (InitializationException ae) { -163 assertEquals("An error occurred with the .NET AssemblyAnalyzer", ae.getMessage()); -164 } finally { -165 System.setProperty(LOG_KEY, oldProp); -166 // Recover the logger -167 // Now recover the way we came in. If we had to set a System property, delete it. Otherwise, -168 // reset the old value -169 if (oldValue == null) { -170 System.getProperties().remove(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH); -171 } else { -172 Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, oldValue); -173 } -174 } -175 } -176 -177 @After -178 public void tearDown() throws Exception { -179 analyzer.close(); -180 } -181 } +142 //This test doesn't work on Windows. +143 assumeFalse(System.getProperty("os.name").startsWith("Windows")); +144 +145 String oldValue = Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH); +146 // if oldValue is null, that means that neither the system property nor the setting has +147 // been set. If that's the case, then we have to make it such that when we recover, +148 // null still comes back. But you can't put a null value in a HashMap, so we have to set +149 // the system property rather than the setting. +150 if (oldValue == null) { +151 System.setProperty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, "/yooser/bine/mono"); +152 } else { +153 Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, "/yooser/bine/mono"); +154 } +155 +156 String oldProp = System.getProperty(LOG_KEY, "info"); +157 try { +158 // Tweak the logging to swallow the warning when testing +159 System.setProperty(LOG_KEY, "error"); +160 // Have to make a NEW analyzer because during setUp, it would have gotten the correct one +161 AssemblyAnalyzer aanalyzer = new AssemblyAnalyzer(); +162 aanalyzer.accept(new File("test.dll")); // trick into "thinking it is active" +163 aanalyzer.initialize(); +164 fail("Expected an InitializationException"); +165 } catch (InitializationException ae) { +166 assertEquals("An error occurred with the .NET AssemblyAnalyzer", ae.getMessage()); +167 } finally { +168 System.setProperty(LOG_KEY, oldProp); +169 // Recover the logger +170 // Now recover the way we came in. If we had to set a System property, delete it. Otherwise, +171 // reset the old value +172 if (oldValue == null) { +173 System.getProperties().remove(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH); +174 } else { +175 Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, oldValue); +176 } +177 } +178 } +179 +180 @After +181 public void tearDown() throws Exception { +182 analyzer.close(); +183 } +184 }
    diff --git a/xref-test/org/owasp/dependencycheck/analyzer/CPEAnalyzerIntegrationTest.html b/xref-test/org/owasp/dependencycheck/analyzer/CPEAnalyzerIntegrationTest.html index 2f11380ef..c0687c636 100644 --- a/xref-test/org/owasp/dependencycheck/analyzer/CPEAnalyzerIntegrationTest.html +++ b/xref-test/org/owasp/dependencycheck/analyzer/CPEAnalyzerIntegrationTest.html @@ -197,84 +197,85 @@ 189 instance.determineCPE(spring); 190 instance.determineCPE(spring3); 191 instance.close(); -192 -193 String expResult = "cpe:/a:apache:struts:2.1.2"; -194 Identifier expIdentifier = new Identifier("cpe", expResult, expResult); -195 String expResultSpring = "cpe:/a:springsource:spring_framework:2.5.5"; -196 String expResultSpring3 = "cpe:/a:vmware:springsource_spring_framework:3.0.0"; -197 -198 for (Identifier i : commonValidator.getIdentifiers()) { -199 Assert.assertFalse("Apache Common Validator - found a CPE identifier?", "cpe".equals(i.getType())); -200 } -201 -202 Assert.assertTrue("Incorrect match size - struts", struts.getIdentifiers().size() >= 1); -203 Assert.assertTrue("Incorrect match - struts", struts.getIdentifiers().contains(expIdentifier)); -204 Assert.assertTrue("Incorrect match size - spring3 - " + spring3.getIdentifiers().size(), spring3.getIdentifiers().size() >= 1); -205 -206 //the following two only work if the HintAnalyzer is used. -207 //Assert.assertTrue("Incorrect match size - spring", spring.getIdentifiers().size() == 1); -208 //Assert.assertTrue("Incorrect match - spring", spring.getIdentifiers().get(0).getValue().equals(expResultSpring)); -209 jarAnalyzer.close(); -210 } -211 -212 /** -213 * Test of determineIdentifiers method, of class CPEAnalyzer. -214 * -215 * @throws Exception is thrown when an exception occurs -216 */ -217 @Test -218 public void testDetermineIdentifiers() throws Exception { -219 Dependency openssl = new Dependency(); -220 openssl.getVendorEvidence().addEvidence("test", "vendor", "openssl", Confidence.HIGHEST); -221 openssl.getProductEvidence().addEvidence("test", "product", "openssl", Confidence.HIGHEST); -222 openssl.getVersionEvidence().addEvidence("test", "version", "1.0.1c", Confidence.HIGHEST); -223 -224 CPEAnalyzer instance = new CPEAnalyzer(); -225 instance.open(); -226 instance.determineIdentifiers(openssl, "openssl", "openssl", Confidence.HIGHEST); -227 instance.close(); -228 -229 String expResult = "cpe:/a:openssl:openssl:1.0.1c"; -230 Identifier expIdentifier = new Identifier("cpe", expResult, expResult); -231 -232 assertTrue(openssl.getIdentifiers().contains(expIdentifier)); -233 -234 } -235 -236 /** -237 * Test of searchCPE method, of class CPEAnalyzer. -238 * -239 * @throws Exception is thrown when an exception occurs -240 */ -241 @Test -242 public void testSearchCPE() throws Exception { -243 String vendor = "apache software foundation"; -244 String product = "struts 2 core"; -245 String version = "2.1.2"; -246 String expVendor = "apache"; -247 String expProduct = "struts"; -248 -249 CPEAnalyzer instance = new CPEAnalyzer(); -250 instance.open(); -251 -252 Set<String> productWeightings = Collections.singleton("struts2"); -253 -254 Set<String> vendorWeightings = Collections.singleton("apache"); -255 -256 List<IndexEntry> result = instance.searchCPE(vendor, product, vendorWeightings, productWeightings); -257 instance.close(); -258 -259 boolean found = false; -260 for (IndexEntry entry : result) { -261 if (expVendor.equals(entry.getVendor()) && expProduct.equals(entry.getProduct())) { -262 found = true; -263 break; -264 } -265 } -266 assertTrue("apache:struts was not identified", found); -267 -268 } -269 } +192 +193 +194 String expResult = "cpe:/a:apache:struts:2.1.2"; +195 Identifier expIdentifier = new Identifier("cpe", expResult, expResult); +196 String expResultSpring = "cpe:/a:springsource:spring_framework:2.5.5"; +197 String expResultSpring3 = "cpe:/a:vmware:springsource_spring_framework:3.0.0"; +198 +199 for (Identifier i : commonValidator.getIdentifiers()) { +200 Assert.assertFalse("Apache Common Validator - found a CPE identifier?", "cpe".equals(i.getType())); +201 } +202 +203 Assert.assertTrue("Incorrect match size - struts", struts.getIdentifiers().size() >= 1); +204 Assert.assertTrue("Incorrect match - struts", struts.getIdentifiers().contains(expIdentifier)); +205 Assert.assertTrue("Incorrect match size - spring3 - " + spring3.getIdentifiers().size(), spring3.getIdentifiers().size() >= 1); +206 +207 //the following two only work if the HintAnalyzer is used. +208 //Assert.assertTrue("Incorrect match size - spring", spring.getIdentifiers().size() == 1); +209 //Assert.assertTrue("Incorrect match - spring", spring.getIdentifiers().get(0).getValue().equals(expResultSpring)); +210 jarAnalyzer.close(); +211 } +212 +213 /** +214 * Test of determineIdentifiers method, of class CPEAnalyzer. +215 * +216 * @throws Exception is thrown when an exception occurs +217 */ +218 @Test +219 public void testDetermineIdentifiers() throws Exception { +220 Dependency openssl = new Dependency(); +221 openssl.getVendorEvidence().addEvidence("test", "vendor", "openssl", Confidence.HIGHEST); +222 openssl.getProductEvidence().addEvidence("test", "product", "openssl", Confidence.HIGHEST); +223 openssl.getVersionEvidence().addEvidence("test", "version", "1.0.1c", Confidence.HIGHEST); +224 +225 CPEAnalyzer instance = new CPEAnalyzer(); +226 instance.open(); +227 instance.determineIdentifiers(openssl, "openssl", "openssl", Confidence.HIGHEST); +228 instance.close(); +229 +230 String expResult = "cpe:/a:openssl:openssl:1.0.1c"; +231 Identifier expIdentifier = new Identifier("cpe", expResult, expResult); +232 +233 assertTrue(openssl.getIdentifiers().contains(expIdentifier)); +234 +235 } +236 +237 /** +238 * Test of searchCPE method, of class CPEAnalyzer. +239 * +240 * @throws Exception is thrown when an exception occurs +241 */ +242 @Test +243 public void testSearchCPE() throws Exception { +244 String vendor = "apache software foundation"; +245 String product = "struts 2 core"; +246 String version = "2.1.2"; +247 String expVendor = "apache"; +248 String expProduct = "struts"; +249 +250 CPEAnalyzer instance = new CPEAnalyzer(); +251 instance.open(); +252 +253 Set<String> productWeightings = Collections.singleton("struts2"); +254 +255 Set<String> vendorWeightings = Collections.singleton("apache"); +256 +257 List<IndexEntry> result = instance.searchCPE(vendor, product, vendorWeightings, productWeightings); +258 instance.close(); +259 +260 boolean found = false; +261 for (IndexEntry entry : result) { +262 if (expVendor.equals(entry.getVendor()) && expProduct.equals(entry.getProduct())) { +263 found = true; +264 break; +265 } +266 } +267 assertTrue("apache:struts was not identified", found); +268 +269 } +270 }
    diff --git a/xref-test/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzerTest.html b/xref-test/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzerTest.html index 02d2e1b11..b42f4c06f 100644 --- a/xref-test/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzerTest.html +++ b/xref-test/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzerTest.html @@ -125,118 +125,117 @@ 117 final Engine engine = new Engine(); 118 analyzer.analyze(result, engine); 119 int size = engine.getDependencies().size(); -120 -121 assertTrue(size >= 1); -122 -123 Dependency dependency = engine.getDependencies().get(0); -124 assertTrue(dependency.getProductEvidence().toString().toLowerCase().contains("redcarpet")); -125 assertTrue(dependency.getVersionEvidence().toString().toLowerCase().contains("2.2.2")); -126 assertTrue(dependency.getFilePath().endsWith(resource)); -127 assertTrue(dependency.getFileName().equals("Gemfile.lock")); -128 } catch (Exception e) { -129 LOGGER.warn("Exception setting up RubyBundleAuditAnalyzer. Make sure Ruby gem bundle-audit is installed. You may also need to set property \"analyzer.bundle.audit.path\"."); -130 Assume.assumeNoException("Exception setting up RubyBundleAuditAnalyzer; bundle audit may not be installed, or property \"analyzer.bundle.audit.path\" may not be set.", e); -131 } -132 } -133 -134 /** -135 * Test Ruby addCriticalityToVulnerability -136 */ -137 @Test -138 public void testAddCriticalityToVulnerability() throws AnalysisException, DatabaseException { -139 try { -140 analyzer.initialize(); -141 -142 final Dependency result = new Dependency(BaseTest.getResourceAsFile(this, -143 "ruby/vulnerable/gems/sinatra/Gemfile.lock")); -144 final Engine engine = new Engine(); -145 analyzer.analyze(result, engine); -146 -147 Dependency dependency = engine.getDependencies().get(0); -148 Vulnerability vulnerability = dependency.getVulnerabilities().first(); -149 assertEquals(vulnerability.getCvssScore(), 5.0f, 0.0); -150 -151 } catch (Exception e) { -152 LOGGER.warn("Exception setting up RubyBundleAuditAnalyzer. Make sure Ruby gem bundle-audit is installed. You may also need to set property \"analyzer.bundle.audit.path\"."); -153 Assume.assumeNoException("Exception setting up RubyBundleAuditAnalyzer; bundle audit may not be installed, or property \"analyzer.bundle.audit.path\" may not be set.", e); -154 } -155 } -156 -157 /** -158 * Test when Ruby bundle-audit is not available on the system. -159 * -160 * @throws AnalysisException is thrown when an exception occurs. -161 */ -162 @Test -163 public void testMissingBundleAudit() throws AnalysisException, DatabaseException { -164 //set a non-exist bundle-audit -165 Settings.setString(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH, "phantom-bundle-audit"); -166 try { -167 //initialize should fail. -168 analyzer.initialize(); -169 } catch (Exception e) { -170 //expected, so ignore. -171 } finally { -172 assertThat(analyzer.isEnabled(), is(false)); -173 LOGGER.info("phantom-bundle-audit is not available. Ruby Bundle Audit Analyzer is disabled as expected."); -174 } -175 } -176 -177 /** -178 * Test Ruby dependencies and their paths. -179 * -180 * @throws AnalysisException is thrown when an exception occurs. -181 * @throws DatabaseException thrown when an exception occurs -182 */ -183 @Test -184 public void testDependenciesPath() throws AnalysisException, DatabaseException { -185 final Engine engine = new Engine(); -186 engine.scan(BaseTest.getResourceAsFile(this, -187 "ruby/vulnerable/gems/rails-4.1.15/")); -188 try { -189 engine.analyzeDependencies(); -190 } catch (NullPointerException ex) { -191 LOGGER.error("NPE", ex); -192 throw ex; -193 } catch (ExceptionCollection ex) { -194 Assume.assumeNoException("Exception setting up RubyBundleAuditAnalyzer; bundle audit may not be installed, or property \"analyzer.bundle.audit.path\" may not be set.", ex); -195 } -196 List<Dependency> dependencies = engine.getDependencies(); -197 LOGGER.info(dependencies.size() + " dependencies found."); -198 Iterator<Dependency> dIterator = dependencies.iterator(); -199 while (dIterator.hasNext()) { -200 Dependency dept = dIterator.next(); -201 LOGGER.info("dept path: " + dept.getActualFilePath()); -202 -203 Set<Identifier> identifiers = dept.getIdentifiers(); -204 Iterator<Identifier> idIterator = identifiers.iterator(); -205 while (idIterator.hasNext()) { -206 Identifier id = idIterator.next(); -207 LOGGER.info(" Identifier: " + id.getValue() + ", type=" + id.getType() + ", url=" + id.getUrl() + ", conf=" + id.getConfidence()); -208 } -209 -210 Set<Evidence> prodEv = dept.getProductEvidence().getEvidence(); -211 Iterator<Evidence> it = prodEv.iterator(); -212 while (it.hasNext()) { -213 Evidence e = it.next(); -214 LOGGER.info(" prod: name=" + e.getName() + ", value=" + e.getValue() + ", source=" + e.getSource() + ", confidence=" + e.getConfidence()); -215 } -216 Set<Evidence> versionEv = dept.getVersionEvidence().getEvidence(); -217 Iterator<Evidence> vIt = versionEv.iterator(); -218 while (vIt.hasNext()) { -219 Evidence e = vIt.next(); -220 LOGGER.info(" version: name=" + e.getName() + ", value=" + e.getValue() + ", source=" + e.getSource() + ", confidence=" + e.getConfidence()); -221 } -222 -223 Set<Evidence> vendorEv = dept.getVendorEvidence().getEvidence(); -224 Iterator<Evidence> vendorIt = vendorEv.iterator(); -225 while (vendorIt.hasNext()) { -226 Evidence e = vendorIt.next(); -227 LOGGER.info(" vendor: name=" + e.getName() + ", value=" + e.getValue() + ", source=" + e.getSource() + ", confidence=" + e.getConfidence()); -228 } -229 } -230 } -231 } +120 assertTrue(size >= 1); +121 +122 Dependency dependency = engine.getDependencies().get(0); +123 assertTrue(dependency.getProductEvidence().toString().toLowerCase().contains("redcarpet")); +124 assertTrue(dependency.getVersionEvidence().toString().toLowerCase().contains("2.2.2")); +125 assertTrue(dependency.getFilePath().endsWith(resource)); +126 assertTrue(dependency.getFileName().equals("Gemfile.lock")); +127 } catch (Exception e) { +128 LOGGER.warn("Exception setting up RubyBundleAuditAnalyzer. Make sure Ruby gem bundle-audit is installed. You may also need to set property \"analyzer.bundle.audit.path\"."); +129 Assume.assumeNoException("Exception setting up RubyBundleAuditAnalyzer; bundle audit may not be installed, or property \"analyzer.bundle.audit.path\" may not be set.", e); +130 } +131 } +132 +133 /** +134 * Test Ruby addCriticalityToVulnerability +135 */ +136 @Test +137 public void testAddCriticalityToVulnerability() throws AnalysisException, DatabaseException { +138 try { +139 analyzer.initialize(); +140 +141 final Dependency result = new Dependency(BaseTest.getResourceAsFile(this, +142 "ruby/vulnerable/gems/sinatra/Gemfile.lock")); +143 final Engine engine = new Engine(); +144 analyzer.analyze(result, engine); +145 +146 Dependency dependency = engine.getDependencies().get(0); +147 Vulnerability vulnerability = dependency.getVulnerabilities().first(); +148 assertEquals(vulnerability.getCvssScore(), 5.0f, 0.0); +149 +150 } catch (Exception e) { +151 LOGGER.warn("Exception setting up RubyBundleAuditAnalyzer. Make sure Ruby gem bundle-audit is installed. You may also need to set property \"analyzer.bundle.audit.path\"."); +152 Assume.assumeNoException("Exception setting up RubyBundleAuditAnalyzer; bundle audit may not be installed, or property \"analyzer.bundle.audit.path\" may not be set.", e); +153 } +154 } +155 +156 /** +157 * Test when Ruby bundle-audit is not available on the system. +158 * +159 * @throws AnalysisException is thrown when an exception occurs. +160 */ +161 @Test +162 public void testMissingBundleAudit() throws AnalysisException, DatabaseException { +163 //set a non-exist bundle-audit +164 Settings.setString(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH, "phantom-bundle-audit"); +165 try { +166 //initialize should fail. +167 analyzer.initialize(); +168 } catch (Exception e) { +169 //expected, so ignore. +170 } finally { +171 assertThat(analyzer.isEnabled(), is(false)); +172 LOGGER.info("phantom-bundle-audit is not available. Ruby Bundle Audit Analyzer is disabled as expected."); +173 } +174 } +175 +176 /** +177 * Test Ruby dependencies and their paths. +178 * +179 * @throws AnalysisException is thrown when an exception occurs. +180 * @throws DatabaseException thrown when an exception occurs +181 */ +182 @Test +183 public void testDependenciesPath() throws AnalysisException, DatabaseException { +184 final Engine engine = new Engine(); +185 engine.scan(BaseTest.getResourceAsFile(this, +186 "ruby/vulnerable/gems/rails-4.1.15/")); +187 try { +188 engine.analyzeDependencies(); +189 } catch (NullPointerException ex) { +190 LOGGER.error("NPE", ex); +191 throw ex; +192 } catch (ExceptionCollection ex) { +193 Assume.assumeNoException("Exception setting up RubyBundleAuditAnalyzer; bundle audit may not be installed, or property \"analyzer.bundle.audit.path\" may not be set.", ex); +194 } +195 List<Dependency> dependencies = engine.getDependencies(); +196 LOGGER.info(dependencies.size() + " dependencies found."); +197 Iterator<Dependency> dIterator = dependencies.iterator(); +198 while (dIterator.hasNext()) { +199 Dependency dept = dIterator.next(); +200 LOGGER.info("dept path: " + dept.getActualFilePath()); +201 +202 Set<Identifier> identifiers = dept.getIdentifiers(); +203 Iterator<Identifier> idIterator = identifiers.iterator(); +204 while (idIterator.hasNext()) { +205 Identifier id = idIterator.next(); +206 LOGGER.info(" Identifier: " + id.getValue() + ", type=" + id.getType() + ", url=" + id.getUrl() + ", conf=" + id.getConfidence()); +207 } +208 +209 Set<Evidence> prodEv = dept.getProductEvidence().getEvidence(); +210 Iterator<Evidence> it = prodEv.iterator(); +211 while (it.hasNext()) { +212 Evidence e = it.next(); +213 LOGGER.info(" prod: name=" + e.getName() + ", value=" + e.getValue() + ", source=" + e.getSource() + ", confidence=" + e.getConfidence()); +214 } +215 Set<Evidence> versionEv = dept.getVersionEvidence().getEvidence(); +216 Iterator<Evidence> vIt = versionEv.iterator(); +217 while (vIt.hasNext()) { +218 Evidence e = vIt.next(); +219 LOGGER.info(" version: name=" + e.getName() + ", value=" + e.getValue() + ", source=" + e.getSource() + ", confidence=" + e.getConfidence()); +220 } +221 +222 Set<Evidence> vendorEv = dept.getVendorEvidence().getEvidence(); +223 Iterator<Evidence> vendorIt = vendorEv.iterator(); +224 while (vendorIt.hasNext()) { +225 Evidence e = vendorIt.next(); +226 LOGGER.info(" vendor: name=" + e.getName() + ", value=" + e.getValue() + ", source=" + e.getSource() + ", confidence=" + e.getConfidence()); +227 } +228 } +229 } +230 }
    diff --git a/xref-test/org/owasp/dependencycheck/analyzer/SwiftAnalyzersTest.html b/xref-test/org/owasp/dependencycheck/analyzer/SwiftAnalyzersTest.html new file mode 100644 index 000000000..5dc465095 --- /dev/null +++ b/xref-test/org/owasp/dependencycheck/analyzer/SwiftAnalyzersTest.html @@ -0,0 +1,136 @@ + + + +SwiftAnalyzersTest xref + + + +
    View Javadoc
    +1   package org.owasp.dependencycheck.analyzer;
    +2   
    +3   import org.junit.After;
    +4   import org.junit.Before;
    +5   import org.junit.Test;
    +6   import org.owasp.dependencycheck.BaseTest;
    +7   import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
    +8   import org.owasp.dependencycheck.dependency.Dependency;
    +9   
    +10  import static org.hamcrest.CoreMatchers.containsString;
    +11  import static org.hamcrest.CoreMatchers.is;
    +12  import static org.junit.Assert.assertThat;
    +13  
    +14  import java.io.File;
    +15  
    +16  /**
    +17   * Unit tests for CocoaPodsAnalyzer.
    +18   *
    +19   * @author Bianca Jiang
    +20   */
    +21  public class SwiftAnalyzersTest extends BaseTest {
    +22  
    +23      /**
    +24       * The analyzer to test.
    +25       */
    +26  	CocoaPodsAnalyzer podsAnalyzer;
    +27  	SwiftPackageManagerAnalyzer spmAnalyzer;
    +28  
    +29      /**
    +30       * Correctly setup the analyzer for testing.
    +31       *
    +32       * @throws Exception thrown if there is a problem
    +33       */
    +34      @Before
    +35      public void setUp() throws Exception {
    +36          podsAnalyzer = new CocoaPodsAnalyzer();
    +37          podsAnalyzer.setFilesMatched(true);
    +38          podsAnalyzer.initialize();
    +39          
    +40          spmAnalyzer = new SwiftPackageManagerAnalyzer();
    +41          spmAnalyzer.setFilesMatched(true);
    +42          spmAnalyzer.initialize();
    +43      }
    +44  
    +45      /**
    +46       * Cleanup the analyzer's temp files, etc.
    +47       *
    +48       * @throws Exception thrown if there is a problem
    +49       */
    +50      @After
    +51      public void tearDown() throws Exception {
    +52          podsAnalyzer.close();
    +53          podsAnalyzer = null;
    +54  
    +55          spmAnalyzer.close();
    +56          spmAnalyzer = null;
    +57      }
    +58  
    +59      /**
    +60       * Test of getName method, of class CocoaPodsAnalyzer.
    +61       */
    +62      @Test
    +63      public void testPodsGetName() {
    +64          assertThat(podsAnalyzer.getName(), is("CocoaPods Package Analyzer"));
    +65      }
    +66  
    +67      /**
    +68       * Test of getName method, of class SwiftPackageManagerAnalyzer.
    +69       */
    +70      @Test
    +71      public void testSPMGetName() {
    +72          assertThat(spmAnalyzer.getName(), is("SWIFT Package Manager Analyzer"));
    +73      }
    +74  
    +75      /**
    +76       * Test of supportsFiles method, of class CocoaPodsAnalyzer.
    +77       */
    +78      @Test
    +79      public void testPodsSupportsFiles() {
    +80          assertThat(podsAnalyzer.accept(new File("test.podspec")), is(true));
    +81      }
    +82  
    +83      /**
    +84       * Test of supportsFiles method, of class SwiftPackageManagerAnalyzer.
    +85       */
    +86      @Test
    +87      public void testSPMSupportsFiles() {
    +88          assertThat(spmAnalyzer.accept(new File("Package.swift")), is(true));
    +89      }
    +90      
    +91      /**
    +92       * Test of analyze method, of class CocoaPodsAnalyzer.
    +93       *
    +94       * @throws AnalysisException is thrown when an exception occurs.
    +95       */
    +96      @Test
    +97      public void testCocoaPodsAnalyzer() throws AnalysisException {
    +98          final Dependency result = new Dependency(BaseTest.getResourceAsFile(this,
    +99                  "swift/cocoapods/EasyPeasy.podspec"));
    +100         podsAnalyzer.analyze(result, null);
    +101         final String vendorString = result.getVendorEvidence().toString();
    +102         
    +103         assertThat(vendorString, containsString("Carlos Vidal"));
    +104         assertThat(vendorString, containsString("https://github.com/nakiostudio/EasyPeasy"));
    +105         assertThat(vendorString, containsString("MIT"));
    +106         assertThat(result.getProductEvidence().toString(), containsString("EasyPeasy"));
    +107         assertThat(result.getVersionEvidence().toString(), containsString("0.2.3"));
    +108     }
    +109 
    +110     /**
    +111      * Test of analyze method, of class SwiftPackageManagerAnalyzer.
    +112      *
    +113      * @throws AnalysisException is thrown when an exception occurs.
    +114      */
    +115     @Test
    +116     public void testSPMAnalyzer() throws AnalysisException {
    +117         final Dependency result = new Dependency(BaseTest.getResourceAsFile(this,
    +118                 "swift/Gloss/Package.swift"));
    +119         spmAnalyzer.analyze(result, null);
    +120 
    +121         assertThat(result.getProductEvidence().toString(), containsString("Gloss"));
    +122     }
    +123 }
    +
    +
    + + + diff --git a/xref-test/org/owasp/dependencycheck/analyzer/package-frame.html b/xref-test/org/owasp/dependencycheck/analyzer/package-frame.html index 2e2d89997..1ef91a5fe 100644 --- a/xref-test/org/owasp/dependencycheck/analyzer/package-frame.html +++ b/xref-test/org/owasp/dependencycheck/analyzer/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.analyzer + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.analyzer @@ -89,6 +89,9 @@
  • RubyGemspecAnalyzerTest +
  • +
  • + SwiftAnalyzersTest
  • VulnerabilitySuppressionAnalyzerIntegrationTest diff --git a/xref-test/org/owasp/dependencycheck/analyzer/package-summary.html b/xref-test/org/owasp/dependencycheck/analyzer/package-summary.html index ea0130070..aad9a130f 100644 --- a/xref-test/org/owasp/dependencycheck/analyzer/package-summary.html +++ b/xref-test/org/owasp/dependencycheck/analyzer/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.analyzer + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.analyzer @@ -159,6 +159,11 @@ RubyGemspecAnalyzerTest + + + + SwiftAnalyzersTest + diff --git a/xref-test/org/owasp/dependencycheck/data/central/package-frame.html b/xref-test/org/owasp/dependencycheck/data/central/package-frame.html index a250635fd..ad2c562b2 100644 --- a/xref-test/org/owasp/dependencycheck/data/central/package-frame.html +++ b/xref-test/org/owasp/dependencycheck/data/central/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.data.central + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.central diff --git a/xref-test/org/owasp/dependencycheck/data/central/package-summary.html b/xref-test/org/owasp/dependencycheck/data/central/package-summary.html index 353e3789f..68f5bcd51 100644 --- a/xref-test/org/owasp/dependencycheck/data/central/package-summary.html +++ b/xref-test/org/owasp/dependencycheck/data/central/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.data.central + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.central diff --git a/xref-test/org/owasp/dependencycheck/data/composer/package-frame.html b/xref-test/org/owasp/dependencycheck/data/composer/package-frame.html index 5e4a43030..67d2476c8 100644 --- a/xref-test/org/owasp/dependencycheck/data/composer/package-frame.html +++ b/xref-test/org/owasp/dependencycheck/data/composer/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.data.composer + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.composer diff --git a/xref-test/org/owasp/dependencycheck/data/composer/package-summary.html b/xref-test/org/owasp/dependencycheck/data/composer/package-summary.html index e801768c0..8e4f4d4f5 100644 --- a/xref-test/org/owasp/dependencycheck/data/composer/package-summary.html +++ b/xref-test/org/owasp/dependencycheck/data/composer/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.data.composer + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.composer diff --git a/xref-test/org/owasp/dependencycheck/data/cpe/package-frame.html b/xref-test/org/owasp/dependencycheck/data/cpe/package-frame.html index e5f473595..6c34f8734 100644 --- a/xref-test/org/owasp/dependencycheck/data/cpe/package-frame.html +++ b/xref-test/org/owasp/dependencycheck/data/cpe/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.data.cpe + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.cpe diff --git a/xref-test/org/owasp/dependencycheck/data/cpe/package-summary.html b/xref-test/org/owasp/dependencycheck/data/cpe/package-summary.html index 7b9fa5155..b4f10ee52 100644 --- a/xref-test/org/owasp/dependencycheck/data/cpe/package-summary.html +++ b/xref-test/org/owasp/dependencycheck/data/cpe/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.data.cpe + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.cpe diff --git a/xref-test/org/owasp/dependencycheck/data/cwe/package-frame.html b/xref-test/org/owasp/dependencycheck/data/cwe/package-frame.html index 477294014..6a192e906 100644 --- a/xref-test/org/owasp/dependencycheck/data/cwe/package-frame.html +++ b/xref-test/org/owasp/dependencycheck/data/cwe/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.data.cwe + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.cwe diff --git a/xref-test/org/owasp/dependencycheck/data/cwe/package-summary.html b/xref-test/org/owasp/dependencycheck/data/cwe/package-summary.html index e86ac3a6b..2ba80aac1 100644 --- a/xref-test/org/owasp/dependencycheck/data/cwe/package-summary.html +++ b/xref-test/org/owasp/dependencycheck/data/cwe/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.data.cwe + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.cwe diff --git a/xref-test/org/owasp/dependencycheck/data/lucene/package-frame.html b/xref-test/org/owasp/dependencycheck/data/lucene/package-frame.html index 4a26dee45..ac20364e1 100644 --- a/xref-test/org/owasp/dependencycheck/data/lucene/package-frame.html +++ b/xref-test/org/owasp/dependencycheck/data/lucene/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.data.lucene + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.lucene diff --git a/xref-test/org/owasp/dependencycheck/data/lucene/package-summary.html b/xref-test/org/owasp/dependencycheck/data/lucene/package-summary.html index 10d526834..babc3d346 100644 --- a/xref-test/org/owasp/dependencycheck/data/lucene/package-summary.html +++ b/xref-test/org/owasp/dependencycheck/data/lucene/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.data.lucene + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.lucene diff --git a/xref-test/org/owasp/dependencycheck/data/nexus/package-frame.html b/xref-test/org/owasp/dependencycheck/data/nexus/package-frame.html index 29caac2d2..9d4bbaf10 100644 --- a/xref-test/org/owasp/dependencycheck/data/nexus/package-frame.html +++ b/xref-test/org/owasp/dependencycheck/data/nexus/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.data.nexus + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.nexus diff --git a/xref-test/org/owasp/dependencycheck/data/nexus/package-summary.html b/xref-test/org/owasp/dependencycheck/data/nexus/package-summary.html index 955bd1d96..029dafe68 100644 --- a/xref-test/org/owasp/dependencycheck/data/nexus/package-summary.html +++ b/xref-test/org/owasp/dependencycheck/data/nexus/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.data.nexus + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.nexus diff --git a/xref-test/org/owasp/dependencycheck/data/nuget/package-frame.html b/xref-test/org/owasp/dependencycheck/data/nuget/package-frame.html index 09b18a862..d35ee774d 100644 --- a/xref-test/org/owasp/dependencycheck/data/nuget/package-frame.html +++ b/xref-test/org/owasp/dependencycheck/data/nuget/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.data.nuget + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.nuget diff --git a/xref-test/org/owasp/dependencycheck/data/nuget/package-summary.html b/xref-test/org/owasp/dependencycheck/data/nuget/package-summary.html index a80a481e2..3ebf30bed 100644 --- a/xref-test/org/owasp/dependencycheck/data/nuget/package-summary.html +++ b/xref-test/org/owasp/dependencycheck/data/nuget/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.data.nuget + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.nuget diff --git a/xref-test/org/owasp/dependencycheck/data/nvdcve/package-frame.html b/xref-test/org/owasp/dependencycheck/data/nvdcve/package-frame.html index 20cd68e90..1d49f51f8 100644 --- a/xref-test/org/owasp/dependencycheck/data/nvdcve/package-frame.html +++ b/xref-test/org/owasp/dependencycheck/data/nvdcve/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.data.nvdcve + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.nvdcve diff --git a/xref-test/org/owasp/dependencycheck/data/nvdcve/package-summary.html b/xref-test/org/owasp/dependencycheck/data/nvdcve/package-summary.html index 2a4cd1719..4bfdd03f1 100644 --- a/xref-test/org/owasp/dependencycheck/data/nvdcve/package-summary.html +++ b/xref-test/org/owasp/dependencycheck/data/nvdcve/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.data.nvdcve + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.nvdcve diff --git a/xref-test/org/owasp/dependencycheck/data/update/NvdCveUpdaterIntegrationTest.html b/xref-test/org/owasp/dependencycheck/data/update/NvdCveUpdaterIntegrationTest.html index 2bd3a4681..f2118830d 100644 --- a/xref-test/org/owasp/dependencycheck/data/update/NvdCveUpdaterIntegrationTest.html +++ b/xref-test/org/owasp/dependencycheck/data/update/NvdCveUpdaterIntegrationTest.html @@ -37,7 +37,7 @@ 29 * 30 * @author Jeremy Long 31 */ -32 public class NvdCveUpdaterIntegrationTest extends BaseTest { +32 public class NvdCveUpdaterIntegrationTest extends BaseTest { 33 34 public NvdCveUpdater getUpdater() throws MalformedURLException, DownloadFailedException, UpdateException { 35 NvdCveUpdater instance = new NvdCveUpdater(); @@ -48,27 +48,26 @@ 40 // /** 41 // * Test of update method, of class StandardUpdate. 42 // */ -43 // @Test -44 // public void testUpdate() throws Exception { -45 // StandardUpdate instance = getStandardUpdateTask(); -46 // instance.update(); -47 // //TODO make this an actual test -48 // } -49 /** -50 * Test of updatesNeeded method, of class StandardUpdate. -51 */ -52 @Test -53 public void testUpdatesNeeded() throws Exception { -54 NvdCveUpdater instance = getUpdater(); -55 try { -56 instance.openDataStores(); -57 UpdateableNvdCve result = instance.getUpdatesNeeded(); -58 assertNotNull(result); -59 } finally { -60 instance.closeDataStores(); -61 } -62 } -63 } +43 @Test +44 public void testUpdate() throws Exception { +45 NvdCveUpdater instance = getUpdater(); +46 instance.update(); +47 } +48 /** +49 * Test of updatesNeeded method, of class StandardUpdate. +50 */ +51 @Test +52 public void testUpdatesNeeded() throws Exception { +53 NvdCveUpdater instance = getUpdater(); +54 try { +55 instance.openDataStores(); +56 UpdateableNvdCve result = instance.getUpdatesNeeded(); +57 assertNotNull(result); +58 } finally { +59 instance.closeDataStores(); +60 } +61 } +62 }
    diff --git a/xref-test/org/owasp/dependencycheck/data/update/nvd/package-frame.html b/xref-test/org/owasp/dependencycheck/data/update/nvd/package-frame.html index 951954371..63de46dcf 100644 --- a/xref-test/org/owasp/dependencycheck/data/update/nvd/package-frame.html +++ b/xref-test/org/owasp/dependencycheck/data/update/nvd/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.data.update.nvd + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.update.nvd @@ -20,9 +20,6 @@
  • NvdCveInfoTest -
  • -
  • - NvdCveUpdaterIntegrationTest
  • NvdCve_1_2_HandlerTest diff --git a/xref-test/org/owasp/dependencycheck/data/update/nvd/package-summary.html b/xref-test/org/owasp/dependencycheck/data/update/nvd/package-summary.html index 06d04306a..73920c22b 100644 --- a/xref-test/org/owasp/dependencycheck/data/update/nvd/package-summary.html +++ b/xref-test/org/owasp/dependencycheck/data/update/nvd/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.data.update.nvd + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.update.nvd @@ -44,11 +44,6 @@ NvdCveInfoTest - - - - NvdCveUpdaterIntegrationTest - diff --git a/xref-test/org/owasp/dependencycheck/data/update/package-frame.html b/xref-test/org/owasp/dependencycheck/data/update/package-frame.html index 80fa232d4..54cd7d325 100644 --- a/xref-test/org/owasp/dependencycheck/data/update/package-frame.html +++ b/xref-test/org/owasp/dependencycheck/data/update/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.data.update + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.update diff --git a/xref-test/org/owasp/dependencycheck/data/update/package-summary.html b/xref-test/org/owasp/dependencycheck/data/update/package-summary.html index f93a1af20..743e282d1 100644 --- a/xref-test/org/owasp/dependencycheck/data/update/package-summary.html +++ b/xref-test/org/owasp/dependencycheck/data/update/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.data.update + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.update diff --git a/xref-test/org/owasp/dependencycheck/dependency/package-frame.html b/xref-test/org/owasp/dependencycheck/dependency/package-frame.html index c27612c4a..e8881bc0e 100644 --- a/xref-test/org/owasp/dependencycheck/dependency/package-frame.html +++ b/xref-test/org/owasp/dependencycheck/dependency/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.dependency + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.dependency diff --git a/xref-test/org/owasp/dependencycheck/dependency/package-summary.html b/xref-test/org/owasp/dependencycheck/dependency/package-summary.html index 3bc4f2eca..db770a0df 100644 --- a/xref-test/org/owasp/dependencycheck/dependency/package-summary.html +++ b/xref-test/org/owasp/dependencycheck/dependency/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.dependency + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.dependency diff --git a/xref-test/org/owasp/dependencycheck/maven/BaseDependencyCheckMojoTest.html b/xref-test/org/owasp/dependencycheck/maven/BaseDependencyCheckMojoTest.html index 031c21559..69004172c 100644 --- a/xref-test/org/owasp/dependencycheck/maven/BaseDependencyCheckMojoTest.html +++ b/xref-test/org/owasp/dependencycheck/maven/BaseDependencyCheckMojoTest.html @@ -41,97 +41,102 @@ 33 import org.apache.maven.project.MavenProject; 34 import static org.junit.Assert.assertFalse; 35 import static org.junit.Assert.assertTrue; -36 import org.junit.Test; -37 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; -38 import org.owasp.dependencycheck.utils.InvalidSettingException; -39 import org.owasp.dependencycheck.utils.Settings; -40 -41 /** -42 * -43 * @author Jeremy Long -44 */ -45 public class BaseDependencyCheckMojoTest extends BaseTest { -46 -47 /** -48 * Checks if the test can be run. The test in this class fail, presumable due to jmockit, if the JDK is 1.8+. -49 * -50 * @return true if the JDK is below 1.8. -51 */ -52 public boolean canRun() { -53 String version = System.getProperty("java.version"); -54 int length = version.indexOf('.', version.indexOf('.') + 1); -55 version = version.substring(0, length); -56 -57 double v = Double.parseDouble(version); -58 return v == 1.7; -59 } -60 -61 /** -62 * Test of scanArtifacts method, of class BaseDependencyCheckMojo. -63 */ -64 @Test -65 public void testScanArtifacts() throws DatabaseException, InvalidSettingException { -66 //TODO get this to work under JDK 1.8 -67 if (canRun()) { -68 MavenProject project = new MockUp<MavenProject>() { -69 @Mock -70 public Set<Artifact> getArtifacts() { -71 Set<Artifact> artifacts = new HashSet<Artifact>(); -72 Artifact a = new ArtifactStub(); -73 try { -74 File file = new File(Test.class.getProtectionDomain().getCodeSource().getLocation().toURI()); -75 a.setFile(file); -76 artifacts.add(a); -77 } catch (URISyntaxException ex) { -78 Logger.getLogger(BaseDependencyCheckMojoTest.class.getName()).log(Level.SEVERE, null, ex); -79 } -80 //File file = new File(this.getClass().getClassLoader().getResource("daytrader-ear-2.1.7.ear").getPath()); -81 -82 return artifacts; -83 } -84 -85 @Mock -86 public String getName() { -87 return "test-project"; -88 } -89 }.getMockInstance(); -90 -91 boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE); -92 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false); -93 MavenEngine engine = new MavenEngine(null, null); -94 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate); -95 -96 assertTrue(engine.getDependencies().isEmpty()); -97 BaseDependencyCheckMojoImpl instance = new BaseDependencyCheckMojoImpl(); -98 instance.scanArtifacts(project, engine); -99 assertFalse(engine.getDependencies().isEmpty()); -100 engine.cleanup(); -101 } -102 } -103 -104 public class BaseDependencyCheckMojoImpl extends BaseDependencyCheckMojo { -105 -106 @Override -107 public void runCheck() throws MojoExecutionException, MojoFailureException { -108 throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. -109 } +36 import org.junit.Assume; +37 import org.junit.Test; +38 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; +39 import org.owasp.dependencycheck.utils.InvalidSettingException; +40 import org.owasp.dependencycheck.utils.Settings; +41 +42 /** +43 * +44 * @author Jeremy Long +45 */ +46 public class BaseDependencyCheckMojoTest extends BaseTest { +47 +48 /** +49 * Checks if the test can be run. The test in this class fail, presumable +50 * due to jmockit, if the JDK is 1.8+. +51 * +52 * @return true if the JDK is below 1.8. +53 */ +54 public boolean canRun() { +55 String version = System.getProperty("java.version"); +56 int length = version.indexOf('.', version.indexOf('.') + 1); +57 version = version.substring(0, length); +58 +59 double v = Double.parseDouble(version); +60 return v == 1.7; +61 } +62 +63 /** +64 * Test of scanArtifacts method, of class BaseDependencyCheckMojo. +65 */ +66 @Test +67 public void testScanArtifacts() throws DatabaseException, InvalidSettingException { +68 if (canRun()) { +69 MavenProject project = new MockUp<MavenProject>() { +70 @Mock +71 public Set<Artifact> getArtifacts() { +72 Set<Artifact> artifacts = new HashSet<Artifact>(); +73 Artifact a = new ArtifactStub(); +74 try { +75 File file = new File(Test.class.getProtectionDomain().getCodeSource().getLocation().toURI()); +76 a.setFile(file); +77 artifacts.add(a); +78 } catch (URISyntaxException ex) { +79 Logger.getLogger(BaseDependencyCheckMojoTest.class.getName()).log(Level.SEVERE, null, ex); +80 } +81 //File file = new File(this.getClass().getClassLoader().getResource("daytrader-ear-2.1.7.ear").getPath()); +82 +83 return artifacts; +84 } +85 +86 @Mock +87 public String getName() { +88 return "test-project"; +89 } +90 }.getMockInstance(); +91 +92 boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE); +93 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false); +94 MavenEngine engine = new MavenEngine(null, null); +95 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate); +96 +97 assertTrue(engine.getDependencies().isEmpty()); +98 BaseDependencyCheckMojoImpl instance = new BaseDependencyCheckMojoImpl(); +99 try { //the mock above fails under some JDKs +100 instance.scanArtifacts(project, engine); +101 } catch (NullPointerException ex) { +102 Assume.assumeNoException(ex); +103 } +104 assertFalse(engine.getDependencies().isEmpty()); +105 engine.cleanup(); +106 } +107 } +108 +109 public class BaseDependencyCheckMojoImpl extends BaseDependencyCheckMojo { 110 111 @Override -112 public String getName(Locale locale) { -113 return "test implementation"; +112 public void runCheck() throws MojoExecutionException, MojoFailureException { +113 throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. 114 } 115 116 @Override -117 public String getDescription(Locale locale) { +117 public String getName(Locale locale) { 118 return "test implementation"; 119 } 120 121 @Override -122 public boolean canGenerateReport() { -123 throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. +122 public String getDescription(Locale locale) { +123 return "test implementation"; 124 } -125 } -126 } +125 +126 @Override +127 public boolean canGenerateReport() { +128 throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. +129 } +130 } +131 }
    diff --git a/xref-test/org/owasp/dependencycheck/maven/BaseTest.html b/xref-test/org/owasp/dependencycheck/maven/BaseTest.html index cdd88e00e..09927913c 100644 --- a/xref-test/org/owasp/dependencycheck/maven/BaseTest.html +++ b/xref-test/org/owasp/dependencycheck/maven/BaseTest.html @@ -25,34 +25,49 @@ 17 */ 18 package org.owasp.dependencycheck.maven; 19 -20 import java.io.InputStream; -21 import org.junit.AfterClass; -22 import org.junit.BeforeClass; -23 import org.owasp.dependencycheck.utils.Settings; -24 -25 /** -26 * -27 * @author Jeremy Long -28 */ -29 public class BaseTest { -30 -31 /** -32 * The properties file location. -33 */ -34 public static final String PROPERTIES_FILE = "mojo.properties"; -35 -36 @BeforeClass -37 public static void setUpClass() throws Exception { -38 Settings.initialize(); -39 InputStream mojoProperties = BaseTest.class.getClassLoader().getResourceAsStream(BaseTest.PROPERTIES_FILE); -40 Settings.mergeProperties(mojoProperties); -41 } -42 -43 @AfterClass -44 public static void tearDownClass() throws Exception { -45 Settings.cleanup(true); -46 } -47 } +20 import java.io.IOException; +21 import java.io.InputStream; +22 import java.util.logging.Level; +23 import java.util.logging.Logger; +24 import org.junit.AfterClass; +25 import org.junit.BeforeClass; +26 import org.owasp.dependencycheck.utils.Settings; +27 +28 /** +29 * +30 * @author Jeremy Long +31 */ +32 public class BaseTest { +33 +34 /** +35 * The properties file location. +36 */ +37 public static final String PROPERTIES_FILE = "mojo.properties"; +38 +39 @BeforeClass +40 public static void setUpClass() throws Exception { +41 Settings.initialize(); +42 InputStream mojoProperties = null; +43 try { +44 mojoProperties = BaseTest.class.getClassLoader().getResourceAsStream(BaseTest.PROPERTIES_FILE); +45 Settings.mergeProperties(mojoProperties); +46 } finally { +47 if (mojoProperties != null) { +48 try { +49 mojoProperties.close(); +50 } catch (IOException ex) { +51 Logger.getLogger(BaseTest.class.getName()).log(Level.SEVERE, null, ex); +52 } +53 } +54 } +55 +56 } +57 +58 @AfterClass +59 public static void tearDownClass() throws Exception { +60 Settings.cleanup(true); +61 } +62 }
    diff --git a/xref-test/org/owasp/dependencycheck/maven/package-frame.html b/xref-test/org/owasp/dependencycheck/maven/package-frame.html index 10d07b058..bbe0af75d 100644 --- a/xref-test/org/owasp/dependencycheck/maven/package-frame.html +++ b/xref-test/org/owasp/dependencycheck/maven/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.maven + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.maven diff --git a/xref-test/org/owasp/dependencycheck/maven/package-summary.html b/xref-test/org/owasp/dependencycheck/maven/package-summary.html index 757e9c400..69aa26474 100644 --- a/xref-test/org/owasp/dependencycheck/maven/package-summary.html +++ b/xref-test/org/owasp/dependencycheck/maven/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.maven + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.maven diff --git a/xref-test/org/owasp/dependencycheck/package-frame.html b/xref-test/org/owasp/dependencycheck/package-frame.html index 23acb85bf..7bda2632b 100644 --- a/xref-test/org/owasp/dependencycheck/package-frame.html +++ b/xref-test/org/owasp/dependencycheck/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck diff --git a/xref-test/org/owasp/dependencycheck/package-summary.html b/xref-test/org/owasp/dependencycheck/package-summary.html index 52fe8c7c1..7c3af5702 100644 --- a/xref-test/org/owasp/dependencycheck/package-summary.html +++ b/xref-test/org/owasp/dependencycheck/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck diff --git a/xref-test/org/owasp/dependencycheck/reporting/package-frame.html b/xref-test/org/owasp/dependencycheck/reporting/package-frame.html index 594144a52..3c5339d85 100644 --- a/xref-test/org/owasp/dependencycheck/reporting/package-frame.html +++ b/xref-test/org/owasp/dependencycheck/reporting/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.reporting + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.reporting diff --git a/xref-test/org/owasp/dependencycheck/reporting/package-summary.html b/xref-test/org/owasp/dependencycheck/reporting/package-summary.html index 68a7e7527..7a32fa47c 100644 --- a/xref-test/org/owasp/dependencycheck/reporting/package-summary.html +++ b/xref-test/org/owasp/dependencycheck/reporting/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.reporting + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.reporting diff --git a/xref-test/org/owasp/dependencycheck/taskdefs/package-frame.html b/xref-test/org/owasp/dependencycheck/taskdefs/package-frame.html index bd8a2bb7a..58502f52d 100644 --- a/xref-test/org/owasp/dependencycheck/taskdefs/package-frame.html +++ b/xref-test/org/owasp/dependencycheck/taskdefs/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.taskdefs + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.taskdefs diff --git a/xref-test/org/owasp/dependencycheck/taskdefs/package-summary.html b/xref-test/org/owasp/dependencycheck/taskdefs/package-summary.html index 067193d51..ae1ac30bc 100644 --- a/xref-test/org/owasp/dependencycheck/taskdefs/package-summary.html +++ b/xref-test/org/owasp/dependencycheck/taskdefs/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.taskdefs + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.taskdefs diff --git a/xref-test/org/owasp/dependencycheck/utils/package-frame.html b/xref-test/org/owasp/dependencycheck/utils/package-frame.html index bb0d2f2f2..381b72925 100644 --- a/xref-test/org/owasp/dependencycheck/utils/package-frame.html +++ b/xref-test/org/owasp/dependencycheck/utils/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.utils + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.utils diff --git a/xref-test/org/owasp/dependencycheck/utils/package-summary.html b/xref-test/org/owasp/dependencycheck/utils/package-summary.html index 98c97914c..359cdccc7 100644 --- a/xref-test/org/owasp/dependencycheck/utils/package-summary.html +++ b/xref-test/org/owasp/dependencycheck/utils/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.utils + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.utils diff --git a/xref-test/org/owasp/dependencycheck/xml/hints/HintHandlerTest.html b/xref-test/org/owasp/dependencycheck/xml/hints/HintHandlerTest.html index 24a30c1b7..eb87a5d9a 100644 --- a/xref-test/org/owasp/dependencycheck/xml/hints/HintHandlerTest.html +++ b/xref-test/org/owasp/dependencycheck/xml/hints/HintHandlerTest.html @@ -60,7 +60,7 @@ 52 @Test 53 public void testHandler() throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException, SAXException, FileNotFoundException, UnsupportedEncodingException, IOException { 54 File file = BaseTest.getResourceAsFile(this, "hints.xml"); -55 File schema = BaseTest.getResourceAsFile(this, "schema/dependency-hint.1.0.xsd"); +55 File schema = BaseTest.getResourceAsFile(this, "schema/dependency-hint.1.1.xsd"); 56 HintHandler handler = new HintHandler(); 57 58 SAXParserFactory factory = SAXParserFactory.newInstance(); diff --git a/xref-test/org/owasp/dependencycheck/xml/hints/package-frame.html b/xref-test/org/owasp/dependencycheck/xml/hints/package-frame.html index b618ed212..ed9b7b63e 100644 --- a/xref-test/org/owasp/dependencycheck/xml/hints/package-frame.html +++ b/xref-test/org/owasp/dependencycheck/xml/hints/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.xml.hints + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.xml.hints diff --git a/xref-test/org/owasp/dependencycheck/xml/hints/package-summary.html b/xref-test/org/owasp/dependencycheck/xml/hints/package-summary.html index 0ef33de38..b1d75ba98 100644 --- a/xref-test/org/owasp/dependencycheck/xml/hints/package-summary.html +++ b/xref-test/org/owasp/dependencycheck/xml/hints/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.xml.hints + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.xml.hints diff --git a/xref-test/org/owasp/dependencycheck/xml/pom/package-frame.html b/xref-test/org/owasp/dependencycheck/xml/pom/package-frame.html index 7c5eeaa7c..975a75357 100644 --- a/xref-test/org/owasp/dependencycheck/xml/pom/package-frame.html +++ b/xref-test/org/owasp/dependencycheck/xml/pom/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.xml.pom + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.xml.pom diff --git a/xref-test/org/owasp/dependencycheck/xml/pom/package-summary.html b/xref-test/org/owasp/dependencycheck/xml/pom/package-summary.html index f943fc539..2565ca721 100644 --- a/xref-test/org/owasp/dependencycheck/xml/pom/package-summary.html +++ b/xref-test/org/owasp/dependencycheck/xml/pom/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.xml.pom + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.xml.pom diff --git a/xref-test/org/owasp/dependencycheck/xml/suppression/package-frame.html b/xref-test/org/owasp/dependencycheck/xml/suppression/package-frame.html index 14dc21be0..eae23623a 100644 --- a/xref-test/org/owasp/dependencycheck/xml/suppression/package-frame.html +++ b/xref-test/org/owasp/dependencycheck/xml/suppression/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.xml.suppression + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.xml.suppression diff --git a/xref-test/org/owasp/dependencycheck/xml/suppression/package-summary.html b/xref-test/org/owasp/dependencycheck/xml/suppression/package-summary.html index 3159a7f72..f32de78d8 100644 --- a/xref-test/org/owasp/dependencycheck/xml/suppression/package-summary.html +++ b/xref-test/org/owasp/dependencycheck/xml/suppression/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.xml.suppression + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.xml.suppression diff --git a/xref-test/overview-frame.html b/xref-test/overview-frame.html index 28ecf9fe3..2cf6ed547 100644 --- a/xref-test/overview-frame.html +++ b/xref-test/overview-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference + Dependency-Check 1.4.3 Reference diff --git a/xref-test/overview-summary.html b/xref-test/overview-summary.html index 1fc69ec90..c2e5d8aef 100644 --- a/xref-test/overview-summary.html +++ b/xref-test/overview-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference + Dependency-Check 1.4.3 Reference @@ -24,7 +24,7 @@ -

    Dependency-Check 1.4.2 Reference

    +

    Dependency-Check 1.4.3 Reference

    diff --git a/xref/allclasses-frame.html b/xref/allclasses-frame.html index 25644da9f..7d0ad7978 100644 --- a/xref/allclasses-frame.html +++ b/xref/allclasses-frame.html @@ -103,6 +103,9 @@
  • CliParser +
  • +
  • + CocoaPodsAnalyzer
  • ComposerDependency @@ -460,6 +463,9 @@
  • SuppressionRule +
  • +
  • + SwiftPackageManagerAnalyzer
  • TokenPairConcatenatingFilter diff --git a/xref/index.html b/xref/index.html index e5cd82e24..b705ec2b8 100644 --- a/xref/index.html +++ b/xref/index.html @@ -4,7 +4,7 @@ - Dependency-Check 1.4.2 Reference + Dependency-Check 1.4.3 Reference diff --git a/xref/org/owasp/dependencycheck/App.html b/xref/org/owasp/dependencycheck/App.html index 216acd54d..03aba4333 100644 --- a/xref/org/owasp/dependencycheck/App.html +++ b/xref/org/owasp/dependencycheck/App.html @@ -166,364 +166,369 @@ 158 exitCode = -4; 159 } 160 try { -161 runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getProjectName(), cli.getScanFiles(), -162 cli.getExcludeList(), cli.getSymLinkDepth()); -163 } catch (InvalidScanPathException ex) { -164 LOGGER.error("An invalid scan path was detected; unable to scan '//*' paths"); -165 exitCode = -10; -166 } catch (DatabaseException ex) { -167 LOGGER.error(ex.getMessage()); -168 exitCode = -11; -169 } catch (ReportException ex) { -170 LOGGER.error(ex.getMessage()); -171 exitCode = -12; -172 } catch (ExceptionCollection ex) { -173 if (ex.isFatal()) { -174 exitCode = -13; -175 LOGGER.error("One or more fatal errors occured"); -176 } else { -177 exitCode = -14; -178 } -179 for (Throwable e : ex.getExceptions()) { -180 LOGGER.error(e.getMessage()); -181 } -182 } -183 } else { -184 cli.printHelp(); -185 } -186 return exitCode; -187 } -188 -189 /** -190 * Scans the specified directories and writes the dependency reports to the -191 * reportDirectory. -192 * -193 * @param reportDirectory the path to the directory where the reports will -194 * be written -195 * @param outputFormat the output format of the report -196 * @param applicationName the application name for the report -197 * @param files the files/directories to scan -198 * @param excludes the patterns for files/directories to exclude -199 * @param symLinkDepth the depth that symbolic links will be followed -200 * -201 * @throws InvalidScanPathException thrown if the path to scan starts with -202 * "//" -203 * @throws ReportException thrown when the report cannot be generated -204 * @throws DatabaseException thrown when there is an error connecting to the -205 * database -206 * @throws ExceptionCollection thrown when an exception occurs during -207 * analysis; there may be multiple exceptions contained within the -208 * collection. -209 */ -210 private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files, -211 String[] excludes, int symLinkDepth) throws InvalidScanPathException, DatabaseException, ExceptionCollection, ReportException { -212 Engine engine = null; -213 try { -214 engine = new Engine(); -215 final List<String> antStylePaths = new ArrayList<String>(); -216 for (String file : files) { -217 final String antPath = ensureCanonicalPath(file); -218 antStylePaths.add(antPath); -219 } -220 -221 final Set<File> paths = new HashSet<File>(); -222 for (String file : antStylePaths) { -223 LOGGER.debug("Scanning {}", file); -224 final DirectoryScanner scanner = new DirectoryScanner(); -225 String include = file.replace('\\', '/'); -226 File baseDir; -227 -228 if (include.startsWith("//")) { -229 throw new InvalidScanPathException("Unable to scan paths specified by //"); -230 } else { -231 final int pos = getLastFileSeparator(include); -232 final String tmpBase = include.substring(0, pos); -233 final String tmpInclude = include.substring(pos + 1); -234 if (tmpInclude.indexOf('*') >= 0 || tmpInclude.indexOf('?') >= 0 -235 || (new File(include)).isFile()) { -236 baseDir = new File(tmpBase); -237 include = tmpInclude; -238 } else { -239 baseDir = new File(tmpBase, tmpInclude); -240 include = "**/*"; -241 } -242 } -243 scanner.setBasedir(baseDir); -244 final String[] includes = {include}; -245 scanner.setIncludes(includes); -246 scanner.setMaxLevelsOfSymlinks(symLinkDepth); -247 if (symLinkDepth <= 0) { -248 scanner.setFollowSymlinks(false); -249 } -250 if (excludes != null && excludes.length > 0) { -251 scanner.addExcludes(excludes); -252 } -253 scanner.scan(); -254 if (scanner.getIncludedFilesCount() > 0) { -255 for (String s : scanner.getIncludedFiles()) { -256 final File f = new File(baseDir, s); -257 LOGGER.debug("Found file {}", f.toString()); -258 paths.add(f); -259 } -260 } -261 } -262 engine.scan(paths); -263 -264 ExceptionCollection exCol = null; -265 try { -266 engine.analyzeDependencies(); -267 } catch (ExceptionCollection ex) { -268 if (ex.isFatal()) { -269 throw ex; -270 } -271 exCol = ex; -272 } -273 final List<Dependency> dependencies = engine.getDependencies(); -274 DatabaseProperties prop = null; -275 CveDB cve = null; -276 try { -277 cve = new CveDB(); -278 cve.open(); -279 prop = cve.getDatabaseProperties(); -280 } finally { -281 if (cve != null) { -282 cve.close(); -283 } -284 } -285 final ReportGenerator report = new ReportGenerator(applicationName, dependencies, engine.getAnalyzers(), prop); -286 try { -287 report.generateReports(reportDirectory, outputFormat); -288 } catch (ReportException ex) { -289 if (exCol != null) { -290 exCol.addException(ex); -291 throw exCol; -292 } else { -293 throw ex; -294 } -295 } -296 if (exCol != null && exCol.getExceptions().size()>0) { -297 throw exCol; -298 } -299 } finally { -300 if (engine != null) { -301 engine.cleanup(); -302 } -303 } -304 -305 } -306 -307 /** -308 * Only executes the update phase of dependency-check. -309 * -310 * @throws UpdateException thrown if there is an error updating -311 * @throws DatabaseException thrown if a fatal error occurred and a -312 * connection to the database could not be established -313 */ -314 private void runUpdateOnly() throws UpdateException, DatabaseException { -315 Engine engine = null; -316 try { -317 engine = new Engine(); -318 engine.doUpdates(); -319 } finally { -320 if (engine != null) { -321 engine.cleanup(); -322 } -323 } -324 } -325 -326 /** -327 * Updates the global Settings. -328 * -329 * @param cli a reference to the CLI Parser that contains the command line -330 * arguments used to set the corresponding settings in the core engine. -331 * -332 * @throws InvalidSettingException thrown when a user defined properties -333 * file is unable to be loaded. -334 */ -335 private void populateSettings(CliParser cli) throws InvalidSettingException { -336 final boolean autoUpdate = cli.isAutoUpdate(); -337 final String connectionTimeout = cli.getConnectionTimeout(); -338 final String proxyServer = cli.getProxyServer(); -339 final String proxyPort = cli.getProxyPort(); -340 final String proxyUser = cli.getProxyUsername(); -341 final String proxyPass = cli.getProxyPassword(); -342 final String dataDirectory = cli.getDataDirectory(); -343 final File propertiesFile = cli.getPropertiesFile(); -344 final String suppressionFile = cli.getSuppressionFile(); -345 final String nexusUrl = cli.getNexusUrl(); -346 final String databaseDriverName = cli.getDatabaseDriverName(); -347 final String databaseDriverPath = cli.getDatabaseDriverPath(); -348 final String connectionString = cli.getConnectionString(); -349 final String databaseUser = cli.getDatabaseUser(); -350 final String databasePassword = cli.getDatabasePassword(); -351 final String additionalZipExtensions = cli.getAdditionalZipExtensions(); -352 final String pathToMono = cli.getPathToMono(); -353 final String cveMod12 = cli.getModifiedCve12Url(); -354 final String cveMod20 = cli.getModifiedCve20Url(); -355 final String cveBase12 = cli.getBaseCve12Url(); -356 final String cveBase20 = cli.getBaseCve20Url(); -357 final Integer cveValidForHours = cli.getCveValidForHours(); -358 final boolean experimentalEnabled = cli.isExperimentalEnabled(); -359 -360 if (propertiesFile != null) { -361 try { -362 Settings.mergeProperties(propertiesFile); -363 } catch (FileNotFoundException ex) { -364 throw new InvalidSettingException("Unable to find properties file '" + propertiesFile.getPath() + "'", ex); -365 } catch (IOException ex) { -366 throw new InvalidSettingException("Error reading properties file '" + propertiesFile.getPath() + "'", ex); -367 } -368 } -369 // We have to wait until we've merged the properties before attempting to set whether we use -370 // the proxy for Nexus since it could be disabled in the properties, but not explicitly stated -371 // on the command line -372 final boolean nexusUsesProxy = cli.isNexusUsesProxy(); -373 if (dataDirectory != null) { -374 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory); -375 } else if (System.getProperty("basedir") != null) { -376 final File dataDir = new File(System.getProperty("basedir"), "data"); -377 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath()); -378 } else { -379 final File jarPath = new File(App.class.getProtectionDomain().getCodeSource().getLocation().getPath()); -380 final File base = jarPath.getParentFile(); -381 final String sub = Settings.getString(Settings.KEYS.DATA_DIRECTORY); -382 final File dataDir = new File(base, sub); -383 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath()); -384 } -385 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate); -386 Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_SERVER, proxyServer); -387 Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PORT, proxyPort); -388 Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_USERNAME, proxyUser); -389 Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PASSWORD, proxyPass); -390 Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout); -391 Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); -392 Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours); -393 -394 //File Type Analyzer Settings -395 Settings.setBoolean(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, experimentalEnabled); -396 Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, !cli.isJarDisabled()); -397 Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, !cli.isArchiveDisabled()); -398 Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, !cli.isPythonDistributionDisabled()); -399 Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, !cli.isPythonPackageDisabled()); -400 Settings.setBoolean(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, !cli.isAutoconfDisabled()); -401 Settings.setBoolean(Settings.KEYS.ANALYZER_CMAKE_ENABLED, !cli.isCmakeDisabled()); -402 Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, !cli.isNuspecDisabled()); -403 Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, !cli.isAssemblyDisabled()); -404 Settings.setBoolean(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED, !cli.isBundleAuditDisabled()); -405 Settings.setBoolean(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, !cli.isOpenSSLDisabled()); -406 Settings.setBoolean(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, !cli.isComposerDisabled()); -407 Settings.setBoolean(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, !cli.isNodeJsDisabled()); -408 Settings.setBoolean(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, !cli.isRubyGemspecDisabled()); -409 Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, !cli.isCentralDisabled()); -410 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, !cli.isNexusDisabled()); -411 -412 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH, cli.getPathToBundleAudit()); -413 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); -414 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy); -415 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName); -416 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath); -417 Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString); -418 Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser); -419 Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword); -420 Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, additionalZipExtensions); -421 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); -422 if (cveBase12 != null && !cveBase12.isEmpty()) { -423 Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, cveBase12); -424 Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, cveBase20); -425 Settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, cveMod12); -426 Settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, cveMod20); -427 } -428 } -429 -430 /** -431 * Creates a file appender and adds it to logback. -432 * -433 * @param verboseLog the path to the verbose log file -434 */ -435 private void prepareLogger(String verboseLog) { -436 final StaticLoggerBinder loggerBinder = StaticLoggerBinder.getSingleton(); -437 final LoggerContext context = (LoggerContext) loggerBinder.getLoggerFactory(); -438 -439 final PatternLayoutEncoder encoder = new PatternLayoutEncoder(); -440 encoder.setPattern("%d %C:%L%n%-5level - %msg%n"); -441 encoder.setContext(context); -442 encoder.start(); -443 final FileAppender fa = new FileAppender(); -444 fa.setAppend(true); -445 fa.setEncoder(encoder); -446 fa.setContext(context); -447 fa.setFile(verboseLog); -448 final File f = new File(verboseLog); -449 String name = f.getName(); -450 final int i = name.lastIndexOf('.'); -451 if (i > 1) { -452 name = name.substring(0, i); -453 } -454 fa.setName(name); -455 fa.start(); -456 final ch.qos.logback.classic.Logger rootLogger = context.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME); -457 rootLogger.addAppender(fa); -458 } -459 -460 /** -461 * Takes a path and resolves it to be a canonical &amp; absolute path. The -462 * caveats are that this method will take an Ant style file selector path -463 * (../someDir/**\/*.jar) and convert it to an absolute/canonical path (at -464 * least to the left of the first * or ?). -465 * -466 * @param path the path to canonicalize -467 * @return the canonical path -468 */ -469 protected String ensureCanonicalPath(String path) { -470 String basePath; -471 String wildCards = null; -472 final String file = path.replace('\\', '/'); -473 if (file.contains("*") || file.contains("?")) { -474 -475 int pos = getLastFileSeparator(file); -476 if (pos < 0) { -477 return file; -478 } -479 pos += 1; -480 basePath = file.substring(0, pos); -481 wildCards = file.substring(pos); -482 } else { -483 basePath = file; -484 } -485 -486 File f = new File(basePath); -487 try { -488 f = f.getCanonicalFile(); -489 if (wildCards != null) { -490 f = new File(f, wildCards); -491 } -492 } catch (IOException ex) { -493 LOGGER.warn("Invalid path '{}' was provided.", path); -494 LOGGER.debug("Invalid path provided", ex); -495 } -496 return f.getAbsolutePath().replace('\\', '/'); -497 } -498 -499 /** -500 * Returns the position of the last file separator. -501 * -502 * @param file a file path -503 * @return the position of the last file separator -504 */ -505 private int getLastFileSeparator(String file) { -506 if (file.contains("*") || file.contains("?")) { -507 int p1 = file.indexOf('*'); -508 int p2 = file.indexOf('?'); -509 p1 = p1 > 0 ? p1 : file.length(); -510 p2 = p2 > 0 ? p2 : file.length(); -511 int pos = p1 < p2 ? p1 : p2; -512 pos = file.lastIndexOf('/', pos); -513 return pos; -514 } else { -515 return file.lastIndexOf('/'); -516 } -517 } -518 } +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 }
    diff --git a/xref/org/owasp/dependencycheck/CliParser.html b/xref/org/owasp/dependencycheck/CliParser.html index 3305f4a91..133d1cec5 100644 --- a/xref/org/owasp/dependencycheck/CliParser.html +++ b/xref/org/owasp/dependencycheck/CliParser.html @@ -204,1197 +204,1201 @@ 196 isValid = false; 197 final String msg = String.format("Invalid '%s' argument: '%s'%nUnable to scan paths that start with '//'.", argumentName, path); 198 throw new FileNotFoundException(msg); -199 } -200 } -201 -202 /** -203 * Generates an Options collection that is used to parse the command line -204 * and to display the help message. -205 * -206 * @return the command line options used for parsing the command line -207 */ -208 @SuppressWarnings("static-access") -209 private Options createCommandLineOptions() { -210 final Options options = new Options(); -211 addStandardOptions(options); -212 addAdvancedOptions(options); -213 addDeprecatedOptions(options); -214 return options; -215 } -216 -217 /** -218 * Adds the standard command line options to the given options collection. -219 * -220 * @param options a collection of command line arguments -221 * @throws IllegalArgumentException thrown if there is an exception -222 */ -223 @SuppressWarnings("static-access") -224 private void addStandardOptions(final Options options) throws IllegalArgumentException { -225 final Option help = new Option(ARGUMENT.HELP_SHORT, ARGUMENT.HELP, false, -226 "Print this message."); -227 -228 final Option advancedHelp = Option.builder().longOpt(ARGUMENT.ADVANCED_HELP) -229 .desc("Print the advanced help message.").build(); -230 -231 final Option version = new Option(ARGUMENT.VERSION_SHORT, ARGUMENT.VERSION, -232 false, "Print the version information."); -233 -234 final Option noUpdate = new Option(ARGUMENT.DISABLE_AUTO_UPDATE_SHORT, ARGUMENT.DISABLE_AUTO_UPDATE, -235 false, "Disables the automatic updating of the CPE data."); -236 -237 final Option projectName = Option.builder().hasArg().argName("name").longOpt(ARGUMENT.PROJECT) -238 .desc("The name of the project being scanned. This is a required argument.") -239 .build(); +199 } else if ((path.endsWith("/*") && !path.endsWith("**/*")) || (path.endsWith("\\*") && path.endsWith("**\\*"))) { +200 final String msg = String.format("Possibly incorrect path '%s' from argument '%s' because it ends with a slash star; " +201 + "dependency-check uses ant-style paths", path, argumentName); +202 LOGGER.warn(msg); +203 } +204 } +205 +206 /** +207 * Generates an Options collection that is used to parse the command line +208 * and to display the help message. +209 * +210 * @return the command line options used for parsing the command line +211 */ +212 @SuppressWarnings("static-access") +213 private Options createCommandLineOptions() { +214 final Options options = new Options(); +215 addStandardOptions(options); +216 addAdvancedOptions(options); +217 addDeprecatedOptions(options); +218 return options; +219 } +220 +221 /** +222 * Adds the standard command line options to the given options collection. +223 * +224 * @param options a collection of command line arguments +225 * @throws IllegalArgumentException thrown if there is an exception +226 */ +227 @SuppressWarnings("static-access") +228 private void addStandardOptions(final Options options) throws IllegalArgumentException { +229 final Option help = new Option(ARGUMENT.HELP_SHORT, ARGUMENT.HELP, false, +230 "Print this message."); +231 +232 final Option advancedHelp = Option.builder().longOpt(ARGUMENT.ADVANCED_HELP) +233 .desc("Print the advanced help message.").build(); +234 +235 final Option version = new Option(ARGUMENT.VERSION_SHORT, ARGUMENT.VERSION, +236 false, "Print the version information."); +237 +238 final Option noUpdate = new Option(ARGUMENT.DISABLE_AUTO_UPDATE_SHORT, ARGUMENT.DISABLE_AUTO_UPDATE, +239 false, "Disables the automatic updating of the CPE data."); 240 -241 final Option path = Option.builder(ARGUMENT.SCAN_SHORT).argName("path").hasArg().longOpt(ARGUMENT.SCAN) -242 .desc("The path to scan - this option can be specified multiple times. Ant style" -243 + " paths are supported (e.g. path/**/*.jar).") -244 .build(); -245 -246 final Option excludes = Option.builder().argName("pattern").hasArg().longOpt(ARGUMENT.EXCLUDE) -247 .desc("Specify and exclusion pattern. This option can be specified multiple times" -248 + " and it accepts Ant style excludsions.") -249 .build(); -250 -251 final Option props = Option.builder(ARGUMENT.PROP_SHORT).argName("file").hasArg().longOpt(ARGUMENT.PROP) -252 .desc("A property file to load.") +241 final Option projectName = Option.builder().hasArg().argName("name").longOpt(ARGUMENT.PROJECT) +242 .desc("The name of the project being scanned. This is a required argument.") +243 .build(); +244 +245 final Option path = Option.builder(ARGUMENT.SCAN_SHORT).argName("path").hasArg().longOpt(ARGUMENT.SCAN) +246 .desc("The path to scan - this option can be specified multiple times. Ant style" +247 + " paths are supported (e.g. path/**/*.jar).") +248 .build(); +249 +250 final Option excludes = Option.builder().argName("pattern").hasArg().longOpt(ARGUMENT.EXCLUDE) +251 .desc("Specify and exclusion pattern. This option can be specified multiple times" +252 + " and it accepts Ant style excludsions.") 253 .build(); 254 -255 final Option out = Option.builder(ARGUMENT.OUT_SHORT).argName("path").hasArg().longOpt(ARGUMENT.OUT) -256 .desc("The folder to write reports to. This defaults to the current directory. " -257 + "It is possible to set this to a specific file name if the format argument is not set to ALL.") -258 .build(); -259 -260 final Option outputFormat = Option.builder(ARGUMENT.OUTPUT_FORMAT_SHORT).argName("format").hasArg().longOpt(ARGUMENT.OUTPUT_FORMAT) -261 .desc("The output format to write to (XML, HTML, VULN, ALL). The default is HTML.") +255 final Option props = Option.builder(ARGUMENT.PROP_SHORT).argName("file").hasArg().longOpt(ARGUMENT.PROP) +256 .desc("A property file to load.") +257 .build(); +258 +259 final Option out = Option.builder(ARGUMENT.OUT_SHORT).argName("path").hasArg().longOpt(ARGUMENT.OUT) +260 .desc("The folder to write reports to. This defaults to the current directory. " +261 + "It is possible to set this to a specific file name if the format argument is not set to ALL.") 262 .build(); 263 -264 final Option verboseLog = Option.builder(ARGUMENT.VERBOSE_LOG_SHORT).argName("file").hasArg().longOpt(ARGUMENT.VERBOSE_LOG) -265 .desc("The file path to write verbose logging information.") +264 final Option outputFormat = Option.builder(ARGUMENT.OUTPUT_FORMAT_SHORT).argName("format").hasArg().longOpt(ARGUMENT.OUTPUT_FORMAT) +265 .desc("The output format to write to (XML, HTML, VULN, ALL). The default is HTML.") 266 .build(); 267 -268 final Option symLinkDepth = Option.builder().argName("depth").hasArg().longOpt(ARGUMENT.SYM_LINK_DEPTH) -269 .desc("Sets how deep nested symbolic links will be followed; 0 indicates symbolic links will not be followed.") +268 final Option verboseLog = Option.builder(ARGUMENT.VERBOSE_LOG_SHORT).argName("file").hasArg().longOpt(ARGUMENT.VERBOSE_LOG) +269 .desc("The file path to write verbose logging information.") 270 .build(); 271 -272 final Option suppressionFile = Option.builder().argName("file").hasArg().longOpt(ARGUMENT.SUPPRESSION_FILE) -273 .desc("The file path to the suppression XML file.") +272 final Option symLinkDepth = Option.builder().argName("depth").hasArg().longOpt(ARGUMENT.SYM_LINK_DEPTH) +273 .desc("Sets how deep nested symbolic links will be followed; 0 indicates symbolic links will not be followed.") 274 .build(); 275 -276 final Option cveValidForHours = Option.builder().argName("hours").hasArg().longOpt(ARGUMENT.CVE_VALID_FOR_HOURS) -277 .desc("The number of hours to wait before checking for new updates from the NVD.") +276 final Option suppressionFile = Option.builder().argName("file").hasArg().longOpt(ARGUMENT.SUPPRESSION_FILE) +277 .desc("The file path to the suppression XML file.") 278 .build(); 279 -280 final Option experimentalEnabled = Option.builder().longOpt(ARGUMENT.EXPERIMENTAL) -281 .desc("Enables the experimental analzers.") +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.") 282 .build(); 283 -284 //This is an option group because it can be specified more then once. -285 final OptionGroup og = new OptionGroup(); -286 og.addOption(path); +284 final Option experimentalEnabled = Option.builder().longOpt(ARGUMENT.EXPERIMENTAL) +285 .desc("Enables the experimental analzers.") +286 .build(); 287 -288 final OptionGroup exog = new OptionGroup(); -289 exog.addOption(excludes); -290 -291 options.addOptionGroup(og) -292 .addOptionGroup(exog) -293 .addOption(projectName) -294 .addOption(out) -295 .addOption(outputFormat) -296 .addOption(version) -297 .addOption(help) -298 .addOption(advancedHelp) -299 .addOption(noUpdate) -300 .addOption(symLinkDepth) -301 .addOption(props) -302 .addOption(verboseLog) -303 .addOption(suppressionFile) -304 .addOption(cveValidForHours) -305 .addOption(experimentalEnabled); -306 } -307 -308 /** -309 * Adds the advanced command line options to the given options collection. -310 * These are split out for purposes of being able to display two different -311 * help messages. -312 * -313 * @param options a collection of command line arguments -314 * @throws IllegalArgumentException thrown if there is an exception -315 */ -316 @SuppressWarnings("static-access") -317 private void addAdvancedOptions(final Options options) throws IllegalArgumentException { -318 -319 final Option cve12Base = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_BASE_12) -320 .desc("Base URL for each year’s CVE 1.2, the %d will be replaced with the year. ") -321 .build(); +288 //This is an option group because it can be specified more then once. +289 final OptionGroup og = new OptionGroup(); +290 og.addOption(path); +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 cve20Base = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_BASE_20) -324 .desc("Base URL for each year’s CVE 2.0, the %d will be replaced with the year.") +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 cve12Modified = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_MOD_12) -328 .desc("URL for the modified CVE 1.2.") +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 cve20Modified = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_MOD_20) -332 .desc("URL for the modified CVE 2.0.") +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 updateOnly = Option.builder().longOpt(ARGUMENT.UPDATE_ONLY) -336 .desc("Only update the local NVD data cache; no scan will be executed.").build(); -337 -338 final Option data = Option.builder(ARGUMENT.DATA_DIRECTORY_SHORT).argName("path").hasArg().longOpt(ARGUMENT.DATA_DIRECTORY) -339 .desc("The location of the H2 Database file. This option should generally not be set.") -340 .build(); +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 nexusUrl = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.NEXUS_URL) -343 .desc("The url to the Nexus Server's REST API Endpoint (http://domain/nexus/service/local). " -344 + "If not set the Nexus Analyzer will be disabled.").build(); +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 nexusUsesProxy = Option.builder().argName("true/false").hasArg().longOpt(ARGUMENT.NEXUS_USES_PROXY) -347 .desc("Whether or not the configured proxy should be used when connecting to Nexus.") -348 .build(); +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 additionalZipExtensions = Option.builder().argName("extensions").hasArg() -351 .longOpt(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS) -352 .desc("A comma separated list of additional extensions to be scanned as ZIP files " -353 + "(ZIP, EAR, WAR are already treated as zip files)").build(); -354 -355 final Option pathToMono = Option.builder().argName("path").hasArg().longOpt(ARGUMENT.PATH_TO_MONO) -356 .desc("The path to Mono for .NET Assembly analysis on non-windows systems.") -357 .build(); +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(); 358 -359 final Option pathToBundleAudit = Option.builder().argName("path").hasArg() -360 .longOpt(ARGUMENT.PATH_TO_BUNDLE_AUDIT) -361 .desc("The path to bundle-audit for Gem bundle analysis.").build(); +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 connectionTimeout = Option.builder(ARGUMENT.CONNECTION_TIMEOUT_SHORT).argName("timeout").hasArg() -364 .longOpt(ARGUMENT.CONNECTION_TIMEOUT).desc("The connection timeout (in milliseconds) to use when downloading resources.") -365 .build(); +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 proxyServer = Option.builder().argName("server").hasArg().longOpt(ARGUMENT.PROXY_SERVER) -368 .desc("The proxy server to use when downloading resources.").build(); -369 -370 final Option proxyPort = Option.builder().argName("port").hasArg().longOpt(ARGUMENT.PROXY_PORT) -371 .desc("The proxy port to use when downloading resources.").build(); -372 -373 final Option proxyUsername = Option.builder().argName("user").hasArg().longOpt(ARGUMENT.PROXY_USERNAME) -374 .desc("The proxy username to use when downloading resources.").build(); -375 -376 final Option proxyPassword = Option.builder().argName("pass").hasArg().longOpt(ARGUMENT.PROXY_PASSWORD) -377 .desc("The proxy password to use when downloading resources.").build(); -378 -379 final Option connectionString = Option.builder().argName("connStr").hasArg().longOpt(ARGUMENT.CONNECTION_STRING) -380 .desc("The connection string to the database.").build(); -381 -382 final Option dbUser = Option.builder().argName("user").hasArg().longOpt(ARGUMENT.DB_NAME) -383 .desc("The username used to connect to the database.").build(); -384 -385 final Option dbPassword = Option.builder().argName("password").hasArg().longOpt(ARGUMENT.DB_PASSWORD) -386 .desc("The password for connecting to the database.").build(); -387 -388 final Option dbDriver = Option.builder().argName("driver").hasArg().longOpt(ARGUMENT.DB_DRIVER) -389 .desc("The database driver name.").build(); -390 -391 final Option dbDriverPath = Option.builder().argName("path").hasArg().longOpt(ARGUMENT.DB_DRIVER_PATH) -392 .desc("The path to the database driver; note, this does not need to be set unless the JAR is outside of the classpath.") -393 .build(); +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 disableJarAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_JAR) -396 .desc("Disable the Jar Analyzer.").build(); -397 -398 final Option disableArchiveAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_ARCHIVE) -399 .desc("Disable the Archive Analyzer.").build(); -400 -401 final Option disableNuspecAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_NUSPEC) -402 .desc("Disable the Nuspec Analyzer.").build(); -403 -404 final Option disableAssemblyAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_ASSEMBLY) -405 .desc("Disable the .NET Assembly Analyzer.").build(); -406 -407 final Option disablePythonDistributionAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_PY_DIST) -408 .desc("Disable the Python Distribution Analyzer.").build(); -409 -410 final Option disablePythonPackageAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_PY_PKG) -411 .desc("Disable the Python Package Analyzer.").build(); -412 -413 final Option disableComposerAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_COMPOSER) -414 .desc("Disable the PHP Composer Analyzer.").build(); -415 -416 final Option disableAutoconfAnalyzer = Option.builder() -417 .longOpt(ARGUMENT.DISABLE_AUTOCONF) -418 .desc("Disable the Autoconf Analyzer.").build(); +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 disableOpenSSLAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_OPENSSL) -421 .desc("Disable the OpenSSL Analyzer.").build(); -422 final Option disableCmakeAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_CMAKE) -423 .desc("Disable the Cmake Analyzer.").build(); -424 -425 final Option disableCentralAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_CENTRAL) -426 .desc("Disable the Central Analyzer. If this analyzer is disabled it is likely you also want to disable " -427 + "the Nexus Analyzer.").build(); +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(); 428 -429 final Option disableNexusAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_NEXUS) -430 .desc("Disable the Nexus Analyzer.").build(); -431 -432 final Option purge = Option.builder().longOpt(ARGUMENT.PURGE_NVD) -433 .desc("Purges the local NVD data cache") -434 .build(); +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 options.addOption(updateOnly) -437 .addOption(cve12Base) -438 .addOption(cve20Base) -439 .addOption(cve12Modified) -440 .addOption(cve20Modified) -441 .addOption(proxyPort) -442 .addOption(proxyServer) -443 .addOption(proxyUsername) -444 .addOption(proxyPassword) -445 .addOption(connectionTimeout) -446 .addOption(connectionString) -447 .addOption(dbUser) -448 .addOption(data) -449 .addOption(dbPassword) -450 .addOption(dbDriver) -451 .addOption(dbDriverPath) -452 .addOption(disableJarAnalyzer) -453 .addOption(disableArchiveAnalyzer) -454 .addOption(disableAssemblyAnalyzer) -455 .addOption(pathToBundleAudit) -456 .addOption(disablePythonDistributionAnalyzer) -457 .addOption(disableCmakeAnalyzer) -458 .addOption(disablePythonPackageAnalyzer) -459 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_RUBYGEMS) -460 .desc("Disable the Ruby Gemspec Analyzer.").build()) -461 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_BUNDLE_AUDIT) -462 .desc("Disable the Ruby Bundler-Audit Analyzer.").build()) -463 .addOption(disableAutoconfAnalyzer) -464 .addOption(disableComposerAnalyzer) -465 .addOption(disableOpenSSLAnalyzer) -466 .addOption(disableNuspecAnalyzer) -467 .addOption(disableCentralAnalyzer) -468 .addOption(disableNexusAnalyzer) -469 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_NODE_JS) -470 .desc("Disable the Node.js Package Analyzer.").build()) -471 .addOption(nexusUrl) -472 .addOption(nexusUsesProxy) -473 .addOption(additionalZipExtensions) -474 .addOption(pathToMono) -475 .addOption(pathToBundleAudit) -476 .addOption(purge); -477 } -478 -479 /** -480 * Adds the deprecated command line options to the given options collection. -481 * These are split out for purposes of not including them in the help -482 * message. We need to add the deprecated options so as not to break -483 * existing scripts. -484 * -485 * @param options a collection of command line arguments -486 * @throws IllegalArgumentException thrown if there is an exception -487 */ -488 @SuppressWarnings({"static-access", "deprecation"}) -489 private void addDeprecatedOptions(final Options options) throws IllegalArgumentException { -490 -491 final Option proxyServer = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.PROXY_URL) -492 .desc("The proxy url argument is deprecated, use proxyserver instead.") -493 .build(); -494 final Option appName = Option.builder(ARGUMENT.APP_NAME_SHORT).argName("name").hasArg().longOpt(ARGUMENT.APP_NAME) -495 .desc("The name of the project being scanned.") -496 .build(); -497 -498 options.addOption(proxyServer); -499 options.addOption(appName); -500 } +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 /** -503 * Determines if the 'version' command line argument was passed in. -504 * -505 * @return whether or not the 'version' command line argument was passed in -506 */ -507 public boolean isGetVersion() { -508 return (line != null) && line.hasOption(ARGUMENT.VERSION); -509 } -510 -511 /** -512 * Determines if the 'help' command line argument was passed in. -513 * -514 * @return whether or not the 'help' command line argument was passed in -515 */ -516 public boolean isGetHelp() { -517 return (line != null) && line.hasOption(ARGUMENT.HELP); -518 } -519 -520 /** -521 * Determines if the 'scan' command line argument was passed in. -522 * -523 * @return whether or not the 'scan' command line argument was passed in -524 */ -525 public boolean isRunScan() { -526 return (line != null) && isValid && line.hasOption(ARGUMENT.SCAN); -527 } -528 -529 /** -530 * Returns the symbolic link depth (how deeply symbolic links will be -531 * followed). -532 * -533 * @return the symbolic link depth -534 */ -535 public int getSymLinkDepth() { -536 int value = 0; -537 try { -538 value = Integer.parseInt(line.getOptionValue(ARGUMENT.SYM_LINK_DEPTH, "0")); -539 if (value < 0) { -540 value = 0; -541 } -542 } catch (NumberFormatException ex) { -543 LOGGER.debug("Symbolic link was not a number"); -544 } -545 return value; -546 } -547 -548 /** -549 * Returns true if the disableJar command line argument was specified. -550 * -551 * @return true if the disableJar command line argument was specified; -552 * otherwise false -553 */ -554 public boolean isJarDisabled() { -555 return (line != null) && line.hasOption(ARGUMENT.DISABLE_JAR); -556 } -557 -558 /** -559 * Returns true if the disableArchive command line argument was specified. -560 * -561 * @return true if the disableArchive command line argument was specified; -562 * otherwise false -563 */ -564 public boolean isArchiveDisabled() { -565 return (line != null) && line.hasOption(ARGUMENT.DISABLE_ARCHIVE); -566 } -567 -568 /** -569 * Returns true if the disableNuspec command line argument was specified. -570 * -571 * @return true if the disableNuspec command line argument was specified; -572 * otherwise false -573 */ -574 public boolean isNuspecDisabled() { -575 return (line != null) && line.hasOption(ARGUMENT.DISABLE_NUSPEC); -576 } -577 -578 /** -579 * Returns true if the disableAssembly command line argument was specified. -580 * -581 * @return true if the disableAssembly command line argument was specified; -582 * otherwise false -583 */ -584 public boolean isAssemblyDisabled() { -585 return (line != null) && line.hasOption(ARGUMENT.DISABLE_ASSEMBLY); -586 } -587 -588 /** -589 * Returns true if the disableBundleAudit command line argument was -590 * specified. -591 * -592 * @return true if the disableBundleAudit command line argument was -593 * specified; otherwise false -594 */ -595 public boolean isBundleAuditDisabled() { -596 return (line != null) && line.hasOption(ARGUMENT.DISABLE_BUNDLE_AUDIT); -597 } -598 -599 /** -600 * Returns true if the disablePyDist command line argument was specified. -601 * -602 * @return true if the disablePyDist command line argument was specified; -603 * otherwise false -604 */ -605 public boolean isPythonDistributionDisabled() { -606 return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_DIST); -607 } -608 -609 /** -610 * Returns true if the disablePyPkg command line argument was specified. -611 * -612 * @return true if the disablePyPkg command line argument was specified; -613 * otherwise false -614 */ -615 public boolean isPythonPackageDisabled() { -616 return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_PKG); -617 } -618 -619 /** -620 * Returns whether the Ruby gemspec analyzer is disabled. -621 * -622 * @return true if the {@link ARGUMENT#DISABLE_RUBYGEMS} command line -623 * argument was specified; otherwise false -624 */ -625 public boolean isRubyGemspecDisabled() { -626 return (null != line) && line.hasOption(ARGUMENT.DISABLE_RUBYGEMS); -627 } -628 -629 /** -630 * Returns true if the disableCmake command line argument was specified. -631 * -632 * @return true if the disableCmake command line argument was specified; -633 * otherwise false -634 */ -635 public boolean isCmakeDisabled() { -636 return (line != null) && line.hasOption(ARGUMENT.DISABLE_CMAKE); -637 } -638 -639 /** -640 * Returns true if the disableAutoconf command line argument was specified. -641 * -642 * @return true if the disableAutoconf command line argument was specified; -643 * otherwise false -644 */ -645 public boolean isAutoconfDisabled() { -646 return (line != null) && line.hasOption(ARGUMENT.DISABLE_AUTOCONF); -647 } -648 -649 /** -650 * Returns true if the disableComposer command line argument was specified. -651 * -652 * @return true if the disableComposer command line argument was specified; -653 * otherwise false -654 */ -655 public boolean isComposerDisabled() { -656 return (line != null) && line.hasOption(ARGUMENT.DISABLE_COMPOSER); -657 } -658 -659 /** -660 * Returns true if the disableNexus command line argument was specified. -661 * -662 * @return true if the disableNexus command line argument was specified; -663 * otherwise false -664 */ -665 public boolean isNexusDisabled() { -666 return (line != null) && line.hasOption(ARGUMENT.DISABLE_NEXUS); -667 } -668 -669 /** -670 * Returns true if the disableOpenSSL command line argument was specified. -671 * -672 * @return true if the disableOpenSSL command line argument was specified; -673 * otherwise false -674 */ -675 public boolean isOpenSSLDisabled() { -676 return (line != null) && line.hasOption(ARGUMENT.DISABLE_OPENSSL); -677 } -678 -679 /** -680 * Returns true if the disableNodeJS command line argument was specified. -681 * -682 * @return true if the disableNodeJS command line argument was specified; -683 * otherwise false -684 */ -685 public boolean isNodeJsDisabled() { -686 return (line != null) && line.hasOption(ARGUMENT.DISABLE_NODE_JS); -687 } -688 -689 /** -690 * Returns true if the disableCentral command line argument was specified. -691 * -692 * @return true if the disableCentral command line argument was specified; -693 * otherwise false -694 */ -695 public boolean isCentralDisabled() { -696 return (line != null) && line.hasOption(ARGUMENT.DISABLE_CENTRAL); -697 } -698 -699 /** -700 * Returns the url to the nexus server if one was specified. -701 * -702 * @return the url to the nexus server; if none was specified this will -703 * return null; -704 */ -705 public String getNexusUrl() { -706 if (line == null || !line.hasOption(ARGUMENT.NEXUS_URL)) { -707 return null; -708 } else { -709 return line.getOptionValue(ARGUMENT.NEXUS_URL); -710 } -711 } -712 -713 /** -714 * Returns true if the Nexus Analyzer should use the configured proxy to -715 * connect to Nexus; otherwise false is returned. -716 * -717 * @return true if the Nexus Analyzer should use the configured proxy to -718 * connect to Nexus; otherwise false -719 */ -720 public boolean isNexusUsesProxy() { -721 // If they didn't specify whether Nexus needs to use the proxy, we should -722 // still honor the property if it's set. -723 if (line == null || !line.hasOption(ARGUMENT.NEXUS_USES_PROXY)) { -724 try { -725 return Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY); -726 } catch (InvalidSettingException ise) { -727 return true; -728 } -729 } else { -730 return Boolean.parseBoolean(line.getOptionValue(ARGUMENT.NEXUS_USES_PROXY)); -731 } -732 } -733 -734 /** -735 * Displays the command line help message to the standard output. -736 */ -737 public void printHelp() { -738 final HelpFormatter formatter = new HelpFormatter(); -739 final Options options = new Options(); -740 addStandardOptions(options); -741 if (line != null && line.hasOption(ARGUMENT.ADVANCED_HELP)) { -742 addAdvancedOptions(options); -743 } -744 final String helpMsg = String.format("%n%s" -745 + " can be used to identify if there are any known CVE vulnerabilities in libraries utilized by an application. " -746 + "%s will automatically update required data from the Internet, such as the CVE and CPE data files from nvd.nist.gov.%n%n", -747 Settings.getString("application.name", "DependencyCheck"), -748 Settings.getString("application.name", "DependencyCheck")); -749 -750 formatter.printHelp(Settings.getString("application.name", "DependencyCheck"), -751 helpMsg, -752 options, -753 "", -754 true); -755 } -756 -757 /** -758 * Retrieves the file command line parameter(s) specified for the 'scan' -759 * argument. -760 * -761 * @return the file paths specified on the command line for scan -762 */ -763 public String[] getScanFiles() { -764 return line.getOptionValues(ARGUMENT.SCAN); -765 } -766 -767 /** -768 * Retrieves the list of excluded file patterns specified by the 'exclude' -769 * argument. -770 * -771 * @return the excluded file patterns -772 */ -773 public String[] getExcludeList() { -774 return line.getOptionValues(ARGUMENT.EXCLUDE); -775 } -776 -777 /** -778 * Returns the directory to write the reports to specified on the command -779 * line. -780 * -781 * @return the path to the reports directory. -782 */ -783 public String getReportDirectory() { -784 return line.getOptionValue(ARGUMENT.OUT, "."); -785 } -786 -787 /** -788 * Returns the path to Mono for .NET Assembly analysis on non-windows -789 * systems. -790 * -791 * @return the path to Mono -792 */ -793 public String getPathToMono() { -794 return line.getOptionValue(ARGUMENT.PATH_TO_MONO); -795 } -796 -797 /** -798 * Returns the path to bundle-audit for Ruby bundle analysis. -799 * -800 * @return the path to Mono -801 */ -802 public String getPathToBundleAudit() { -803 return line.getOptionValue(ARGUMENT.PATH_TO_BUNDLE_AUDIT); -804 } -805 -806 /** -807 * Returns the output format specified on the command line. Defaults to HTML -808 * if no format was specified. -809 * -810 * @return the output format name. -811 */ -812 public String getReportFormat() { -813 return line.getOptionValue(ARGUMENT.OUTPUT_FORMAT, "HTML"); -814 } -815 -816 /** -817 * Returns the application name specified on the command line. -818 * -819 * @return the application name. -820 */ -821 public String getProjectName() { -822 final String appName = line.getOptionValue(ARGUMENT.APP_NAME); -823 String name = line.getOptionValue(ARGUMENT.PROJECT); -824 if (name == null && appName != null) { -825 name = appName; -826 LOGGER.warn("The '" + ARGUMENT.APP_NAME + "' argument should no longer be used; use '" + ARGUMENT.PROJECT + "' instead."); -827 } -828 return name; -829 } -830 -831 /** -832 * Returns the base URL for the CVE 1.2 XMl file. -833 * -834 * @return the URL to the CVE 1.2 XML file. -835 */ -836 public String getBaseCve12Url() { -837 return line.getOptionValue(ARGUMENT.CVE_BASE_12); -838 } -839 -840 /** -841 * Returns the base URL for the CVE 2.0 XMl file. -842 * -843 * @return the URL to the CVE 2.0 XML file. -844 */ -845 public String getBaseCve20Url() { -846 return line.getOptionValue(ARGUMENT.CVE_BASE_20); -847 } -848 -849 /** -850 * Returns the URL for the modified CVE 1.2 XMl file. -851 * -852 * @return the URL to the modified CVE 1.2 XML file. -853 */ -854 public String getModifiedCve12Url() { -855 return line.getOptionValue(ARGUMENT.CVE_MOD_12); -856 } -857 -858 /** -859 * Returns the URL for the modified CVE 2.0 XMl file. -860 * -861 * @return the URL to the modified CVE 2.0 XML file. -862 */ -863 public String getModifiedCve20Url() { -864 return line.getOptionValue(ARGUMENT.CVE_MOD_20); -865 } -866 -867 /** -868 * Returns the connection timeout. -869 * -870 * @return the connection timeout -871 */ -872 public String getConnectionTimeout() { -873 return line.getOptionValue(ARGUMENT.CONNECTION_TIMEOUT); -874 } -875 -876 /** -877 * Returns the proxy server. -878 * -879 * @return the proxy server -880 */ -881 @SuppressWarnings("deprecation") -882 public String getProxyServer() { -883 -884 String server = line.getOptionValue(ARGUMENT.PROXY_SERVER); -885 if (server == null) { -886 server = line.getOptionValue(ARGUMENT.PROXY_URL); -887 if (server != null) { -888 LOGGER.warn("An old command line argument 'proxyurl' was detected; use proxyserver instead"); -889 } -890 } -891 return server; -892 } -893 -894 /** -895 * Returns the proxy port. -896 * -897 * @return the proxy port -898 */ -899 public String getProxyPort() { -900 return line.getOptionValue(ARGUMENT.PROXY_PORT); -901 } -902 -903 /** -904 * Returns the proxy username. -905 * -906 * @return the proxy username -907 */ -908 public String getProxyUsername() { -909 return line.getOptionValue(ARGUMENT.PROXY_USERNAME); -910 } -911 -912 /** -913 * Returns the proxy password. -914 * -915 * @return the proxy password -916 */ -917 public String getProxyPassword() { -918 return line.getOptionValue(ARGUMENT.PROXY_PASSWORD); -919 } -920 -921 /** -922 * Get the value of dataDirectory. -923 * -924 * @return the value of dataDirectory -925 */ -926 public String getDataDirectory() { -927 return line.getOptionValue(ARGUMENT.DATA_DIRECTORY); -928 } -929 -930 /** -931 * Returns the properties file specified on the command line. -932 * -933 * @return the properties file specified on the command line -934 */ -935 public File getPropertiesFile() { -936 final String path = line.getOptionValue(ARGUMENT.PROP); -937 if (path != null) { -938 return new File(path); -939 } -940 return null; -941 } -942 -943 /** -944 * Returns the path to the verbose log file. -945 * -946 * @return the path to the verbose log file -947 */ -948 public String getVerboseLog() { -949 return line.getOptionValue(ARGUMENT.VERBOSE_LOG); -950 } -951 -952 /** -953 * Returns the path to the suppression file. -954 * -955 * @return the path to the suppression file -956 */ -957 public String getSuppressionFile() { -958 return line.getOptionValue(ARGUMENT.SUPPRESSION_FILE); -959 } -960 -961 /** -962 * <p> -963 * Prints the manifest information to standard output.</p> -964 * <ul><li>Implementation-Title: ${pom.name}</li> -965 * <li>Implementation-Version: ${pom.version}</li></ul> -966 */ -967 public void printVersionInfo() { -968 final String version = String.format("%s version %s", -969 Settings.getString(Settings.KEYS.APPLICATION_VAME, "dependency-check"), -970 Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown")); -971 System.out.println(version); -972 } -973 -974 /** -975 * Checks if the auto update feature has been disabled. If it has been -976 * disabled via the command line this will return false. -977 * -978 * @return <code>true</code> if auto-update is allowed; otherwise -979 * <code>false</code> -980 */ -981 public boolean isAutoUpdate() { -982 return line != null && !line.hasOption(ARGUMENT.DISABLE_AUTO_UPDATE); -983 } -984 -985 /** -986 * Checks if the update only flag has been set. -987 * -988 * @return <code>true</code> if the update only flag has been set; otherwise -989 * <code>false</code>. -990 */ -991 public boolean isUpdateOnly() { -992 return line != null && line.hasOption(ARGUMENT.UPDATE_ONLY); -993 } -994 -995 /** -996 * Checks if the purge NVD flag has been set. -997 * -998 * @return <code>true</code> if the purge nvd flag has been set; otherwise -999 * <code>false</code>. -1000 */ -1001 public boolean isPurge() { -1002 return line != null && line.hasOption(ARGUMENT.PURGE_NVD); -1003 } -1004 -1005 /** -1006 * Returns the database driver name if specified; otherwise null is -1007 * returned. -1008 * -1009 * @return the database driver name if specified; otherwise null is returned -1010 */ -1011 public String getDatabaseDriverName() { -1012 return line.getOptionValue(ARGUMENT.DB_DRIVER); -1013 } -1014 -1015 /** -1016 * Returns the database driver path if specified; otherwise null is -1017 * returned. -1018 * -1019 * @return the database driver name if specified; otherwise null is returned -1020 */ -1021 public String getDatabaseDriverPath() { -1022 return line.getOptionValue(ARGUMENT.DB_DRIVER_PATH); -1023 } -1024 -1025 /** -1026 * Returns the database connection string if specified; otherwise null is -1027 * returned. -1028 * -1029 * @return the database connection string if specified; otherwise null is -1030 * returned -1031 */ -1032 public String getConnectionString() { -1033 return line.getOptionValue(ARGUMENT.CONNECTION_STRING); -1034 } -1035 -1036 /** -1037 * Returns the database database user name if specified; otherwise null is -1038 * returned. -1039 * -1040 * @return the database database user name if specified; otherwise null is -1041 * returned -1042 */ -1043 public String getDatabaseUser() { -1044 return line.getOptionValue(ARGUMENT.DB_NAME); -1045 } -1046 -1047 /** -1048 * Returns the database database password if specified; otherwise null is -1049 * returned. -1050 * -1051 * @return the database database password if specified; otherwise null is -1052 * returned -1053 */ -1054 public String getDatabasePassword() { -1055 return line.getOptionValue(ARGUMENT.DB_PASSWORD); -1056 } -1057 -1058 /** -1059 * Returns the additional Extensions if specified; otherwise null is -1060 * returned. -1061 * -1062 * @return the additional Extensions; otherwise null is returned -1063 */ -1064 public String getAdditionalZipExtensions() { -1065 return line.getOptionValue(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS); -1066 } -1067 -1068 /** -1069 * Get the value of cveValidForHours. -1070 * -1071 * @return the value of cveValidForHours -1072 */ -1073 public Integer getCveValidForHours() { -1074 final String v = line.getOptionValue(ARGUMENT.CVE_VALID_FOR_HOURS); -1075 if (v != null) { -1076 return Integer.parseInt(v); -1077 } -1078 return null; -1079 } -1080 -1081 /** -1082 * Returns true if the experimental analyzers are enabled. -1083 * -1084 * @return true if the experimental analyzers are enabled; otherwise false -1085 */ -1086 public boolean isExperimentalEnabled() { -1087 return line.hasOption(ARGUMENT.EXPERIMENTAL); -1088 } -1089 -1090 /** -1091 * A collection of static final strings that represent the possible command -1092 * line arguments. -1093 */ -1094 public static class ARGUMENT { -1095 -1096 /** -1097 * The long CLI argument name specifying the directory/file to scan. -1098 */ -1099 public static final String SCAN = "scan"; +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> +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 short CLI argument name specifying the directory/file to scan. +1101 * The long CLI argument name specifying the directory/file to scan. 1102 */ -1103 public static final String SCAN_SHORT = "s"; +1103 public static final String SCAN = "scan"; 1104 /** -1105 * The long CLI argument name specifying that the CPE/CVE/etc. data -1106 * should not be automatically updated. -1107 */ -1108 public static final String DISABLE_AUTO_UPDATE = "noupdate"; -1109 /** -1110 * The short CLI argument name specifying that the CPE/CVE/etc. data -1111 * should not be automatically updated. -1112 */ -1113 public static final String DISABLE_AUTO_UPDATE_SHORT = "n"; -1114 /** -1115 * The long CLI argument name specifying that only the update phase -1116 * should be executed; no scan should be run. -1117 */ -1118 public static final String UPDATE_ONLY = "updateonly"; -1119 /** -1120 * The long CLI argument name specifying that only the update phase -1121 * should be executed; no scan should be run. -1122 */ -1123 public static final String PURGE_NVD = "purge"; -1124 /** -1125 * The long CLI argument name specifying the directory to write the -1126 * reports to. -1127 */ -1128 public static final String OUT = "out"; -1129 /** -1130 * The short CLI argument name specifying the directory to write the -1131 * reports to. -1132 */ -1133 public static final String OUT_SHORT = "o"; -1134 /** -1135 * The long CLI argument name specifying the output format to write the -1136 * reports to. -1137 */ -1138 public static final String OUTPUT_FORMAT = "format"; -1139 /** -1140 * The short CLI argument name specifying the output format to write the -1141 * reports to. -1142 */ -1143 public static final String OUTPUT_FORMAT_SHORT = "f"; -1144 /** -1145 * The long CLI argument name specifying the name of the project to be -1146 * scanned. -1147 */ -1148 public static final String PROJECT = "project"; -1149 /** -1150 * The long CLI argument name specifying the name of the application to -1151 * be scanned. -1152 * -1153 * @deprecated project should be used instead -1154 */ -1155 @Deprecated -1156 public static final String APP_NAME = "app"; -1157 /** -1158 * The short CLI argument name specifying the name of the application to -1159 * be scanned. -1160 * -1161 * @deprecated project should be used instead -1162 */ -1163 @Deprecated -1164 public static final String APP_NAME_SHORT = "a"; -1165 /** -1166 * The long CLI argument name asking for help. -1167 */ -1168 public static final String HELP = "help"; +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. +1116 */ +1117 public static final String DISABLE_AUTO_UPDATE_SHORT = "n"; +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 advanced help. +1170 * The long CLI argument name asking for help. 1171 */ -1172 public static final String ADVANCED_HELP = "advancedHelp"; +1172 public static final String HELP = "help"; 1173 /** -1174 * The short CLI argument name asking for help. +1174 * The long CLI argument name asking for advanced help. 1175 */ -1176 public static final String HELP_SHORT = "h"; +1176 public static final String ADVANCED_HELP = "advancedHelp"; 1177 /** -1178 * The long CLI argument name asking for the version. +1178 * The short CLI argument name asking for help. 1179 */ -1180 public static final String VERSION_SHORT = "v"; +1180 public static final String HELP_SHORT = "h"; 1181 /** -1182 * The short CLI argument name asking for the version. +1182 * The long CLI argument name asking for the version. 1183 */ -1184 public static final String VERSION = "version"; +1184 public static final String VERSION_SHORT = "v"; 1185 /** -1186 * The CLI argument name indicating the proxy port. +1186 * The short CLI argument name asking for the version. 1187 */ -1188 public static final String PROXY_PORT = "proxyport"; +1188 public static final String VERSION = "version"; 1189 /** -1190 * The CLI argument name indicating the proxy server. +1190 * The CLI argument name indicating the proxy port. 1191 */ -1192 public static final String PROXY_SERVER = "proxyserver"; +1192 public static final String PROXY_PORT = "proxyport"; 1193 /** -1194 * The CLI argument name indicating the proxy url. -1195 * -1196 * @deprecated use {@link #PROXY_SERVER} instead -1197 */ -1198 @Deprecated -1199 public static final String PROXY_URL = "proxyurl"; -1200 /** -1201 * The CLI argument name indicating the proxy username. -1202 */ -1203 public static final String PROXY_USERNAME = "proxyuser"; +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 +1201 */ +1202 @Deprecated +1203 public static final String PROXY_URL = "proxyurl"; 1204 /** -1205 * The CLI argument name indicating the proxy password. +1205 * The CLI argument name indicating the proxy username. 1206 */ -1207 public static final String PROXY_PASSWORD = "proxypass"; +1207 public static final String PROXY_USERNAME = "proxyuser"; 1208 /** -1209 * The short CLI argument name indicating the connection timeout. +1209 * The CLI argument name indicating the proxy password. 1210 */ -1211 public static final String CONNECTION_TIMEOUT_SHORT = "c"; +1211 public static final String PROXY_PASSWORD = "proxypass"; 1212 /** -1213 * The CLI argument name indicating the connection timeout. +1213 * The short CLI argument name indicating the connection timeout. 1214 */ -1215 public static final String CONNECTION_TIMEOUT = "connectiontimeout"; +1215 public static final String CONNECTION_TIMEOUT_SHORT = "c"; 1216 /** -1217 * The short CLI argument name for setting the location of an additional -1218 * properties file. -1219 */ -1220 public static final String PROP_SHORT = "P"; -1221 /** -1222 * The CLI argument name for setting the location of an additional -1223 * properties file. -1224 */ -1225 public static final String PROP = "propertyfile"; -1226 /** -1227 * The CLI argument name for setting the location of the data directory. +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. 1228 */ -1229 public static final String DATA_DIRECTORY = "data"; +1229 public static final String PROP = "propertyfile"; 1230 /** -1231 * The CLI argument name for setting the URL for the CVE Data Files. +1231 * The CLI argument name for setting the location of the data directory. 1232 */ -1233 public static final String CVE_MOD_12 = "cveUrl12Modified"; +1233 public static final String DATA_DIRECTORY = "data"; 1234 /** 1235 * The CLI argument name for setting the URL for the CVE Data Files. 1236 */ -1237 public static final String CVE_MOD_20 = "cveUrl20Modified"; +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_BASE_12 = "cveUrl12Base"; +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_20 = "cveUrl20Base"; +1245 public static final String CVE_BASE_12 = "cveUrl12Base"; 1246 /** -1247 * The short CLI argument name for setting the location of the data -1248 * directory. -1249 */ -1250 public static final String DATA_DIRECTORY_SHORT = "d"; -1251 /** -1252 * The CLI argument name for setting the location of the data directory. +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 VERBOSE_LOG = "log"; +1254 public static final String DATA_DIRECTORY_SHORT = "d"; 1255 /** -1256 * The short CLI argument name for setting the location of the data -1257 * directory. -1258 */ -1259 public static final String VERBOSE_LOG_SHORT = "l"; -1260 -1261 /** -1262 * The CLI argument name for setting the depth of symbolic links that -1263 * will be followed. -1264 */ -1265 public static final String SYM_LINK_DEPTH = "symLink"; -1266 /** -1267 * The CLI argument name for setting the location of the suppression -1268 * file. -1269 */ -1270 public static final String SUPPRESSION_FILE = "suppression"; -1271 /** -1272 * The CLI argument name for setting the location of the suppression -1273 * file. -1274 */ -1275 public static final String CVE_VALID_FOR_HOURS = "cveValidForHours"; -1276 /** -1277 * Disables the Jar Analyzer. +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. +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 DISABLE_JAR = "disableJar"; +1279 public static final String CVE_VALID_FOR_HOURS = "cveValidForHours"; 1280 /** -1281 * Disables the Archive Analyzer. +1281 * Disables the Jar Analyzer. 1282 */ -1283 public static final String DISABLE_ARCHIVE = "disableArchive"; +1283 public static final String DISABLE_JAR = "disableJar"; 1284 /** -1285 * Disables the Python Distribution Analyzer. +1285 * Disables the Archive Analyzer. 1286 */ -1287 public static final String DISABLE_PY_DIST = "disablePyDist"; +1287 public static final String DISABLE_ARCHIVE = "disableArchive"; 1288 /** -1289 * Disables the Python Package Analyzer. +1289 * Disables the Python Distribution Analyzer. 1290 */ -1291 public static final String DISABLE_PY_PKG = "disablePyPkg"; +1291 public static final String DISABLE_PY_DIST = "disablePyDist"; 1292 /** 1293 * Disables the Python Package Analyzer. 1294 */ -1295 public static final String DISABLE_COMPOSER = "disableComposer"; +1295 public static final String DISABLE_PY_PKG = "disablePyPkg"; 1296 /** -1297 * Disables the Ruby Gemspec Analyzer. +1297 * Disables the Python Package Analyzer. 1298 */ -1299 public static final String DISABLE_RUBYGEMS = "disableRubygems"; +1299 public static final String DISABLE_COMPOSER = "disableComposer"; 1300 /** -1301 * Disables the Autoconf Analyzer. +1301 * Disables the Ruby Gemspec Analyzer. 1302 */ -1303 public static final String DISABLE_AUTOCONF = "disableAutoconf"; +1303 public static final String DISABLE_RUBYGEMS = "disableRubygems"; 1304 /** -1305 * Disables the Cmake Analyzer. +1305 * Disables the Autoconf Analyzer. 1306 */ -1307 public static final String DISABLE_CMAKE = "disableCmake"; +1307 public static final String DISABLE_AUTOCONF = "disableAutoconf"; 1308 /** -1309 * Disables the Assembly Analyzer. +1309 * Disables the Cmake Analyzer. 1310 */ -1311 public static final String DISABLE_ASSEMBLY = "disableAssembly"; +1311 public static final String DISABLE_CMAKE = "disableCmake"; 1312 /** -1313 * Disables the Ruby Bundler Audit Analyzer. +1313 * Disables the Assembly Analyzer. 1314 */ -1315 public static final String DISABLE_BUNDLE_AUDIT = "disableBundleAudit"; +1315 public static final String DISABLE_ASSEMBLY = "disableAssembly"; 1316 /** -1317 * Disables the Nuspec Analyzer. +1317 * Disables the Ruby Bundler Audit Analyzer. 1318 */ -1319 public static final String DISABLE_NUSPEC = "disableNuspec"; +1319 public static final String DISABLE_BUNDLE_AUDIT = "disableBundleAudit"; 1320 /** -1321 * Disables the Central Analyzer. +1321 * Disables the Nuspec Analyzer. 1322 */ -1323 public static final String DISABLE_CENTRAL = "disableCentral"; +1323 public static final String DISABLE_NUSPEC = "disableNuspec"; 1324 /** -1325 * Disables the Nexus Analyzer. +1325 * Disables the Central Analyzer. 1326 */ -1327 public static final String DISABLE_NEXUS = "disableNexus"; +1327 public static final String DISABLE_CENTRAL = "disableCentral"; 1328 /** -1329 * Disables the OpenSSL Analyzer. +1329 * Disables the Nexus Analyzer. 1330 */ -1331 public static final String DISABLE_OPENSSL = "disableOpenSSL"; +1331 public static final String DISABLE_NEXUS = "disableNexus"; 1332 /** -1333 * Disables the Node.js Package Analyzer. +1333 * Disables the OpenSSL Analyzer. 1334 */ -1335 public static final String DISABLE_NODE_JS = "disableNodeJS"; +1335 public static final String DISABLE_OPENSSL = "disableOpenSSL"; 1336 /** -1337 * The URL of the nexus server. +1337 * Disables the Node.js Package Analyzer. 1338 */ -1339 public static final String NEXUS_URL = "nexus"; +1339 public static final String DISABLE_NODE_JS = "disableNodeJS"; 1340 /** -1341 * Whether or not the defined proxy should be used when connecting to -1342 * Nexus. -1343 */ -1344 public static final String NEXUS_USES_PROXY = "nexusUsesProxy"; -1345 /** -1346 * The CLI argument name for setting the connection string. +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 CONNECTION_STRING = "connectionString"; +1348 public static final String NEXUS_USES_PROXY = "nexusUsesProxy"; 1349 /** -1350 * The CLI argument name for setting the database user name. +1350 * The CLI argument name for setting the connection string. 1351 */ -1352 public static final String DB_NAME = "dbUser"; +1352 public static final String CONNECTION_STRING = "connectionString"; 1353 /** -1354 * The CLI argument name for setting the database password. +1354 * The CLI argument name for setting the database user name. 1355 */ -1356 public static final String DB_PASSWORD = "dbPassword"; +1356 public static final String DB_NAME = "dbUser"; 1357 /** -1358 * The CLI argument name for setting the database driver name. +1358 * The CLI argument name for setting the database password. 1359 */ -1360 public static final String DB_DRIVER = "dbDriverName"; +1360 public static final String DB_PASSWORD = "dbPassword"; 1361 /** -1362 * The CLI argument name for setting the path to the database driver; in -1363 * case it is not on the class path. -1364 */ -1365 public static final String DB_DRIVER_PATH = "dbDriverPath"; -1366 /** -1367 * The CLI argument name for setting the path to mono for .NET Assembly -1368 * analysis on non-windows systems. -1369 */ -1370 public static final String PATH_TO_MONO = "mono"; -1371 /** -1372 * The CLI argument name for setting extra extensions. +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 ADDITIONAL_ZIP_EXTENSIONS = "zipExtensions"; +1374 public static final String PATH_TO_MONO = "mono"; 1375 /** -1376 * Exclude path argument. +1376 * The CLI argument name for setting extra extensions. 1377 */ -1378 public static final String EXCLUDE = "exclude"; +1378 public static final String ADDITIONAL_ZIP_EXTENSIONS = "zipExtensions"; 1379 /** -1380 * The CLI argument name for setting the path to bundle-audit for Ruby -1381 * bundle analysis. -1382 */ -1383 public static final String PATH_TO_BUNDLE_AUDIT = "bundleAudit"; -1384 /** -1385 * The CLI argument to enable the experimental analyzers. +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 private static final String EXPERIMENTAL = "enableExperimental"; -1388 } -1389 } +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 }
    diff --git a/xref/org/owasp/dependencycheck/Engine.html b/xref/org/owasp/dependencycheck/Engine.html index 3f0c2ae7e..e4cd6cf99 100644 --- a/xref/org/owasp/dependencycheck/Engine.html +++ b/xref/org/owasp/dependencycheck/Engine.html @@ -376,7 +376,7 @@ 368 } 369 370 LOGGER.debug("\n----------------------------------------------------\nBEGIN ANALYSIS\n----------------------------------------------------"); -371 LOGGER.info("Analysis Starting"); +371 LOGGER.info("Analysis Started"); 372 final long analysisStart = System.currentTimeMillis(); 373 374 // analysis phases diff --git a/xref/org/owasp/dependencycheck/agent/package-frame.html b/xref/org/owasp/dependencycheck/agent/package-frame.html index 50f477099..ad331cb6d 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.2 Reference Package org.owasp.dependencycheck.agent + Dependency-Check 1.4.3 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 66f186594..8d42657b6 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.2 Reference Package org.owasp.dependencycheck.agent + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.agent diff --git a/xref/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.html index 0e9f20d3b..dff6d6872 100644 --- a/xref/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.html @@ -138,56 +138,67 @@ 130 } 131 } else { 132 file = new File(suppressionFilePath); -133 if (!file.exists()) { -134 final InputStream suppressionsFromClasspath = this.getClass().getClassLoader().getResourceAsStream(suppressionFilePath); -135 if (suppressionsFromClasspath != null) { -136 deleteTempFile = true; -137 file = FileUtils.getTempFile("suppression", "xml"); -138 try { -139 org.apache.commons.io.FileUtils.copyInputStreamToFile(suppressionsFromClasspath, file); -140 } catch (IOException ex) { -141 throwSuppressionParseException("Unable to locate suppressions file in classpath", ex); -142 } -143 } -144 } -145 } -146 if (file != null) { -147 try { -148 rules.addAll(parser.parseSuppressionRules(file)); -149 LOGGER.debug("{} suppression rules were loaded.", rules.size()); -150 } catch (SuppressionParseException ex) { -151 LOGGER.warn("Unable to parse suppression xml file '{}'", file.getPath()); -152 LOGGER.warn(ex.getMessage()); -153 throw ex; -154 } -155 } -156 } catch (DownloadFailedException ex) { -157 throwSuppressionParseException("Unable to fetch the configured suppression file", ex); -158 } catch (MalformedURLException ex) { -159 throwSuppressionParseException("Configured suppression file has an invalid URL", ex); -160 } catch (IOException ex) { -161 throwSuppressionParseException("Unable to create temp file for suppressions", ex); -162 } finally { -163 if (deleteTempFile && file != null) { -164 FileUtils.delete(file); -165 } -166 } -167 } -168 -169 /** -170 * Utility method to throw parse exceptions. -171 * -172 * @param message the exception message -173 * @param exception the cause of the exception -174 * @throws SuppressionParseException throws the generated -175 * SuppressionParseException -176 */ -177 private void throwSuppressionParseException(String message, Exception exception) throws SuppressionParseException { -178 LOGGER.warn(message); -179 LOGGER.debug("", exception); -180 throw new SuppressionParseException(message, exception); -181 } -182 } +133 InputStream suppressionsFromClasspath = null; +134 if (!file.exists()) { +135 try { +136 suppressionsFromClasspath = this.getClass().getClassLoader().getResourceAsStream(suppressionFilePath); +137 if (suppressionsFromClasspath != null) { +138 deleteTempFile = true; +139 file = FileUtils.getTempFile("suppression", "xml"); +140 try { +141 org.apache.commons.io.FileUtils.copyInputStreamToFile(suppressionsFromClasspath, file); +142 } catch (IOException ex) { +143 throwSuppressionParseException("Unable to locate suppressions file in classpath", ex); +144 } +145 } +146 } finally { +147 if (suppressionsFromClasspath != null) { +148 try { +149 suppressionsFromClasspath.close(); +150 } catch (IOException ex) { +151 LOGGER.debug("Failed to close stream", ex); +152 } +153 } +154 } +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 }
    diff --git a/xref/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.html index 357c4dac7..101341061 100644 --- a/xref/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.html @@ -365,230 +365,238 @@ 357 */ 358 private void extractFiles(File archive, File destination, Engine engine) throws AnalysisException { 359 if (archive != null && destination != null) { -360 FileInputStream fis; -361 try { -362 fis = new FileInputStream(archive); -363 } catch (FileNotFoundException ex) { -364 LOGGER.debug("", ex); -365 throw new AnalysisException("Archive file was not found.", ex); -366 } -367 final String archiveExt = FileUtils.getFileExtension(archive.getName()).toLowerCase(); -368 try { -369 if (ZIPPABLES.contains(archiveExt)) { -370 final BufferedInputStream in = new BufferedInputStream(fis); -371 ensureReadableJar(archiveExt, in); -372 extractArchive(new ZipArchiveInputStream(in), destination, engine); -373 } else if ("tar".equals(archiveExt)) { -374 extractArchive(new TarArchiveInputStream(new BufferedInputStream(fis)), destination, engine); -375 } else if ("gz".equals(archiveExt) || "tgz".equals(archiveExt)) { -376 final String uncompressedName = GzipUtils.getUncompressedFilename(archive.getName()); -377 final File f = new File(destination, uncompressedName); -378 if (engine.accept(f)) { -379 decompressFile(new GzipCompressorInputStream(new BufferedInputStream(fis)), f); -380 } -381 } else if ("bz2".equals(archiveExt) || "tbz2".equals(archiveExt)) { -382 final String uncompressedName = BZip2Utils.getUncompressedFilename(archive.getName()); -383 final File f = new File(destination, uncompressedName); -384 if (engine.accept(f)) { -385 decompressFile(new BZip2CompressorInputStream(new BufferedInputStream(fis)), f); -386 } -387 } -388 } catch (ArchiveExtractionException ex) { -389 LOGGER.warn("Exception extracting archive '{}'.", archive.getName()); -390 LOGGER.debug("", ex); -391 } catch (IOException ex) { -392 LOGGER.warn("Exception reading archive '{}'.", archive.getName()); -393 LOGGER.debug("", ex); -394 } finally { -395 close(fis); -396 } -397 } -398 } -399 -400 /** -401 * Checks if the file being scanned is a JAR that begins with '#!/bin' which -402 * indicates it is a fully executable jar. If a fully executable JAR is -403 * identified the input stream will be advanced to the start of the actual -404 * JAR file ( skipping the script). -405 * -406 * @see -407 * <a href="http://docs.spring.io/spring-boot/docs/1.3.0.BUILD-SNAPSHOT/reference/htmlsingle/#deployment-install">Installing -408 * Spring Boot Applications</a> -409 * @param archiveExt the file extension -410 * @param in the input stream -411 * @throws IOException thrown if there is an error reading the stream -412 */ -413 private void ensureReadableJar(final String archiveExt, BufferedInputStream in) throws IOException { -414 if ("jar".equals(archiveExt) && in.markSupported()) { -415 in.mark(7); -416 final byte[] b = new byte[7]; -417 in.read(b); -418 if (b[0] == '#' -419 && b[1] == '!' -420 && b[2] == '/' -421 && b[3] == 'b' -422 && b[4] == 'i' -423 && b[5] == 'n' -424 && b[6] == '/') { -425 boolean stillLooking = true; -426 int chr, nxtChr; -427 while (stillLooking && (chr = in.read()) != -1) { -428 if (chr == '\n' || chr == '\r') { -429 in.mark(4); -430 if ((chr = in.read()) != -1) { -431 if (chr == 'P' && (chr = in.read()) != -1) { -432 if (chr == 'K' && (chr = in.read()) != -1) { -433 if ((chr == 3 || chr == 5 || chr == 7) && (nxtChr = in.read()) != -1) { -434 if (nxtChr == chr + 1) { -435 stillLooking = false; -436 in.reset(); -437 } -438 } -439 } -440 } -441 } -442 } -443 } -444 } -445 } -446 } -447 -448 /** -449 * Extracts files from an archive. -450 * -451 * @param input the archive to extract files from -452 * @param destination the location to write the files too -453 * @param engine the dependency-check engine -454 * @throws ArchiveExtractionException thrown if there is an exception -455 * extracting files from the archive -456 */ -457 private void extractArchive(ArchiveInputStream input, File destination, Engine engine) throws ArchiveExtractionException { -458 ArchiveEntry entry; -459 try { -460 while ((entry = input.getNextEntry()) != null) { -461 final File file = new File(destination, entry.getName()); -462 if (entry.isDirectory()) { -463 if (!file.exists() && !file.mkdirs()) { -464 final String msg = String.format("Unable to create directory '%s'.", file.getAbsolutePath()); -465 throw new AnalysisException(msg); -466 } -467 } else if (engine.accept(file)) { -468 extractAcceptedFile(input, file); -469 } -470 } -471 } catch (Throwable ex) { -472 throw new ArchiveExtractionException(ex); -473 } finally { -474 close(input); -475 } -476 } -477 -478 /** -479 * Extracts a file from an archive. -480 * -481 * @param input the archives input stream -482 * @param file the file to extract -483 * @throws AnalysisException thrown if there is an error -484 */ -485 private static void extractAcceptedFile(ArchiveInputStream input, File file) throws AnalysisException { -486 LOGGER.debug("Extracting '{}'", file.getPath()); -487 FileOutputStream fos = null; -488 try { -489 final File parent = file.getParentFile(); -490 if (!parent.isDirectory() && !parent.mkdirs()) { -491 final String msg = String.format("Unable to build directory '%s'.", parent.getAbsolutePath()); -492 throw new AnalysisException(msg); -493 } -494 fos = new FileOutputStream(file); -495 IOUtils.copy(input, fos); -496 } catch (FileNotFoundException ex) { -497 LOGGER.debug("", ex); -498 final String msg = String.format("Unable to find file '%s'.", file.getName()); -499 throw new AnalysisException(msg, ex); -500 } catch (IOException ex) { -501 LOGGER.debug("", ex); -502 final String msg = String.format("IO Exception while parsing file '%s'.", file.getName()); -503 throw new AnalysisException(msg, ex); -504 } finally { -505 close(fos); -506 } -507 } -508 -509 /** -510 * Decompresses a file. -511 * -512 * @param inputStream the compressed file -513 * @param outputFile the location to write the decompressed file -514 * @throws ArchiveExtractionException thrown if there is an exception -515 * decompressing the file -516 */ -517 private void decompressFile(CompressorInputStream inputStream, File outputFile) throws ArchiveExtractionException { -518 LOGGER.debug("Decompressing '{}'", outputFile.getPath()); -519 FileOutputStream out = null; -520 try { -521 out = new FileOutputStream(outputFile); -522 IOUtils.copy(inputStream, out); -523 } catch (FileNotFoundException ex) { -524 LOGGER.debug("", ex); -525 throw new ArchiveExtractionException(ex); -526 } catch (IOException ex) { -527 LOGGER.debug("", ex); -528 throw new ArchiveExtractionException(ex); -529 } finally { -530 close(out); -531 } -532 } -533 -534 /** -535 * Close the given {@link Closeable} instance, ignoring nulls, and logging -536 * any thrown {@link IOException}. -537 * -538 * @param closeable to be closed -539 */ -540 private static void close(Closeable closeable) { -541 if (null != closeable) { -542 try { -543 closeable.close(); -544 } catch (IOException ex) { -545 LOGGER.trace("", ex); -546 } -547 } -548 } -549 -550 /** -551 * Attempts to determine if a zip file is actually a JAR file. -552 * -553 * @param dependency the dependency to check -554 * @return true if the dependency appears to be a JAR file; otherwise false -555 */ -556 private boolean isZipFileActuallyJarFile(Dependency dependency) { -557 boolean isJar = false; -558 ZipFile zip = null; -559 try { -560 zip = new ZipFile(dependency.getActualFilePath()); -561 if (zip.getEntry("META-INF/MANIFEST.MF") != null -562 || zip.getEntry("META-INF/maven") != null) { -563 final Enumeration<ZipArchiveEntry> entries = zip.getEntries(); -564 while (entries.hasMoreElements()) { -565 final ZipArchiveEntry entry = entries.nextElement(); -566 if (!entry.isDirectory()) { -567 final String name = entry.getName().toLowerCase(); -568 if (name.endsWith(".class")) { -569 isJar = true; -570 break; -571 } -572 } -573 } -574 } -575 } catch (IOException ex) { -576 LOGGER.debug("Unable to unzip zip file '{}'", dependency.getFilePath(), ex); -577 } finally { -578 ZipFile.closeQuietly(zip); -579 } -580 -581 return isJar; -582 } -583 } +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 }
    diff --git a/xref/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.html index 12b21ab99..34acd7d46 100644 --- a/xref/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.html @@ -53,282 +53,330 @@ 45 import java.util.List; 46 import javax.xml.parsers.ParserConfigurationException; 47 import org.owasp.dependencycheck.exception.InitializationException; -48 -49 /** -50 * Analyzer for getting company, product, and version information from a .NET -51 * assembly. -52 * -53 * @author colezlaw -54 * -55 */ -56 public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer { -57 -58 /** -59 * The analyzer name -60 */ -61 private static final String ANALYZER_NAME = "Assembly Analyzer"; -62 /** -63 * The analysis phase -64 */ -65 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION; -66 /** -67 * The list of supported extensions -68 */ -69 private static final String[] SUPPORTED_EXTENSIONS = {"dll", "exe"}; -70 /** -71 * The temp value for GrokAssembly.exe -72 */ -73 private File grokAssemblyExe = null; -74 /** -75 * The DocumentBuilder for parsing the XML -76 */ -77 private DocumentBuilder builder; -78 /** -79 * Logger -80 */ -81 private static final Logger LOGGER = LoggerFactory.getLogger(AssemblyAnalyzer.class); -82 -83 /** -84 * Builds the beginnings of a List for ProcessBuilder -85 * -86 * @return the list of arguments to begin populating the ProcessBuilder -87 */ -88 private List<String> buildArgumentList() { -89 // Use file.separator as a wild guess as to whether this is Windows -90 final List<String> args = new ArrayList<String>(); -91 if (!"\\".equals(System.getProperty("file.separator"))) { -92 if (Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH) != null) { -93 args.add(Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH)); -94 } else { -95 args.add("mono"); -96 } -97 } -98 args.add(grokAssemblyExe.getPath()); -99 -100 return args; -101 } -102 -103 /** -104 * Performs the analysis on a single Dependency. -105 * -106 * @param dependency the dependency to analyze -107 * @param engine the engine to perform the analysis under -108 * @throws AnalysisException if anything goes sideways -109 */ -110 @Override -111 public void analyzeFileType(Dependency dependency, Engine engine) -112 throws AnalysisException { -113 if (grokAssemblyExe == null) { -114 LOGGER.warn("GrokAssembly didn't get deployed"); -115 return; -116 } -117 -118 final List<String> args = buildArgumentList(); -119 args.add(dependency.getActualFilePath()); -120 final ProcessBuilder pb = new ProcessBuilder(args); -121 Document doc = null; -122 try { -123 final Process proc = pb.start(); -124 -125 doc = builder.parse(proc.getInputStream()); -126 -127 // Try evacuating the error stream -128 final String errorStream = IOUtils.toString(proc.getErrorStream(), "UTF-8"); -129 if (null != errorStream && !errorStream.isEmpty()) { -130 LOGGER.warn("Error from GrokAssembly: {}", errorStream); -131 } +48 import org.apache.commons.lang3.SystemUtils; +49 +50 /** +51 * Analyzer for getting company, product, and version information from a .NET +52 * assembly. +53 * +54 * @author colezlaw +55 * +56 */ +57 public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer { +58 +59 /** +60 * The analyzer name +61 */ +62 private static final String ANALYZER_NAME = "Assembly Analyzer"; +63 /** +64 * The analysis phase +65 */ +66 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION; +67 /** +68 * The list of supported extensions +69 */ +70 private static final String[] SUPPORTED_EXTENSIONS = {"dll", "exe"}; +71 /** +72 * The temp value for GrokAssembly.exe +73 */ +74 private File grokAssemblyExe = null; +75 /** +76 * The DocumentBuilder for parsing the XML +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 int rc = 0; -134 try { -135 rc = proc.waitFor(); -136 } catch (InterruptedException ie) { -137 return; -138 } -139 if (rc == 3) { -140 LOGGER.debug("{} is not a .NET assembly or executable and as such cannot be analyzed by dependency-check", -141 dependency.getActualFilePath()); -142 return; -143 } else if (rc != 0) { -144 LOGGER.warn("Return code {} from GrokAssembly", rc); -145 } -146 -147 final XPath xpath = XPathFactory.newInstance().newXPath(); -148 -149 // First, see if there was an error -150 final String error = xpath.evaluate("/assembly/error", doc); -151 if (error != null && !error.isEmpty()) { -152 throw new AnalysisException(error); -153 } +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 final String version = xpath.evaluate("/assembly/version", doc); -156 if (version != null) { -157 dependency.getVersionEvidence().addEvidence(new Evidence("grokassembly", "version", -158 version, Confidence.HIGHEST)); +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 vendor = xpath.evaluate("/assembly/company", doc); -162 if (vendor != null) { -163 dependency.getVendorEvidence().addEvidence(new Evidence("grokassembly", "vendor", -164 vendor, Confidence.HIGH)); +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 product = xpath.evaluate("/assembly/product", doc); -168 if (product != null) { -169 dependency.getProductEvidence().addEvidence(new Evidence("grokassembly", "product", -170 product, Confidence.HIGH)); +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 } catch (IOException ioe) { -174 throw new AnalysisException(ioe); -175 } catch (SAXException saxe) { -176 throw new AnalysisException("Couldn't parse GrokAssembly result", saxe); -177 } catch (XPathExpressionException xpe) { -178 // This shouldn't happen -179 throw new AnalysisException(xpe); -180 } -181 } -182 -183 /** -184 * Initialize the analyzer. In this case, extract GrokAssembly.exe to a -185 * temporary location. -186 * -187 * @throws InitializationException thrown if anything goes wrong -188 */ -189 @Override -190 public void initializeFileTypeAnalyzer() throws InitializationException { -191 final File tempFile; -192 try { -193 tempFile = File.createTempFile("GKA", ".exe", Settings.getTempDirectory()); -194 } catch (IOException ex) { -195 setEnabled(false); -196 throw new InitializationException("Unable to create temporary file for the assembly analyzerr", ex); -197 } -198 FileOutputStream fos = null; -199 InputStream is = null; -200 try { -201 fos = new FileOutputStream(tempFile); -202 is = AssemblyAnalyzer.class.getClassLoader().getResourceAsStream("GrokAssembly.exe"); -203 IOUtils.copy(is, fos); -204 -205 grokAssemblyExe = tempFile; -206 // Set the temp file to get deleted when we're done -207 grokAssemblyExe.deleteOnExit(); -208 LOGGER.debug("Extracted GrokAssembly.exe to {}", grokAssemblyExe.getPath()); -209 } catch (IOException ioe) { -210 this.setEnabled(false); -211 LOGGER.warn("Could not extract GrokAssembly.exe: {}", ioe.getMessage()); -212 throw new InitializationException("Could not extract GrokAssembly.exe", ioe); -213 } finally { -214 if (fos != null) { -215 try { -216 fos.close(); -217 } catch (Throwable e) { -218 LOGGER.debug("Error closing output stream"); -219 } -220 } -221 if (is != null) { -222 try { -223 is.close(); -224 } catch (Throwable e) { -225 LOGGER.debug("Error closing input stream"); -226 } -227 } -228 } -229 -230 // Now, need to see if GrokAssembly actually runs from this location. -231 final List<String> args = buildArgumentList(); -232 try { -233 final ProcessBuilder pb = new ProcessBuilder(args); -234 final Process p = pb.start(); -235 // Try evacuating the error stream -236 IOUtils.copy(p.getErrorStream(), NullOutputStream.NULL_OUTPUT_STREAM); -237 -238 final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(p.getInputStream()); -239 final XPath xpath = XPathFactory.newInstance().newXPath(); -240 final String error = xpath.evaluate("/assembly/error", doc); -241 if (p.waitFor() != 1 || error == null || error.isEmpty()) { -242 LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer, please see the log for more details."); -243 LOGGER.debug("GrokAssembly.exe is not working properly"); -244 grokAssemblyExe = null; -245 setEnabled(false); -246 throw new InitializationException("Could not execute .NET AssemblyAnalyzer"); -247 } -248 } catch (InitializationException e) { -249 throw e; -250 } catch (Throwable e) { -251 LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer;\n" -252 + "this can be ignored unless you are scanning .NET DLLs. Please see the log for more details."); -253 LOGGER.debug("Could not execute GrokAssembly {}", e.getMessage()); -254 setEnabled(false); -255 throw new InitializationException("An error occurred with the .NET AssemblyAnalyzer", e); -256 } -257 try { -258 builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); -259 } catch (ParserConfigurationException ex) { -260 setEnabled(false); -261 throw new InitializationException("Error initializing the assembly analyzer", ex); -262 } -263 } -264 -265 /** -266 * Removes resources used from the local file system. -267 * -268 * @throws Exception thrown if there is a problem closing the analyzer -269 */ -270 @Override -271 public void close() throws Exception { -272 super.close(); -273 try { -274 if (grokAssemblyExe != null && !grokAssemblyExe.delete()) { -275 grokAssemblyExe.deleteOnExit(); -276 } -277 } catch (SecurityException se) { -278 LOGGER.debug("Can't delete temporary GrokAssembly.exe"); -279 } -280 } -281 -282 /** -283 * The File Filter used to filter supported extensions. -284 */ -285 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions( -286 SUPPORTED_EXTENSIONS).build(); -287 -288 @Override -289 protected FileFilter getFileFilter() { -290 return FILTER; -291 } -292 -293 /** -294 * Gets this analyzer's name. -295 * -296 * @return the analyzer name -297 */ -298 @Override -299 public String getName() { -300 return ANALYZER_NAME; -301 } -302 -303 /** -304 * Returns the phase this analyzer runs under. -305 * -306 * @return the phase this runs under +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 @Override -309 public AnalysisPhase getAnalysisPhase() { -310 return ANALYSIS_PHASE; -311 } -312 -313 /** -314 * Returns the key used in the properties file to reference the analyzer's -315 * enabled property. -316 * -317 * @return the analyzer's enabled property setting key -318 */ -319 @Override -320 protected String getAnalyzerEnabledSettingKey() { -321 return Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED; -322 } -323 } +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 }
    diff --git a/xref/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.html index f090a3223..d9f5e97dd 100644 --- a/xref/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.html @@ -204,53 +204,56 @@ 196 * @param engine the dependency-check engine 197 * @param contents the version information 198 */ -199 private void analyzeSetVersionCommand(Dependency dependency, Engine engine, String contents) { -200 Dependency currentDep = dependency; -201 -202 final Matcher m = SET_VERSION.matcher(contents); -203 int count = 0; -204 while (m.find()) { -205 count++; -206 LOGGER.debug("Found project command match with {} groups: {}", -207 m.groupCount(), m.group(0)); -208 String product = m.group(1); -209 final String version = m.group(2); -210 LOGGER.debug("Group 1: " + product); -211 LOGGER.debug("Group 2: " + version); -212 final String aliasPrefix = "ALIASOF_"; -213 if (product.startsWith(aliasPrefix)) { -214 product = product.replaceFirst(aliasPrefix, ""); -215 } -216 if (count > 1) { -217 //TODO - refactor so we do not assign to the parameter (checkstyle) -218 currentDep = new Dependency(dependency.getActualFile()); -219 currentDep.setDisplayFileName(String.format("%s:%s", dependency.getDisplayFileName(), product)); -220 final String filePath = String.format("%s:%s", dependency.getFilePath(), product); -221 currentDep.setFilePath(filePath); -222 -223 byte[] path; -224 try { -225 path = filePath.getBytes("UTF-8"); -226 } catch (UnsupportedEncodingException ex) { -227 path = filePath.getBytes(); -228 } -229 currentDep.setSha1sum(Checksum.getHex(sha1.digest(path))); -230 engine.getDependencies().add(currentDep); -231 } -232 final String source = currentDep.getDisplayFileName(); -233 currentDep.getProductEvidence().addEvidence(source, "Product", -234 product, Confidence.MEDIUM); -235 currentDep.getVersionEvidence().addEvidence(source, "Version", -236 version, Confidence.MEDIUM); -237 } -238 LOGGER.debug(String.format("Found %d matches.", count)); -239 } -240 -241 @Override -242 protected String getAnalyzerEnabledSettingKey() { -243 return Settings.KEYS.ANALYZER_CMAKE_ENABLED; -244 } -245 } +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 }
    diff --git a/xref/org/owasp/dependencycheck/analyzer/CPEAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/CPEAnalyzer.html index dada8235f..1cd289873 100644 --- a/xref/org/owasp/dependencycheck/analyzer/CPEAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/CPEAnalyzer.html @@ -33,793 +33,801 @@ 25 import java.util.List; 26 import java.util.Set; 27 import java.util.StringTokenizer; -28 import org.apache.lucene.document.Document; -29 import org.apache.lucene.index.CorruptIndexException; -30 import org.apache.lucene.queryparser.classic.ParseException; -31 import org.apache.lucene.search.ScoreDoc; -32 import org.apache.lucene.search.TopDocs; -33 import org.owasp.dependencycheck.Engine; -34 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; -35 import org.owasp.dependencycheck.data.cpe.CpeMemoryIndex; -36 import org.owasp.dependencycheck.data.cpe.Fields; -37 import org.owasp.dependencycheck.data.cpe.IndexEntry; -38 import org.owasp.dependencycheck.data.cpe.IndexException; -39 import org.owasp.dependencycheck.data.lucene.LuceneUtils; -40 import org.owasp.dependencycheck.data.nvdcve.CveDB; -41 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; -42 import org.owasp.dependencycheck.dependency.Confidence; -43 import org.owasp.dependencycheck.dependency.Dependency; -44 import org.owasp.dependencycheck.dependency.Evidence; -45 import org.owasp.dependencycheck.dependency.EvidenceCollection; -46 import org.owasp.dependencycheck.dependency.Identifier; -47 import org.owasp.dependencycheck.dependency.VulnerableSoftware; -48 import org.owasp.dependencycheck.exception.InitializationException; -49 import org.owasp.dependencycheck.utils.DependencyVersion; -50 import org.owasp.dependencycheck.utils.DependencyVersionUtil; -51 import org.slf4j.Logger; -52 import org.slf4j.LoggerFactory; -53 -54 /** -55 * CPEAnalyzer is a utility class that takes a project dependency and attempts -56 * to discern if there is an associated CPE. It uses the evidence contained -57 * within the dependency to search the Lucene index. -58 * -59 * @author Jeremy Long -60 */ -61 public class CPEAnalyzer implements Analyzer { -62 -63 /** -64 * The Logger. -65 */ -66 private static final Logger LOGGER = LoggerFactory.getLogger(CPEAnalyzer.class); -67 /** -68 * The maximum number of query results to return. -69 */ -70 static final int MAX_QUERY_RESULTS = 25; -71 /** -72 * The weighting boost to give terms when constructing the Lucene query. -73 */ -74 static final String WEIGHTING_BOOST = "^5"; -75 /** -76 * A string representation of a regular expression defining characters -77 * utilized within the CPE Names. -78 */ -79 static final String CLEANSE_CHARACTER_RX = "[^A-Za-z0-9 ._-]"; -80 /** -81 * A string representation of a regular expression used to remove all but -82 * alpha characters. -83 */ -84 static final String CLEANSE_NONALPHA_RX = "[^A-Za-z]*"; -85 /** -86 * The additional size to add to a new StringBuilder to account for extra -87 * data that will be written into the string. -88 */ -89 static final int STRING_BUILDER_BUFFER = 20; -90 /** -91 * The CPE in memory index. -92 */ -93 private CpeMemoryIndex cpe; -94 /** -95 * The CVE Database. -96 */ -97 private CveDB cve; -98 -99 /** -100 * The URL to perform a search of the NVD CVE data at NIST. -101 */ -102 public static final String NVD_SEARCH_URL = "https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=%s"; -103 -104 /** -105 * Returns the name of this analyzer. -106 * -107 * @return the name of this analyzer. -108 */ -109 @Override -110 public String getName() { -111 return "CPE Analyzer"; -112 } -113 -114 /** -115 * Returns the analysis phase that this analyzer should run in. -116 * -117 * @return the analysis phase that this analyzer should run in. -118 */ -119 @Override -120 public AnalysisPhase getAnalysisPhase() { -121 return AnalysisPhase.IDENTIFIER_ANALYSIS; -122 } -123 -124 /** -125 * Creates the CPE Lucene Index. -126 * -127 * @throws InitializationException is thrown if there is an issue opening -128 * the index. -129 */ -130 @Override -131 public void initialize() throws InitializationException { -132 try { -133 this.open(); -134 } catch (IOException ex) { -135 LOGGER.debug("Exception initializing the Lucene Index", ex); -136 throw new InitializationException("An exception occurred initializing the Lucene Index", ex); -137 } catch (DatabaseException ex) { -138 LOGGER.debug("Exception accessing the database", ex); -139 throw new InitializationException("An exception occurred accessing the database", ex); -140 } -141 } -142 -143 /** -144 * Opens the data source. -145 * -146 * @throws IOException when the Lucene directory to be queried does not -147 * exist or is corrupt. -148 * @throws DatabaseException when the database throws an exception. This -149 * usually occurs when the database is in use by another process. -150 */ -151 public void open() throws IOException, DatabaseException { -152 if (!isOpen()) { -153 cve = new CveDB(); -154 cve.open(); -155 cpe = CpeMemoryIndex.getInstance(); -156 try { -157 LOGGER.info("Creating the CPE Index"); -158 final long creationStart = System.currentTimeMillis(); -159 cpe.open(cve); -160 LOGGER.info("CPE Index Created ({} ms)", System.currentTimeMillis() - creationStart); -161 } catch (IndexException ex) { -162 LOGGER.debug("IndexException", ex); -163 throw new DatabaseException(ex); -164 } -165 } -166 } -167 -168 /** -169 * Closes the data sources. -170 */ -171 @Override -172 public void close() { -173 if (cpe != null) { -174 cpe.close(); -175 cpe = null; -176 } -177 if (cve != null) { -178 cve.close(); -179 cve = null; -180 } -181 } -182 -183 public boolean isOpen() { -184 return cpe != null && cpe.isOpen(); -185 } -186 -187 /** -188 * Searches the data store of CPE entries, trying to identify the CPE for -189 * the given dependency based on the evidence contained within. The -190 * dependency passed in is updated with any identified CPE values. -191 * -192 * @param dependency the dependency to search for CPE entries on. -193 * @throws CorruptIndexException is thrown when the Lucene index is corrupt. -194 * @throws IOException is thrown when an IOException occurs. -195 * @throws ParseException is thrown when the Lucene query cannot be parsed. -196 */ -197 protected void determineCPE(Dependency dependency) throws CorruptIndexException, IOException, ParseException { -198 //TODO test dojo-war against this. we shold get dojo-toolkit:dojo-toolkit AND dojo-toolkit:toolkit -199 String vendors = ""; -200 String products = ""; -201 for (Confidence confidence : Confidence.values()) { -202 if (dependency.getVendorEvidence().contains(confidence)) { -203 vendors = addEvidenceWithoutDuplicateTerms(vendors, dependency.getVendorEvidence(), confidence); -204 LOGGER.debug("vendor search: {}", vendors); -205 } -206 if (dependency.getProductEvidence().contains(confidence)) { -207 products = addEvidenceWithoutDuplicateTerms(products, dependency.getProductEvidence(), confidence); -208 LOGGER.debug("product search: {}", products); -209 } -210 if (!vendors.isEmpty() && !products.isEmpty()) { -211 final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getVendorEvidence().getWeighting(), -212 dependency.getProductEvidence().getWeighting()); -213 if (entries == null) { -214 continue; -215 } -216 boolean identifierAdded = false; -217 for (IndexEntry e : entries) { -218 LOGGER.debug("Verifying entry: {}", e); -219 if (verifyEntry(e, dependency)) { -220 final String vendor = e.getVendor(); -221 final String product = e.getProduct(); -222 LOGGER.debug("identified vendor/product: {}/{}", vendor, product); -223 identifierAdded |= determineIdentifiers(dependency, vendor, product, confidence); -224 } -225 } -226 if (identifierAdded) { -227 break; -228 } -229 } -230 } -231 } -232 -233 /** -234 * Returns the text created by concatenating the text and the values from -235 * the EvidenceCollection (filtered for a specific confidence). This -236 * attempts to prevent duplicate terms from being added.<br/<br/> Note, if -237 * the evidence is longer then 200 characters it will be truncated. -238 * -239 * @param text the base text. -240 * @param ec an EvidenceCollection -241 * @param confidenceFilter a Confidence level to filter the evidence by. -242 * @return the new evidence text -243 */ -244 private String addEvidenceWithoutDuplicateTerms(final String text, final EvidenceCollection ec, Confidence confidenceFilter) { -245 final String txt = (text == null) ? "" : text; -246 final StringBuilder sb = new StringBuilder(txt.length() + (20 * ec.size())); -247 sb.append(' ').append(txt).append(' '); -248 for (Evidence e : ec.iterator(confidenceFilter)) { -249 String value = e.getValue(); -250 -251 //hack to get around the fact that lucene does a really good job of recognizing domains and not -252 // splitting them. TODO - put together a better lucene analyzer specific to the domain. -253 if (value.startsWith("http://")) { -254 value = value.substring(7).replaceAll("\\.", " "); -255 } -256 if (value.startsWith("https://")) { -257 value = value.substring(8).replaceAll("\\.", " "); -258 } -259 if (sb.indexOf(" " + value + " ") < 0) { -260 sb.append(value).append(' '); -261 } -262 } -263 return sb.toString().trim(); -264 } -265 -266 /** -267 * <p> -268 * Searches the Lucene CPE index to identify possible CPE entries associated -269 * with the supplied vendor, product, and version.</p> -270 * -271 * <p> -272 * If either the vendorWeightings or productWeightings lists have been -273 * populated this data is used to add weighting factors to the search.</p> -274 * -275 * @param vendor the text used to search the vendor field -276 * @param product the text used to search the product field -277 * @param vendorWeightings a list of strings to use to add weighting factors -278 * to the vendor field -279 * @param productWeightings Adds a list of strings that will be used to add -280 * weighting factors to the product search -281 * @return a list of possible CPE values -282 */ -283 protected List<IndexEntry> searchCPE(String vendor, String product, -284 Set<String> vendorWeightings, Set<String> productWeightings) { -285 -286 final List<IndexEntry> ret = new ArrayList<IndexEntry>(MAX_QUERY_RESULTS); -287 -288 final String searchString = buildSearch(vendor, product, vendorWeightings, productWeightings); -289 if (searchString == null) { -290 return ret; -291 } -292 try { -293 final TopDocs docs = cpe.search(searchString, MAX_QUERY_RESULTS); -294 for (ScoreDoc d : docs.scoreDocs) { -295 if (d.score >= 0.08) { -296 final Document doc = cpe.getDocument(d.doc); -297 final IndexEntry entry = new IndexEntry(); -298 entry.setVendor(doc.get(Fields.VENDOR)); -299 entry.setProduct(doc.get(Fields.PRODUCT)); -300 entry.setSearchScore(d.score); -301 if (!ret.contains(entry)) { -302 ret.add(entry); -303 } -304 } -305 } -306 return ret; -307 } catch (ParseException ex) { -308 LOGGER.warn("An error occurred querying the CPE data. See the log for more details."); -309 LOGGER.info("Unable to parse: {}", searchString, ex); -310 } catch (IOException ex) { -311 LOGGER.warn("An error occurred reading CPE data. See the log for more details."); -312 LOGGER.info("IO Error with search string: {}", searchString, ex); -313 } -314 return null; -315 } -316 -317 /** -318 * <p> -319 * Builds a Lucene search string by properly escaping data and constructing -320 * a valid search query.</p> -321 * -322 * <p> -323 * If either the possibleVendor or possibleProducts lists have been -324 * populated this data is used to add weighting factors to the search string -325 * generated.</p> -326 * -327 * @param vendor text to search the vendor field -328 * @param product text to search the product field -329 * @param vendorWeighting a list of strings to apply to the vendor to boost -330 * the terms weight -331 * @param productWeightings a list of strings to apply to the product to -332 * boost the terms weight -333 * @return the Lucene query -334 */ -335 protected String buildSearch(String vendor, String product, -336 Set<String> vendorWeighting, Set<String> productWeightings) { -337 final String v = vendor; //.replaceAll("[^\\w\\d]", " "); -338 final String p = product; //.replaceAll("[^\\w\\d]", " "); -339 final StringBuilder sb = new StringBuilder(v.length() + p.length() -340 + Fields.PRODUCT.length() + Fields.VENDOR.length() + STRING_BUILDER_BUFFER); -341 -342 if (!appendWeightedSearch(sb, Fields.PRODUCT, p, productWeightings)) { -343 return null; -344 } -345 sb.append(" AND "); -346 if (!appendWeightedSearch(sb, Fields.VENDOR, v, vendorWeighting)) { -347 return null; -348 } -349 return sb.toString(); -350 } -351 -352 /** -353 * This method constructs a Lucene query for a given field. The searchText -354 * is split into separate words and if the word is within the list of -355 * weighted words then an additional weighting is applied to the term as it -356 * is appended into the query. -357 * -358 * @param sb a StringBuilder that the query text will be appended to. -359 * @param field the field within the Lucene index that the query is -360 * searching. -361 * @param searchText text used to construct the query. -362 * @param weightedText a list of terms that will be considered higher -363 * importance when searching. -364 * @return if the append was successful. -365 */ -366 private boolean appendWeightedSearch(StringBuilder sb, String field, String searchText, Set<String> weightedText) { -367 sb.append(' ').append(field).append(":( "); -368 -369 final String cleanText = cleanseText(searchText); -370 -371 if (cleanText.isEmpty()) { -372 return false; -373 } -374 -375 if (weightedText == null || weightedText.isEmpty()) { -376 LuceneUtils.appendEscapedLuceneQuery(sb, cleanText); -377 } else { -378 final StringTokenizer tokens = new StringTokenizer(cleanText); -379 while (tokens.hasMoreElements()) { -380 final String word = tokens.nextToken(); -381 StringBuilder temp = null; -382 for (String weighted : weightedText) { -383 final String weightedStr = cleanseText(weighted); -384 if (equalsIgnoreCaseAndNonAlpha(word, weightedStr)) { -385 temp = new StringBuilder(word.length() + 2); -386 LuceneUtils.appendEscapedLuceneQuery(temp, word); -387 temp.append(WEIGHTING_BOOST); -388 if (!word.equalsIgnoreCase(weightedStr)) { -389 temp.append(' '); -390 LuceneUtils.appendEscapedLuceneQuery(temp, weightedStr); -391 temp.append(WEIGHTING_BOOST); -392 } -393 break; -394 } -395 } -396 sb.append(' '); -397 if (temp == null) { -398 LuceneUtils.appendEscapedLuceneQuery(sb, word); -399 } else { -400 sb.append(temp); -401 } -402 } -403 } -404 sb.append(" ) "); -405 return true; -406 } -407 -408 /** -409 * Removes characters from the input text that are not used within the CPE -410 * index. -411 * -412 * @param text is the text to remove the characters from. -413 * @return the text having removed some characters. -414 */ -415 private String cleanseText(String text) { -416 return text.replaceAll(CLEANSE_CHARACTER_RX, " "); -417 } -418 -419 /** -420 * Compares two strings after lower casing them and removing the non-alpha -421 * characters. -422 * -423 * @param l string one to compare. -424 * @param r string two to compare. -425 * @return whether or not the two strings are similar. -426 */ -427 private boolean equalsIgnoreCaseAndNonAlpha(String l, String r) { -428 if (l == null || r == null) { -429 return false; -430 } -431 -432 final String left = l.replaceAll(CLEANSE_NONALPHA_RX, ""); -433 final String right = r.replaceAll(CLEANSE_NONALPHA_RX, ""); -434 return left.equalsIgnoreCase(right); -435 } -436 -437 /** -438 * Ensures that the CPE Identified matches the dependency. This validates -439 * that the product, vendor, and version information for the CPE are -440 * contained within the dependencies evidence. -441 * -442 * @param entry a CPE entry. -443 * @param dependency the dependency that the CPE entries could be for. -444 * @return whether or not the entry is valid. -445 */ -446 private boolean verifyEntry(final IndexEntry entry, final Dependency dependency) { -447 boolean isValid = false; -448 -449 //TODO - does this nullify some of the fuzzy matching that happens in the lucene search? -450 // for instance CPE some-component and in the evidence we have SomeComponent. -451 if (collectionContainsString(dependency.getProductEvidence(), entry.getProduct()) -452 && collectionContainsString(dependency.getVendorEvidence(), entry.getVendor())) { -453 //&& collectionContainsVersion(dependency.getVersionEvidence(), entry.getVersion()) -454 isValid = true; -455 } -456 return isValid; -457 } -458 -459 /** -460 * Used to determine if the EvidenceCollection contains a specific string. -461 * -462 * @param ec an EvidenceCollection -463 * @param text the text to search for -464 * @return whether or not the EvidenceCollection contains the string -465 */ -466 private boolean collectionContainsString(EvidenceCollection ec, String text) { -467 //TODO - likely need to change the split... not sure if this will work for CPE with special chars -468 if (text == null) { -469 return false; -470 } -471 final String[] words = text.split("[\\s_-]"); -472 final List<String> list = new ArrayList<String>(); -473 String tempWord = null; -474 for (String word : words) { -475 /* -476 single letter words should be concatenated with the next word. -477 so { "m", "core", "sample" } -> { "mcore", "sample" } -478 */ -479 if (tempWord != null) { -480 list.add(tempWord + word); -481 tempWord = null; -482 } else if (word.length() <= 2) { -483 tempWord = word; -484 } else { -485 list.add(word); -486 } -487 } -488 if (tempWord != null) { -489 if (!list.isEmpty()) { -490 final String tmp = list.get(list.size() - 1) + tempWord; -491 list.add(tmp); -492 } else { -493 list.add(tempWord); -494 } -495 } -496 if (list.isEmpty()) { -497 return false; -498 } -499 boolean contains = true; -500 for (String word : list) { -501 contains &= ec.containsUsedString(word); -502 } -503 return contains; -504 } -505 -506 /** -507 * Analyzes a dependency and attempts to determine if there are any CPE -508 * identifiers for this dependency. -509 * -510 * @param dependency The Dependency to analyze. -511 * @param engine The analysis engine -512 * @throws AnalysisException is thrown if there is an issue analyzing the -513 * dependency. -514 */ -515 @Override -516 public synchronized void analyze(Dependency dependency, Engine engine) throws AnalysisException { -517 try { -518 determineCPE(dependency); -519 } catch (CorruptIndexException ex) { -520 throw new AnalysisException("CPE Index is corrupt.", ex); -521 } catch (IOException ex) { -522 throw new AnalysisException("Failure opening the CPE Index.", ex); -523 } catch (ParseException ex) { -524 throw new AnalysisException("Unable to parse the generated Lucene query for this dependency.", ex); -525 } -526 } -527 -528 /** -529 * Retrieves a list of CPE values from the CveDB based on the vendor and -530 * product passed in. The list is then validated to find only CPEs that are -531 * valid for the given dependency. It is possible that the CPE identified is -532 * a best effort "guess" based on the vendor, product, and version -533 * information. -534 * -535 * @param dependency the Dependency being analyzed -536 * @param vendor the vendor for the CPE being analyzed -537 * @param product the product for the CPE being analyzed -538 * @param currentConfidence the current confidence being used during -539 * analysis -540 * @return <code>true</code> if an identifier was added to the dependency; -541 * otherwise <code>false</code> -542 * @throws UnsupportedEncodingException is thrown if UTF-8 is not supported -543 */ -544 protected boolean determineIdentifiers(Dependency dependency, String vendor, String product, -545 Confidence currentConfidence) throws UnsupportedEncodingException { -546 final Set<VulnerableSoftware> cpes = cve.getCPEs(vendor, product); -547 DependencyVersion bestGuess = new DependencyVersion("-"); -548 Confidence bestGuessConf = null; -549 boolean hasBroadMatch = false; -550 final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>(); -551 -552 //TODO the following algorithm incorrectly identifies things as a lower version -553 // if there lower confidence evidence when the current (highest) version number -554 // is newer then anything in the NVD. -555 for (Confidence conf : Confidence.values()) { -556 for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) { -557 final DependencyVersion evVer = DependencyVersionUtil.parseVersion(evidence.getValue()); -558 if (evVer == null) { -559 continue; -560 } -561 for (VulnerableSoftware vs : cpes) { -562 DependencyVersion dbVer; -563 if (vs.getUpdate() != null && !vs.getUpdate().isEmpty()) { -564 dbVer = DependencyVersionUtil.parseVersion(vs.getVersion() + '.' + vs.getUpdate()); -565 } else { -566 dbVer = DependencyVersionUtil.parseVersion(vs.getVersion()); -567 } -568 if (dbVer == null) { //special case, no version specified - everything is vulnerable -569 hasBroadMatch = true; -570 final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8")); -571 final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.BROAD_MATCH, conf); -572 collected.add(match); -573 } else if (evVer.equals(dbVer)) { //yeah! exact match -574 final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8")); -575 final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf); -576 collected.add(match); -577 -578 //TODO the following isn't quite right is it? need to think about this guessing game a bit more. -579 } else if (evVer.getVersionParts().size() <= dbVer.getVersionParts().size() -580 && evVer.matchesAtLeastThreeLevels(dbVer)) { -581 if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) { -582 if (bestGuess.getVersionParts().size() < dbVer.getVersionParts().size()) { -583 bestGuess = dbVer; -584 bestGuessConf = conf; -585 } -586 } -587 } -588 } -589 if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) { -590 if (bestGuess.getVersionParts().size() < evVer.getVersionParts().size()) { -591 bestGuess = evVer; -592 bestGuessConf = conf; -593 } -594 } -595 } -596 } -597 final String cpeName = String.format("cpe:/a:%s:%s:%s", vendor, product, bestGuess.toString()); -598 String url = null; -599 if (hasBroadMatch) { //if we have a broad match we can add the URL to the best guess. -600 final String cpeUrlName = String.format("cpe:/a:%s:%s", vendor, product); -601 url = String.format(NVD_SEARCH_URL, URLEncoder.encode(cpeUrlName, "UTF-8")); -602 } -603 if (bestGuessConf == null) { -604 bestGuessConf = Confidence.LOW; -605 } -606 final IdentifierMatch match = new IdentifierMatch("cpe", cpeName, url, IdentifierConfidence.BEST_GUESS, bestGuessConf); -607 collected.add(match); -608 -609 Collections.sort(collected); -610 final IdentifierConfidence bestIdentifierQuality = collected.get(0).getConfidence(); -611 final Confidence bestEvidenceQuality = collected.get(0).getEvidenceConfidence(); -612 boolean identifierAdded = false; -613 for (IdentifierMatch m : collected) { -614 if (bestIdentifierQuality.equals(m.getConfidence()) -615 && bestEvidenceQuality.equals(m.getEvidenceConfidence())) { -616 final Identifier i = m.getIdentifier(); -617 if (bestIdentifierQuality == IdentifierConfidence.BEST_GUESS) { -618 i.setConfidence(Confidence.LOW); -619 } else { -620 i.setConfidence(bestEvidenceQuality); -621 } -622 dependency.addIdentifier(i); -623 identifierAdded = true; -624 } -625 } -626 return identifierAdded; -627 } -628 -629 /** -630 * The confidence whether the identifier is an exact match, or a best guess. -631 */ -632 private enum IdentifierConfidence { -633 -634 /** -635 * An exact match for the CPE. -636 */ -637 EXACT_MATCH, -638 /** -639 * A best guess for the CPE. -640 */ -641 BEST_GUESS, -642 /** -643 * The entire vendor/product group must be added (without a guess at -644 * version) because there is a CVE with a VS that only specifies -645 * vendor/product. -646 */ -647 BROAD_MATCH -648 } -649 -650 /** -651 * A simple object to hold an identifier and carry information about the -652 * confidence in the identifier. -653 */ -654 private static class IdentifierMatch implements Comparable<IdentifierMatch> { -655 -656 /** -657 * Constructs an IdentifierMatch. -658 * -659 * @param type the type of identifier (such as CPE) -660 * @param value the value of the identifier -661 * @param url the URL of the identifier -662 * @param identifierConfidence the confidence in the identifier: best -663 * guess or exact match -664 * @param evidenceConfidence the confidence of the evidence used to find -665 * the identifier -666 */ -667 IdentifierMatch(String type, String value, String url, IdentifierConfidence identifierConfidence, Confidence evidenceConfidence) { -668 this.identifier = new Identifier(type, value, url); -669 this.confidence = identifierConfidence; -670 this.evidenceConfidence = evidenceConfidence; -671 } -672 //<editor-fold defaultstate="collapsed" desc="Property implementations: evidenceConfidence, confidence, identifier"> -673 /** -674 * The confidence in the evidence used to identify this match. -675 */ -676 private Confidence evidenceConfidence; -677 -678 /** -679 * Get the value of evidenceConfidence -680 * -681 * @return the value of evidenceConfidence -682 */ -683 public Confidence getEvidenceConfidence() { -684 return evidenceConfidence; -685 } -686 -687 /** -688 * Set the value of evidenceConfidence -689 * -690 * @param evidenceConfidence new value of evidenceConfidence -691 */ -692 public void setEvidenceConfidence(Confidence evidenceConfidence) { -693 this.evidenceConfidence = evidenceConfidence; -694 } -695 /** -696 * The confidence whether this is an exact match, or a best guess. -697 */ -698 private IdentifierConfidence confidence; -699 -700 /** -701 * Get the value of confidence. -702 * -703 * @return the value of confidence -704 */ -705 public IdentifierConfidence getConfidence() { -706 return confidence; -707 } -708 -709 /** -710 * Set the value of confidence. -711 * -712 * @param confidence new value of confidence -713 */ -714 public void setConfidence(IdentifierConfidence confidence) { -715 this.confidence = confidence; -716 } -717 /** -718 * The CPE identifier. -719 */ -720 private Identifier identifier; -721 -722 /** -723 * Get the value of identifier. -724 * -725 * @return the value of identifier -726 */ -727 public Identifier getIdentifier() { -728 return identifier; -729 } -730 -731 /** -732 * Set the value of identifier. -733 * -734 * @param identifier new value of identifier -735 */ -736 public void setIdentifier(Identifier identifier) { -737 this.identifier = identifier; -738 } -739 //</editor-fold> -740 //<editor-fold defaultstate="collapsed" desc="Standard implementations of toString, hashCode, and equals"> -741 -742 /** -743 * Standard toString() implementation. -744 * -745 * @return the string representation of the object -746 */ -747 @Override -748 public String toString() { -749 return "IdentifierMatch{" + "evidenceConfidence=" + evidenceConfidence -750 + ", confidence=" + confidence + ", identifier=" + identifier + '}'; -751 } -752 -753 /** -754 * Standard hashCode() implementation. -755 * -756 * @return the hashCode -757 */ -758 @Override -759 public int hashCode() { -760 int hash = 5; -761 hash = 97 * hash + (this.evidenceConfidence != null ? this.evidenceConfidence.hashCode() : 0); -762 hash = 97 * hash + (this.confidence != null ? this.confidence.hashCode() : 0); -763 hash = 97 * hash + (this.identifier != null ? this.identifier.hashCode() : 0); -764 return hash; -765 } -766 -767 /** -768 * Standard equals implementation. -769 * -770 * @param obj the object to compare -771 * @return true if the objects are equal, otherwise false -772 */ -773 @Override -774 public boolean equals(Object obj) { -775 if (obj == null) { -776 return false; -777 } -778 if (getClass() != obj.getClass()) { -779 return false; -780 } -781 final IdentifierMatch other = (IdentifierMatch) obj; -782 if (this.evidenceConfidence != other.evidenceConfidence) { -783 return false; -784 } -785 if (this.confidence != other.confidence) { -786 return false; -787 } -788 if (this.identifier != other.identifier && (this.identifier == null || !this.identifier.equals(other.identifier))) { -789 return false; -790 } -791 return true; -792 } -793 //</editor-fold> -794 -795 /** -796 * Standard implementation of compareTo that compares identifier -797 * confidence, evidence confidence, and then the identifier. -798 * -799 * @param o the IdentifierMatch to compare to -800 * @return the natural ordering of IdentifierMatch -801 */ -802 @Override -803 public int compareTo(IdentifierMatch o) { -804 int conf = this.confidence.compareTo(o.confidence); -805 if (conf == 0) { -806 conf = this.evidenceConfidence.compareTo(o.evidenceConfidence); -807 if (conf == 0) { -808 conf = identifier.compareTo(o.identifier); -809 } -810 } -811 return conf; -812 } -813 } -814 } +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"); +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 }
    diff --git a/xref/org/owasp/dependencycheck/analyzer/CentralAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/CentralAnalyzer.html index 3fc3de35e..886f0d5d1 100644 --- a/xref/org/owasp/dependencycheck/analyzer/CentralAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/CentralAnalyzer.html @@ -237,23 +237,24 @@ 229 LOGGER.warn("Unable to download pom.xml for {} from Central; " 230 + "this could result in undetected CPE/CVEs.", dependency.getFileName()); 231 } finally { -232 if (pomFile != null && !FileUtils.deleteQuietly(pomFile)) { -233 pomFile.deleteOnExit(); -234 } -235 } -236 } -237 -238 } -239 } catch (IllegalArgumentException iae) { -240 LOGGER.info("invalid sha1-hash on {}", dependency.getFileName()); -241 } catch (FileNotFoundException fnfe) { -242 LOGGER.debug("Artifact not found in repository: '{}", dependency.getFileName()); -243 } catch (IOException ioe) { -244 LOGGER.debug("Could not connect to Central search", ioe); -245 errorFlag = true; -246 } -247 } -248 } +232 if (pomFile != null && pomFile.exists() && !FileUtils.deleteQuietly(pomFile)) { +233 LOGGER.debug("Failed to delete temporary pom file {}", pomFile.toString()); +234 pomFile.deleteOnExit(); +235 } +236 } +237 } +238 +239 } +240 } catch (IllegalArgumentException iae) { +241 LOGGER.info("invalid sha1-hash on {}", dependency.getFileName()); +242 } catch (FileNotFoundException fnfe) { +243 LOGGER.debug("Artifact not found in repository: '{}", dependency.getFileName()); +244 } catch (IOException ioe) { +245 LOGGER.debug("Could not connect to Central search", ioe); +246 errorFlag = true; +247 } +248 } +249 }
    diff --git a/xref/org/owasp/dependencycheck/analyzer/CocoaPodsAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/CocoaPodsAnalyzer.html new file mode 100644 index 000000000..7327e372c --- /dev/null +++ b/xref/org/owasp/dependencycheck/analyzer/CocoaPodsAnalyzer.html @@ -0,0 +1,218 @@ + + + +CocoaPodsAnalyzer 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 IBM Corporation. All Rights Reserved.
    +17   */
    +18  package org.owasp.dependencycheck.analyzer;
    +19  
    +20  import java.io.File;
    +21  import java.io.FileFilter;
    +22  import java.io.IOException;
    +23  import java.nio.charset.Charset;
    +24  import java.util.regex.Matcher;
    +25  import java.util.regex.Pattern;
    +26  
    +27  import org.apache.commons.io.FileUtils;
    +28  import org.owasp.dependencycheck.Engine;
    +29  import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
    +30  import org.owasp.dependencycheck.dependency.Confidence;
    +31  import org.owasp.dependencycheck.dependency.Dependency;
    +32  import org.owasp.dependencycheck.dependency.EvidenceCollection;
    +33  import org.owasp.dependencycheck.utils.FileFilterBuilder;
    +34  import org.owasp.dependencycheck.utils.Settings;
    +35  
    +36  /**
    +37   * This analyzer is used to analyze SWIFT and Objective-C packages by collecting
    +38   * information from .podspec files. CocoaPods dependency manager see
    +39   * https://cocoapods.org/.
    +40   *
    +41   * @author Bianca Jiang (https://twitter.com/biancajiang)
    +42   */
    +43  @Experimental
    +44  public class CocoaPodsAnalyzer extends AbstractFileTypeAnalyzer {
    +45  
    +46      /**
    +47       * The logger.
    +48       */
    +49  //    private static final Logger LOGGER = LoggerFactory.getLogger(CocoaPodsAnalyzer.class);
    +50      /**
    +51       * The name of the analyzer.
    +52       */
    +53      private static final String ANALYZER_NAME = "CocoaPods Package Analyzer";
    +54  
    +55      /**
    +56       * The phase that this analyzer is intended to run in.
    +57       */
    +58      private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
    +59  
    +60      /**
    +61       * The file name to scan.
    +62       */
    +63      public static final String PODSPEC = "podspec";
    +64      /**
    +65       * Filter that detects files named "*.podspec".
    +66       */
    +67      private static final FileFilter PODSPEC_FILTER = FileFilterBuilder.newInstance().addExtensions(PODSPEC).build();
    +68  
    +69      /**
    +70       * The capture group #1 is the block variable. e.g. "Pod::Spec.new do
    +71       * |spec|"
    +72       */
    +73      private static final Pattern PODSPEC_BLOCK_PATTERN = Pattern.compile("Pod::Spec\\.new\\s+?do\\s+?\\|(.+?)\\|");
    +74  
    +75      /**
    +76       * Returns the FileFilter
    +77       *
    +78       * @return the FileFilter
    +79       */
    +80      @Override
    +81      protected FileFilter getFileFilter() {
    +82          return PODSPEC_FILTER;
    +83      }
    +84  
    +85      @Override
    +86      protected void initializeFileTypeAnalyzer() {
    +87          // NO-OP
    +88      }
    +89  
    +90      /**
    +91       * Returns the name of the analyzer.
    +92       *
    +93       * @return the name of the analyzer.
    +94       */
    +95      @Override
    +96      public String getName() {
    +97          return ANALYZER_NAME;
    +98      }
    +99  
    +100     /**
    +101      * Returns the phase that the analyzer is intended to run in.
    +102      *
    +103      * @return the phase that the analyzer is intended to run in.
    +104      */
    +105     @Override
    +106     public AnalysisPhase getAnalysisPhase() {
    +107         return ANALYSIS_PHASE;
    +108     }
    +109 
    +110     /**
    +111      * Returns the key used in the properties file to reference the analyzer's
    +112      * enabled property.
    +113      *
    +114      * @return the analyzer's enabled property setting key
    +115      */
    +116     @Override
    +117     protected String getAnalyzerEnabledSettingKey() {
    +118         return Settings.KEYS.ANALYZER_COCOAPODS_ENABLED;
    +119     }
    +120 
    +121     @Override
    +122     protected void analyzeFileType(Dependency dependency, Engine engine)
    +123             throws AnalysisException {
    +124 
    +125         String contents;
    +126         try {
    +127             contents = FileUtils.readFileToString(dependency.getActualFile(), Charset.defaultCharset());
    +128         } catch (IOException e) {
    +129             throw new AnalysisException(
    +130                     "Problem occurred while reading dependency file.", e);
    +131         }
    +132         final Matcher matcher = PODSPEC_BLOCK_PATTERN.matcher(contents);
    +133         if (matcher.find()) {
    +134             contents = contents.substring(matcher.end());
    +135             final String blockVariable = matcher.group(1);
    +136 
    +137             final EvidenceCollection vendor = dependency.getVendorEvidence();
    +138             final EvidenceCollection product = dependency.getProductEvidence();
    +139             final EvidenceCollection version = dependency.getVersionEvidence();
    +140 
    +141             final String name = addStringEvidence(product, contents, blockVariable, "name", "name", Confidence.HIGHEST);
    +142             if (!name.isEmpty()) {
    +143                 vendor.addEvidence(PODSPEC, "name_project", name, Confidence.HIGHEST);
    +144             }
    +145             addStringEvidence(product, contents, blockVariable, "summary", "summary", Confidence.HIGHEST);
    +146 
    +147             addStringEvidence(vendor, contents, blockVariable, "author", "authors?", Confidence.HIGHEST);
    +148             addStringEvidence(vendor, contents, blockVariable, "homepage", "homepage", Confidence.HIGHEST);
    +149             addStringEvidence(vendor, contents, blockVariable, "license", "licen[cs]es?", Confidence.HIGHEST);
    +150 
    +151             addStringEvidence(version, contents, blockVariable, "version", "version", Confidence.HIGHEST);
    +152         }
    +153 
    +154         setPackagePath(dependency);
    +155     }
    +156 
    +157     /**
    +158      * Extracts evidence from the contents and adds it to the given evidence
    +159      * collection.
    +160      *
    +161      * @param evidences the evidence collection to update
    +162      * @param contents the text to extract evidence from
    +163      * @param blockVariable the block variable within the content to search for
    +164      * @param field the name of the field being searched for
    +165      * @param fieldPattern the field pattern within the contents to search for
    +166      * @param confidence the confidence level of the evidence if found
    +167      * @return the string that was added as evidence
    +168      */
    +169     private String addStringEvidence(EvidenceCollection evidences, String contents,
    +170             String blockVariable, String field, String fieldPattern, Confidence confidence) {
    +171         String value = "";
    +172 
    +173         //capture array value between [ ]
    +174         final Matcher arrayMatcher = Pattern.compile(
    +175                 String.format("\\s*?%s\\.%s\\s*?=\\s*?\\{\\s*?(.*?)\\s*?\\}", blockVariable, fieldPattern),
    +176                 Pattern.CASE_INSENSITIVE).matcher(contents);
    +177         if (arrayMatcher.find()) {
    +178             value = arrayMatcher.group(1);
    +179         } else { //capture single value between quotes
    +180             final Matcher matcher = Pattern.compile(
    +181                     String.format("\\s*?%s\\.%s\\s*?=\\s*?(['\"])(.*?)\\1", blockVariable, fieldPattern),
    +182                     Pattern.CASE_INSENSITIVE).matcher(contents);
    +183             if (matcher.find()) {
    +184                 value = matcher.group(2);
    +185             }
    +186         }
    +187         if (value.length() > 0) {
    +188             evidences.addEvidence(PODSPEC, field, value, confidence);
    +189         }
    +190         return value;
    +191     }
    +192 
    +193     /**
    +194      * Sets the package path on the given dependency.
    +195      *
    +196      * @param dep the dependency to update
    +197      */
    +198     private void setPackagePath(Dependency dep) {
    +199         final File file = new File(dep.getFilePath());
    +200         final String parent = file.getParent();
    +201         if (parent != null) {
    +202             dep.setPackagePath(parent);
    +203         }
    +204     }
    +205 }
    +
    +
    + + + diff --git a/xref/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.html index b8b973dd7..0ab088c9a 100644 --- a/xref/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.html @@ -125,393 +125,446 @@ 117 final ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex()); 118 while (subIterator.hasNext()) { 119 final Dependency nextDependency = subIterator.next(); -120 if (hashesMatch(dependency, nextDependency) && !containedInWar(dependency.getFilePath()) -121 && !containedInWar(nextDependency.getFilePath())) { -122 if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) { -123 mergeDependencies(dependency, nextDependency, dependenciesToRemove); -124 } else { -125 mergeDependencies(nextDependency, dependency, dependenciesToRemove); -126 break; //since we merged into the next dependency - skip forward to the next in mainIterator -127 } -128 } else if (isShadedJar(dependency, nextDependency)) { -129 if (dependency.getFileName().toLowerCase().endsWith("pom.xml")) { -130 mergeDependencies(nextDependency, dependency, dependenciesToRemove); -131 nextDependency.getRelatedDependencies().remove(dependency); -132 break; -133 } else { -134 mergeDependencies(dependency, nextDependency, dependenciesToRemove); -135 dependency.getRelatedDependencies().remove(nextDependency); -136 } -137 } else if (cpeIdentifiersMatch(dependency, nextDependency) -138 && hasSameBasePath(dependency, nextDependency) -139 && fileNameMatch(dependency, nextDependency)) { -140 if (isCore(dependency, nextDependency)) { -141 mergeDependencies(dependency, nextDependency, dependenciesToRemove); -142 } else { -143 mergeDependencies(nextDependency, dependency, dependenciesToRemove); -144 break; //since we merged into the next dependency - skip forward to the next in mainIterator -145 } -146 } else if (isSameRubyGem(dependency, nextDependency)) { -147 final Dependency main = getMainGemspecDependency(dependency, nextDependency); +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) { 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 } -155 } -156 } -157 } -158 //removing dependencies here as ensuring correctness and avoiding ConcurrentUpdateExceptions -159 // was difficult because of the inner iterator. -160 engine.getDependencies().removeAll(dependenciesToRemove); -161 } -162 } -163 -164 /** -165 * Adds the relatedDependency to the dependency's related dependencies. -166 * -167 * @param dependency the main dependency -168 * @param relatedDependency a collection of dependencies to be removed from -169 * the main analysis loop, this is the source of dependencies to remove -170 * @param dependenciesToRemove a collection of dependencies that will be -171 * removed from the main analysis loop, this function adds to this -172 * collection -173 */ -174 private void mergeDependencies(final Dependency dependency, final Dependency relatedDependency, final Set<Dependency> dependenciesToRemove) { -175 dependency.addRelatedDependency(relatedDependency); -176 final Iterator<Dependency> i = relatedDependency.getRelatedDependencies().iterator(); -177 while (i.hasNext()) { -178 dependency.addRelatedDependency(i.next()); -179 i.remove(); -180 } -181 if (dependency.getSha1sum().equals(relatedDependency.getSha1sum())) { -182 dependency.addAllProjectReferences(relatedDependency.getProjectReferences()); -183 } -184 dependenciesToRemove.add(relatedDependency); -185 } -186 -187 /** -188 * Attempts to trim a maven repo to a common base path. This is typically -189 * [drive]\[repo_location]\repository\[path1]\[path2]. -190 * -191 * @param path the path to trim -192 * @return a string representing the base path. -193 */ -194 private String getBaseRepoPath(final String path) { -195 int pos = path.indexOf("repository" + File.separator) + 11; -196 if (pos < 0) { -197 return path; -198 } -199 int tmp = path.indexOf(File.separator, pos); -200 if (tmp <= 0) { -201 return path; -202 } -203 if (tmp > 0) { -204 pos = tmp + 1; +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 tmp = path.indexOf(File.separator, pos); -207 if (tmp > 0) { -208 pos = tmp + 1; +206 int tmp = path.indexOf(File.separator, pos); +207 if (tmp <= 0) { +208 return path; 209 } -210 return path.substring(0, pos); -211 } -212 -213 /** -214 * Returns true if the file names (and version if it exists) of the two -215 * dependencies are sufficiently similar. -216 * -217 * @param dependency1 a dependency2 to compare -218 * @param dependency2 a dependency2 to compare -219 * @return true if the identifiers in the two supplied dependencies are -220 * equal -221 */ -222 private boolean fileNameMatch(Dependency dependency1, Dependency dependency2) { -223 if (dependency1 == null || dependency1.getFileName() == null -224 || dependency2 == null || dependency2.getFileName() == null) { -225 return false; -226 } -227 final String fileName1 = dependency1.getActualFile().getName(); -228 final String fileName2 = dependency2.getActualFile().getName(); -229 -230 //version check -231 final DependencyVersion version1 = DependencyVersionUtil.parseVersion(fileName1); -232 final DependencyVersion version2 = DependencyVersionUtil.parseVersion(fileName2); -233 if (version1 != null && version2 != null && !version1.equals(version2)) { -234 return false; -235 } +210 if (tmp > 0) { +211 pos = tmp + 1; +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 //filename check -238 final Matcher match1 = STARTING_TEXT_PATTERN.matcher(fileName1); -239 final Matcher match2 = STARTING_TEXT_PATTERN.matcher(fileName2); -240 if (match1.find() && match2.find()) { -241 return match1.group().equals(match2.group()); +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 return false; -245 } -246 -247 /** -248 * Returns true if the CPE identifiers in the two supplied dependencies are -249 * equal. -250 * -251 * @param dependency1 a dependency2 to compare -252 * @param dependency2 a dependency2 to compare -253 * @return true if the identifiers in the two supplied dependencies are -254 * equal -255 */ -256 private boolean cpeIdentifiersMatch(Dependency dependency1, Dependency dependency2) { -257 if (dependency1 == null || dependency1.getIdentifiers() == null -258 || dependency2 == null || dependency2.getIdentifiers() == null) { -259 return false; -260 } -261 boolean matches = false; -262 int cpeCount1 = 0; -263 int cpeCount2 = 0; -264 for (Identifier i : dependency1.getIdentifiers()) { -265 if ("cpe".equals(i.getType())) { -266 cpeCount1 += 1; -267 } -268 } -269 for (Identifier i : dependency2.getIdentifiers()) { -270 if ("cpe".equals(i.getType())) { -271 cpeCount2 += 1; -272 } -273 } -274 if (cpeCount1 > 0 && cpeCount1 == cpeCount2) { -275 for (Identifier i : dependency1.getIdentifiers()) { -276 if ("cpe".equals(i.getType())) { -277 matches |= dependency2.getIdentifiers().contains(i); -278 if (!matches) { -279 break; -280 } -281 } -282 } -283 } -284 LOGGER.debug("IdentifiersMatch={} ({}, {})", matches, dependency1.getFileName(), dependency2.getFileName()); -285 return matches; -286 } -287 -288 /** -289 * Determines if the two dependencies have the same base path. -290 * -291 * @param dependency1 a Dependency object -292 * @param dependency2 a Dependency object -293 * @return true if the base paths of the dependencies are identical -294 */ -295 private boolean hasSameBasePath(Dependency dependency1, Dependency dependency2) { -296 if (dependency1 == null || dependency2 == null) { -297 return false; -298 } -299 final File lFile = new File(dependency1.getFilePath()); -300 String left = lFile.getParent(); -301 final File rFile = new File(dependency2.getFilePath()); -302 String right = rFile.getParent(); -303 if (left == null) { -304 return right == null; +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) { +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; 305 } -306 if (left.equalsIgnoreCase(right)) { -307 return true; -308 } -309 if (left.matches(".*[/\\\\]repository[/\\\\].*") && right.matches(".*[/\\\\]repository[/\\\\].*")) { -310 left = getBaseRepoPath(left); -311 right = getBaseRepoPath(right); -312 } -313 if (left.equalsIgnoreCase(right)) { -314 return true; -315 } -316 //new code -317 for (Dependency child : dependency2.getRelatedDependencies()) { -318 if (hasSameBasePath(dependency1, child)) { -319 return true; -320 } -321 } -322 return false; -323 } -324 -325 /** -326 * Bundling Ruby gems that are identified from different .gemspec files but -327 * denote the same package path. This happens when Ruby bundler installs an -328 * application's dependencies by running "bundle install". -329 * -330 * @param dependency1 dependency to compare -331 * @param dependency2 dependency to compare -332 * @return true if the the dependencies being analyzed appear to be the -333 * same; otherwise false -334 */ -335 private boolean isSameRubyGem(Dependency dependency1, Dependency dependency2) { -336 if (dependency1 == null || dependency2 == null -337 || !dependency1.getFileName().endsWith(".gemspec") -338 || !dependency2.getFileName().endsWith(".gemspec") -339 || dependency1.getPackagePath() == null -340 || dependency2.getPackagePath() == null) { -341 return false; -342 } -343 if (dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath())) { -344 return true; -345 } -346 -347 return false; -348 } -349 -350 /** -351 * Ruby gems installed by "bundle install" can have zero or more *.gemspec -352 * files, all of which have the same packagePath and should be grouped. If -353 * one of these gemspec is from <parent>/specifications/*.gemspec, because -354 * it is a stub with fully resolved gem meta-data created by Ruby bundler, -355 * this dependency should be the main one. Otherwise, use dependency2 as -356 * main. -357 * -358 * This method returns null if any dependency is not from *.gemspec, or the -359 * two do not have the same packagePath. In this case, they should not be -360 * grouped. -361 * -362 * @param dependency1 dependency to compare -363 * @param dependency2 dependency to compare -364 * @return the main dependency; or null if a gemspec is not included in the -365 * analysis -366 */ -367 private Dependency getMainGemspecDependency(Dependency dependency1, Dependency dependency2) { -368 if (isSameRubyGem(dependency1, dependency2)) { -369 final File lFile = dependency1.getActualFile(); -370 final File left = lFile.getParentFile(); -371 if (left != null && left.getName().equalsIgnoreCase("specifications")) { -372 return dependency1; -373 } -374 return dependency2; -375 } -376 return null; -377 } -378 -379 /** -380 * This is likely a very broken attempt at determining if the 'left' -381 * dependency is the 'core' library in comparison to the 'right' library. -382 * -383 * @param left the dependency to test -384 * @param right the dependency to test against -385 * @return a boolean indicating whether or not the left dependency should be -386 * considered the "core" version. -387 */ -388 boolean isCore(Dependency left, Dependency right) { -389 final String leftName = left.getFileName().toLowerCase(); -390 final String rightName = right.getFileName().toLowerCase(); -391 -392 final boolean returnVal; -393 if (!rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") -394 || rightName.contains("core") && !leftName.contains("core") -395 || rightName.contains("kernel") && !leftName.contains("kernel")) { -396 returnVal = false; -397 } else if (rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && !leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") -398 || !rightName.contains("core") && leftName.contains("core") -399 || !rightName.contains("kernel") && leftName.contains("kernel")) { -400 returnVal = true; -401 // } else if (leftName.matches(".*struts2\\-core.*") && rightName.matches(".*xwork\\-core.*")) { -402 // returnVal = true; -403 // } else if (rightName.matches(".*struts2\\-core.*") && leftName.matches(".*xwork\\-core.*")) { -404 // returnVal = false; -405 } else { -406 /* -407 * considered splitting the names up and comparing the components, -408 * but decided that the file name length should be sufficient as the -409 * "core" component, if this follows a normal naming protocol should -410 * be shorter: -411 * axis2-saaj-1.4.1.jar -412 * axis2-1.4.1.jar <----- -413 * axis2-kernel-1.4.1.jar -414 */ -415 returnVal = leftName.length() <= rightName.length(); -416 } -417 LOGGER.debug("IsCore={} ({}, {})", returnVal, left.getFileName(), right.getFileName()); -418 return returnVal; -419 } -420 -421 /** -422 * Compares the SHA1 hashes of two dependencies to determine if they are -423 * equal. -424 * -425 * @param dependency1 a dependency object to compare -426 * @param dependency2 a dependency object to compare -427 * @return true if the sha1 hashes of the two dependencies match; otherwise -428 * false -429 */ -430 private boolean hashesMatch(Dependency dependency1, Dependency dependency2) { -431 if (dependency1 == null || dependency2 == null || dependency1.getSha1sum() == null || dependency2.getSha1sum() == null) { -432 return false; -433 } -434 return dependency1.getSha1sum().equals(dependency2.getSha1sum()); -435 } -436 -437 /** -438 * Determines if the jar is shaded and the created pom.xml identified the -439 * same CPE as the jar - if so, the pom.xml dependency should be removed. -440 * -441 * @param dependency a dependency to check -442 * @param nextDependency another dependency to check -443 * @return true if on of the dependencies is a pom.xml and the identifiers -444 * between the two collections match; otherwise false -445 */ -446 private boolean isShadedJar(Dependency dependency, Dependency nextDependency) { -447 final String mainName = dependency.getFileName().toLowerCase(); -448 final String nextName = nextDependency.getFileName().toLowerCase(); -449 if (mainName.endsWith(".jar") && nextName.endsWith("pom.xml")) { -450 return dependency.getIdentifiers().containsAll(nextDependency.getIdentifiers()); -451 } else if (nextName.endsWith(".jar") && mainName.endsWith("pom.xml")) { -452 return nextDependency.getIdentifiers().containsAll(dependency.getIdentifiers()); -453 } -454 return false; -455 } -456 -457 /** -458 * Determines which path is shortest; if path lengths are equal then we use -459 * compareTo of the string method to determine if the first path is smaller. -460 * -461 * @param left the first path to compare -462 * @param right the second path to compare -463 * @return <code>true</code> if the leftPath is the shortest; otherwise -464 * <code>false</code> -465 */ -466 protected boolean firstPathIsShortest(String left, String right) { -467 final String leftPath = left.replace('\\', '/'); -468 final String rightPath = right.replace('\\', '/'); -469 -470 final int leftCount = countChar(leftPath, '/'); -471 final int rightCount = countChar(rightPath, '/'); -472 if (leftCount == rightCount) { -473 return leftPath.compareTo(rightPath) <= 0; -474 } else { -475 return leftCount < rightCount; -476 } -477 } -478 -479 /** -480 * Counts the number of times the character is present in the string. -481 * -482 * @param string the string to count the characters in -483 * @param c the character to count -484 * @return the number of times the character is present in the string -485 */ -486 private int countChar(String string, char c) { -487 int count = 0; -488 final int max = string.length(); -489 for (int i = 0; i < max; i++) { -490 if (c == string.charAt(i)) { -491 count++; -492 } -493 } -494 return count; -495 } -496 -497 /** -498 * Checks if the given file path is contained within a war or ear file. -499 * -500 * @param filePath the file path to check -501 * @return true if the path contains '.war\' or '.ear\'. -502 */ -503 private boolean containedInWar(String filePath) { -504 return filePath == null ? false : filePath.matches(".*\\.(ear|war)[\\\\/].*"); -505 } -506 } +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 +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. +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> +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; +428 } +429 return null; +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. +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 }
    diff --git a/xref/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.html index 623b7e3ac..026d40df0 100644 --- a/xref/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.html @@ -78,52 +78,54 @@ 70 /** 71 * Python init files 72 */ -73 private static final NameFileFilter IGNORED_FILES = new NameFileFilter(new String[]{ -74 "__init__.py", -75 "__init__.pyc", -76 "__init__.pyo", -77 }); -78 -79 /** -80 * Collects information about the file name. -81 * -82 * @param dependency the dependency to analyze. -83 * @param engine the engine that is scanning the dependencies -84 * @throws AnalysisException is thrown if there is an error reading the JAR -85 * file. -86 */ -87 @Override -88 public void analyze(Dependency dependency, Engine engine) throws AnalysisException { -89 -90 //strip any path information that may get added by ArchiveAnalyzer, etc. -91 final File f = dependency.getActualFile(); -92 final String fileName = FilenameUtils.removeExtension(f.getName()); -93 -94 //add version evidence -95 final DependencyVersion version = DependencyVersionUtil.parseVersion(fileName); -96 if (version != null) { -97 // If the version number is just a number like 2 or 23, reduce the confidence -98 // a shade. This should hopefully correct for cases like log4j.jar or -99 // struts2-core.jar -100 if (version.getVersionParts() == null || version.getVersionParts().size() < 2) { -101 dependency.getVersionEvidence().addEvidence("file", "name", -102 version.toString(), Confidence.MEDIUM); -103 } else { -104 dependency.getVersionEvidence().addEvidence("file", "version", -105 version.toString(), Confidence.HIGHEST); -106 } -107 dependency.getVersionEvidence().addEvidence("file", "name", -108 fileName, Confidence.MEDIUM); -109 } -110 -111 if (!IGNORED_FILES.accept(f)) { -112 dependency.getProductEvidence().addEvidence("file", "name", -113 fileName, Confidence.HIGH); -114 dependency.getVendorEvidence().addEvidence("file", "name", -115 fileName, Confidence.HIGH); -116 } -117 } -118 } +73 //CSOFF: WhitespaceAfter +74 private static final NameFileFilter IGNORED_FILES = new NameFileFilter(new String[]{ +75 "__init__.py", +76 "__init__.pyc", +77 "__init__.pyo",}); +78 //CSON: WhitespaceAfter +79 +80 /** +81 * Collects information about the file name. +82 * +83 * @param dependency the dependency to analyze. +84 * @param engine the engine that is scanning the dependencies +85 * @throws AnalysisException is thrown if there is an error reading the JAR +86 * file. +87 */ +88 @Override +89 public void analyze(Dependency dependency, Engine engine) throws AnalysisException { +90 +91 //strip any path information that may get added by ArchiveAnalyzer, etc. +92 final File f = dependency.getActualFile(); +93 final String fileName = FilenameUtils.removeExtension(f.getName()); +94 +95 //add version evidence +96 final DependencyVersion version = DependencyVersionUtil.parseVersion(fileName); +97 final String packageName = DependencyVersionUtil.parsePreVersion(fileName); +98 if (version != null) { +99 // If the version number is just a number like 2 or 23, reduce the confidence +100 // a shade. This should hopefully correct for cases like log4j.jar or +101 // struts2-core.jar +102 if (version.getVersionParts() == null || version.getVersionParts().size() < 2) { +103 dependency.getVersionEvidence().addEvidence("file", "version", +104 version.toString(), Confidence.MEDIUM); +105 } else { +106 dependency.getVersionEvidence().addEvidence("file", "version", +107 version.toString(), Confidence.HIGHEST); +108 } +109 dependency.getVersionEvidence().addEvidence("file", "name", +110 packageName, Confidence.MEDIUM); +111 } +112 +113 if (!IGNORED_FILES.accept(f)) { +114 dependency.getProductEvidence().addEvidence("file", "name", +115 packageName, Confidence.HIGH); +116 dependency.getVendorEvidence().addEvidence("file", "name", +117 packageName, Confidence.HIGH); +118 } +119 } +120 }
    diff --git a/xref/org/owasp/dependencycheck/analyzer/HintAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/HintAnalyzer.html index 3cd496f97..0871b68a1 100644 --- a/xref/org/owasp/dependencycheck/analyzer/HintAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/HintAnalyzer.html @@ -162,203 +162,213 @@ 154 for (Evidence e : hint.getAddProduct()) { 155 dependency.getProductEvidence().addEvidence(e); 156 } -157 } -158 } -159 -160 final Iterator<Evidence> itr = dependency.getVendorEvidence().iterator(); -161 final List<Evidence> newEntries = new ArrayList<Evidence>(); -162 while (itr.hasNext()) { -163 final Evidence e = itr.next(); -164 for (VendorDuplicatingHintRule dhr : hints.getVendorDuplicatingHintRules()) { -165 if (dhr.getValue().equalsIgnoreCase(e.getValue(false))) { -166 newEntries.add(new Evidence(e.getSource() + " (hint)", -167 e.getName(), dhr.getDuplicate(), e.getConfidence())); -168 } -169 } -170 } -171 for (Evidence e : newEntries) { -172 dependency.getVendorEvidence().addEvidence(e); +157 for (Evidence e : hint.getAddVersion()) { +158 dependency.getVersionEvidence().addEvidence(e); +159 } +160 } +161 } +162 +163 final Iterator<Evidence> itr = dependency.getVendorEvidence().iterator(); +164 final List<Evidence> newEntries = new ArrayList<Evidence>(); +165 while (itr.hasNext()) { +166 final Evidence e = itr.next(); +167 for (VendorDuplicatingHintRule dhr : hints.getVendorDuplicatingHintRules()) { +168 if (dhr.getValue().equalsIgnoreCase(e.getValue(false))) { +169 newEntries.add(new Evidence(e.getSource() + " (hint)", +170 e.getName(), dhr.getDuplicate(), e.getConfidence())); +171 } +172 } 173 } -174 -175 //<editor-fold defaultstate="collapsed" desc="Old implementation"> -176 /* -177 final Evidence springTest1 = new Evidence("Manifest", -178 "Implementation-Title", -179 "Spring Framework", -180 Confidence.HIGH); -181 -182 final Evidence springTest2 = new Evidence("Manifest", -183 "Implementation-Title", -184 "org.springframework.core", -185 Confidence.HIGH); -186 -187 final Evidence springTest3 = new Evidence("Manifest", -188 "Implementation-Title", -189 "spring-core", -190 Confidence.HIGH); -191 -192 final Evidence springTest4 = new Evidence("jar", -193 "package name", -194 "springframework", -195 Confidence.LOW); -196 -197 final Evidence springSecurityTest1 = new Evidence("Manifest", -198 "Bundle-Name", -199 "Spring Security Core", -200 Confidence.MEDIUM); -201 -202 final Evidence springSecurityTest2 = new Evidence("pom", -203 "artifactid", -204 "spring-security-core", -205 Confidence.HIGH); -206 -207 final Evidence symfony = new Evidence("composer.lock", -208 "vendor", -209 "symfony", -210 Confidence.HIGHEST); -211 -212 final Evidence zendframeworkVendor = new Evidence("composer.lock", -213 "vendor", -214 "zendframework", -215 Confidence.HIGHEST); -216 -217 final Evidence zendframeworkProduct = new Evidence("composer.lock", -218 "product", -219 "zendframework", -220 Confidence.HIGHEST); -221 -222 //springsource/vware problem -223 final Set<Evidence> product = dependency.getProductEvidence().getEvidence(); -224 final Set<Evidence> vendor = dependency.getVendorEvidence().getEvidence(); -225 -226 if (product.contains(springTest1) || product.contains(springTest2) || product.contains(springTest3) -227 || (dependency.getFileName().contains("spring") && product.contains(springTest4))) { -228 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource spring framework", Confidence.HIGH); -229 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "SpringSource", Confidence.HIGH); -230 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH); -231 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "pivotal", Confidence.HIGH); -232 } -233 -234 if (vendor.contains(springTest4)) { -235 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource_spring_framework", Confidence.HIGH); -236 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH); -237 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "pivotal", Confidence.HIGH); -238 } -239 -240 if (product.contains(springSecurityTest1) || product.contains(springSecurityTest2)) { -241 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource_spring_security", Confidence.HIGH); -242 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "SpringSource", Confidence.HIGH); -243 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH); -244 } -245 -246 if (vendor.contains(symfony)) { -247 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "sensiolabs", Confidence.HIGHEST); -248 } -249 -250 if (vendor.contains(zendframeworkVendor)) { -251 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "zend", Confidence.HIGHEST); -252 } -253 -254 if (product.contains(zendframeworkProduct)) { -255 dependency.getProductEvidence().addEvidence("hint analyzer", "vendor", "zend_framework", Confidence.HIGHEST); -256 } -257 -258 //sun/oracle problem -259 final Iterator<Evidence> itr = dependency.getVendorEvidence().iterator(); -260 final List<Evidence> newEntries = new ArrayList<Evidence>(); -261 while (itr.hasNext()) { -262 final Evidence e = itr.next(); -263 if ("sun".equalsIgnoreCase(e.getValue(false))) { -264 final Evidence newEvidence = new Evidence(e.getSource() + " (hint)", e.getName(), "oracle", e.getConfidence()); -265 newEntries.add(newEvidence); -266 } else if ("oracle".equalsIgnoreCase(e.getValue(false))) { -267 final Evidence newEvidence = new Evidence(e.getSource() + " (hint)", e.getName(), "sun", e.getConfidence()); +174 for (Evidence e : newEntries) { +175 dependency.getVendorEvidence().addEvidence(e); +176 } +177 +178 //<editor-fold defaultstate="collapsed" desc="Old implementation"> +179 /* +180 final Evidence springTest1 = new Evidence("Manifest", +181 "Implementation-Title", +182 "Spring Framework", +183 Confidence.HIGH); +184 +185 final Evidence springTest2 = new Evidence("Manifest", +186 "Implementation-Title", +187 "org.springframework.core", +188 Confidence.HIGH); +189 +190 final Evidence springTest3 = new Evidence("Manifest", +191 "Implementation-Title", +192 "spring-core", +193 Confidence.HIGH); +194 +195 final Evidence springTest4 = new Evidence("jar", +196 "package name", +197 "springframework", +198 Confidence.LOW); +199 +200 final Evidence springSecurityTest1 = new Evidence("Manifest", +201 "Bundle-Name", +202 "Spring Security Core", +203 Confidence.MEDIUM); +204 +205 final Evidence springSecurityTest2 = new Evidence("pom", +206 "artifactid", +207 "spring-security-core", +208 Confidence.HIGH); +209 +210 final Evidence symfony = new Evidence("composer.lock", +211 "vendor", +212 "symfony", +213 Confidence.HIGHEST); +214 +215 final Evidence zendframeworkVendor = new Evidence("composer.lock", +216 "vendor", +217 "zendframework", +218 Confidence.HIGHEST); +219 +220 final Evidence zendframeworkProduct = new Evidence("composer.lock", +221 "product", +222 "zendframework", +223 Confidence.HIGHEST); +224 +225 //springsource/vware problem +226 final Set<Evidence> product = dependency.getProductEvidence().getEvidence(); +227 final Set<Evidence> vendor = dependency.getVendorEvidence().getEvidence(); +228 +229 if (product.contains(springTest1) || product.contains(springTest2) || product.contains(springTest3) +230 || (dependency.getFileName().contains("spring") && product.contains(springTest4))) { +231 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource spring framework", Confidence.HIGH); +232 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "SpringSource", Confidence.HIGH); +233 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH); +234 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "pivotal", Confidence.HIGH); +235 } +236 +237 if (vendor.contains(springTest4)) { +238 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource_spring_framework", Confidence.HIGH); +239 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH); +240 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "pivotal", Confidence.HIGH); +241 } +242 +243 if (product.contains(springSecurityTest1) || product.contains(springSecurityTest2)) { +244 dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource_spring_security", Confidence.HIGH); +245 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "SpringSource", Confidence.HIGH); +246 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH); +247 } +248 +249 if (vendor.contains(symfony)) { +250 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "sensiolabs", Confidence.HIGHEST); +251 } +252 +253 if (vendor.contains(zendframeworkVendor)) { +254 dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "zend", Confidence.HIGHEST); +255 } +256 +257 if (product.contains(zendframeworkProduct)) { +258 dependency.getProductEvidence().addEvidence("hint analyzer", "vendor", "zend_framework", Confidence.HIGHEST); +259 } +260 +261 //sun/oracle problem +262 final Iterator<Evidence> itr = dependency.getVendorEvidence().iterator(); +263 final List<Evidence> newEntries = new ArrayList<Evidence>(); +264 while (itr.hasNext()) { +265 final Evidence e = itr.next(); +266 if ("sun".equalsIgnoreCase(e.getValue(false))) { +267 final Evidence newEvidence = new Evidence(e.getSource() + " (hint)", e.getName(), "oracle", e.getConfidence()); 268 newEntries.add(newEvidence); -269 } -270 } -271 for (Evidence e : newEntries) { -272 dependency.getVendorEvidence().addEvidence(e); +269 } else if ("oracle".equalsIgnoreCase(e.getValue(false))) { +270 final Evidence newEvidence = new Evidence(e.getSource() + " (hint)", e.getName(), "sun", e.getConfidence()); +271 newEntries.add(newEvidence); +272 } 273 } -274 */ -275 //</editor-fold> -276 } -277 -278 /** -279 * Loads the hint rules file. -280 * -281 * @throws HintParseException thrown if the XML cannot be parsed. -282 */ -283 private void loadHintRules() throws HintParseException { -284 final HintParser parser = new HintParser(); -285 File file = null; -286 try { -287 hints = parser.parseHints(this.getClass().getClassLoader().getResourceAsStream(HINT_RULE_FILE_NAME)); -288 } catch (HintParseException ex) { -289 LOGGER.error("Unable to parse the base hint data file"); -290 LOGGER.debug("Unable to parse the base hint data file", ex); -291 } catch (SAXException ex) { +274 for (Evidence e : newEntries) { +275 dependency.getVendorEvidence().addEvidence(e); +276 } +277 */ +278 //</editor-fold> +279 } +280 +281 /** +282 * Loads the hint rules file. +283 * +284 * @throws HintParseException thrown if the XML cannot be parsed. +285 */ +286 private void loadHintRules() throws HintParseException { +287 final HintParser parser = new HintParser(); +288 File file = null; +289 try { +290 hints = parser.parseHints(this.getClass().getClassLoader().getResourceAsStream(HINT_RULE_FILE_NAME)); +291 } catch (HintParseException ex) { 292 LOGGER.error("Unable to parse the base hint data file"); 293 LOGGER.debug("Unable to parse the base hint data file", ex); -294 } -295 final String filePath = Settings.getString(Settings.KEYS.HINTS_FILE); -296 if (filePath == null) { -297 return; -298 } -299 boolean deleteTempFile = false; -300 try { -301 final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE); -302 if (uriRx.matcher(filePath).matches()) { -303 deleteTempFile = true; -304 file = FileUtils.getTempFile("hint", "xml"); -305 final URL url = new URL(filePath); -306 try { -307 Downloader.fetchFile(url, file, false); -308 } catch (DownloadFailedException ex) { -309 Downloader.fetchFile(url, file, true); -310 } -311 } else { -312 file = new File(filePath); -313 if (!file.exists()) { -314 final InputStream fromClasspath = this.getClass().getClassLoader().getResourceAsStream(filePath); -315 if (fromClasspath != null) { -316 deleteTempFile = true; -317 file = FileUtils.getTempFile("hint", "xml"); -318 try { -319 org.apache.commons.io.FileUtils.copyInputStreamToFile(fromClasspath, file); -320 } catch (IOException ex) { -321 throw new HintParseException("Unable to locate suppressions file in classpath", ex); -322 } -323 } -324 } -325 } -326 -327 if (file != null) { -328 try { -329 final Hints newHints = parser.parseHints(file); -330 hints.getHintRules().addAll(newHints.getHintRules()); -331 hints.getVendorDuplicatingHintRules().addAll(newHints.getVendorDuplicatingHintRules()); -332 LOGGER.debug("{} hint rules were loaded.", hints.getHintRules().size()); -333 LOGGER.debug("{} duplicating hint rules were loaded.", hints.getVendorDuplicatingHintRules().size()); -334 } catch (HintParseException ex) { -335 LOGGER.warn("Unable to parse hint rule xml file '{}'", file.getPath()); -336 LOGGER.warn(ex.getMessage()); -337 LOGGER.debug("", ex); -338 throw ex; -339 } -340 } -341 } catch (DownloadFailedException ex) { -342 throw new HintParseException("Unable to fetch the configured hint file", ex); -343 } catch (MalformedURLException ex) { -344 throw new HintParseException("Configured hint file has an invalid URL", ex); -345 } catch (IOException ex) { -346 throw new HintParseException("Unable to create temp file for hints", ex); -347 } finally { -348 if (deleteTempFile && file != null) { -349 FileUtils.delete(file); +294 } catch (SAXException ex) { +295 LOGGER.error("Unable to parse the base hint data file"); +296 LOGGER.debug("Unable to parse the base hint data file", ex); +297 } +298 final String filePath = Settings.getString(Settings.KEYS.HINTS_FILE); +299 if (filePath == null) { +300 return; +301 } +302 boolean deleteTempFile = false; +303 try { +304 final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE); +305 if (uriRx.matcher(filePath).matches()) { +306 deleteTempFile = true; +307 file = FileUtils.getTempFile("hint", "xml"); +308 final URL url = new URL(filePath); +309 try { +310 Downloader.fetchFile(url, file, false); +311 } catch (DownloadFailedException ex) { +312 Downloader.fetchFile(url, file, true); +313 } +314 } else { +315 file = new File(filePath); +316 if (!file.exists()) { +317 InputStream fromClasspath = null; +318 try { +319 fromClasspath = this.getClass().getClassLoader().getResourceAsStream(filePath); +320 if (fromClasspath != null) { +321 deleteTempFile = true; +322 file = FileUtils.getTempFile("hint", "xml"); +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); +327 } +328 } +329 } finally { +330 if (fromClasspath != null) { +331 fromClasspath.close(); +332 } +333 } +334 } +335 } +336 +337 if (file != null) { +338 try { +339 final Hints newHints = parser.parseHints(file); +340 hints.getHintRules().addAll(newHints.getHintRules()); +341 hints.getVendorDuplicatingHintRules().addAll(newHints.getVendorDuplicatingHintRules()); +342 LOGGER.debug("{} hint rules were loaded.", hints.getHintRules().size()); +343 LOGGER.debug("{} duplicating hint rules were loaded.", hints.getVendorDuplicatingHintRules().size()); +344 } catch (HintParseException ex) { +345 LOGGER.warn("Unable to parse hint rule xml file '{}'", file.getPath()); +346 LOGGER.warn(ex.getMessage()); +347 LOGGER.debug("", ex); +348 throw ex; +349 } 350 } -351 } -352 } -353 } +351 } catch (DownloadFailedException ex) { +352 throw new HintParseException("Unable to fetch the configured hint file", ex); +353 } catch (MalformedURLException ex) { +354 throw new HintParseException("Configured hint file has an invalid URL", ex); +355 } catch (IOException ex) { +356 throw new HintParseException("Unable to create temp file for hints", ex); +357 } finally { +358 if (deleteTempFile && file != null) { +359 FileUtils.delete(file); +360 } +361 } +362 } +363 }
    diff --git a/xref/org/owasp/dependencycheck/analyzer/JarAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/JarAnalyzer.html index 197720596..21f77be2a 100644 --- a/xref/org/owasp/dependencycheck/analyzer/JarAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/JarAnalyzer.html @@ -333,396 +333,396 @@ 325 } else { 326 pom = PomUtils.readPom(externalPom); 327 } -328 pom.processProperties(pomProperties); -329 foundSomething |= setPomEvidence(dependency, pom, classes); -330 } -331 } catch (AnalysisException ex) { -332 LOGGER.warn("An error occurred while analyzing '{}'.", dependency.getActualFilePath()); -333 LOGGER.trace("", ex); -334 } -335 } -336 return foundSomething; -337 } -338 -339 /** -340 * Given a path to a pom.xml within a JarFile, this method attempts to load -341 * a sibling pom.properties if one exists. -342 * -343 * @param path the path to the pom.xml within the JarFile -344 * @param jar the JarFile to load the pom.properties from -345 * @return a Properties object or null if no pom.properties was found -346 * @throws IOException thrown if there is an exception reading the -347 * pom.properties -348 */ -349 private Properties retrievePomProperties(String path, final JarFile jar) throws IOException { -350 Properties pomProperties = null; -351 final String propPath = path.substring(0, path.length() - 7) + "pom.properies"; -352 final ZipEntry propEntry = jar.getEntry(propPath); -353 if (propEntry != null) { -354 Reader reader = null; -355 try { -356 reader = new InputStreamReader(jar.getInputStream(propEntry), "UTF-8"); -357 pomProperties = new Properties(); -358 pomProperties.load(reader); -359 LOGGER.debug("Read pom.properties: {}", propPath); -360 } finally { -361 if (reader != null) { -362 try { -363 reader.close(); -364 } catch (IOException ex) { -365 LOGGER.trace("close error", ex); -366 } -367 } -368 } -369 } -370 return pomProperties; -371 } -372 -373 /** -374 * Searches a JarFile for pom.xml entries and returns a listing of these -375 * entries. -376 * -377 * @param jar the JarFile to search -378 * @return a list of pom.xml entries -379 * @throws IOException thrown if there is an exception reading a JarEntry -380 */ -381 private List<String> retrievePomListing(final JarFile jar) throws IOException { -382 final List<String> pomEntries = new ArrayList<String>(); -383 final Enumeration<JarEntry> entries = jar.entries(); -384 while (entries.hasMoreElements()) { -385 final JarEntry entry = entries.nextElement(); -386 final String entryName = (new File(entry.getName())).getName().toLowerCase(); -387 if (!entry.isDirectory() && "pom.xml".equals(entryName)) { -388 LOGGER.trace("POM Entry found: {}", entry.getName()); -389 pomEntries.add(entry.getName()); -390 } -391 } -392 return pomEntries; -393 } -394 -395 /** -396 * Retrieves the specified POM from a jar file and converts it to a Model. -397 * -398 * @param path the path to the pom.xml file within the jar file -399 * @param jar the jar file to extract the pom from -400 * @param dependency the dependency being analyzed -401 * @return returns the POM object -402 * @throws AnalysisException is thrown if there is an exception extracting -403 * or parsing the POM {@link org.owasp.dependencycheck.xml.pom.Model} object -404 */ -405 private Model extractPom(String path, JarFile jar, Dependency dependency) throws AnalysisException { -406 InputStream input = null; -407 FileOutputStream fos = null; -408 final File tmpDir = getNextTempDirectory(); -409 final File file = new File(tmpDir, "pom.xml"); -410 try { -411 final ZipEntry entry = jar.getEntry(path); -412 input = jar.getInputStream(entry); -413 fos = new FileOutputStream(file); -414 IOUtils.copy(input, fos); -415 dependency.setActualFilePath(file.getAbsolutePath()); -416 } catch (IOException ex) { -417 LOGGER.warn("An error occurred reading '{}' from '{}'.", path, dependency.getFilePath()); -418 LOGGER.error("", ex); -419 } finally { -420 closeStream(fos); -421 closeStream(input); -422 } -423 return PomUtils.readPom(file); -424 } -425 -426 /** -427 * Silently closes an input stream ignoring errors. -428 * -429 * @param stream an input stream to close -430 */ -431 private void closeStream(InputStream stream) { -432 if (stream != null) { -433 try { -434 stream.close(); -435 } catch (IOException ex) { -436 LOGGER.trace("", ex); -437 } -438 } -439 } -440 -441 /** -442 * Silently closes an output stream ignoring errors. -443 * -444 * @param stream an output stream to close -445 */ -446 private void closeStream(OutputStream stream) { -447 if (stream != null) { -448 try { -449 stream.close(); -450 } catch (IOException ex) { -451 LOGGER.trace("", ex); -452 } -453 } -454 } -455 -456 /** -457 * Sets evidence from the pom on the supplied dependency. -458 * -459 * @param dependency the dependency to set data on -460 * @param pom the information from the pom -461 * @param classes a collection of ClassNameInformation - containing data -462 * about the fully qualified class names within the JAR file being analyzed -463 * @return true if there was evidence within the pom that we could use; -464 * otherwise false -465 */ -466 public static boolean setPomEvidence(Dependency dependency, Model pom, List<ClassNameInformation> classes) { -467 boolean foundSomething = false; -468 boolean addAsIdentifier = true; -469 if (pom == null) { -470 return foundSomething; -471 } -472 String groupid = pom.getGroupId(); -473 String parentGroupId = pom.getParentGroupId(); -474 String artifactid = pom.getArtifactId(); -475 String parentArtifactId = pom.getParentArtifactId(); -476 String version = pom.getVersion(); -477 String parentVersion = pom.getParentVersion(); -478 -479 if ("org.sonatype.oss".equals(parentGroupId) && "oss-parent".equals(parentArtifactId)) { -480 parentGroupId = null; -481 parentArtifactId = null; -482 parentVersion = null; -483 } -484 -485 if ((groupid == null || groupid.isEmpty()) && parentGroupId != null && !parentGroupId.isEmpty()) { -486 groupid = parentGroupId; -487 } -488 -489 final String originalGroupID = groupid; -490 if (groupid.startsWith("org.") || groupid.startsWith("com.")) { -491 groupid = groupid.substring(4); +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 if ((artifactid == null || artifactid.isEmpty()) && parentArtifactId != null && !parentArtifactId.isEmpty()) { -495 artifactid = parentArtifactId; -496 } -497 -498 final String originalArtifactID = artifactid; -499 if (artifactid.startsWith("org.") || artifactid.startsWith("com.")) { -500 artifactid = artifactid.substring(4); +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 if ((version == null || version.isEmpty()) && parentVersion != null && !parentVersion.isEmpty()) { -504 version = parentVersion; -505 } -506 -507 if (groupid != null && !groupid.isEmpty()) { -508 foundSomething = true; -509 dependency.getVendorEvidence().addEvidence("pom", "groupid", groupid, Confidence.HIGHEST); -510 dependency.getProductEvidence().addEvidence("pom", "groupid", groupid, Confidence.LOW); -511 addMatchingValues(classes, groupid, dependency.getVendorEvidence()); -512 addMatchingValues(classes, groupid, dependency.getProductEvidence()); -513 if (parentGroupId != null && !parentGroupId.isEmpty() && !parentGroupId.equals(groupid)) { -514 dependency.getVendorEvidence().addEvidence("pom", "parent-groupid", parentGroupId, Confidence.MEDIUM); -515 dependency.getProductEvidence().addEvidence("pom", "parent-groupid", parentGroupId, Confidence.LOW); -516 addMatchingValues(classes, parentGroupId, dependency.getVendorEvidence()); -517 addMatchingValues(classes, parentGroupId, dependency.getProductEvidence()); -518 } -519 } else { -520 addAsIdentifier = false; -521 } -522 -523 if (artifactid != null && !artifactid.isEmpty()) { -524 foundSomething = true; -525 dependency.getProductEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.HIGHEST); -526 dependency.getVendorEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.LOW); -527 addMatchingValues(classes, artifactid, dependency.getVendorEvidence()); -528 addMatchingValues(classes, artifactid, dependency.getProductEvidence()); -529 if (parentArtifactId != null && !parentArtifactId.isEmpty() && !parentArtifactId.equals(artifactid)) { -530 dependency.getProductEvidence().addEvidence("pom", "parent-artifactid", parentArtifactId, Confidence.MEDIUM); -531 dependency.getVendorEvidence().addEvidence("pom", "parent-artifactid", parentArtifactId, Confidence.LOW); -532 addMatchingValues(classes, parentArtifactId, dependency.getVendorEvidence()); -533 addMatchingValues(classes, parentArtifactId, dependency.getProductEvidence()); -534 } -535 } else { -536 addAsIdentifier = false; -537 } -538 -539 if (version != null && !version.isEmpty()) { -540 foundSomething = true; -541 dependency.getVersionEvidence().addEvidence("pom", "version", version, Confidence.HIGHEST); -542 if (parentVersion != null && !parentVersion.isEmpty() && !parentVersion.equals(version)) { -543 dependency.getVersionEvidence().addEvidence("pom", "parent-version", version, Confidence.LOW); -544 } -545 } else { -546 addAsIdentifier = false; -547 } -548 -549 if (addAsIdentifier) { -550 dependency.addIdentifier("maven", String.format("%s:%s:%s", originalGroupID, originalArtifactID, version), null, Confidence.HIGH); -551 } -552 -553 // org name -554 final String org = pom.getOrganization(); -555 if (org != null && !org.isEmpty()) { -556 dependency.getVendorEvidence().addEvidence("pom", "organization name", org, Confidence.HIGH); -557 dependency.getProductEvidence().addEvidence("pom", "organization name", org, Confidence.LOW); -558 addMatchingValues(classes, org, dependency.getVendorEvidence()); -559 addMatchingValues(classes, org, dependency.getProductEvidence()); -560 } -561 //pom name -562 final String pomName = pom.getName(); -563 if (pomName -564 != null && !pomName.isEmpty()) { -565 foundSomething = true; -566 dependency.getProductEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH); -567 dependency.getVendorEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH); -568 addMatchingValues(classes, pomName, dependency.getVendorEvidence()); -569 addMatchingValues(classes, pomName, dependency.getProductEvidence()); -570 } -571 -572 //Description -573 final String description = pom.getDescription(); -574 if (description != null && !description.isEmpty() && !description.startsWith("POM was created by")) { -575 foundSomething = true; -576 final String trimmedDescription = addDescription(dependency, description, "pom", "description"); -577 addMatchingValues(classes, trimmedDescription, dependency.getVendorEvidence()); -578 addMatchingValues(classes, trimmedDescription, dependency.getProductEvidence()); -579 } -580 -581 final String projectURL = pom.getProjectURL(); -582 if (projectURL != null && !projectURL.trim().isEmpty()) { -583 dependency.getVendorEvidence().addEvidence("pom", "url", projectURL, Confidence.HIGHEST); +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 extractLicense(pom, dependency); -587 return foundSomething; -588 } -589 -590 /** -591 * Analyzes the path information of the classes contained within the -592 * JarAnalyzer to try and determine possible vendor or product names. If any -593 * are found they are stored in the packageVendor and packageProduct -594 * hashSets. -595 * -596 * @param classNames a list of class names -597 * @param dependency a dependency to analyze -598 * @param addPackagesAsEvidence a flag indicating whether or not package -599 * names should be added as evidence. -600 */ -601 protected void analyzePackageNames(List<ClassNameInformation> classNames, -602 Dependency dependency, boolean addPackagesAsEvidence) { -603 final Map<String, Integer> vendorIdentifiers = new HashMap<String, Integer>(); -604 final Map<String, Integer> productIdentifiers = new HashMap<String, Integer>(); -605 analyzeFullyQualifiedClassNames(classNames, vendorIdentifiers, productIdentifiers); -606 -607 final int classCount = classNames.size(); -608 final EvidenceCollection vendor = dependency.getVendorEvidence(); -609 final EvidenceCollection product = dependency.getProductEvidence(); -610 -611 for (Map.Entry<String, Integer> entry : vendorIdentifiers.entrySet()) { -612 final float ratio = entry.getValue() / (float) classCount; -613 if (ratio > 0.5) { -614 //TODO remove weighting -615 vendor.addWeighting(entry.getKey()); -616 if (addPackagesAsEvidence && entry.getKey().length() > 1) { -617 vendor.addEvidence("jar", "package name", entry.getKey(), Confidence.LOW); -618 } -619 } -620 } -621 for (Map.Entry<String, Integer> entry : productIdentifiers.entrySet()) { -622 final float ratio = entry.getValue() / (float) classCount; -623 if (ratio > 0.5) { -624 product.addWeighting(entry.getKey()); -625 if (addPackagesAsEvidence && entry.getKey().length() > 1) { -626 product.addEvidence("jar", "package name", entry.getKey(), Confidence.LOW); -627 } -628 } -629 } -630 } -631 -632 /** -633 * <p> -634 * Reads the manifest from the JAR file and collects the entries. Some -635 * vendorKey entries are:</p> -636 * <ul><li>Implementation Title</li> -637 * <li>Implementation Version</li> <li>Implementation Vendor</li> -638 * <li>Implementation VendorId</li> <li>Bundle Name</li> <li>Bundle -639 * Version</li> <li>Bundle Vendor</li> <li>Bundle Description</li> <li>Main -640 * Class</li> </ul> -641 * However, all but a handful of specific entries are read in. -642 * -643 * @param dependency A reference to the dependency -644 * @param classInformation a collection of class information -645 * @return whether evidence was identified parsing the manifest -646 * @throws IOException if there is an issue reading the JAR file -647 */ -648 protected boolean parseManifest(Dependency dependency, List<ClassNameInformation> classInformation) throws IOException { -649 boolean foundSomething = false; -650 JarFile jar = null; -651 try { -652 jar = new JarFile(dependency.getActualFilePath()); -653 final Manifest manifest = jar.getManifest(); -654 if (manifest == null) { -655 if (!dependency.getFileName().toLowerCase().endsWith("-sources.jar") -656 && !dependency.getFileName().toLowerCase().endsWith("-javadoc.jar") -657 && !dependency.getFileName().toLowerCase().endsWith("-src.jar") -658 && !dependency.getFileName().toLowerCase().endsWith("-doc.jar")) { -659 LOGGER.debug("Jar file '{}' does not contain a manifest.", -660 dependency.getFileName()); -661 } -662 return false; -663 } -664 final EvidenceCollection vendorEvidence = dependency.getVendorEvidence(); -665 final EvidenceCollection productEvidence = dependency.getProductEvidence(); -666 final EvidenceCollection versionEvidence = dependency.getVersionEvidence(); -667 String source = "Manifest"; -668 String specificationVersion = null; -669 boolean hasImplementationVersion = false; -670 Attributes atts = manifest.getMainAttributes(); -671 for (Entry<Object, Object> entry : atts.entrySet()) { -672 String key = entry.getKey().toString(); -673 String value = atts.getValue(key); -674 if (HTML_DETECTION_PATTERN.matcher(value).find()) { -675 value = Jsoup.parse(value).text(); -676 } -677 if (IGNORE_VALUES.contains(value)) { -678 continue; -679 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_TITLE.toString())) { -680 foundSomething = true; -681 productEvidence.addEvidence(source, key, value, Confidence.HIGH); -682 addMatchingValues(classInformation, value, productEvidence); -683 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VERSION.toString())) { -684 hasImplementationVersion = true; +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 versionEvidence.addEvidence(source, key, value, Confidence.HIGH); -687 } else if ("specification-version".equalsIgnoreCase(key)) { -688 specificationVersion = key; -689 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) { +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 vendorEvidence.addEvidence(source, key, value, Confidence.HIGH); -692 addMatchingValues(classInformation, value, vendorEvidence); -693 } else if (key.equalsIgnoreCase(IMPLEMENTATION_VENDOR_ID)) { -694 foundSomething = true; -695 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -696 addMatchingValues(classInformation, value, vendorEvidence); -697 } else if (key.equalsIgnoreCase(BUNDLE_DESCRIPTION)) { -698 foundSomething = true; -699 addDescription(dependency, value, "manifest", key); -700 addMatchingValues(classInformation, value, productEvidence); -701 } else if (key.equalsIgnoreCase(BUNDLE_NAME)) { -702 foundSomething = true; -703 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -704 addMatchingValues(classInformation, value, productEvidence); -705 // //the following caused false positives. -706 // } else if (key.equalsIgnoreCase(BUNDLE_VENDOR)) { -707 // foundSomething = true; -708 // vendorEvidence.addEvidence(source, key, value, Confidence.HIGH); -709 // addMatchingValues(classInformation, value, vendorEvidence); -710 } else if (key.equalsIgnoreCase(BUNDLE_VERSION)) { -711 foundSomething = true; -712 versionEvidence.addEvidence(source, key, value, Confidence.HIGH); -713 } else if (key.equalsIgnoreCase(Attributes.Name.MAIN_CLASS.toString())) { -714 continue; -715 //skipping main class as if this has important information to add -716 // it will be added during class name analysis... if other fields -717 // have the information from the class name then they will get added... +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) diff --git a/xref/org/owasp/dependencycheck/analyzer/NexusAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/NexusAnalyzer.html index 423630215..c2b44db91 100644 --- a/xref/org/owasp/dependencycheck/analyzer/NexusAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/NexusAnalyzer.html @@ -253,24 +253,25 @@ 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 && !FileUtils.deleteQuietly(pomFile)) { -249 pomFile.deleteOnExit(); -250 } -251 } -252 } -253 } catch (IllegalArgumentException iae) { -254 //dependency.addAnalysisException(new AnalysisException("Invalid SHA-1")); -255 LOGGER.info("invalid sha-1 hash on {}", dependency.getFileName()); -256 } catch (FileNotFoundException fnfe) { -257 //dependency.addAnalysisException(new AnalysisException("Artifact not found on repository")); -258 LOGGER.debug("Artifact not found in repository '{}'", dependency.getFileName()); -259 LOGGER.debug(fnfe.getMessage(), fnfe); -260 } catch (IOException ioe) { -261 //dependency.addAnalysisException(new AnalysisException("Could not connect to repository", ioe)); -262 LOGGER.debug("Could not connect to nexus repository", ioe); -263 } -264 } -265 } +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 }
    diff --git a/xref/org/owasp/dependencycheck/analyzer/PythonDistributionAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/PythonDistributionAnalyzer.html index e9aefa0d9..21cf96edf 100644 --- a/xref/org/owasp/dependencycheck/analyzer/PythonDistributionAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/PythonDistributionAnalyzer.html @@ -32,9 +32,9 @@ 24 import java.io.FileNotFoundException; 25 import java.io.FilenameFilter; 26 import java.io.IOException; -27 import org.apache.commons.io.filefilter.NameFileFilter; -28 import org.apache.commons.io.filefilter.SuffixFileFilter; -29 import org.apache.commons.io.input.AutoCloseInputStream; +27 import java.io.InputStream; +28 import org.apache.commons.io.filefilter.NameFileFilter; +29 import org.apache.commons.io.filefilter.SuffixFileFilter; 30 import org.apache.commons.lang3.StringUtils; 31 import org.owasp.dependencycheck.Engine; 32 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; @@ -236,168 +236,180 @@ 228 throw new AnalysisException(ex); 229 } 230 -231 collectWheelMetadata( -232 dependency, -233 getMatchingFile(getMatchingFile(temp, folderFilter), -234 metadataFilter)); -235 } -236 -237 /** -238 * Makes sure a usable temporary directory is available. -239 * -240 * @throws InitializationException an AnalyzeException is thrown when the -241 * temp directory cannot be created -242 */ -243 @Override -244 protected void initializeFileTypeAnalyzer() throws InitializationException { -245 try { -246 final File baseDir = Settings.getTempDirectory(); -247 tempFileLocation = File.createTempFile("check", "tmp", baseDir); -248 if (!tempFileLocation.delete()) { -249 setEnabled(false); -250 final String msg = String.format( -251 "Unable to delete temporary file '%s'.", -252 tempFileLocation.getAbsolutePath()); -253 throw new InitializationException(msg); -254 } -255 if (!tempFileLocation.mkdirs()) { -256 setEnabled(false); -257 final String msg = String.format( -258 "Unable to create directory '%s'.", -259 tempFileLocation.getAbsolutePath()); -260 throw new InitializationException(msg); -261 } -262 } catch (IOException ex) { -263 setEnabled(false); -264 throw new InitializationException("Unable to create a temporary file", ex); -265 } -266 } -267 -268 /** -269 * Deletes any files extracted from the Wheel during analysis. -270 */ -271 @Override -272 public void close() { -273 if (tempFileLocation != null && tempFileLocation.exists()) { -274 LOGGER.debug("Attempting to delete temporary files"); -275 final boolean success = FileUtils.delete(tempFileLocation); -276 if (!success) { -277 LOGGER.warn( -278 "Failed to delete some temporary files, see the log for more details"); -279 } -280 } -281 } -282 -283 /** -284 * Gathers evidence from the METADATA file. -285 * -286 * @param dependency the dependency being analyzed -287 * @param file a reference to the manifest/properties file -288 */ -289 private static void collectWheelMetadata(Dependency dependency, File file) { -290 final InternetHeaders headers = getManifestProperties(file); -291 addPropertyToEvidence(headers, dependency.getVersionEvidence(), -292 "Version", Confidence.HIGHEST); -293 addPropertyToEvidence(headers, dependency.getProductEvidence(), "Name", -294 Confidence.HIGHEST); -295 final String url = headers.getHeader("Home-page", null); -296 final EvidenceCollection vendorEvidence = dependency -297 .getVendorEvidence(); -298 if (StringUtils.isNotBlank(url)) { -299 if (UrlStringUtils.isUrl(url)) { -300 vendorEvidence.addEvidence(METADATA, "vendor", url, -301 Confidence.MEDIUM); -302 } -303 } -304 addPropertyToEvidence(headers, vendorEvidence, "Author", Confidence.LOW); -305 final String summary = headers.getHeader("Summary", null); -306 if (StringUtils.isNotBlank(summary)) { -307 JarAnalyzer -308 .addDescription(dependency, summary, METADATA, "summary"); -309 } -310 } -311 -312 /** -313 * Adds a value to the evidence collection. -314 * -315 * @param headers the properties collection -316 * @param evidence the evidence collection to add the value -317 * @param property the property name -318 * @param confidence the confidence of the evidence -319 */ -320 private static void addPropertyToEvidence(InternetHeaders headers, -321 EvidenceCollection evidence, String property, Confidence confidence) { -322 final String value = headers.getHeader(property, null); -323 LOGGER.debug("Property: {}, Value: {}", property, value); -324 if (StringUtils.isNotBlank(value)) { -325 evidence.addEvidence(METADATA, property, value, confidence); -326 } -327 } -328 -329 /** -330 * Returns a list of files that match the given filter, this does not -331 * recursively scan the directory. -332 * -333 * @param folder the folder to filter -334 * @param filter the filter to apply to the files in the directory -335 * @return the list of Files in the directory that match the provided filter -336 */ -337 private static File getMatchingFile(File folder, FilenameFilter filter) { -338 File result = null; -339 final File[] matches = folder.listFiles(filter); -340 if (null != matches && 1 == matches.length) { -341 result = matches[0]; -342 } -343 return result; -344 } -345 -346 /** -347 * Reads the manifest entries from the provided file. -348 * -349 * @param manifest the manifest -350 * @return the manifest entries -351 */ -352 private static InternetHeaders getManifestProperties(File manifest) { -353 final InternetHeaders result = new InternetHeaders(); -354 if (null == manifest) { -355 LOGGER.debug("Manifest file not found."); -356 } else { -357 try { -358 result.load(new AutoCloseInputStream(new BufferedInputStream( -359 new FileInputStream(manifest)))); -360 } catch (MessagingException e) { -361 LOGGER.warn(e.getMessage(), e); -362 } catch (FileNotFoundException e) { -363 LOGGER.warn(e.getMessage(), e); -364 } -365 } -366 return result; -367 } -368 -369 /** -370 * Retrieves the next temporary destination directory for extracting an -371 * archive. -372 * -373 * @return a directory -374 * @throws AnalysisException thrown if unable to create temporary directory -375 */ -376 private File getNextTempDirectory() throws AnalysisException { -377 File directory; -378 -379 // getting an exception for some directories not being able to be -380 // created; might be because the directory already exists? -381 do { -382 dirCount += 1; -383 directory = new File(tempFileLocation, String.valueOf(dirCount)); -384 } while (directory.exists()); -385 if (!directory.mkdirs()) { -386 throw new AnalysisException(String.format( -387 "Unable to create temp directory '%s'.", -388 directory.getAbsolutePath())); -389 } -390 return directory; -391 } -392 } +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 }
    diff --git a/xref/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.html index ac2dbd5cf..3cd157e12 100644 --- a/xref/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.html @@ -31,478 +31,486 @@ 23 import java.io.IOException; 24 import java.io.InputStreamReader; 25 import java.io.UnsupportedEncodingException; -26 import java.util.ArrayList; -27 import java.util.HashMap; -28 import java.util.List; -29 import java.util.Map; -30 import java.nio.charset.Charset; -31 import org.apache.commons.io.FileUtils; -32 import org.owasp.dependencycheck.Engine; -33 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; -34 import org.owasp.dependencycheck.data.nvdcve.CveDB; -35 import org.owasp.dependencycheck.dependency.Confidence; -36 import org.owasp.dependencycheck.dependency.Dependency; -37 import org.owasp.dependencycheck.dependency.Reference; -38 import org.owasp.dependencycheck.dependency.Vulnerability; -39 import org.owasp.dependencycheck.utils.FileFilterBuilder; -40 import org.owasp.dependencycheck.utils.Settings; -41 import org.slf4j.Logger; -42 import org.slf4j.LoggerFactory; -43 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; -44 import org.owasp.dependencycheck.exception.InitializationException; -45 -46 /** -47 * Used to analyze Ruby Bundler Gemspec.lock files utilizing the 3rd party -48 * bundle-audit tool. -49 * -50 * @author Dale Visser -51 */ -52 @Experimental -53 public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer { -54 -55 /** -56 * The logger. -57 */ -58 private static final Logger LOGGER = LoggerFactory.getLogger(RubyBundleAuditAnalyzer.class); -59 -60 /** -61 * The name of the analyzer. -62 */ -63 private static final String ANALYZER_NAME = "Ruby Bundle Audit Analyzer"; -64 -65 /** -66 * The phase that this analyzer is intended to run in. -67 */ -68 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.PRE_INFORMATION_COLLECTION; -69 /** -70 * The filter defining which files will be analyzed. -71 */ -72 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFilenames("Gemfile.lock").build(); -73 /** -74 * Name. -75 */ -76 public static final String NAME = "Name: "; -77 /** -78 * Version. -79 */ -80 public static final String VERSION = "Version: "; -81 /** -82 * Advisory. -83 */ -84 public static final String ADVISORY = "Advisory: "; -85 /** -86 * Criticality. -87 */ -88 public static final String CRITICALITY = "Criticality: "; -89 -90 /** -91 * The DAL. -92 */ -93 private CveDB cvedb; -94 -95 /** -96 * @return a filter that accepts files named Gemfile.lock -97 */ -98 @Override -99 protected FileFilter getFileFilter() { -100 return FILTER; -101 } -102 -103 /** -104 * Launch bundle-audit. -105 * -106 * @param folder directory that contains bundle audit -107 * @return a handle to the process -108 * @throws AnalysisException thrown when there is an issue launching bundle -109 * audit -110 */ -111 private Process launchBundleAudit(File folder) throws AnalysisException { -112 if (!folder.isDirectory()) { -113 throw new AnalysisException(String.format("%s should have been a directory.", folder.getAbsolutePath())); -114 } -115 final List<String> args = new ArrayList<String>(); -116 final String bundleAuditPath = Settings.getString(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH); -117 args.add(null == bundleAuditPath ? "bundle-audit" : bundleAuditPath); -118 args.add("check"); -119 args.add("--verbose"); -120 final ProcessBuilder builder = new ProcessBuilder(args); -121 builder.directory(folder); -122 try { -123 LOGGER.info("Launching: " + args + " from " + folder); -124 return builder.start(); -125 } catch (IOException ioe) { -126 throw new AnalysisException("bundle-audit failure", ioe); -127 } -128 } -129 -130 /** -131 * Initialize the analyzer. In this case, extract GrokAssembly.exe to a -132 * temporary location. -133 * -134 * @throws InitializationException if anything goes wrong -135 */ -136 @Override -137 public void initializeFileTypeAnalyzer() throws InitializationException { -138 try { -139 cvedb = new CveDB(); -140 cvedb.open(); -141 } catch (DatabaseException ex) { -142 LOGGER.warn("Exception opening the database"); -143 LOGGER.debug("error", ex); -144 setEnabled(false); -145 throw new InitializationException("Error connecting to the database", ex); -146 } -147 // Now, need to see if bundle-audit actually runs from this location. -148 Process process = null; -149 try { -150 process = launchBundleAudit(Settings.getTempDirectory()); -151 } catch (AnalysisException ae) { -152 -153 setEnabled(false); -154 cvedb.close(); -155 cvedb = null; -156 final String msg = String.format("Exception from bundle-audit process: %s. Disabling %s", ae.getCause(), ANALYZER_NAME); -157 throw new InitializationException(msg, ae); -158 } catch (IOException ex) { -159 setEnabled(false); -160 throw new InitializationException("Unable to create temporary file, the Ruby Bundle Audit Analyzer will be disabled", ex); -161 } -162 -163 final int exitValue; -164 try { -165 exitValue = process.waitFor(); -166 } catch (InterruptedException ex) { -167 setEnabled(false); -168 final String msg = String.format("Bundle-audit process was interupted. Disabling %s", ANALYZER_NAME); -169 throw new InitializationException(msg); -170 } -171 if (0 == exitValue) { -172 setEnabled(false); -173 final String msg = String.format("Unexpected exit code from bundle-audit process. Disabling %s: %s", ANALYZER_NAME, exitValue); -174 throw new InitializationException(msg); -175 } else { -176 BufferedReader reader = null; -177 try { -178 reader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8")); -179 if (!reader.ready()) { -180 LOGGER.warn("Bundle-audit error stream unexpectedly not ready. Disabling " + ANALYZER_NAME); -181 setEnabled(false); -182 throw new InitializationException("Bundle-audit error stream unexpectedly not ready."); -183 } else { -184 final String line = reader.readLine(); -185 if (line == null || !line.contains("Errno::ENOENT")) { -186 LOGGER.warn("Unexpected bundle-audit output. Disabling {}: {}", ANALYZER_NAME, line); -187 setEnabled(false); -188 throw new InitializationException("Unexpected bundle-audit output."); -189 } -190 } -191 } catch (UnsupportedEncodingException ex) { -192 setEnabled(false); -193 throw new InitializationException("Unexpected bundle-audit encoding.", ex); -194 } catch (IOException ex) { -195 setEnabled(false); -196 throw new InitializationException("Unable to read bundle-audit output.", ex); -197 } finally { -198 if (null != reader) { -199 try { -200 reader.close(); -201 } catch (IOException ex) { -202 LOGGER.debug("Error closing reader", ex); -203 } -204 } -205 } -206 } -207 -208 if (isEnabled()) { -209 LOGGER.info(ANALYZER_NAME + " is enabled. It is necessary to manually run \"bundle-audit update\" " -210 + "occasionally to keep its database up to date."); -211 } -212 } -213 -214 /** -215 * Returns the name of the analyzer. -216 * -217 * @return the name of the analyzer. -218 */ -219 @Override -220 public String getName() { -221 return ANALYZER_NAME; -222 } -223 -224 /** -225 * Returns the phase that the analyzer is intended to run in. -226 * -227 * @return the phase that the analyzer is intended to run in. -228 */ -229 @Override -230 public AnalysisPhase getAnalysisPhase() { -231 return ANALYSIS_PHASE; -232 } -233 -234 /** -235 * Returns the key used in the properties file to reference the analyzer's -236 * enabled property. -237 * -238 * @return the analyzer's enabled property setting key -239 */ -240 @Override -241 protected String getAnalyzerEnabledSettingKey() { -242 return Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED; -243 } -244 -245 /** -246 * If {@link #analyzeFileType(Dependency, Engine)} is called, then we have -247 * successfully initialized, and it will be necessary to disable -248 * {@link RubyGemspecAnalyzer}. -249 */ -250 private boolean needToDisableGemspecAnalyzer = true; -251 -252 /** -253 * Determines if the analyzer can analyze the given file type. -254 * -255 * @param dependency the dependency to determine if it can analyze -256 * @param engine the dependency-check engine -257 * @throws AnalysisException thrown if there is an analysis exception. -258 */ -259 @Override -260 protected void analyzeFileType(Dependency dependency, Engine engine) -261 throws AnalysisException { -262 if (needToDisableGemspecAnalyzer) { -263 boolean failed = true; -264 final String className = RubyGemspecAnalyzer.class.getName(); -265 for (FileTypeAnalyzer analyzer : engine.getFileTypeAnalyzers()) { -266 if (analyzer instanceof RubyBundlerAnalyzer) { -267 ((RubyBundlerAnalyzer) analyzer).setEnabled(false); -268 LOGGER.info("Disabled " + RubyBundlerAnalyzer.class.getName() + " to avoid noisy duplicate results."); -269 } else if (analyzer instanceof RubyGemspecAnalyzer) { -270 ((RubyGemspecAnalyzer) analyzer).setEnabled(false); -271 LOGGER.info("Disabled " + className + " to avoid noisy duplicate results."); -272 failed = false; -273 } -274 } -275 if (failed) { -276 LOGGER.warn("Did not find " + className + '.'); -277 } -278 needToDisableGemspecAnalyzer = false; -279 } -280 final File parentFile = dependency.getActualFile().getParentFile(); -281 final Process process = launchBundleAudit(parentFile); -282 try { -283 process.waitFor(); -284 } catch (InterruptedException ie) { -285 throw new AnalysisException("bundle-audit process interrupted", ie); -286 } -287 BufferedReader rdr = null; -288 BufferedReader errReader = null; -289 try { -290 errReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8")); -291 while (errReader.ready()) { -292 final String error = errReader.readLine(); -293 LOGGER.warn(error); -294 } -295 rdr = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8")); -296 processBundlerAuditOutput(dependency, engine, rdr); -297 } catch (IOException ioe) { -298 LOGGER.warn("bundle-audit failure", ioe); -299 } finally { -300 if (errReader != null) { -301 try { -302 errReader.close(); -303 } catch (IOException ioe) { -304 LOGGER.warn("bundle-audit close failure", ioe); -305 } -306 } -307 if (null != rdr) { -308 try { -309 rdr.close(); -310 } catch (IOException ioe) { -311 LOGGER.warn("bundle-audit close failure", ioe); -312 } -313 } -314 } -315 -316 } -317 -318 /** -319 * Processes the bundler audit output. -320 * -321 * @param original the dependency -322 * @param engine the dependency-check engine -323 * @param rdr the reader of the report -324 * @throws IOException thrown if the report cannot be read. -325 */ -326 private void processBundlerAuditOutput(Dependency original, Engine engine, BufferedReader rdr) throws IOException { -327 final String parentName = original.getActualFile().getParentFile().getName(); -328 final String fileName = original.getFileName(); -329 final String filePath = original.getFilePath(); -330 Dependency dependency = null; -331 Vulnerability vulnerability = null; -332 String gem = null; -333 final Map<String, Dependency> map = new HashMap<String, Dependency>(); -334 boolean appendToDescription = false; -335 while (rdr.ready()) { -336 final String nextLine = rdr.readLine(); -337 if (null == nextLine) { -338 break; -339 } else if (nextLine.startsWith(NAME)) { -340 appendToDescription = false; -341 gem = nextLine.substring(NAME.length()); -342 if (!map.containsKey(gem)) { -343 map.put(gem, createDependencyForGem(engine, parentName, fileName, filePath, gem)); -344 } -345 dependency = map.get(gem); -346 LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine)); -347 } else if (nextLine.startsWith(VERSION)) { -348 vulnerability = createVulnerability(parentName, dependency, gem, nextLine); -349 } else if (nextLine.startsWith(ADVISORY)) { -350 setVulnerabilityName(parentName, dependency, vulnerability, nextLine); -351 } else if (nextLine.startsWith(CRITICALITY)) { -352 addCriticalityToVulnerability(parentName, vulnerability, nextLine); -353 } else if (nextLine.startsWith("URL: ")) { -354 addReferenceToVulnerability(parentName, vulnerability, nextLine); -355 } else if (nextLine.startsWith("Description:")) { -356 appendToDescription = true; -357 if (null != vulnerability) { -358 vulnerability.setDescription("*** Vulnerability obtained from bundle-audit verbose report. " -359 + "Title link may not work. CPE below is guessed. CVSS score is estimated (-1.0 " -360 + " indicates unknown). See link below for full details. *** "); -361 } -362 } else if (appendToDescription) { +26 import java.nio.charset.Charset; +27 import java.util.ArrayList; +28 import java.util.HashMap; +29 import java.util.List; +30 import java.util.Map; +31 +32 import org.apache.commons.io.FileUtils; +33 import org.owasp.dependencycheck.Engine; +34 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; +35 import org.owasp.dependencycheck.data.nvdcve.CveDB; +36 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; +37 import org.owasp.dependencycheck.dependency.Confidence; +38 import org.owasp.dependencycheck.dependency.Dependency; +39 import org.owasp.dependencycheck.dependency.Reference; +40 import org.owasp.dependencycheck.dependency.Vulnerability; +41 import org.owasp.dependencycheck.exception.InitializationException; +42 import org.owasp.dependencycheck.utils.FileFilterBuilder; +43 import org.owasp.dependencycheck.utils.Settings; +44 import org.slf4j.Logger; +45 import org.slf4j.LoggerFactory; +46 +47 /** +48 * Used to analyze Ruby Bundler Gemspec.lock files utilizing the 3rd party +49 * bundle-audit tool. +50 * +51 * @author Dale Visser +52 */ +53 @Experimental +54 public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer { +55 +56 /** +57 * The logger. +58 */ +59 private static final Logger LOGGER = LoggerFactory.getLogger(RubyBundleAuditAnalyzer.class); +60 +61 /** +62 * The name of the analyzer. +63 */ +64 private static final String ANALYZER_NAME = "Ruby Bundle Audit Analyzer"; +65 +66 /** +67 * The phase that this analyzer is intended to run in. +68 */ +69 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.PRE_INFORMATION_COLLECTION; +70 /** +71 * The filter defining which files will be analyzed. +72 */ +73 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFilenames("Gemfile.lock").build(); +74 /** +75 * Name. +76 */ +77 public static final String NAME = "Name: "; +78 /** +79 * Version. +80 */ +81 public static final String VERSION = "Version: "; +82 /** +83 * Advisory. +84 */ +85 public static final String ADVISORY = "Advisory: "; +86 /** +87 * Criticality. +88 */ +89 public static final String CRITICALITY = "Criticality: "; +90 +91 /** +92 * The DAL. +93 */ +94 private CveDB cvedb; +95 +96 /** +97 * @return a filter that accepts files named Gemfile.lock +98 */ +99 @Override +100 protected FileFilter getFileFilter() { +101 return FILTER; +102 } +103 +104 /** +105 * Launch bundle-audit. +106 * +107 * @param folder directory that contains bundle audit +108 * @return a handle to the process +109 * @throws AnalysisException thrown when there is an issue launching bundle +110 * audit +111 */ +112 private Process launchBundleAudit(File folder) throws AnalysisException { +113 if (!folder.isDirectory()) { +114 throw new AnalysisException(String.format("%s should have been a directory.", folder.getAbsolutePath())); +115 } +116 final List<String> args = new ArrayList<String>(); +117 final String bundleAuditPath = Settings.getString(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH); +118 args.add(null == bundleAuditPath ? "bundle-audit" : bundleAuditPath); +119 args.add("check"); +120 args.add("--verbose"); +121 final ProcessBuilder builder = new ProcessBuilder(args); +122 builder.directory(folder); +123 try { +124 LOGGER.info("Launching: " + args + " from " + folder); +125 return builder.start(); +126 } catch (IOException ioe) { +127 throw new AnalysisException("bundle-audit failure", ioe); +128 } +129 } +130 +131 /** +132 * Initialize the analyzer. In this case, extract GrokAssembly.exe to a +133 * temporary location. +134 * +135 * @throws InitializationException if anything goes wrong +136 */ +137 @Override +138 public void initializeFileTypeAnalyzer() throws InitializationException { +139 try { +140 cvedb = new CveDB(); +141 cvedb.open(); +142 } catch (DatabaseException ex) { +143 LOGGER.warn("Exception opening the database"); +144 LOGGER.debug("error", ex); +145 setEnabled(false); +146 throw new InitializationException("Error connecting to the database", ex); +147 } +148 // Now, need to see if bundle-audit actually runs from this location. +149 Process process = null; +150 try { +151 process = launchBundleAudit(Settings.getTempDirectory()); +152 } catch (AnalysisException ae) { +153 +154 setEnabled(false); +155 cvedb.close(); +156 cvedb = null; +157 final String msg = String.format("Exception from bundle-audit process: %s. Disabling %s", ae.getCause(), ANALYZER_NAME); +158 throw new InitializationException(msg, ae); +159 } catch (IOException ex) { +160 setEnabled(false); +161 throw new InitializationException("Unable to create temporary file, the Ruby Bundle Audit Analyzer will be disabled", ex); +162 } +163 +164 final int exitValue; +165 try { +166 exitValue = process.waitFor(); +167 } catch (InterruptedException ex) { +168 setEnabled(false); +169 final String msg = String.format("Bundle-audit process was interupted. Disabling %s", ANALYZER_NAME); +170 throw new InitializationException(msg); +171 } +172 if (0 == exitValue) { +173 setEnabled(false); +174 final String msg = String.format("Unexpected exit code from bundle-audit process. Disabling %s: %s", ANALYZER_NAME, exitValue); +175 throw new InitializationException(msg); +176 } else { +177 BufferedReader reader = null; +178 try { +179 reader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8")); +180 if (!reader.ready()) { +181 LOGGER.warn("Bundle-audit error stream unexpectedly not ready. Disabling " + ANALYZER_NAME); +182 setEnabled(false); +183 throw new InitializationException("Bundle-audit error stream unexpectedly not ready."); +184 } else { +185 final String line = reader.readLine(); +186 if (line == null || !line.contains("Errno::ENOENT")) { +187 LOGGER.warn("Unexpected bundle-audit output. Disabling {}: {}", ANALYZER_NAME, line); +188 setEnabled(false); +189 throw new InitializationException("Unexpected bundle-audit output."); +190 } +191 } +192 } catch (UnsupportedEncodingException ex) { +193 setEnabled(false); +194 throw new InitializationException("Unexpected bundle-audit encoding.", ex); +195 } catch (IOException ex) { +196 setEnabled(false); +197 throw new InitializationException("Unable to read bundle-audit output.", ex); +198 } finally { +199 if (null != reader) { +200 try { +201 reader.close(); +202 } catch (IOException ex) { +203 LOGGER.debug("Error closing reader", ex); +204 } +205 } +206 } +207 } +208 +209 if (isEnabled()) { +210 LOGGER.info(ANALYZER_NAME + " is enabled. It is necessary to manually run \"bundle-audit update\" " +211 + "occasionally to keep its database up to date."); +212 } +213 } +214 +215 /** +216 * Returns the name of the analyzer. +217 * +218 * @return the name of the analyzer. +219 */ +220 @Override +221 public String getName() { +222 return ANALYZER_NAME; +223 } +224 +225 /** +226 * Returns the phase that the analyzer is intended to run in. +227 * +228 * @return the phase that the analyzer is intended to run in. +229 */ +230 @Override +231 public AnalysisPhase getAnalysisPhase() { +232 return ANALYSIS_PHASE; +233 } +234 +235 /** +236 * Returns the key used in the properties file to reference the analyzer's +237 * enabled property. +238 * +239 * @return the analyzer's enabled property setting key +240 */ +241 @Override +242 protected String getAnalyzerEnabledSettingKey() { +243 return Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED; +244 } +245 +246 /** +247 * If {@link #analyzeFileType(Dependency, Engine)} is called, then we have +248 * successfully initialized, and it will be necessary to disable +249 * {@link RubyGemspecAnalyzer}. +250 */ +251 private boolean needToDisableGemspecAnalyzer = true; +252 +253 /** +254 * Determines if the analyzer can analyze the given file type. +255 * +256 * @param dependency the dependency to determine if it can analyze +257 * @param engine the dependency-check engine +258 * @throws AnalysisException thrown if there is an analysis exception. +259 */ +260 @Override +261 protected void analyzeFileType(Dependency dependency, Engine engine) +262 throws AnalysisException { +263 if (needToDisableGemspecAnalyzer) { +264 boolean failed = true; +265 final String className = RubyGemspecAnalyzer.class.getName(); +266 for (FileTypeAnalyzer analyzer : engine.getFileTypeAnalyzers()) { +267 if (analyzer instanceof RubyBundlerAnalyzer) { +268 ((RubyBundlerAnalyzer) analyzer).setEnabled(false); +269 LOGGER.info("Disabled " + RubyBundlerAnalyzer.class.getName() + " to avoid noisy duplicate results."); +270 } else if (analyzer instanceof RubyGemspecAnalyzer) { +271 ((RubyGemspecAnalyzer) analyzer).setEnabled(false); +272 LOGGER.info("Disabled " + className + " to avoid noisy duplicate results."); +273 failed = false; +274 } +275 } +276 if (failed) { +277 LOGGER.warn("Did not find " + className + '.'); +278 } +279 needToDisableGemspecAnalyzer = false; +280 } +281 final File parentFile = dependency.getActualFile().getParentFile(); +282 final Process process = launchBundleAudit(parentFile); +283 final int exitValue; +284 try { +285 exitValue = process.waitFor(); +286 } catch (InterruptedException ie) { +287 throw new AnalysisException("bundle-audit process interrupted", ie); +288 } +289 if (exitValue != 0) { +290 final String msg = String.format("Unexpected exit code from bundle-audit process; exit code: %s", exitValue); +291 throw new AnalysisException(msg); +292 } +293 BufferedReader rdr = null; +294 BufferedReader errReader = null; +295 try { +296 errReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8")); +297 while (errReader.ready()) { +298 final String error = errReader.readLine(); +299 LOGGER.warn(error); +300 } +301 rdr = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8")); +302 processBundlerAuditOutput(dependency, engine, rdr); +303 } catch (IOException ioe) { +304 LOGGER.warn("bundle-audit failure", ioe); +305 } finally { +306 if (errReader != null) { +307 try { +308 errReader.close(); +309 } catch (IOException ioe) { +310 LOGGER.warn("bundle-audit close failure", ioe); +311 } +312 } +313 if (null != rdr) { +314 try { +315 rdr.close(); +316 } catch (IOException ioe) { +317 LOGGER.warn("bundle-audit close failure", ioe); +318 } +319 } +320 } +321 +322 } +323 +324 /** +325 * Processes the bundler audit output. +326 * +327 * @param original the dependency +328 * @param engine the dependency-check engine +329 * @param rdr the reader of the report +330 * @throws IOException thrown if the report cannot be read. +331 */ +332 private void processBundlerAuditOutput(Dependency original, Engine engine, BufferedReader rdr) throws IOException { +333 final String parentName = original.getActualFile().getParentFile().getName(); +334 final String fileName = original.getFileName(); +335 final String filePath = original.getFilePath(); +336 Dependency dependency = null; +337 Vulnerability vulnerability = null; +338 String gem = null; +339 final Map<String, Dependency> map = new HashMap<String, Dependency>(); +340 boolean appendToDescription = false; +341 while (rdr.ready()) { +342 final String nextLine = rdr.readLine(); +343 if (null == nextLine) { +344 break; +345 } else if (nextLine.startsWith(NAME)) { +346 appendToDescription = false; +347 gem = nextLine.substring(NAME.length()); +348 if (!map.containsKey(gem)) { +349 map.put(gem, createDependencyForGem(engine, parentName, fileName, filePath, gem)); +350 } +351 dependency = map.get(gem); +352 LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine)); +353 } else if (nextLine.startsWith(VERSION)) { +354 vulnerability = createVulnerability(parentName, dependency, gem, nextLine); +355 } else if (nextLine.startsWith(ADVISORY)) { +356 setVulnerabilityName(parentName, dependency, vulnerability, nextLine); +357 } else if (nextLine.startsWith(CRITICALITY)) { +358 addCriticalityToVulnerability(parentName, vulnerability, nextLine); +359 } else if (nextLine.startsWith("URL: ")) { +360 addReferenceToVulnerability(parentName, vulnerability, nextLine); +361 } else if (nextLine.startsWith("Description:")) { +362 appendToDescription = true; 363 if (null != vulnerability) { -364 vulnerability.setDescription(vulnerability.getDescription() + nextLine + "\n"); -365 } -366 } -367 } -368 } -369 -370 /** -371 * Sets the vulnerability name. -372 * -373 * @param parentName the parent name -374 * @param dependency the dependency -375 * @param vulnerability the vulnerability -376 * @param nextLine the line to parse -377 */ -378 private void setVulnerabilityName(String parentName, Dependency dependency, Vulnerability vulnerability, String nextLine) { -379 final String advisory = nextLine.substring((ADVISORY.length())); -380 if (null != vulnerability) { -381 vulnerability.setName(advisory); -382 } -383 if (null != dependency) { -384 dependency.getVulnerabilities().add(vulnerability); // needed to wait for vulnerability name to avoid NPE -385 } -386 LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine)); -387 } -388 -389 /** -390 * Adds a reference to the vulnerability. -391 * -392 * @param parentName the parent name -393 * @param vulnerability the vulnerability -394 * @param nextLine the line to parse -395 */ -396 private void addReferenceToVulnerability(String parentName, Vulnerability vulnerability, String nextLine) { -397 final String url = nextLine.substring(("URL: ").length()); -398 if (null != vulnerability) { -399 final Reference ref = new Reference(); -400 ref.setName(vulnerability.getName()); -401 ref.setSource("bundle-audit"); -402 ref.setUrl(url); -403 vulnerability.getReferences().add(ref); -404 } -405 LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine)); -406 } -407 -408 /** -409 * Adds the criticality to the vulnerability -410 * -411 * @param parentName the parent name -412 * @param vulnerability the vulnerability -413 * @param nextLine the line to parse -414 */ -415 private void addCriticalityToVulnerability(String parentName, Vulnerability vulnerability, String nextLine) { -416 if (null != vulnerability) { -417 final String criticality = nextLine.substring(CRITICALITY.length()).trim(); -418 float score = -1.0f; -419 Vulnerability v = null; -420 try { -421 v = cvedb.getVulnerability(vulnerability.getName()); -422 } catch (DatabaseException ex) { -423 LOGGER.debug("Unable to look up vulnerability {}", vulnerability.getName()); -424 } -425 if (v != null) { -426 score = v.getCvssScore(); -427 } else if ("High".equalsIgnoreCase(criticality)) { -428 score = 8.5f; -429 } else if ("Medium".equalsIgnoreCase(criticality)) { -430 score = 5.5f; -431 } else if ("Low".equalsIgnoreCase(criticality)) { -432 score = 2.0f; -433 } -434 vulnerability.setCvssScore(score); -435 } -436 LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine)); -437 } -438 -439 /** -440 * Creates a vulnerability. -441 * -442 * @param parentName the parent name -443 * @param dependency the dependency -444 * @param gem the gem name -445 * @param nextLine the line to parse -446 * @return the vulnerability -447 */ -448 private Vulnerability createVulnerability(String parentName, Dependency dependency, String gem, String nextLine) { -449 Vulnerability vulnerability = null; -450 if (null != dependency) { -451 final String version = nextLine.substring(VERSION.length()); -452 dependency.getVersionEvidence().addEvidence( -453 "bundler-audit", -454 "Version", -455 version, -456 Confidence.HIGHEST); -457 vulnerability = new Vulnerability(); // don't add to dependency until we have name set later -458 vulnerability.setMatchedCPE( -459 String.format("cpe:/a:%1$s_project:%1$s:%2$s::~~~ruby~~", gem, version), -460 null); -461 vulnerability.setCvssAccessVector("-"); -462 vulnerability.setCvssAccessComplexity("-"); -463 vulnerability.setCvssAuthentication("-"); -464 vulnerability.setCvssAvailabilityImpact("-"); -465 vulnerability.setCvssConfidentialityImpact("-"); -466 vulnerability.setCvssIntegrityImpact("-"); -467 } -468 LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine)); -469 return vulnerability; -470 } -471 -472 /** -473 * Creates the dependency based off of the gem. -474 * -475 * @param engine the engine used for scanning -476 * @param parentName the gem parent -477 * @param fileName the file name -478 * @param filePath the file path -479 * @param gem the gem name -480 * @return the dependency to add -481 * @throws IOException thrown if a temporary gem file could not be written -482 */ -483 private Dependency createDependencyForGem(Engine engine, String parentName, String fileName, String filePath, String gem) throws IOException { -484 final File gemFile = new File(Settings.getTempDirectory(), gem + "_Gemfile.lock"); -485 gemFile.createNewFile(); -486 final String displayFileName = String.format("%s%c%s:%s", parentName, File.separatorChar, fileName, gem); -487 -488 FileUtils.write(gemFile, displayFileName, Charset.defaultCharset()); // unique contents to avoid dependency bundling -489 final Dependency dependency = new Dependency(gemFile); -490 dependency.getProductEvidence().addEvidence("bundler-audit", "Name", gem, Confidence.HIGHEST); -491 dependency.setDisplayFileName(displayFileName); -492 dependency.setFileName(fileName); -493 dependency.setFilePath(filePath); -494 engine.getDependencies().add(dependency); -495 return dependency; -496 } -497 } +364 vulnerability.setDescription("*** Vulnerability obtained from bundle-audit verbose report. " +365 + "Title link may not work. CPE below is guessed. CVSS score is estimated (-1.0 " +366 + " indicates unknown). See link below for full details. *** "); +367 } +368 } else if (appendToDescription) { +369 if (null != vulnerability) { +370 vulnerability.setDescription(vulnerability.getDescription() + nextLine + "\n"); +371 } +372 } +373 } +374 } +375 +376 /** +377 * Sets the vulnerability name. +378 * +379 * @param parentName the parent name +380 * @param dependency the dependency +381 * @param vulnerability the vulnerability +382 * @param nextLine the line to parse +383 */ +384 private void setVulnerabilityName(String parentName, Dependency dependency, Vulnerability vulnerability, String nextLine) { +385 final String advisory = nextLine.substring((ADVISORY.length())); +386 if (null != vulnerability) { +387 vulnerability.setName(advisory); +388 } +389 if (null != dependency) { +390 dependency.getVulnerabilities().add(vulnerability); // needed to wait for vulnerability name to avoid NPE +391 } +392 LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine)); +393 } +394 +395 /** +396 * Adds a reference to the vulnerability. +397 * +398 * @param parentName the parent name +399 * @param vulnerability the vulnerability +400 * @param nextLine the line to parse +401 */ +402 private void addReferenceToVulnerability(String parentName, Vulnerability vulnerability, String nextLine) { +403 final String url = nextLine.substring(("URL: ").length()); +404 if (null != vulnerability) { +405 final Reference ref = new Reference(); +406 ref.setName(vulnerability.getName()); +407 ref.setSource("bundle-audit"); +408 ref.setUrl(url); +409 vulnerability.getReferences().add(ref); +410 } +411 LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine)); +412 } +413 +414 /** +415 * Adds the criticality to the vulnerability +416 * +417 * @param parentName the parent name +418 * @param vulnerability the vulnerability +419 * @param nextLine the line to parse +420 */ +421 private void addCriticalityToVulnerability(String parentName, Vulnerability vulnerability, String nextLine) { +422 if (null != vulnerability) { +423 final String criticality = nextLine.substring(CRITICALITY.length()).trim(); +424 float score = -1.0f; +425 Vulnerability v = null; +426 try { +427 v = cvedb.getVulnerability(vulnerability.getName()); +428 } catch (DatabaseException ex) { +429 LOGGER.debug("Unable to look up vulnerability {}", vulnerability.getName()); +430 } +431 if (v != null) { +432 score = v.getCvssScore(); +433 } else if ("High".equalsIgnoreCase(criticality)) { +434 score = 8.5f; +435 } else if ("Medium".equalsIgnoreCase(criticality)) { +436 score = 5.5f; +437 } else if ("Low".equalsIgnoreCase(criticality)) { +438 score = 2.0f; +439 } +440 vulnerability.setCvssScore(score); +441 } +442 LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine)); +443 } +444 +445 /** +446 * Creates a vulnerability. +447 * +448 * @param parentName the parent name +449 * @param dependency the dependency +450 * @param gem the gem name +451 * @param nextLine the line to parse +452 * @return the vulnerability +453 */ +454 private Vulnerability createVulnerability(String parentName, Dependency dependency, String gem, String nextLine) { +455 Vulnerability vulnerability = null; +456 if (null != dependency) { +457 final String version = nextLine.substring(VERSION.length()); +458 dependency.getVersionEvidence().addEvidence( +459 "bundler-audit", +460 "Version", +461 version, +462 Confidence.HIGHEST); +463 vulnerability = new Vulnerability(); // don't add to dependency until we have name set later +464 vulnerability.setMatchedCPE( +465 String.format("cpe:/a:%1$s_project:%1$s:%2$s::~~~ruby~~", gem, version), +466 null); +467 vulnerability.setCvssAccessVector("-"); +468 vulnerability.setCvssAccessComplexity("-"); +469 vulnerability.setCvssAuthentication("-"); +470 vulnerability.setCvssAvailabilityImpact("-"); +471 vulnerability.setCvssConfidentialityImpact("-"); +472 vulnerability.setCvssIntegrityImpact("-"); +473 } +474 LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine)); +475 return vulnerability; +476 } +477 +478 /** +479 * Creates the dependency based off of the gem. +480 * +481 * @param engine the engine used for scanning +482 * @param parentName the gem parent +483 * @param fileName the file name +484 * @param filePath the file path +485 * @param gem the gem name +486 * @return the dependency to add +487 * @throws IOException thrown if a temporary gem file could not be written +488 */ +489 private Dependency createDependencyForGem(Engine engine, String parentName, String fileName, String filePath, String gem) throws IOException { +490 final File gemFile = new File(Settings.getTempDirectory(), gem + "_Gemfile.lock"); +491 if (!gemFile.createNewFile()) { +492 throw new IOException("Unable to create temporary gem file"); +493 } +494 final String displayFileName = String.format("%s%c%s:%s", parentName, File.separatorChar, fileName, gem); +495 +496 FileUtils.write(gemFile, displayFileName, Charset.defaultCharset()); // unique contents to avoid dependency bundling +497 final Dependency dependency = new Dependency(gemFile); +498 dependency.getProductEvidence().addEvidence("bundler-audit", "Name", gem, Confidence.HIGHEST); +499 dependency.setDisplayFileName(displayFileName); +500 dependency.setFileName(fileName); +501 dependency.setFilePath(filePath); +502 engine.getDependencies().add(dependency); +503 return dependency; +504 } +505 }
    diff --git a/xref/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.html index b461d876a..8a3555149 100644 --- a/xref/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.html @@ -21,7 +21,7 @@ 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * -16 * Copyright (c) 2016 Bianca Jiang. All Rights Reserved. +16 * Copyright (c) 2016 IBM Corporation. All Rights Reserved. 17 */ 18 package org.owasp.dependencycheck.analyzer; 19 @@ -51,7 +51,7 @@ 43 * {@link RubyGemspecAnalyzer}, so it will enabled/disabled with 44 * {@link RubyGemspecAnalyzer}. 45 * -46 * @author Bianca Jiang (biancajiang@gmail.com) +46 * @author Bianca Jiang (https://twitter.com/biancajiang) 47 */ 48 @Experimental 49 public class RubyBundlerAnalyzer extends RubyGemspecAnalyzer { diff --git a/xref/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzer.html index c6a328761..30aa18927 100644 --- a/xref/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzer.html @@ -225,33 +225,36 @@ 217 return name.contains(VERSION_FILE_NAME); 218 } 219 }); -220 for (File f : matchingFiles) { -221 try { -222 final List<String> lines = FileUtils.readLines(f, Charset.defaultCharset()); -223 if (lines.size() == 1) { //TODO other checking? -224 final String value = lines.get(0).trim(); -225 versionEvidences.addEvidence(GEMSPEC, "version", value, Confidence.HIGH); -226 } -227 } catch (IOException e) { -228 LOGGER.debug("Error reading gemspec", e); -229 } -230 } -231 } -232 } -233 -234 /** -235 * Sets the package path on the dependency. -236 * -237 * @param dep the dependency to alter -238 */ -239 private void setPackagePath(Dependency dep) { -240 final File file = new File(dep.getFilePath()); -241 final String parent = file.getParent(); -242 if (parent != null) { -243 dep.setPackagePath(parent); -244 } -245 } -246 } +220 if (matchingFiles == null) { +221 return; +222 } +223 for (File f : matchingFiles) { +224 try { +225 final List<String> lines = FileUtils.readLines(f, Charset.defaultCharset()); +226 if (lines.size() == 1) { //TODO other checking? +227 final String value = lines.get(0).trim(); +228 versionEvidences.addEvidence(GEMSPEC, "version", value, Confidence.HIGH); +229 } +230 } catch (IOException e) { +231 LOGGER.debug("Error reading gemspec", e); +232 } +233 } +234 } +235 } +236 +237 /** +238 * Sets the package path on the dependency. +239 * +240 * @param dep the dependency to alter +241 */ +242 private void setPackagePath(Dependency dep) { +243 final File file = new File(dep.getFilePath()); +244 final String parent = file.getParent(); +245 if (parent != null) { +246 dep.setPackagePath(parent); +247 } +248 } +249 }
    diff --git a/xref/org/owasp/dependencycheck/analyzer/SwiftPackageManagerAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/SwiftPackageManagerAnalyzer.html new file mode 100644 index 000000000..8d1c90a44 --- /dev/null +++ b/xref/org/owasp/dependencycheck/analyzer/SwiftPackageManagerAnalyzer.html @@ -0,0 +1,205 @@ + + + +SwiftPackageManagerAnalyzer 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 IBM Corporation. All Rights Reserved.
    +17   */
    +18  package org.owasp.dependencycheck.analyzer;
    +19  
    +20  import java.io.File;
    +21  import java.io.FileFilter;
    +22  import java.io.IOException;
    +23  import java.nio.charset.Charset;
    +24  import java.util.regex.Matcher;
    +25  import java.util.regex.Pattern;
    +26  
    +27  import org.apache.commons.io.FileUtils;
    +28  import org.owasp.dependencycheck.Engine;
    +29  import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
    +30  import org.owasp.dependencycheck.dependency.Confidence;
    +31  import org.owasp.dependencycheck.dependency.Dependency;
    +32  import org.owasp.dependencycheck.dependency.EvidenceCollection;
    +33  import org.owasp.dependencycheck.utils.FileFilterBuilder;
    +34  import org.owasp.dependencycheck.utils.Settings;
    +35  
    +36  /**
    +37   * This analyzer is used to analyze the SWIFT Package Manager
    +38   * (https://swift.org/package-manager/). It collects information about a package
    +39   * from Package.swift files.
    +40   *
    +41   * @author Bianca Jiang (https://twitter.com/biancajiang)
    +42   */
    +43  @Experimental
    +44  public class SwiftPackageManagerAnalyzer extends AbstractFileTypeAnalyzer {
    +45  
    +46      /**
    +47       * The name of the analyzer.
    +48       */
    +49      private static final String ANALYZER_NAME = "SWIFT Package Manager Analyzer";
    +50  
    +51      /**
    +52       * The phase that this analyzer is intended to run in.
    +53       */
    +54      private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
    +55  
    +56      /**
    +57       * The file name to scan.
    +58       */
    +59      public static final String SPM_FILE_NAME = "Package.swift";
    +60  
    +61      /**
    +62       * Filter that detects files named "package.json".
    +63       */
    +64      private static final FileFilter SPM_FILE_FILTER = FileFilterBuilder.newInstance().addFilenames(SPM_FILE_NAME).build();
    +65  
    +66      /**
    +67       * The capture group #1 is the block variable. e.g. "import
    +68       * PackageDescription let package = Package( name: "Gloss" )"
    +69       */
    +70      private static final Pattern SPM_BLOCK_PATTERN = Pattern.compile("let[^=]+=\\s*Package\\s*\\(\\s*([^)]*)\\s*\\)", Pattern.DOTALL);
    +71  
    +72      /**
    +73       * Returns the FileFilter
    +74       *
    +75       * @return the FileFilter
    +76       */
    +77      @Override
    +78      protected FileFilter getFileFilter() {
    +79          return SPM_FILE_FILTER;
    +80      }
    +81  
    +82      @Override
    +83      protected void initializeFileTypeAnalyzer() {
    +84          // NO-OP
    +85      }
    +86  
    +87      /**
    +88       * Returns the name of the analyzer.
    +89       *
    +90       * @return the name of the analyzer.
    +91       */
    +92      @Override
    +93      public String getName() {
    +94          return ANALYZER_NAME;
    +95      }
    +96  
    +97      /**
    +98       * Returns the phase that the analyzer is intended to run in.
    +99       *
    +100      * @return the phase that the analyzer is intended to run in.
    +101      */
    +102     @Override
    +103     public AnalysisPhase getAnalysisPhase() {
    +104         return ANALYSIS_PHASE;
    +105     }
    +106 
    +107     /**
    +108      * Returns the key used in the properties file to reference the analyzer's
    +109      * enabled property.
    +110      *
    +111      * @return the analyzer's enabled property setting key
    +112      */
    +113     @Override
    +114     protected String getAnalyzerEnabledSettingKey() {
    +115         return Settings.KEYS.ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED;
    +116     }
    +117 
    +118     @Override
    +119     protected void analyzeFileType(Dependency dependency, Engine engine)
    +120             throws AnalysisException {
    +121 
    +122         String contents;
    +123         try {
    +124             contents = FileUtils.readFileToString(dependency.getActualFile(), Charset.defaultCharset());
    +125         } catch (IOException e) {
    +126             throw new AnalysisException(
    +127                     "Problem occurred while reading dependency file.", e);
    +128         }
    +129         final Matcher matcher = SPM_BLOCK_PATTERN.matcher(contents);
    +130         if (matcher.find()) {
    +131             final String packageDescription = matcher.group(1);
    +132             if (packageDescription.isEmpty()) {
    +133                 return;
    +134             }
    +135 
    +136             final EvidenceCollection product = dependency.getProductEvidence();
    +137             final EvidenceCollection vendor = dependency.getVendorEvidence();
    +138 
    +139             //SPM is currently under development for SWIFT 3. Its current metadata includes package name and dependencies.
    +140             //Future interesting metadata: version, license, homepage, author, summary, etc.
    +141             final String name = addStringEvidence(product, packageDescription, "name", "name", Confidence.HIGHEST);
    +142             if (name != null && !name.isEmpty()) {
    +143                 vendor.addEvidence(SPM_FILE_NAME, "name_project", name, Confidence.HIGHEST);
    +144             }
    +145         }
    +146         setPackagePath(dependency);
    +147     }
    +148 
    +149     /**
    +150      * Extracts evidence from the package description and adds it to the given
    +151      * evidence collection.
    +152      *
    +153      * @param evidences the evidence collection to update
    +154      * @param packageDescription the text to extract evidence from
    +155      * @param field the name of the field being searched for
    +156      * @param fieldPattern the field pattern within the contents to search for
    +157      * @param confidence the confidence level of the evidence if found
    +158      * @return the string that was added as evidence
    +159      */
    +160     private String addStringEvidence(EvidenceCollection evidences,
    +161             String packageDescription, String field, String fieldPattern, Confidence confidence) {
    +162         String value = "";
    +163 
    +164         final Matcher matcher = Pattern.compile(
    +165                 String.format("%s *:\\s*\"([^\"]*)", fieldPattern), Pattern.DOTALL).matcher(packageDescription);
    +166         if (matcher.find()) {
    +167             value = matcher.group(1);
    +168         }
    +169 
    +170         if (value != null) {
    +171             value = value.trim();
    +172             if (value.length() > 0) {
    +173                 evidences.addEvidence(SPM_FILE_NAME, field, value, confidence);
    +174             }
    +175         }
    +176 
    +177         return value;
    +178     }
    +179 
    +180     /**
    +181      * Sets the package path on the given dependency.
    +182      *
    +183      * @param dep the dependency to update
    +184      */
    +185     private void setPackagePath(Dependency dep) {
    +186         final File file = new File(dep.getFilePath());
    +187         final String parent = file.getParent();
    +188         if (parent != null) {
    +189             dep.setPackagePath(parent);
    +190         }
    +191     }
    +192 }
    +
    +
    + + + diff --git a/xref/org/owasp/dependencycheck/analyzer/exception/package-frame.html b/xref/org/owasp/dependencycheck/analyzer/exception/package-frame.html index 85ff8cbcd..b0971b9e8 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.2 Reference Package org.owasp.dependencycheck.analyzer.exception + Dependency-Check 1.4.3 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 ff80f50bd..97d576deb 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.2 Reference Package org.owasp.dependencycheck.analyzer.exception + Dependency-Check 1.4.3 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 d0f34d2c1..71b88d8fd 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.2 Reference Package org.owasp.dependencycheck.analyzer + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.analyzer @@ -53,6 +53,9 @@
  • ClassNameInformation +
  • +
  • + CocoaPodsAnalyzer
  • ComposerLockAnalyzer @@ -116,6 +119,9 @@
  • RubyGemspecAnalyzer +
  • +
  • + SwiftPackageManagerAnalyzer
  • VulnerabilitySuppressionAnalyzer diff --git a/xref/org/owasp/dependencycheck/analyzer/package-summary.html b/xref/org/owasp/dependencycheck/analyzer/package-summary.html index 7c7fb82dd..32f07292a 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.2 Reference Package org.owasp.dependencycheck.analyzer + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.analyzer @@ -99,6 +99,11 @@
  • + + + + + +
    ClassNameInformation
    + CocoaPodsAnalyzer +
    @@ -204,6 +209,11 @@ RubyGemspecAnalyzer
    + SwiftPackageManagerAnalyzer +
    diff --git a/xref/org/owasp/dependencycheck/ant/logging/package-frame.html b/xref/org/owasp/dependencycheck/ant/logging/package-frame.html index 0423f6497..7e6d7ad72 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.2 Reference Package org.owasp.dependencycheck.ant.logging + Dependency-Check 1.4.3 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 f7f836f5c..38e88e0de 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.2 Reference Package org.owasp.dependencycheck.ant.logging + Dependency-Check 1.4.3 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 8687f3fb7..b7dba63dd 100644 --- a/xref/org/owasp/dependencycheck/data/central/CentralSearch.html +++ b/xref/org/owasp/dependencycheck/data/central/CentralSearch.html @@ -69,8 +69,8 @@ 61 /** 62 * Creates a NexusSearch for the given repository URL. 63 * -64 * @param rootURL the URL of the repository on which searches should execute. Only parameters are added to this (so it should -65 * end in /select) +64 * @param rootURL the URL of the repository on which searches should +65 * execute. Only parameters are added to this (so it should end in /select) 66 */ 67 public CentralSearch(URL rootURL) { 68 this.rootURL = rootURL; @@ -84,99 +84,96 @@ 76 } 77 78 /** -79 * Searches the configured Central URL for the given sha1 hash. If the artifact is found, a <code>MavenArtifact</code> is -80 * populated with the GAV. -81 * -82 * @param sha1 the SHA-1 hash string for which to search -83 * @return the populated Maven GAV. -84 * @throws IOException if it's unable to connect to the specified repository or if the specified artifact is not found. -85 */ -86 public List<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 } -90 -91 final URL url = new URL(rootURL + String.format("?q=1:\"%s\"&wt=xml", sha1)); -92 -93 LOGGER.debug("Searching Central url {}", url); +79 * Searches the configured Central URL for the given sha1 hash. If the +80 * artifact is found, a <code>MavenArtifact</code> is populated with the +81 * GAV. +82 * +83 * @param sha1 the SHA-1 hash string for which to search +84 * @return the populated Maven GAV. +85 * @throws IOException if it's unable to connect to the specified repository +86 * or if the specified artifact is not found. +87 */ +88 public List<MavenArtifact> searchSha1(String sha1) throws IOException { +89 if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) { +90 throw new IllegalArgumentException("Invalid SHA1 format"); +91 } +92 List<MavenArtifact> result = null; +93 final URL url = new URL(rootURL + String.format("?q=1:\"%s\"&wt=xml", sha1)); 94 -95 // Determine if we need to use a proxy. The rules: -96 // 1) If the proxy is set, AND the setting is set to true, use the proxy -97 // 2) Otherwise, don't use the proxy (either the proxy isn't configured, -98 // or proxy is specifically set to false) -99 final HttpURLConnection conn = URLConnectionFactory.createHttpURLConnection(url, useProxy); -100 -101 conn.setDoOutput(true); +95 LOGGER.debug("Searching Central url {}", url); +96 +97 // Determine if we need to use a proxy. The rules: +98 // 1) If the proxy is set, AND the setting is set to true, use the proxy +99 // 2) Otherwise, don't use the proxy (either the proxy isn't configured, +100 // or proxy is specifically set to false) +101 final HttpURLConnection conn = URLConnectionFactory.createHttpURLConnection(url, useProxy); 102 -103 // JSON would be more elegant, but there's not currently a dependency -104 // on JSON, so don't want to add one just for this -105 conn.addRequestProperty("Accept", "application/xml"); -106 conn.connect(); -107 -108 if (conn.getResponseCode() == 200) { -109 boolean missing = false; -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 numFound = xpath.evaluate("/response/result/@numFound", doc); -116 if ("0".equals(numFound)) { -117 missing = true; -118 } else { -119 final List<MavenArtifact> result = new ArrayList<MavenArtifact>(); -120 final NodeList docs = (NodeList) xpath.evaluate("/response/result/doc", doc, XPathConstants.NODESET); -121 for (int i = 0; i < docs.getLength(); i++) { -122 final String g = xpath.evaluate("./str[@name='g']", docs.item(i)); -123 LOGGER.trace("GroupId: {}", g); -124 final String a = xpath.evaluate("./str[@name='a']", docs.item(i)); -125 LOGGER.trace("ArtifactId: {}", a); -126 final String v = xpath.evaluate("./str[@name='v']", docs.item(i)); -127 NodeList atts = (NodeList) xpath.evaluate("./arr[@name='ec']/str", docs.item(i), XPathConstants.NODESET); -128 boolean pomAvailable = false; -129 boolean jarAvailable = false; -130 for (int x = 0; x < atts.getLength(); x++) { -131 final String tmp = xpath.evaluate(".", atts.item(x)); -132 if (".pom".equals(tmp)) { -133 pomAvailable = true; -134 } else if (".jar".equals(tmp)) { -135 jarAvailable = true; -136 } -137 } -138 -139 atts = (NodeList) xpath.evaluate("./arr[@name='tags']/str", docs.item(i), XPathConstants.NODESET); -140 boolean useHTTPS = false; -141 for (int x = 0; x < atts.getLength(); x++) { -142 final String tmp = xpath.evaluate(".", atts.item(x)); -143 if ("https".equals(tmp)) { -144 useHTTPS = true; -145 } -146 } -147 -148 LOGGER.trace("Version: {}", v); -149 result.add(new MavenArtifact(g, a, v, jarAvailable, pomAvailable, useHTTPS)); -150 } -151 -152 return result; -153 } -154 } catch (Throwable e) { -155 // Anything else is jacked up XML stuff that we really can't recover -156 // from well -157 throw new IOException(e.getMessage(), e); -158 } -159 -160 if (missing) { -161 throw new FileNotFoundException("Artifact not found in Central"); -162 } -163 } else { -164 LOGGER.debug("Could not connect to Central received response code: {} {}", -165 conn.getResponseCode(), conn.getResponseMessage()); -166 throw new IOException("Could not connect to Central"); -167 } -168 -169 return null; -170 } -171 } +103 conn.setDoOutput(true); +104 +105 // JSON would be more elegant, but there's not currently a dependency +106 // on JSON, so don't want to add one just for this +107 conn.addRequestProperty("Accept", "application/xml"); +108 conn.connect(); +109 +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 }
    diff --git a/xref/org/owasp/dependencycheck/data/central/package-frame.html b/xref/org/owasp/dependencycheck/data/central/package-frame.html index a42026d23..1110619b7 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.2 Reference Package org.owasp.dependencycheck.data.central + Dependency-Check 1.4.3 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 a49bcaf80..76122895b 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.2 Reference Package org.owasp.dependencycheck.data.central + Dependency-Check 1.4.3 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 dfb5400ed..8430b0865 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.2 Reference Package org.owasp.dependencycheck.data.composer + Dependency-Check 1.4.3 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 4de001e3f..66a530780 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.2 Reference Package org.owasp.dependencycheck.data.composer + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.composer diff --git a/xref/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.html b/xref/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.html index ed2431682..d8fc2cfaf 100644 --- a/xref/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.html +++ b/xref/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.html @@ -217,107 +217,110 @@ 209 210 final Set<Pair<String, String>> data = cve.getVendorProductList(); 211 for (Pair<String, String> pair : data) { -212 v.setStringValue(pair.getLeft()); -213 p.setStringValue(pair.getRight()); -214 indexWriter.addDocument(doc); -215 resetFieldAnalyzer(); -216 } -217 } catch (DatabaseException ex) { -218 LOGGER.debug("", ex); -219 throw new IndexException("Error reading CPE data", ex); -220 } -221 } catch (CorruptIndexException ex) { -222 throw new IndexException("Unable to close an in-memory index", ex); -223 } catch (IOException ex) { -224 throw new IndexException("Unable to close an in-memory index", ex); -225 } finally { -226 if (indexWriter != null) { -227 try { -228 try { -229 indexWriter.commit(); -230 } finally { -231 indexWriter.close(true); -232 } -233 } catch (CorruptIndexException ex) { -234 throw new IndexException("Unable to close an in-memory index", ex); -235 } catch (IOException ex) { -236 throw new IndexException("Unable to close an in-memory index", ex); -237 } -238 if (analyzer != null) { -239 analyzer.close(); +212 //todo figure out why there are null products +213 if (pair.getLeft() != null && pair.getRight() != null) { +214 v.setStringValue(pair.getLeft()); +215 p.setStringValue(pair.getRight()); +216 indexWriter.addDocument(doc); +217 resetFieldAnalyzer(); +218 } +219 } +220 } catch (DatabaseException ex) { +221 LOGGER.debug("", ex); +222 throw new IndexException("Error reading CPE data", ex); +223 } +224 } catch (CorruptIndexException ex) { +225 throw new IndexException("Unable to close an in-memory index", ex); +226 } catch (IOException ex) { +227 throw new IndexException("Unable to close an in-memory index", ex); +228 } finally { +229 if (indexWriter != null) { +230 try { +231 try { +232 indexWriter.commit(); +233 } finally { +234 indexWriter.close(true); +235 } +236 } catch (CorruptIndexException ex) { +237 throw new IndexException("Unable to close an in-memory index", ex); +238 } catch (IOException ex) { +239 throw new IndexException("Unable to close an in-memory index", ex); 240 } -241 } -242 } -243 } -244 -245 /** -246 * Resets the product and vendor field analyzers. -247 */ -248 private void resetFieldAnalyzer() { -249 if (productFieldAnalyzer != null) { -250 productFieldAnalyzer.clear(); -251 } -252 if (vendorFieldAnalyzer != null) { -253 vendorFieldAnalyzer.clear(); +241 if (analyzer != null) { +242 analyzer.close(); +243 } +244 } +245 } +246 } +247 +248 /** +249 * Resets the product and vendor field analyzers. +250 */ +251 private void resetFieldAnalyzer() { +252 if (productFieldAnalyzer != null) { +253 productFieldAnalyzer.clear(); 254 } -255 } -256 -257 /** -258 * Searches the index using the given search string. -259 * -260 * @param searchString the query text -261 * @param maxQueryResults the maximum number of documents to return -262 * @return the TopDocs found by the search -263 * @throws ParseException thrown when the searchString is invalid -264 * @throws IOException is thrown if there is an issue with the underlying -265 * Index -266 */ -267 public TopDocs search(String searchString, int maxQueryResults) throws ParseException, IOException { -268 if (searchString == null || searchString.trim().isEmpty()) { -269 throw new ParseException("Query is null or empty"); -270 } -271 LOGGER.debug(searchString); -272 final Query query = queryParser.parse(searchString); -273 return search(query, maxQueryResults); -274 } -275 -276 /** -277 * Searches the index using the given query. -278 * -279 * @param query the query used to search the index -280 * @param maxQueryResults the max number of results to return -281 * @return the TopDocs found be the query -282 * @throws CorruptIndexException thrown if the Index is corrupt -283 * @throws IOException thrown if there is an IOException -284 */ -285 public TopDocs search(Query query, int maxQueryResults) throws CorruptIndexException, IOException { -286 resetFieldAnalyzer(); -287 return indexSearcher.search(query, maxQueryResults); -288 } -289 -290 /** -291 * Retrieves a document from the Index. -292 * -293 * @param documentId the id of the document to retrieve -294 * @return the Document -295 * @throws IOException thrown if there is an IOException -296 */ -297 public Document getDocument(int documentId) throws IOException { -298 return indexSearcher.doc(documentId); -299 } -300 -301 /** -302 * Returns the number of CPE entries stored in the index. -303 * -304 * @return the number of CPE entries stored in the index -305 */ -306 public int numDocs() { -307 if (indexReader == null) { -308 return -1; -309 } -310 return indexReader.numDocs(); -311 } -312 } +255 if (vendorFieldAnalyzer != null) { +256 vendorFieldAnalyzer.clear(); +257 } +258 } +259 +260 /** +261 * Searches the index using the given search string. +262 * +263 * @param searchString the query text +264 * @param maxQueryResults the maximum number of documents to return +265 * @return the TopDocs found by the search +266 * @throws ParseException thrown when the searchString is invalid +267 * @throws IOException is thrown if there is an issue with the underlying +268 * Index +269 */ +270 public TopDocs search(String searchString, int maxQueryResults) throws ParseException, IOException { +271 if (searchString == null || searchString.trim().isEmpty()) { +272 throw new ParseException("Query is null or empty"); +273 } +274 LOGGER.debug(searchString); +275 final Query query = queryParser.parse(searchString); +276 return search(query, maxQueryResults); +277 } +278 +279 /** +280 * Searches the index using the given query. +281 * +282 * @param query the query used to search the index +283 * @param maxQueryResults the max number of results to return +284 * @return the TopDocs found be the query +285 * @throws CorruptIndexException thrown if the Index is corrupt +286 * @throws IOException thrown if there is an IOException +287 */ +288 public TopDocs search(Query query, int maxQueryResults) throws CorruptIndexException, IOException { +289 resetFieldAnalyzer(); +290 return indexSearcher.search(query, maxQueryResults); +291 } +292 +293 /** +294 * Retrieves a document from the Index. +295 * +296 * @param documentId the id of the document to retrieve +297 * @return the Document +298 * @throws IOException thrown if there is an IOException +299 */ +300 public Document getDocument(int documentId) throws IOException { +301 return indexSearcher.doc(documentId); +302 } +303 +304 /** +305 * Returns the number of CPE entries stored in the index. +306 * +307 * @return the number of CPE entries stored in the index +308 */ +309 public int numDocs() { +310 if (indexReader == null) { +311 return -1; +312 } +313 return indexReader.numDocs(); +314 } +315 }
    diff --git a/xref/org/owasp/dependencycheck/data/cpe/package-frame.html b/xref/org/owasp/dependencycheck/data/cpe/package-frame.html index 2757b0930..36b62e432 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.2 Reference Package org.owasp.dependencycheck.data.cpe + Dependency-Check 1.4.3 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 5ad4cf289..2884a27b2 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.2 Reference Package org.owasp.dependencycheck.data.cpe + Dependency-Check 1.4.3 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 a93fb5865..e78c9f00d 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.2 Reference Package org.owasp.dependencycheck.data.cwe + Dependency-Check 1.4.3 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 f2208637a..c7525ee6c 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.2 Reference Package org.owasp.dependencycheck.data.cwe + Dependency-Check 1.4.3 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 8d781fe1d..e49c33407 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.2 Reference Package org.owasp.dependencycheck.data.lucene + Dependency-Check 1.4.3 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 3ec952763..4d36964af 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.2 Reference Package org.owasp.dependencycheck.data.lucene + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.lucene diff --git a/xref/org/owasp/dependencycheck/data/nexus/package-frame.html b/xref/org/owasp/dependencycheck/data/nexus/package-frame.html index 27cdda001..eb8df971d 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.2 Reference Package org.owasp.dependencycheck.data.nexus + Dependency-Check 1.4.3 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 8721636f3..61551b25b 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.2 Reference Package org.owasp.dependencycheck.data.nexus + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.nexus diff --git a/xref/org/owasp/dependencycheck/data/nuget/package-frame.html b/xref/org/owasp/dependencycheck/data/nuget/package-frame.html index a75ac4aa4..31ebdccda 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.2 Reference Package org.owasp.dependencycheck.data.nuget + Dependency-Check 1.4.3 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 bbc99da59..eeaa8ffe1 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.2 Reference Package org.owasp.dependencycheck.data.nuget + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.nuget diff --git a/xref/org/owasp/dependencycheck/data/nvdcve/ConnectionFactory.html b/xref/org/owasp/dependencycheck/data/nvdcve/ConnectionFactory.html index ed37e7d2b..7ac37a94a 100644 --- a/xref/org/owasp/dependencycheck/data/nvdcve/ConnectionFactory.html +++ b/xref/org/owasp/dependencycheck/data/nvdcve/ConnectionFactory.html @@ -44,350 +44,371 @@ 36 import org.slf4j.LoggerFactory; 37 38 /** -39 * Loads the configured database driver and returns the database connection. If the embedded H2 database is used obtaining a -40 * connection will ensure the database file exists and that the appropriate table structure has been created. -41 * -42 * @author Jeremy Long -43 */ -44 public final class ConnectionFactory { -45 -46 /** -47 * The Logger. -48 */ -49 private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionFactory.class); -50 /** -51 * The version of the current DB Schema. -52 */ -53 public static final String DB_SCHEMA_VERSION = Settings.getString(Settings.KEYS.DB_VERSION); -54 /** -55 * Resource location for SQL file used to create the database schema. -56 */ -57 public static final String DB_STRUCTURE_RESOURCE = "data/initialize.sql"; -58 /** -59 * Resource location for SQL file used to create the database schema. -60 */ -61 public static final String DB_STRUCTURE_UPDATE_RESOURCE = "data/upgrade_%s.sql"; -62 /** -63 * The URL that discusses upgrading non-H2 databases. -64 */ -65 public static final String UPGRADE_HELP_URL = "http://jeremylong.github.io/DependencyCheck/data/upgrade.html"; -66 /** -67 * The database driver used to connect to the database. -68 */ -69 private static Driver driver = null; -70 /** -71 * The database connection string. -72 */ -73 private static String connectionString = null; -74 /** -75 * The username to connect to the database. -76 */ -77 private static String userName = null; -78 /** -79 * The password for the database. -80 */ -81 private static String password = null; -82 -83 /** -84 * Private constructor for this factory class; no instance is ever needed. -85 */ -86 private ConnectionFactory() { -87 } -88 -89 /** -90 * Initializes the connection factory. Ensuring that the appropriate drivers are loaded and that a connection can be made -91 * successfully. -92 * -93 * @throws DatabaseException thrown if we are unable to connect to the database -94 */ -95 public static synchronized void initialize() throws DatabaseException { -96 //this only needs to be called once. -97 if (connectionString != null) { -98 return; -99 } -100 Connection conn = null; -101 try { -102 //load the driver if necessary -103 final String driverName = Settings.getString(Settings.KEYS.DB_DRIVER_NAME, ""); -104 if (!driverName.isEmpty()) { //likely need to load the correct driver -105 LOGGER.debug("Loading driver: {}", driverName); -106 final String driverPath = Settings.getString(Settings.KEYS.DB_DRIVER_PATH, ""); -107 try { -108 if (!driverPath.isEmpty()) { -109 LOGGER.debug("Loading driver from: {}", driverPath); -110 driver = DriverLoader.load(driverName, driverPath); -111 } else { -112 driver = DriverLoader.load(driverName); -113 } -114 } catch (DriverLoadException ex) { -115 LOGGER.debug("Unable to load database driver", ex); -116 throw new DatabaseException("Unable to load database driver"); -117 } -118 } -119 userName = Settings.getString(Settings.KEYS.DB_USER, "dcuser"); -120 //yes, yes - hard-coded password - only if there isn't one in the properties file. -121 password = Settings.getString(Settings.KEYS.DB_PASSWORD, "DC-Pass1337!"); -122 try { -123 connectionString = Settings.getConnectionString( -124 Settings.KEYS.DB_CONNECTION_STRING, -125 Settings.KEYS.DB_FILE_NAME); -126 } catch (IOException ex) { -127 LOGGER.debug( -128 "Unable to retrieve the database connection string", ex); -129 throw new DatabaseException("Unable to retrieve the database connection string"); -130 } -131 boolean shouldCreateSchema = false; -132 try { -133 if (connectionString.startsWith("jdbc:h2:file:")) { //H2 -134 shouldCreateSchema = !h2DataFileExists(); -135 LOGGER.debug("Need to create DB Structure: {}", shouldCreateSchema); -136 } -137 } catch (IOException ioex) { -138 LOGGER.debug("Unable to verify database exists", ioex); -139 throw new DatabaseException("Unable to verify database exists"); -140 } -141 LOGGER.debug("Loading database connection"); -142 LOGGER.debug("Connection String: {}", connectionString); -143 LOGGER.debug("Database User: {}", userName); -144 -145 try { -146 conn = DriverManager.getConnection(connectionString, userName, password); -147 } catch (SQLException ex) { -148 if (ex.getMessage().contains("java.net.UnknownHostException") && connectionString.contains("AUTO_SERVER=TRUE;")) { -149 connectionString = connectionString.replace("AUTO_SERVER=TRUE;", ""); -150 try { -151 conn = DriverManager.getConnection(connectionString, userName, password); -152 Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString); -153 LOGGER.debug( -154 "Unable to start the database in server mode; reverting to single user mode"); -155 } catch (SQLException sqlex) { -156 LOGGER.debug("Unable to connect to the database", ex); -157 throw new DatabaseException("Unable to connect to the database"); -158 } -159 } else { -160 LOGGER.debug("Unable to connect to the database", ex); -161 throw new DatabaseException("Unable to connect to the database"); -162 } -163 } -164 -165 if (shouldCreateSchema) { -166 try { -167 createTables(conn); -168 } catch (DatabaseException dex) { -169 LOGGER.debug("", dex); -170 throw new DatabaseException("Unable to create the database structure"); -171 } -172 } -173 try { -174 ensureSchemaVersion(conn); -175 } catch (DatabaseException dex) { -176 LOGGER.debug("", dex); -177 throw new DatabaseException("Database schema does not match this version of dependency-check", dex); -178 } -179 } finally { -180 if (conn != null) { -181 try { -182 conn.close(); -183 } catch (SQLException ex) { -184 LOGGER.debug("An error occurred closing the connection", ex); -185 } -186 } -187 } -188 } -189 -190 /** -191 * Cleans up resources and unloads any registered database drivers. This needs to be called to ensure the driver is -192 * unregistered prior to the finalize method being called as during shutdown the class loader used to load the driver may be -193 * unloaded prior to the driver being de-registered. -194 */ -195 public static synchronized void cleanup() { -196 if (driver != null) { -197 try { -198 DriverManager.deregisterDriver(driver); -199 } catch (SQLException ex) { -200 LOGGER.debug("An error occurred unloading the database driver", ex); -201 } catch (Throwable unexpected) { -202 LOGGER.debug( -203 "An unexpected throwable occurred unloading the database driver", unexpected); -204 } -205 driver = null; -206 } -207 connectionString = null; -208 userName = null; -209 password = null; -210 } -211 -212 /** -213 * Constructs a new database connection object per the database configuration. -214 * -215 * @return a database connection object -216 * @throws DatabaseException thrown if there is an exception loading the database connection -217 */ -218 public static Connection getConnection() throws DatabaseException { -219 initialize(); -220 Connection conn = null; -221 try { -222 conn = DriverManager.getConnection(connectionString, userName, password); -223 } catch (SQLException ex) { -224 LOGGER.debug("", ex); -225 throw new DatabaseException("Unable to connect to the database"); -226 } -227 return conn; -228 } -229 -230 /** -231 * Determines if the H2 database file exists. If it does not exist then the data structure will need to be created. -232 * -233 * @return true if the H2 database file does not exist; otherwise false -234 * @throws IOException thrown if the data directory does not exist and cannot be created -235 */ -236 private static boolean h2DataFileExists() throws IOException { -237 final File dir = Settings.getDataDirectory(); -238 final String fileName = Settings.getString(Settings.KEYS.DB_FILE_NAME); -239 final File file = new File(dir, fileName); -240 return file.exists(); -241 } -242 -243 /** -244 * Creates the database structure (tables and indexes) to store the CVE data. -245 * -246 * @param conn the database connection -247 * @throws DatabaseException thrown if there is a Database Exception -248 */ -249 private static void createTables(Connection conn) throws DatabaseException { -250 LOGGER.debug("Creating database structure"); -251 InputStream is = null; -252 try { -253 is = ConnectionFactory.class.getClassLoader().getResourceAsStream(DB_STRUCTURE_RESOURCE); -254 final String dbStructure = IOUtils.toString(is, "UTF-8"); -255 -256 Statement statement = null; -257 try { -258 statement = conn.createStatement(); -259 statement.execute(dbStructure); -260 } catch (SQLException ex) { -261 LOGGER.debug("", ex); -262 throw new DatabaseException("Unable to create database statement", ex); -263 } finally { -264 DBUtils.closeStatement(statement); -265 } -266 } catch (IOException ex) { -267 throw new DatabaseException("Unable to create database schema", ex); -268 } finally { -269 IOUtils.closeQuietly(is); -270 } -271 } -272 -273 /** -274 * Updates the database schema by loading the upgrade script for the version specified. The intended use is that if the -275 * current schema version is 2.9 then we would call updateSchema(conn, "2.9"). This would load the upgrade_2.9.sql file and -276 * execute it against the database. The upgrade script must update the 'version' in the properties table. -277 * -278 * @param conn the database connection object -279 * @param appExpectedVersion the schema version that the application expects -280 * @param currentDbVersion the current schema version of the database -281 * @throws DatabaseException thrown if there is an exception upgrading the database schema -282 */ -283 private static void updateSchema(Connection conn, DependencyVersion appExpectedVersion, DependencyVersion currentDbVersion) -284 throws DatabaseException { -285 -286 final String databaseProductName; -287 try { -288 databaseProductName = conn.getMetaData().getDatabaseProductName(); -289 } catch (SQLException ex) { -290 throw new DatabaseException("Unable to get the database product name"); -291 } -292 if ("h2".equalsIgnoreCase(databaseProductName)) { -293 LOGGER.debug("Updating database structure"); -294 InputStream is = null; -295 String updateFile = null; -296 try { -297 updateFile = String.format(DB_STRUCTURE_UPDATE_RESOURCE, currentDbVersion.toString()); -298 is = ConnectionFactory.class.getClassLoader().getResourceAsStream(updateFile); -299 if (is == null) { -300 throw new DatabaseException(String.format("Unable to load update file '%s'", updateFile)); -301 } -302 final String dbStructureUpdate = IOUtils.toString(is, "UTF-8"); -303 -304 Statement statement = null; -305 try { -306 statement = conn.createStatement(); -307 final boolean success = statement.execute(dbStructureUpdate); -308 if (!success && statement.getUpdateCount() <= 0) { -309 throw new DatabaseException(String.format("Unable to upgrade the database schema to %s", -310 currentDbVersion.toString())); -311 } -312 } catch (SQLException ex) { -313 LOGGER.debug("", ex); -314 throw new DatabaseException("Unable to update database schema", ex); -315 } finally { -316 DBUtils.closeStatement(statement); -317 } -318 } catch (IOException ex) { -319 final String msg = String.format("Upgrade SQL file does not exist: %s", updateFile); -320 throw new DatabaseException(msg, ex); -321 } finally { -322 IOUtils.closeQuietly(is); -323 } -324 } else { -325 final int e0 = Integer.parseInt(appExpectedVersion.getVersionParts().get(0)); -326 final int c0 = Integer.parseInt(currentDbVersion.getVersionParts().get(0)); -327 final int e1 = Integer.parseInt(appExpectedVersion.getVersionParts().get(1)); -328 final int c1 = Integer.parseInt(currentDbVersion.getVersionParts().get(1)); -329 if (e0 == c0 && e1 < c1) { -330 LOGGER.warn("A new version of dependency-check is available; consider upgrading"); -331 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false); -332 } else if (e0 == c0 && e1 == c1) { -333 //do nothing - not sure how we got here, but just incase... -334 } else { -335 LOGGER.error("The database schema must be upgraded to use this version of dependency-check. Please see {} for more information.", -336 UPGRADE_HELP_URL); -337 throw new DatabaseException("Database schema is out of date"); -338 } -339 } -340 } -341 -342 /** -343 * Counter to ensure that calls to ensureSchemaVersion does not end up in an endless loop. -344 */ -345 private static int callDepth = 0; -346 -347 /** -348 * Uses the provided connection to check the specified schema version within the database. -349 * -350 * @param conn the database connection object -351 * @throws DatabaseException thrown if the schema version is not compatible with this version of dependency-check -352 */ -353 private static void ensureSchemaVersion(Connection conn) throws DatabaseException { -354 ResultSet rs = null; -355 PreparedStatement ps = null; -356 try { -357 //TODO convert this to use DatabaseProperties -358 ps = conn.prepareStatement("SELECT value FROM properties WHERE id = 'version'"); -359 rs = ps.executeQuery(); -360 if (rs.next()) { -361 final DependencyVersion appDbVersion = DependencyVersionUtil.parseVersion(DB_SCHEMA_VERSION); -362 final DependencyVersion db = DependencyVersionUtil.parseVersion(rs.getString(1)); -363 if (appDbVersion.compareTo(db) > 0) { -364 LOGGER.debug("Current Schema: {}", DB_SCHEMA_VERSION); -365 LOGGER.debug("DB Schema: {}", rs.getString(1)); -366 updateSchema(conn, appDbVersion, db); -367 if (++callDepth < 10) { -368 ensureSchemaVersion(conn); -369 } -370 } -371 } else { -372 throw new DatabaseException("Database schema is missing"); -373 } -374 } catch (SQLException ex) { -375 LOGGER.debug("", ex); -376 throw new DatabaseException("Unable to check the database schema version"); -377 } finally { -378 DBUtils.closeResultSet(rs); -379 DBUtils.closeStatement(ps); -380 } -381 } -382 } +39 * Loads the configured database driver and returns the database connection. If +40 * the embedded H2 database is used obtaining a connection will ensure the +41 * database file exists and that the appropriate table structure has been +42 * created. +43 * +44 * @author Jeremy Long +45 */ +46 public final class ConnectionFactory { +47 +48 /** +49 * The Logger. +50 */ +51 private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionFactory.class); +52 /** +53 * The version of the current DB Schema. +54 */ +55 public static final String DB_SCHEMA_VERSION = Settings.getString(Settings.KEYS.DB_VERSION); +56 /** +57 * Resource location for SQL file used to create the database schema. +58 */ +59 public static final String DB_STRUCTURE_RESOURCE = "data/initialize.sql"; +60 /** +61 * Resource location for SQL file used to create the database schema. +62 */ +63 public static final String DB_STRUCTURE_UPDATE_RESOURCE = "data/upgrade_%s.sql"; +64 /** +65 * The URL that discusses upgrading non-H2 databases. +66 */ +67 public static final String UPGRADE_HELP_URL = "http://jeremylong.github.io/DependencyCheck/data/upgrade.html"; +68 /** +69 * The database driver used to connect to the database. +70 */ +71 private static Driver driver = null; +72 /** +73 * The database connection string. +74 */ +75 private static String connectionString = null; +76 /** +77 * The username to connect to the database. +78 */ +79 private static String userName = null; +80 /** +81 * The password for the database. +82 */ +83 private static String password = null; +84 +85 /** +86 * Private constructor for this factory class; no instance is ever needed. +87 */ +88 private ConnectionFactory() { +89 } +90 +91 /** +92 * Initializes the connection factory. Ensuring that the appropriate drivers +93 * are loaded and that a connection can be made successfully. +94 * +95 * @throws DatabaseException thrown if we are unable to connect to the +96 * database +97 */ +98 public static void initialize() throws DatabaseException { +99 //this only needs to be called once. +100 if (connectionString != null) { +101 return; +102 } +103 Connection conn = null; +104 try { +105 //load the driver if necessary +106 final String driverName = Settings.getString(Settings.KEYS.DB_DRIVER_NAME, ""); +107 if (!driverName.isEmpty()) { //likely need to load the correct driver +108 LOGGER.debug("Loading driver: {}", driverName); +109 final String driverPath = Settings.getString(Settings.KEYS.DB_DRIVER_PATH, ""); +110 try { +111 if (!driverPath.isEmpty()) { +112 LOGGER.debug("Loading driver from: {}", driverPath); +113 driver = DriverLoader.load(driverName, driverPath); +114 } else { +115 driver = DriverLoader.load(driverName); +116 } +117 } catch (DriverLoadException ex) { +118 LOGGER.debug("Unable to load database driver", ex); +119 throw new DatabaseException("Unable to load database driver"); +120 } +121 } +122 userName = Settings.getString(Settings.KEYS.DB_USER, "dcuser"); +123 //yes, yes - hard-coded password - only if there isn't one in the properties file. +124 password = Settings.getString(Settings.KEYS.DB_PASSWORD, "DC-Pass1337!"); +125 try { +126 connectionString = Settings.getConnectionString( +127 Settings.KEYS.DB_CONNECTION_STRING, +128 Settings.KEYS.DB_FILE_NAME); +129 } catch (IOException ex) { +130 LOGGER.debug( +131 "Unable to retrieve the database connection string", ex); +132 throw new DatabaseException("Unable to retrieve the database connection string"); +133 } +134 boolean shouldCreateSchema = false; +135 try { +136 if (connectionString.startsWith("jdbc:h2:file:")) { //H2 +137 shouldCreateSchema = !h2DataFileExists(); +138 LOGGER.debug("Need to create DB Structure: {}", shouldCreateSchema); +139 } +140 } catch (IOException ioex) { +141 LOGGER.debug("Unable to verify database exists", ioex); +142 throw new DatabaseException("Unable to verify database exists"); +143 } +144 LOGGER.debug("Loading database connection"); +145 LOGGER.debug("Connection String: {}", connectionString); +146 LOGGER.debug("Database User: {}", userName); +147 +148 try { +149 conn = DriverManager.getConnection(connectionString, userName, password); +150 } catch (SQLException ex) { +151 if (ex.getMessage().contains("java.net.UnknownHostException") && connectionString.contains("AUTO_SERVER=TRUE;")) { +152 connectionString = connectionString.replace("AUTO_SERVER=TRUE;", ""); +153 try { +154 conn = DriverManager.getConnection(connectionString, userName, password); +155 Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString); +156 LOGGER.debug( +157 "Unable to start the database in server mode; reverting to single user mode"); +158 } catch (SQLException sqlex) { +159 LOGGER.debug("Unable to connect to the database", ex); +160 throw new DatabaseException("Unable to connect to the database"); +161 } +162 } else { +163 LOGGER.debug("Unable to connect to the database", ex); +164 throw new DatabaseException("Unable to connect to the database"); +165 } +166 } +167 +168 if (shouldCreateSchema) { +169 try { +170 createTables(conn); +171 } catch (DatabaseException dex) { +172 LOGGER.debug("", dex); +173 throw new DatabaseException("Unable to create the database structure"); +174 } +175 } +176 try { +177 ensureSchemaVersion(conn); +178 } catch (DatabaseException dex) { +179 LOGGER.debug("", dex); +180 throw new DatabaseException("Database schema does not match this version of dependency-check", dex); +181 } +182 } finally { +183 if (conn != null) { +184 try { +185 conn.close(); +186 } catch (SQLException ex) { +187 LOGGER.debug("An error occurred closing the connection", ex); +188 } +189 } +190 } +191 } +192 +193 /** +194 * Cleans up resources and unloads any registered database drivers. This +195 * needs to be called to ensure the driver is unregistered prior to the +196 * finalize method being called as during shutdown the class loader used to +197 * load the driver may be unloaded prior to the driver being de-registered. +198 */ +199 public static void cleanup() { +200 if (driver != null) { +201 try { +202 DriverManager.deregisterDriver(driver); +203 } catch (SQLException ex) { +204 LOGGER.debug("An error occurred unloading the database driver", ex); +205 } catch (Throwable unexpected) { +206 LOGGER.debug( +207 "An unexpected throwable occurred unloading the database driver", unexpected); +208 } +209 driver = null; +210 } +211 connectionString = null; +212 userName = null; +213 password = null; +214 } +215 +216 /** +217 * Constructs a new database connection object per the database +218 * configuration. +219 * +220 * @return a database connection object +221 * @throws DatabaseException thrown if there is an exception loading the +222 * database connection +223 */ +224 public static Connection getConnection() throws DatabaseException { +225 initialize(); +226 Connection conn = null; +227 try { +228 conn = DriverManager.getConnection(connectionString, userName, password); +229 } catch (SQLException ex) { +230 LOGGER.debug("", ex); +231 throw new DatabaseException("Unable to connect to the database"); +232 } +233 return conn; +234 } +235 +236 /** +237 * Determines if the H2 database file exists. If it does not exist then the +238 * data structure will need to be created. +239 * +240 * @return true if the H2 database file does not exist; otherwise false +241 * @throws IOException thrown if the data directory does not exist and +242 * cannot be created +243 */ +244 private static boolean h2DataFileExists() throws IOException { +245 final File dir = Settings.getDataDirectory(); +246 final String fileName = Settings.getString(Settings.KEYS.DB_FILE_NAME); +247 final File file = new File(dir, fileName); +248 return file.exists(); +249 } +250 +251 /** +252 * Creates the database structure (tables and indexes) to store the CVE +253 * data. +254 * +255 * @param conn the database connection +256 * @throws DatabaseException thrown if there is a Database Exception +257 */ +258 private static void createTables(Connection conn) throws DatabaseException { +259 LOGGER.debug("Creating database structure"); +260 InputStream is = null; +261 try { +262 is = ConnectionFactory.class.getClassLoader().getResourceAsStream(DB_STRUCTURE_RESOURCE); +263 final String dbStructure = IOUtils.toString(is, "UTF-8"); +264 +265 Statement statement = null; +266 try { +267 statement = conn.createStatement(); +268 statement.execute(dbStructure); +269 } catch (SQLException ex) { +270 LOGGER.debug("", ex); +271 throw new DatabaseException("Unable to create database statement", ex); +272 } finally { +273 DBUtils.closeStatement(statement); +274 } +275 } catch (IOException ex) { +276 throw new DatabaseException("Unable to create database schema", ex); +277 } finally { +278 IOUtils.closeQuietly(is); +279 } +280 } +281 +282 /** +283 * Updates the database schema by loading the upgrade script for the version +284 * specified. The intended use is that if the current schema version is 2.9 +285 * then we would call updateSchema(conn, "2.9"). This would load the +286 * upgrade_2.9.sql file and execute it against the database. The upgrade +287 * script must update the 'version' in the properties table. +288 * +289 * @param conn the database connection object +290 * @param appExpectedVersion the schema version that the application expects +291 * @param currentDbVersion the current schema version of the database +292 * @throws DatabaseException thrown if there is an exception upgrading the +293 * database schema +294 */ +295 private static void updateSchema(Connection conn, DependencyVersion appExpectedVersion, DependencyVersion currentDbVersion) +296 throws DatabaseException { +297 +298 final String databaseProductName; +299 try { +300 databaseProductName = conn.getMetaData().getDatabaseProductName(); +301 } catch (SQLException ex) { +302 throw new DatabaseException("Unable to get the database product name"); +303 } +304 if ("h2".equalsIgnoreCase(databaseProductName)) { +305 LOGGER.debug("Updating database structure"); +306 InputStream is = null; +307 String updateFile = null; +308 try { +309 updateFile = String.format(DB_STRUCTURE_UPDATE_RESOURCE, currentDbVersion.toString()); +310 is = ConnectionFactory.class.getClassLoader().getResourceAsStream(updateFile); +311 if (is == null) { +312 throw new DatabaseException(String.format("Unable to load update file '%s'", updateFile)); +313 } +314 final String dbStructureUpdate = IOUtils.toString(is, "UTF-8"); +315 +316 Statement statement = null; +317 try { +318 statement = conn.createStatement(); +319 final boolean success = statement.execute(dbStructureUpdate); +320 if (!success && statement.getUpdateCount() <= 0) { +321 throw new DatabaseException(String.format("Unable to upgrade the database schema to %s", +322 currentDbVersion.toString())); +323 } +324 } catch (SQLException ex) { +325 LOGGER.debug("", ex); +326 throw new DatabaseException("Unable to update database schema", ex); +327 } finally { +328 DBUtils.closeStatement(statement); +329 } +330 } catch (IOException ex) { +331 final String msg = String.format("Upgrade SQL file does not exist: %s", updateFile); +332 throw new DatabaseException(msg, ex); +333 } finally { +334 IOUtils.closeQuietly(is); +335 } +336 } else { +337 final int e0 = Integer.parseInt(appExpectedVersion.getVersionParts().get(0)); +338 final int c0 = Integer.parseInt(currentDbVersion.getVersionParts().get(0)); +339 final int e1 = Integer.parseInt(appExpectedVersion.getVersionParts().get(1)); +340 final int c1 = Integer.parseInt(currentDbVersion.getVersionParts().get(1)); +341 if (e0 == c0 && e1 < c1) { +342 LOGGER.warn("A new version of dependency-check is available; consider upgrading"); +343 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false); +344 } else if (e0 == c0 && e1 == c1) { +345 //do nothing - not sure how we got here, but just incase... +346 } else { +347 LOGGER.error("The database schema must be upgraded to use this version of dependency-check. Please see {} for more information.", +348 UPGRADE_HELP_URL); +349 throw new DatabaseException("Database schema is out of date"); +350 } +351 } +352 } +353 +354 /** +355 * Counter to ensure that calls to ensureSchemaVersion does not end up in an +356 * endless loop. +357 */ +358 private static int callDepth = 0; +359 +360 /** +361 * Uses the provided connection to check the specified schema version within +362 * the database. +363 * +364 * @param conn the database connection object +365 * @throws DatabaseException thrown if the schema version is not compatible +366 * with this version of dependency-check +367 */ +368 private static void ensureSchemaVersion(Connection conn) throws DatabaseException { +369 ResultSet rs = null; +370 PreparedStatement ps = null; +371 try { +372 //TODO convert this to use DatabaseProperties +373 ps = conn.prepareStatement("SELECT value FROM properties WHERE id = 'version'"); +374 rs = ps.executeQuery(); +375 if (rs.next()) { +376 final DependencyVersion appDbVersion = DependencyVersionUtil.parseVersion(DB_SCHEMA_VERSION); +377 if (appDbVersion == null) { +378 throw new DatabaseException("Invalid application database schema"); +379 } +380 final DependencyVersion db = DependencyVersionUtil.parseVersion(rs.getString(1)); +381 if (db == null) { +382 throw new DatabaseException("Invalid database schema"); +383 } +384 if (appDbVersion.compareTo(db) > 0) { +385 LOGGER.debug("Current Schema: {}", DB_SCHEMA_VERSION); +386 LOGGER.debug("DB Schema: {}", rs.getString(1)); +387 updateSchema(conn, appDbVersion, db); +388 if (++callDepth < 10) { +389 ensureSchemaVersion(conn); +390 } +391 } +392 } else { +393 throw new DatabaseException("Database schema is missing"); +394 } +395 } catch (SQLException ex) { +396 LOGGER.debug("", ex); +397 throw new DatabaseException("Unable to check the database schema version"); +398 } finally { +399 DBUtils.closeResultSet(rs); +400 DBUtils.closeStatement(ps); +401 } +402 } +403 }
    diff --git a/xref/org/owasp/dependencycheck/data/nvdcve/CveDB.html b/xref/org/owasp/dependencycheck/data/nvdcve/CveDB.html index 9fae88f80..1d4d2db7a 100644 --- a/xref/org/owasp/dependencycheck/data/nvdcve/CveDB.html +++ b/xref/org/owasp/dependencycheck/data/nvdcve/CveDB.html @@ -95,766 +95,768 @@ 87 open(); 88 try { 89 final String databaseProductName = conn.getMetaData().getDatabaseProductName(); -90 batchSupported = conn.getMetaData().supportsBatchUpdates(); -91 LOGGER.debug("Database dialect: {}", databaseProductName); -92 final Locale dbDialect = new Locale(databaseProductName); -93 statementBundle = ResourceBundle.getBundle("data/dbStatements", dbDialect); -94 } catch (SQLException se) { -95 LOGGER.warn("Problem loading database specific dialect!", se); -96 statementBundle = ResourceBundle.getBundle("data/dbStatements"); -97 } -98 databaseProperties = new DatabaseProperties(this); -99 } catch (DatabaseException ex) { -100 throw ex; -101 } -102 } -103 -104 /** -105 * Returns the database connection. -106 * -107 * @return the database connection -108 */ -109 protected Connection getConnection() { -110 return conn; -111 } -112 -113 /** -114 * Opens the database connection. If the database does not exist, it will -115 * create a new one. -116 * -117 * @throws DatabaseException thrown if there is an error opening the -118 * database connection -119 */ -120 public final void open() throws DatabaseException { -121 if (!isOpen()) { -122 conn = ConnectionFactory.getConnection(); -123 } -124 } -125 -126 /** -127 * Closes the DB4O database. Close should be called on this object when it -128 * is done being used. -129 */ -130 public void close() { -131 if (conn != null) { -132 try { -133 conn.close(); -134 } catch (SQLException ex) { -135 LOGGER.error("There was an error attempting to close the CveDB, see the log for more details."); -136 LOGGER.debug("", ex); -137 } catch (Throwable ex) { -138 LOGGER.error("There was an exception attempting to close the CveDB, see the log for more details."); -139 LOGGER.debug("", ex); -140 } -141 conn = null; -142 } -143 } -144 -145 /** -146 * Returns whether the database connection is open or closed. -147 * -148 * @return whether the database connection is open or closed -149 */ -150 public boolean isOpen() { -151 return conn != null; -152 } -153 -154 /** -155 * Commits all completed transactions. -156 * -157 * @throws SQLException thrown if a SQL Exception occurs -158 */ -159 public void commit() throws SQLException { -160 //temporary remove this as autocommit is on. -161 //if (conn != null) { -162 // conn.commit(); -163 //} -164 } -165 -166 /** -167 * Cleans up the object and ensures that "close" has been called. -168 * -169 * @throws Throwable thrown if there is a problem -170 */ -171 @Override -172 @SuppressWarnings("FinalizeDeclaration") -173 protected void finalize() throws Throwable { -174 LOGGER.debug("Entering finalize"); -175 close(); -176 super.finalize(); -177 } -178 /** -179 * Database properties object containing the 'properties' from the database -180 * table. -181 */ -182 private DatabaseProperties databaseProperties; -183 -184 /** -185 * Get the value of databaseProperties. -186 * -187 * @return the value of databaseProperties -188 */ -189 public DatabaseProperties getDatabaseProperties() { -190 return databaseProperties; -191 } -192 -193 /** -194 * Searches the CPE entries in the database and retrieves all entries for a -195 * given vendor and product combination. The returned list will include all -196 * versions of the product that are registered in the NVD CVE data. -197 * -198 * @param vendor the identified vendor name of the dependency being analyzed -199 * @param product the identified name of the product of the dependency being -200 * analyzed -201 * @return a set of vulnerable software -202 */ -203 public Set<VulnerableSoftware> getCPEs(String vendor, String product) { -204 final Set<VulnerableSoftware> cpe = new HashSet<VulnerableSoftware>(); -205 ResultSet rs = null; -206 PreparedStatement ps = null; -207 try { -208 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_CPE_ENTRIES")); -209 ps.setString(1, vendor); -210 ps.setString(2, product); -211 rs = ps.executeQuery(); -212 -213 while (rs.next()) { -214 final VulnerableSoftware vs = new VulnerableSoftware(); -215 vs.setCpe(rs.getString(1)); -216 cpe.add(vs); -217 } -218 } catch (SQLException ex) { -219 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details."); -220 LOGGER.debug("", ex); -221 } finally { -222 DBUtils.closeResultSet(rs); -223 DBUtils.closeStatement(ps); -224 } -225 return cpe; -226 } -227 -228 /** -229 * Returns the entire list of vendor/product combinations. -230 * -231 * @return the entire list of vendor/product combinations -232 * @throws DatabaseException thrown when there is an error retrieving the -233 * data from the DB -234 */ -235 public Set<Pair<String, String>> getVendorProductList() throws DatabaseException { -236 final Set<Pair<String, String>> data = new HashSet<Pair<String, String>>(); -237 ResultSet rs = null; -238 PreparedStatement ps = null; -239 try { -240 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_VENDOR_PRODUCT_LIST")); -241 rs = ps.executeQuery(); -242 while (rs.next()) { -243 data.add(new Pair<String, String>(rs.getString(1), rs.getString(2))); -244 } -245 } catch (SQLException ex) { -246 final String msg = "An unexpected SQL Exception occurred; please see the verbose log for more details."; -247 throw new DatabaseException(msg, ex); -248 } finally { -249 DBUtils.closeResultSet(rs); -250 DBUtils.closeStatement(ps); -251 } -252 return data; -253 } -254 -255 /** -256 * Returns a set of properties. -257 * -258 * @return the properties from the database -259 */ -260 Properties getProperties() { -261 final Properties prop = new Properties(); -262 PreparedStatement ps = null; -263 ResultSet rs = null; -264 try { -265 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_PROPERTIES")); -266 rs = ps.executeQuery(); -267 while (rs.next()) { -268 prop.setProperty(rs.getString(1), rs.getString(2)); -269 } -270 } catch (SQLException ex) { -271 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details."); -272 LOGGER.debug("", ex); -273 } finally { -274 DBUtils.closeStatement(ps); -275 DBUtils.closeResultSet(rs); -276 } -277 return prop; -278 } -279 -280 /** -281 * Saves a property to the database. -282 * -283 * @param key the property key -284 * @param value the property value -285 */ -286 void saveProperty(String key, String value) { -287 try { -288 try { -289 final PreparedStatement mergeProperty = getConnection().prepareStatement(statementBundle.getString("MERGE_PROPERTY")); -290 try { -291 mergeProperty.setString(1, key); -292 mergeProperty.setString(2, value); -293 mergeProperty.executeUpdate(); -294 } finally { -295 DBUtils.closeStatement(mergeProperty); -296 } -297 } catch (MissingResourceException mre) { -298 // No Merge statement, so doing an Update/Insert... -299 PreparedStatement updateProperty = null; -300 PreparedStatement insertProperty = null; -301 try { -302 updateProperty = getConnection().prepareStatement(statementBundle.getString("UPDATE_PROPERTY")); -303 updateProperty.setString(1, value); -304 updateProperty.setString(2, key); -305 if (updateProperty.executeUpdate() == 0) { -306 insertProperty = getConnection().prepareStatement(statementBundle.getString("INSERT_PROPERTY")); -307 insertProperty.setString(1, key); -308 insertProperty.setString(2, value); -309 insertProperty.executeUpdate(); -310 } -311 } finally { -312 DBUtils.closeStatement(updateProperty); -313 DBUtils.closeStatement(insertProperty); -314 } -315 } -316 } catch (SQLException ex) { -317 LOGGER.warn("Unable to save property '{}' with a value of '{}' to the database", key, value); -318 LOGGER.debug("", ex); -319 } -320 } -321 -322 /** -323 * Retrieves the vulnerabilities associated with the specified CPE. -324 * -325 * @param cpeStr the CPE name -326 * @return a list of Vulnerabilities -327 * @throws DatabaseException thrown if there is an exception retrieving data -328 */ -329 public List<Vulnerability> getVulnerabilities(String cpeStr) throws DatabaseException { -330 final VulnerableSoftware cpe = new VulnerableSoftware(); -331 try { -332 cpe.parseName(cpeStr); -333 } catch (UnsupportedEncodingException ex) { -334 LOGGER.trace("", ex); -335 } -336 final DependencyVersion detectedVersion = parseDependencyVersion(cpe); -337 final List<Vulnerability> vulnerabilities = new ArrayList<Vulnerability>(); -338 -339 PreparedStatement ps = null; -340 ResultSet rs = null; -341 try { -342 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_CVE_FROM_SOFTWARE")); -343 ps.setString(1, cpe.getVendor()); -344 ps.setString(2, cpe.getProduct()); -345 rs = ps.executeQuery(); -346 String currentCVE = ""; -347 -348 final Map<String, Boolean> vulnSoftware = new HashMap<String, Boolean>(); -349 while (rs.next()) { -350 final String cveId = rs.getString(1); -351 if (!currentCVE.equals(cveId)) { //check for match and add -352 final Entry<String, Boolean> matchedCPE = getMatchingSoftware(vulnSoftware, cpe.getVendor(), cpe.getProduct(), detectedVersion); -353 if (matchedCPE != null) { -354 final Vulnerability v = getVulnerability(currentCVE); -355 v.setMatchedCPE(matchedCPE.getKey(), matchedCPE.getValue() ? "Y" : null); -356 vulnerabilities.add(v); -357 } -358 vulnSoftware.clear(); -359 currentCVE = cveId; -360 } -361 -362 final String cpeId = rs.getString(2); -363 final String previous = rs.getString(3); -364 final Boolean p = previous != null && !previous.isEmpty(); -365 vulnSoftware.put(cpeId, p); -366 } -367 //remember to process the last set of CVE/CPE entries -368 final Entry<String, Boolean> matchedCPE = getMatchingSoftware(vulnSoftware, cpe.getVendor(), cpe.getProduct(), detectedVersion); -369 if (matchedCPE != null) { -370 final Vulnerability v = getVulnerability(currentCVE); -371 v.setMatchedCPE(matchedCPE.getKey(), matchedCPE.getValue() ? "Y" : null); -372 vulnerabilities.add(v); -373 } -374 } catch (SQLException ex) { -375 throw new DatabaseException("Exception retrieving vulnerability for " + cpeStr, ex); -376 } finally { -377 DBUtils.closeResultSet(rs); -378 DBUtils.closeStatement(ps); -379 } -380 return vulnerabilities; -381 } -382 -383 /** -384 * Gets a vulnerability for the provided CVE. -385 * -386 * @param cve the CVE to lookup -387 * @return a vulnerability object -388 * @throws DatabaseException if an exception occurs -389 */ -390 public Vulnerability getVulnerability(String cve) throws DatabaseException { -391 PreparedStatement psV = null; -392 PreparedStatement psR = null; -393 PreparedStatement psS = null; -394 ResultSet rsV = null; -395 ResultSet rsR = null; -396 ResultSet rsS = null; -397 Vulnerability vuln = null; -398 -399 try { -400 psV = getConnection().prepareStatement(statementBundle.getString("SELECT_VULNERABILITY")); -401 psV.setString(1, cve); -402 rsV = psV.executeQuery(); -403 if (rsV.next()) { -404 vuln = new Vulnerability(); -405 vuln.setName(cve); -406 vuln.setDescription(rsV.getString(2)); -407 String cwe = rsV.getString(3); -408 if (cwe != null) { -409 final String name = CweDB.getCweName(cwe); -410 if (name != null) { -411 cwe += ' ' + name; -412 } -413 } -414 final int cveId = rsV.getInt(1); -415 vuln.setCwe(cwe); -416 vuln.setCvssScore(rsV.getFloat(4)); -417 vuln.setCvssAccessVector(rsV.getString(5)); -418 vuln.setCvssAccessComplexity(rsV.getString(6)); -419 vuln.setCvssAuthentication(rsV.getString(7)); -420 vuln.setCvssConfidentialityImpact(rsV.getString(8)); -421 vuln.setCvssIntegrityImpact(rsV.getString(9)); -422 vuln.setCvssAvailabilityImpact(rsV.getString(10)); -423 -424 psR = getConnection().prepareStatement(statementBundle.getString("SELECT_REFERENCES")); -425 psR.setInt(1, cveId); -426 rsR = psR.executeQuery(); -427 while (rsR.next()) { -428 vuln.addReference(rsR.getString(1), rsR.getString(2), rsR.getString(3)); -429 } -430 psS = getConnection().prepareStatement(statementBundle.getString("SELECT_SOFTWARE")); -431 psS.setInt(1, cveId); -432 rsS = psS.executeQuery(); -433 while (rsS.next()) { -434 final String cpe = rsS.getString(1); -435 final String prevVersion = rsS.getString(2); -436 if (prevVersion == null) { -437 vuln.addVulnerableSoftware(cpe); -438 } else { -439 vuln.addVulnerableSoftware(cpe, prevVersion); -440 } -441 } -442 } -443 } catch (SQLException ex) { -444 throw new DatabaseException("Error retrieving " + cve, ex); -445 } finally { -446 DBUtils.closeResultSet(rsV); -447 DBUtils.closeResultSet(rsR); -448 DBUtils.closeResultSet(rsS); -449 DBUtils.closeStatement(psV); -450 DBUtils.closeStatement(psR); -451 DBUtils.closeStatement(psS); -452 } -453 return vuln; -454 } -455 -456 /** -457 * Updates the vulnerability within the database. If the vulnerability does -458 * not exist it will be added. -459 * -460 * @param vuln the vulnerability to add to the database -461 * @throws DatabaseException is thrown if the database -462 */ -463 public void updateVulnerability(Vulnerability vuln) throws DatabaseException { -464 PreparedStatement selectVulnerabilityId = null; -465 PreparedStatement deleteVulnerability = null; -466 PreparedStatement deleteReferences = null; -467 PreparedStatement deleteSoftware = null; -468 PreparedStatement updateVulnerability = null; -469 PreparedStatement insertVulnerability = null; -470 PreparedStatement insertReference = null; -471 PreparedStatement selectCpeId = null; -472 PreparedStatement insertCpe = null; -473 PreparedStatement insertSoftware = null; -474 -475 try { -476 selectVulnerabilityId = getConnection().prepareStatement(statementBundle.getString("SELECT_VULNERABILITY_ID")); -477 deleteVulnerability = getConnection().prepareStatement(statementBundle.getString("DELETE_VULNERABILITY")); -478 deleteReferences = getConnection().prepareStatement(statementBundle.getString("DELETE_REFERENCE")); -479 deleteSoftware = getConnection().prepareStatement(statementBundle.getString("DELETE_SOFTWARE")); -480 updateVulnerability = getConnection().prepareStatement(statementBundle.getString("UPDATE_VULNERABILITY")); -481 final String[] ids = {"id"}; -482 insertVulnerability = getConnection().prepareStatement(statementBundle.getString("INSERT_VULNERABILITY"), -483 //Statement.RETURN_GENERATED_KEYS); -484 ids); -485 insertReference = getConnection().prepareStatement(statementBundle.getString("INSERT_REFERENCE")); -486 selectCpeId = getConnection().prepareStatement(statementBundle.getString("SELECT_CPE_ID")); -487 insertCpe = getConnection().prepareStatement(statementBundle.getString("INSERT_CPE"), -488 //Statement.RETURN_GENERATED_KEYS); -489 ids); -490 insertSoftware = getConnection().prepareStatement(statementBundle.getString("INSERT_SOFTWARE")); -491 int vulnerabilityId = 0; -492 selectVulnerabilityId.setString(1, vuln.getName()); -493 ResultSet rs = selectVulnerabilityId.executeQuery(); -494 if (rs.next()) { -495 vulnerabilityId = rs.getInt(1); -496 // first delete any existing vulnerability info. We don't know what was updated. yes, slower but atm easier. -497 deleteReferences.setInt(1, vulnerabilityId); -498 deleteReferences.execute(); -499 deleteSoftware.setInt(1, vulnerabilityId); -500 deleteSoftware.execute(); -501 } -502 DBUtils.closeResultSet(rs); -503 rs = null; -504 -505 if (vulnerabilityId != 0) { -506 if (vuln.getDescription().contains("** REJECT **")) { -507 deleteVulnerability.setInt(1, vulnerabilityId); -508 deleteVulnerability.executeUpdate(); -509 } else { -510 updateVulnerability.setString(1, vuln.getDescription()); -511 updateVulnerability.setString(2, vuln.getCwe()); -512 updateVulnerability.setFloat(3, vuln.getCvssScore()); -513 updateVulnerability.setString(4, vuln.getCvssAccessVector()); -514 updateVulnerability.setString(5, vuln.getCvssAccessComplexity()); -515 updateVulnerability.setString(6, vuln.getCvssAuthentication()); -516 updateVulnerability.setString(7, vuln.getCvssConfidentialityImpact()); -517 updateVulnerability.setString(8, vuln.getCvssIntegrityImpact()); -518 updateVulnerability.setString(9, vuln.getCvssAvailabilityImpact()); -519 updateVulnerability.setInt(10, vulnerabilityId); -520 updateVulnerability.executeUpdate(); -521 } -522 } else { -523 insertVulnerability.setString(1, vuln.getName()); -524 insertVulnerability.setString(2, vuln.getDescription()); -525 insertVulnerability.setString(3, vuln.getCwe()); -526 insertVulnerability.setFloat(4, vuln.getCvssScore()); -527 insertVulnerability.setString(5, vuln.getCvssAccessVector()); -528 insertVulnerability.setString(6, vuln.getCvssAccessComplexity()); -529 insertVulnerability.setString(7, vuln.getCvssAuthentication()); -530 insertVulnerability.setString(8, vuln.getCvssConfidentialityImpact()); -531 insertVulnerability.setString(9, vuln.getCvssIntegrityImpact()); -532 insertVulnerability.setString(10, vuln.getCvssAvailabilityImpact()); -533 insertVulnerability.execute(); -534 try { -535 rs = insertVulnerability.getGeneratedKeys(); -536 rs.next(); -537 vulnerabilityId = rs.getInt(1); -538 } catch (SQLException ex) { -539 final String msg = String.format("Unable to retrieve id for new vulnerability for '%s'", vuln.getName()); -540 throw new DatabaseException(msg, ex); -541 } finally { -542 DBUtils.closeResultSet(rs); -543 rs = null; -544 } -545 } -546 -547 for (Reference r : vuln.getReferences()) { -548 insertReference.setInt(1, vulnerabilityId); -549 insertReference.setString(2, r.getName()); -550 insertReference.setString(3, r.getUrl()); -551 insertReference.setString(4, r.getSource()); -552 -553 if (batchSupported) { -554 insertReference.addBatch(); -555 } else { -556 insertReference.execute(); -557 } -558 } -559 -560 if (batchSupported) { -561 insertReference.executeBatch(); -562 } -563 -564 for (VulnerableSoftware s : vuln.getVulnerableSoftware()) { -565 int cpeProductId = 0; -566 selectCpeId.setString(1, s.getName()); -567 try { -568 rs = selectCpeId.executeQuery(); -569 if (rs.next()) { -570 cpeProductId = rs.getInt(1); -571 } -572 } catch (SQLException ex) { -573 throw new DatabaseException("Unable to get primary key for new cpe: " + s.getName(), ex); -574 } finally { -575 DBUtils.closeResultSet(rs); -576 rs = null; -577 } -578 -579 if (cpeProductId == 0) { -580 insertCpe.setString(1, s.getName()); -581 insertCpe.setString(2, s.getVendor()); -582 insertCpe.setString(3, s.getProduct()); -583 insertCpe.executeUpdate(); -584 cpeProductId = DBUtils.getGeneratedKey(insertCpe); -585 } -586 if (cpeProductId == 0) { -587 throw new DatabaseException("Unable to retrieve cpeProductId - no data returned"); -588 } -589 -590 insertSoftware.setInt(1, vulnerabilityId); -591 insertSoftware.setInt(2, cpeProductId); -592 -593 if (s.getPreviousVersion() == null) { -594 insertSoftware.setNull(3, java.sql.Types.VARCHAR); -595 } else { -596 insertSoftware.setString(3, s.getPreviousVersion()); -597 } -598 if (batchSupported) { -599 insertSoftware.addBatch(); -600 } else { -601 try { -602 insertSoftware.execute(); -603 } catch (SQLException ex) { -604 if (ex.getMessage().contains("Duplicate entry")) { -605 final String msg = String.format("Duplicate software key identified in '%s:%s'", vuln.getName(), s.getName()); -606 LOGGER.debug(msg, ex); -607 } else { -608 throw ex; -609 } -610 } -611 } -612 } -613 if (batchSupported) { -614 insertSoftware.executeBatch(); -615 } -616 } catch (SQLException ex) { -617 final String msg = String.format("Error updating '%s'", vuln.getName()); -618 LOGGER.debug(msg, ex); -619 throw new DatabaseException(msg, ex); -620 } finally { -621 DBUtils.closeStatement(selectVulnerabilityId); -622 DBUtils.closeStatement(deleteReferences); -623 DBUtils.closeStatement(deleteSoftware); -624 DBUtils.closeStatement(updateVulnerability); -625 DBUtils.closeStatement(deleteVulnerability); -626 DBUtils.closeStatement(insertVulnerability); -627 DBUtils.closeStatement(insertReference); -628 DBUtils.closeStatement(selectCpeId); -629 DBUtils.closeStatement(insertCpe); -630 DBUtils.closeStatement(insertSoftware); -631 } -632 } -633 -634 /** -635 * Checks to see if data exists so that analysis can be performed. -636 * -637 * @return <code>true</code> if data exists; otherwise <code>false</code> -638 */ -639 public boolean dataExists() { -640 Statement cs = null; -641 ResultSet rs = null; -642 try { -643 cs = conn.createStatement(); -644 rs = cs.executeQuery("SELECT COUNT(*) records FROM cpeEntry"); -645 if (rs.next()) { -646 if (rs.getInt(1) > 0) { -647 return true; -648 } -649 } -650 } catch (SQLException ex) { -651 String dd; -652 try { -653 dd = Settings.getDataDirectory().getAbsolutePath(); -654 } catch (IOException ex1) { -655 dd = Settings.getString(Settings.KEYS.DATA_DIRECTORY); -656 } -657 LOGGER.error("Unable to access the local database.\n\nEnsure that '{}' is a writable directory. " -658 + "If the problem persist try deleting the files in '{}' and running {} again. If the problem continues, please " -659 + "create a log file (see documentation at http://jeremylong.github.io/DependencyCheck/) and open a ticket at " -660 + "https://github.com/jeremylong/DependencyCheck/issues and include the log file.\n\n", -661 dd, dd, Settings.getString(Settings.KEYS.APPLICATION_VAME)); -662 LOGGER.debug("", ex); -663 } finally { -664 DBUtils.closeResultSet(rs); -665 DBUtils.closeStatement(cs); -666 } -667 return false; -668 } -669 -670 /** -671 * It is possible that orphaned rows may be generated during database -672 * updates. This should be called after all updates have been completed to -673 * ensure orphan entries are removed. -674 */ -675 public void cleanupDatabase() { -676 PreparedStatement ps = null; -677 try { -678 ps = getConnection().prepareStatement(statementBundle.getString("CLEANUP_ORPHANS")); -679 if (ps != null) { -680 ps.executeUpdate(); -681 } -682 } catch (SQLException ex) { -683 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details."); -684 LOGGER.debug("", ex); -685 } finally { -686 DBUtils.closeStatement(ps); -687 } -688 } -689 -690 /** -691 * Determines if the given identifiedVersion is affected by the given cpeId -692 * and previous version flag. A non-null, non-empty string passed to the -693 * previous version argument indicates that all previous versions are -694 * affected. -695 * -696 * @param vendor the vendor of the dependency being analyzed -697 * @param product the product name of the dependency being analyzed -698 * @param vulnerableSoftware a map of the vulnerable software with a boolean -699 * indicating if all previous versions are affected -700 * @param identifiedVersion the identified version of the dependency being -701 * analyzed -702 * @return true if the identified version is affected, otherwise false -703 */ -704 Entry<String, Boolean> getMatchingSoftware(Map<String, Boolean> vulnerableSoftware, String vendor, String product, -705 DependencyVersion identifiedVersion) { -706 -707 final boolean isVersionTwoADifferentProduct = "apache".equals(vendor) && "struts".equals(product); +90 LOGGER.debug("Database dialect: {}", databaseProductName); +91 final Locale dbDialect = new Locale(databaseProductName); +92 statementBundle = ResourceBundle.getBundle("data/dbStatements", dbDialect); +93 if ("mysql".equalsIgnoreCase(databaseProductName)) { +94 batchSupported = false; +95 } +96 } catch (SQLException se) { +97 LOGGER.warn("Problem loading database specific dialect!", se); +98 statementBundle = ResourceBundle.getBundle("data/dbStatements"); +99 } +100 databaseProperties = new DatabaseProperties(this); +101 } catch (DatabaseException ex) { +102 throw ex; +103 } +104 } +105 +106 /** +107 * Returns the database connection. +108 * +109 * @return the database connection +110 */ +111 protected Connection getConnection() { +112 return conn; +113 } +114 +115 /** +116 * Opens the database connection. If the database does not exist, it will +117 * create a new one. +118 * +119 * @throws DatabaseException thrown if there is an error opening the +120 * database connection +121 */ +122 public final void open() throws DatabaseException { +123 if (!isOpen()) { +124 conn = ConnectionFactory.getConnection(); +125 } +126 } +127 +128 /** +129 * Closes the DB4O database. Close should be called on this object when it +130 * is done being used. +131 */ +132 public void close() { +133 if (conn != null) { +134 try { +135 conn.close(); +136 } catch (SQLException ex) { +137 LOGGER.error("There was an error attempting to close the CveDB, see the log for more details."); +138 LOGGER.debug("", ex); +139 } catch (Throwable ex) { +140 LOGGER.error("There was an exception attempting to close the CveDB, see the log for more details."); +141 LOGGER.debug("", ex); +142 } +143 conn = null; +144 } +145 } +146 +147 /** +148 * Returns whether the database connection is open or closed. +149 * +150 * @return whether the database connection is open or closed +151 */ +152 public boolean isOpen() { +153 return conn != null; +154 } +155 +156 /** +157 * Commits all completed transactions. +158 * +159 * @throws SQLException thrown if a SQL Exception occurs +160 */ +161 public void commit() throws SQLException { +162 //temporary remove this as autocommit is on. +163 //if (conn != null) { +164 // conn.commit(); +165 //} +166 } +167 +168 /** +169 * Cleans up the object and ensures that "close" has been called. +170 * +171 * @throws Throwable thrown if there is a problem +172 */ +173 @Override +174 @SuppressWarnings("FinalizeDeclaration") +175 protected void finalize() throws Throwable { +176 LOGGER.debug("Entering finalize"); +177 close(); +178 super.finalize(); +179 } +180 /** +181 * Database properties object containing the 'properties' from the database +182 * table. +183 */ +184 private DatabaseProperties databaseProperties; +185 +186 /** +187 * Get the value of databaseProperties. +188 * +189 * @return the value of databaseProperties +190 */ +191 public DatabaseProperties getDatabaseProperties() { +192 return databaseProperties; +193 } +194 +195 /** +196 * Searches the CPE entries in the database and retrieves all entries for a +197 * given vendor and product combination. The returned list will include all +198 * versions of the product that are registered in the NVD CVE data. +199 * +200 * @param vendor the identified vendor name of the dependency being analyzed +201 * @param product the identified name of the product of the dependency being +202 * analyzed +203 * @return a set of vulnerable software +204 */ +205 public Set<VulnerableSoftware> getCPEs(String vendor, String product) { +206 final Set<VulnerableSoftware> cpe = new HashSet<VulnerableSoftware>(); +207 ResultSet rs = null; +208 PreparedStatement ps = null; +209 try { +210 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_CPE_ENTRIES")); +211 ps.setString(1, vendor); +212 ps.setString(2, product); +213 rs = ps.executeQuery(); +214 +215 while (rs.next()) { +216 final VulnerableSoftware vs = new VulnerableSoftware(); +217 vs.setCpe(rs.getString(1)); +218 cpe.add(vs); +219 } +220 } catch (SQLException ex) { +221 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details."); +222 LOGGER.debug("", ex); +223 } finally { +224 DBUtils.closeResultSet(rs); +225 DBUtils.closeStatement(ps); +226 } +227 return cpe; +228 } +229 +230 /** +231 * Returns the entire list of vendor/product combinations. +232 * +233 * @return the entire list of vendor/product combinations +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 { +238 final Set<Pair<String, String>> data = new HashSet<Pair<String, String>>(); +239 ResultSet rs = null; +240 PreparedStatement ps = null; +241 try { +242 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_VENDOR_PRODUCT_LIST")); +243 rs = ps.executeQuery(); +244 while (rs.next()) { +245 data.add(new Pair<String, String>(rs.getString(1), rs.getString(2))); +246 } +247 } catch (SQLException ex) { +248 final String msg = "An unexpected SQL Exception occurred; please see the verbose log for more details."; +249 throw new DatabaseException(msg, ex); +250 } finally { +251 DBUtils.closeResultSet(rs); +252 DBUtils.closeStatement(ps); +253 } +254 return data; +255 } +256 +257 /** +258 * Returns a set of properties. +259 * +260 * @return the properties from the database +261 */ +262 Properties getProperties() { +263 final Properties prop = new Properties(); +264 PreparedStatement ps = null; +265 ResultSet rs = null; +266 try { +267 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_PROPERTIES")); +268 rs = ps.executeQuery(); +269 while (rs.next()) { +270 prop.setProperty(rs.getString(1), rs.getString(2)); +271 } +272 } catch (SQLException ex) { +273 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details."); +274 LOGGER.debug("", ex); +275 } finally { +276 DBUtils.closeStatement(ps); +277 DBUtils.closeResultSet(rs); +278 } +279 return prop; +280 } +281 +282 /** +283 * Saves a property to the database. +284 * +285 * @param key the property key +286 * @param value the property value +287 */ +288 void saveProperty(String key, String value) { +289 try { +290 try { +291 final PreparedStatement mergeProperty = getConnection().prepareStatement(statementBundle.getString("MERGE_PROPERTY")); +292 try { +293 mergeProperty.setString(1, key); +294 mergeProperty.setString(2, value); +295 mergeProperty.executeUpdate(); +296 } finally { +297 DBUtils.closeStatement(mergeProperty); +298 } +299 } catch (MissingResourceException mre) { +300 // No Merge statement, so doing an Update/Insert... +301 PreparedStatement updateProperty = null; +302 PreparedStatement insertProperty = null; +303 try { +304 updateProperty = getConnection().prepareStatement(statementBundle.getString("UPDATE_PROPERTY")); +305 updateProperty.setString(1, value); +306 updateProperty.setString(2, key); +307 if (updateProperty.executeUpdate() == 0) { +308 insertProperty = getConnection().prepareStatement(statementBundle.getString("INSERT_PROPERTY")); +309 insertProperty.setString(1, key); +310 insertProperty.setString(2, value); +311 insertProperty.executeUpdate(); +312 } +313 } finally { +314 DBUtils.closeStatement(updateProperty); +315 DBUtils.closeStatement(insertProperty); +316 } +317 } +318 } catch (SQLException ex) { +319 LOGGER.warn("Unable to save property '{}' with a value of '{}' to the database", key, value); +320 LOGGER.debug("", ex); +321 } +322 } +323 +324 /** +325 * Retrieves the vulnerabilities associated with the specified CPE. +326 * +327 * @param cpeStr the CPE name +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 { +332 final VulnerableSoftware cpe = new VulnerableSoftware(); +333 try { +334 cpe.parseName(cpeStr); +335 } catch (UnsupportedEncodingException ex) { +336 LOGGER.trace("", ex); +337 } +338 final DependencyVersion detectedVersion = parseDependencyVersion(cpe); +339 final List<Vulnerability> vulnerabilities = new ArrayList<Vulnerability>(); +340 +341 PreparedStatement ps = null; +342 ResultSet rs = null; +343 try { +344 ps = getConnection().prepareStatement(statementBundle.getString("SELECT_CVE_FROM_SOFTWARE")); +345 ps.setString(1, cpe.getVendor()); +346 ps.setString(2, cpe.getProduct()); +347 rs = ps.executeQuery(); +348 String currentCVE = ""; +349 +350 final Map<String, Boolean> vulnSoftware = new HashMap<String, Boolean>(); +351 while (rs.next()) { +352 final String cveId = rs.getString(1); +353 if (!currentCVE.equals(cveId)) { //check for match and add +354 final Entry<String, Boolean> matchedCPE = getMatchingSoftware(vulnSoftware, cpe.getVendor(), cpe.getProduct(), detectedVersion); +355 if (matchedCPE != null) { +356 final Vulnerability v = getVulnerability(currentCVE); +357 v.setMatchedCPE(matchedCPE.getKey(), matchedCPE.getValue() ? "Y" : null); +358 vulnerabilities.add(v); +359 } +360 vulnSoftware.clear(); +361 currentCVE = cveId; +362 } +363 +364 final String cpeId = rs.getString(2); +365 final String previous = rs.getString(3); +366 final Boolean p = previous != null && !previous.isEmpty(); +367 vulnSoftware.put(cpeId, p); +368 } +369 //remember to process the last set of CVE/CPE entries +370 final Entry<String, Boolean> matchedCPE = getMatchingSoftware(vulnSoftware, cpe.getVendor(), cpe.getProduct(), detectedVersion); +371 if (matchedCPE != null) { +372 final Vulnerability v = getVulnerability(currentCVE); +373 v.setMatchedCPE(matchedCPE.getKey(), matchedCPE.getValue() ? "Y" : null); +374 vulnerabilities.add(v); +375 } +376 } catch (SQLException ex) { +377 throw new DatabaseException("Exception retrieving vulnerability for " + cpeStr, ex); +378 } finally { +379 DBUtils.closeResultSet(rs); +380 DBUtils.closeStatement(ps); +381 } +382 return vulnerabilities; +383 } +384 +385 /** +386 * Gets a vulnerability for the provided CVE. +387 * +388 * @param cve the CVE to lookup +389 * @return a vulnerability object +390 * @throws DatabaseException if an exception occurs +391 */ +392 public Vulnerability getVulnerability(String cve) throws DatabaseException { +393 PreparedStatement psV = null; +394 PreparedStatement psR = null; +395 PreparedStatement psS = null; +396 ResultSet rsV = null; +397 ResultSet rsR = null; +398 ResultSet rsS = null; +399 Vulnerability vuln = null; +400 +401 try { +402 psV = getConnection().prepareStatement(statementBundle.getString("SELECT_VULNERABILITY")); +403 psV.setString(1, cve); +404 rsV = psV.executeQuery(); +405 if (rsV.next()) { +406 vuln = new Vulnerability(); +407 vuln.setName(cve); +408 vuln.setDescription(rsV.getString(2)); +409 String cwe = rsV.getString(3); +410 if (cwe != null) { +411 final String name = CweDB.getCweName(cwe); +412 if (name != null) { +413 cwe += ' ' + name; +414 } +415 } +416 final int cveId = rsV.getInt(1); +417 vuln.setCwe(cwe); +418 vuln.setCvssScore(rsV.getFloat(4)); +419 vuln.setCvssAccessVector(rsV.getString(5)); +420 vuln.setCvssAccessComplexity(rsV.getString(6)); +421 vuln.setCvssAuthentication(rsV.getString(7)); +422 vuln.setCvssConfidentialityImpact(rsV.getString(8)); +423 vuln.setCvssIntegrityImpact(rsV.getString(9)); +424 vuln.setCvssAvailabilityImpact(rsV.getString(10)); +425 +426 psR = getConnection().prepareStatement(statementBundle.getString("SELECT_REFERENCES")); +427 psR.setInt(1, cveId); +428 rsR = psR.executeQuery(); +429 while (rsR.next()) { +430 vuln.addReference(rsR.getString(1), rsR.getString(2), rsR.getString(3)); +431 } +432 psS = getConnection().prepareStatement(statementBundle.getString("SELECT_SOFTWARE")); +433 psS.setInt(1, cveId); +434 rsS = psS.executeQuery(); +435 while (rsS.next()) { +436 final String cpe = rsS.getString(1); +437 final String prevVersion = rsS.getString(2); +438 if (prevVersion == null) { +439 vuln.addVulnerableSoftware(cpe); +440 } else { +441 vuln.addVulnerableSoftware(cpe, prevVersion); +442 } +443 } +444 } +445 } catch (SQLException ex) { +446 throw new DatabaseException("Error retrieving " + cve, ex); +447 } finally { +448 DBUtils.closeResultSet(rsV); +449 DBUtils.closeResultSet(rsR); +450 DBUtils.closeResultSet(rsS); +451 DBUtils.closeStatement(psV); +452 DBUtils.closeStatement(psR); +453 DBUtils.closeStatement(psS); +454 } +455 return vuln; +456 } +457 +458 /** +459 * Updates the vulnerability within the database. If the vulnerability does +460 * not exist it will be added. +461 * +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 { +466 PreparedStatement selectVulnerabilityId = null; +467 PreparedStatement deleteVulnerability = null; +468 PreparedStatement deleteReferences = null; +469 PreparedStatement deleteSoftware = null; +470 PreparedStatement updateVulnerability = null; +471 PreparedStatement insertVulnerability = null; +472 PreparedStatement insertReference = null; +473 PreparedStatement selectCpeId = null; +474 PreparedStatement insertCpe = null; +475 PreparedStatement insertSoftware = null; +476 +477 try { +478 selectVulnerabilityId = getConnection().prepareStatement(statementBundle.getString("SELECT_VULNERABILITY_ID")); +479 deleteVulnerability = getConnection().prepareStatement(statementBundle.getString("DELETE_VULNERABILITY")); +480 deleteReferences = getConnection().prepareStatement(statementBundle.getString("DELETE_REFERENCE")); +481 deleteSoftware = getConnection().prepareStatement(statementBundle.getString("DELETE_SOFTWARE")); +482 updateVulnerability = getConnection().prepareStatement(statementBundle.getString("UPDATE_VULNERABILITY")); +483 final String[] ids = {"id"}; +484 insertVulnerability = getConnection().prepareStatement(statementBundle.getString("INSERT_VULNERABILITY"), +485 //Statement.RETURN_GENERATED_KEYS); +486 ids); +487 insertReference = getConnection().prepareStatement(statementBundle.getString("INSERT_REFERENCE")); +488 selectCpeId = getConnection().prepareStatement(statementBundle.getString("SELECT_CPE_ID")); +489 insertCpe = getConnection().prepareStatement(statementBundle.getString("INSERT_CPE"), +490 //Statement.RETURN_GENERATED_KEYS); +491 ids); +492 insertSoftware = getConnection().prepareStatement(statementBundle.getString("INSERT_SOFTWARE")); +493 int vulnerabilityId = 0; +494 selectVulnerabilityId.setString(1, vuln.getName()); +495 ResultSet rs = selectVulnerabilityId.executeQuery(); +496 if (rs.next()) { +497 vulnerabilityId = rs.getInt(1); +498 // first delete any existing vulnerability info. We don't know what was updated. yes, slower but atm easier. +499 deleteReferences.setInt(1, vulnerabilityId); +500 deleteReferences.execute(); +501 deleteSoftware.setInt(1, vulnerabilityId); +502 deleteSoftware.execute(); +503 } +504 DBUtils.closeResultSet(rs); +505 rs = null; +506 +507 if (vulnerabilityId != 0) { +508 if (vuln.getDescription().contains("** REJECT **")) { +509 deleteVulnerability.setInt(1, vulnerabilityId); +510 deleteVulnerability.executeUpdate(); +511 } else { +512 updateVulnerability.setString(1, vuln.getDescription()); +513 updateVulnerability.setString(2, vuln.getCwe()); +514 updateVulnerability.setFloat(3, vuln.getCvssScore()); +515 updateVulnerability.setString(4, vuln.getCvssAccessVector()); +516 updateVulnerability.setString(5, vuln.getCvssAccessComplexity()); +517 updateVulnerability.setString(6, vuln.getCvssAuthentication()); +518 updateVulnerability.setString(7, vuln.getCvssConfidentialityImpact()); +519 updateVulnerability.setString(8, vuln.getCvssIntegrityImpact()); +520 updateVulnerability.setString(9, vuln.getCvssAvailabilityImpact()); +521 updateVulnerability.setInt(10, vulnerabilityId); +522 updateVulnerability.executeUpdate(); +523 } +524 } else { +525 insertVulnerability.setString(1, vuln.getName()); +526 insertVulnerability.setString(2, vuln.getDescription()); +527 insertVulnerability.setString(3, vuln.getCwe()); +528 insertVulnerability.setFloat(4, vuln.getCvssScore()); +529 insertVulnerability.setString(5, vuln.getCvssAccessVector()); +530 insertVulnerability.setString(6, vuln.getCvssAccessComplexity()); +531 insertVulnerability.setString(7, vuln.getCvssAuthentication()); +532 insertVulnerability.setString(8, vuln.getCvssConfidentialityImpact()); +533 insertVulnerability.setString(9, vuln.getCvssIntegrityImpact()); +534 insertVulnerability.setString(10, vuln.getCvssAvailabilityImpact()); +535 insertVulnerability.execute(); +536 try { +537 rs = insertVulnerability.getGeneratedKeys(); +538 rs.next(); +539 vulnerabilityId = rs.getInt(1); +540 } catch (SQLException ex) { +541 final String msg = String.format("Unable to retrieve id for new vulnerability for '%s'", vuln.getName()); +542 throw new DatabaseException(msg, ex); +543 } finally { +544 DBUtils.closeResultSet(rs); +545 rs = null; +546 } +547 } +548 +549 for (Reference r : vuln.getReferences()) { +550 insertReference.setInt(1, vulnerabilityId); +551 insertReference.setString(2, r.getName()); +552 insertReference.setString(3, r.getUrl()); +553 insertReference.setString(4, r.getSource()); +554 +555 if (batchSupported) { +556 insertReference.addBatch(); +557 } else { +558 insertReference.execute(); +559 } +560 } +561 +562 if (batchSupported) { +563 insertReference.executeBatch(); +564 } +565 +566 for (VulnerableSoftware s : vuln.getVulnerableSoftware()) { +567 int cpeProductId = 0; +568 selectCpeId.setString(1, s.getName()); +569 try { +570 rs = selectCpeId.executeQuery(); +571 if (rs.next()) { +572 cpeProductId = rs.getInt(1); +573 } +574 } catch (SQLException ex) { +575 throw new DatabaseException("Unable to get primary key for new cpe: " + s.getName(), ex); +576 } finally { +577 DBUtils.closeResultSet(rs); +578 rs = null; +579 } +580 +581 if (cpeProductId == 0) { +582 insertCpe.setString(1, s.getName()); +583 insertCpe.setString(2, s.getVendor()); +584 insertCpe.setString(3, s.getProduct()); +585 insertCpe.executeUpdate(); +586 cpeProductId = DBUtils.getGeneratedKey(insertCpe); +587 } +588 if (cpeProductId == 0) { +589 throw new DatabaseException("Unable to retrieve cpeProductId - no data returned"); +590 } +591 +592 insertSoftware.setInt(1, vulnerabilityId); +593 insertSoftware.setInt(2, cpeProductId); +594 +595 if (s.getPreviousVersion() == null) { +596 insertSoftware.setNull(3, java.sql.Types.VARCHAR); +597 } else { +598 insertSoftware.setString(3, s.getPreviousVersion()); +599 } +600 if (batchSupported) { +601 insertSoftware.addBatch(); +602 } else { +603 try { +604 insertSoftware.execute(); +605 } catch (SQLException ex) { +606 if (ex.getMessage().contains("Duplicate entry")) { +607 final String msg = String.format("Duplicate software key identified in '%s:%s'", vuln.getName(), s.getName()); +608 LOGGER.debug(msg, ex); +609 } else { +610 throw ex; +611 } +612 } +613 } +614 } +615 if (batchSupported) { +616 insertSoftware.executeBatch(); +617 } +618 } catch (SQLException ex) { +619 final String msg = String.format("Error updating '%s'", vuln.getName()); +620 LOGGER.debug(msg, ex); +621 throw new DatabaseException(msg, ex); +622 } finally { +623 DBUtils.closeStatement(selectVulnerabilityId); +624 DBUtils.closeStatement(deleteReferences); +625 DBUtils.closeStatement(deleteSoftware); +626 DBUtils.closeStatement(updateVulnerability); +627 DBUtils.closeStatement(deleteVulnerability); +628 DBUtils.closeStatement(insertVulnerability); +629 DBUtils.closeStatement(insertReference); +630 DBUtils.closeStatement(selectCpeId); +631 DBUtils.closeStatement(insertCpe); +632 DBUtils.closeStatement(insertSoftware); +633 } +634 } +635 +636 /** +637 * Checks to see if data exists so that analysis can be performed. +638 * +639 * @return <code>true</code> if data exists; otherwise <code>false</code> +640 */ +641 public boolean dataExists() { +642 Statement cs = null; +643 ResultSet rs = null; +644 try { +645 cs = conn.createStatement(); +646 rs = cs.executeQuery("SELECT COUNT(*) records FROM cpeEntry"); +647 if (rs.next()) { +648 if (rs.getInt(1) > 0) { +649 return true; +650 } +651 } +652 } catch (SQLException ex) { +653 String dd; +654 try { +655 dd = Settings.getDataDirectory().getAbsolutePath(); +656 } catch (IOException ex1) { +657 dd = Settings.getString(Settings.KEYS.DATA_DIRECTORY); +658 } +659 LOGGER.error("Unable to access the local database.\n\nEnsure that '{}' is a writable directory. " +660 + "If the problem persist try deleting the files in '{}' and running {} again. If the problem continues, please " +661 + "create a log file (see documentation at http://jeremylong.github.io/DependencyCheck/) and open a ticket at " +662 + "https://github.com/jeremylong/DependencyCheck/issues and include the log file.\n\n", +663 dd, dd, Settings.getString(Settings.KEYS.APPLICATION_NAME)); +664 LOGGER.debug("", ex); +665 } finally { +666 DBUtils.closeResultSet(rs); +667 DBUtils.closeStatement(cs); +668 } +669 return false; +670 } +671 +672 /** +673 * It is possible that orphaned rows may be generated during database +674 * updates. This should be called after all updates have been completed to +675 * ensure orphan entries are removed. +676 */ +677 public void cleanupDatabase() { +678 PreparedStatement ps = null; +679 try { +680 ps = getConnection().prepareStatement(statementBundle.getString("CLEANUP_ORPHANS")); +681 if (ps != null) { +682 ps.executeUpdate(); +683 } +684 } catch (SQLException ex) { +685 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details."); +686 LOGGER.debug("", ex); +687 } finally { +688 DBUtils.closeStatement(ps); +689 } +690 } +691 +692 /** +693 * Determines if the given identifiedVersion is affected by the given cpeId +694 * and previous version flag. A non-null, non-empty string passed to the +695 * previous version argument indicates that all previous versions are +696 * affected. +697 * +698 * @param vendor the vendor of the dependency being analyzed +699 * @param product the product name of the dependency being analyzed +700 * @param vulnerableSoftware a map of the vulnerable software with a boolean +701 * indicating if all previous versions are affected +702 * @param identifiedVersion the identified version of the dependency being +703 * analyzed +704 * @return true if the identified version is affected, otherwise false +705 */ +706 Entry<String, Boolean> getMatchingSoftware(Map<String, Boolean> vulnerableSoftware, String vendor, String product, +707 DependencyVersion identifiedVersion) { 708 -709 final Set<String> majorVersionsAffectingAllPrevious = new HashSet<String>(); -710 final boolean matchesAnyPrevious = identifiedVersion == null || "-".equals(identifiedVersion.toString()); -711 String majorVersionMatch = null; -712 for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) { -713 final DependencyVersion v = parseDependencyVersion(entry.getKey()); -714 if (v == null || "-".equals(v.toString())) { //all versions -715 return entry; -716 } -717 if (entry.getValue()) { -718 if (matchesAnyPrevious) { -719 return entry; -720 } -721 if (identifiedVersion != null && identifiedVersion.getVersionParts().get(0).equals(v.getVersionParts().get(0))) { -722 majorVersionMatch = v.getVersionParts().get(0); -723 } -724 majorVersionsAffectingAllPrevious.add(v.getVersionParts().get(0)); -725 } -726 } -727 if (matchesAnyPrevious) { -728 return null; -729 } -730 -731 final boolean canSkipVersions = majorVersionMatch != null && majorVersionsAffectingAllPrevious.size() > 1; -732 //yes, we are iterating over this twice. The first time we are skipping versions those that affect all versions -733 //then later we process those that affect all versions. This could be done with sorting... -734 for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) { -735 if (!entry.getValue()) { -736 final DependencyVersion v = parseDependencyVersion(entry.getKey()); -737 //this can't dereference a null 'majorVersionMatch' as canSkipVersions accounts for this. -738 if (canSkipVersions && !majorVersionMatch.equals(v.getVersionParts().get(0))) { -739 continue; -740 } -741 //this can't dereference a null 'identifiedVersion' because if it was null we would have exited -742 //in the above loop or just after loop (if matchesAnyPrevious return null). -743 if (identifiedVersion.equals(v)) { -744 return entry; -745 } -746 } -747 } -748 for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) { -749 if (entry.getValue()) { -750 final DependencyVersion v = parseDependencyVersion(entry.getKey()); -751 //this can't dereference a null 'majorVersionMatch' as canSkipVersions accounts for this. -752 if (canSkipVersions && !majorVersionMatch.equals(v.getVersionParts().get(0))) { -753 continue; -754 } -755 //this can't dereference a null 'identifiedVersion' because if it was null we would have exited -756 //in the above loop or just after loop (if matchesAnyPrevious return null). -757 if (entry.getValue() && identifiedVersion.compareTo(v) <= 0) { -758 if (!(isVersionTwoADifferentProduct && !identifiedVersion.getVersionParts().get(0).equals(v.getVersionParts().get(0)))) { -759 return entry; -760 } -761 } -762 } -763 } -764 return null; -765 } -766 -767 /** -768 * Parses the version (including revision) from a CPE identifier. If no -769 * version is identified then a '-' is returned. -770 * -771 * @param cpeStr a cpe identifier -772 * @return a dependency version -773 */ -774 private DependencyVersion parseDependencyVersion(String cpeStr) { -775 final VulnerableSoftware cpe = new VulnerableSoftware(); -776 try { -777 cpe.parseName(cpeStr); -778 } catch (UnsupportedEncodingException ex) { -779 //never going to happen. -780 LOGGER.trace("", ex); -781 } -782 return parseDependencyVersion(cpe); -783 } -784 -785 /** -786 * Takes a CPE and parses out the version number. If no version is -787 * identified then a '-' is returned. -788 * -789 * @param cpe a cpe object -790 * @return a dependency version -791 */ -792 private DependencyVersion parseDependencyVersion(VulnerableSoftware cpe) { -793 final DependencyVersion cpeVersion; -794 if (cpe.getVersion() != null && !cpe.getVersion().isEmpty()) { -795 final String versionText; -796 if (cpe.getUpdate() != null && !cpe.getUpdate().isEmpty()) { -797 versionText = String.format("%s.%s", cpe.getVersion(), cpe.getUpdate()); -798 } else { -799 versionText = cpe.getVersion(); -800 } -801 cpeVersion = DependencyVersionUtil.parseVersion(versionText); -802 } else { -803 cpeVersion = new DependencyVersion("-"); -804 } -805 return cpeVersion; -806 } -807 -808 /** -809 * This method is only referenced in unused code. -810 * -811 * Deletes unused dictionary entries from the database. -812 */ -813 public void deleteUnusedCpe() { -814 PreparedStatement ps = null; -815 try { -816 ps = getConnection().prepareStatement(statementBundle.getString("DELETE_UNUSED_DICT_CPE")); -817 ps.executeUpdate(); -818 } catch (SQLException ex) { -819 LOGGER.error("Unable to delete CPE dictionary entries", ex); -820 } finally { -821 DBUtils.closeStatement(ps); -822 } -823 } -824 -825 /** -826 * This method is only referenced in unused code and will likely break on -827 * MySQL if ever used due to the MERGE statement. -828 * -829 * Merges CPE entries into the database. +709 final boolean isVersionTwoADifferentProduct = "apache".equals(vendor) && "struts".equals(product); +710 +711 final Set<String> majorVersionsAffectingAllPrevious = new HashSet<String>(); +712 final boolean matchesAnyPrevious = identifiedVersion == null || "-".equals(identifiedVersion.toString()); +713 String majorVersionMatch = null; +714 for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) { +715 final DependencyVersion v = parseDependencyVersion(entry.getKey()); +716 if (v == null || "-".equals(v.toString())) { //all versions +717 return entry; +718 } +719 if (entry.getValue()) { +720 if (matchesAnyPrevious) { +721 return entry; +722 } +723 if (identifiedVersion != null && identifiedVersion.getVersionParts().get(0).equals(v.getVersionParts().get(0))) { +724 majorVersionMatch = v.getVersionParts().get(0); +725 } +726 majorVersionsAffectingAllPrevious.add(v.getVersionParts().get(0)); +727 } +728 } +729 if (matchesAnyPrevious) { +730 return null; +731 } +732 +733 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 for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) { +737 if (!entry.getValue()) { +738 final DependencyVersion v = parseDependencyVersion(entry.getKey()); +739 //this can't dereference a null 'majorVersionMatch' as canSkipVersions accounts for this. +740 if (canSkipVersions && !majorVersionMatch.equals(v.getVersionParts().get(0))) { +741 continue; +742 } +743 //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 if (identifiedVersion.equals(v)) { +746 return entry; +747 } +748 } +749 } +750 for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) { +751 if (entry.getValue()) { +752 final DependencyVersion v = parseDependencyVersion(entry.getKey()); +753 //this can't dereference a null 'majorVersionMatch' as canSkipVersions accounts for this. +754 if (canSkipVersions && !majorVersionMatch.equals(v.getVersionParts().get(0))) { +755 continue; +756 } +757 //this can't dereference a null 'identifiedVersion' because if it was null we would have exited +758 //in the above loop or just after loop (if matchesAnyPrevious return null). +759 if (entry.getValue() && identifiedVersion.compareTo(v) <= 0) { +760 if (!(isVersionTwoADifferentProduct && !identifiedVersion.getVersionParts().get(0).equals(v.getVersionParts().get(0)))) { +761 return entry; +762 } +763 } +764 } +765 } +766 return null; +767 } +768 +769 /** +770 * Parses the version (including revision) from a CPE identifier. If no +771 * version is identified then a '-' is returned. +772 * +773 * @param cpeStr a cpe identifier +774 * @return a dependency version +775 */ +776 private DependencyVersion parseDependencyVersion(String cpeStr) { +777 final VulnerableSoftware cpe = new VulnerableSoftware(); +778 try { +779 cpe.parseName(cpeStr); +780 } catch (UnsupportedEncodingException ex) { +781 //never going to happen. +782 LOGGER.trace("", ex); +783 } +784 return parseDependencyVersion(cpe); +785 } +786 +787 /** +788 * Takes a CPE and parses out the version number. If no version is +789 * identified then a '-' is returned. +790 * +791 * @param cpe a cpe object +792 * @return a dependency version +793 */ +794 private DependencyVersion parseDependencyVersion(VulnerableSoftware cpe) { +795 final DependencyVersion cpeVersion; +796 if (cpe.getVersion() != null && !cpe.getVersion().isEmpty()) { +797 final String versionText; +798 if (cpe.getUpdate() != null && !cpe.getUpdate().isEmpty()) { +799 versionText = String.format("%s.%s", cpe.getVersion(), cpe.getUpdate()); +800 } else { +801 versionText = cpe.getVersion(); +802 } +803 cpeVersion = DependencyVersionUtil.parseVersion(versionText); +804 } else { +805 cpeVersion = new DependencyVersion("-"); +806 } +807 return cpeVersion; +808 } +809 +810 /** +811 * This method is only referenced in unused code. +812 * +813 * Deletes unused dictionary entries from the database. +814 */ +815 public void deleteUnusedCpe() { +816 PreparedStatement ps = null; +817 try { +818 ps = getConnection().prepareStatement(statementBundle.getString("DELETE_UNUSED_DICT_CPE")); +819 ps.executeUpdate(); +820 } catch (SQLException ex) { +821 LOGGER.error("Unable to delete CPE dictionary entries", ex); +822 } finally { +823 DBUtils.closeStatement(ps); +824 } +825 } +826 +827 /** +828 * This method is only referenced in unused code and will likely break on +829 * MySQL if ever used due to the MERGE statement. 830 * -831 * @param cpe the CPE identifier -832 * @param vendor the CPE vendor -833 * @param product the CPE product -834 */ -835 public void addCpe(String cpe, String vendor, String product) { -836 PreparedStatement ps = null; -837 try { -838 ps = getConnection().prepareStatement(statementBundle.getString("ADD_DICT_CPE")); -839 ps.setString(1, cpe); -840 ps.setString(2, vendor); -841 ps.setString(3, product); -842 ps.executeUpdate(); -843 } catch (SQLException ex) { -844 LOGGER.error("Unable to add CPE dictionary entry", ex); -845 } finally { -846 DBUtils.closeStatement(ps); -847 } -848 } -849 } +831 * Merges CPE entries into the database. +832 * +833 * @param cpe the CPE identifier +834 * @param vendor the CPE vendor +835 * @param product the CPE product +836 */ +837 public void addCpe(String cpe, String vendor, String product) { +838 PreparedStatement ps = null; +839 try { +840 ps = getConnection().prepareStatement(statementBundle.getString("ADD_DICT_CPE")); +841 ps.setString(1, cpe); +842 ps.setString(2, vendor); +843 ps.setString(3, product); +844 ps.executeUpdate(); +845 } catch (SQLException ex) { +846 LOGGER.error("Unable to add CPE dictionary entry", ex); +847 } finally { +848 DBUtils.closeStatement(ps); +849 } +850 } +851 }
    diff --git a/xref/org/owasp/dependencycheck/data/nvdcve/package-frame.html b/xref/org/owasp/dependencycheck/data/nvdcve/package-frame.html index 46555b90e..315e84eee 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.2 Reference Package org.owasp.dependencycheck.data.nvdcve + Dependency-Check 1.4.3 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 4fd072923..5209749a5 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.2 Reference Package org.owasp.dependencycheck.data.nvdcve + Dependency-Check 1.4.3 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 19eb152fa..7a0aec0a8 100644 --- a/xref/org/owasp/dependencycheck/data/update/CpeUpdater.html +++ b/xref/org/owasp/dependencycheck/data/update/CpeUpdater.html @@ -166,46 +166,48 @@ 158 final String originalPath = file.getPath(); 159 final File gzip = new File(originalPath + ".gz"); 160 if (gzip.isFile() && !gzip.delete()) { -161 gzip.deleteOnExit(); -162 } -163 if (!file.renameTo(gzip)) { -164 throw new IOException("Unable to rename '" + file.getPath() + "'"); -165 } -166 final File newfile = new File(originalPath); -167 -168 final byte[] buffer = new byte[4096]; -169 -170 GZIPInputStream cin = null; -171 FileOutputStream out = null; -172 try { -173 cin = new GZIPInputStream(new FileInputStream(gzip)); -174 out = new FileOutputStream(newfile); -175 -176 int len; -177 while ((len = cin.read(buffer)) > 0) { -178 out.write(buffer, 0, len); -179 } -180 } finally { -181 if (cin != null) { -182 try { -183 cin.close(); -184 } catch (IOException ex) { -185 LOGGER.trace("ignore", ex); -186 } -187 } -188 if (out != null) { -189 try { -190 out.close(); -191 } catch (IOException ex) { -192 LOGGER.trace("ignore", ex); -193 } -194 } -195 if (gzip.isFile()) { -196 FileUtils.deleteQuietly(gzip); -197 } -198 } -199 } -200 } +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); +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 } +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 }
    diff --git a/xref/org/owasp/dependencycheck/data/update/EngineVersionCheck.html b/xref/org/owasp/dependencycheck/data/update/EngineVersionCheck.html index 756ce7202..1edd3a333 100644 --- a/xref/org/owasp/dependencycheck/data/update/EngineVersionCheck.html +++ b/xref/org/owasp/dependencycheck/data/update/EngineVersionCheck.html @@ -228,11 +228,11 @@ 220 return releaseVersion.trim(); 221 } 222 } catch (MalformedURLException ex) { -223 LOGGER.debug("Unable to retrieve current release version of dependency-check", ex); +223 LOGGER.debug("Unable to retrieve current release version of dependency-check - malformed url?"); 224 } catch (URLConnectionFailureException ex) { -225 LOGGER.debug("Unable to retrieve current release version of dependency-check", ex); +225 LOGGER.debug("Unable to retrieve current release version of dependency-check - connection failed"); 226 } catch (IOException ex) { -227 LOGGER.debug("Unable to retrieve current release version of dependency-check", ex); +227 LOGGER.debug("Unable to retrieve current release version of dependency-check - i/o exception"); 228 } finally { 229 if (conn != null) { 230 conn.disconnect(); diff --git a/xref/org/owasp/dependencycheck/data/update/NvdCveUpdater.html b/xref/org/owasp/dependencycheck/data/update/NvdCveUpdater.html index ccd49bf55..caa45c914 100644 --- a/xref/org/owasp/dependencycheck/data/update/NvdCveUpdater.html +++ b/xref/org/owasp/dependencycheck/data/update/NvdCveUpdater.html @@ -85,10 +85,10 @@ 77 } 78 if (autoUpdate && checkUpdate()) { 79 final UpdateableNvdCve updateable = getUpdatesNeeded(); -80 getProperties().save(DatabaseProperties.LAST_CHECKED, Long.toString(System.currentTimeMillis())); -81 if (updateable.isUpdateNeeded()) { -82 performUpdate(updateable); -83 } +80 if (updateable.isUpdateNeeded()) { +81 performUpdate(updateable); +82 } +83 getProperties().save(DatabaseProperties.LAST_CHECKED, Long.toString(System.currentTimeMillis())); 84 } 85 } catch (MalformedURLException ex) { 86 throw new UpdateException("NVD CVE properties files contain an invalid URL, unable to update the data to use the most current data.", ex); @@ -164,200 +164,193 @@ 156 * @throws UpdateException is thrown if there is an error updating the 157 * database 158 */ -159 public void performUpdate(UpdateableNvdCve updateable) throws UpdateException { +159 private void performUpdate(UpdateableNvdCve updateable) throws UpdateException { 160 int maxUpdates = 0; -161 try { -162 for (NvdCveInfo cve : updateable) { -163 if (cve.getNeedsUpdate()) { -164 maxUpdates += 1; -165 } -166 } -167 if (maxUpdates <= 0) { -168 return; -169 } -170 if (maxUpdates > 3) { -171 LOGGER.info("NVD CVE requires several updates; this could take a couple of minutes."); -172 } -173 if (maxUpdates > 0) { -174 openDataStores(); -175 } -176 -177 final int poolSize = (MAX_THREAD_POOL_SIZE < maxUpdates) ? MAX_THREAD_POOL_SIZE : maxUpdates; -178 -179 final ExecutorService downloadExecutors = Executors.newFixedThreadPool(poolSize); -180 final ExecutorService processExecutor = Executors.newSingleThreadExecutor(); -181 final Set<Future<Future<ProcessTask>>> downloadFutures = new HashSet<Future<Future<ProcessTask>>>(maxUpdates); -182 for (NvdCveInfo cve : updateable) { -183 if (cve.getNeedsUpdate()) { -184 final DownloadTask call = new DownloadTask(cve, processExecutor, getCveDB(), Settings.getInstance()); -185 downloadFutures.add(downloadExecutors.submit(call)); -186 } -187 } -188 downloadExecutors.shutdown(); -189 -190 //next, move the future future processTasks to just future processTasks -191 final Set<Future<ProcessTask>> processFutures = new HashSet<Future<ProcessTask>>(maxUpdates); -192 for (Future<Future<ProcessTask>> future : downloadFutures) { -193 Future<ProcessTask> task = null; -194 try { -195 task = future.get(); -196 } catch (InterruptedException ex) { -197 downloadExecutors.shutdownNow(); -198 processExecutor.shutdownNow(); -199 -200 LOGGER.debug("Thread was interrupted during download", ex); -201 throw new UpdateException("The download was interrupted", ex); -202 } catch (ExecutionException ex) { -203 downloadExecutors.shutdownNow(); -204 processExecutor.shutdownNow(); -205 -206 LOGGER.debug("Thread was interrupted during download execution", ex); -207 throw new UpdateException("The execution of the download was interrupted", ex); -208 } -209 if (task == null) { -210 downloadExecutors.shutdownNow(); -211 processExecutor.shutdownNow(); -212 LOGGER.debug("Thread was interrupted during download"); -213 throw new UpdateException("The download was interrupted; unable to complete the update"); -214 } else { -215 processFutures.add(task); -216 } -217 } -218 -219 for (Future<ProcessTask> future : processFutures) { -220 try { -221 final ProcessTask task = future.get(); -222 if (task.getException() != null) { -223 throw task.getException(); -224 } -225 } catch (InterruptedException ex) { -226 processExecutor.shutdownNow(); -227 LOGGER.debug("Thread was interrupted during processing", ex); -228 throw new UpdateException(ex); -229 } catch (ExecutionException ex) { -230 processExecutor.shutdownNow(); -231 LOGGER.debug("Execution Exception during process", ex); -232 throw new UpdateException(ex); -233 } finally { -234 processExecutor.shutdown(); -235 } -236 } -237 -238 if (maxUpdates >= 1) { //ensure the modified file date gets written (we may not have actually updated it) -239 getProperties().save(updateable.get(MODIFIED)); -240 LOGGER.info("Begin database maintenance."); -241 getCveDB().cleanupDatabase(); -242 LOGGER.info("End database maintenance."); -243 } -244 } finally { -245 closeDataStores(); -246 } -247 } -248 -249 /** -250 * Determines if the index needs to be updated. This is done by fetching the -251 * NVD CVE meta data and checking the last update date. If the data needs to -252 * be refreshed this method will return the NvdCveUrl for the files that -253 * need to be updated. -254 * -255 * @return the collection of files that need to be updated -256 * @throws MalformedURLException is thrown if the URL for the NVD CVE Meta -257 * data is incorrect -258 * @throws DownloadFailedException is thrown if there is an error. -259 * downloading the NVD CVE download data file -260 * @throws UpdateException Is thrown if there is an issue with the last -261 * updated properties file -262 */ -263 protected final UpdateableNvdCve getUpdatesNeeded() throws MalformedURLException, DownloadFailedException, UpdateException { -264 UpdateableNvdCve updates = null; -265 try { -266 updates = retrieveCurrentTimestampsFromWeb(); -267 } catch (InvalidDataException ex) { -268 final String msg = "Unable to retrieve valid timestamp from nvd cve downloads page"; -269 LOGGER.debug(msg, ex); -270 throw new DownloadFailedException(msg, ex); -271 } catch (InvalidSettingException ex) { -272 LOGGER.debug("Invalid setting found when retrieving timestamps", ex); -273 throw new DownloadFailedException("Invalid settings", ex); -274 } -275 -276 if (updates == null) { -277 throw new DownloadFailedException("Unable to retrieve the timestamps of the currently published NVD CVE data"); -278 } -279 if (!getProperties().isEmpty()) { -280 try { -281 final long lastUpdated = Long.parseLong(getProperties().getProperty(DatabaseProperties.LAST_UPDATED, "0")); -282 final long now = System.currentTimeMillis(); -283 final int days = Settings.getInt(Settings.KEYS.CVE_MODIFIED_VALID_FOR_DAYS, 7); -284 if (lastUpdated == updates.getTimeStamp(MODIFIED)) { -285 updates.clear(); //we don't need to update anything. -286 } else if (DateUtil.withinDateRange(lastUpdated, now, days)) { -287 for (NvdCveInfo entry : updates) { -288 if (MODIFIED.equals(entry.getId())) { -289 entry.setNeedsUpdate(true); -290 } else { -291 entry.setNeedsUpdate(false); -292 } -293 } -294 } else { //we figure out which of the several XML files need to be downloaded. -295 for (NvdCveInfo entry : updates) { -296 if (MODIFIED.equals(entry.getId())) { -297 entry.setNeedsUpdate(true); -298 } else { -299 long currentTimestamp = 0; -300 try { -301 currentTimestamp = Long.parseLong(getProperties().getProperty(DatabaseProperties.LAST_UPDATED_BASE -302 + entry.getId(), "0")); -303 } catch (NumberFormatException ex) { -304 LOGGER.debug("Error parsing '{}' '{}' from nvdcve.lastupdated", -305 DatabaseProperties.LAST_UPDATED_BASE, entry.getId(), ex); -306 } -307 if (currentTimestamp == entry.getTimestamp()) { -308 entry.setNeedsUpdate(false); -309 } -310 } -311 } -312 } -313 } catch (NumberFormatException ex) { -314 LOGGER.warn("An invalid schema version or timestamp exists in the data.properties file."); -315 LOGGER.debug("", ex); -316 } -317 } -318 return updates; -319 } -320 -321 /** -322 * Retrieves the timestamps from the NVD CVE meta data file. -323 * -324 * @return the timestamp from the currently published nvdcve downloads page -325 * @throws MalformedURLException thrown if the URL for the NVD CCE Meta data -326 * is incorrect. -327 * @throws DownloadFailedException thrown if there is an error downloading -328 * the nvd cve meta data file -329 * @throws InvalidDataException thrown if there is an exception parsing the -330 * timestamps -331 * @throws InvalidSettingException thrown if the settings are invalid -332 */ -333 private UpdateableNvdCve retrieveCurrentTimestampsFromWeb() -334 throws MalformedURLException, DownloadFailedException, InvalidDataException, InvalidSettingException { -335 -336 final UpdateableNvdCve updates = new UpdateableNvdCve(); -337 updates.add(MODIFIED, Settings.getString(Settings.KEYS.CVE_MODIFIED_20_URL), -338 Settings.getString(Settings.KEYS.CVE_MODIFIED_12_URL), -339 false); -340 -341 final int start = Settings.getInt(Settings.KEYS.CVE_START_YEAR); -342 final int end = Calendar.getInstance().get(Calendar.YEAR); -343 final String baseUrl20 = Settings.getString(Settings.KEYS.CVE_SCHEMA_2_0); -344 final String baseUrl12 = Settings.getString(Settings.KEYS.CVE_SCHEMA_1_2); -345 for (int i = start; i <= end; i++) { -346 updates.add(Integer.toString(i), String.format(baseUrl20, i), -347 String.format(baseUrl12, i), -348 true); -349 } -350 return updates; -351 } -352 } +161 for (NvdCveInfo cve : updateable) { +162 if (cve.getNeedsUpdate()) { +163 maxUpdates += 1; +164 } +165 } +166 if (maxUpdates <= 0) { +167 return; +168 } +169 if (maxUpdates > 3) { +170 LOGGER.info("NVD CVE requires several updates; this could take a couple of minutes."); +171 } +172 +173 final int poolSize = (MAX_THREAD_POOL_SIZE < maxUpdates) ? MAX_THREAD_POOL_SIZE : maxUpdates; +174 +175 final ExecutorService downloadExecutors = Executors.newFixedThreadPool(poolSize); +176 final ExecutorService processExecutor = Executors.newSingleThreadExecutor(); +177 final Set<Future<Future<ProcessTask>>> downloadFutures = new HashSet<Future<Future<ProcessTask>>>(maxUpdates); +178 for (NvdCveInfo cve : updateable) { +179 if (cve.getNeedsUpdate()) { +180 final DownloadTask call = new DownloadTask(cve, processExecutor, getCveDB(), Settings.getInstance()); +181 downloadFutures.add(downloadExecutors.submit(call)); +182 } +183 } +184 downloadExecutors.shutdown(); +185 +186 //next, move the future future processTasks to just future processTasks +187 final Set<Future<ProcessTask>> processFutures = new HashSet<Future<ProcessTask>>(maxUpdates); +188 for (Future<Future<ProcessTask>> future : downloadFutures) { +189 Future<ProcessTask> task = null; +190 try { +191 task = future.get(); +192 } catch (InterruptedException ex) { +193 downloadExecutors.shutdownNow(); +194 processExecutor.shutdownNow(); +195 +196 LOGGER.debug("Thread was interrupted during download", ex); +197 throw new UpdateException("The download was interrupted", ex); +198 } catch (ExecutionException ex) { +199 downloadExecutors.shutdownNow(); +200 processExecutor.shutdownNow(); +201 +202 LOGGER.debug("Thread was interrupted during download execution", ex); +203 throw new UpdateException("The execution of the download was interrupted", ex); +204 } +205 if (task == null) { +206 downloadExecutors.shutdownNow(); +207 processExecutor.shutdownNow(); +208 LOGGER.debug("Thread was interrupted during download"); +209 throw new UpdateException("The download was interrupted; unable to complete the update"); +210 } else { +211 processFutures.add(task); +212 } +213 } +214 +215 for (Future<ProcessTask> future : processFutures) { +216 try { +217 final ProcessTask task = future.get(); +218 if (task.getException() != null) { +219 throw task.getException(); +220 } +221 } catch (InterruptedException ex) { +222 processExecutor.shutdownNow(); +223 LOGGER.debug("Thread was interrupted during processing", ex); +224 throw new UpdateException(ex); +225 } catch (ExecutionException ex) { +226 processExecutor.shutdownNow(); +227 LOGGER.debug("Execution Exception during process", ex); +228 throw new UpdateException(ex); +229 } finally { +230 processExecutor.shutdown(); +231 } +232 } +233 +234 if (maxUpdates >= 1) { //ensure the modified file date gets written (we may not have actually updated it) +235 getProperties().save(updateable.get(MODIFIED)); +236 LOGGER.info("Begin database maintenance."); +237 getCveDB().cleanupDatabase(); +238 LOGGER.info("End database maintenance."); +239 } +240 } +241 +242 /** +243 * Determines if the index needs to be updated. This is done by fetching the +244 * NVD CVE meta data and checking the last update date. If the data needs to +245 * be refreshed this method will return the NvdCveUrl for the files that +246 * need to be updated. +247 * +248 * @return the collection of files that need to be updated +249 * @throws MalformedURLException is thrown if the URL for the NVD CVE Meta +250 * data is incorrect +251 * @throws DownloadFailedException is thrown if there is an error. +252 * downloading the NVD CVE download data file +253 * @throws UpdateException Is thrown if there is an issue with the last +254 * updated properties file +255 */ +256 protected final UpdateableNvdCve getUpdatesNeeded() throws MalformedURLException, DownloadFailedException, UpdateException { +257 UpdateableNvdCve updates = null; +258 try { +259 updates = retrieveCurrentTimestampsFromWeb(); +260 } catch (InvalidDataException ex) { +261 final String msg = "Unable to retrieve valid timestamp from nvd cve downloads page"; +262 LOGGER.debug(msg, ex); +263 throw new DownloadFailedException(msg, ex); +264 } catch (InvalidSettingException ex) { +265 LOGGER.debug("Invalid setting found when retrieving timestamps", ex); +266 throw new DownloadFailedException("Invalid settings", ex); +267 } +268 +269 if (updates == null) { +270 throw new DownloadFailedException("Unable to retrieve the timestamps of the currently published NVD CVE data"); +271 } +272 if (!getProperties().isEmpty()) { +273 try { +274 final long lastUpdated = Long.parseLong(getProperties().getProperty(DatabaseProperties.LAST_UPDATED, "0")); +275 final long now = System.currentTimeMillis(); +276 final int days = Settings.getInt(Settings.KEYS.CVE_MODIFIED_VALID_FOR_DAYS, 7); +277 if (lastUpdated == updates.getTimeStamp(MODIFIED)) { +278 updates.clear(); //we don't need to update anything. +279 } else if (DateUtil.withinDateRange(lastUpdated, now, days)) { +280 for (NvdCveInfo entry : updates) { +281 if (MODIFIED.equals(entry.getId())) { +282 entry.setNeedsUpdate(true); +283 } else { +284 entry.setNeedsUpdate(false); +285 } +286 } +287 } else { //we figure out which of the several XML files need to be downloaded. +288 for (NvdCveInfo entry : updates) { +289 if (MODIFIED.equals(entry.getId())) { +290 entry.setNeedsUpdate(true); +291 } else { +292 long currentTimestamp = 0; +293 try { +294 currentTimestamp = Long.parseLong(getProperties().getProperty(DatabaseProperties.LAST_UPDATED_BASE +295 + entry.getId(), "0")); +296 } catch (NumberFormatException ex) { +297 LOGGER.debug("Error parsing '{}' '{}' from nvdcve.lastupdated", +298 DatabaseProperties.LAST_UPDATED_BASE, entry.getId(), ex); +299 } +300 if (currentTimestamp == entry.getTimestamp()) { +301 entry.setNeedsUpdate(false); +302 } +303 } +304 } +305 } +306 } catch (NumberFormatException ex) { +307 LOGGER.warn("An invalid schema version or timestamp exists in the data.properties file."); +308 LOGGER.debug("", ex); +309 } +310 } +311 return updates; +312 } +313 +314 /** +315 * Retrieves the timestamps from the NVD CVE meta data file. +316 * +317 * @return the timestamp from the currently published nvdcve downloads page +318 * @throws MalformedURLException thrown if the URL for the NVD CCE Meta data +319 * is incorrect. +320 * @throws DownloadFailedException thrown if there is an error downloading +321 * the nvd cve meta data file +322 * @throws InvalidDataException thrown if there is an exception parsing the +323 * timestamps +324 * @throws InvalidSettingException thrown if the settings are invalid +325 */ +326 private UpdateableNvdCve retrieveCurrentTimestampsFromWeb() +327 throws MalformedURLException, DownloadFailedException, InvalidDataException, InvalidSettingException { +328 +329 final UpdateableNvdCve updates = new UpdateableNvdCve(); +330 updates.add(MODIFIED, Settings.getString(Settings.KEYS.CVE_MODIFIED_20_URL), +331 Settings.getString(Settings.KEYS.CVE_MODIFIED_12_URL), +332 false); +333 +334 final int start = Settings.getInt(Settings.KEYS.CVE_START_YEAR); +335 final int end = Calendar.getInstance().get(Calendar.YEAR); +336 final String baseUrl20 = Settings.getString(Settings.KEYS.CVE_SCHEMA_2_0); +337 final String baseUrl12 = Settings.getString(Settings.KEYS.CVE_SCHEMA_1_2); +338 for (int i = start; i <= end; i++) { +339 updates.add(Integer.toString(i), String.format(baseUrl20, i), +340 String.format(baseUrl12, i), +341 true); +342 } +343 return updates; +344 } +345 }
    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 496874446..5bb3cbe38 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.2 Reference Package org.owasp.dependencycheck.data.update.cpe + Dependency-Check 1.4.3 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 3ca1837ec..db77799fa 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.2 Reference Package org.owasp.dependencycheck.data.update.cpe + Dependency-Check 1.4.3 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 440168171..b2abb9cfa 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.2 Reference Package org.owasp.dependencycheck.data.update.exception + Dependency-Check 1.4.3 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 97449ad9e..a74f48053 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.2 Reference Package org.owasp.dependencycheck.data.update.exception + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.update.exception diff --git a/xref/org/owasp/dependencycheck/data/update/nvd/DownloadTask.html b/xref/org/owasp/dependencycheck/data/update/nvd/DownloadTask.html index dd7845863..d1090ab61 100644 --- a/xref/org/owasp/dependencycheck/data/update/nvd/DownloadTask.html +++ b/xref/org/owasp/dependencycheck/data/update/nvd/DownloadTask.html @@ -63,269 +63,261 @@ 55 * @param nvdCveInfo the NVD CVE info 56 * @param processor the processor service to submit the downloaded files to 57 * @param cveDB the CVE DB to use to store the vulnerability data -58 * @param settings a reference to the global settings object; this is necessary so that when the thread is started the -59 * dependencies have a correct reference to the global settings. -60 * @throws UpdateException thrown if temporary files could not be created -61 */ -62 public DownloadTask(NvdCveInfo nvdCveInfo, ExecutorService processor, CveDB cveDB, Settings settings) throws UpdateException { -63 this.nvdCveInfo = nvdCveInfo; -64 this.processorService = processor; -65 this.cveDB = cveDB; -66 this.settings = settings; -67 -68 final File file1; -69 final File file2; -70 -71 try { -72 file1 = File.createTempFile("cve" + nvdCveInfo.getId() + '_', ".xml", Settings.getTempDirectory()); -73 file2 = File.createTempFile("cve_1_2_" + nvdCveInfo.getId() + '_', ".xml", Settings.getTempDirectory()); -74 } catch (IOException ex) { -75 throw new UpdateException("Unable to create temporary files", ex); -76 } -77 this.first = file1; -78 this.second = file2; -79 -80 } -81 /** -82 * The CVE DB to use when processing the files. -83 */ -84 private final CveDB cveDB; -85 /** -86 * The processor service to pass the results of the download to. -87 */ -88 private final ExecutorService processorService; -89 /** -90 * The NVD CVE Meta Data. -91 */ -92 private NvdCveInfo nvdCveInfo; -93 /** -94 * A reference to the global settings object. -95 */ -96 private final Settings settings; -97 -98 /** -99 * Get the value of nvdCveInfo. -100 * -101 * @return the value of nvdCveInfo -102 */ -103 public NvdCveInfo getNvdCveInfo() { -104 return nvdCveInfo; -105 } -106 -107 /** -108 * Set the value of nvdCveInfo. -109 * -110 * @param nvdCveInfo new value of nvdCveInfo -111 */ -112 public void setNvdCveInfo(NvdCveInfo nvdCveInfo) { -113 this.nvdCveInfo = nvdCveInfo; -114 } -115 /** -116 * a file. -117 */ -118 private File first; -119 -120 /** -121 * Get the value of first. -122 * -123 * @return the value of first -124 */ -125 public File getFirst() { -126 return first; -127 } -128 -129 /** -130 * Set the value of first. -131 * -132 * @param first new value of first -133 */ -134 public void setFirst(File first) { -135 this.first = first; -136 } -137 /** -138 * a file. -139 */ -140 private File second; -141 -142 /** -143 * Get the value of second. -144 * -145 * @return the value of second -146 */ -147 public File getSecond() { -148 return second; -149 } -150 -151 /** -152 * Set the value of second. -153 * -154 * @param second new value of second -155 */ -156 public void setSecond(File second) { -157 this.second = second; -158 } -159 -160 @Override -161 public Future<ProcessTask> call() throws Exception { -162 try { -163 Settings.setInstance(settings); -164 final URL url1 = new URL(nvdCveInfo.getUrl()); -165 final URL url2 = new URL(nvdCveInfo.getOldSchemaVersionUrl()); -166 LOGGER.info("Download Started for NVD CVE - {}", nvdCveInfo.getId()); -167 final long startDownload = System.currentTimeMillis(); -168 try { -169 Downloader.fetchFile(url1, first); -170 Downloader.fetchFile(url2, second); -171 } catch (DownloadFailedException ex) { -172 LOGGER.warn("Download Failed for NVD CVE - {}\nSome CVEs may not be reported.", nvdCveInfo.getId()); -173 if (Settings.getString(Settings.KEYS.PROXY_SERVER) == null) { -174 LOGGER.info( -175 "If you are behind a proxy you may need to configure dependency-check to use the proxy."); -176 } -177 LOGGER.debug("", ex); -178 return null; -179 } -180 if (url1.toExternalForm().endsWith(".xml.gz") && !isXml(first)) { -181 extractGzip(first); -182 } -183 if (url2.toExternalForm().endsWith(".xml.gz") && !isXml(second)) { -184 extractGzip(second); -185 } -186 -187 LOGGER.info("Download Complete for NVD CVE - {} ({} ms)", nvdCveInfo.getId(), -188 System.currentTimeMillis() - startDownload); -189 if (this.processorService == null) { -190 return null; -191 } -192 final ProcessTask task = new ProcessTask(cveDB, this, settings); -193 return this.processorService.submit(task); -194 -195 } catch (Throwable ex) { -196 LOGGER.warn("An exception occurred downloading NVD CVE - {}\nSome CVEs may not be reported.", nvdCveInfo.getId()); -197 LOGGER.debug("Download Task Failed", ex); -198 } finally { -199 Settings.cleanup(false); -200 } -201 return null; -202 } -203 -204 /** -205 * Attempts to delete the files that were downloaded. -206 */ -207 public void cleanup() { -208 boolean deleted = false; -209 try { -210 if (first != null && first.exists()) { -211 deleted = first.delete(); -212 } -213 } finally { -214 if (first != null && (first.exists() || !deleted)) { -215 first.deleteOnExit(); -216 } -217 } -218 try { -219 deleted = false; -220 if (second != null && second.exists()) { -221 deleted = second.delete(); -222 } -223 } finally { -224 if (second != null && (second.exists() || !deleted)) { -225 second.deleteOnExit(); -226 } -227 } -228 } -229 -230 /** -231 * Checks the file header to see if it is an XML file. -232 * -233 * @param file the file to check -234 * @return true if the file is XML -235 */ -236 public static boolean isXml(File file) { -237 if (file == null || !file.isFile()) { -238 return false; -239 } -240 InputStream is = null; -241 try { -242 is = new FileInputStream(file); -243 -244 final byte[] buf = new byte[5]; -245 int read = 0; -246 try { -247 read = is.read(buf); -248 } catch (IOException ex) { -249 return false; -250 } -251 return read == 5 -252 && buf[0] == '<' -253 && (buf[1] == '?') -254 && (buf[2] == 'x' || buf[2] == 'X') -255 && (buf[3] == 'm' || buf[3] == 'M') -256 && (buf[4] == 'l' || buf[4] == 'L'); -257 } catch (FileNotFoundException ex) { -258 return false; -259 } finally { -260 if (is != null) { -261 try { -262 is.close(); -263 } catch (IOException ex) { -264 LOGGER.debug("Error closing stream", ex); -265 } -266 } -267 } -268 } -269 -270 /** -271 * Extracts the file contained in a gzip archive. The extracted file is placed in the exact same path as the file specified. -272 * -273 * @param file the archive file -274 * @throws FileNotFoundException thrown if the file does not exist -275 * @throws IOException thrown if there is an error extracting the file. -276 */ -277 private void extractGzip(File file) throws FileNotFoundException, IOException { -278 final String originalPath = file.getPath(); -279 final File gzip = new File(originalPath + ".gz"); -280 if (gzip.isFile() && !gzip.delete()) { -281 gzip.deleteOnExit(); -282 } -283 if (!file.renameTo(gzip)) { -284 throw new IOException("Unable to rename '" + file.getPath() + "'"); -285 } -286 final File newfile = new File(originalPath); -287 -288 final byte[] buffer = new byte[4096]; -289 -290 GZIPInputStream cin = null; -291 FileOutputStream out = null; -292 try { -293 cin = new GZIPInputStream(new FileInputStream(gzip)); -294 out = new FileOutputStream(newfile); -295 -296 int len; -297 while ((len = cin.read(buffer)) > 0) { -298 out.write(buffer, 0, len); -299 } -300 } finally { -301 if (cin != null) { -302 try { -303 cin.close(); -304 } catch (IOException ex) { -305 LOGGER.trace("ignore", ex); -306 } -307 } -308 if (out != null) { -309 try { -310 out.close(); -311 } catch (IOException ex) { -312 LOGGER.trace("ignore", ex); -313 } -314 } -315 if (gzip.isFile()) { -316 FileUtils.deleteQuietly(gzip); -317 } -318 } -319 } -320 } +58 * @param settings a reference to the global settings object; this is +59 * necessary so that when the thread is started the dependencies have a +60 * correct reference to the global settings. +61 * @throws UpdateException thrown if temporary files could not be created +62 */ +63 public DownloadTask(NvdCveInfo nvdCveInfo, ExecutorService processor, CveDB cveDB, Settings settings) throws UpdateException { +64 this.nvdCveInfo = nvdCveInfo; +65 this.processorService = processor; +66 this.cveDB = cveDB; +67 this.settings = settings; +68 +69 final File file1; +70 final File file2; +71 +72 try { +73 file1 = File.createTempFile("cve" + nvdCveInfo.getId() + '_', ".xml", Settings.getTempDirectory()); +74 file2 = File.createTempFile("cve_1_2_" + nvdCveInfo.getId() + '_', ".xml", Settings.getTempDirectory()); +75 } catch (IOException ex) { +76 throw new UpdateException("Unable to create temporary files", ex); +77 } +78 this.first = file1; +79 this.second = file2; +80 +81 } +82 /** +83 * The CVE DB to use when processing the files. +84 */ +85 private final CveDB cveDB; +86 /** +87 * The processor service to pass the results of the download to. +88 */ +89 private final ExecutorService processorService; +90 /** +91 * The NVD CVE Meta Data. +92 */ +93 private NvdCveInfo nvdCveInfo; +94 /** +95 * A reference to the global settings object. +96 */ +97 private final Settings settings; +98 +99 /** +100 * Get the value of nvdCveInfo. +101 * +102 * @return the value of nvdCveInfo +103 */ +104 public NvdCveInfo getNvdCveInfo() { +105 return nvdCveInfo; +106 } +107 +108 /** +109 * Set the value of nvdCveInfo. +110 * +111 * @param nvdCveInfo new value of nvdCveInfo +112 */ +113 public void setNvdCveInfo(NvdCveInfo nvdCveInfo) { +114 this.nvdCveInfo = nvdCveInfo; +115 } +116 /** +117 * a file. +118 */ +119 private File first; +120 +121 /** +122 * Get the value of first. +123 * +124 * @return the value of first +125 */ +126 public File getFirst() { +127 return first; +128 } +129 +130 /** +131 * Set the value of first. +132 * +133 * @param first new value of first +134 */ +135 public void setFirst(File first) { +136 this.first = first; +137 } +138 /** +139 * a file. +140 */ +141 private File second; +142 +143 /** +144 * Get the value of second. +145 * +146 * @return the value of second +147 */ +148 public File getSecond() { +149 return second; +150 } +151 +152 /** +153 * Set the value of second. +154 * +155 * @param second new value of second +156 */ +157 public void setSecond(File second) { +158 this.second = second; +159 } +160 +161 @Override +162 public Future<ProcessTask> call() throws Exception { +163 try { +164 Settings.setInstance(settings); +165 final URL url1 = new URL(nvdCveInfo.getUrl()); +166 final URL url2 = new URL(nvdCveInfo.getOldSchemaVersionUrl()); +167 LOGGER.info("Download Started for NVD CVE - {}", nvdCveInfo.getId()); +168 final long startDownload = System.currentTimeMillis(); +169 try { +170 Downloader.fetchFile(url1, first); +171 Downloader.fetchFile(url2, second); +172 } catch (DownloadFailedException ex) { +173 LOGGER.warn("Download Failed for NVD CVE - {}\nSome CVEs may not be reported.", nvdCveInfo.getId()); +174 if (Settings.getString(Settings.KEYS.PROXY_SERVER) == null) { +175 LOGGER.info( +176 "If you are behind a proxy you may need to configure dependency-check to use the proxy."); +177 } +178 LOGGER.debug("", ex); +179 return null; +180 } +181 if (url1.toExternalForm().endsWith(".xml.gz") && !isXml(first)) { +182 extractGzip(first); +183 } +184 if (url2.toExternalForm().endsWith(".xml.gz") && !isXml(second)) { +185 extractGzip(second); +186 } +187 +188 LOGGER.info("Download Complete for NVD CVE - {} ({} ms)", nvdCveInfo.getId(), +189 System.currentTimeMillis() - startDownload); +190 if (this.processorService == null) { +191 return null; +192 } +193 final ProcessTask task = new ProcessTask(cveDB, this, settings); +194 return this.processorService.submit(task); +195 +196 } catch (Throwable ex) { +197 LOGGER.warn("An exception occurred downloading NVD CVE - {}\nSome CVEs may not be reported.", nvdCveInfo.getId()); +198 LOGGER.debug("Download Task Failed", ex); +199 } finally { +200 Settings.cleanup(false); +201 } +202 return null; +203 } +204 +205 /** +206 * Attempts to delete the files that were downloaded. +207 */ +208 public void cleanup() { +209 if (first != null && first.exists() && first.delete()) { +210 LOGGER.debug("Failed to delete first temporary file {}", second.toString()); +211 first.deleteOnExit(); +212 } +213 if (second != null && second.exists() && !second.delete()) { +214 LOGGER.debug("Failed to delete second temporary file {}", second.toString()); +215 second.deleteOnExit(); +216 } +217 } +218 +219 /** +220 * Checks the file header to see if it is an XML file. +221 * +222 * @param file the file to check +223 * @return true if the file is XML +224 */ +225 public static boolean isXml(File file) { +226 if (file == null || !file.isFile()) { +227 return false; +228 } +229 InputStream is = null; +230 try { +231 is = new FileInputStream(file); +232 +233 final byte[] buf = new byte[5]; +234 int read = 0; +235 try { +236 read = is.read(buf); +237 } catch (IOException ex) { +238 return false; +239 } +240 return read == 5 +241 && buf[0] == '<' +242 && (buf[1] == '?') +243 && (buf[2] == 'x' || buf[2] == 'X') +244 && (buf[3] == 'm' || buf[3] == 'M') +245 && (buf[4] == 'l' || buf[4] == 'L'); +246 } catch (FileNotFoundException ex) { +247 return false; +248 } finally { +249 if (is != null) { +250 try { +251 is.close(); +252 } catch (IOException ex) { +253 LOGGER.debug("Error closing stream", ex); +254 } +255 } +256 } +257 } +258 +259 /** +260 * Extracts the file contained in a gzip archive. The extracted file is +261 * placed in the exact same path as the file specified. +262 * +263 * @param file the archive file +264 * @throws FileNotFoundException thrown if the file does not exist +265 * @throws IOException thrown if there is an error extracting the file. +266 */ +267 private void extractGzip(File file) throws FileNotFoundException, IOException { +268 final String originalPath = file.getPath(); +269 final File gzip = new File(originalPath + ".gz"); +270 if (gzip.isFile() && !gzip.delete()) { +271 LOGGER.debug("Failed to delete initial temporary file when extracting 'gz' {}", gzip.toString()); +272 gzip.deleteOnExit(); +273 } +274 if (!file.renameTo(gzip)) { +275 throw new IOException("Unable to rename '" + file.getPath() + "'"); +276 } +277 final File newfile = new File(originalPath); +278 +279 final byte[] buffer = new byte[4096]; +280 +281 GZIPInputStream cin = null; +282 FileOutputStream out = null; +283 try { +284 cin = new GZIPInputStream(new FileInputStream(gzip)); +285 out = new FileOutputStream(newfile); +286 +287 int len; +288 while ((len = cin.read(buffer)) > 0) { +289 out.write(buffer, 0, len); +290 } +291 } finally { +292 if (cin != null) { +293 try { +294 cin.close(); +295 } catch (IOException ex) { +296 LOGGER.trace("ignore", ex); +297 } +298 } +299 if (out != null) { +300 try { +301 out.close(); +302 } catch (IOException ex) { +303 LOGGER.trace("ignore", ex); +304 } +305 } +306 if (gzip.isFile() && !FileUtils.deleteQuietly(gzip)) { +307 LOGGER.debug("Failed to delete temporary file when extracting 'gz' {}", gzip.toString()); +308 gzip.deleteOnExit(); +309 } +310 } +311 } +312 }
    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 5d67f7106..90134865e 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.2 Reference Package org.owasp.dependencycheck.data.update.nvd + Dependency-Check 1.4.3 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 ba128ad5c..ef04d5911 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.2 Reference Package org.owasp.dependencycheck.data.update.nvd + Dependency-Check 1.4.3 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 ab1f4a029..c77fe7898 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.2 Reference Package org.owasp.dependencycheck.data.update + Dependency-Check 1.4.3 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 efda66383..285a903d6 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.2 Reference Package org.owasp.dependencycheck.data.update + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.update diff --git a/xref/org/owasp/dependencycheck/dependency/Reference.html b/xref/org/owasp/dependencycheck/dependency/Reference.html index 2230c6e7a..3d956b3b4 100644 --- a/xref/org/owasp/dependencycheck/dependency/Reference.html +++ b/xref/org/owasp/dependencycheck/dependency/Reference.html @@ -26,144 +26,137 @@ 18 package org.owasp.dependencycheck.dependency; 19 20 import java.io.Serializable; -21 -22 /** -23 * An external reference for a vulnerability. This contains a name, URL, and a -24 * source. -25 * -26 * @author Jeremy Long -27 */ -28 public class Reference implements Serializable, Comparable<Reference> { -29 -30 /** -31 * the serial version uid. -32 */ -33 private static final long serialVersionUID = -3444464824563008021L; -34 /** -35 * The name of the reference. -36 */ -37 private String name; -38 -39 /** -40 * Get the value of name. -41 * -42 * @return the value of name -43 */ -44 public String getName() { -45 return name; -46 } -47 -48 /** -49 * Set the value of name. -50 * -51 * @param name new value of name -52 */ -53 public void setName(String name) { -54 this.name = name; -55 } -56 /** -57 * the url for the reference. -58 */ -59 private String url; -60 -61 /** -62 * Get the value of url. -63 * -64 * @return the value of url -65 */ -66 public String getUrl() { -67 return url; -68 } -69 -70 /** -71 * Set the value of url. -72 * -73 * @param url new value of url -74 */ -75 public void setUrl(String url) { -76 this.url = url; -77 } -78 /** -79 * the source of the reference. -80 */ -81 private String source; -82 -83 /** -84 * Get the value of source. -85 * -86 * @return the value of source -87 */ -88 public String getSource() { -89 return source; -90 } -91 -92 /** -93 * Set the value of source. -94 * -95 * @param source new value of source -96 */ -97 public void setSource(String source) { -98 this.source = source; -99 } -100 -101 @Override -102 public String toString() { -103 return "Reference: { name='" + this.name + "', url='" + this.url + "', source='" + this.source + "' }"; -104 } -105 -106 @Override -107 public boolean equals(Object obj) { -108 if (obj == null) { -109 return false; -110 } -111 if (getClass() != obj.getClass()) { -112 return false; -113 } -114 final Reference other = (Reference) obj; -115 if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) { -116 return false; -117 } -118 if ((this.url == null) ? (other.url != null) : !this.url.equals(other.url)) { -119 return false; -120 } -121 if ((this.source == null) ? (other.source != null) : !this.source.equals(other.source)) { -122 return false; -123 } -124 return true; -125 } -126 -127 @Override -128 public int hashCode() { -129 int hash = 5; -130 hash = 67 * hash + (this.name != null ? this.name.hashCode() : 0); -131 hash = 67 * hash + (this.url != null ? this.url.hashCode() : 0); -132 hash = 67 * hash + (this.source != null ? this.source.hashCode() : 0); -133 return hash; -134 } -135 -136 /** -137 * Implementation of the comparable interface. -138 * -139 * @param o the Reference being compared -140 * @return an integer indicating the ordering of the two objects -141 */ -142 @Override -143 public int compareTo(Reference o) { -144 if (source.equals(o.source)) { -145 if (name.equals(o.name)) { -146 if (url.equals(o.url)) { -147 return 0; //they are equal -148 } else { -149 return url.compareTo(o.url); -150 } -151 } else { -152 return name.compareTo(o.name); -153 } -154 } else { -155 return source.compareTo(o.source); -156 } -157 } -158 } +21 import org.apache.commons.lang3.builder.CompareToBuilder; +22 +23 /** +24 * An external reference for a vulnerability. This contains a name, URL, and a +25 * source. +26 * +27 * @author Jeremy Long +28 */ +29 public class Reference implements Serializable, Comparable<Reference> { +30 +31 /** +32 * the serial version uid. +33 */ +34 private static final long serialVersionUID = -3444464824563008021L; +35 /** +36 * The name of the reference. +37 */ +38 private String name; +39 +40 /** +41 * Get the value of name. +42 * +43 * @return the value of name +44 */ +45 public String getName() { +46 return name; +47 } +48 +49 /** +50 * Set the value of name. +51 * +52 * @param name new value of name +53 */ +54 public void setName(String name) { +55 this.name = name; +56 } +57 /** +58 * the url for the reference. +59 */ +60 private String url; +61 +62 /** +63 * Get the value of url. +64 * +65 * @return the value of url +66 */ +67 public String getUrl() { +68 return url; +69 } +70 +71 /** +72 * Set the value of url. +73 * +74 * @param url new value of url +75 */ +76 public void setUrl(String url) { +77 this.url = url; +78 } +79 /** +80 * the source of the reference. +81 */ +82 private String source; +83 +84 /** +85 * Get the value of source. +86 * +87 * @return the value of source +88 */ +89 public String getSource() { +90 return source; +91 } +92 +93 /** +94 * Set the value of source. +95 * +96 * @param source new value of source +97 */ +98 public void setSource(String source) { +99 this.source = source; +100 } +101 +102 @Override +103 public String toString() { +104 return "Reference: { name='" + this.name + "', url='" + this.url + "', source='" + this.source + "' }"; +105 } +106 +107 @Override +108 public boolean equals(Object obj) { +109 if (obj == null) { +110 return false; +111 } +112 if (getClass() != obj.getClass()) { +113 return false; +114 } +115 final Reference other = (Reference) obj; +116 if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) { +117 return false; +118 } +119 if ((this.url == null) ? (other.url != null) : !this.url.equals(other.url)) { +120 return false; +121 } +122 if ((this.source == null) ? (other.source != null) : !this.source.equals(other.source)) { +123 return false; +124 } +125 return true; +126 } +127 +128 @Override +129 public int hashCode() { +130 int hash = 5; +131 hash = 67 * hash + (this.name != null ? this.name.hashCode() : 0); +132 hash = 67 * hash + (this.url != null ? this.url.hashCode() : 0); +133 hash = 67 * hash + (this.source != null ? this.source.hashCode() : 0); +134 return hash; +135 } +136 +137 /** +138 * Implementation of the comparable interface. +139 * +140 * @param o the Reference being compared +141 * @return an integer indicating the ordering of the two objects +142 */ +143 @Override +144 public int compareTo(Reference o) { +145 return new CompareToBuilder() +146 .append(source, o.source) +147 .append(name, o.name) +148 .append(url, o.url) +149 .toComparison(); +150 } +151 }
    diff --git a/xref/org/owasp/dependencycheck/dependency/Vulnerability.html b/xref/org/owasp/dependencycheck/dependency/Vulnerability.html index fe0cd852f..64c9527b8 100644 --- a/xref/org/owasp/dependencycheck/dependency/Vulnerability.html +++ b/xref/org/owasp/dependencycheck/dependency/Vulnerability.html @@ -29,447 +29,453 @@ 21 import java.util.Set; 22 import java.util.SortedSet; 23 import java.util.TreeSet; -24 -25 /** -26 * Contains the information about a vulnerability. -27 * -28 * @author Jeremy Long -29 */ -30 public class Vulnerability implements Serializable, Comparable<Vulnerability> { -31 -32 /** -33 * The serial version uid. -34 */ -35 private static final long serialVersionUID = 307319490326651052L; -36 -37 /** -38 * The name of the vulnerability. -39 */ -40 private String name; -41 -42 /** -43 * Get the value of name. -44 * -45 * @return the value of name -46 */ -47 public String getName() { -48 return name; -49 } -50 -51 /** -52 * Set the value of name. -53 * -54 * @param name new value of name -55 */ -56 public void setName(String name) { -57 this.name = name; -58 } -59 /** -60 * the description of the vulnerability. -61 */ -62 private String description; -63 -64 /** -65 * Get the value of description. -66 * -67 * @return the value of description -68 */ -69 public String getDescription() { -70 return description; -71 } -72 -73 /** -74 * Set the value of description. -75 * -76 * @param description new value of description -77 */ -78 public void setDescription(String description) { -79 this.description = description; -80 } -81 /** -82 * References for this vulnerability. -83 */ -84 private SortedSet<Reference> references = new TreeSet<Reference>(); -85 -86 /** -87 * Get the value of references. -88 * -89 * @return the value of references -90 */ -91 public Set<Reference> getReferences() { -92 return references; -93 } -94 -95 /** -96 * Set the value of references. -97 * -98 * @param references new value of references -99 */ -100 public void setReferences(SortedSet<Reference> references) { -101 this.references = references; -102 } -103 -104 /** -105 * Adds a reference to the references collection. -106 * -107 * @param ref a reference for the vulnerability -108 */ -109 public void addReference(Reference ref) { -110 this.references.add(ref); -111 } -112 -113 /** -114 * Adds a reference. -115 * -116 * @param referenceSource the source of the reference -117 * @param referenceName the referenceName of the reference -118 * @param referenceUrl the url of the reference -119 */ -120 public void addReference(String referenceSource, String referenceName, String referenceUrl) { -121 final Reference ref = new Reference(); -122 ref.setSource(referenceSource); -123 ref.setName(referenceName); -124 ref.setUrl(referenceUrl); -125 this.references.add(ref); -126 } -127 /** -128 * A set of vulnerable software. -129 */ -130 private SortedSet<VulnerableSoftware> vulnerableSoftware = new TreeSet<VulnerableSoftware>(); -131 -132 /** -133 * Get the value of vulnerableSoftware. -134 * -135 * @return the value of vulnerableSoftware -136 */ -137 public Set<VulnerableSoftware> getVulnerableSoftware() { -138 return vulnerableSoftware; -139 } -140 -141 /** -142 * Set the value of vulnerableSoftware. -143 * -144 * @param vulnerableSoftware new value of vulnerableSoftware -145 */ -146 public void setVulnerableSoftware(SortedSet<VulnerableSoftware> vulnerableSoftware) { -147 this.vulnerableSoftware = vulnerableSoftware; -148 } -149 -150 /** -151 * Adds an entry for vulnerable software. -152 * -153 * @param cpe string representation of a CPE entry -154 * @return if the add succeeded -155 */ -156 public boolean addVulnerableSoftware(String cpe) { -157 return addVulnerableSoftware(cpe, null); -158 } -159 -160 /** -161 * Adds an entry for vulnerable software. -162 * -163 * @param cpe string representation of a cpe -164 * @param previousVersion the previous version (previousVersion - cpe would be considered vulnerable) -165 * @return if the add succeeded -166 */ -167 public boolean addVulnerableSoftware(String cpe, String previousVersion) { -168 final VulnerableSoftware vs = new VulnerableSoftware(); -169 vs.setCpe(cpe); -170 if (previousVersion != null) { -171 vs.setPreviousVersion(previousVersion); -172 } -173 return updateVulnerableSoftware(vs); -174 } -175 -176 /** -177 * Adds or updates a vulnerable software entry. -178 * -179 * @param vulnSoftware the vulnerable software -180 * @return if the update succeeded -181 */ -182 public boolean updateVulnerableSoftware(VulnerableSoftware vulnSoftware) { -183 if (vulnerableSoftware.contains(vulnSoftware)) { -184 vulnerableSoftware.remove(vulnSoftware); -185 } -186 return vulnerableSoftware.add(vulnSoftware); -187 } -188 /** -189 * The CWE for the vulnerability. -190 */ -191 private String cwe; -192 -193 /** -194 * Get the value of cwe. -195 * -196 * @return the value of cwe -197 */ -198 public String getCwe() { -199 return cwe; -200 } -201 -202 /** -203 * Set the value of cwe. -204 * -205 * @param cwe new value of cwe -206 */ -207 public void setCwe(String cwe) { -208 this.cwe = cwe; -209 } -210 /** -211 * CVSS Score. -212 */ -213 private float cvssScore; -214 -215 /** -216 * Get the value of cvssScore. -217 * -218 * @return the value of cvssScore -219 */ -220 public float getCvssScore() { -221 return cvssScore; -222 } -223 -224 /** -225 * Set the value of cvssScore. -226 * -227 * @param cvssScore new value of cvssScore -228 */ -229 public void setCvssScore(float cvssScore) { -230 this.cvssScore = cvssScore; -231 } -232 /** -233 * CVSS Access Vector. -234 */ -235 private String cvssAccessVector; -236 -237 /** -238 * Get the value of cvssAccessVector. -239 * -240 * @return the value of cvssAccessVector -241 */ -242 public String getCvssAccessVector() { -243 return cvssAccessVector; -244 } -245 -246 /** -247 * Set the value of cvssAccessVector. -248 * -249 * @param cvssAccessVector new value of cvssAccessVector -250 */ -251 public void setCvssAccessVector(String cvssAccessVector) { -252 this.cvssAccessVector = cvssAccessVector; -253 } -254 /** -255 * CVSS Access Complexity. -256 */ -257 private String cvssAccessComplexity; -258 -259 /** -260 * Get the value of cvssAccessComplexity. -261 * -262 * @return the value of cvssAccessComplexity -263 */ -264 public String getCvssAccessComplexity() { -265 return cvssAccessComplexity; -266 } -267 -268 /** -269 * Set the value of cvssAccessComplexity. -270 * -271 * @param cvssAccessComplexity new value of cvssAccessComplexity -272 */ -273 public void setCvssAccessComplexity(String cvssAccessComplexity) { -274 this.cvssAccessComplexity = cvssAccessComplexity; -275 } -276 /** -277 * CVSS Authentication. -278 */ -279 private String cvssAuthentication; -280 -281 /** -282 * Get the value of cvssAuthentication. -283 * -284 * @return the value of cvssAuthentication -285 */ -286 public String getCvssAuthentication() { -287 return cvssAuthentication; -288 } -289 -290 /** -291 * Set the value of cvssAuthentication. -292 * -293 * @param cvssAuthentication new value of cvssAuthentication -294 */ -295 public void setCvssAuthentication(String cvssAuthentication) { -296 this.cvssAuthentication = cvssAuthentication; -297 } -298 /** -299 * CVSS Confidentiality Impact. -300 */ -301 private String cvssConfidentialityImpact; -302 -303 /** -304 * Get the value of cvssConfidentialityImpact. -305 * -306 * @return the value of cvssConfidentialityImpact -307 */ -308 public String getCvssConfidentialityImpact() { -309 return cvssConfidentialityImpact; -310 } -311 -312 /** -313 * Set the value of cvssConfidentialityImpact. -314 * -315 * @param cvssConfidentialityImpact new value of cvssConfidentialityImpact -316 */ -317 public void setCvssConfidentialityImpact(String cvssConfidentialityImpact) { -318 this.cvssConfidentialityImpact = cvssConfidentialityImpact; -319 } -320 /** -321 * CVSS Integrity Impact. -322 */ -323 private String cvssIntegrityImpact; -324 -325 /** -326 * Get the value of cvssIntegrityImpact. -327 * -328 * @return the value of cvssIntegrityImpact -329 */ -330 public String getCvssIntegrityImpact() { -331 return cvssIntegrityImpact; -332 } -333 -334 /** -335 * Set the value of cvssIntegrityImpact. -336 * -337 * @param cvssIntegrityImpact new value of cvssIntegrityImpact -338 */ -339 public void setCvssIntegrityImpact(String cvssIntegrityImpact) { -340 this.cvssIntegrityImpact = cvssIntegrityImpact; -341 } -342 /** -343 * CVSS Availability Impact. -344 */ -345 private String cvssAvailabilityImpact; -346 -347 /** -348 * Get the value of cvssAvailabilityImpact. -349 * -350 * @return the value of cvssAvailabilityImpact -351 */ -352 public String getCvssAvailabilityImpact() { -353 return cvssAvailabilityImpact; -354 } -355 -356 /** -357 * Set the value of cvssAvailabilityImpact. -358 * -359 * @param cvssAvailabilityImpact new value of cvssAvailabilityImpact -360 */ -361 public void setCvssAvailabilityImpact(String cvssAvailabilityImpact) { -362 this.cvssAvailabilityImpact = cvssAvailabilityImpact; -363 } -364 -365 @Override -366 public boolean equals(Object obj) { -367 if (obj == null) { -368 return false; -369 } -370 if (getClass() != obj.getClass()) { -371 return false; -372 } -373 final Vulnerability other = (Vulnerability) obj; -374 if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) { -375 return false; -376 } -377 return true; -378 } -379 -380 @Override -381 public int hashCode() { -382 int hash = 5; -383 hash = 41 * hash + (this.name != null ? this.name.hashCode() : 0); -384 return hash; -385 } -386 -387 @Override -388 public String toString() { -389 final StringBuilder sb = new StringBuilder("Vulnerability "); -390 sb.append(this.name); -391 sb.append("\nReferences:\n"); -392 for (Reference reference : this.references) { -393 sb.append("=> "); -394 sb.append(reference); -395 sb.append("\n"); -396 } -397 sb.append("\nSoftware:\n"); -398 for (VulnerableSoftware software : this.vulnerableSoftware) { -399 sb.append("=> "); -400 sb.append(software); -401 sb.append("\n"); -402 } -403 return sb.toString(); -404 } -405 /** -406 * Compares two vulnerabilities. -407 * -408 * @param v a vulnerability to be compared -409 * @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than -410 * the specified vulnerability -411 */ -412 @Override -413 public int compareTo(Vulnerability v) { -414 return v.getName().compareTo(this.getName()); -415 } -416 -417 /** -418 * The CPE id that caused this vulnerability to be flagged. -419 */ -420 private String matchedCPE; -421 /** -422 * Whether or not all previous versions were affected. -423 */ -424 private String matchedAllPreviousCPE; -425 -426 /** -427 * Sets the CPE that caused this vulnerability to be flagged. -428 * -429 * @param cpeId a CPE identifier -430 * @param previous a flag indicating whether or not all previous versions were affected (any non-null value is -431 * considered true) -432 */ -433 public void setMatchedCPE(String cpeId, String previous) { -434 matchedCPE = cpeId; -435 matchedAllPreviousCPE = previous; -436 } -437 -438 /** -439 * Get the value of matchedCPE. -440 * -441 * @return the value of matchedCPE -442 */ -443 public String getMatchedCPE() { -444 return matchedCPE; -445 } -446 -447 /** -448 * Get the value of matchedAllPreviousCPE. -449 * -450 * @return the value of matchedAllPreviousCPE -451 */ -452 public String getMatchedAllPreviousCPE() { -453 return matchedAllPreviousCPE; -454 } -455 -456 /** -457 * Determines whether or not matchedAllPreviousCPE has been set. -458 * -459 * @return true if matchedAllPreviousCPE is not null; otherwise false -460 */ -461 public boolean hasMatchedAllPreviousCPE() { -462 return matchedAllPreviousCPE != null; -463 } -464 } +24 import org.apache.commons.lang3.builder.CompareToBuilder; +25 +26 /** +27 * Contains the information about a vulnerability. +28 * +29 * @author Jeremy Long +30 */ +31 public class Vulnerability implements Serializable, Comparable<Vulnerability> { +32 +33 /** +34 * The serial version uid. +35 */ +36 private static final long serialVersionUID = 307319490326651052L; +37 +38 /** +39 * The name of the vulnerability. +40 */ +41 private String name; +42 +43 /** +44 * Get the value of name. +45 * +46 * @return the value of name +47 */ +48 public String getName() { +49 return name; +50 } +51 +52 /** +53 * Set the value of name. +54 * +55 * @param name new value of name +56 */ +57 public void setName(String name) { +58 this.name = name; +59 } +60 /** +61 * the description of the vulnerability. +62 */ +63 private String description; +64 +65 /** +66 * Get the value of description. +67 * +68 * @return the value of description +69 */ +70 public String getDescription() { +71 return description; +72 } +73 +74 /** +75 * Set the value of description. +76 * +77 * @param description new value of description +78 */ +79 public void setDescription(String description) { +80 this.description = description; +81 } +82 /** +83 * References for this vulnerability. +84 */ +85 private SortedSet<Reference> references = new TreeSet<Reference>(); +86 +87 /** +88 * Get the value of references. +89 * +90 * @return the value of references +91 */ +92 public Set<Reference> getReferences() { +93 return references; +94 } +95 +96 /** +97 * Set the value of references. +98 * +99 * @param references new value of references +100 */ +101 public void setReferences(SortedSet<Reference> references) { +102 this.references = references; +103 } +104 +105 /** +106 * Adds a reference to the references collection. +107 * +108 * @param ref a reference for the vulnerability +109 */ +110 public void addReference(Reference ref) { +111 this.references.add(ref); +112 } +113 +114 /** +115 * Adds a reference. +116 * +117 * @param referenceSource the source of the reference +118 * @param referenceName the referenceName of the reference +119 * @param referenceUrl the url of the reference +120 */ +121 public void addReference(String referenceSource, String referenceName, String referenceUrl) { +122 final Reference ref = new Reference(); +123 ref.setSource(referenceSource); +124 ref.setName(referenceName); +125 ref.setUrl(referenceUrl); +126 this.references.add(ref); +127 } +128 /** +129 * A set of vulnerable software. +130 */ +131 private SortedSet<VulnerableSoftware> vulnerableSoftware = new TreeSet<VulnerableSoftware>(); +132 +133 /** +134 * Get the value of vulnerableSoftware. +135 * +136 * @return the value of vulnerableSoftware +137 */ +138 public Set<VulnerableSoftware> getVulnerableSoftware() { +139 return vulnerableSoftware; +140 } +141 +142 /** +143 * Set the value of vulnerableSoftware. +144 * +145 * @param vulnerableSoftware new value of vulnerableSoftware +146 */ +147 public void setVulnerableSoftware(SortedSet<VulnerableSoftware> vulnerableSoftware) { +148 this.vulnerableSoftware = vulnerableSoftware; +149 } +150 +151 /** +152 * Adds an entry for vulnerable software. +153 * +154 * @param cpe string representation of a CPE entry +155 * @return if the add succeeded +156 */ +157 public boolean addVulnerableSoftware(String cpe) { +158 return addVulnerableSoftware(cpe, null); +159 } +160 +161 /** +162 * Adds an entry for vulnerable software. +163 * +164 * @param cpe string representation of a cpe +165 * @param previousVersion the previous version (previousVersion - cpe would +166 * be considered vulnerable) +167 * @return if the add succeeded +168 */ +169 public boolean addVulnerableSoftware(String cpe, String previousVersion) { +170 final VulnerableSoftware vs = new VulnerableSoftware(); +171 vs.setCpe(cpe); +172 if (previousVersion != null) { +173 vs.setPreviousVersion(previousVersion); +174 } +175 return updateVulnerableSoftware(vs); +176 } +177 +178 /** +179 * Adds or updates a vulnerable software entry. +180 * +181 * @param vulnSoftware the vulnerable software +182 * @return if the update succeeded +183 */ +184 public boolean updateVulnerableSoftware(VulnerableSoftware vulnSoftware) { +185 if (vulnerableSoftware.contains(vulnSoftware)) { +186 vulnerableSoftware.remove(vulnSoftware); +187 } +188 return vulnerableSoftware.add(vulnSoftware); +189 } +190 /** +191 * The CWE for the vulnerability. +192 */ +193 private String cwe; +194 +195 /** +196 * Get the value of cwe. +197 * +198 * @return the value of cwe +199 */ +200 public String getCwe() { +201 return cwe; +202 } +203 +204 /** +205 * Set the value of cwe. +206 * +207 * @param cwe new value of cwe +208 */ +209 public void setCwe(String cwe) { +210 this.cwe = cwe; +211 } +212 /** +213 * CVSS Score. +214 */ +215 private float cvssScore; +216 +217 /** +218 * Get the value of cvssScore. +219 * +220 * @return the value of cvssScore +221 */ +222 public float getCvssScore() { +223 return cvssScore; +224 } +225 +226 /** +227 * Set the value of cvssScore. +228 * +229 * @param cvssScore new value of cvssScore +230 */ +231 public void setCvssScore(float cvssScore) { +232 this.cvssScore = cvssScore; +233 } +234 /** +235 * CVSS Access Vector. +236 */ +237 private String cvssAccessVector; +238 +239 /** +240 * Get the value of cvssAccessVector. +241 * +242 * @return the value of cvssAccessVector +243 */ +244 public String getCvssAccessVector() { +245 return cvssAccessVector; +246 } +247 +248 /** +249 * Set the value of cvssAccessVector. +250 * +251 * @param cvssAccessVector new value of cvssAccessVector +252 */ +253 public void setCvssAccessVector(String cvssAccessVector) { +254 this.cvssAccessVector = cvssAccessVector; +255 } +256 /** +257 * CVSS Access Complexity. +258 */ +259 private String cvssAccessComplexity; +260 +261 /** +262 * Get the value of cvssAccessComplexity. +263 * +264 * @return the value of cvssAccessComplexity +265 */ +266 public String getCvssAccessComplexity() { +267 return cvssAccessComplexity; +268 } +269 +270 /** +271 * Set the value of cvssAccessComplexity. +272 * +273 * @param cvssAccessComplexity new value of cvssAccessComplexity +274 */ +275 public void setCvssAccessComplexity(String cvssAccessComplexity) { +276 this.cvssAccessComplexity = cvssAccessComplexity; +277 } +278 /** +279 * CVSS Authentication. +280 */ +281 private String cvssAuthentication; +282 +283 /** +284 * Get the value of cvssAuthentication. +285 * +286 * @return the value of cvssAuthentication +287 */ +288 public String getCvssAuthentication() { +289 return cvssAuthentication; +290 } +291 +292 /** +293 * Set the value of cvssAuthentication. +294 * +295 * @param cvssAuthentication new value of cvssAuthentication +296 */ +297 public void setCvssAuthentication(String cvssAuthentication) { +298 this.cvssAuthentication = cvssAuthentication; +299 } +300 /** +301 * CVSS Confidentiality Impact. +302 */ +303 private String cvssConfidentialityImpact; +304 +305 /** +306 * Get the value of cvssConfidentialityImpact. +307 * +308 * @return the value of cvssConfidentialityImpact +309 */ +310 public String getCvssConfidentialityImpact() { +311 return cvssConfidentialityImpact; +312 } +313 +314 /** +315 * Set the value of cvssConfidentialityImpact. +316 * +317 * @param cvssConfidentialityImpact new value of cvssConfidentialityImpact +318 */ +319 public void setCvssConfidentialityImpact(String cvssConfidentialityImpact) { +320 this.cvssConfidentialityImpact = cvssConfidentialityImpact; +321 } +322 /** +323 * CVSS Integrity Impact. +324 */ +325 private String cvssIntegrityImpact; +326 +327 /** +328 * Get the value of cvssIntegrityImpact. +329 * +330 * @return the value of cvssIntegrityImpact +331 */ +332 public String getCvssIntegrityImpact() { +333 return cvssIntegrityImpact; +334 } +335 +336 /** +337 * Set the value of cvssIntegrityImpact. +338 * +339 * @param cvssIntegrityImpact new value of cvssIntegrityImpact +340 */ +341 public void setCvssIntegrityImpact(String cvssIntegrityImpact) { +342 this.cvssIntegrityImpact = cvssIntegrityImpact; +343 } +344 /** +345 * CVSS Availability Impact. +346 */ +347 private String cvssAvailabilityImpact; +348 +349 /** +350 * Get the value of cvssAvailabilityImpact. +351 * +352 * @return the value of cvssAvailabilityImpact +353 */ +354 public String getCvssAvailabilityImpact() { +355 return cvssAvailabilityImpact; +356 } +357 +358 /** +359 * Set the value of cvssAvailabilityImpact. +360 * +361 * @param cvssAvailabilityImpact new value of cvssAvailabilityImpact +362 */ +363 public void setCvssAvailabilityImpact(String cvssAvailabilityImpact) { +364 this.cvssAvailabilityImpact = cvssAvailabilityImpact; +365 } +366 +367 @Override +368 public boolean equals(Object obj) { +369 if (obj == null) { +370 return false; +371 } +372 if (getClass() != obj.getClass()) { +373 return false; +374 } +375 final Vulnerability other = (Vulnerability) obj; +376 if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) { +377 return false; +378 } +379 return true; +380 } +381 +382 @Override +383 public int hashCode() { +384 int hash = 5; +385 hash = 41 * hash + (this.name != null ? this.name.hashCode() : 0); +386 return hash; +387 } +388 +389 @Override +390 public String toString() { +391 final StringBuilder sb = new StringBuilder("Vulnerability "); +392 sb.append(this.name); +393 sb.append("\nReferences:\n"); +394 for (Reference reference : this.references) { +395 sb.append("=> "); +396 sb.append(reference); +397 sb.append("\n"); +398 } +399 sb.append("\nSoftware:\n"); +400 for (VulnerableSoftware software : this.vulnerableSoftware) { +401 sb.append("=> "); +402 sb.append(software); +403 sb.append("\n"); +404 } +405 return sb.toString(); +406 } +407 +408 /** +409 * Compares two vulnerabilities. +410 * +411 * @param v a vulnerability to be compared +412 * @return a negative integer, zero, or a positive integer as this object is +413 * less than, equal to, or greater than the specified vulnerability +414 */ +415 @Override +416 public int compareTo(Vulnerability v) { +417 return new CompareToBuilder() +418 .append(this.name, v.name) +419 .toComparison(); +420 //return v.getName().compareTo(this.getName()); +421 } +422 +423 /** +424 * The CPE id that caused this vulnerability to be flagged. +425 */ +426 private String matchedCPE; +427 /** +428 * Whether or not all previous versions were affected. +429 */ +430 private String matchedAllPreviousCPE; +431 +432 /** +433 * Sets the CPE that caused this vulnerability to be flagged. +434 * +435 * @param cpeId a CPE identifier +436 * @param previous a flag indicating whether or not all previous versions +437 * were affected (any non-null value is considered true) +438 */ +439 public void setMatchedCPE(String cpeId, String previous) { +440 matchedCPE = cpeId; +441 matchedAllPreviousCPE = previous; +442 } +443 +444 /** +445 * Get the value of matchedCPE. +446 * +447 * @return the value of matchedCPE +448 */ +449 public String getMatchedCPE() { +450 return matchedCPE; +451 } +452 +453 /** +454 * Get the value of matchedAllPreviousCPE. +455 * +456 * @return the value of matchedAllPreviousCPE +457 */ +458 public String getMatchedAllPreviousCPE() { +459 return matchedAllPreviousCPE; +460 } +461 +462 /** +463 * Determines whether or not matchedAllPreviousCPE has been set. +464 * +465 * @return true if matchedAllPreviousCPE is not null; otherwise false +466 */ +467 public boolean hasMatchedAllPreviousCPE() { +468 return matchedAllPreviousCPE != null; +469 } +470 }
    diff --git a/xref/org/owasp/dependencycheck/dependency/package-frame.html b/xref/org/owasp/dependencycheck/dependency/package-frame.html index 59d14bf44..8e5806dd8 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.2 Reference Package org.owasp.dependencycheck.dependency + Dependency-Check 1.4.3 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 76c196fce..7a87e079c 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.2 Reference Package org.owasp.dependencycheck.dependency + Dependency-Check 1.4.3 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 cdb8e053d..05272f763 100644 --- a/xref/org/owasp/dependencycheck/exception/ExceptionCollection.html +++ b/xref/org/owasp/dependencycheck/exception/ExceptionCollection.html @@ -98,128 +98,141 @@ 90 this.exceptions.add(exceptions); 91 this.fatal = fatal; 92 } -93 /** -94 * Instantiates a new exception collection. -95 * -96 * @param msg the exception message -97 * @param exception a list of exceptions -98 */ -99 public ExceptionCollection(String msg, Throwable exception) { -100 super(msg); -101 this.exceptions = new ArrayList<Throwable>(); -102 this.exceptions.add(exception); -103 this.fatal = false; -104 } -105 -106 /** -107 * Instantiates a new exception collection. -108 */ -109 public ExceptionCollection() { -110 super(); -111 this.exceptions = new ArrayList<Throwable>(); -112 } -113 /** -114 * The serial version uid. -115 */ -116 private static final long serialVersionUID = 1L; -117 -118 /** -119 * A collection of exceptions. -120 */ -121 private List<Throwable> exceptions; -122 -123 /** -124 * Get the value of exceptions. -125 * -126 * @return the value of exceptions -127 */ -128 public List<Throwable> getExceptions() { -129 return exceptions; -130 } -131 -132 /** -133 * Adds an exception to the collection. -134 * -135 * @param ex the exception to add -136 */ -137 public void addException(Throwable ex) { -138 this.exceptions.add(ex); -139 } -140 -141 /** -142 * Adds an exception to the collection. -143 * -144 * @param ex the exception to add -145 * @param fatal flag indicating if this is a fatal error -146 */ -147 public void addException(Throwable ex, boolean fatal) { -148 addException(ex); -149 this.fatal = fatal; -150 } -151 -152 /** -153 * Flag indicating if a fatal exception occurred that would prevent the -154 * attempt at completing the analysis even if exceptions occurred. -155 */ -156 private boolean fatal = false; -157 -158 /** -159 * Get the value of fatal. -160 * -161 * @return the value of fatal -162 */ -163 public boolean isFatal() { -164 return fatal; -165 } -166 -167 /** -168 * Set the value of fatal. -169 * -170 * @param fatal new value of fatal -171 */ -172 public void setFatal(boolean fatal) { -173 this.fatal = fatal; -174 } -175 -176 /** -177 * Prints the stack trace. -178 * -179 * @param s the writer to print to -180 */ -181 @Override -182 public void printStackTrace(PrintWriter s) { -183 s.println("Multiple Exceptions Occured"); -184 super.printStackTrace(s); -185 for (Throwable t : this.exceptions) { -186 s.println("Next Exception:"); -187 t.printStackTrace(s); -188 } -189 } -190 -191 /** -192 * Prints the stack trace. -193 * -194 * @param s the stream to write the stack trace to -195 */ -196 @Override -197 public void printStackTrace(PrintStream s) { -198 s.println("Multiple Exceptions Occured"); -199 super.printStackTrace(s); -200 for (Throwable t : this.exceptions) { -201 s.println("Next Exception:"); -202 t.printStackTrace(s); -203 } -204 } -205 -206 /** -207 * Prints the stack trace to standard error. -208 */ -209 @Override -210 public void printStackTrace() { -211 this.printStackTrace(System.err); -212 } -213 -214 } +93 +94 /** +95 * Instantiates a new exception collection. +96 * +97 * @param msg the exception message +98 * @param exception a list of exceptions +99 */ +100 public ExceptionCollection(String msg, Throwable exception) { +101 super(msg); +102 this.exceptions = new ArrayList<Throwable>(); +103 this.exceptions.add(exception); +104 this.fatal = false; +105 } +106 +107 /** +108 * Instantiates a new exception collection. +109 */ +110 public ExceptionCollection() { +111 super(); +112 this.exceptions = new ArrayList<Throwable>(); +113 } +114 /** +115 * The serial version uid. +116 */ +117 private static final long serialVersionUID = 1L; +118 +119 /** +120 * A collection of exceptions. +121 */ +122 private List<Throwable> exceptions; +123 +124 /** +125 * Get the value of exceptions. +126 * +127 * @return the value of exceptions +128 */ +129 public List<Throwable> getExceptions() { +130 return exceptions; +131 } +132 +133 /** +134 * Adds an exception to the collection. +135 * +136 * @param ex the exception to add +137 */ +138 public void addException(Throwable ex) { +139 this.exceptions.add(ex); +140 } +141 +142 /** +143 * Adds an exception to the collection. +144 * +145 * @param ex the exception to add +146 * @param fatal flag indicating if this is a fatal error +147 */ +148 public void addException(Throwable ex, boolean fatal) { +149 addException(ex); +150 this.fatal = fatal; +151 } +152 +153 /** +154 * Flag indicating if a fatal exception occurred that would prevent the +155 * attempt at completing the analysis even if exceptions occurred. +156 */ +157 private boolean fatal = false; +158 +159 /** +160 * Get the value of fatal. +161 * +162 * @return the value of fatal +163 */ +164 public boolean isFatal() { +165 return fatal; +166 } +167 +168 /** +169 * Set the value of fatal. +170 * +171 * @param fatal new value of fatal +172 */ +173 public void setFatal(boolean fatal) { +174 this.fatal = fatal; +175 } +176 +177 /** +178 * Prints the stack trace. +179 * +180 * @param s the writer to print to +181 */ +182 @Override +183 public void printStackTrace(PrintWriter s) { +184 s.println("Multiple Exceptions Occured"); +185 super.printStackTrace(s); +186 for (Throwable t : this.exceptions) { +187 s.println("Next Exception:"); +188 t.printStackTrace(s); +189 } +190 } +191 +192 /** +193 * Prints the stack trace. +194 * +195 * @param s the stream to write the stack trace to +196 */ +197 @Override +198 public void printStackTrace(PrintStream s) { +199 s.println("Multiple Exceptions Occurred"); +200 super.printStackTrace(s); +201 for (Throwable t : this.exceptions) { +202 s.println("Next Exception:"); +203 t.printStackTrace(s); +204 } +205 } +206 +207 /** +208 * Returns the error message, including the message from all contained +209 * exceptions. +210 * +211 * @return the error message +212 */ +213 @Override +214 public String getMessage() { +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:"); +219 } else { +220 sb.append(msg); +221 } +222 for (Throwable t : this.exceptions) { +223 sb.append("\n\t").append(t.getMessage()); +224 } +225 return sb.toString(); +226 } +227 }
    diff --git a/xref/org/owasp/dependencycheck/exception/package-frame.html b/xref/org/owasp/dependencycheck/exception/package-frame.html index 350806464..d87498521 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.2 Reference Package org.owasp.dependencycheck.exception + Dependency-Check 1.4.3 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 e62f31535..536cc0052 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.2 Reference Package org.owasp.dependencycheck.exception + Dependency-Check 1.4.3 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 5291d3b9c..6939c508a 100644 --- a/xref/org/owasp/dependencycheck/maven/AggregateMojo.html +++ b/xref/org/owasp/dependencycheck/maven/AggregateMojo.html @@ -27,366 +27,273 @@ 19 20 import java.io.File; 21 import java.io.IOException; -22 import java.util.ArrayList; -23 import java.util.Collections; -24 import java.util.HashSet; -25 import java.util.List; -26 import java.util.Locale; -27 import java.util.Set; -28 import org.apache.maven.plugin.MojoExecutionException; -29 import org.apache.maven.plugin.MojoFailureException; -30 import org.apache.maven.plugins.annotations.LifecyclePhase; -31 import org.apache.maven.plugins.annotations.Mojo; -32 import org.apache.maven.plugins.annotations.Parameter; -33 import org.apache.maven.plugins.annotations.ResolutionScope; -34 import org.apache.maven.project.MavenProject; -35 import org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer; -36 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; -37 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; -38 import org.owasp.dependencycheck.dependency.Dependency; -39 import org.owasp.dependencycheck.exception.ExceptionCollection; -40 import org.owasp.dependencycheck.exception.ReportException; -41 import org.owasp.dependencycheck.utils.Settings; -42 -43 /** -44 * Maven Plugin that checks project dependencies and the dependencies of all -45 * child modules to see if they have any known published vulnerabilities. -46 * -47 * @author Jeremy Long -48 */ -49 @Mojo( -50 name = "aggregate", -51 defaultPhase = LifecyclePhase.VERIFY, -52 /*aggregator = true,*/ -53 threadSafe = false, -54 requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, -55 requiresOnline = true -56 ) -57 public class AggregateMojo extends BaseDependencyCheckMojo { -58 -59 /** -60 * The key to store aggregate exception in the root Maven execution context. -61 */ -62 private static final String AGGREGATE_EXCEPTIONS = "AggregateExceptions"; -63 -64 /** -65 * Executes the aggregate dependency-check goal. This runs dependency-check -66 * and generates the subsequent reports. -67 * -68 * @throws MojoExecutionException thrown if there is ane exception running -69 * the mojo -70 * @throws MojoFailureException thrown if dependency-check is configured to -71 * fail the build -72 */ -73 @Override -74 public void runCheck() throws MojoExecutionException, MojoFailureException { -75 final MavenEngine engine = generateDataFile(); -76 if (engine == null) { -77 return; -78 } -79 -80 if (getProject() == getLastProject()) { -81 //ensure that the .ser file was created for each. -82 for (MavenProject current : getReactorProjects()) { -83 final File dataFile = getDataFile(current); -84 if (dataFile == null && !skipProject(current)) { //dc was never run on this project. write the ser to the target. -85 getLog().error(String.format("Module '%s' did not execute dependency-check; an attempt will be made to perform " -86 + "the check but dependencies may be missed resulting in false negatives.", current.getName())); -87 generateDataFile(engine, current); -88 } -89 } -90 for (MavenProject current : getReactorProjects()) { -91 List<Dependency> dependencies = readDataFile(current); -92 if (dependencies == null) { -93 dependencies = new ArrayList<Dependency>(); -94 } -95 final Set<MavenProject> childProjects = getDescendants(current); -96 for (MavenProject reportOn : childProjects) { -97 final List<Dependency> childDeps = readDataFile(reportOn); -98 if (childDeps != null && !childDeps.isEmpty()) { -99 if (getLog().isDebugEnabled()) { -100 getLog().debug(String.format("Adding %d dependencies from %s", childDeps.size(), reportOn.getName())); -101 } -102 dependencies.addAll(childDeps); -103 } else if (getLog().isDebugEnabled()) { -104 getLog().debug(String.format("No dependencies read for %s", reportOn.getName())); -105 } -106 } -107 engine.getDependencies().clear(); -108 engine.getDependencies().addAll(dependencies); -109 final DependencyBundlingAnalyzer bundler = new DependencyBundlingAnalyzer(); -110 try { -111 if (getLog().isDebugEnabled()) { -112 getLog().debug(String.format("Dependency count pre-bundler: %s", engine.getDependencies().size())); -113 } -114 bundler.analyze(null, engine); -115 if (getLog().isDebugEnabled()) { -116 getLog().debug(String.format("Dependency count post-bundler: %s", engine.getDependencies().size())); -117 } -118 } catch (AnalysisException ex) { -119 getLog().warn("An error occurred grouping the dependencies; duplicate entries may exist in the report", ex); -120 getLog().debug("Bundling Exception", ex); -121 } -122 -123 File outputDir = getCorrectOutputDirectory(current); -124 if (outputDir == null) { -125 //in some regards we shouldn't be writting this, but we are anyway. -126 //we shouldn't write this because nothing is configured to generate this report. -127 outputDir = new File(current.getBuild().getDirectory()); -128 } -129 try { -130 writeReports(engine, current, outputDir); -131 } catch (ReportException ex) { -132 ExceptionCollection exCol = (ExceptionCollection) engine.getExecutionRoot().getContextValue(AGGREGATE_EXCEPTIONS); -133 if (exCol == null) { -134 exCol = new ExceptionCollection("Error writing aggregate report", ex); -135 } else { -136 exCol.addException(ex); -137 } -138 if (this.isFailOnError()) { -139 throw new MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol); -140 } else { -141 getLog().debug("One or more exceptions occured during dependency-check analysis", exCol); -142 } -143 } -144 } -145 } -146 engine.cleanup(); -147 Settings.cleanup(); -148 } -149 -150 /** -151 * Gets the last project in the reactor - taking into account skipped -152 * projects. -153 * -154 * @return the last project in the reactor -155 */ -156 private MavenProject getLastProject() { -157 for (int x = getReactorProjects().size() - 1; x >= 0; x--) { -158 final MavenProject p = getReactorProjects().get(x); -159 if (!skipProject(p)) { -160 return p; -161 } -162 } -163 return null; -164 } -165 -166 /** -167 * Tests if the project is being skipped in the Maven site report. -168 * -169 * @param project a project in the reactor -170 * @return true if the project is skipped; otherwise false -171 */ -172 private boolean skipProject(MavenProject project) { -173 final String skip = (String) project.getProperties().get("maven.site.skip"); -174 return "true".equalsIgnoreCase(skip) && isGeneratingSite(); -175 } +22 import java.util.Collections; +23 import java.util.HashSet; +24 import java.util.Locale; +25 import java.util.Set; +26 import org.apache.maven.plugin.MojoExecutionException; +27 import org.apache.maven.plugin.MojoFailureException; +28 import org.apache.maven.plugins.annotations.LifecyclePhase; +29 import org.apache.maven.plugins.annotations.Mojo; +30 import org.apache.maven.plugins.annotations.Parameter; +31 import org.apache.maven.plugins.annotations.ResolutionScope; +32 import org.apache.maven.project.MavenProject; +33 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; +34 import org.owasp.dependencycheck.exception.ExceptionCollection; +35 import org.owasp.dependencycheck.exception.ReportException; +36 import org.owasp.dependencycheck.utils.Settings; +37 +38 /** +39 * Maven Plugin that checks project dependencies and the dependencies of all +40 * child modules to see if they have any known published vulnerabilities. +41 * +42 * @author Jeremy Long +43 */ +44 @Mojo( +45 name = "aggregate", +46 defaultPhase = LifecyclePhase.VERIFY, +47 aggregator = true, +48 threadSafe = false, +49 requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, +50 requiresOnline = true +51 ) +52 public class AggregateMojo extends BaseDependencyCheckMojo { +53 +54 /** +55 * Executes the aggregate dependency-check goal. This runs dependency-check +56 * and generates the subsequent reports. +57 * +58 * @throws MojoExecutionException thrown if there is ane exception running +59 * the mojo +60 * @throws MojoFailureException thrown if dependency-check is configured to +61 * fail the build +62 */ +63 @Override +64 public void runCheck() throws MojoExecutionException, MojoFailureException { +65 final MavenEngine engine = loadEngine(); +66 if (engine == null) { +67 return; +68 } +69 +70 ExceptionCollection exCol = scanArtifacts(getProject(), engine); +71 +72 for (MavenProject childProject : getDescendants(this.getProject())) { +73 final ExceptionCollection ex = scanArtifacts(childProject, engine); +74 if (ex != null) { +75 if (exCol == null) { +76 exCol = ex; +77 } +78 exCol.getExceptions().addAll(ex.getExceptions()); +79 if (ex.isFatal()) { +80 exCol.setFatal(true); +81 } +82 } +83 } +84 +85 try { +86 engine.analyzeDependencies(); +87 } catch (ExceptionCollection ex) { +88 if (exCol == null) { +89 exCol = ex; +90 } else if (ex.isFatal()) { +91 exCol.setFatal(true); +92 exCol.getExceptions().addAll(ex.getExceptions()); +93 } +94 if (exCol.isFatal()) { +95 final String msg = String.format("Fatal exception(s) analyzing %s", getProject().getName()); +96 if (this.isFailOnError()) { +97 throw new MojoExecutionException(msg, exCol); +98 } +99 getLog().error(msg); +100 if (getLog().isDebugEnabled()) { +101 getLog().debug(exCol); +102 } +103 return; +104 } else { +105 final String msg = String.format("Exception(s) analyzing %s", getProject().getName()); +106 if (getLog().isDebugEnabled()) { +107 getLog().debug(msg, exCol); +108 } +109 } +110 } +111 File outputDir = getCorrectOutputDirectory(this.getProject()); +112 if (outputDir == null) { +113 //in some regards we shouldn't be writting this, but we are anyway. +114 //we shouldn't write this because nothing is configured to generate this report. +115 outputDir = new File(this.getProject().getBuild().getDirectory()); +116 } +117 try { +118 writeReports(engine, this.getProject(), outputDir); +119 } catch (ReportException ex) { +120 if (exCol == null) { +121 exCol = new ExceptionCollection("Error writing aggregate report", ex); +122 } else { +123 exCol.addException(ex); +124 } +125 if (this.isFailOnError()) { +126 throw new MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol); +127 } else { +128 getLog().debug("One or more exceptions occured during dependency-check analysis", exCol); +129 } +130 } +131 showSummary(this.getProject(), engine.getDependencies()); +132 checkForFailure(engine.getDependencies()); +133 engine.cleanup(); +134 Settings.cleanup(); +135 } +136 +137 /** +138 * Returns a set containing all the descendant projects of the given +139 * project. +140 * +141 * @param project the project for which all descendants will be returned +142 * @return the set of descendant projects +143 */ +144 protected Set<MavenProject> getDescendants(MavenProject project) { +145 if (project == null) { +146 return Collections.emptySet(); +147 } +148 final Set<MavenProject> descendants = new HashSet<MavenProject>(); +149 int size = 0; +150 if (getLog().isDebugEnabled()) { +151 getLog().debug(String.format("Collecting descendants of %s", project.getName())); +152 } +153 for (String m : project.getModules()) { +154 for (MavenProject mod : getReactorProjects()) { +155 try { +156 File mpp = new File(project.getBasedir(), m); +157 mpp = mpp.getCanonicalFile(); +158 if (mpp.compareTo(mod.getBasedir()) == 0 && descendants.add(mod) +159 && getLog().isDebugEnabled()) { +160 getLog().debug(String.format("Decendent module %s added", mod.getName())); +161 +162 } +163 } catch (IOException ex) { +164 if (getLog().isDebugEnabled()) { +165 getLog().debug("Unable to determine module path", ex); +166 } +167 } +168 } +169 } +170 do { +171 size = descendants.size(); +172 for (MavenProject p : getReactorProjects()) { +173 if (project.equals(p.getParent()) || descendants.contains(p.getParent())) { +174 if (descendants.add(p) && getLog().isDebugEnabled()) { +175 getLog().debug(String.format("Decendent %s added", p.getName())); 176 -177 /** -178 * Returns a set containing all the descendant projects of the given -179 * project. -180 * -181 * @param project the project for which all descendants will be returned -182 * @return the set of descendant projects -183 */ -184 protected Set<MavenProject> getDescendants(MavenProject project) { -185 if (project == null) { -186 return Collections.emptySet(); -187 } -188 final Set<MavenProject> descendants = new HashSet<MavenProject>(); -189 int size = 0; -190 if (getLog().isDebugEnabled()) { -191 getLog().debug(String.format("Collecting descendants of %s", project.getName())); -192 } -193 for (String m : project.getModules()) { -194 for (MavenProject mod : getReactorProjects()) { -195 try { -196 File mpp = new File(project.getBasedir(), m); -197 mpp = mpp.getCanonicalFile(); -198 if (mpp.compareTo(mod.getBasedir()) == 0 && descendants.add(mod) -199 && getLog().isDebugEnabled()) { -200 getLog().debug(String.format("Decendent module %s added", mod.getName())); -201 -202 } -203 } catch (IOException ex) { -204 if (getLog().isDebugEnabled()) { -205 getLog().debug("Unable to determine module path", ex); -206 } -207 } -208 } -209 } -210 do { -211 size = descendants.size(); -212 for (MavenProject p : getReactorProjects()) { -213 if (project.equals(p.getParent()) || descendants.contains(p.getParent())) { -214 if (descendants.add(p) && getLog().isDebugEnabled()) { -215 getLog().debug(String.format("Decendent %s added", p.getName())); -216 -217 } -218 for (MavenProject modTest : getReactorProjects()) { -219 if (p.getModules() != null && p.getModules().contains(modTest.getName()) -220 && descendants.add(modTest) -221 && getLog().isDebugEnabled()) { -222 getLog().debug(String.format("Decendent %s added", modTest.getName())); -223 } -224 } -225 } -226 final Set<MavenProject> addedDescendants = new HashSet<MavenProject>(); -227 for (MavenProject dec : descendants) { -228 for (String mod : dec.getModules()) { -229 try { -230 File mpp = new File(dec.getBasedir(), mod); -231 mpp = mpp.getCanonicalFile(); -232 if (mpp.compareTo(p.getBasedir()) == 0) { -233 addedDescendants.add(p); -234 } -235 } catch (IOException ex) { -236 if (getLog().isDebugEnabled()) { -237 getLog().debug("Unable to determine module path", ex); -238 } -239 } -240 } -241 } -242 for (MavenProject addedDescendant : addedDescendants) { -243 if (descendants.add(addedDescendant) && getLog().isDebugEnabled()) { -244 getLog().debug(String.format("Decendent module %s added", addedDescendant.getName())); -245 } -246 } -247 } -248 } while (size != 0 && size != descendants.size()); -249 if (getLog().isDebugEnabled()) { -250 getLog().debug(String.format("%s has %d children", project, descendants.size())); -251 } -252 return descendants; -253 } -254 -255 /** -256 * Test if the project has pom packaging -257 * -258 * @param mavenProject Project to test -259 * @return <code>true</code> if it has a pom packaging; otherwise -260 * <code>false</code> -261 */ -262 protected boolean isMultiModule(MavenProject mavenProject) { -263 return "pom".equals(mavenProject.getPackaging()); -264 } -265 -266 /** -267 * Initializes the engine, runs a scan, and writes the serialized -268 * dependencies to disk. -269 * -270 * @return the MavenEngine used to execute dependency-check -271 * @throws MojoExecutionException thrown if there is an exception running -272 * the mojo -273 * @throws MojoFailureException thrown if dependency-check is configured to -274 * fail the build if severe CVEs are identified. -275 */ -276 protected MavenEngine generateDataFile() throws MojoExecutionException, MojoFailureException { -277 MavenEngine engine = null; -278 try { -279 engine = initializeEngine(); -280 } catch (DatabaseException ex) { -281 if (getLog().isDebugEnabled()) { -282 getLog().debug("Database connection error", ex); -283 } -284 final String msg = "An exception occured connecting to the local database. Please see the log file for more details."; -285 if (this.isFailOnError()) { -286 throw new MojoExecutionException(msg, ex); -287 } -288 getLog().error(msg, ex); -289 return null; -290 } -291 return generateDataFile(engine, getProject()); -292 } -293 -294 /** -295 * Runs dependency-check's MavenEngine and writes the serialized -296 * dependencies to disk. -297 * -298 * @param engine the MavenEngine to use when scanning. -299 * @param project the project to scan and generate the data file for -300 * @return the MavenEngine used to execute dependency-check -301 * @throws MojoExecutionException thrown if there is an exception running -302 * the mojo -303 * @throws MojoFailureException thrown if dependency-check is configured to -304 * fail the build if severe CVEs are identified. -305 */ -306 protected MavenEngine generateDataFile(MavenEngine engine, MavenProject project) throws MojoExecutionException, MojoFailureException { -307 if (getLog().isDebugEnabled()) { -308 getLog().debug(String.format("Begin Scanning: %s", project.getName())); -309 } -310 engine.getDependencies().clear(); -311 engine.resetFileTypeAnalyzers(); -312 scanArtifacts(project, engine); -313 try { -314 engine.analyzeDependencies(); -315 } catch (ExceptionCollection ex) { -316 ExceptionCollection col = (ExceptionCollection) engine.getExecutionRoot().getContextValue(AGGREGATE_EXCEPTIONS); -317 if (col == null) { -318 col = ex; -319 } else if (ex.isFatal()) { -320 col.setFatal(true); -321 col.getExceptions().addAll(ex.getExceptions()); -322 } -323 if (col.isFatal()) { -324 final String msg = String.format("Fatal exception(s) analyzing %s", project.getName()); -325 if (this.isFailOnError()) { -326 throw new MojoExecutionException(msg, ex); -327 } -328 getLog().error(msg, col); -329 return null; -330 } else { -331 final String msg = String.format("Exception(s) analyzing %s", project.getName()); -332 if (getLog().isDebugEnabled()) { -333 getLog().debug(msg, ex); -334 } -335 engine.getExecutionRoot().setContextValue(AGGREGATE_EXCEPTIONS, col); -336 } -337 } -338 final File target = new File(project.getBuild().getDirectory()); -339 writeDataFile(project, target, engine.getDependencies()); -340 showSummary(project, engine.getDependencies()); -341 checkForFailure(engine.getDependencies()); -342 return engine; -343 } -344 -345 @Override -346 public boolean canGenerateReport() { -347 return true; //aggregate always returns true for now - we can look at a more complicated/acurate solution later -348 } -349 -350 /** -351 * The name of the report in the site. -352 */ -353 @SuppressWarnings("CanBeFinal") -354 @Parameter(property = "name", defaultValue = "dependency-check:aggregate", required = true) -355 private String name = "dependency-check:aggregate"; -356 -357 /** -358 * Returns the report name. -359 * -360 * @param locale the location -361 * @return the report name -362 */ -363 @Override -364 public String getName(Locale locale) { -365 return name; -366 } -367 -368 /** -369 * Gets the description of the Dependency-Check report to be displayed in -370 * the Maven Generated Reports page. -371 * -372 * @param locale The Locale to get the description for -373 * @return the description -374 */ -375 @Override -376 public String getDescription(Locale locale) { -377 return "Generates an aggregate report of all child Maven projects providing details on any " -378 + "published vulnerabilities within project dependencies. This report is a best " -379 + "effort and may contain false positives and false negatives."; -380 } -381 } +177 } +178 for (MavenProject modTest : getReactorProjects()) { +179 if (p.getModules() != null && p.getModules().contains(modTest.getName()) +180 && descendants.add(modTest) +181 && getLog().isDebugEnabled()) { +182 getLog().debug(String.format("Decendent %s added", modTest.getName())); +183 } +184 } +185 } +186 final Set<MavenProject> addedDescendants = new HashSet<MavenProject>(); +187 for (MavenProject dec : descendants) { +188 for (String mod : dec.getModules()) { +189 try { +190 File mpp = new File(dec.getBasedir(), mod); +191 mpp = mpp.getCanonicalFile(); +192 if (mpp.compareTo(p.getBasedir()) == 0) { +193 addedDescendants.add(p); +194 } +195 } catch (IOException ex) { +196 if (getLog().isDebugEnabled()) { +197 getLog().debug("Unable to determine module path", ex); +198 } +199 } +200 } +201 } +202 for (MavenProject addedDescendant : addedDescendants) { +203 if (descendants.add(addedDescendant) && getLog().isDebugEnabled()) { +204 getLog().debug(String.format("Decendent module %s added", addedDescendant.getName())); +205 } +206 } +207 } +208 } while (size != 0 && size != descendants.size()); +209 if (getLog().isDebugEnabled()) { +210 getLog().debug(String.format("%s has %d children", project, descendants.size())); +211 } +212 return descendants; +213 } +214 +215 /** +216 * Test if the project has pom packaging +217 * +218 * @param mavenProject Project to test +219 * @return <code>true</code> if it has a pom packaging; otherwise +220 * <code>false</code> +221 */ +222 protected boolean isMultiModule(MavenProject mavenProject) { +223 return "pom".equals(mavenProject.getPackaging()); +224 } +225 +226 /** +227 * Initializes the engine. +228 * +229 * @return the MavenEngine used to execute dependency-check +230 * @throws MojoExecutionException thrown if there is an exception running +231 * the Mojo +232 * @throws MojoFailureException thrown if dependency-check is configured to +233 * fail the build if severe CVEs are identified. +234 */ +235 protected MavenEngine loadEngine() throws MojoExecutionException, MojoFailureException { +236 MavenEngine engine = null; +237 try { +238 engine = initializeEngine(); +239 } catch (DatabaseException ex) { +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."; +244 if (this.isFailOnError()) { +245 throw new MojoExecutionException(msg, ex); +246 } +247 getLog().error(msg, ex); +248 } +249 return engine; +250 } +251 +252 @Override +253 public boolean canGenerateReport() { +254 return true; //aggregate always returns true for now - we can look at a more complicated/acurate solution later +255 } +256 +257 /** +258 * The name of the report in the site. +259 */ +260 @SuppressWarnings("CanBeFinal") +261 @Parameter(property = "name", defaultValue = "dependency-check:aggregate", required = true) +262 private String name = "dependency-check:aggregate"; +263 +264 /** +265 * Returns the report name. +266 * +267 * @param locale the location +268 * @return the report name +269 */ +270 @Override +271 public String getName(Locale locale) { +272 return name; +273 } +274 +275 /** +276 * Gets the description of the Dependency-Check report to be displayed in +277 * the Maven Generated Reports page. +278 * +279 * @param locale The Locale to get the description for +280 * @return the description +281 */ +282 @Override +283 public String getDescription(Locale locale) { +284 return "Generates an aggregate report of all child Maven projects providing details on any " +285 + "published vulnerabilities within project dependencies. This report is a best " +286 + "effort and may contain false positives and false negatives."; +287 } +288 }
    diff --git a/xref/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.html b/xref/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.html index e07c364c5..a8d9cb601 100644 --- a/xref/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.html +++ b/xref/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.html @@ -35,7 +35,7 @@ 27 import java.io.ObjectOutputStream; 28 import java.util.List; 29 import java.util.Locale; -30 import org.apache.maven.artifact.Artifact; +30 import org.eclipse.aether.artifact.Artifact; 31 import org.apache.maven.doxia.sink.Sink; 32 import org.apache.maven.plugin.AbstractMojo; 33 import org.apache.maven.plugin.MojoExecutionException; @@ -47,1101 +47,1225 @@ 39 import org.apache.maven.reporting.MavenReportException; 40 import org.apache.maven.settings.Proxy; 41 import org.apache.maven.settings.Server; -42 import org.owasp.dependencycheck.data.nexus.MavenArtifact; -43 import org.owasp.dependencycheck.data.nvdcve.CveDB; -44 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; -45 import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties; -46 import org.owasp.dependencycheck.dependency.Confidence; -47 import org.owasp.dependencycheck.dependency.Dependency; -48 import org.owasp.dependencycheck.dependency.Identifier; -49 import org.owasp.dependencycheck.dependency.Vulnerability; -50 import org.owasp.dependencycheck.exception.ReportException; -51 import org.owasp.dependencycheck.reporting.ReportGenerator; -52 import org.owasp.dependencycheck.utils.ExpectedOjectInputStream; -53 import org.owasp.dependencycheck.utils.Settings; -54 import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher; -55 import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher; -56 import org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException; -57 -58 /** -59 * -60 * @author Jeremy Long -61 */ -62 public abstract class BaseDependencyCheckMojo extends AbstractMojo implements MavenReport { -63 -64 //<editor-fold defaultstate="collapsed" desc="Private fields"> -65 /** -66 * The properties file location. -67 */ -68 private static final String PROPERTIES_FILE = "mojo.properties"; -69 /** -70 * System specific new line character. -71 */ -72 private static final String NEW_LINE = System.getProperty("line.separator", "\n").intern(); -73 //</editor-fold> -74 // <editor-fold defaultstate="collapsed" desc="Maven bound parameters and components"> -75 /** -76 * Sets whether or not the external report format should be used. -77 */ -78 @Parameter(property = "metaFileName", defaultValue = "dependency-check.ser", required = true) -79 private String dataFileName; +42 import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder; +43 import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException; +44 import org.apache.maven.shared.dependency.graph.DependencyNode; +45 import org.eclipse.aether.RepositorySystem; +46 import org.eclipse.aether.RepositorySystemSession; +47 import org.eclipse.aether.artifact.DefaultArtifact; +48 import org.eclipse.aether.repository.RemoteRepository; +49 import org.eclipse.aether.resolution.ArtifactRequest; +50 import org.eclipse.aether.resolution.ArtifactResolutionException; +51 import org.eclipse.aether.resolution.ArtifactResult; +52 import org.owasp.dependencycheck.data.nexus.MavenArtifact; +53 import org.owasp.dependencycheck.data.nvdcve.CveDB; +54 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; +55 import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties; +56 import org.owasp.dependencycheck.dependency.Confidence; +57 import org.owasp.dependencycheck.dependency.Dependency; +58 import org.owasp.dependencycheck.dependency.Identifier; +59 import org.owasp.dependencycheck.dependency.Vulnerability; +60 import org.owasp.dependencycheck.exception.ExceptionCollection; +61 import org.owasp.dependencycheck.exception.ReportException; +62 import org.owasp.dependencycheck.reporting.ReportGenerator; +63 import org.owasp.dependencycheck.utils.ExpectedOjectInputStream; +64 import org.owasp.dependencycheck.utils.Settings; +65 import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher; +66 import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher; +67 import org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException; +68 +69 /** +70 * +71 * @author Jeremy Long +72 */ +73 public abstract class BaseDependencyCheckMojo extends AbstractMojo implements MavenReport { +74 +75 //<editor-fold defaultstate="collapsed" desc="Private fields"> +76 /** +77 * The properties file location. +78 */ +79 private static final String PROPERTIES_FILE = "mojo.properties"; 80 /** -81 * Sets whether or not the external report format should be used. +81 * System specific new line character. 82 */ -83 @Parameter(property = "failOnError", defaultValue = "true", required = true) -84 private boolean failOnError; -85 +83 private static final String NEW_LINE = System.getProperty("line.separator", "\n").intern(); +84 //</editor-fold> +85 // <editor-fold defaultstate="collapsed" desc="Maven bound parameters and components"> 86 /** -87 * Returns if the mojo should fail the build if an exception occurs. -88 * -89 * @return whether or not the mojo should fail the build -90 */ -91 protected boolean isFailOnError() { -92 return failOnError; -93 } -94 -95 /** -96 * The Maven Project Object. -97 */ -98 @Parameter(property = "project", required = true, readonly = true) -99 private MavenProject project; -100 /** -101 * List of Maven project of the current build -102 */ -103 @Parameter(readonly = true, required = true, property = "reactorProjects") -104 private List<MavenProject> reactorProjects; +87 * Sets whether or not the external report format should be used. +88 */ +89 @Parameter(property = "metaFileName", defaultValue = "dependency-check.ser", required = true) +90 private String dataFileName; +91 /** +92 * Sets whether or not the external report format should be used. +93 */ +94 @Parameter(property = "failOnError", defaultValue = "true", required = true) +95 private boolean failOnError; +96 +97 /** +98 * Returns if the mojo should fail the build if an exception occurs. +99 * +100 * @return whether or not the mojo should fail the build +101 */ +102 protected boolean isFailOnError() { +103 return failOnError; +104 } 105 106 /** -107 * The output directory. This generally maps to "target". +107 * The Maven Project Object. 108 */ -109 @Parameter(defaultValue = "${project.build.directory}", required = true) -110 private File outputDirectory; +109 @Parameter(property = "project", required = true, readonly = true) +110 private MavenProject project; 111 /** -112 * Specifies the destination directory for the generated Dependency-Check -113 * report. This generally maps to "target/site". -114 */ -115 @Parameter(property = "project.reporting.outputDirectory", required = true) -116 private File reportOutputDirectory; -117 /** -118 * Specifies if the build should be failed if a CVSS score above a specified -119 * level is identified. The default is 11 which means since the CVSS scores -120 * are 0-10, by default the build will never fail. -121 */ -122 @SuppressWarnings("CanBeFinal") -123 @Parameter(property = "failBuildOnCVSS", defaultValue = "11", required = true) -124 private float failBuildOnCVSS = 11; -125 /** -126 * Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not -127 * recommended that this be turned to false. Default is true. -128 */ -129 @Parameter(property = "autoUpdate") -130 private Boolean autoUpdate; -131 /** -132 * Sets whether Experimental analyzers are enabled. Default is false. -133 */ -134 @Parameter(property = "enableExperimental") -135 private Boolean enableExperimental; -136 /** -137 * Generate aggregate reports in multi-module projects. -138 * -139 * @deprecated use the aggregate goal instead -140 */ -141 @Parameter(property = "aggregate") -142 @Deprecated -143 private Boolean aggregate; -144 /** -145 * The report format to be generated (HTML, XML, VULN, ALL). This -146 * configuration option has no affect if using this within the Site plug-in -147 * unless the externalReport is set to true. Default is HTML. -148 */ -149 @SuppressWarnings("CanBeFinal") -150 @Parameter(property = "format", defaultValue = "HTML", required = true) -151 private String format = "HTML"; +112 * List of Maven project of the current build +113 */ +114 @Parameter(readonly = true, required = true, property = "reactorProjects") +115 private List<MavenProject> reactorProjects; +116 /** +117 * The entry point to Aether, i.e. the component doing all the work. +118 */ +119 @Component +120 private RepositorySystem repoSystem; +121 +122 /** +123 * The current repository/network configuration of Maven. +124 */ +125 @Parameter(defaultValue = "${repositorySystemSession}", readonly = true) +126 private RepositorySystemSession repoSession; +127 +128 /** +129 * The project's remote repositories to use for the resolution of plug-ins +130 * and their dependencies. +131 */ +132 @Parameter(defaultValue = "${project.remotePluginRepositories}", readonly = true) +133 private List<RemoteRepository> remoteRepos; +134 +135 /** +136 * Component within Maven to build the dependency graph. +137 */ +138 @Component +139 private DependencyGraphBuilder dependencyGraphBuilder; +140 +141 /** +142 * The output directory. This generally maps to "target". +143 */ +144 @Parameter(defaultValue = "${project.build.directory}", required = true) +145 private File outputDirectory; +146 /** +147 * Specifies the destination directory for the generated Dependency-Check +148 * report. This generally maps to "target/site". +149 */ +150 @Parameter(property = "project.reporting.outputDirectory", required = true) +151 private File reportOutputDirectory; 152 /** -153 * The Maven settings. -154 */ -155 @Parameter(property = "mavenSettings", defaultValue = "${settings}", required = false) -156 private org.apache.maven.settings.Settings mavenSettings; -157 -158 /** -159 * The maven settings proxy id. -160 */ -161 @Parameter(property = "mavenSettingsProxyId", required = false) -162 private String mavenSettingsProxyId; -163 -164 /** -165 * The Connection Timeout. -166 */ -167 @Parameter(property = "connectionTimeout", defaultValue = "", required = false) -168 private String connectionTimeout; -169 /** -170 * The path to the suppression file. -171 */ -172 @Parameter(property = "suppressionFile", defaultValue = "", required = false) -173 private String suppressionFile; -174 /** -175 * Flag indicating whether or not to show a summary in the output. -176 */ -177 @SuppressWarnings("CanBeFinal") -178 @Parameter(property = "showSummary", defaultValue = "true", required = false) -179 private boolean showSummary = true; -180 -181 /** -182 * Whether or not the Jar Analyzer is enabled. +153 * Specifies if the build should be failed if a CVSS score above a specified +154 * level is identified. The default is 11 which means since the CVSS scores +155 * are 0-10, by default the build will never fail. +156 */ +157 @SuppressWarnings("CanBeFinal") +158 @Parameter(property = "failBuildOnCVSS", defaultValue = "11", required = true) +159 private float failBuildOnCVSS = 11; +160 /** +161 * Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not +162 * recommended that this be turned to false. Default is true. +163 */ +164 @Parameter(property = "autoUpdate") +165 private Boolean autoUpdate; +166 /** +167 * Sets whether Experimental analyzers are enabled. Default is false. +168 */ +169 @Parameter(property = "enableExperimental") +170 private Boolean enableExperimental; +171 /** +172 * Generate aggregate reports in multi-module projects. +173 * +174 * @deprecated use the aggregate goal instead +175 */ +176 @Parameter(property = "aggregate") +177 @Deprecated +178 private Boolean aggregate; +179 /** +180 * The report format to be generated (HTML, XML, VULN, ALL). This +181 * configuration option has no affect if using this within the Site plug-in +182 * unless the externalReport is set to true. Default is HTML. 183 */ -184 @Parameter(property = "jarAnalyzerEnabled", required = false) -185 private Boolean jarAnalyzerEnabled; -186 +184 @SuppressWarnings("CanBeFinal") +185 @Parameter(property = "format", defaultValue = "HTML", required = true) +186 private String format = "HTML"; 187 /** -188 * Whether or not the Archive Analyzer is enabled. +188 * The Maven settings. 189 */ -190 @Parameter(property = "archiveAnalyzerEnabled", required = false) -191 private Boolean archiveAnalyzerEnabled; +190 @Parameter(property = "mavenSettings", defaultValue = "${settings}", required = false) +191 private org.apache.maven.settings.Settings mavenSettings; 192 193 /** -194 * Sets whether the Python Distribution Analyzer will be used. +194 * The maven settings proxy id. 195 */ -196 @Parameter(property = "pyDistributionAnalyzerEnabled", required = false) -197 private Boolean pyDistributionAnalyzerEnabled; -198 /** -199 * Sets whether the Python Package Analyzer will be used. -200 */ -201 @Parameter(property = "pyPackageAnalyzerEnabled", required = false) -202 private Boolean pyPackageAnalyzerEnabled; -203 /** -204 * Sets whether the Ruby Gemspec Analyzer will be used. -205 */ -206 @Parameter(property = "rubygemsAnalyzerEnabled", required = false) -207 private Boolean rubygemsAnalyzerEnabled; -208 /** -209 * Sets whether or not the openssl Analyzer should be used. -210 */ -211 @Parameter(property = "opensslAnalyzerEnabled", required = false) -212 private Boolean opensslAnalyzerEnabled; -213 /** -214 * Sets whether or not the CMake Analyzer should be used. -215 */ -216 @Parameter(property = "cmakeAnalyzerEnabled", required = false) -217 private Boolean cmakeAnalyzerEnabled; -218 /** -219 * Sets whether or not the autoconf Analyzer should be used. -220 */ -221 @Parameter(property = "autoconfAnalyzerEnabled", required = false) -222 private Boolean autoconfAnalyzerEnabled; -223 /** -224 * Sets whether or not the PHP Composer Lock File Analyzer should be used. -225 */ -226 @Parameter(property = "composerAnalyzerEnabled", required = false) -227 private Boolean composerAnalyzerEnabled; +196 @Parameter(property = "mavenSettingsProxyId", required = false) +197 private String mavenSettingsProxyId; +198 +199 /** +200 * The Connection Timeout. +201 */ +202 @Parameter(property = "connectionTimeout", defaultValue = "", required = false) +203 private String connectionTimeout; +204 /** +205 * The path to the suppression file. +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; +215 +216 /** +217 * Whether or not the Jar Analyzer is enabled. +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 or not the Node.js Analyzer should be used. +229 * Sets whether the Python Distribution Analyzer will be used. 230 */ -231 @Parameter(property = "nodeAnalyzerEnabled", required = false) -232 private Boolean nodeAnalyzerEnabled; -233 -234 /** -235 * Whether or not the .NET Assembly Analyzer is enabled. -236 */ -237 @Parameter(property = "assemblyAnalyzerEnabled", required = false) -238 private Boolean assemblyAnalyzerEnabled; -239 -240 /** -241 * Whether or not the .NET Nuspec Analyzer is enabled. -242 */ -243 @Parameter(property = "nuspecAnalyzerEnabled", required = false) -244 private Boolean nuspecAnalyzerEnabled; -245 -246 /** -247 * Whether or not the Central Analyzer is enabled. -248 */ -249 @Parameter(property = "centralAnalyzerEnabled", required = false) -250 private Boolean centralAnalyzerEnabled; -251 -252 /** -253 * Whether or not the Nexus Analyzer is enabled. -254 */ -255 @Parameter(property = "nexusAnalyzerEnabled", required = false) -256 private Boolean nexusAnalyzerEnabled; -257 +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 * The URL of a Nexus server's REST API end point -260 * (http://domain/nexus/service/local). -261 */ -262 @Parameter(property = "nexusUrl", required = false) -263 private String nexusUrl; -264 /** -265 * Whether or not the configured proxy is used to connect to Nexus. -266 */ -267 @Parameter(property = "nexusUsesProxy", required = false) -268 private Boolean nexusUsesProxy; +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 * The database connection string. +270 * Whether or not the .NET Assembly Analyzer is enabled. 271 */ -272 @Parameter(property = "connectionString", defaultValue = "", required = false) -273 private String connectionString; +272 @Parameter(property = "assemblyAnalyzerEnabled", required = false) +273 private Boolean assemblyAnalyzerEnabled; 274 275 /** -276 * Returns the connection string. -277 * -278 * @return the connection string -279 */ -280 protected String getConnectionString() { -281 return connectionString; -282 } -283 /** -284 * The database driver name. An example would be org.h2.Driver. -285 */ -286 @Parameter(property = "databaseDriverName", defaultValue = "", required = false) -287 private String databaseDriverName; -288 /** -289 * The path to the database driver if it is not on the class path. -290 */ -291 @Parameter(property = "databaseDriverPath", defaultValue = "", required = false) -292 private String databaseDriverPath; +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 server id in the settings.xml; used to retrieve encrypted passwords -295 * from the settings.xml. +294 * The URL of a Nexus server's REST API end point +295 * (http://domain/nexus/service/local). 296 */ -297 @Parameter(property = "serverId", defaultValue = "", required = false) -298 private String serverId; +297 @Parameter(property = "nexusUrl", required = false) +298 private String nexusUrl; 299 /** -300 * A reference to the settings.xml settings. +300 * Whether or not the configured proxy is used to connect to Nexus. 301 */ -302 @Parameter(defaultValue = "${settings}", readonly = true, required = true) -303 private org.apache.maven.settings.Settings settingsXml; +302 @Parameter(property = "nexusUsesProxy", required = false) +303 private Boolean nexusUsesProxy; 304 /** -305 * The security dispatcher that can decrypt passwords in the settings.xml. +305 * The database connection string. 306 */ -307 @Component(role = SecDispatcher.class, hint = "default") -308 private SecDispatcher securityDispatcher; -309 /** -310 * The database user name. -311 */ -312 @Parameter(property = "databaseUser", defaultValue = "", required = false) -313 private String databaseUser; -314 /** -315 * The password to use when connecting to the database. -316 */ -317 @Parameter(property = "databasePassword", defaultValue = "", required = false) -318 private String databasePassword; -319 /** -320 * A comma-separated list of file extensions to add to analysis next to jar, -321 * zip, .... -322 */ -323 @Parameter(property = "zipExtensions", required = false) -324 private String zipExtensions; -325 /** -326 * Skip Dependency Check altogether. -327 */ -328 @SuppressWarnings("CanBeFinal") -329 @Parameter(property = "dependency-check.skip", defaultValue = "false", required = false) -330 private boolean skip = false; -331 /** -332 * Skip Analysis for Test Scope Dependencies. -333 */ -334 @SuppressWarnings("CanBeFinal") -335 @Parameter(property = "skipTestScope", defaultValue = "true", required = false) -336 private boolean skipTestScope = true; -337 /** -338 * Skip Analysis for Runtime Scope Dependencies. -339 */ -340 @SuppressWarnings("CanBeFinal") -341 @Parameter(property = "skipRuntimeScope", defaultValue = "false", required = false) -342 private boolean skipRuntimeScope = false; -343 /** -344 * Skip Analysis for Provided Scope Dependencies. -345 */ -346 @SuppressWarnings("CanBeFinal") -347 @Parameter(property = "skipProvidedScope", defaultValue = "false", required = false) -348 private boolean skipProvidedScope = false; +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 data directory, hold DC SQL DB. +350 * The password to use when connecting to the database. 351 */ -352 @Parameter(property = "dataDirectory", defaultValue = "", required = false) -353 private String dataDirectory; +352 @Parameter(property = "databasePassword", defaultValue = "", required = false) +353 private String databasePassword; 354 /** -355 * Data Mirror URL for CVE 1.2. -356 */ -357 @Parameter(property = "cveUrl12Modified", defaultValue = "", required = false) -358 private String cveUrl12Modified; -359 /** -360 * Data Mirror URL for CVE 2.0. -361 */ -362 @Parameter(property = "cveUrl20Modified", defaultValue = "", required = false) -363 private String cveUrl20Modified; -364 /** -365 * Base Data Mirror URL for CVE 1.2. -366 */ -367 @Parameter(property = "cveUrl12Base", defaultValue = "", required = false) -368 private String cveUrl12Base; -369 /** -370 * Data Mirror URL for CVE 2.0. -371 */ -372 @Parameter(property = "cveUrl20Base", defaultValue = "", required = false) -373 private String cveUrl20Base; -374 /** -375 * Optionally skip excessive CVE update checks for a designated duration in -376 * hours. -377 */ -378 @Parameter(property = "cveValidForHours", defaultValue = "", required = false) -379 private Integer cveValidForHours; -380 -381 /** -382 * The path to mono for .NET Assembly analysis on non-windows systems. -383 */ -384 @Parameter(property = "pathToMono", defaultValue = "", required = false) -385 private String pathToMono; -386 -387 /** -388 * The Proxy URL. -389 * -390 * @deprecated Please use mavenSettings instead +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 @SuppressWarnings("CanBeFinal") -393 @Parameter(property = "proxyUrl", defaultValue = "", required = false) -394 @Deprecated -395 private String proxyUrl = null; -396 /** -397 * Sets whether or not the external report format should be used. -398 * -399 * @deprecated the internal report is no longer supported -400 */ -401 @SuppressWarnings("CanBeFinal") -402 @Parameter(property = "externalReport") -403 @Deprecated -404 private String externalReport = null; -405 // </editor-fold> -406 //<editor-fold defaultstate="collapsed" desc="Base Maven implementation"> -407 -408 /** -409 * Executes dependency-check. -410 * -411 * @throws MojoExecutionException thrown if there is an exception executing -412 * the mojo -413 * @throws MojoFailureException thrown if dependency-check failed the build -414 */ -415 @Override -416 public void execute() throws MojoExecutionException, MojoFailureException { -417 generatingSite = false; -418 if (skip) { -419 getLog().info("Skipping " + getName(Locale.US)); -420 } else { -421 validateAggregate(); -422 project.setContextValue(getOutputDirectoryContextKey(), this.outputDirectory); -423 runCheck(); -424 } -425 } -426 -427 /** -428 * Checks if the aggregate configuration parameter has been set to true. If -429 * it has a MojoExecutionException is thrown because the aggregate -430 * configuration parameter is no longer supported. -431 * -432 * @throws MojoExecutionException thrown if aggregate is set to true -433 */ -434 private void validateAggregate() throws MojoExecutionException { -435 if (aggregate != null && aggregate) { -436 final String msg = "Aggregate configuration detected - as of dependency-check 1.2.8 this no longer supported. " -437 + "Please use the aggregate goal instead."; -438 throw new MojoExecutionException(msg); -439 } -440 } -441 -442 /** -443 * Generates the Dependency-Check Site Report. -444 * -445 * @param sink the sink to write the report to -446 * @param locale the locale to use when generating the report -447 * @throws MavenReportException if a maven report exception occurs -448 * @deprecated use -449 * {@link #generate(org.apache.maven.doxia.sink.Sink, java.util.Locale)} -450 * instead. -451 */ -452 @Override -453 @Deprecated -454 public final void generate(@SuppressWarnings("deprecation") org.codehaus.doxia.sink.Sink sink, Locale locale) throws MavenReportException { -455 generate((Sink) sink, locale); -456 } -457 -458 /** -459 * A flag indicating whether or not the maven site is being generated. -460 */ -461 private boolean generatingSite = false; -462 -463 /** -464 * Returns true if the Maven site is being generated. -465 * -466 * @return true if the Maven site is being generated -467 */ -468 protected boolean isGeneratingSite() { -469 return generatingSite; -470 } -471 -472 /** -473 * Generates the Dependency-Check Site Report. -474 * -475 * @param sink the sink to write the report to -476 * @param locale the locale to use when generating the report -477 * @throws MavenReportException if a maven report exception occurs -478 */ -479 public void generate(Sink sink, Locale locale) throws MavenReportException { -480 generatingSite = true; -481 try { -482 validateAggregate(); -483 } catch (MojoExecutionException ex) { -484 throw new MavenReportException(ex.getMessage()); -485 } -486 project.setContextValue(getOutputDirectoryContextKey(), getReportOutputDirectory()); -487 try { -488 runCheck(); -489 } catch (MojoExecutionException ex) { -490 throw new MavenReportException(ex.getMessage(), ex); -491 } catch (MojoFailureException ex) { -492 getLog().warn("Vulnerabilities were identifies that exceed the CVSS threshold for failing the build"); -493 } -494 } -495 -496 /** -497 * Returns the correct output directory depending on if a site is being -498 * executed or not. -499 * -500 * @return the directory to write the report(s) -501 * @throws MojoExecutionException thrown if there is an error loading the -502 * file path -503 */ -504 protected File getCorrectOutputDirectory() throws MojoExecutionException { -505 return getCorrectOutputDirectory(this.project); -506 } -507 -508 /** -509 * Returns the correct output directory depending on if a site is being -510 * executed or not. -511 * -512 * @param current the Maven project to get the output directory from -513 * @return the directory to write the report(s) -514 */ -515 protected File getCorrectOutputDirectory(MavenProject current) { -516 final Object obj = current.getContextValue(getOutputDirectoryContextKey()); -517 if (obj != null && obj instanceof File) { -518 return (File) obj; -519 } -520 File target = new File(current.getBuild().getDirectory()); -521 if (target.getParentFile() != null && "target".equals(target.getParentFile().getName())) { -522 target = target.getParentFile(); -523 } -524 return target; -525 } -526 -527 /** -528 * Returns the correct output directory depending on if a site is being -529 * executed or not. -530 * -531 * @param current the Maven project to get the output directory from -532 * @return the directory to write the report(s) -533 */ -534 protected File getDataFile(MavenProject current) { -535 if (getLog().isDebugEnabled()) { -536 getLog().debug(String.format("Getting data filefor %s using key '%s'", current.getName(), getDataFileContextKey())); -537 } -538 final Object obj = current.getContextValue(getDataFileContextKey()); -539 if (obj != null) { -540 if (obj instanceof String) { -541 final File f = new File((String) obj); -542 return f; -543 } -544 } else if (getLog().isDebugEnabled()) { -545 getLog().debug("Context value not found"); -546 } -547 return null; -548 } -549 -550 /** -551 * Scans the project's artifacts and adds them to the engine's dependency -552 * list. -553 * -554 * @param project the project to scan the dependencies of -555 * @param engine the engine to use to scan the dependencies -556 */ -557 protected void scanArtifacts(MavenProject project, MavenEngine engine) { -558 for (Artifact a : project.getArtifacts()) { -559 if (excludeFromScan(a)) { -560 continue; -561 } -562 final List<Dependency> deps = engine.scan(a.getFile().getAbsoluteFile()); -563 if (deps != null) { -564 if (deps.size() == 1) { -565 final Dependency d = deps.get(0); -566 if (d != null) { -567 final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion()); -568 d.addAsEvidence("pom", ma, Confidence.HIGHEST); -569 d.addProjectReference(project.getName()); -570 if (getLog().isDebugEnabled()) { -571 getLog().debug(String.format("Adding project reference %s on dependency %s", project.getName(), -572 d.getDisplayFileName())); -573 } -574 } -575 } else if (getLog().isDebugEnabled()) { -576 final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s:%s:%s'", -577 a.getGroupId(), a.getArtifactId(), a.getVersion()); -578 getLog().debug(msg); -579 } -580 } +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 +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 +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 } -583 -584 /** -585 * Executes the dependency-check scan and generates the necassary report. -586 * -587 * @throws MojoExecutionException thrown if there is an exception running -588 * the scan -589 * @throws MojoFailureException thrown if dependency-check is configured to -590 * fail the build -591 */ -592 public abstract void runCheck() throws MojoExecutionException, MojoFailureException; -593 -594 /** -595 * Sets the Reporting output directory. -596 * -597 * @param directory the output directory -598 */ -599 @Override -600 public void setReportOutputDirectory(File directory) { -601 reportOutputDirectory = directory; -602 } -603 -604 /** -605 * Returns the report output directory. -606 * -607 * @return the report output directory -608 */ -609 @Override -610 public File getReportOutputDirectory() { -611 return reportOutputDirectory; -612 } -613 -614 /** -615 * Returns the output directory. -616 * -617 * @return the output directory -618 */ -619 public File getOutputDirectory() { -620 return outputDirectory; -621 } -622 -623 /** -624 * Returns whether this is an external report. This method always returns -625 * true. -626 * -627 * @return <code>true</code> -628 */ -629 @Override -630 public final boolean isExternalReport() { -631 return true; -632 } -633 -634 /** -635 * Returns the output name. +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 } +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 * @return the output name -638 */ -639 @Override -640 public String getOutputName() { -641 if ("HTML".equalsIgnoreCase(this.format) || "ALL".equalsIgnoreCase(this.format)) { -642 return "dependency-check-report"; -643 } else if ("XML".equalsIgnoreCase(this.format)) { -644 return "dependency-check-report.xml#"; -645 } else if ("VULN".equalsIgnoreCase(this.format)) { -646 return "dependency-check-vulnerability"; -647 } else { -648 getLog().warn("Unknown report format used during site generation."); -649 return "dependency-check-report"; -650 } -651 } -652 -653 /** -654 * Returns the category name. -655 * -656 * @return the category name -657 */ -658 @Override -659 public String getCategoryName() { -660 return MavenReport.CATEGORY_PROJECT_REPORTS; -661 } -662 //</editor-fold> -663 -664 /** -665 * Initializes a new <code>MavenEngine</code> that can be used for scanning. -666 * -667 * @return a newly instantiated <code>MavenEngine</code> -668 * @throws DatabaseException thrown if there is a database exception -669 */ -670 protected MavenEngine initializeEngine() throws DatabaseException { -671 populateSettings(); -672 return new MavenEngine(this.project, -673 this.reactorProjects); -674 } -675 -676 /** -677 * Takes the properties supplied and updates the dependency-check settings. -678 * Additionally, this sets the system properties required to change the -679 * proxy url, port, and connection timeout. -680 */ -681 protected void populateSettings() { -682 Settings.initialize(); -683 InputStream mojoProperties = null; -684 try { -685 mojoProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE); -686 Settings.mergeProperties(mojoProperties); -687 } catch (IOException ex) { -688 getLog().warn("Unable to load the dependency-check ant task.properties file."); -689 if (getLog().isDebugEnabled()) { -690 getLog().debug("", ex); -691 } -692 } finally { -693 if (mojoProperties != null) { -694 try { -695 mojoProperties.close(); -696 } catch (IOException ex) { -697 if (getLog().isDebugEnabled()) { -698 getLog().debug("", ex); -699 } -700 } -701 } -702 } -703 Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate); -704 -705 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental); -706 -707 if (externalReport != null) { -708 getLog().warn("The 'externalReport' option was set; this configuration option has been removed. " -709 + "Please update the dependency-check-maven plugin's configuration"); -710 } -711 -712 if (proxyUrl != null && !proxyUrl.isEmpty()) { -713 getLog().warn("Deprecated configuration detected, proxyUrl will be ignored; use the maven settings " + "to configure the proxy instead"); -714 } -715 final Proxy proxy = getMavenProxy(); -716 if (proxy != null) { -717 Settings.setString(Settings.KEYS.PROXY_SERVER, proxy.getHost()); -718 Settings.setString(Settings.KEYS.PROXY_PORT, Integer.toString(proxy.getPort())); -719 final String userName = proxy.getUsername(); -720 final String password = proxy.getPassword(); -721 Settings.setStringIfNotNull(Settings.KEYS.PROXY_USERNAME, userName); -722 Settings.setStringIfNotNull(Settings.KEYS.PROXY_PASSWORD, password); -723 Settings.setStringIfNotNull(Settings.KEYS.PROXY_NON_PROXY_HOSTS, proxy.getNonProxyHosts()); -724 } -725 -726 Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout); -727 Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); -728 -729 //File Type Analyzer Settings -730 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled); -731 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled); -732 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled); -733 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled); -734 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); -735 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy); -736 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled); -737 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled); -738 Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions); -739 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); -740 -741 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, pyDistributionAnalyzerEnabled); -742 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, pyPackageAnalyzerEnabled); -743 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, rubygemsAnalyzerEnabled); -744 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, opensslAnalyzerEnabled); -745 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CMAKE_ENABLED, cmakeAnalyzerEnabled); -746 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, autoconfAnalyzerEnabled); -747 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, composerAnalyzerEnabled); -748 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, nodeAnalyzerEnabled); -749 -750 //Database configuration -751 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName); -752 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath); -753 Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString); -754 -755 if (databaseUser == null && databasePassword == null && serverId != null) { -756 final Server server = settingsXml.getServer(serverId); -757 if (server != null) { -758 databaseUser = server.getUsername(); -759 try { -760 //The following fix was copied from: -761 // https://github.com/bsorrentino/maven-confluence-plugin/blob/master/maven-confluence-reporting-plugin/src/main/java/org/bsc/maven/confluence/plugin/AbstractBaseConfluenceMojo.java -762 // -763 // FIX to resolve -764 // org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException: -765 // java.io.FileNotFoundException: ~/.settings-security.xml (No such file or directory) -766 // -767 if (securityDispatcher instanceof DefaultSecDispatcher) { -768 ((DefaultSecDispatcher) securityDispatcher).setConfigurationFile("~/.m2/settings-security.xml"); -769 } -770 -771 databasePassword = securityDispatcher.decrypt(server.getPassword()); -772 } catch (SecDispatcherException ex) { -773 if (ex.getCause() instanceof FileNotFoundException -774 || (ex.getCause() != null && ex.getCause().getCause() instanceof FileNotFoundException)) { -775 //maybe its not encrypted? -776 final String tmp = server.getPassword(); -777 if (tmp.startsWith("{") && tmp.endsWith("}")) { -778 getLog().error(String.format( -779 "Unable to decrypt the server password for server id '%s' in settings.xml%n\tCause: %s", -780 serverId, ex.getMessage())); -781 } else { -782 databasePassword = tmp; -783 } -784 } else { -785 getLog().error(String.format( -786 "Unable to decrypt the server password for server id '%s' in settings.xml%n\tCause: %s", -787 serverId, ex.getMessage())); -788 } -789 } -790 } else { -791 getLog().error(String.format("Server '%s' not found in the settings.xml file", serverId)); -792 } -793 } -794 -795 Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser); -796 Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword); -797 Settings.setStringIfNotEmpty(Settings.KEYS.DATA_DIRECTORY, dataDirectory); +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(); +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 +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."); +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 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified); -800 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified); -801 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base); -802 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base); -803 Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours); -804 -805 } -806 -807 /** -808 * Returns the maven proxy. -809 * -810 * @return the maven proxy -811 */ -812 private Proxy getMavenProxy() { -813 if (mavenSettings != null) { -814 final List<Proxy> proxies = mavenSettings.getProxies(); -815 if (proxies != null && !proxies.isEmpty()) { -816 if (mavenSettingsProxyId != null) { -817 for (Proxy proxy : proxies) { -818 if (mavenSettingsProxyId.equalsIgnoreCase(proxy.getId())) { -819 return proxy; -820 } -821 } -822 } else if (proxies.size() == 1) { -823 return proxies.get(0); -824 } else { -825 getLog().warn("Multiple proxy definitions exist in the Maven settings. In the dependency-check " -826 + "configuration set the mavenSettingsProxyId so that the correct proxy will be used."); -827 throw new IllegalStateException("Ambiguous proxy definition"); -828 } -829 } -830 } -831 return null; -832 } -833 -834 /** -835 * Tests is the artifact should be included in the scan (i.e. is the -836 * dependency in a scope that is being scanned). -837 * -838 * @param a the Artifact to test -839 * @return <code>true</code> if the artifact is in an excluded scope; -840 * otherwise <code>false</code> -841 */ -842 protected boolean excludeFromScan(Artifact a) { -843 if (skipTestScope && Artifact.SCOPE_TEST.equals(a.getScope())) { -844 return true; -845 } -846 if (skipProvidedScope && Artifact.SCOPE_PROVIDED.equals(a.getScope())) { -847 return true; -848 } -849 if (skipRuntimeScope && !Artifact.SCOPE_RUNTIME.equals(a.getScope())) { -850 return true; -851 } -852 return false; -853 } -854 -855 /** -856 * Returns a reference to the current project. This method is used instead -857 * of auto-binding the project via component annotation in concrete -858 * implementations of this. If the child has a -859 * <code>@Component MavenProject project;</code> defined then the abstract -860 * class (i.e. this class) will not have access to the current project (just -861 * the way Maven works with the binding). -862 * -863 * @return returns a reference to the current project -864 */ -865 protected MavenProject getProject() { -866 return project; -867 } -868 -869 /** -870 * Returns the list of Maven Projects in this build. -871 * -872 * @return the list of Maven Projects in this build -873 */ -874 protected List<MavenProject> getReactorProjects() { -875 return reactorProjects; -876 } +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 } +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 /** -879 * Returns the report format. -880 * -881 * @return the report format -882 */ -883 protected String getFormat() { -884 return format; -885 } -886 -887 /** -888 * Generates the reports for a given dependency-check engine. -889 * -890 * @param engine a dependency-check engine -891 * @param p the Maven project -892 * @param outputDir the directory path to write the report(s) -893 * @throws ReportException thrown if there is an error writing the report -894 */ -895 protected void writeReports(MavenEngine engine, MavenProject p, File outputDir) throws ReportException { -896 DatabaseProperties prop = null; -897 CveDB cve = null; -898 try { -899 cve = new CveDB(); -900 cve.open(); -901 prop = cve.getDatabaseProperties(); -902 } catch (DatabaseException ex) { -903 if (getLog().isDebugEnabled()) { -904 getLog().debug("Unable to retrieve DB Properties", ex); -905 } -906 } finally { -907 if (cve != null) { -908 cve.close(); -909 } -910 } -911 final ReportGenerator r = new ReportGenerator(p.getName(), engine.getDependencies(), engine.getAnalyzers(), prop); -912 try { -913 r.generateReports(outputDir.getAbsolutePath(), format); -914 } catch (ReportException ex) { -915 final String msg = String.format("Error generating the report for %s", p.getName()); -916 throw new ReportException(msg, ex); -917 } -918 -919 } -920 -921 //<editor-fold defaultstate="collapsed" desc="Methods to fail build or show summary"> -922 /** -923 * Checks to see if a vulnerability has been identified with a CVSS score -924 * that is above the threshold set in the configuration. -925 * -926 * @param dependencies the list of dependency objects -927 * @throws MojoFailureException thrown if a CVSS score is found that is -928 * higher then the threshold set -929 */ -930 protected void checkForFailure(List<Dependency> dependencies) throws MojoFailureException { -931 if (failBuildOnCVSS <= 10) { -932 final StringBuilder ids = new StringBuilder(); -933 for (Dependency d : dependencies) { -934 boolean addName = true; -935 for (Vulnerability v : d.getVulnerabilities()) { -936 if (v.getCvssScore() >= failBuildOnCVSS) { -937 if (addName) { -938 addName = false; -939 ids.append(NEW_LINE).append(d.getFileName()).append(": "); -940 ids.append(v.getName()); -941 } else { -942 ids.append(", ").append(v.getName()); +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 } +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 } -946 } -947 if (ids.length() > 0) { -948 final String msg = String.format("%n%nDependency-Check Failure:%n" -949 + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n" -950 + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString()); -951 throw new MojoFailureException(msg); +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 } -955 -956 /** -957 * Generates a warning message listing a summary of dependencies and their -958 * associated CPE and CVE entries. -959 * -960 * @param mp the Maven project for which the summary is shown -961 * @param dependencies a list of dependency objects -962 */ -963 protected void showSummary(MavenProject mp, List<Dependency> dependencies) { -964 if (showSummary) { -965 final StringBuilder summary = new StringBuilder(); -966 for (Dependency d : dependencies) { -967 boolean firstEntry = true; -968 final StringBuilder ids = new StringBuilder(); -969 for (Vulnerability v : d.getVulnerabilities()) { -970 if (firstEntry) { -971 firstEntry = false; -972 } else { -973 ids.append(", "); -974 } -975 ids.append(v.getName()); -976 } -977 if (ids.length() > 0) { -978 summary.append(d.getFileName()).append(" ("); -979 firstEntry = true; -980 for (Identifier id : d.getIdentifiers()) { -981 if (firstEntry) { -982 firstEntry = false; -983 } else { -984 summary.append(", "); -985 } -986 summary.append(id.getValue()); -987 } -988 summary.append(") : ").append(ids).append(NEW_LINE); -989 } -990 } -991 if (summary.length() > 0) { -992 final String msg = String.format("%n%n" + "One or more dependencies were identified with known vulnerabilities in %s:%n%n%s" -993 + "%n%nSee the dependency-check report for more details.%n%n", mp.getName(), summary.toString()); -994 getLog().warn(msg); -995 } -996 } -997 } -998 -999 //</editor-fold> -1000 //<editor-fold defaultstate="collapsed" desc="Methods to read/write the serialized data file"> +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 key used to store the path to the data file that is saved by -1003 * <code>writeDataFile()</code>. This key is used in the -1004 * <code>MavenProject.(set|get)ContextValue</code>. -1005 * -1006 * @return the key used to store the path to the data file -1007 */ -1008 protected String getDataFileContextKey() { -1009 return "dependency-check-path-" + dataFileName; -1010 } -1011 -1012 /** -1013 * Returns the key used to store the path to the output directory. When -1014 * generating the report in the <code>executeAggregateReport()</code> the -1015 * output directory should be obtained by using this key. -1016 * -1017 * @return the key used to store the path to the output directory -1018 */ -1019 protected String getOutputDirectoryContextKey() { -1020 return "dependency-output-dir-" + dataFileName; -1021 } -1022 -1023 /** -1024 * Writes the scan data to disk. This is used to serialize the scan data -1025 * between the "check" and "aggregate" phase. -1026 * -1027 * @param mp the mMven project for which the data file was created -1028 * @param writeTo the directory to write the data file -1029 * @param dependencies the list of dependencies to serialize -1030 */ -1031 protected void writeDataFile(MavenProject mp, File writeTo, List<Dependency> dependencies) { -1032 File file; -1033 //check to see if this was already written out -1034 if (mp.getContextValue(this.getDataFileContextKey()) == null) { -1035 if (writeTo == null) { -1036 file = new File(mp.getBuild().getDirectory()); -1037 file = new File(file, dataFileName); -1038 } else { -1039 file = new File(writeTo, dataFileName); -1040 } -1041 final File parent = file.getParentFile(); -1042 if (!parent.isDirectory() && !parent.mkdirs()) { -1043 getLog().error(String.format("Directory '%s' does not exist and cannot be created; unable to write data file.", -1044 parent.getAbsolutePath())); -1045 } -1046 -1047 ObjectOutputStream out = null; -1048 try { -1049 if (dependencies != null) { -1050 out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file))); -1051 out.writeObject(dependencies); -1052 } -1053 if (getLog().isDebugEnabled()) { -1054 getLog().debug(String.format("Serialized data file written to '%s' for %s, referenced by key %s", -1055 file.getAbsolutePath(), mp.getName(), this.getDataFileContextKey())); -1056 } -1057 mp.setContextValue(this.getDataFileContextKey(), file.getAbsolutePath()); -1058 } catch (IOException ex) { -1059 getLog().warn("Unable to create data file used for report aggregation; " -1060 + "if report aggregation is being used the results may be incomplete."); -1061 if (getLog().isDebugEnabled()) { -1062 getLog().debug(ex.getMessage(), ex); -1063 } -1064 } finally { -1065 if (out != null) { -1066 try { -1067 out.close(); -1068 } catch (IOException ex) { -1069 if (getLog().isDebugEnabled()) { -1070 getLog().debug("ignore", ex); -1071 } -1072 } -1073 } -1074 } -1075 } -1076 } -1077 -1078 /** -1079 * Reads the serialized scan data from disk. This is used to serialize the -1080 * scan data between the "check" and "aggregate" phase. -1081 * -1082 * @param project the Maven project to read the data file from -1083 * @return a <code>MavenEngine</code> object populated with dependencies if -1084 * the serialized data file exists; otherwise <code>null</code> is returned +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 List<Dependency> readDataFile(MavenProject project) { -1087 final Object oPath = project.getContextValue(this.getDataFileContextKey()); -1088 if (oPath == null) { -1089 return null; -1090 } -1091 List<Dependency> ret = null; -1092 final String path = (String) oPath; -1093 //ObjectInputStream ois = null; -1094 ExpectedOjectInputStream ois = null; -1095 try { -1096 //ois = new ObjectInputStream(new FileInputStream(path)); -1097 ois = new ExpectedOjectInputStream(new FileInputStream(path), -1098 "java.util.ArrayList", -1099 "java.util.HashSet", -1100 "java.util.TreeSet", -1101 "java.lang.AbstractSet", -1102 "java.lang.AbstractCollection", -1103 "java.lang.Enum", -1104 "org.owasp.dependencycheck.dependency.Confidence", -1105 "org.owasp.dependencycheck.dependency.Dependency", -1106 "org.owasp.dependencycheck.dependency.Evidence", -1107 "org.owasp.dependencycheck.dependency.EvidenceCollection", -1108 "org.owasp.dependencycheck.dependency.Identifier", -1109 "org.owasp.dependencycheck.dependency.Reference", -1110 "org.owasp.dependencycheck.dependency.Vulnerability", -1111 "org.owasp.dependencycheck.dependency.VulnerabilityComparator", -1112 "org.owasp.dependencycheck.dependency.VulnerableSoftware", -1113 "org.owasp.dependencycheck.data.cpe.IndexEntry"); -1114 @SuppressWarnings("unchecked") -1115 final List<Dependency> depList = (List<Dependency>) ois.readObject(); -1116 ret = depList; -1117 } catch (FileNotFoundException ex) { -1118 //TODO fix logging -1119 getLog().error("", ex); -1120 } catch (IOException ex) { -1121 getLog().error("", ex); -1122 } catch (ClassNotFoundException ex) { -1123 getLog().error("", ex); -1124 } finally { -1125 if (ois != null) { -1126 try { -1127 ois.close(); -1128 } catch (IOException ex) { -1129 getLog().error("", ex); -1130 } -1131 } -1132 } -1133 return ret; -1134 } -1135 //</editor-fold> -1136 } +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."); +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 }
    diff --git a/xref/org/owasp/dependencycheck/maven/CheckMojo.html b/xref/org/owasp/dependencycheck/maven/CheckMojo.html index d49a01f5d..4f9851398 100644 --- a/xref/org/owasp/dependencycheck/maven/CheckMojo.html +++ b/xref/org/owasp/dependencycheck/maven/CheckMojo.html @@ -63,7 +63,7 @@ 55 public boolean canGenerateReport() { 56 boolean isCapable = false; 57 for (Artifact a : getProject().getArtifacts()) { -58 if (!excludeFromScan(a)) { +58 if (!excludeFromScan(a.getScope())) { 59 isCapable = true; 60 break; 61 } @@ -96,76 +96,75 @@ 88 getLog().error(msg); 89 } 90 if (engine != null) { -91 scanArtifacts(getProject(), engine); +91 ExceptionCollection exCol = scanArtifacts(getProject(), engine); 92 if (engine.getDependencies().isEmpty()) { 93 getLog().info("No dependencies were identified that could be analyzed by dependency-check"); 94 } else { -95 ExceptionCollection exCol = null; -96 try { -97 engine.analyzeDependencies(); -98 } catch (ExceptionCollection ex) { -99 if (this.isFailOnError() && ex.isFatal()) { -100 throw new MojoExecutionException("One or more exceptions occured during analysis", ex); -101 } -102 exCol = ex; -103 } -104 if (exCol == null || !exCol.isFatal()) { -105 try { -106 writeReports(engine, getProject(), getCorrectOutputDirectory()); -107 } catch (ReportException ex) { -108 if (this.isFailOnError()) { -109 if (exCol != null) { -110 exCol.addException(ex); -111 } else { -112 exCol = new ExceptionCollection("Unable to write the dependency-check report", ex); -113 } -114 } -115 } -116 writeDataFile(getProject(), null, engine.getDependencies()); -117 showSummary(getProject(), engine.getDependencies()); -118 checkForFailure(engine.getDependencies()); -119 if (exCol != null && this.isFailOnError()) { -120 throw new MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol); -121 } -122 } -123 } -124 engine.cleanup(); -125 } -126 Settings.cleanup(); -127 } -128 -129 /** -130 * The name of the report in the site. -131 */ -132 @SuppressWarnings("CanBeFinal") -133 @Parameter(property = "name", defaultValue = "dependency-check", required = true) -134 private String name = "dependency-check"; -135 -136 /** -137 * Returns the report name. -138 * -139 * @param locale the location -140 * @return the report name -141 */ -142 @Override -143 public String getName(Locale locale) { -144 return name; -145 } -146 -147 /** -148 * Gets the description of the Dependency-Check report to be displayed in -149 * the Maven Generated Reports page. -150 * -151 * @param locale The Locale to get the description for -152 * @return the description -153 */ -154 @Override -155 public String getDescription(Locale locale) { -156 return "Generates a report providing details on any published vulnerabilities within project dependencies. " -157 + "This report is a best effort and may contain false positives and false negatives."; -158 } -159 -160 } +95 try { +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); +100 } +101 exCol = ex; +102 } +103 if (exCol == null || !exCol.isFatal()) { +104 try { +105 writeReports(engine, getProject(), getCorrectOutputDirectory()); +106 } catch (ReportException ex) { +107 if (this.isFailOnError()) { +108 if (exCol != null) { +109 exCol.addException(ex); +110 } else { +111 exCol = new ExceptionCollection("Unable to write the dependency-check report", ex); +112 } +113 } +114 } +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); +120 } +121 } +122 } +123 engine.cleanup(); +124 } +125 Settings.cleanup(); +126 } +127 +128 /** +129 * The name of the report in the site. +130 */ +131 @SuppressWarnings("CanBeFinal") +132 @Parameter(property = "name", defaultValue = "dependency-check", required = true) +133 private String name = "dependency-check"; +134 +135 /** +136 * Returns the report name. +137 * +138 * @param locale the location +139 * @return the report name +140 */ +141 @Override +142 public String getName(Locale locale) { +143 return name; +144 } +145 +146 /** +147 * Gets the description of the Dependency-Check report to be displayed in +148 * the Maven Generated Reports page. +149 * +150 * @param locale The Locale to get the description for +151 * @return the description +152 */ +153 @Override +154 public String getDescription(Locale locale) { +155 return "Generates a report providing details on any published vulnerabilities within project dependencies. " +156 + "This report is a best effort and may contain false positives and false negatives."; +157 } +158 +159 }
    diff --git a/xref/org/owasp/dependencycheck/maven/package-frame.html b/xref/org/owasp/dependencycheck/maven/package-frame.html index cd2155977..51cfc30b4 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.2 Reference Package org.owasp.dependencycheck.maven + Dependency-Check 1.4.3 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 5705d0756..7150b5b8f 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.2 Reference Package org.owasp.dependencycheck.maven + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.maven diff --git a/xref/org/owasp/dependencycheck/maven/slf4j/package-frame.html b/xref/org/owasp/dependencycheck/maven/slf4j/package-frame.html index ed4603c8a..52b080aa0 100644 --- a/xref/org/owasp/dependencycheck/maven/slf4j/package-frame.html +++ b/xref/org/owasp/dependencycheck/maven/slf4j/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.maven.slf4j + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.maven.slf4j diff --git a/xref/org/owasp/dependencycheck/maven/slf4j/package-summary.html b/xref/org/owasp/dependencycheck/maven/slf4j/package-summary.html index db02684a9..f9c384cb4 100644 --- a/xref/org/owasp/dependencycheck/maven/slf4j/package-summary.html +++ b/xref/org/owasp/dependencycheck/maven/slf4j/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference Package org.owasp.dependencycheck.maven.slf4j + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.maven.slf4j diff --git a/xref/org/owasp/dependencycheck/package-frame.html b/xref/org/owasp/dependencycheck/package-frame.html index 3efd2f233..42790602d 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.2 Reference Package org.owasp.dependencycheck + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck diff --git a/xref/org/owasp/dependencycheck/package-summary.html b/xref/org/owasp/dependencycheck/package-summary.html index 19284ef74..85a2b8438 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.2 Reference Package org.owasp.dependencycheck + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck diff --git a/xref/org/owasp/dependencycheck/reporting/package-frame.html b/xref/org/owasp/dependencycheck/reporting/package-frame.html index f0c8b99b2..1d597656d 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.2 Reference Package org.owasp.dependencycheck.reporting + Dependency-Check 1.4.3 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 7b6ff33b8..08c09f52c 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.2 Reference Package org.owasp.dependencycheck.reporting + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.reporting diff --git a/xref/org/owasp/dependencycheck/taskdefs/package-frame.html b/xref/org/owasp/dependencycheck/taskdefs/package-frame.html index fc4581800..a1e7231b0 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.2 Reference Package org.owasp.dependencycheck.taskdefs + Dependency-Check 1.4.3 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 96369986f..909fc4d45 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.2 Reference Package org.owasp.dependencycheck.taskdefs + Dependency-Check 1.4.3 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 d670894e2..1ca6881e7 100644 --- a/xref/org/owasp/dependencycheck/utils/Checksum.html +++ b/xref/org/owasp/dependencycheck/utils/Checksum.html @@ -66,11 +66,11 @@ 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 MessageDigest digest = MessageDigest.getInstance(algorithm); +61 final MessageDigest digest = MessageDigest.getInstance(algorithm); 62 FileInputStream fis = null; 63 try { 64 fis = new FileInputStream(file); -65 FileChannel ch = fis.getChannel(); +65 final FileChannel ch = fis.getChannel(); 66 long remainingToRead = file.length(); 67 long start = 0; 68 while (remainingToRead > 0) { @@ -82,7 +82,7 @@ 74 amountToRead = remainingToRead; 75 remainingToRead = 0; 76 } -77 MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, start, amountToRead); +77 final MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, start, amountToRead); 78 digest.update(byteBuffer); 79 start += amountToRead; 80 } @@ -107,7 +107,7 @@ 99 * @throws NoSuchAlgorithmException when the MD5 algorithm is not available 100 */ 101 public static String getMD5Checksum(File file) throws IOException, NoSuchAlgorithmException { -102 byte[] b = getChecksum("MD5", file); +102 final byte[] b = getChecksum("MD5", file); 103 return getHex(b); 104 } 105 @@ -120,7 +120,7 @@ 112 * @throws NoSuchAlgorithmException when the SHA1 algorithm is not available 113 */ 114 public static String getSHA1Checksum(File file) throws IOException, NoSuchAlgorithmException { -115 byte[] b = getChecksum("SHA1", file); +115 final byte[] b = getChecksum("SHA1", file); 116 return getHex(b); 117 } 118 /** diff --git a/xref/org/owasp/dependencycheck/utils/DependencyVersionUtil.html b/xref/org/owasp/dependencycheck/utils/DependencyVersionUtil.html index 786752621..8619c2cf6 100644 --- a/xref/org/owasp/dependencycheck/utils/DependencyVersionUtil.html +++ b/xref/org/owasp/dependencycheck/utils/DependencyVersionUtil.html @@ -32,78 +32,114 @@ 24 25 /** 26 * <p> -27 * A utility class to extract version numbers from file names (or other strings containing version numbers.</p> -28 * -29 * @author Jeremy Long -30 */ -31 public final class DependencyVersionUtil { -32 -33 /** -34 * Regular expression to extract version numbers from file names. -35 */ -36 private static final Pattern RX_VERSION = Pattern.compile("\\d+(\\.\\d{1,6})+(\\.?([_-](release|beta|alpha|\\d+)|[a-zA-Z_-]{1,3}\\d{0,8}))?"); -37 /** -38 * Regular expression to extract a single version number without periods. This is a last ditch effort just to check in case we -39 * are missing a version number using the previous regex. -40 */ -41 private static final Pattern RX_SINGLE_VERSION = Pattern.compile("\\d+(\\.?([_-](release|beta|alpha)|[a-zA-Z_-]{1,3}\\d{1,8}))?"); -42 -43 /** -44 * Private constructor for utility class. -45 */ -46 private DependencyVersionUtil() { -47 } -48 -49 /** -50 * <p> -51 * A utility class to extract version numbers from file names (or other strings containing version numbers.</p> -52 * <pre> -53 * Example: -54 * Give the file name: library-name-1.4.1r2-release.jar -55 * This function would return: 1.4.1.r2</pre> -56 * -57 * @param text the text being analyzed -58 * @return a DependencyVersion containing the version -59 */ -60 public static DependencyVersion parseVersion(String text) { -61 if (text == null) { -62 return null; -63 } -64 //'-' is a special case used within the CVE entries, just include it as the version. -65 if ("-".equals(text)) { -66 final DependencyVersion dv = new DependencyVersion(); -67 final List<String> list = new ArrayList<String>(); -68 list.add(text); -69 dv.setVersionParts(list); -70 return dv; -71 } -72 String version = null; -73 Matcher matcher = RX_VERSION.matcher(text); -74 if (matcher.find()) { -75 version = matcher.group(); -76 } -77 //throw away the results if there are two things that look like version numbers -78 if (matcher.find()) { -79 return null; -80 } -81 if (version == null) { -82 matcher = RX_SINGLE_VERSION.matcher(text); -83 if (matcher.find()) { -84 version = matcher.group(); -85 } else { -86 return null; -87 } -88 //throw away the results if there are two things that look like version numbers -89 if (matcher.find()) { -90 return null; -91 } -92 } -93 if (version != null && version.endsWith("-py2") && version.length() > 4) { -94 version = version.substring(0, version.length() - 4); -95 } -96 return new DependencyVersion(version); -97 } -98 } +27 * A utility class to extract version numbers from file names (or other strings +28 * containing version numbers.</p> +29 * +30 * @author Jeremy Long +31 */ +32 public final class DependencyVersionUtil { +33 +34 /** +35 * Regular expression to extract version numbers from file names. +36 */ +37 private static final Pattern RX_VERSION = Pattern.compile("\\d+(\\.\\d{1,6})+(\\.?([_-](release|beta|alpha|\\d+)|[a-zA-Z_-]{1,3}\\d{0,8}))?"); +38 /** +39 * Regular expression to extract a single version number without periods. +40 * This is a last ditch effort just to check in case we are missing a +41 * version number using the previous regex. +42 */ +43 private static final Pattern RX_SINGLE_VERSION = Pattern.compile("\\d+(\\.?([_-](release|beta|alpha)|[a-zA-Z_-]{1,3}\\d{1,8}))?"); +44 +45 /** +46 * Regular expression to extract the part before the version numbers if +47 * there are any based on RX_VERSION. In most cases, this part represents a +48 * more accurate name. +49 */ +50 private static final Pattern RX_PRE_VERSION = Pattern.compile("^(.+)[_-](\\d+\\.\\d{1,6})+"); +51 +52 /** +53 * Private constructor for utility class. +54 */ +55 private DependencyVersionUtil() { +56 } +57 +58 /** +59 * <p> +60 * A utility class to extract version numbers from file names (or other +61 * strings containing version numbers.</p> +62 * <pre> +63 * Example: +64 * Give the file name: library-name-1.4.1r2-release.jar +65 * This function would return: 1.4.1.r2</pre> +66 * +67 * @param text the text being analyzed +68 * @return a DependencyVersion containing the version +69 */ +70 public static DependencyVersion parseVersion(String text) { +71 if (text == null) { +72 return null; +73 } +74 //'-' is a special case used within the CVE entries, just include it as the version. +75 if ("-".equals(text)) { +76 final DependencyVersion dv = new DependencyVersion(); +77 final List<String> list = new ArrayList<String>(); +78 list.add(text); +79 dv.setVersionParts(list); +80 return dv; +81 } +82 String version = null; +83 Matcher matcher = RX_VERSION.matcher(text); +84 if (matcher.find()) { +85 version = matcher.group(); +86 } +87 //throw away the results if there are two things that look like version numbers +88 if (matcher.find()) { +89 return null; +90 } +91 if (version == null) { +92 matcher = RX_SINGLE_VERSION.matcher(text); +93 if (matcher.find()) { +94 version = matcher.group(); +95 } else { +96 return null; +97 } +98 //throw away the results if there are two things that look like version numbers +99 if (matcher.find()) { +100 return null; +101 } +102 } +103 if (version != null && version.endsWith("-py2") && version.length() > 4) { +104 version = version.substring(0, version.length() - 4); +105 } +106 return new DependencyVersion(version); +107 } +108 +109 /** +110 * <p> +111 * A utility class to extract the part before version numbers from file +112 * names (or other strings containing version numbers. In most cases, this +113 * part represents a more accurate name than the full file name.</p> +114 * <pre> +115 * Example: +116 * Give the file name: library-name-1.4.1r2-release.jar +117 * This function would return: library-name</pre> +118 * +119 * @param text the text being analyzed +120 * @return the part before the version numbers if any, otherwise return the +121 * text itself. +122 */ +123 public static String parsePreVersion(String text) { +124 if (parseVersion(text) == null) { +125 return text; +126 } +127 +128 final Matcher matcher = RX_PRE_VERSION.matcher(text); +129 if (matcher.find()) { +130 return matcher.group(1); +131 } +132 return text; +133 } +134 }
    diff --git a/xref/org/owasp/dependencycheck/utils/Downloader.html b/xref/org/owasp/dependencycheck/utils/Downloader.html index 1b5a46416..1be66e97c 100644 --- a/xref/org/owasp/dependencycheck/utils/Downloader.html +++ b/xref/org/owasp/dependencycheck/utils/Downloader.html @@ -308,11 +308,11 @@ 300 * @throws DownloadFailedException a wrapper exception that contains the 301 * original exception as the cause 302 */ -303 protected static void checkForCommonExceptionTypes(IOException ex) throws DownloadFailedException { +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 = String.format("Unable to resolve domain '%s'", cause.getMessage()); +307 final String msg = format("Unable to resolve domain '%s'", cause.getMessage()); 308 LOGGER.error(msg); 309 throw new DownloadFailedException(msg); 310 } diff --git a/xref/org/owasp/dependencycheck/utils/FileUtils.html b/xref/org/owasp/dependencycheck/utils/FileUtils.html index df9af50bb..3c7a93528 100644 --- a/xref/org/owasp/dependencycheck/utils/FileUtils.html +++ b/xref/org/owasp/dependencycheck/utils/FileUtils.html @@ -32,91 +32,92 @@ 24 import java.io.File; 25 import java.io.IOException; 26 import java.util.UUID; -27 -28 /** -29 * A collection of utilities for processing information about files. -30 * -31 * @author Jeremy Long -32 */ -33 public final class FileUtils { -34 -35 /** -36 * The logger. -37 */ -38 private static final Logger LOGGER = LoggerFactory.getLogger(FileUtils.class); -39 /** -40 * Bit bucket for non-Windows systems -41 */ -42 private static final String BIT_BUCKET_UNIX = "/dev/null"; -43 -44 /** -45 * Bit bucket for Windows systems (yes, only one 'L') -46 */ -47 private static final String BIT_BUCKET_WIN = "NUL"; -48 -49 /** -50 * Private constructor for a utility class. -51 */ -52 private FileUtils() { -53 } -54 -55 /** -56 * Returns the (lowercase) file extension for a specified file. -57 * -58 * @param fileName the file name to retrieve the file extension from. -59 * @return the file extension. -60 */ -61 public static String getFileExtension(String fileName) { -62 final String fileExt = FilenameUtils.getExtension(fileName); -63 return null == fileExt || fileExt.isEmpty() ? null : fileExt.toLowerCase(); -64 } -65 -66 /** -67 * Deletes a file. If the File is a directory it will recursively delete the contents. -68 * -69 * @param file the File to delete -70 * @return true if the file was deleted successfully, otherwise false -71 */ -72 public static boolean delete(File file) { -73 final boolean success = org.apache.commons.io.FileUtils.deleteQuietly(file); -74 if (!success) { -75 LOGGER.debug("Failed to delete file: {}; attempting to delete on exit.", file.getPath()); -76 file.deleteOnExit(); -77 } -78 return success; -79 } -80 -81 /** -82 * Generates a new temporary file name that is guaranteed to be unique. -83 * -84 * @param prefix the prefix for the file name to generate -85 * @param extension the extension of the generated file name -86 * @return a temporary File -87 * @throws java.io.IOException thrown if the temporary folder could not be created -88 */ -89 public static File getTempFile(String prefix, String extension) throws IOException { -90 final File dir = Settings.getTempDirectory(); -91 final String tempFileName = String.format("%s%s.%s", prefix, UUID.randomUUID().toString(), extension); -92 final File tempFile = new File(dir, tempFileName); -93 if (tempFile.exists()) { -94 return getTempFile(prefix, extension); -95 } -96 return tempFile; -97 } -98 -99 /** -100 * Return the bit bucket for the OS. '/dev/null' for Unix and 'NUL' for Windows -101 * -102 * @return a String containing the bit bucket -103 */ -104 public static String getBitBucket() { -105 if (System.getProperty("os.name").startsWith("Windows")) { -106 return BIT_BUCKET_WIN; -107 } else { -108 return BIT_BUCKET_UNIX; -109 } -110 } -111 } +27 import org.apache.commons.lang3.SystemUtils; +28 +29 /** +30 * A collection of utilities for processing information about files. +31 * +32 * @author Jeremy Long +33 */ +34 public final class FileUtils { +35 +36 /** +37 * The logger. +38 */ +39 private static final Logger LOGGER = LoggerFactory.getLogger(FileUtils.class); +40 /** +41 * Bit bucket for non-Windows systems +42 */ +43 private static final String BIT_BUCKET_UNIX = "/dev/null"; +44 +45 /** +46 * Bit bucket for Windows systems (yes, only one 'L') +47 */ +48 private static final String BIT_BUCKET_WIN = "NUL"; +49 +50 /** +51 * Private constructor for a utility class. +52 */ +53 private FileUtils() { +54 } +55 +56 /** +57 * Returns the (lowercase) file extension for a specified file. +58 * +59 * @param fileName the file name to retrieve the file extension from. +60 * @return the file extension. +61 */ +62 public static String getFileExtension(String fileName) { +63 final String fileExt = FilenameUtils.getExtension(fileName); +64 return null == fileExt || fileExt.isEmpty() ? null : fileExt.toLowerCase(); +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 }
    diff --git a/xref/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.html b/xref/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.html index 0c780ffa3..cd0018537 100644 --- a/xref/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.html +++ b/xref/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.html @@ -86,7 +86,7 @@ 78 */ 79 @Override 80 public String[] getDefaultCipherSuites() { -81 return Arrays.copyOf(ciphers, ciphers.length); +81 return sslCtxt.getSocketFactory().getDefaultCipherSuites(); 82 } 83 84 /** @@ -96,7 +96,7 @@ 88 */ 89 @Override 90 public String[] getSupportedCipherSuites() { -91 return Arrays.copyOf(ciphers, ciphers.length); +91 return sslCtxt.getSocketFactory().getSupportedCipherSuites(); 92 } 93 94 /** @@ -133,264 +133,168 @@ 125 final SSLSocket ss = (SSLSocket) factory.createSocket(s, host, port, autoClose); 126 127 ss.setEnabledProtocols(protocols); -128 ss.setEnabledCipherSuites(ciphers); -129 -130 return ss; -131 } -132 -133 /** -134 * Creates a new SSL Socket. -135 * -136 * @param address the address to connect to -137 * @param port the port number -138 * @param localAddress the local address -139 * @param localPort the local port -140 * @return the SSL Socket -141 * @throws IOException thrown if the creation fails -142 */ -143 @Override -144 public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { -145 final SSLSocketFactory factory = sslCtxt.getSocketFactory(); -146 final SSLSocket ss = (SSLSocket) factory.createSocket(address, port, localAddress, localPort); -147 -148 ss.setEnabledProtocols(protocols); -149 ss.setEnabledCipherSuites(ciphers); -150 -151 return ss; -152 } -153 -154 /** -155 * Creates a new SSL Socket. -156 * -157 * @param host the host to connect to -158 * @param port the port to connect to -159 * @param localHost the local host -160 * @param localPort the local port -161 * @return the SSL Socket -162 * @throws IOException thrown if the creation fails -163 */ -164 @Override -165 public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { -166 final SSLSocketFactory factory = sslCtxt.getSocketFactory(); -167 final SSLSocket ss = (SSLSocket) factory.createSocket(host, port, localHost, localPort); +128 +129 return ss; +130 } +131 +132 /** +133 * Creates a new SSL Socket. +134 * +135 * @param address the address to connect to +136 * @param port the port number +137 * @param localAddress the local address +138 * @param localPort the local port +139 * @return the SSL Socket +140 * @throws IOException thrown if the creation fails +141 */ +142 @Override +143 public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { +144 final SSLSocketFactory factory = sslCtxt.getSocketFactory(); +145 final SSLSocket ss = (SSLSocket) factory.createSocket(address, port, localAddress, localPort); +146 +147 ss.setEnabledProtocols(protocols); +148 +149 return ss; +150 } +151 +152 /** +153 * Creates a new SSL Socket. +154 * +155 * @param host the host to connect to +156 * @param port the port to connect to +157 * @param localHost the local host +158 * @param localPort the local port +159 * @return the SSL Socket +160 * @throws IOException thrown if the creation fails +161 */ +162 @Override +163 public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { +164 final SSLSocketFactory factory = sslCtxt.getSocketFactory(); +165 final SSLSocket ss = (SSLSocket) factory.createSocket(host, port, localHost, localPort); +166 +167 ss.setEnabledProtocols(protocols); 168 -169 ss.setEnabledProtocols(protocols); -170 ss.setEnabledCipherSuites(ciphers); +169 return ss; +170 } 171 -172 return ss; -173 } -174 -175 /** -176 * Creates a new SSL Socket. -177 * -178 * @param host the host to connect to -179 * @param port the port to connect to -180 * @return the SSL Socket -181 * @throws IOException thrown if the creation fails -182 */ -183 @Override -184 public Socket createSocket(InetAddress host, int port) throws IOException { -185 final SSLSocketFactory factory = sslCtxt.getSocketFactory(); -186 final SSLSocket ss = (SSLSocket) factory.createSocket(host, port); -187 -188 ss.setEnabledProtocols(protocols); -189 ss.setEnabledCipherSuites(ciphers); -190 -191 return ss; -192 } -193 -194 /** -195 * Creates a new SSL Socket. -196 * -197 * @param host the host to connect to -198 * @param port the port to connect to -199 * @return the SSL Socket -200 * @throws IOException thrown if the creation fails -201 */ -202 @Override -203 public Socket createSocket(String host, int port) throws IOException { -204 final SSLSocketFactory factory = sslCtxt.getSocketFactory(); -205 final SSLSocket ss = (SSLSocket) factory.createSocket(host, port); -206 -207 ss.setEnabledProtocols(protocols); -208 ss.setEnabledCipherSuites(ciphers); -209 -210 return ss; -211 } -212 -213 /** -214 * Initializes the SSL Socket Factory Extension. -215 * -216 * @param km the key managers -217 * @param tm the trust managers -218 * @param random the secure random number generator -219 * @throws NoSuchAlgorithmException thrown when an algorithm is not -220 * supported -221 * @throws KeyManagementException thrown if initialization fails -222 */ -223 private void initSSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random) -224 throws NoSuchAlgorithmException, KeyManagementException { -225 sslCtxt = SSLContext.getInstance("TLS"); -226 sslCtxt.init(km, tm, random); -227 -228 protocols = getProtocolList(); -229 ciphers = getCipherList(); -230 } -231 -232 /** -233 * Initializes the SSL Socket Factory Extension. -234 * -235 * @param ctx the SSL context -236 * @throws NoSuchAlgorithmException thrown when an algorithm is not -237 * supported -238 * @throws KeyManagementException thrown if initialization fails -239 */ -240 private void initSSLSocketFactoryEx(SSLContext ctx) -241 throws NoSuchAlgorithmException, KeyManagementException { -242 sslCtxt = ctx; -243 -244 protocols = getProtocolList(); -245 ciphers = getCipherList(); -246 } -247 -248 /** -249 * Returns the protocol list. -250 * -251 * @return the protocol list -252 */ -253 protected String[] getProtocolList() { -254 final String[] preferredProtocols = {"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"}; -255 String[] availableProtocols = null; -256 -257 SSLSocket socket = null; -258 -259 try { -260 final SSLSocketFactory factory = sslCtxt.getSocketFactory(); -261 socket = (SSLSocket) factory.createSocket(); -262 -263 availableProtocols = socket.getSupportedProtocols(); -264 Arrays.sort(availableProtocols); -265 } catch (Exception ex) { -266 LOGGER.debug("Error getting protocol list, using TLSv1", ex); -267 return new String[]{"TLSv1"}; -268 } finally { -269 if (socket != null) { -270 try { -271 socket.close(); -272 } catch (IOException ex) { -273 LOGGER.trace("Error closing socket", ex); -274 } +172 /** +173 * Creates a new SSL Socket. +174 * +175 * @param host the host to connect to +176 * @param port the port to connect to +177 * @return the SSL Socket +178 * @throws IOException thrown if the creation fails +179 */ +180 @Override +181 public Socket createSocket(InetAddress host, int port) throws IOException { +182 final SSLSocketFactory factory = sslCtxt.getSocketFactory(); +183 final SSLSocket ss = (SSLSocket) factory.createSocket(host, port); +184 +185 ss.setEnabledProtocols(protocols); +186 +187 return ss; +188 } +189 +190 /** +191 * Creates a new SSL Socket. +192 * +193 * @param host the host to connect to +194 * @param port the port to connect to +195 * @return the SSL Socket +196 * @throws IOException thrown if the creation fails +197 */ +198 @Override +199 public Socket createSocket(String host, int port) throws IOException { +200 final SSLSocketFactory factory = sslCtxt.getSocketFactory(); +201 final SSLSocket ss = (SSLSocket) factory.createSocket(host, port); +202 +203 ss.setEnabledProtocols(protocols); +204 +205 return ss; +206 } +207 +208 /** +209 * Initializes the SSL Socket Factory Extension. +210 * +211 * @param km the key managers +212 * @param tm the trust managers +213 * @param random the secure random number generator +214 * @throws NoSuchAlgorithmException thrown when an algorithm is not +215 * supported +216 * @throws KeyManagementException thrown if initialization fails +217 */ +218 private void initSSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random) +219 throws NoSuchAlgorithmException, KeyManagementException { +220 sslCtxt = SSLContext.getInstance("TLS"); +221 sslCtxt.init(km, tm, random); +222 +223 protocols = getProtocolList(); +224 } +225 +226 /** +227 * Initializes the SSL Socket Factory Extension. +228 * +229 * @param ctx the SSL context +230 * @throws NoSuchAlgorithmException thrown when an algorithm is not +231 * supported +232 * @throws KeyManagementException thrown if initialization fails +233 */ +234 private void initSSLSocketFactoryEx(SSLContext ctx) +235 throws NoSuchAlgorithmException, KeyManagementException { +236 sslCtxt = ctx; +237 protocols = getProtocolList(); +238 } +239 +240 /** +241 * Returns the protocol list. +242 * +243 * @return the protocol list +244 */ +245 protected String[] getProtocolList() { +246 final String[] preferredProtocols = {"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"}; +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 final List<String> aa = new ArrayList<String>(); -279 for (String preferredProtocol : preferredProtocols) { -280 final int idx = Arrays.binarySearch(availableProtocols, preferredProtocol); -281 if (idx >= 0) { -282 aa.add(preferredProtocol); -283 } -284 } -285 -286 return aa.toArray(new String[0]); -287 } -288 -289 /** -290 * Returns the cipher list. -291 * -292 * @return the cipher list -293 */ -294 protected String[] getCipherList() { -295 final String[] preferredCiphers = { -296 // *_CHACHA20_POLY1305 are 3x to 4x faster than existing cipher suites. -297 // http://googleonlinesecurity.blogspot.com/2014/04/speeding-up-and-strengthening-https.html -298 // Use them if available. Normative names can be found at (TLS spec depends on IPSec spec): -299 // http://tools.ietf.org/html/draft-nir-ipsecme-chacha20-poly1305-01 -300 // http://tools.ietf.org/html/draft-mavrogiannopoulos-chacha-tls-02 -301 "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", -302 "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", -303 "TLS_ECDHE_ECDSA_WITH_CHACHA20_SHA", -304 "TLS_ECDHE_RSA_WITH_CHACHA20_SHA", -305 "TLS_DHE_RSA_WITH_CHACHA20_POLY1305", -306 "TLS_RSA_WITH_CHACHA20_POLY1305", -307 "TLS_DHE_RSA_WITH_CHACHA20_SHA", -308 "TLS_RSA_WITH_CHACHA20_SHA", -309 // Done with bleeding edge, back to TLS v1.2 and below -310 "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", -311 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", -312 "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", -313 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", -314 "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", -315 "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", -316 "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", -317 "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", -318 // TLS v1.0 (with some SSLv3 interop) -319 "TLS_DHE_RSA_WITH_AES_256_CBC_SHA384", -320 "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256", -321 "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", -322 "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", -323 "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", -324 "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", -325 "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA", -326 "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA", -327 // RSA key transport sucks, but they are needed as a fallback. -328 // For example, microsoft.com fails under all versions of TLS -329 // if they are not included. If only TLS 1.0 is available at -330 // the client, then google.com will fail too. TLS v1.3 is -331 // trying to deprecate them, so it will be interesteng to see -332 // what happens. -333 "TLS_RSA_WITH_AES_256_CBC_SHA256", -334 "TLS_RSA_WITH_AES_256_CBC_SHA", -335 "TLS_RSA_WITH_AES_128_CBC_SHA256", -336 "TLS_RSA_WITH_AES_128_CBC_SHA", -337 }; -338 -339 String[] availableCiphers; -340 -341 try { -342 final SSLSocketFactory factory = sslCtxt.getSocketFactory(); -343 availableCiphers = factory.getSupportedCipherSuites(); -344 Arrays.sort(availableCiphers); -345 } catch (Exception e) { -346 LOGGER.debug("Error retrieving ciphers", e); -347 return new String[]{ -348 "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", -349 "TLS_DHE_DSS_WITH_AES_256_CBC_SHA", -350 "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", -351 "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", -352 "TLS_RSA_WITH_AES_256_CBC_SHA256", -353 "TLS_RSA_WITH_AES_256_CBC_SHA", -354 "TLS_RSA_WITH_AES_128_CBC_SHA256", -355 "TLS_RSA_WITH_AES_128_CBC_SHA", -356 "TLS_EMPTY_RENEGOTIATION_INFO_SCSV", -357 }; -358 } -359 -360 final List<String> aa = new ArrayList<String>(); -361 for (String preferredCipher : preferredCiphers) { -362 final int idx = Arrays.binarySearch(availableCiphers, preferredCipher); -363 if (idx >= 0) { -364 aa.add(preferredCipher); -365 } -366 } -367 -368 aa.add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV"); -369 -370 return aa.toArray(new String[0]); -371 } -372 -373 /** -374 * The SSL context. -375 */ -376 private SSLContext sslCtxt; -377 /** -378 * The cipher suites. -379 */ -380 private String[] ciphers; -381 /** -382 * The protocols. -383 */ -384 private String[] protocols; -385 } +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 }
    diff --git a/xref/org/owasp/dependencycheck/utils/Settings.html b/xref/org/owasp/dependencycheck/utils/Settings.html index 3dddd026c..db25a5eb5 100644 --- a/xref/org/owasp/dependencycheck/utils/Settings.html +++ b/xref/org/owasp/dependencycheck/utils/Settings.html @@ -63,7 +63,7 @@ 55 /** 56 * The key to obtain the application name. 57 */ -58 public static final String APPLICATION_VAME = "application.name"; +58 public static final String APPLICATION_NAME = "application.name"; 59 /** 60 * The key to obtain the application version. 61 */ @@ -297,640 +297,648 @@ 289 */ 290 public static final String ANALYZER_OPENSSL_ENABLED = "analyzer.openssl.enabled"; 291 /** -292 * The properties key for the Central search URL. +292 * The properties key for whether the cocoapods analyzer is enabled. 293 */ -294 public static final String ANALYZER_CENTRAL_URL = "analyzer.central.url"; +294 public static final String ANALYZER_COCOAPODS_ENABLED = "analyzer.cocoapods.enabled"; 295 /** -296 * The path to mono, if available. +296 * The properties key for whether the SWIFT package manager analyzer is enabled. 297 */ -298 public static final String ANALYZER_ASSEMBLY_MONO_PATH = "analyzer.assembly.mono.path"; +298 public static final String ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED = "analyzer.swift.package.manager.enabled"; 299 /** -300 * The path to bundle-audit, if available. +300 * The properties key for the Central search URL. 301 */ -302 public static final String ANALYZER_BUNDLE_AUDIT_PATH = "analyzer.bundle.audit.path"; +302 public static final String ANALYZER_CENTRAL_URL = "analyzer.central.url"; 303 /** -304 * The additional configured zip file extensions, if available. +304 * The path to mono, if available. 305 */ -306 public static final String ADDITIONAL_ZIP_EXTENSIONS = "extensions.zip"; +306 public static final String ANALYZER_ASSEMBLY_MONO_PATH = "analyzer.assembly.mono.path"; 307 /** -308 * The key to obtain the path to the VFEED data file. +308 * The path to bundle-audit, if available. 309 */ -310 public static final String VFEED_DATA_FILE = "vfeed.data_file"; +310 public static final String ANALYZER_BUNDLE_AUDIT_PATH = "analyzer.bundle.audit.path"; 311 /** -312 * The key to obtain the VFEED connection string. +312 * The additional configured zip file extensions, if available. 313 */ -314 public static final String VFEED_CONNECTION_STRING = "vfeed.connection_string"; -315 -316 /** -317 * The key to obtain the base download URL for the VFeed data file. -318 */ -319 public static final String VFEED_DOWNLOAD_URL = "vfeed.download_url"; -320 /** -321 * The key to obtain the download file name for the VFeed data. -322 */ -323 public static final String VFEED_DOWNLOAD_FILE = "vfeed.download_file"; +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 VFeed update status. +325 * The key to obtain the base download URL for the VFeed data file. 326 */ -327 public static final String VFEED_UPDATE_STATUS = "vfeed.update_status"; -328 -329 /** -330 * The HTTP request method for query last modified date. -331 */ -332 public static final String DOWNLOADER_QUICK_QUERY_TIMESTAMP = "downloader.quick.query.timestamp"; -333 } -334 //</editor-fold> -335 -336 /** -337 * The logger. -338 */ -339 private static final Logger LOGGER = LoggerFactory.getLogger(Settings.class); -340 /** -341 * The properties file location. -342 */ -343 private static final String PROPERTIES_FILE = "dependencycheck.properties"; +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 * Thread local settings. +345 * The logger. 346 */ -347 private static final ThreadLocal<Settings> LOCAL_SETTINGS = new ThreadLocal<Settings>(); +347 private static final Logger LOGGER = LoggerFactory.getLogger(Settings.class); 348 /** -349 * The properties. +349 * The properties file location. 350 */ -351 private Properties props = null; -352 -353 /** -354 * Private constructor for the Settings class. This class loads the -355 * properties files. -356 * -357 * @param propertiesFilePath the path to the base properties file to load +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 Settings(String propertiesFilePath) { -360 InputStream in = null; -361 props = new Properties(); -362 try { -363 in = this.getClass().getClassLoader().getResourceAsStream(propertiesFilePath); -364 props.load(in); -365 } catch (IOException ex) { -366 LOGGER.error("Unable to load default settings."); -367 LOGGER.debug("", ex); -368 } finally { -369 if (in != null) { -370 try { -371 in.close(); -372 } catch (IOException ex) { -373 LOGGER.trace("", ex); -374 } -375 } -376 } -377 logProperties("Properties loaded", props); -378 } -379 -380 /** -381 * Initializes the thread local settings object. Note, to use the settings -382 * object you must call this method. However, you must also call -383 * Settings.cleanup() to properly release resources. -384 */ -385 public static void initialize() { -386 LOCAL_SETTINGS.set(new Settings(PROPERTIES_FILE)); -387 } -388 -389 /** -390 * Initializes the thread local settings object. Note, to use the settings -391 * object you must call this method. However, you must also call -392 * Settings.cleanup() to properly release resources. -393 * -394 * @param propertiesFilePath the path to the base properties file to load -395 */ -396 public static void initialize(String propertiesFilePath) { -397 LOCAL_SETTINGS.set(new Settings(propertiesFilePath)); -398 } -399 -400 /** -401 * Cleans up resources to prevent memory leaks. -402 * +359 private Properties props = null; +360 +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 cleanup() { -405 cleanup(true); +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 * -411 * @param deleteTemporary flag indicating whether any temporary directories -412 * generated should be removed -413 */ -414 public static void cleanup(boolean deleteTemporary) { -415 if (deleteTemporary && tempDirectory != null && tempDirectory.exists()) { -416 FileUtils.delete(tempDirectory); -417 if (tempDirectory.exists()) { -418 try { -419 Thread.sleep(2000); -420 } catch (InterruptedException ex) { -421 LOGGER.trace("ignore", ex); -422 } -423 FileUtils.delete(tempDirectory); -424 } -425 } -426 try { -427 LOCAL_SETTINGS.remove(); -428 } catch (Throwable ex) { -429 LOGGER.debug("Error cleaning up Settings", ex); -430 } -431 } -432 -433 /** -434 * Gets the underlying instance of the Settings object. -435 * -436 * @return the Settings object -437 */ -438 public static Settings getInstance() { -439 return LOCAL_SETTINGS.get(); -440 } -441 -442 /** -443 * Sets the instance of the Settings object to use in this thread. -444 * -445 * @param instance the instance of the settings object to use in this thread -446 */ -447 public static void setInstance(Settings instance) { -448 LOCAL_SETTINGS.set(instance); -449 } -450 -451 /** -452 * Logs the properties. This will not log any properties that contain -453 * 'password' in the key. -454 * -455 * @param header the header to print with the log message -456 * @param properties the properties to log -457 */ -458 private static void logProperties(String header, Properties properties) { -459 if (LOGGER.isDebugEnabled()) { -460 final StringWriter sw = new StringWriter(); -461 PrintWriter pw = null; -462 try { -463 pw = new PrintWriter(sw); -464 pw.format("%s:%n%n", header); -465 final Enumeration<?> e = properties.propertyNames(); -466 while (e.hasMoreElements()) { -467 final String key = (String) e.nextElement(); -468 if (key.contains("password")) { -469 pw.format("%s='*****'%n", key); -470 } else { -471 final String value = properties.getProperty(key); -472 if (value != null) { -473 pw.format("%s='%s'%n", key, value); -474 } -475 } -476 } -477 pw.flush(); -478 LOGGER.debug(sw.toString()); -479 } finally { -480 if (pw != null) { -481 pw.close(); -482 } -483 } -484 -485 } -486 } -487 -488 /** -489 * Sets a property value. -490 * -491 * @param key the key for the property -492 * @param value the value for the property -493 */ -494 public static void setString(String key, String value) { -495 LOCAL_SETTINGS.get().props.setProperty(key, value); -496 LOGGER.debug("Setting: {}='{}'", key, value); -497 } -498 -499 /** -500 * Sets a property value only if the value is not null. -501 * -502 * @param key the key for the property -503 * @param value the value for the property -504 */ -505 public static void setStringIfNotNull(String key, String value) { -506 if (null != value) { -507 setString(key, value); -508 } -509 } -510 -511 /** -512 * Sets a property value only if the value is not null and not empty. -513 * -514 * @param key the key for the property -515 * @param value the value for the property -516 */ -517 public static void setStringIfNotEmpty(String key, String value) { -518 if (null != value && !value.isEmpty()) { -519 setString(key, value); -520 } -521 } -522 -523 /** -524 * Sets a property value. -525 * -526 * @param key the key for the property -527 * @param value the value for the property -528 */ -529 public static void setBoolean(String key, boolean value) { -530 setString(key, Boolean.toString(value)); -531 } -532 -533 /** -534 * Sets a property value only if the value is not null. -535 * -536 * @param key the key for the property -537 * @param value the value for the property -538 */ -539 public static void setBooleanIfNotNull(String key, Boolean value) { -540 if (null != value) { -541 setBoolean(key, value); -542 } -543 } -544 -545 /** -546 * Sets a property value. -547 * -548 * @param key the key for the property -549 * @param value the value for the property -550 */ -551 public static void setInt(String key, int value) { -552 LOCAL_SETTINGS.get().props.setProperty(key, String.valueOf(value)); -553 LOGGER.debug("Setting: {}='{}'", key, value); -554 } -555 -556 /** -557 * Sets a property value only if the value is not null. -558 * -559 * @param key the key for the property -560 * @param value the value for the property -561 */ -562 public static void setIntIfNotNull(String key, Integer value) { -563 if (null != value) { -564 setInt(key, value); -565 } -566 } -567 -568 /** -569 * Merges a new properties file into the current properties. This method -570 * allows for the loading of a user provided properties file.<br><br> -571 * <b>Note</b>: even if using this method - system properties will be loaded -572 * before properties loaded from files. -573 * -574 * @param filePath the path to the properties file to merge. -575 * @throws FileNotFoundException is thrown when the filePath points to a -576 * non-existent file -577 * @throws IOException is thrown when there is an exception loading/merging -578 * the properties -579 */ -580 public static void mergeProperties(File filePath) throws FileNotFoundException, IOException { -581 FileInputStream fis = null; -582 try { -583 fis = new FileInputStream(filePath); -584 mergeProperties(fis); -585 } finally { -586 if (fis != null) { -587 try { -588 fis.close(); -589 } catch (IOException ex) { -590 LOGGER.trace("close error", ex); -591 } -592 } -593 } -594 } -595 -596 /** -597 * Merges a new properties file into the current properties. This method -598 * allows for the loading of a user provided properties file.<br><br> -599 * Note: even if using this method - system properties will be loaded before -600 * properties loaded from files. -601 * -602 * @param filePath the path to the properties file to merge. -603 * @throws FileNotFoundException is thrown when the filePath points to a -604 * non-existent file -605 * @throws IOException is thrown when there is an exception loading/merging -606 * the properties -607 */ -608 public static void mergeProperties(String filePath) throws FileNotFoundException, IOException { -609 FileInputStream fis = null; -610 try { -611 fis = new FileInputStream(filePath); -612 mergeProperties(fis); -613 } finally { -614 if (fis != null) { -615 try { -616 fis.close(); -617 } catch (IOException ex) { -618 LOGGER.trace("close error", ex); -619 } -620 } -621 } -622 } -623 -624 /** -625 * Merges a new properties file into the current properties. This method -626 * allows for the loading of a user provided properties file.<br><br> -627 * <b>Note</b>: even if using this method - system properties will be loaded -628 * before properties loaded from files. -629 * -630 * @param stream an Input Stream pointing at a properties file to merge -631 * @throws IOException is thrown when there is an exception loading/merging -632 * the properties -633 */ -634 public static void mergeProperties(InputStream stream) throws IOException { -635 LOCAL_SETTINGS.get().props.load(stream); -636 logProperties("Properties updated via merge", LOCAL_SETTINGS.get().props); -637 } -638 -639 /** -640 * Returns a value from the properties file as a File object. If the value -641 * was specified as a system property or passed in via the -Dprop=value -642 * argument - this method will return the value from the system properties -643 * before the values in the contained configuration file. -644 * -645 * @param key the key to lookup within the properties file -646 * @return the property from the properties file converted to a File object -647 */ -648 public static File getFile(String key) { -649 final String file = getString(key); -650 if (file == null) { -651 return null; -652 } -653 return new File(file); -654 } -655 -656 /** -657 * Returns a value from the properties file as a File object. If the value -658 * was specified as a system property or passed in via the -Dprop=value -659 * argument - this method will return the value from the system properties -660 * before the values in the contained configuration file. -661 * -662 * This method will check the configured base directory and will use this as -663 * the base of the file path. Additionally, if the base directory begins -664 * with a leading "[JAR]\" sequence with the path to the folder containing -665 * the JAR file containing this class. -666 * -667 * @param key the key to lookup within the properties file -668 * @return the property from the properties file converted to a File object -669 */ -670 protected static File getDataFile(String key) { -671 final String file = getString(key); -672 LOGGER.debug("Settings.getDataFile() - file: '{}'", file); -673 if (file == null) { -674 return null; -675 } -676 if (file.startsWith("[JAR]")) { -677 LOGGER.debug("Settings.getDataFile() - transforming filename"); -678 final File jarPath = getJarPath(); -679 LOGGER.debug("Settings.getDataFile() - jar file: '{}'", jarPath.toString()); -680 final File retVal = new File(jarPath, file.substring(6)); -681 LOGGER.debug("Settings.getDataFile() - returning: '{}'", retVal.toString()); -682 return retVal; +411 */ +412 public static void cleanup() { +413 cleanup(true); +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 return new File(file); -685 } -686 -687 /** -688 * Attempts to retrieve the folder containing the Jar file containing the -689 * Settings class. -690 * -691 * @return a File object -692 */ -693 private static File getJarPath() { -694 final String jarPath = Settings.class.getProtectionDomain().getCodeSource().getLocation().getPath(); -695 String decodedPath = "."; -696 try { -697 decodedPath = URLDecoder.decode(jarPath, "UTF-8"); -698 } catch (UnsupportedEncodingException ex) { -699 LOGGER.trace("", ex); -700 } -701 -702 final File path = new File(decodedPath); -703 if (path.getName().toLowerCase().endsWith(".jar")) { -704 return path.getParentFile(); -705 } else { -706 return new File("."); -707 } -708 } +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 /** -711 * Returns a value from the properties file. If the value was specified as a -712 * system property or passed in via the -Dprop=value argument - this method -713 * will return the value from the system properties before the values in the -714 * contained configuration file. -715 * -716 * @param key the key to lookup within the properties file -717 * @param defaultValue the default value for the requested property -718 * @return the property from the properties file -719 */ -720 public static String getString(String key, String defaultValue) { -721 final String str = System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key, defaultValue)); -722 return str; -723 } -724 -725 /** -726 * A reference to the temporary directory; used incase it needs to be -727 * deleted during cleanup. -728 */ -729 private static File tempDirectory = null; -730 -731 /** -732 * Returns the temporary directory. -733 * -734 * @return the temporary directory -735 * @throws java.io.IOException thrown if the temporary directory does not -736 * exist and cannot be created -737 */ -738 public static File getTempDirectory() throws IOException { -739 final File tmpDir = new File(Settings.getString(Settings.KEYS.TEMP_DIRECTORY, System.getProperty("java.io.tmpdir")), "dctemp"); -740 if (!tmpDir.exists() && !tmpDir.mkdirs()) { -741 final String msg = String.format("Unable to make a temporary folder '%s'", tmpDir.getPath()); -742 throw new IOException(msg); -743 } -744 tempDirectory = tmpDir; -745 return tmpDir; -746 } -747 -748 /** -749 * Returns a value from the properties file. If the value was specified as a -750 * system property or passed in via the -Dprop=value argument - this method -751 * will return the value from the system properties before the values in the -752 * contained configuration file. -753 * -754 * @param key the key to lookup within the properties file -755 * @return the property from the properties file -756 */ -757 public static String getString(String key) { -758 return System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key)); -759 } -760 -761 /** -762 * Removes a property from the local properties collection. This is mainly -763 * used in test cases. -764 * -765 * @param key the property key to remove -766 */ -767 public static void removeProperty(String key) { -768 LOCAL_SETTINGS.get().props.remove(key); -769 } -770 -771 /** -772 * Returns an int value from the properties file. If the value was specified -773 * as a system property or passed in via the -Dprop=value argument - this -774 * method will return the value from the system properties before the values -775 * in the contained configuration file. -776 * -777 * @param key the key to lookup within the properties file -778 * @return the property from the properties file -779 * @throws InvalidSettingException is thrown if there is an error retrieving -780 * the setting -781 */ -782 public static int getInt(String key) throws InvalidSettingException { -783 try { -784 return Integer.parseInt(Settings.getString(key)); -785 } catch (NumberFormatException ex) { -786 throw new InvalidSettingException("Could not convert property '" + key + "' to an int.", ex); -787 } -788 } -789 -790 /** -791 * Returns an int value from the properties file. If the value was specified -792 * as a system property or passed in via the -Dprop=value argument - this -793 * method will return the value from the system properties before the values -794 * in the contained configuration file. -795 * -796 * @param key the key to lookup within the properties file -797 * @param defaultValue the default value to return -798 * @return the property from the properties file or the defaultValue if the -799 * property does not exist or cannot be converted to an integer -800 */ -801 public static int getInt(String key, int defaultValue) { -802 int value; -803 try { -804 value = Integer.parseInt(Settings.getString(key)); -805 } catch (NumberFormatException ex) { -806 if (!Settings.getString(key, "").isEmpty()) { -807 LOGGER.debug("Could not convert property '{}={}' to an int; using {} instead.", key, Settings.getString(key), defaultValue); -808 } -809 value = defaultValue; -810 } -811 return value; -812 } -813 -814 /** -815 * Returns a long value from the properties file. If the value was specified -816 * as a system property or passed in via the -Dprop=value argument - this -817 * method will return the value from the system properties before the values -818 * in the contained configuration file. -819 * -820 * @param key the key to lookup within the properties file -821 * @return the property from the properties file -822 * @throws InvalidSettingException is thrown if there is an error retrieving -823 * the setting -824 */ -825 public static long getLong(String key) throws InvalidSettingException { -826 try { -827 return Long.parseLong(Settings.getString(key)); -828 } catch (NumberFormatException ex) { -829 throw new InvalidSettingException("Could not convert property '" + key + "' to a long.", ex); -830 } -831 } -832 -833 /** -834 * Returns a boolean value from the properties file. If the value was -835 * specified as a system property or passed in via the -836 * <code>-Dprop=value</code> argument this method will return the value from -837 * the system properties before the values in the contained configuration -838 * file. -839 * -840 * @param key the key to lookup within the properties file -841 * @return the property from the properties file -842 * @throws InvalidSettingException is thrown if there is an error retrieving -843 * the setting -844 */ -845 public static boolean getBoolean(String key) throws InvalidSettingException { -846 return Boolean.parseBoolean(Settings.getString(key)); -847 } -848 -849 /** -850 * Returns a boolean value from the properties file. If the value was -851 * specified as a system property or passed in via the -852 * <code>-Dprop=value</code> argument this method will return the value from -853 * the system properties before the values in the contained configuration -854 * file. -855 * -856 * @param key the key to lookup within the properties file -857 * @param defaultValue the default value to return if the setting does not -858 * exist -859 * @return the property from the properties file -860 * @throws InvalidSettingException is thrown if there is an error retrieving -861 * the setting -862 */ -863 public static boolean getBoolean(String key, boolean defaultValue) throws InvalidSettingException { -864 return Boolean.parseBoolean(Settings.getString(key, Boolean.toString(defaultValue))); -865 } -866 -867 /** -868 * Returns a connection string from the configured properties. If the -869 * connection string contains a %s, this method will determine the 'data' -870 * directory and replace the %s with the path to the data directory. If the -871 * data directory does not exists it will be created. -872 * -873 * @param connectionStringKey the property file key for the connection -874 * string -875 * @param dbFileNameKey the settings key for the db filename -876 * @return the connection string -877 * @throws IOException thrown the data directory cannot be created -878 * @throws InvalidSettingException thrown if there is an invalid setting -879 */ -880 public static String getConnectionString(String connectionStringKey, String dbFileNameKey) -881 throws IOException, InvalidSettingException { -882 final String connStr = Settings.getString(connectionStringKey); -883 if (connStr == null) { -884 final String msg = String.format("Invalid properties file; %s is missing.", connectionStringKey); -885 throw new InvalidSettingException(msg); -886 } -887 if (connStr.contains("%s")) { -888 final File directory = getDataDirectory(); -889 String fileName = null; -890 if (dbFileNameKey != null) { -891 fileName = Settings.getString(dbFileNameKey); -892 } -893 if (fileName == null) { -894 final String msg = String.format("Invalid properties file to get a file based connection string; '%s' must be defined.", -895 dbFileNameKey); -896 throw new InvalidSettingException(msg); -897 } -898 if (connStr.startsWith("jdbc:h2:file:") && fileName.endsWith(".h2.db")) { -899 fileName = fileName.substring(0, fileName.length() - 6); +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); +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 // yes, for H2 this path won't actually exists - but this is sufficient to get the value needed -902 final File dbFile = new File(directory, fileName); -903 final String cString = String.format(connStr, dbFile.getCanonicalPath()); -904 LOGGER.debug("Connection String: '{}'", cString); -905 return cString; -906 } -907 return connStr; -908 } -909 -910 /** -911 * Retrieves the directory that the JAR file exists in so that we can ensure -912 * we always use a common data directory for the embedded H2 database. This -913 * is public solely for some unit tests; otherwise this should be private. -914 * -915 * @return the data directory to store data files -916 * @throws IOException is thrown if an IOException occurs of course... -917 */ -918 public static File getDataDirectory() throws IOException { -919 final File path = Settings.getDataFile(Settings.KEYS.DATA_DIRECTORY); -920 if (path.exists() || path.mkdirs()) { -921 return path; -922 } -923 throw new IOException(String.format("Unable to create the data directory '%s'", path.getAbsolutePath())); -924 } -925 } +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 }
    diff --git a/xref/org/owasp/dependencycheck/utils/URLConnectionFactory.html b/xref/org/owasp/dependencycheck/utils/URLConnectionFactory.html index f38bcbe57..cbb6a4306 100644 --- a/xref/org/owasp/dependencycheck/utils/URLConnectionFactory.html +++ b/xref/org/owasp/dependencycheck/utils/URLConnectionFactory.html @@ -36,180 +36,181 @@ 28 import java.net.Proxy; 29 import java.net.SocketAddress; 30 import java.net.URL; -31 import java.security.KeyManagementException; -32 import java.security.NoSuchAlgorithmException; -33 import javax.net.ssl.HttpsURLConnection; -34 import org.slf4j.Logger; -35 import org.slf4j.LoggerFactory; -36 -37 /** -38 * A URLConnection Factory to create new connections. This encapsulates several -39 * configuration checks to ensure that the connection uses the correct proxy -40 * settings. -41 * -42 * @author Jeremy Long -43 */ -44 public final class URLConnectionFactory { -45 -46 /** -47 * The logger. -48 */ -49 private static final Logger LOGGER = LoggerFactory.getLogger(URLConnectionFactory.class); -50 -51 /** -52 * Private constructor for this factory. -53 */ -54 private URLConnectionFactory() { -55 } -56 -57 /** -58 * Utility method to create an HttpURLConnection. If the application is -59 * configured to use a proxy this method will retrieve the proxy settings -60 * and use them when setting up the connection. -61 * -62 * @param url the url to connect to -63 * @return an HttpURLConnection -64 * @throws URLConnectionFailureException thrown if there is an exception -65 */ -66 @SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE", justification = "Just being extra safe") -67 public static HttpURLConnection createHttpURLConnection(URL url) throws URLConnectionFailureException { -68 HttpURLConnection conn = null; -69 final String proxyUrl = Settings.getString(Settings.KEYS.PROXY_SERVER); -70 -71 try { -72 if (proxyUrl != null && !matchNonProxy(url)) { -73 final int proxyPort = Settings.getInt(Settings.KEYS.PROXY_PORT); -74 final SocketAddress address = new InetSocketAddress(proxyUrl, proxyPort); -75 -76 final String username = Settings.getString(Settings.KEYS.PROXY_USERNAME); -77 final String password = Settings.getString(Settings.KEYS.PROXY_PASSWORD); -78 -79 if (username != null && password != null) { -80 final Authenticator auth = new Authenticator() { -81 @Override -82 public PasswordAuthentication getPasswordAuthentication() { -83 if (getRequestorType().equals(Authenticator.RequestorType.PROXY)) { -84 return new PasswordAuthentication(username, password.toCharArray()); -85 } -86 return super.getPasswordAuthentication(); -87 } -88 }; -89 Authenticator.setDefault(auth); -90 } -91 -92 final Proxy proxy = new Proxy(Proxy.Type.HTTP, address); -93 conn = (HttpURLConnection) url.openConnection(proxy); -94 } else { -95 conn = (HttpURLConnection) url.openConnection(); -96 } -97 final int timeout = Settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 10000); -98 conn.setConnectTimeout(timeout); -99 conn.setInstanceFollowRedirects(true); -100 } catch (IOException ex) { -101 if (conn != null) { -102 try { -103 conn.disconnect(); -104 } finally { -105 conn = null; -106 } -107 } -108 throw new URLConnectionFailureException("Error getting connection.", ex); -109 } -110 configureTLS(url, conn); -111 return conn; -112 } -113 -114 /** -115 * Check if hostname matches nonProxy settings -116 * -117 * @param url the url to connect to -118 * @return matching result. true: match nonProxy -119 */ -120 private static boolean matchNonProxy(final URL url) { -121 final String host = url.getHost(); -122 -123 // code partially from org.apache.maven.plugins.site.AbstractDeployMojo#getProxyInfo -124 final String nonProxyHosts = Settings.getString(Settings.KEYS.PROXY_NON_PROXY_HOSTS); -125 if (null != nonProxyHosts) { -126 final String[] nonProxies = nonProxyHosts.split("(,)|(;)|(\\|)"); -127 for (final String nonProxyHost : nonProxies) { -128 //if ( StringUtils.contains( nonProxyHost, "*" ) ) -129 if (null != nonProxyHost && nonProxyHost.contains("*")) { -130 // Handle wildcard at the end, beginning or middle of the nonProxyHost -131 final int pos = nonProxyHost.indexOf('*'); -132 final String nonProxyHostPrefix = nonProxyHost.substring(0, pos); -133 final String nonProxyHostSuffix = nonProxyHost.substring(pos + 1); -134 // prefix* -135 if (!StringUtils.isEmpty(nonProxyHostPrefix) && host.startsWith(nonProxyHostPrefix) && StringUtils.isEmpty(nonProxyHostSuffix)) { -136 return true; -137 } -138 // *suffix -139 if (StringUtils.isEmpty(nonProxyHostPrefix) && !StringUtils.isEmpty(nonProxyHostSuffix) && host.endsWith(nonProxyHostSuffix)) { -140 return true; -141 } -142 // prefix*suffix -143 if (!StringUtils.isEmpty(nonProxyHostPrefix) && host.startsWith(nonProxyHostPrefix) && !StringUtils.isEmpty(nonProxyHostSuffix) -144 && host.endsWith(nonProxyHostSuffix)) { -145 return true; -146 } -147 } else if (host.equals(nonProxyHost)) { -148 return true; -149 } -150 } -151 } -152 return false; -153 } -154 -155 /** -156 * Utility method to create an HttpURLConnection. The use of a proxy here is -157 * optional as there may be cases where a proxy is configured but we don't -158 * want to use it (for example, if there's an internal repository -159 * configured) -160 * -161 * @param url the URL to connect to -162 * @param proxy whether to use the proxy (if configured) -163 * @return a newly constructed HttpURLConnection -164 * @throws URLConnectionFailureException thrown if there is an exception -165 */ -166 public static HttpURLConnection createHttpURLConnection(URL url, boolean proxy) throws URLConnectionFailureException { -167 if (proxy) { -168 return createHttpURLConnection(url); -169 } -170 HttpURLConnection conn = null; -171 try { -172 conn = (HttpURLConnection) url.openConnection(); -173 final int timeout = Settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 10000); -174 conn.setConnectTimeout(timeout); -175 conn.setInstanceFollowRedirects(true); -176 } catch (IOException ioe) { -177 throw new URLConnectionFailureException("Error getting connection.", ioe); -178 } -179 configureTLS(url, conn); -180 return conn; -181 } -182 -183 /** -184 * If the protocol is HTTPS, this will configure the cipher suites so that -185 * connections can be made to the NVD, and others, using older versions of -186 * Java. -187 * -188 * @param url the URL -189 * @param conn the connection -190 */ -191 private static void configureTLS(URL url, HttpURLConnection conn) { -192 if ("https".equals(url.getProtocol())) { -193 try { -194 final HttpsURLConnection secCon = (HttpsURLConnection) conn; -195 final SSLSocketFactoryEx factory = new SSLSocketFactoryEx(); -196 secCon.setSSLSocketFactory(factory); -197 } catch (NoSuchAlgorithmException ex) { -198 LOGGER.debug("Unsupported algorithm in SSLSocketFactoryEx", ex); -199 } catch (KeyManagementException ex) { -200 LOGGER.debug("Key mnagement eception in SSLSocketFactoryEx", ex); -201 } -202 } -203 } -204 } +31 import java.net.URLConnection; +32 import java.security.KeyManagementException; +33 import java.security.NoSuchAlgorithmException; +34 import javax.net.ssl.HttpsURLConnection; +35 import org.slf4j.Logger; +36 import org.slf4j.LoggerFactory; +37 +38 /** +39 * A URLConnection Factory to create new connections. This encapsulates several +40 * configuration checks to ensure that the connection uses the correct proxy +41 * settings. +42 * +43 * @author Jeremy Long +44 */ +45 public final class URLConnectionFactory { +46 +47 /** +48 * The logger. +49 */ +50 private static final Logger LOGGER = LoggerFactory.getLogger(URLConnectionFactory.class); +51 +52 /** +53 * Private constructor for this factory. +54 */ +55 private URLConnectionFactory() { +56 } +57 +58 /** +59 * Utility method to create an HttpURLConnection. If the application is +60 * configured to use a proxy this method will retrieve the proxy settings +61 * and use them when setting up the connection. +62 * +63 * @param url the url to connect to +64 * @return an HttpURLConnection +65 * @throws URLConnectionFailureException thrown if there is an exception +66 */ +67 @SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE", justification = "Just being extra safe") +68 public static HttpURLConnection createHttpURLConnection(URL url) throws URLConnectionFailureException { +69 HttpURLConnection conn = null; +70 final String proxyUrl = Settings.getString(Settings.KEYS.PROXY_SERVER); +71 +72 try { +73 if (proxyUrl != null && !matchNonProxy(url)) { +74 final int proxyPort = Settings.getInt(Settings.KEYS.PROXY_PORT); +75 final SocketAddress address = new InetSocketAddress(proxyUrl, proxyPort); +76 +77 final String username = Settings.getString(Settings.KEYS.PROXY_USERNAME); +78 final String password = Settings.getString(Settings.KEYS.PROXY_PASSWORD); +79 +80 if (username != null && password != null) { +81 final Authenticator auth = new Authenticator() { +82 @Override +83 public PasswordAuthentication getPasswordAuthentication() { +84 if (getRequestorType().equals(Authenticator.RequestorType.PROXY)) { +85 return new PasswordAuthentication(username, password.toCharArray()); +86 } +87 return super.getPasswordAuthentication(); +88 } +89 }; +90 Authenticator.setDefault(auth); +91 } +92 +93 final Proxy proxy = new Proxy(Proxy.Type.HTTP, address); +94 conn = (HttpURLConnection) url.openConnection(proxy); +95 } else { +96 conn = (HttpURLConnection) url.openConnection(); +97 } +98 final int timeout = Settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 10000); +99 conn.setConnectTimeout(timeout); +100 conn.setInstanceFollowRedirects(true); +101 } catch (IOException ex) { +102 if (conn != null) { +103 try { +104 conn.disconnect(); +105 } finally { +106 conn = null; +107 } +108 } +109 throw new URLConnectionFailureException("Error getting connection.", ex); +110 } +111 configureTLS(url, conn); +112 return conn; +113 } +114 +115 /** +116 * Check if hostname matches nonProxy settings +117 * +118 * @param url the url to connect to +119 * @return matching result. true: match nonProxy +120 */ +121 private static boolean matchNonProxy(final URL url) { +122 final String host = url.getHost(); +123 +124 // code partially from org.apache.maven.plugins.site.AbstractDeployMojo#getProxyInfo +125 final String nonProxyHosts = Settings.getString(Settings.KEYS.PROXY_NON_PROXY_HOSTS); +126 if (null != nonProxyHosts) { +127 final String[] nonProxies = nonProxyHosts.split("(,)|(;)|(\\|)"); +128 for (final String nonProxyHost : nonProxies) { +129 //if ( StringUtils.contains( nonProxyHost, "*" ) ) +130 if (null != nonProxyHost && nonProxyHost.contains("*")) { +131 // Handle wildcard at the end, beginning or middle of the nonProxyHost +132 final int pos = nonProxyHost.indexOf('*'); +133 final String nonProxyHostPrefix = nonProxyHost.substring(0, pos); +134 final String nonProxyHostSuffix = nonProxyHost.substring(pos + 1); +135 // prefix* +136 if (!StringUtils.isEmpty(nonProxyHostPrefix) && host.startsWith(nonProxyHostPrefix) && StringUtils.isEmpty(nonProxyHostSuffix)) { +137 return true; +138 } +139 // *suffix +140 if (StringUtils.isEmpty(nonProxyHostPrefix) && !StringUtils.isEmpty(nonProxyHostSuffix) && host.endsWith(nonProxyHostSuffix)) { +141 return true; +142 } +143 // prefix*suffix +144 if (!StringUtils.isEmpty(nonProxyHostPrefix) && host.startsWith(nonProxyHostPrefix) && !StringUtils.isEmpty(nonProxyHostSuffix) +145 && host.endsWith(nonProxyHostSuffix)) { +146 return true; +147 } +148 } else if (host.equals(nonProxyHost)) { +149 return true; +150 } +151 } +152 } +153 return false; +154 } +155 +156 /** +157 * Utility method to create an HttpURLConnection. The use of a proxy here is +158 * optional as there may be cases where a proxy is configured but we don't +159 * want to use it (for example, if there's an internal repository +160 * configured) +161 * +162 * @param url the URL to connect to +163 * @param proxy whether to use the proxy (if configured) +164 * @return a newly constructed HttpURLConnection +165 * @throws URLConnectionFailureException thrown if there is an exception +166 */ +167 public static HttpURLConnection createHttpURLConnection(URL url, boolean proxy) throws URLConnectionFailureException { +168 if (proxy) { +169 return createHttpURLConnection(url); +170 } +171 HttpURLConnection conn = null; +172 try { +173 conn = (HttpURLConnection) url.openConnection(); +174 final int timeout = Settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 10000); +175 conn.setConnectTimeout(timeout); +176 conn.setInstanceFollowRedirects(true); +177 } catch (IOException ioe) { +178 throw new URLConnectionFailureException("Error getting connection.", ioe); +179 } +180 configureTLS(url, conn); +181 return conn; +182 } +183 +184 /** +185 * If the protocol is HTTPS, this will configure the cipher suites so that +186 * connections can be made to the NVD, and others, using older versions of +187 * Java. +188 * +189 * @param url the URL +190 * @param conn the connection +191 */ +192 private static void configureTLS(URL url, URLConnection conn) { +193 if ("https".equals(url.getProtocol())) { +194 try { +195 final HttpsURLConnection secCon = (HttpsURLConnection) conn; +196 final SSLSocketFactoryEx factory = new SSLSocketFactoryEx(); +197 secCon.setSSLSocketFactory(factory); +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); +202 } +203 } +204 } +205 }
    diff --git a/xref/org/owasp/dependencycheck/utils/package-frame.html b/xref/org/owasp/dependencycheck/utils/package-frame.html index 99a1974d3..510c411f0 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.2 Reference Package org.owasp.dependencycheck.utils + Dependency-Check 1.4.3 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 2257c8530..a1326aa1e 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.2 Reference Package org.owasp.dependencycheck.utils + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.utils diff --git a/xref/org/owasp/dependencycheck/xml/hints/HintHandler.html b/xref/org/owasp/dependencycheck/xml/hints/HintHandler.html index f09cdc53b..943e12b74 100644 --- a/xref/org/owasp/dependencycheck/xml/hints/HintHandler.html +++ b/xref/org/owasp/dependencycheck/xml/hints/HintHandler.html @@ -70,159 +70,176 @@ 62 */ 63 private static final String DUPLICATE = "duplicate"; 64 /** -65 * Attribute name. +65 * Attribute value. 66 */ 67 private static final String VENDOR = "vendor"; 68 /** -69 * Attribute name. +69 * Attribute value. 70 */ -71 private static final String CONFIDENCE = "confidence"; +71 private static final String PRODUCT = "product"; 72 /** -73 * Attribute name. +73 * Attribute value. 74 */ -75 private static final String VALUE = "value"; +75 private static final String VERSION = "version"; 76 /** 77 * Attribute name. 78 */ -79 private static final String NAME = "name"; +79 private static final String CONFIDENCE = "confidence"; 80 /** 81 * Attribute name. 82 */ -83 private static final String SOURCE = "source"; +83 private static final String VALUE = "value"; 84 /** 85 * Attribute name. 86 */ -87 private static final String TYPE = "type"; +87 private static final String NAME = "name"; 88 /** 89 * Attribute name. 90 */ -91 private static final String CASE_SENSITIVE = "caseSensitive"; +91 private static final String SOURCE = "source"; 92 /** 93 * Attribute name. 94 */ -95 private static final String REGEX = "regex"; +95 private static final String TYPE = "type"; 96 /** 97 * Attribute name. 98 */ -99 private static final String CONTAINS = "contains"; -100 //</editor-fold> -101 -102 /** -103 * The list of hint rules. -104 */ -105 private final List<HintRule> hintRules = new ArrayList<HintRule>(); -106 -107 /** -108 * Returns the list of hint rules. -109 * -110 * @return the value of hintRules -111 */ -112 public List<HintRule> getHintRules() { -113 return hintRules; -114 } -115 -116 /** -117 * The list of vendor duplicating hint rules. -118 */ -119 private final List<VendorDuplicatingHintRule> vendorDuplicatingHintRules = new ArrayList<VendorDuplicatingHintRule>(); -120 -121 /** -122 * Returns the list of vendor duplicating hint rules. -123 * -124 * @return the list of vendor duplicating hint rules -125 */ -126 public List<VendorDuplicatingHintRule> getVendorDuplicatingHintRules() { -127 return vendorDuplicatingHintRules; -128 } -129 -130 /** -131 * The current rule being read. -132 */ -133 private HintRule rule; -134 /** -135 * The current state of the parent node (to differentiate between 'add' and -136 * 'given'). -137 */ -138 private boolean inAddNode = false; -139 -140 /** -141 * Handles the start element event. -142 * -143 * @param uri the uri of the element being processed -144 * @param localName the local name of the element being processed -145 * @param qName the qName of the element being processed -146 * @param attr the attributes of the element being processed -147 * @throws SAXException thrown if there is an exception processing -148 */ -149 @Override -150 public void startElement(String uri, String localName, String qName, Attributes attr) throws SAXException { -151 if (HINT.equals(qName)) { -152 rule = new HintRule(); -153 } else if (ADD.equals(qName)) { -154 inAddNode = true; -155 } else if (GIVEN.equals(qName)) { -156 inAddNode = false; -157 } else if (EVIDENCE.equals(qName)) { -158 final String hintType = attr.getValue(TYPE); -159 if (VENDOR.equals(hintType)) { -160 if (inAddNode) { -161 rule.addAddVendor(attr.getValue(SOURCE), -162 attr.getValue(NAME), -163 attr.getValue(VALUE), -164 Confidence.valueOf(attr.getValue(CONFIDENCE))); -165 } else { -166 rule.addGivenVendor(attr.getValue(SOURCE), -167 attr.getValue(NAME), -168 attr.getValue(VALUE), -169 Confidence.valueOf(attr.getValue(CONFIDENCE))); -170 } -171 } else if (inAddNode) { -172 rule.addAddProduct(attr.getValue(SOURCE), -173 attr.getValue(NAME), -174 attr.getValue(VALUE), -175 Confidence.valueOf(attr.getValue(CONFIDENCE))); -176 } else { -177 rule.addGivenProduct(attr.getValue(SOURCE), -178 attr.getValue(NAME), -179 attr.getValue(VALUE), -180 Confidence.valueOf(attr.getValue(CONFIDENCE))); -181 } -182 } else if (FILE_NAME.equals(qName)) { -183 final PropertyType pt = new PropertyType(); -184 pt.setValue(attr.getValue(CONTAINS)); -185 if (attr.getLength() > 0) { -186 final String regex = attr.getValue(REGEX); -187 if (regex != null) { -188 pt.setRegex(Boolean.parseBoolean(regex)); -189 } -190 final String caseSensitive = attr.getValue(CASE_SENSITIVE); -191 if (caseSensitive != null) { -192 pt.setCaseSensitive(Boolean.parseBoolean(caseSensitive)); -193 } -194 } -195 rule.addFilename(pt); -196 } else if (VENDOR_DUPLICATING_RULE.equals(qName)) { -197 vendorDuplicatingHintRules.add(new VendorDuplicatingHintRule(attr.getValue(VALUE), attr.getValue(DUPLICATE))); -198 } -199 } -200 -201 /** -202 * Handles the end element event. -203 * -204 * @param uri the element's URI -205 * @param localName the local name -206 * @param qName the qualified name -207 * @throws SAXException thrown if there is an exception processing the -208 * element -209 */ -210 @Override -211 public void endElement(String uri, String localName, String qName) throws SAXException { -212 if (HINT.equals(qName) && rule != null) { -213 hintRules.add(rule); -214 rule = null; +99 private static final String CASE_SENSITIVE = "caseSensitive"; +100 /** +101 * Attribute name. +102 */ +103 private static final String REGEX = "regex"; +104 /** +105 * Attribute name. +106 */ +107 private static final String CONTAINS = "contains"; +108 //</editor-fold> +109 +110 /** +111 * The list of hint rules. +112 */ +113 private final List<HintRule> hintRules = new ArrayList<HintRule>(); +114 +115 /** +116 * Returns the list of hint rules. +117 * +118 * @return the value of hintRules +119 */ +120 public List<HintRule> getHintRules() { +121 return hintRules; +122 } +123 +124 /** +125 * The list of vendor duplicating hint rules. +126 */ +127 private final List<VendorDuplicatingHintRule> vendorDuplicatingHintRules = new ArrayList<VendorDuplicatingHintRule>(); +128 +129 /** +130 * Returns the list of vendor duplicating hint rules. +131 * +132 * @return the list of vendor duplicating hint rules +133 */ +134 public List<VendorDuplicatingHintRule> getVendorDuplicatingHintRules() { +135 return vendorDuplicatingHintRules; +136 } +137 +138 /** +139 * The current rule being read. +140 */ +141 private HintRule rule; +142 /** +143 * The current state of the parent node (to differentiate between 'add' and +144 * 'given'). +145 */ +146 private boolean inAddNode = false; +147 +148 /** +149 * Handles the start element event. +150 * +151 * @param uri the uri of the element being processed +152 * @param localName the local name of the element being processed +153 * @param qName the qName of the element being processed +154 * @param attr the attributes of the element being processed +155 * @throws SAXException thrown if there is an exception processing +156 */ +157 @Override +158 public void startElement(String uri, String localName, String qName, Attributes attr) throws SAXException { +159 if (HINT.equals(qName)) { +160 rule = new HintRule(); +161 } else if (ADD.equals(qName)) { +162 inAddNode = true; +163 } else if (GIVEN.equals(qName)) { +164 inAddNode = false; +165 } else if (EVIDENCE.equals(qName)) { +166 final String hintType = attr.getValue(TYPE); +167 if (VENDOR.equals(hintType)) { +168 if (inAddNode) { +169 rule.addAddVendor(attr.getValue(SOURCE), +170 attr.getValue(NAME), +171 attr.getValue(VALUE), +172 Confidence.valueOf(attr.getValue(CONFIDENCE))); +173 } else { +174 rule.addGivenVendor(attr.getValue(SOURCE), +175 attr.getValue(NAME), +176 attr.getValue(VALUE), +177 Confidence.valueOf(attr.getValue(CONFIDENCE))); +178 } +179 } else if (PRODUCT.equals(hintType)) { +180 if (inAddNode) { +181 rule.addAddProduct(attr.getValue(SOURCE), +182 attr.getValue(NAME), +183 attr.getValue(VALUE), +184 Confidence.valueOf(attr.getValue(CONFIDENCE))); +185 } else { +186 rule.addGivenProduct(attr.getValue(SOURCE), +187 attr.getValue(NAME), +188 attr.getValue(VALUE), +189 Confidence.valueOf(attr.getValue(CONFIDENCE))); +190 } +191 } else if (VERSION.equals(hintType)) { +192 if (inAddNode) { +193 rule.addAddVersion(attr.getValue(SOURCE), +194 attr.getValue(NAME), +195 attr.getValue(VALUE), +196 Confidence.valueOf(attr.getValue(CONFIDENCE))); +197 } +198 } +199 } else if (FILE_NAME.equals(qName)) { +200 final PropertyType pt = new PropertyType(); +201 pt.setValue(attr.getValue(CONTAINS)); +202 if (attr.getLength() > 0) { +203 final String regex = attr.getValue(REGEX); +204 if (regex != null) { +205 pt.setRegex(Boolean.parseBoolean(regex)); +206 } +207 final String caseSensitive = attr.getValue(CASE_SENSITIVE); +208 if (caseSensitive != null) { +209 pt.setCaseSensitive(Boolean.parseBoolean(caseSensitive)); +210 } +211 } +212 rule.addFilename(pt); +213 } else if (VENDOR_DUPLICATING_RULE.equals(qName)) { +214 vendorDuplicatingHintRules.add(new VendorDuplicatingHintRule(attr.getValue(VALUE), attr.getValue(DUPLICATE))); 215 } 216 } -217 } +217 +218 /** +219 * Handles the end element event. +220 * +221 * @param uri the element's URI +222 * @param localName the local name +223 * @param qName the qualified name +224 * @throws SAXException thrown if there is an exception processing the +225 * element +226 */ +227 @Override +228 public void endElement(String uri, String localName, String qName) throws SAXException { +229 if (HINT.equals(qName) && rule != null) { +230 hintRules.add(rule); +231 rule = null; +232 } +233 } +234 }
    diff --git a/xref/org/owasp/dependencycheck/xml/hints/HintParser.html b/xref/org/owasp/dependencycheck/xml/hints/HintParser.html index ca18ae491..7ffb4ffda 100644 --- a/xref/org/owasp/dependencycheck/xml/hints/HintParser.html +++ b/xref/org/owasp/dependencycheck/xml/hints/HintParser.html @@ -72,7 +72,7 @@ 64 /** 65 * The schema for the hint XML files. 66 */ -67 private static final String HINT_SCHEMA = "schema/dependency-hint.1.0.xsd"; +67 private static final String HINT_SCHEMA = "schema/dependency-hint.1.1.xsd"; 68 69 /** 70 * Parses the given XML file and returns a list of the hints contained. @@ -112,46 +112,55 @@ 104 * @throws SAXException thrown if the XML cannot be parsed 105 */ 106 public Hints parseHints(InputStream inputStream) throws HintParseException, SAXException { -107 try { -108 final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream(HINT_SCHEMA); -109 final HintHandler handler = new HintHandler(); -110 final SAXParserFactory factory = SAXParserFactory.newInstance(); -111 factory.setNamespaceAware(true); -112 factory.setValidating(true); -113 final SAXParser saxParser = factory.newSAXParser(); -114 saxParser.setProperty(HintParser.JAXP_SCHEMA_LANGUAGE, HintParser.W3C_XML_SCHEMA); -115 saxParser.setProperty(HintParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); -116 final XMLReader xmlReader = saxParser.getXMLReader(); -117 xmlReader.setErrorHandler(new HintErrorHandler()); -118 xmlReader.setContentHandler(handler); -119 -120 final Reader reader = new InputStreamReader(inputStream, "UTF-8"); -121 final InputSource in = new InputSource(reader); -122 -123 xmlReader.parse(in); -124 final Hints hints = new Hints(); -125 hints.setHintRules(handler.getHintRules()); -126 hints.setVendorDuplicatingHintRules(handler.getVendorDuplicatingHintRules()); -127 return hints; -128 } catch (ParserConfigurationException ex) { -129 LOGGER.debug("", ex); -130 throw new HintParseException(ex); -131 } catch (SAXException ex) { -132 if (ex.getMessage().contains("Cannot find the declaration of element 'hints'.")) { -133 throw ex; -134 } else { -135 LOGGER.debug("", ex); -136 throw new HintParseException(ex); -137 } -138 } catch (FileNotFoundException ex) { -139 LOGGER.debug("", ex); -140 throw new HintParseException(ex); -141 } catch (IOException ex) { -142 LOGGER.debug("", ex); -143 throw new HintParseException(ex); -144 } -145 } -146 } +107 InputStream schemaStream = null; +108 try { +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 }
    diff --git a/xref/org/owasp/dependencycheck/xml/hints/HintRule.html b/xref/org/owasp/dependencycheck/xml/hints/HintRule.html index c17ba93e9..dfe9c38a7 100644 --- a/xref/org/owasp/dependencycheck/xml/hints/HintRule.html +++ b/xref/org/owasp/dependencycheck/xml/hints/HintRule.html @@ -94,78 +94,103 @@ 86 private final List<Evidence> givenVendor = new ArrayList<Evidence>(); 87 88 /** -89 * Adds a given vendors to the list of evidence to matched. -90 * -91 * @param source the source of the evidence -92 * @param name the name of the evidence -93 * @param value the value of the evidence -94 * @param confidence the confidence of the evidence -95 */ -96 public void addGivenVendor(String source, String name, String value, Confidence confidence) { -97 givenVendor.add(new Evidence(source, name, value, confidence)); -98 } -99 -100 /** -101 * Get the value of givenVendor. -102 * -103 * @return the value of givenVendor +89 * The list of product evidence to add. +90 */ +91 private final List<Evidence> addProduct = new ArrayList<Evidence>(); +92 /** +93 * The list of version evidence to add. +94 */ +95 private final List<Evidence> addVersion = new ArrayList<Evidence>(); +96 +97 /** +98 * Adds a given vendors to the list of evidence to matched. +99 * +100 * @param source the source of the evidence +101 * @param name the name of the evidence +102 * @param value the value of the evidence +103 * @param confidence the confidence of the evidence 104 */ -105 public List<Evidence> getGivenVendor() { -106 return givenVendor; +105 public void addGivenVendor(String source, String name, String value, Confidence confidence) { +106 givenVendor.add(new Evidence(source, name, value, confidence)); 107 } 108 109 /** -110 * The list of product evidence to add. -111 */ -112 private final List<Evidence> addProduct = new ArrayList<Evidence>(); -113 -114 /** -115 * Adds a given product to the list of evidence to add when matched. -116 * -117 * @param source the source of the evidence -118 * @param name the name of the evidence -119 * @param value the value of the evidence -120 * @param confidence the confidence of the evidence -121 */ -122 public void addAddProduct(String source, String name, String value, Confidence confidence) { -123 addProduct.add(new Evidence(source, name, value, confidence)); -124 } -125 -126 /** -127 * Get the value of addProduct. -128 * -129 * @return the value of addProduct -130 */ -131 public List<Evidence> getAddProduct() { -132 return addProduct; -133 } -134 -135 /** -136 * The list of vendor hints to add. -137 */ -138 private final List<Evidence> addVendor = new ArrayList<Evidence>(); -139 -140 /** -141 * Adds a given vendor to the list of evidence to add when matched. -142 * -143 * @param source the source of the evidence -144 * @param name the name of the evidence -145 * @param value the value of the evidence -146 * @param confidence the confidence of the evidence -147 */ -148 public void addAddVendor(String source, String name, String value, Confidence confidence) { -149 addVendor.add(new Evidence(source, name, value, confidence)); -150 } -151 -152 /** -153 * Get the value of addVendor. -154 * -155 * @return the value of addVendor -156 */ -157 public List<Evidence> getAddVendor() { -158 return addVendor; -159 } -160 } +110 * Get the value of givenVendor. +111 * +112 * @return the value of givenVendor +113 */ +114 public List<Evidence> getGivenVendor() { +115 return givenVendor; +116 } +117 +118 /** +119 * Adds a given product to the list of evidence to add when matched. +120 * +121 * @param source the source of the evidence +122 * @param name the name of the evidence +123 * @param value the value of the evidence +124 * @param confidence the confidence of the evidence +125 */ +126 public void addAddProduct(String source, String name, String value, Confidence confidence) { +127 addProduct.add(new Evidence(source, name, value, confidence)); +128 } +129 +130 /** +131 * Get the value of addProduct. +132 * +133 * @return the value of addProduct +134 */ +135 public List<Evidence> getAddProduct() { +136 return addProduct; +137 } +138 +139 /** +140 * Adds a given version to the list of evidence to add when matched. +141 * +142 * @param source the source of the evidence +143 * @param name the name of the evidence +144 * @param value the value of the evidence +145 * @param confidence the confidence of the evidence +146 */ +147 public void addAddVersion(String source, String name, String value, Confidence confidence) { +148 addVersion.add(new Evidence(source, name, value, confidence)); +149 } +150 +151 /** +152 * Get the value of addVersion. +153 * +154 * @return the value of addVersion +155 */ +156 public List<Evidence> getAddVersion() { +157 return addVersion; +158 } +159 +160 /** +161 * The list of vendor hints to add. +162 */ +163 private final List<Evidence> addVendor = new ArrayList<Evidence>(); +164 +165 /** +166 * Adds a given vendor to the list of evidence to add when matched. +167 * +168 * @param source the source of the evidence +169 * @param name the name of the evidence +170 * @param value the value of the evidence +171 * @param confidence the confidence of the evidence +172 */ +173 public void addAddVendor(String source, String name, String value, Confidence confidence) { +174 addVendor.add(new Evidence(source, name, value, confidence)); +175 } +176 +177 /** +178 * Get the value of addVendor. +179 * +180 * @return the value of addVendor +181 */ +182 public List<Evidence> getAddVendor() { +183 return addVendor; +184 } +185 }
    diff --git a/xref/org/owasp/dependencycheck/xml/hints/package-frame.html b/xref/org/owasp/dependencycheck/xml/hints/package-frame.html index b7634b0a1..5f8695c7e 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.2 Reference Package org.owasp.dependencycheck.xml.hints + Dependency-Check 1.4.3 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 36b6cf5ed..69804e1a0 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.2 Reference Package org.owasp.dependencycheck.xml.hints + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.xml.hints diff --git a/xref/org/owasp/dependencycheck/xml/pom/PomUtils.html b/xref/org/owasp/dependencycheck/xml/pom/PomUtils.html index 534ba81f2..aadfe5987 100644 --- a/xref/org/owasp/dependencycheck/xml/pom/PomUtils.html +++ b/xref/org/owasp/dependencycheck/xml/pom/PomUtils.html @@ -56,74 +56,82 @@ 48 * 49 * @param file the pom.xml file 50 * @return returns a -51 * @throws AnalysisException is thrown if there is an exception extracting or parsing the POM {@link Model} object -52 */ -53 public static Model readPom(File file) throws AnalysisException { -54 Model model = null; +51 * @throws AnalysisException is thrown if there is an exception extracting +52 * or parsing the POM {@link Model} object +53 */ +54 public static Model readPom(File file) throws AnalysisException { 55 try { 56 final PomParser parser = new PomParser(); -57 model = parser.parse(file); -58 } catch (PomParseException ex) { -59 LOGGER.warn("Unable to parse pom '{}'", file.getPath()); -60 LOGGER.debug("", ex); -61 throw new AnalysisException(ex); -62 } catch (IOException ex) { -63 LOGGER.warn("Unable to parse pom '{}'(IO Exception)", file.getPath()); +57 final Model model = parser.parse(file); +58 if (model == null) { +59 throw new AnalysisException(String.format("Unable to parse pom '%s'", file.getPath())); +60 } +61 return model; +62 } catch (PomParseException ex) { +63 LOGGER.warn("Unable to parse pom '{}'", file.getPath()); 64 LOGGER.debug("", ex); 65 throw new AnalysisException(ex); -66 } catch (Throwable ex) { -67 LOGGER.warn("Unexpected error during parsing of the pom '{}'", file.getPath()); +66 } catch (IOException ex) { +67 LOGGER.warn("Unable to parse pom '{}'(IO Exception)", file.getPath()); 68 LOGGER.debug("", ex); 69 throw new AnalysisException(ex); -70 } -71 return model; -72 } -73 -74 /** -75 * Retrieves the specified POM from a jar file and converts it to a Model. -76 * -77 * @param path the path to the pom.xml file within the jar file -78 * @param jar the jar file to extract the pom from -79 * @return returns a -80 * @throws AnalysisException is thrown if there is an exception extracting or parsing the POM {@link Model} object -81 */ -82 public static Model readPom(String path, JarFile jar) throws AnalysisException { -83 final ZipEntry entry = jar.getEntry(path); -84 Model model = null; -85 if (entry != null) { //should never be null -86 try { -87 final PomParser parser = new PomParser(); -88 model = parser.parse(jar.getInputStream(entry)); -89 LOGGER.debug("Read POM {}", path); -90 } catch (SecurityException ex) { -91 LOGGER.warn("Unable to parse pom '{}' in jar '{}'; invalid signature", path, jar.getName()); -92 LOGGER.debug("", ex); -93 throw new AnalysisException(ex); -94 } catch (IOException ex) { -95 LOGGER.warn("Unable to parse pom '{}' in jar '{}' (IO Exception)", path, jar.getName()); -96 LOGGER.debug("", ex); -97 throw new AnalysisException(ex); -98 } catch (Throwable ex) { -99 LOGGER.warn("Unexpected error during parsing of the pom '{}' in jar '{}'", path, jar.getName()); -100 LOGGER.debug("", ex); -101 throw new AnalysisException(ex); -102 } -103 } -104 return model; -105 } -106 -107 /** -108 * Reads in the pom file and adds elements as evidence to the given dependency. -109 * -110 * @param dependency the dependency being analyzed -111 * @param pomFile the pom file to read -112 * @throws AnalysisException is thrown if there is an exception parsing the pom -113 */ -114 public static void analyzePOM(Dependency dependency, File pomFile) throws AnalysisException { -115 final Model pom = PomUtils.readPom(pomFile); -116 JarAnalyzer.setPomEvidence(dependency, pom, null); -117 } -118 } +70 } catch (Throwable ex) { +71 LOGGER.warn("Unexpected error during parsing of the pom '{}'", file.getPath()); +72 LOGGER.debug("", ex); +73 throw new AnalysisException(ex); +74 } +75 } +76 +77 /** +78 * Retrieves the specified POM from a jar file and converts it to a Model. +79 * +80 * @param path the path to the pom.xml file within the jar file +81 * @param jar the jar file to extract the pom from +82 * @return returns a +83 * @throws AnalysisException is thrown if there is an exception extracting +84 * or parsing the POM {@link Model} object +85 */ +86 public static Model readPom(String path, JarFile jar) throws AnalysisException { +87 final ZipEntry entry = jar.getEntry(path); +88 Model model = null; +89 if (entry != null) { //should never be null +90 try { +91 final PomParser parser = new PomParser(); +92 model = parser.parse(jar.getInputStream(entry)); +93 if (model == null) { +94 throw new AnalysisException(String.format("Unable to parse pom '%s/%s'", jar.getName(), path)); +95 } +96 } catch (SecurityException ex) { +97 LOGGER.warn("Unable to parse pom '{}' in jar '{}'; invalid signature", path, jar.getName()); +98 LOGGER.debug("", ex); +99 throw new AnalysisException(ex); +100 } catch (IOException ex) { +101 LOGGER.warn("Unable to parse pom '{}' in jar '{}' (IO Exception)", path, jar.getName()); +102 LOGGER.debug("", ex); +103 throw new AnalysisException(ex); +104 } catch (Throwable ex) { +105 LOGGER.warn("Unexpected error during parsing of the pom '{}' in jar '{}'", path, jar.getName()); +106 LOGGER.debug("", ex); +107 throw new AnalysisException(ex); +108 } +109 } +110 return model; +111 } +112 +113 /** +114 * Reads in the pom file and adds elements as evidence to the given +115 * dependency. +116 * +117 * @param dependency the dependency being analyzed +118 * @param pomFile the pom file to read +119 * @throws AnalysisException is thrown if there is an exception parsing the +120 * pom +121 */ +122 public static void analyzePOM(Dependency dependency, File pomFile) throws AnalysisException { +123 final Model pom = PomUtils.readPom(pomFile); +124 JarAnalyzer.setPomEvidence(dependency, pom, null); +125 } +126 }
    diff --git a/xref/org/owasp/dependencycheck/xml/pom/package-frame.html b/xref/org/owasp/dependencycheck/xml/pom/package-frame.html index 66d86d1f3..fc7973b24 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.2 Reference Package org.owasp.dependencycheck.xml.pom + Dependency-Check 1.4.3 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 fa4e8b2e9..da664d834 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.2 Reference Package org.owasp.dependencycheck.xml.pom + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.xml.pom diff --git a/xref/org/owasp/dependencycheck/xml/suppression/SuppressionErrorHandler.html b/xref/org/owasp/dependencycheck/xml/suppression/SuppressionErrorHandler.html index c9387de53..2bce126c7 100644 --- a/xref/org/owasp/dependencycheck/xml/suppression/SuppressionErrorHandler.html +++ b/xref/org/owasp/dependencycheck/xml/suppression/SuppressionErrorHandler.html @@ -25,84 +25,82 @@ 17 */ 18 package org.owasp.dependencycheck.xml.suppression; 19 -20 import org.slf4j.Logger; -21 import org.slf4j.LoggerFactory; -22 import org.xml.sax.ErrorHandler; -23 import org.xml.sax.SAXException; -24 import org.xml.sax.SAXParseException; -25 -26 /** -27 * An XML parsing error handler. -28 * -29 * @author Jeremy Long -30 */ -31 public class SuppressionErrorHandler implements ErrorHandler { -32 -33 /** -34 * The logger. -35 */ -36 private static final Logger LOGGER = LoggerFactory.getLogger(SuppressionErrorHandler.class); -37 -38 /** -39 * Builds a prettier exception message. -40 * -41 * @param ex the SAXParseException -42 * @return an easier to read exception message -43 */ -44 private String getPrettyParseExceptionInfo(SAXParseException ex) { +20 import org.xml.sax.ErrorHandler; +21 import org.xml.sax.SAXException; +22 import org.xml.sax.SAXParseException; +23 +24 /** +25 * An XML parsing error handler. +26 * +27 * @author Jeremy Long +28 */ +29 public class SuppressionErrorHandler implements ErrorHandler { +30 +31 /** +32 * The logger. +33 */ +34 //private static final Logger LOGGER = LoggerFactory.getLogger(SuppressionErrorHandler.class); +35 +36 /** +37 * Builds a prettier exception message. +38 * +39 * @param ex the SAXParseException +40 * @return an easier to read exception message +41 */ +42 private String getPrettyParseExceptionInfo(SAXParseException ex) { +43 +44 final StringBuilder sb = new StringBuilder(); 45 -46 final StringBuilder sb = new StringBuilder(); -47 -48 if (ex.getSystemId() != null) { -49 sb.append("systemId=").append(ex.getSystemId()).append(", "); -50 } -51 if (ex.getPublicId() != null) { -52 sb.append("publicId=").append(ex.getPublicId()).append(", "); -53 } -54 if (ex.getLineNumber() > 0) { -55 sb.append("Line=").append(ex.getLineNumber()); -56 } -57 if (ex.getColumnNumber() > 0) { -58 sb.append(", Column=").append(ex.getColumnNumber()); -59 } -60 sb.append(": ").append(ex.getMessage()); -61 -62 return sb.toString(); -63 } -64 -65 /** -66 * Logs warnings. -67 * -68 * @param ex the warning to log -69 * @throws SAXException is never thrown -70 */ -71 @Override -72 public void warning(SAXParseException ex) throws SAXException { -73 //LOGGER.debug("", ex); -74 } -75 -76 /** -77 * Handles errors. -78 * -79 * @param ex the error to handle -80 * @throws SAXException is always thrown -81 */ -82 @Override -83 public void error(SAXParseException ex) throws SAXException { -84 throw new SAXException(getPrettyParseExceptionInfo(ex)); -85 } -86 -87 /** -88 * Handles fatal exceptions. -89 * -90 * @param ex a fatal exception -91 * @throws SAXException is always -92 */ -93 @Override -94 public void fatalError(SAXParseException ex) throws SAXException { -95 throw new SAXException(getPrettyParseExceptionInfo(ex)); -96 } -97 } +46 if (ex.getSystemId() != null) { +47 sb.append("systemId=").append(ex.getSystemId()).append(", "); +48 } +49 if (ex.getPublicId() != null) { +50 sb.append("publicId=").append(ex.getPublicId()).append(", "); +51 } +52 if (ex.getLineNumber() > 0) { +53 sb.append("Line=").append(ex.getLineNumber()); +54 } +55 if (ex.getColumnNumber() > 0) { +56 sb.append(", Column=").append(ex.getColumnNumber()); +57 } +58 sb.append(": ").append(ex.getMessage()); +59 +60 return sb.toString(); +61 } +62 +63 /** +64 * Logs warnings. +65 * +66 * @param ex the warning to log +67 * @throws SAXException is never thrown +68 */ +69 @Override +70 public void warning(SAXParseException ex) throws SAXException { +71 //LOGGER.debug("", ex); +72 } +73 +74 /** +75 * Handles errors. +76 * +77 * @param ex the error to handle +78 * @throws SAXException is always thrown +79 */ +80 @Override +81 public void error(SAXParseException ex) throws SAXException { +82 throw new SAXException(getPrettyParseExceptionInfo(ex)); +83 } +84 +85 /** +86 * Handles fatal exceptions. +87 * +88 * @param ex a fatal exception +89 * @throws SAXException is always +90 */ +91 @Override +92 public void fatalError(SAXParseException ex) throws SAXException { +93 throw new SAXException(getPrettyParseExceptionInfo(ex)); +94 } +95 }
    diff --git a/xref/org/owasp/dependencycheck/xml/suppression/SuppressionParser.html b/xref/org/owasp/dependencycheck/xml/suppression/SuppressionParser.html index 1981f2df2..584dfa251 100644 --- a/xref/org/owasp/dependencycheck/xml/suppression/SuppressionParser.html +++ b/xref/org/owasp/dependencycheck/xml/suppression/SuppressionParser.html @@ -129,88 +129,106 @@ 121 * @throws SAXException thrown if the XML cannot be parsed 122 */ 123 public List<SuppressionRule> parseSuppressionRules(InputStream inputStream) throws SuppressionParseException, SAXException { -124 try { -125 final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream(SUPPRESSION_SCHEMA); -126 final SuppressionHandler handler = new SuppressionHandler(); -127 final SAXParserFactory factory = SAXParserFactory.newInstance(); -128 factory.setNamespaceAware(true); -129 factory.setValidating(true); -130 final SAXParser saxParser = factory.newSAXParser(); -131 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA); -132 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); -133 final XMLReader xmlReader = saxParser.getXMLReader(); -134 xmlReader.setErrorHandler(new SuppressionErrorHandler()); -135 xmlReader.setContentHandler(handler); -136 -137 final Reader reader = new InputStreamReader(inputStream, "UTF-8"); -138 final InputSource in = new InputSource(reader); -139 //in.setEncoding("UTF-8"); -140 -141 xmlReader.parse(in); -142 -143 return handler.getSuppressionRules(); -144 } catch (ParserConfigurationException ex) { -145 LOGGER.debug("", ex); -146 throw new SuppressionParseException(ex); -147 } catch (SAXException ex) { -148 if (ex.getMessage().contains("Cannot find the declaration of element 'suppressions'.")) { -149 throw ex; -150 } else { -151 LOGGER.debug("", ex); -152 throw new SuppressionParseException(ex); -153 } -154 } catch (FileNotFoundException ex) { -155 LOGGER.debug("", ex); -156 throw new SuppressionParseException(ex); -157 } catch (IOException ex) { -158 LOGGER.debug("", ex); -159 throw new SuppressionParseException(ex); -160 } -161 } -162 -163 /** -164 * Parses the given XML stream and returns a list of the suppression rules -165 * contained. -166 * -167 * @param inputStream an InputStream containing suppression rues -168 * @return a list of suppression rules -169 * @throws SuppressionParseException if the XML cannot be parsed -170 */ -171 private List<SuppressionRule> parseOldSuppressionRules(InputStream inputStream) throws SuppressionParseException { -172 try { -173 final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream(OLD_SUPPRESSION_SCHEMA); -174 final SuppressionHandler handler = new SuppressionHandler(); -175 final SAXParserFactory factory = SAXParserFactory.newInstance(); -176 factory.setNamespaceAware(true); -177 factory.setValidating(true); -178 final SAXParser saxParser = factory.newSAXParser(); -179 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA); -180 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); -181 final XMLReader xmlReader = saxParser.getXMLReader(); -182 xmlReader.setErrorHandler(new SuppressionErrorHandler()); -183 xmlReader.setContentHandler(handler); -184 -185 final Reader reader = new InputStreamReader(inputStream, "UTF-8"); -186 final InputSource in = new InputSource(reader); -187 -188 xmlReader.parse(in); -189 -190 return handler.getSuppressionRules(); -191 } catch (ParserConfigurationException ex) { -192 LOGGER.debug("", ex); -193 throw new SuppressionParseException(ex); -194 } catch (SAXException ex) { -195 LOGGER.debug("", ex); -196 throw new SuppressionParseException(ex); -197 } catch (FileNotFoundException ex) { -198 LOGGER.debug("", ex); -199 throw new SuppressionParseException(ex); -200 } catch (IOException ex) { -201 LOGGER.debug("", ex); -202 throw new SuppressionParseException(ex); -203 } -204 } -205 } +124 InputStream schemaStream = null; +125 try { +126 schemaStream = this.getClass().getClassLoader().getResourceAsStream(SUPPRESSION_SCHEMA); +127 final SuppressionHandler handler = new SuppressionHandler(); +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 }
    diff --git a/xref/org/owasp/dependencycheck/xml/suppression/package-frame.html b/xref/org/owasp/dependencycheck/xml/suppression/package-frame.html index c411073e4..676f27eb1 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.2 Reference Package org.owasp.dependencycheck.xml.suppression + Dependency-Check 1.4.3 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 01cf39d60..d5d784671 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.2 Reference Package org.owasp.dependencycheck.xml.suppression + Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.xml.suppression diff --git a/xref/org/slf4j/impl/package-frame.html b/xref/org/slf4j/impl/package-frame.html index 1165df056..02654a591 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.2 Reference Package org.slf4j.impl + Dependency-Check 1.4.3 Reference Package org.slf4j.impl diff --git a/xref/org/slf4j/impl/package-summary.html b/xref/org/slf4j/impl/package-summary.html index 44988dd58..4b03c151d 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.2 Reference Package org.slf4j.impl + Dependency-Check 1.4.3 Reference Package org.slf4j.impl diff --git a/xref/overview-frame.html b/xref/overview-frame.html index b27fecb98..c5d7b4de7 100644 --- a/xref/overview-frame.html +++ b/xref/overview-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference + Dependency-Check 1.4.3 Reference diff --git a/xref/overview-summary.html b/xref/overview-summary.html index 479525040..9ea5ea634 100644 --- a/xref/overview-summary.html +++ b/xref/overview-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.2 Reference + Dependency-Check 1.4.3 Reference @@ -24,7 +24,7 @@ -

    Dependency-Check 1.4.2 Reference

    +

    Dependency-Check 1.4.3 Reference