View Javadoc
1   /*
2    * This file is part of dependency-check-cli.
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) 2012 Jeremy Long. All Rights Reserved.
17   */
18  package org.owasp.dependencycheck;
19  
20  import java.io.File;
21  import java.io.FileNotFoundException;
22  
23  import org.apache.commons.cli.CommandLine;
24  import org.apache.commons.cli.CommandLineParser;
25  import org.apache.commons.cli.DefaultParser;
26  import org.apache.commons.cli.HelpFormatter;
27  import org.apache.commons.cli.Option;
28  import org.apache.commons.cli.OptionGroup;
29  import org.apache.commons.cli.Options;
30  import org.apache.commons.cli.ParseException;
31  import org.owasp.dependencycheck.reporting.ReportGenerator.Format;
32  import org.owasp.dependencycheck.utils.InvalidSettingException;
33  import org.owasp.dependencycheck.utils.Settings;
34  import org.slf4j.Logger;
35  import org.slf4j.LoggerFactory;
36  
37  /**
38   * A utility to parse command line arguments for the DependencyCheck.
39   *
40   * @author Jeremy Long
41   */
42  public final class CliParser {
43  
44      /**
45       * The logger.
46       */
47      private static final Logger LOGGER = LoggerFactory.getLogger(CliParser.class);
48      /**
49       * The command line.
50       */
51      private CommandLine line;
52      /**
53       * Indicates whether the arguments are valid.
54       */
55      private boolean isValid = true;
56  
57      /**
58       * Parses the arguments passed in and captures the results for later use.
59       *
60       * @param args the command line arguments
61       * @throws FileNotFoundException is thrown when a 'file' argument does not point to a file that exists.
62       * @throws ParseException is thrown when a Parse Exception occurs.
63       */
64      public void parse(String[] args) throws FileNotFoundException, ParseException {
65          line = parseArgs(args);
66  
67          if (line != null) {
68              validateArgs();
69          }
70      }
71  
72      /**
73       * Parses the command line arguments.
74       *
75       * @param args the command line arguments
76       * @return the results of parsing the command line arguments
77       * @throws ParseException if the arguments are invalid
78       */
79      private CommandLine parseArgs(String[] args) throws ParseException {
80          final CommandLineParser parser = new DefaultParser();
81          final Options options = createCommandLineOptions();
82          return parser.parse(options, args);
83      }
84  
85      /**
86       * Validates that the command line arguments are valid.
87       *
88       * @throws FileNotFoundException if there is a file specified by either the SCAN or CPE command line arguments that does not
89       * exist.
90       * @throws ParseException is thrown if there is an exception parsing the command line.
91       */
92      private void validateArgs() throws FileNotFoundException, ParseException {
93          if (isUpdateOnly() || isRunScan()) {
94              final String value = line.getOptionValue(ARGUMENT.CVE_VALID_FOR_HOURS);
95              if (value != null) {
96                  try {
97                      final int i = Integer.parseInt(value);
98                      if (i < 0) {
99                          throw new ParseException("Invalid Setting: cveValidForHours must be a number greater than or equal to 0.");
100                     }
101                 } catch (NumberFormatException ex) {
102                     throw new ParseException("Invalid Setting: cveValidForHours must be a number greater than or equal to 0.");
103                 }
104             }
105         }
106         if (isRunScan()) {
107             validatePathExists(getScanFiles(), ARGUMENT.SCAN);
108             validatePathExists(getReportDirectory(), ARGUMENT.OUT);
109             if (getPathToMono() != null) {
110                 validatePathExists(getPathToMono(), ARGUMENT.PATH_TO_MONO);
111             }
112             if (!line.hasOption(ARGUMENT.APP_NAME) && !line.hasOption(ARGUMENT.PROJECT)) {
113                 throw new ParseException("Missing '" + ARGUMENT.PROJECT + "' argument; the scan cannot be run without the an project name.");
114             }
115             if (line.hasOption(ARGUMENT.OUTPUT_FORMAT)) {
116                 final String format = line.getOptionValue(ARGUMENT.OUTPUT_FORMAT);
117                 try {
118                     Format.valueOf(format);
119                 } catch (IllegalArgumentException ex) {
120                     final String msg = String.format("An invalid 'format' of '%s' was specified. "
121                             + "Supported output formats are XML, HTML, VULN, or ALL", format);
122                     throw new ParseException(msg);
123                 }
124             }
125             if ((getBaseCve12Url() != null || getBaseCve20Url() != null || getModifiedCve12Url() != null || getModifiedCve20Url() != null)
126                     && (getBaseCve12Url() == null || getBaseCve20Url() == null || getModifiedCve12Url() == null || getModifiedCve20Url() == null)) {
127                 final String msg = "If one of the CVE URLs is specified they must all be specified; please add the missing CVE URL.";
128                 throw new ParseException(msg);
129             }
130             if (line.hasOption((ARGUMENT.SYM_LINK_DEPTH))) {
131                 try {
132                     final int i = Integer.parseInt(line.getOptionValue(ARGUMENT.SYM_LINK_DEPTH));
133                     if (i < 0) {
134                         throw new ParseException("Symbolic Link Depth (symLink) must be greater than zero.");
135                     }
136                 } catch (NumberFormatException ex) {
137                     throw new ParseException("Symbolic Link Depth (symLink) is not a number.");
138                 }
139             }
140         }
141     }
142 
143     /**
144      * Validates whether or not the path(s) points at a file that exists; if the path(s) does not point to an existing file a
145      * FileNotFoundException is thrown.
146      *
147      * @param paths the paths to validate if they exists
148      * @param optType the option being validated (e.g. scan, out, etc.)
149      * @throws FileNotFoundException is thrown if one of the paths being validated does not exist.
150      */
151     private void validatePathExists(String[] paths, String optType) throws FileNotFoundException {
152         for (String path : paths) {
153             validatePathExists(path, optType);
154         }
155     }
156 
157     /**
158      * Validates whether or not the path points at a file that exists; if the path does not point to an existing file a
159      * FileNotFoundException is thrown.
160      *
161      * @param path the paths to validate if they exists
162      * @param argumentName the argument being validated (e.g. scan, out, etc.)
163      * @throws FileNotFoundException is thrown if the path being validated does not exist.
164      */
165     private void validatePathExists(String path, String argumentName) throws FileNotFoundException {
166         if (path == null) {
167             isValid = false;
168             final String msg = String.format("Invalid '%s' argument: null", argumentName);
169             throw new FileNotFoundException(msg);
170         } else if (!path.contains("*") && !path.contains("?")) {
171             File f = new File(path);
172             if ("o".equalsIgnoreCase(argumentName.substring(0, 1)) && !"ALL".equalsIgnoreCase(this.getReportFormat())) {
173                 final String checkPath = path.toLowerCase();
174                 if (checkPath.endsWith(".html") || checkPath.endsWith(".xml") || checkPath.endsWith(".htm")) {
175                     if (f.getParentFile() == null) {
176                         f = new File(".", path);
177                     }
178                     if (!f.getParentFile().isDirectory()) {
179                         isValid = false;
180                         final String msg = String.format("Invalid '%s' argument: '%s'", argumentName, path);
181                         throw new FileNotFoundException(msg);
182                     }
183                 }
184             } else {
185                 if (!f.exists()) {
186                     isValid = false;
187                     final String msg = String.format("Invalid '%s' argument: '%s'", argumentName, path);
188                     throw new FileNotFoundException(msg);
189                 }
190             }
191         } else if (path.startsWith("//") || path.startsWith("\\\\")) {
192             isValid = false;
193             final String msg = String.format("Invalid '%s' argument: '%s'%nUnable to scan paths that start with '//'.", argumentName, path);
194             throw new FileNotFoundException(msg);
195         }
196     }
197 
198     /**
199      * Generates an Options collection that is used to parse the command line and to display the help message.
200      *
201      * @return the command line options used for parsing the command line
202      */
203     @SuppressWarnings("static-access")
204     private Options createCommandLineOptions() {
205         final Options options = new Options();
206         addStandardOptions(options);
207         addAdvancedOptions(options);
208         addDeprecatedOptions(options);
209         return options;
210     }
211 
212     /**
213      * Adds the standard command line options to the given options collection.
214      *
215      * @param options a collection of command line arguments
216      * @throws IllegalArgumentException thrown if there is an exception
217      */
218     @SuppressWarnings("static-access")
219     private void addStandardOptions(final Options options) throws IllegalArgumentException {
220         final Option help = new Option(ARGUMENT.HELP_SHORT, ARGUMENT.HELP, false,
221                 "Print this message.");
222 
223         final Option advancedHelp = Option.builder().longOpt(ARGUMENT.ADVANCED_HELP)
224                 .desc("Print the advanced help message.").build();
225 
226         final Option version = new Option(ARGUMENT.VERSION_SHORT, ARGUMENT.VERSION,
227                 false, "Print the version information.");
228 
229         final Option noUpdate = new Option(ARGUMENT.DISABLE_AUTO_UPDATE_SHORT, ARGUMENT.DISABLE_AUTO_UPDATE,
230                 false, "Disables the automatic updating of the CPE data.");
231 
232         final Option projectName = Option.builder().hasArg().argName("name").longOpt(ARGUMENT.PROJECT)
233                 .desc("The name of the project being scanned. This is a required argument.")
234                 .build();
235 
236         final Option path = Option.builder(ARGUMENT.SCAN_SHORT).argName("path").hasArg().longOpt(ARGUMENT.SCAN)
237                 .desc("The path to scan - this option can be specified multiple times. Ant style"
238                         + " paths are supported (e.g. path/**/*.jar).")
239                 .build();
240 
241         final Option excludes = Option.builder().argName("pattern").hasArg().longOpt(ARGUMENT.EXCLUDE)
242                 .desc("Specify and exclusion pattern. This option can be specified multiple times"
243                         + " and it accepts Ant style excludsions.")
244                 .build();
245 
246         final Option props = Option.builder(ARGUMENT.PROP_SHORT).argName("file").hasArg().longOpt(ARGUMENT.PROP)
247                 .desc("A property file to load.")
248                 .build();
249 
250         final Option out = Option.builder(ARGUMENT.OUT_SHORT).argName("path").hasArg().longOpt(ARGUMENT.OUT)
251                 .desc("The folder to write reports to. This defaults to the current directory. "
252                         + "It is possible to set this to a specific file name if the format argument is not set to ALL.")
253                 .build();
254 
255         final Option outputFormat = Option.builder(ARGUMENT.OUTPUT_FORMAT_SHORT).argName("format").hasArg().longOpt(ARGUMENT.OUTPUT_FORMAT)
256                 .desc("The output format to write to (XML, HTML, VULN, ALL). The default is HTML.")
257                 .build();
258 
259         final Option verboseLog = Option.builder(ARGUMENT.VERBOSE_LOG_SHORT).argName("file").hasArg().longOpt(ARGUMENT.VERBOSE_LOG)
260                 .desc("The file path to write verbose logging information.")
261                 .build();
262 
263         final Option symLinkDepth = Option.builder().argName("depth").hasArg().longOpt(ARGUMENT.SYM_LINK_DEPTH)
264                 .desc("Sets how deep nested symbolic links will be followed; 0 indicates symbolic links will not be followed.")
265                 .build();
266 
267         final Option suppressionFile = Option.builder().argName("file").hasArg().longOpt(ARGUMENT.SUPPRESSION_FILE)
268                 .desc("The file path to the suppression XML file.")
269                 .build();
270 
271         final Option cveValidForHours = Option.builder().argName("hours").hasArg().longOpt(ARGUMENT.CVE_VALID_FOR_HOURS)
272                 .desc("The number of hours to wait before checking for new updates from the NVD.")
273                 .build();
274 
275         //This is an option group because it can be specified more then once.
276         final OptionGroup og = new OptionGroup();
277         og.addOption(path);
278 
279         final OptionGroup exog = new OptionGroup();
280         exog.addOption(excludes);
281 
282         options.addOptionGroup(og)
283                 .addOptionGroup(exog)
284                 .addOption(projectName)
285                 .addOption(out)
286                 .addOption(outputFormat)
287                 .addOption(version)
288                 .addOption(help)
289                 .addOption(advancedHelp)
290                 .addOption(noUpdate)
291                 .addOption(symLinkDepth)
292                 .addOption(props)
293                 .addOption(verboseLog)
294                 .addOption(suppressionFile)
295                 .addOption(cveValidForHours);
296     }
297 
298     /**
299      * Adds the advanced command line options to the given options collection. These are split out for purposes of being able to
300      * display two different help messages.
301      *
302      * @param options a collection of command line arguments
303      * @throws IllegalArgumentException thrown if there is an exception
304      */
305     @SuppressWarnings("static-access")
306     private void addAdvancedOptions(final Options options) throws IllegalArgumentException {
307 
308         final Option cve12Base = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_BASE_12)
309                 .desc("Base URL for each year’s CVE 1.2, the %d will be replaced with the year. ")
310                 .build();
311 
312         final Option cve20Base = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_BASE_20)
313                 .desc("Base URL for each year’s CVE 2.0, the %d will be replaced with the year.")
314                 .build();
315 
316         final Option cve12Modified = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_MOD_12)
317                 .desc("URL for the modified CVE 1.2.")
318                 .build();
319 
320         final Option cve20Modified = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_MOD_20)
321                 .desc("URL for the modified CVE 2.0.")
322                 .build();
323 
324         final Option updateOnly = Option.builder().longOpt(ARGUMENT.UPDATE_ONLY)
325                 .desc("Only update the local NVD data cache; no scan will be executed.").build();
326 
327         final Option data = Option.builder(ARGUMENT.DATA_DIRECTORY_SHORT).argName("path").hasArg().longOpt(ARGUMENT.DATA_DIRECTORY)
328                 .desc("The location of the H2 Database file. This option should generally not be set.")
329                 .build();
330 
331         final Option nexusUrl = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.NEXUS_URL)
332                 .desc("The url to the Nexus Server's REST API Endpoint (http://domain/nexus/service/local). "
333                         + "If not set the Nexus Analyzer will be disabled.").build();
334 
335         final Option nexusUsesProxy = Option.builder().argName("true/false").hasArg().longOpt(ARGUMENT.NEXUS_USES_PROXY)
336                 .desc("Whether or not the configured proxy should be used when connecting to Nexus.")
337                 .build();
338 
339         final Option additionalZipExtensions = Option.builder().argName("extensions").hasArg()
340                 .longOpt(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS)
341                 .desc("A comma separated list of additional extensions to be scanned as ZIP files "
342                         + "(ZIP, EAR, WAR are already treated as zip files)").build();
343 
344         final Option pathToMono = Option.builder().argName("path").hasArg().longOpt(ARGUMENT.PATH_TO_MONO)
345                 .desc("The path to Mono for .NET Assembly analysis on non-windows systems.")
346                 .build();
347         
348         final Option pathToBundleAudit = Option.builder().argName("path").hasArg()
349                 .longOpt(ARGUMENT.PATH_TO_BUNDLE_AUDIT)
350                 .desc("The path to bundle-audit for Gem bundle analysis.").build();
351 
352         final Option connectionTimeout = Option.builder(ARGUMENT.CONNECTION_TIMEOUT_SHORT).argName("timeout").hasArg()
353                 .longOpt(ARGUMENT.CONNECTION_TIMEOUT).desc("The connection timeout (in milliseconds) to use when downloading resources.")
354                 .build();
355 
356         final Option proxyServer = Option.builder().argName("server").hasArg().longOpt(ARGUMENT.PROXY_SERVER)
357                 .desc("The proxy server to use when downloading resources.").build();
358 
359         final Option proxyPort = Option.builder().argName("port").hasArg().longOpt(ARGUMENT.PROXY_PORT)
360                 .desc("The proxy port to use when downloading resources.").build();
361 
362         final Option proxyUsername = Option.builder().argName("user").hasArg().longOpt(ARGUMENT.PROXY_USERNAME)
363                 .desc("The proxy username to use when downloading resources.").build();
364 
365         final Option proxyPassword = Option.builder().argName("pass").hasArg().longOpt(ARGUMENT.PROXY_PASSWORD)
366                 .desc("The proxy password to use when downloading resources.").build();
367 
368         final Option connectionString = Option.builder().argName("connStr").hasArg().longOpt(ARGUMENT.CONNECTION_STRING)
369                 .desc("The connection string to the database.").build();
370 
371         final Option dbUser = Option.builder().argName("user").hasArg().longOpt(ARGUMENT.DB_NAME)
372                 .desc("The username used to connect to the database.").build();
373 
374         final Option dbPassword = Option.builder().argName("password").hasArg().longOpt(ARGUMENT.DB_PASSWORD)
375                 .desc("The password for connecting to the database.").build();
376 
377         final Option dbDriver = Option.builder().argName("driver").hasArg().longOpt(ARGUMENT.DB_DRIVER)
378                 .desc("The database driver name.").build();
379 
380         final Option dbDriverPath = Option.builder().argName("path").hasArg().longOpt(ARGUMENT.DB_DRIVER_PATH)
381                 .desc("The path to the database driver; note, this does not need to be set unless the JAR is outside of the classpath.")
382                 .build();
383 
384         final Option disableJarAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_JAR)
385                 .desc("Disable the Jar Analyzer.").build();
386 
387         final Option disableArchiveAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_ARCHIVE)
388                 .desc("Disable the Archive Analyzer.").build();
389 
390         final Option disableNuspecAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_NUSPEC)
391                 .desc("Disable the Nuspec Analyzer.").build();
392 
393         final Option disableAssemblyAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_ASSEMBLY)
394                 .desc("Disable the .NET Assembly Analyzer.").build();
395 
396         final Option disablePythonDistributionAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_PY_DIST)
397                 .desc("Disable the Python Distribution Analyzer.").build();
398 
399         final Option disablePythonPackageAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_PY_PKG)
400                 .desc("Disable the Python Package Analyzer.").build();
401 
402         final Option disableComposerAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_COMPOSER)
403                 .desc("Disable the PHP Composer Analyzer.").build();
404 
405         final Option disableAutoconfAnalyzer = Option.builder()
406                 .longOpt(ARGUMENT.DISABLE_AUTOCONF)
407                 .desc("Disable the Autoconf Analyzer.").build();
408 
409         final Option disableOpenSSLAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_OPENSSL)
410                 .desc("Disable the OpenSSL Analyzer.").build();
411         final Option disableCmakeAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_CMAKE)
412                 .desc("Disable the Cmake Analyzer.").build();
413 
414         final Option disableCentralAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_CENTRAL)
415                 .desc("Disable the Central Analyzer. If this analyzer is disabled it is likely you also want to disable "
416                         + "the Nexus Analyzer.").build();
417 
418         final Option disableNexusAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_NEXUS)
419                 .desc("Disable the Nexus Analyzer.").build();
420 
421         final Option purge = Option.builder().longOpt(ARGUMENT.PURGE_NVD)
422                 .desc("Purges the local NVD data cache")
423                 .build();
424 
425         options.addOption(updateOnly)
426                 .addOption(cve12Base)
427                 .addOption(cve20Base)
428                 .addOption(cve12Modified)
429                 .addOption(cve20Modified)
430                 .addOption(proxyPort)
431                 .addOption(proxyServer)
432                 .addOption(proxyUsername)
433                 .addOption(proxyPassword)
434                 .addOption(connectionTimeout)
435                 .addOption(connectionString)
436                 .addOption(dbUser)
437                 .addOption(data)
438                 .addOption(dbPassword)
439                 .addOption(dbDriver)
440                 .addOption(dbDriverPath)
441                 .addOption(disableJarAnalyzer)
442                 .addOption(disableArchiveAnalyzer)
443                 .addOption(disableAssemblyAnalyzer)
444                 .addOption(pathToBundleAudit)
445                 .addOption(disablePythonDistributionAnalyzer)
446                 .addOption(disableCmakeAnalyzer)
447                 .addOption(disablePythonPackageAnalyzer)
448                 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_RUBYGEMS)
449                         .desc("Disable the Ruby Gemspec Analyzer.").build())
450                 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_BUNDLE_AUDIT)
451                         .desc("Disable the Ruby Bundler-Audit Analyzer.").build())
452                 .addOption(disableAutoconfAnalyzer)
453                 .addOption(disableComposerAnalyzer)
454                 .addOption(disableOpenSSLAnalyzer)
455                 .addOption(disableNuspecAnalyzer)
456                 .addOption(disableCentralAnalyzer)
457                 .addOption(disableNexusAnalyzer)
458                 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_NODE_JS)
459                         .desc("Disable the Node.js Package Analyzer.").build())
460                 .addOption(nexusUrl)
461                 .addOption(nexusUsesProxy)
462                 .addOption(additionalZipExtensions)
463                 .addOption(pathToMono)
464                 .addOption(pathToBundleAudit)
465                 .addOption(purge);
466     }
467 
468     /**
469      * Adds the deprecated command line options to the given options collection. These are split out for purposes of not including
470      * them in the help message. We need to add the deprecated options so as not to break existing scripts.
471      *
472      * @param options a collection of command line arguments
473      * @throws IllegalArgumentException thrown if there is an exception
474      */
475     @SuppressWarnings({"static-access", "deprecation"})
476     private void addDeprecatedOptions(final Options options) throws IllegalArgumentException {
477 
478         final Option proxyServer = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.PROXY_URL)
479                 .desc("The proxy url argument is deprecated, use proxyserver instead.")
480                 .build();
481         final Option appName = Option.builder(ARGUMENT.APP_NAME_SHORT).argName("name").hasArg().longOpt(ARGUMENT.APP_NAME)
482                 .desc("The name of the project being scanned.")
483                 .build();
484 
485         options.addOption(proxyServer);
486         options.addOption(appName);
487     }
488 
489     /**
490      * Determines if the 'version' command line argument was passed in.
491      *
492      * @return whether or not the 'version' command line argument was passed in
493      */
494     public boolean isGetVersion() {
495         return (line != null) && line.hasOption(ARGUMENT.VERSION);
496     }
497 
498     /**
499      * Determines if the 'help' command line argument was passed in.
500      *
501      * @return whether or not the 'help' command line argument was passed in
502      */
503     public boolean isGetHelp() {
504         return (line != null) && line.hasOption(ARGUMENT.HELP);
505     }
506 
507     /**
508      * Determines if the 'scan' command line argument was passed in.
509      *
510      * @return whether or not the 'scan' command line argument was passed in
511      */
512     public boolean isRunScan() {
513         return (line != null) && isValid && line.hasOption(ARGUMENT.SCAN);
514     }
515 
516     /**
517      * Returns the symbolic link depth (how deeply symbolic links will be followed).
518      *
519      * @return the symbolic link depth
520      */
521     public int getSymLinkDepth() {
522         int value = 0;
523         try {
524             value = Integer.parseInt(line.getOptionValue(ARGUMENT.SYM_LINK_DEPTH, "0"));
525             if (value < 0) {
526                 value = 0;
527             }
528         } catch (NumberFormatException ex) {
529             LOGGER.debug("Symbolic link was not a number");
530         }
531         return value;
532     }
533 
534     /**
535      * Returns true if the disableJar command line argument was specified.
536      *
537      * @return true if the disableJar command line argument was specified; otherwise false
538      */
539     public boolean isJarDisabled() {
540         return (line != null) && line.hasOption(ARGUMENT.DISABLE_JAR);
541     }
542 
543     /**
544      * Returns true if the disableArchive command line argument was specified.
545      *
546      * @return true if the disableArchive command line argument was specified; otherwise false
547      */
548     public boolean isArchiveDisabled() {
549         return (line != null) && line.hasOption(ARGUMENT.DISABLE_ARCHIVE);
550     }
551 
552     /**
553      * Returns true if the disableNuspec command line argument was specified.
554      *
555      * @return true if the disableNuspec command line argument was specified; otherwise false
556      */
557     public boolean isNuspecDisabled() {
558         return (line != null) && line.hasOption(ARGUMENT.DISABLE_NUSPEC);
559     }
560 
561     /**
562      * Returns true if the disableAssembly command line argument was specified.
563      *
564      * @return true if the disableAssembly command line argument was specified; otherwise false
565      */
566     public boolean isAssemblyDisabled() {
567         return (line != null) && line.hasOption(ARGUMENT.DISABLE_ASSEMBLY);
568     }
569 
570     /**
571      * Returns true if the disableBundleAudit command line argument was specified.
572      *
573      * @return true if the disableBundleAudit command line argument was specified; otherwise false
574      */
575     public boolean isBundleAuditDisabled() {
576         return (line != null) && line.hasOption(ARGUMENT.DISABLE_BUNDLE_AUDIT);
577     }
578 
579 
580     /**
581      * Returns true if the disablePyDist command line argument was specified.
582      *
583      * @return true if the disablePyDist command line argument was specified; otherwise false
584      */
585     public boolean isPythonDistributionDisabled() {
586         return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_DIST);
587     }
588 
589     /**
590      * Returns true if the disablePyPkg command line argument was specified.
591      *
592      * @return true if the disablePyPkg command line argument was specified; otherwise false
593      */
594     public boolean isPythonPackageDisabled() {
595         return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_PKG);
596     }
597 
598     /**
599      * Returns whether the Ruby gemspec analyzer is disabled.
600      *
601      * @return true if the {@link ARGUMENT#DISABLE_RUBYGEMS} command line argument was specified; otherwise false
602      */
603     public boolean isRubyGemspecDisabled() {
604         return (null != line) && line.hasOption(ARGUMENT.DISABLE_RUBYGEMS);
605     }
606 
607     /**
608      * Returns true if the disableCmake command line argument was specified.
609      *
610      * @return true if the disableCmake command line argument was specified; otherwise false
611      */
612     public boolean isCmakeDisabled() {
613         return (line != null) && line.hasOption(ARGUMENT.DISABLE_CMAKE);
614     }
615 
616     /**
617      * Returns true if the disableAutoconf command line argument was specified.
618      *
619      * @return true if the disableAutoconf command line argument was specified; otherwise false
620      */
621     public boolean isAutoconfDisabled() {
622         return (line != null) && line.hasOption(ARGUMENT.DISABLE_AUTOCONF);
623     }
624 
625     /**
626      * Returns true if the disableComposer command line argument was specified.
627      *
628      * @return true if the disableComposer command line argument was specified; otherwise false
629      */
630     public boolean isComposerDisabled() {
631         return (line != null) && line.hasOption(ARGUMENT.DISABLE_COMPOSER);
632     }
633 
634     /**
635      * Returns true if the disableNexus command line argument was specified.
636      *
637      * @return true if the disableNexus command line argument was specified; otherwise false
638      */
639     public boolean isNexusDisabled() {
640         return (line != null) && line.hasOption(ARGUMENT.DISABLE_NEXUS);
641     }
642 
643     /**
644      * Returns true if the disableOpenSSL command line argument was specified.
645      *
646      * @return true if the disableOpenSSL command line argument was specified; otherwise false
647      */
648     public boolean isOpenSSLDisabled() {
649         return (line != null) && line.hasOption(ARGUMENT.DISABLE_OPENSSL);
650     }
651 
652     /**
653      * Returns true if the disableNodeJS command line argument was specified.
654      *
655      * @return true if the disableNodeJS command line argument was specified; otherwise false
656      */
657     public boolean isNodeJsDisabled() {
658         return (line != null) && line.hasOption(ARGUMENT.DISABLE_NODE_JS);
659     }
660 
661     /**
662      * Returns true if the disableCentral command line argument was specified.
663      *
664      * @return true if the disableCentral command line argument was specified; otherwise false
665      */
666     public boolean isCentralDisabled() {
667         return (line != null) && line.hasOption(ARGUMENT.DISABLE_CENTRAL);
668     }
669 
670     /**
671      * Returns the url to the nexus server if one was specified.
672      *
673      * @return the url to the nexus server; if none was specified this will return null;
674      */
675     public String getNexusUrl() {
676         if (line == null || !line.hasOption(ARGUMENT.NEXUS_URL)) {
677             return null;
678         } else {
679             return line.getOptionValue(ARGUMENT.NEXUS_URL);
680         }
681     }
682 
683     /**
684      * Returns true if the Nexus Analyzer should use the configured proxy to connect to Nexus; otherwise false is returned.
685      *
686      * @return true if the Nexus Analyzer should use the configured proxy to connect to Nexus; otherwise false
687      */
688     public boolean isNexusUsesProxy() {
689         // If they didn't specify whether Nexus needs to use the proxy, we should
690         // still honor the property if it's set.
691         if (line == null || !line.hasOption(ARGUMENT.NEXUS_USES_PROXY)) {
692             try {
693                 return Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY);
694             } catch (InvalidSettingException ise) {
695                 return true;
696             }
697         } else {
698             return Boolean.parseBoolean(line.getOptionValue(ARGUMENT.NEXUS_USES_PROXY));
699         }
700     }
701 
702     /**
703      * Displays the command line help message to the standard output.
704      */
705     public void printHelp() {
706         final HelpFormatter formatter = new HelpFormatter();
707         final Options options = new Options();
708         addStandardOptions(options);
709         if (line != null && line.hasOption(ARGUMENT.ADVANCED_HELP)) {
710             addAdvancedOptions(options);
711         }
712         final String helpMsg = String.format("%n%s"
713                 + " can be used to identify if there are any known CVE vulnerabilities in libraries utilized by an application. "
714                 + "%s will automatically update required data from the Internet, such as the CVE and CPE data files from nvd.nist.gov.%n%n",
715                 Settings.getString("application.name", "DependencyCheck"),
716                 Settings.getString("application.name", "DependencyCheck"));
717 
718         formatter.printHelp(Settings.getString("application.name", "DependencyCheck"),
719                 helpMsg,
720                 options,
721                 "",
722                 true);
723     }
724 
725     /**
726      * Retrieves the file command line parameter(s) specified for the 'scan' argument.
727      *
728      * @return the file paths specified on the command line for scan
729      */
730     public String[] getScanFiles() {
731         return line.getOptionValues(ARGUMENT.SCAN);
732     }
733 
734     /**
735      * Retrieves the list of excluded file patterns specified by the 'exclude' argument.
736      *
737      * @return the excluded file patterns
738      */
739     public String[] getExcludeList() {
740         return line.getOptionValues(ARGUMENT.EXCLUDE);
741     }
742 
743     /**
744      * Returns the directory to write the reports to specified on the command line.
745      *
746      * @return the path to the reports directory.
747      */
748     public String getReportDirectory() {
749         return line.getOptionValue(ARGUMENT.OUT, ".");
750     }
751 
752     /**
753      * Returns the path to Mono for .NET Assembly analysis on non-windows systems.
754      *
755      * @return the path to Mono
756      */
757     public String getPathToMono() {
758         return line.getOptionValue(ARGUMENT.PATH_TO_MONO);
759     }
760 
761     /**
762      * Returns the path to bundle-audit for Ruby bundle analysis.
763      *
764      * @return the path to Mono
765      */
766     public String getPathToBundleAudit() {
767         return line.getOptionValue(ARGUMENT.PATH_TO_BUNDLE_AUDIT);
768     }
769 
770     /**
771      * Returns the output format specified on the command line. Defaults to HTML if no format was specified.
772      *
773      * @return the output format name.
774      */
775     public String getReportFormat() {
776         return line.getOptionValue(ARGUMENT.OUTPUT_FORMAT, "HTML");
777     }
778 
779     /**
780      * Returns the application name specified on the command line.
781      *
782      * @return the application name.
783      */
784     public String getProjectName() {
785         final String appName = line.getOptionValue(ARGUMENT.APP_NAME);
786         String name = line.getOptionValue(ARGUMENT.PROJECT);
787         if (name == null && appName != null) {
788             name = appName;
789             LOGGER.warn("The '" + ARGUMENT.APP_NAME + "' argument should no longer be used; use '" + ARGUMENT.PROJECT + "' instead.");
790         }
791         return name;
792     }
793 
794     /**
795      * Returns the base URL for the CVE 1.2 XMl file.
796      *
797      * @return the URL to the CVE 1.2 XML file.
798      */
799     public String getBaseCve12Url() {
800         return line.getOptionValue(ARGUMENT.CVE_BASE_12);
801     }
802 
803     /**
804      * Returns the base URL for the CVE 2.0 XMl file.
805      *
806      * @return the URL to the CVE 2.0 XML file.
807      */
808     public String getBaseCve20Url() {
809         return line.getOptionValue(ARGUMENT.CVE_BASE_20);
810     }
811 
812     /**
813      * Returns the URL for the modified CVE 1.2 XMl file.
814      *
815      * @return the URL to the modified CVE 1.2 XML file.
816      */
817     public String getModifiedCve12Url() {
818         return line.getOptionValue(ARGUMENT.CVE_MOD_12);
819     }
820 
821     /**
822      * Returns the URL for the modified CVE 2.0 XMl file.
823      *
824      * @return the URL to the modified CVE 2.0 XML file.
825      */
826     public String getModifiedCve20Url() {
827         return line.getOptionValue(ARGUMENT.CVE_MOD_20);
828     }
829 
830     /**
831      * Returns the connection timeout.
832      *
833      * @return the connection timeout
834      */
835     public String getConnectionTimeout() {
836         return line.getOptionValue(ARGUMENT.CONNECTION_TIMEOUT);
837     }
838 
839     /**
840      * Returns the proxy server.
841      *
842      * @return the proxy server
843      */
844     @SuppressWarnings("deprecation")
845     public String getProxyServer() {
846 
847         String server = line.getOptionValue(ARGUMENT.PROXY_SERVER);
848         if (server == null) {
849             server = line.getOptionValue(ARGUMENT.PROXY_URL);
850             if (server != null) {
851                 LOGGER.warn("An old command line argument 'proxyurl' was detected; use proxyserver instead");
852             }
853         }
854         return server;
855     }
856 
857     /**
858      * Returns the proxy port.
859      *
860      * @return the proxy port
861      */
862     public String getProxyPort() {
863         return line.getOptionValue(ARGUMENT.PROXY_PORT);
864     }
865 
866     /**
867      * Returns the proxy username.
868      *
869      * @return the proxy username
870      */
871     public String getProxyUsername() {
872         return line.getOptionValue(ARGUMENT.PROXY_USERNAME);
873     }
874 
875     /**
876      * Returns the proxy password.
877      *
878      * @return the proxy password
879      */
880     public String getProxyPassword() {
881         return line.getOptionValue(ARGUMENT.PROXY_PASSWORD);
882     }
883 
884     /**
885      * Get the value of dataDirectory.
886      *
887      * @return the value of dataDirectory
888      */
889     public String getDataDirectory() {
890         return line.getOptionValue(ARGUMENT.DATA_DIRECTORY);
891     }
892 
893     /**
894      * Returns the properties file specified on the command line.
895      *
896      * @return the properties file specified on the command line
897      */
898     public File getPropertiesFile() {
899         final String path = line.getOptionValue(ARGUMENT.PROP);
900         if (path != null) {
901             return new File(path);
902         }
903         return null;
904     }
905 
906     /**
907      * Returns the path to the verbose log file.
908      *
909      * @return the path to the verbose log file
910      */
911     public String getVerboseLog() {
912         return line.getOptionValue(ARGUMENT.VERBOSE_LOG);
913     }
914 
915     /**
916      * Returns the path to the suppression file.
917      *
918      * @return the path to the suppression file
919      */
920     public String getSuppressionFile() {
921         return line.getOptionValue(ARGUMENT.SUPPRESSION_FILE);
922     }
923 
924     /**
925      * <p>
926      * Prints the manifest information to standard output.</p>
927      * <ul><li>Implementation-Title: ${pom.name}</li>
928      * <li>Implementation-Version: ${pom.version}</li></ul>
929      */
930     public void printVersionInfo() {
931         final String version = String.format("%s version %s",
932                 Settings.getString(Settings.KEYS.APPLICATION_VAME, "dependency-check"),
933                 Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown"));
934         System.out.println(version);
935     }
936 
937     /**
938      * Checks if the auto update feature has been disabled. If it has been disabled via the command line this will return false.
939      *
940      * @return <code>true</code> if auto-update is allowed; otherwise <code>false</code>
941      */
942     public boolean isAutoUpdate() {
943         return line != null && !line.hasOption(ARGUMENT.DISABLE_AUTO_UPDATE);
944     }
945 
946     /**
947      * Checks if the update only flag has been set.
948      *
949      * @return <code>true</code> if the update only flag has been set; otherwise <code>false</code>.
950      */
951     public boolean isUpdateOnly() {
952         return line != null && line.hasOption(ARGUMENT.UPDATE_ONLY);
953     }
954 
955     /**
956      * Checks if the purge NVD flag has been set.
957      *
958      * @return <code>true</code> if the purge nvd flag has been set; otherwise <code>false</code>.
959      */
960     public boolean isPurge() {
961         return line != null && line.hasOption(ARGUMENT.PURGE_NVD);
962     }
963 
964     /**
965      * Returns the database driver name if specified; otherwise null is returned.
966      *
967      * @return the database driver name if specified; otherwise null is returned
968      */
969     public String getDatabaseDriverName() {
970         return line.getOptionValue(ARGUMENT.DB_DRIVER);
971     }
972 
973     /**
974      * Returns the database driver path if specified; otherwise null is returned.
975      *
976      * @return the database driver name if specified; otherwise null is returned
977      */
978     public String getDatabaseDriverPath() {
979         return line.getOptionValue(ARGUMENT.DB_DRIVER_PATH);
980     }
981 
982     /**
983      * Returns the database connection string if specified; otherwise null is returned.
984      *
985      * @return the database connection string if specified; otherwise null is returned
986      */
987     public String getConnectionString() {
988         return line.getOptionValue(ARGUMENT.CONNECTION_STRING);
989     }
990 
991     /**
992      * Returns the database database user name if specified; otherwise null is returned.
993      *
994      * @return the database database user name if specified; otherwise null is returned
995      */
996     public String getDatabaseUser() {
997         return line.getOptionValue(ARGUMENT.DB_NAME);
998     }
999 
1000     /**
1001      * Returns the database database password if specified; otherwise null is returned.
1002      *
1003      * @return the database database password if specified; otherwise null is returned
1004      */
1005     public String getDatabasePassword() {
1006         return line.getOptionValue(ARGUMENT.DB_PASSWORD);
1007     }
1008 
1009     /**
1010      * Returns the additional Extensions if specified; otherwise null is returned.
1011      *
1012      * @return the additional Extensions; otherwise null is returned
1013      */
1014     public String getAdditionalZipExtensions() {
1015         return line.getOptionValue(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS);
1016     }
1017 
1018     /**
1019      * Get the value of cveValidForHours.
1020      *
1021      * @return the value of cveValidForHours
1022      */
1023     public Integer getCveValidForHours() {
1024         final String v = line.getOptionValue(ARGUMENT.CVE_VALID_FOR_HOURS);
1025         if (v != null) {
1026             return Integer.parseInt(v);
1027         }
1028         return null;
1029     }
1030 
1031     /**
1032      * A collection of static final strings that represent the possible command line arguments.
1033      */
1034     public static class ARGUMENT {
1035 
1036         /**
1037          * The long CLI argument name specifying the directory/file to scan.
1038          */
1039         public static final String SCAN = "scan";
1040         /**
1041          * The short CLI argument name specifying the directory/file to scan.
1042          */
1043         public static final String SCAN_SHORT = "s";
1044         /**
1045          * The long CLI argument name specifying that the CPE/CVE/etc. data should not be automatically updated.
1046          */
1047         public static final String DISABLE_AUTO_UPDATE = "noupdate";
1048         /**
1049          * The short CLI argument name specifying that the CPE/CVE/etc. data should not be automatically updated.
1050          */
1051         public static final String DISABLE_AUTO_UPDATE_SHORT = "n";
1052         /**
1053          * The long CLI argument name specifying that only the update phase should be executed; no scan should be run.
1054          */
1055         public static final String UPDATE_ONLY = "updateonly";
1056         /**
1057          * The long CLI argument name specifying that only the update phase should be executed; no scan should be run.
1058          */
1059         public static final String PURGE_NVD = "purge";
1060         /**
1061          * The long CLI argument name specifying the directory to write the reports to.
1062          */
1063         public static final String OUT = "out";
1064         /**
1065          * The short CLI argument name specifying the directory to write the reports to.
1066          */
1067         public static final String OUT_SHORT = "o";
1068         /**
1069          * The long CLI argument name specifying the output format to write the reports to.
1070          */
1071         public static final String OUTPUT_FORMAT = "format";
1072         /**
1073          * The short CLI argument name specifying the output format to write the reports to.
1074          */
1075         public static final String OUTPUT_FORMAT_SHORT = "f";
1076         /**
1077          * The long CLI argument name specifying the name of the project to be scanned.
1078          */
1079         public static final String PROJECT = "project";
1080         /**
1081          * The long CLI argument name specifying the name of the application to be scanned.
1082          *
1083          * @deprecated project should be used instead
1084          */
1085         @Deprecated
1086         public static final String APP_NAME = "app";
1087         /**
1088          * The short CLI argument name specifying the name of the application to be scanned.
1089          *
1090          * @deprecated project should be used instead
1091          */
1092         @Deprecated
1093         public static final String APP_NAME_SHORT = "a";
1094         /**
1095          * The long CLI argument name asking for help.
1096          */
1097         public static final String HELP = "help";
1098         /**
1099          * The long CLI argument name asking for advanced help.
1100          */
1101         public static final String ADVANCED_HELP = "advancedHelp";
1102         /**
1103          * The short CLI argument name asking for help.
1104          */
1105         public static final String HELP_SHORT = "h";
1106         /**
1107          * The long CLI argument name asking for the version.
1108          */
1109         public static final String VERSION_SHORT = "v";
1110         /**
1111          * The short CLI argument name asking for the version.
1112          */
1113         public static final String VERSION = "version";
1114         /**
1115          * The CLI argument name indicating the proxy port.
1116          */
1117         public static final String PROXY_PORT = "proxyport";
1118         /**
1119          * The CLI argument name indicating the proxy server.
1120          */
1121         public static final String PROXY_SERVER = "proxyserver";
1122         /**
1123          * The CLI argument name indicating the proxy url.
1124          *
1125          * @deprecated use {@link #PROXY_SERVER} instead
1126          */
1127         @Deprecated
1128         public static final String PROXY_URL = "proxyurl";
1129         /**
1130          * The CLI argument name indicating the proxy username.
1131          */
1132         public static final String PROXY_USERNAME = "proxyuser";
1133         /**
1134          * The CLI argument name indicating the proxy password.
1135          */
1136         public static final String PROXY_PASSWORD = "proxypass";
1137         /**
1138          * The short CLI argument name indicating the connection timeout.
1139          */
1140         public static final String CONNECTION_TIMEOUT_SHORT = "c";
1141         /**
1142          * The CLI argument name indicating the connection timeout.
1143          */
1144         public static final String CONNECTION_TIMEOUT = "connectiontimeout";
1145         /**
1146          * The short CLI argument name for setting the location of an additional properties file.
1147          */
1148         public static final String PROP_SHORT = "P";
1149         /**
1150          * The CLI argument name for setting the location of an additional properties file.
1151          */
1152         public static final String PROP = "propertyfile";
1153         /**
1154          * The CLI argument name for setting the location of the data directory.
1155          */
1156         public static final String DATA_DIRECTORY = "data";
1157         /**
1158          * The CLI argument name for setting the URL for the CVE Data Files.
1159          */
1160         public static final String CVE_MOD_12 = "cveUrl12Modified";
1161         /**
1162          * The CLI argument name for setting the URL for the CVE Data Files.
1163          */
1164         public static final String CVE_MOD_20 = "cveUrl20Modified";
1165         /**
1166          * The CLI argument name for setting the URL for the CVE Data Files.
1167          */
1168         public static final String CVE_BASE_12 = "cveUrl12Base";
1169         /**
1170          * The CLI argument name for setting the URL for the CVE Data Files.
1171          */
1172         public static final String CVE_BASE_20 = "cveUrl20Base";
1173         /**
1174          * The short CLI argument name for setting the location of the data directory.
1175          */
1176         public static final String DATA_DIRECTORY_SHORT = "d";
1177         /**
1178          * The CLI argument name for setting the location of the data directory.
1179          */
1180         public static final String VERBOSE_LOG = "log";
1181         /**
1182          * The short CLI argument name for setting the location of the data directory.
1183          */
1184         public static final String VERBOSE_LOG_SHORT = "l";
1185 
1186         /**
1187          * The CLI argument name for setting the depth of symbolic links that will be followed.
1188          */
1189         public static final String SYM_LINK_DEPTH = "symLink";
1190         /**
1191          * The CLI argument name for setting the location of the suppression file.
1192          */
1193         public static final String SUPPRESSION_FILE = "suppression";
1194         /**
1195          * The CLI argument name for setting the location of the suppression file.
1196          */
1197         public static final String CVE_VALID_FOR_HOURS = "cveValidForHours";
1198         /**
1199          * Disables the Jar Analyzer.
1200          */
1201         public static final String DISABLE_JAR = "disableJar";
1202         /**
1203          * Disables the Archive Analyzer.
1204          */
1205         public static final String DISABLE_ARCHIVE = "disableArchive";
1206         /**
1207          * Disables the Python Distribution Analyzer.
1208          */
1209         public static final String DISABLE_PY_DIST = "disablePyDist";
1210         /**
1211          * Disables the Python Package Analyzer.
1212          */
1213         public static final String DISABLE_PY_PKG = "disablePyPkg";
1214         /**
1215          * Disables the Python Package Analyzer.
1216          */
1217         public static final String DISABLE_COMPOSER = "disableComposer";
1218         /**
1219          * Disables the Ruby Gemspec Analyzer.
1220          */
1221         public static final String DISABLE_RUBYGEMS = "disableRubygems";
1222         /**
1223          * Disables the Autoconf Analyzer.
1224          */
1225         public static final String DISABLE_AUTOCONF = "disableAutoconf";
1226         /**
1227          * Disables the Cmake Analyzer.
1228          */
1229         public static final String DISABLE_CMAKE = "disableCmake";
1230         /**
1231          * Disables the Assembly Analyzer.
1232          */
1233         public static final String DISABLE_ASSEMBLY = "disableAssembly";
1234         /**
1235          * Disables the Ruby Bundler Audit Analyzer.
1236          */
1237         public static final String DISABLE_BUNDLE_AUDIT = "disableBundleAudit";
1238         /**
1239          * Disables the Nuspec Analyzer.
1240          */
1241         public static final String DISABLE_NUSPEC = "disableNuspec";
1242         /**
1243          * Disables the Central Analyzer.
1244          */
1245         public static final String DISABLE_CENTRAL = "disableCentral";
1246         /**
1247          * Disables the Nexus Analyzer.
1248          */
1249         public static final String DISABLE_NEXUS = "disableNexus";
1250         /**
1251          * Disables the OpenSSL Analyzer.
1252          */
1253         public static final String DISABLE_OPENSSL = "disableOpenSSL";
1254         /**
1255          * Disables the Node.js Package Analyzer.
1256          */
1257         public static final String DISABLE_NODE_JS = "disableNodeJS";
1258         /**
1259          * The URL of the nexus server.
1260          */
1261         public static final String NEXUS_URL = "nexus";
1262         /**
1263          * Whether or not the defined proxy should be used when connecting to Nexus.
1264          */
1265         public static final String NEXUS_USES_PROXY = "nexusUsesProxy";
1266         /**
1267          * The CLI argument name for setting the connection string.
1268          */
1269         public static final String CONNECTION_STRING = "connectionString";
1270         /**
1271          * The CLI argument name for setting the database user name.
1272          */
1273         public static final String DB_NAME = "dbUser";
1274         /**
1275          * The CLI argument name for setting the database password.
1276          */
1277         public static final String DB_PASSWORD = "dbPassword";
1278         /**
1279          * The CLI argument name for setting the database driver name.
1280          */
1281         public static final String DB_DRIVER = "dbDriverName";
1282         /**
1283          * The CLI argument name for setting the path to the database driver; in case it is not on the class path.
1284          */
1285         public static final String DB_DRIVER_PATH = "dbDriverPath";
1286         /**
1287          * The CLI argument name for setting the path to mono for .NET Assembly analysis on non-windows systems.
1288          */
1289         public static final String PATH_TO_MONO = "mono";
1290         /**
1291          * The CLI argument name for setting extra extensions.
1292          */
1293         public static final String ADDITIONAL_ZIP_EXTENSIONS = "zipExtensions";
1294         /**
1295          * Exclude path argument.
1296          */
1297         public static final String EXCLUDE = "exclude";
1298         /**
1299          * The CLI argument name for setting the path to bundle-audit for Ruby bundle analysis.
1300          */
1301         public static final String PATH_TO_BUNDLE_AUDIT = "bundleAudit";
1302     }
1303 }