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  import java.util.logging.Logger;
23  
24  import org.apache.commons.cli.CommandLine;
25  import org.apache.commons.cli.CommandLineParser;
26  import org.apache.commons.cli.HelpFormatter;
27  import org.apache.commons.cli.Option;
28  import org.apache.commons.cli.OptionBuilder;
29  import org.apache.commons.cli.OptionGroup;
30  import org.apache.commons.cli.Options;
31  import org.apache.commons.cli.ParseException;
32  import org.apache.commons.cli.PosixParser;
33  import org.owasp.dependencycheck.reporting.ReportGenerator.Format;
34  import org.owasp.dependencycheck.utils.InvalidSettingException;
35  import org.owasp.dependencycheck.utils.Settings;
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 = Logger.getLogger(CliParser.class.getName());
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 PosixParser();
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 (isRunScan()) {
94              validatePathExists(getScanFiles(), ARGUMENT.SCAN);
95              validatePathExists(getReportDirectory(), ARGUMENT.OUT);
96              if (getPathToMono() != null) {
97                  validatePathExists(getPathToMono(), ARGUMENT.PATH_TO_MONO);
98              }
99              if (!line.hasOption(ARGUMENT.APP_NAME)) {
100                 throw new ParseException("Missing 'app' argument; the scan cannot be run without the an application name.");
101             }
102             if (line.hasOption(ARGUMENT.OUTPUT_FORMAT)) {
103                 final String format = line.getOptionValue(ARGUMENT.OUTPUT_FORMAT);
104                 try {
105                     Format.valueOf(format);
106                 } catch (IllegalArgumentException ex) {
107                     final String msg = String.format("An invalid 'format' of '%s' was specified. "
108                             + "Supported output formats are XML, HTML, VULN, or ALL", format);
109                     throw new ParseException(msg);
110                 }
111             }
112         }
113     }
114 
115     /**
116      * 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
117      * FileNotFoundException is thrown.
118      *
119      * @param paths the paths to validate if they exists
120      * @param optType the option being validated (e.g. scan, out, etc.)
121      * @throws FileNotFoundException is thrown if one of the paths being validated does not exist.
122      */
123     private void validatePathExists(String[] paths, String optType) throws FileNotFoundException {
124         for (String path : paths) {
125             validatePathExists(path, optType);
126         }
127     }
128 
129     /**
130      * Validates whether or not the path points at a file that exists; if the path does not point to an existing file a
131      * FileNotFoundException is thrown.
132      *
133      * @param path the paths to validate if they exists
134      * @param argumentName the argument being validated (e.g. scan, out, etc.)
135      * @throws FileNotFoundException is thrown if the path being validated does not exist.
136      */
137     private void validatePathExists(String path, String argumentName) throws FileNotFoundException {
138         if (path == null) {
139             isValid = false;
140             final String msg = String.format("Invalid '%s' argument: null", argumentName);
141             throw new FileNotFoundException(msg);
142         } else if (!path.contains("*") && !path.contains("?")) {
143             File f = new File(path);
144             if ("o".equalsIgnoreCase(argumentName.substring(0, 1)) && !"ALL".equalsIgnoreCase(this.getReportFormat())) {
145                 final String checkPath = path.toLowerCase();
146                 if (checkPath.endsWith(".html") || checkPath.endsWith(".xml") || checkPath.endsWith(".htm")) {
147                     if (f.getParentFile() == null) {
148                         f = new File(".", path);
149                     }
150                     if (!f.getParentFile().isDirectory()) {
151                         isValid = false;
152                         final String msg = String.format("Invalid '%s' argument: '%s'", argumentName, path);
153                         throw new FileNotFoundException(msg);
154                     }
155                 }
156             } else {
157                 if (!f.exists()) {
158                     isValid = false;
159                     final String msg = String.format("Invalid '%s' argument: '%s'", argumentName, path);
160                     throw new FileNotFoundException(msg);
161                 }
162             }
163         } else if (path.startsWith("//") || path.startsWith("\\\\")) {
164             isValid = false;
165             final String msg = String.format("Invalid '%s' argument: '%s'%nUnable to scan paths that start with '//'.", argumentName, path);
166             throw new FileNotFoundException(msg);
167         }
168     }
169 
170     /**
171      * Generates an Options collection that is used to parse the command line and to display the help message.
172      *
173      * @return the command line options used for parsing the command line
174      */
175     @SuppressWarnings("static-access")
176     private Options createCommandLineOptions() {
177         final Options options = new Options();
178         addStandardOptions(options);
179         addAdvancedOptions(options);
180         addDeprecatedOptions(options);
181         return options;
182     }
183 
184     /**
185      * Adds the standard command line options to the given options collection.
186      *
187      * @param options a collection of command line arguments
188      * @throws IllegalArgumentException thrown if there is an exception
189      */
190     @SuppressWarnings("static-access")
191     private void addStandardOptions(final Options options) throws IllegalArgumentException {
192         final Option help = new Option(ARGUMENT.HELP_SHORT, ARGUMENT.HELP, false,
193                 "Print this message.");
194 
195         final Option advancedHelp = OptionBuilder.withLongOpt(ARGUMENT.ADVANCED_HELP)
196                 .withDescription("Print the advanced help message.").create();
197 
198         final Option version = new Option(ARGUMENT.VERSION_SHORT, ARGUMENT.VERSION,
199                 false, "Print the version information.");
200 
201         final Option noUpdate = new Option(ARGUMENT.DISABLE_AUTO_UPDATE_SHORT, ARGUMENT.DISABLE_AUTO_UPDATE,
202                 false, "Disables the automatic updating of the CPE data.");
203 
204         final Option appName = OptionBuilder.withArgName("name").hasArg().withLongOpt(ARGUMENT.APP_NAME)
205                 .withDescription("The name of the application being scanned. This is a required argument.")
206                 .create(ARGUMENT.APP_NAME_SHORT);
207 
208         final Option path = OptionBuilder.withArgName("path").hasArg().withLongOpt(ARGUMENT.SCAN)
209                 .withDescription("The path to scan - this option can be specified multiple times. Ant style"
210                         + " paths are supported (e.g. path/**/*.jar).")
211                 .create(ARGUMENT.SCAN_SHORT);
212 
213         final Option excludes = OptionBuilder.withArgName("pattern").hasArg().withLongOpt(ARGUMENT.EXCLUDE)
214                 .withDescription("Specify and exclusion pattern. This option can be specified multiple times"
215                         + " and it accepts Ant style excludsions.")
216                 .create();
217 
218         final Option props = OptionBuilder.withArgName("file").hasArg().withLongOpt(ARGUMENT.PROP)
219                 .withDescription("A property file to load.")
220                 .create(ARGUMENT.PROP_SHORT);
221 
222         final Option out = OptionBuilder.withArgName("path").hasArg().withLongOpt(ARGUMENT.OUT)
223                 .withDescription("The folder to write reports to. This defaults to the current directory. "
224                         + "It is possible to set this to a specific file name if the format argument is not set to ALL.")
225                 .create(ARGUMENT.OUT_SHORT);
226 
227         final Option outputFormat = OptionBuilder.withArgName("format").hasArg().withLongOpt(ARGUMENT.OUTPUT_FORMAT)
228                 .withDescription("The output format to write to (XML, HTML, VULN, ALL). The default is HTML.")
229                 .create(ARGUMENT.OUTPUT_FORMAT_SHORT);
230 
231         final Option verboseLog = OptionBuilder.withArgName("file").hasArg().withLongOpt(ARGUMENT.VERBOSE_LOG)
232                 .withDescription("The file path to write verbose logging information.")
233                 .create(ARGUMENT.VERBOSE_LOG_SHORT);
234 
235         final Option suppressionFile = OptionBuilder.withArgName("file").hasArg().withLongOpt(ARGUMENT.SUPPRESSION_FILE)
236                 .withDescription("The file path to the suppression XML file.")
237                 .create();
238 
239         //This is an option group because it can be specified more then once.
240         final OptionGroup og = new OptionGroup();
241         og.addOption(path);
242 
243         final OptionGroup exog = new OptionGroup();
244         exog.addOption(excludes);
245 
246         options.addOptionGroup(og)
247                 .addOptionGroup(exog)
248                 .addOption(out)
249                 .addOption(outputFormat)
250                 .addOption(appName)
251                 .addOption(version)
252                 .addOption(help)
253                 .addOption(advancedHelp)
254                 .addOption(noUpdate)
255                 .addOption(props)
256                 .addOption(verboseLog)
257                 .addOption(suppressionFile);
258     }
259 
260     /**
261      * Adds the advanced command line options to the given options collection. These are split out for purposes of being able to
262      * display two different help messages.
263      *
264      * @param options a collection of command line arguments
265      * @throws IllegalArgumentException thrown if there is an exception
266      */
267     @SuppressWarnings("static-access")
268     private void addAdvancedOptions(final Options options) throws IllegalArgumentException {
269 
270         final Option updateOnly = OptionBuilder.withLongOpt(ARGUMENT.UPDATE_ONLY)
271                 .withDescription("Only update the local NVD data cache; no scan will be executed.").create();
272 
273         final Option data = OptionBuilder.withArgName("path").hasArg().withLongOpt(ARGUMENT.DATA_DIRECTORY)
274                 .withDescription("The location of the H2 Database file. This option should generally not be set.")
275                 .create(ARGUMENT.DATA_DIRECTORY_SHORT);
276 
277         final Option connectionTimeout = OptionBuilder.withArgName("timeout").hasArg().withLongOpt(ARGUMENT.CONNECTION_TIMEOUT)
278                 .withDescription("The connection timeout (in milliseconds) to use when downloading resources.")
279                 .create(ARGUMENT.CONNECTION_TIMEOUT_SHORT);
280 
281         final Option proxyServer = OptionBuilder.withArgName("server").hasArg().withLongOpt(ARGUMENT.PROXY_SERVER)
282                 .withDescription("The proxy server to use when downloading resources.")
283                 .create();
284 
285         final Option proxyPort = OptionBuilder.withArgName("port").hasArg().withLongOpt(ARGUMENT.PROXY_PORT)
286                 .withDescription("The proxy port to use when downloading resources.")
287                 .create();
288 
289         final Option proxyUsername = OptionBuilder.withArgName("user").hasArg().withLongOpt(ARGUMENT.PROXY_USERNAME)
290                 .withDescription("The proxy username to use when downloading resources.")
291                 .create();
292 
293         final Option proxyPassword = OptionBuilder.withArgName("pass").hasArg().withLongOpt(ARGUMENT.PROXY_PASSWORD)
294                 .withDescription("The proxy password to use when downloading resources.")
295                 .create();
296 
297         final Option connectionString = OptionBuilder.withArgName("connStr").hasArg().withLongOpt(ARGUMENT.CONNECTION_STRING)
298                 .withDescription("The connection string to the database.")
299                 .create();
300 
301         final Option dbUser = OptionBuilder.withArgName("user").hasArg().withLongOpt(ARGUMENT.DB_NAME)
302                 .withDescription("The username used to connect to the database.")
303                 .create();
304 
305         final Option dbPassword = OptionBuilder.withArgName("password").hasArg().withLongOpt(ARGUMENT.DB_PASSWORD)
306                 .withDescription("The password for connecting to the database.")
307                 .create();
308 
309         final Option dbDriver = OptionBuilder.withArgName("driver").hasArg().withLongOpt(ARGUMENT.DB_DRIVER)
310                 .withDescription("The database driver name.")
311                 .create();
312 
313         final Option dbDriverPath = OptionBuilder.withArgName("path").hasArg().withLongOpt(ARGUMENT.DB_DRIVER_PATH)
314                 .withDescription("The path to the database driver; note, this does not need to be set unless the JAR is outside of the classpath.")
315                 .create();
316 
317         final Option disableJarAnalyzer = OptionBuilder.withLongOpt(ARGUMENT.DISABLE_JAR)
318                 .withDescription("Disable the Jar Analyzer.")
319                 .create();
320         final Option disableArchiveAnalyzer = OptionBuilder.withLongOpt(ARGUMENT.DISABLE_ARCHIVE)
321                 .withDescription("Disable the Archive Analyzer.")
322                 .create();
323         final Option disableNuspecAnalyzer = OptionBuilder.withLongOpt(ARGUMENT.DISABLE_NUSPEC)
324                 .withDescription("Disable the Nuspec Analyzer.")
325                 .create();
326 
327         final Option disableAssemblyAnalyzer = OptionBuilder.withLongOpt(ARGUMENT.DISABLE_ASSEMBLY)
328                 .withDescription("Disable the .NET Assembly Analyzer.")
329                 .create();
330 
331         final Option disablePythonDistributionAnalyzer = OptionBuilder.withLongOpt(ARGUMENT.DISABLE_PY_DIST)
332                 .withDescription("Disable the Python Distribution Analyzer.").create();
333 
334         final Option disablePythonPackageAnalyzer = OptionBuilder.withLongOpt(ARGUMENT.DISABLE_PY_PKG)
335                 .withDescription("Disable the Python Package Analyzer.").create();
336 
337         final Option disableCentralAnalyzer = OptionBuilder.withLongOpt(ARGUMENT.DISABLE_CENTRAL)
338                 .withDescription("Disable the Central Analyzer. If this analyzer is disabled it is likely you also want to disable "
339                         + "the Nexus Analyzer.")
340                 .create();
341 
342         final Option disableNexusAnalyzer = OptionBuilder.withLongOpt(ARGUMENT.DISABLE_NEXUS)
343                 .withDescription("Disable the Nexus Analyzer.")
344                 .create();
345 
346         final Option nexusUrl = OptionBuilder.withArgName("url").hasArg().withLongOpt(ARGUMENT.NEXUS_URL)
347                 .withDescription("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.")
349                 .create();
350 
351         final Option nexusUsesProxy = OptionBuilder.withArgName("true/false").hasArg().withLongOpt(ARGUMENT.NEXUS_USES_PROXY)
352                 .withDescription("Whether or not the configured proxy should be used when connecting to Nexus.")
353                 .create();
354 
355         final Option additionalZipExtensions = OptionBuilder.withArgName("extensions").hasArg()
356                 .withLongOpt(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS)
357                 .withDescription("A comma separated list of additional extensions to be scanned as ZIP files "
358                         + "(ZIP, EAR, WAR are already treated as zip files)")
359                 .create();
360 
361         final Option pathToMono = OptionBuilder.withArgName("path").hasArg().withLongOpt(ARGUMENT.PATH_TO_MONO)
362                 .withDescription("The path to Mono for .NET Assembly analysis on non-windows systems.")
363                 .create();
364 
365         options.addOption(updateOnly)
366                 .addOption(proxyPort)
367                 .addOption(proxyServer)
368                 .addOption(proxyUsername)
369                 .addOption(proxyPassword)
370                 .addOption(connectionTimeout)
371                 .addOption(connectionString)
372                 .addOption(dbUser)
373                 .addOption(data)
374                 .addOption(dbPassword)
375                 .addOption(dbDriver)
376                 .addOption(dbDriverPath)
377                 .addOption(disableJarAnalyzer)
378                 .addOption(disableArchiveAnalyzer)
379                 .addOption(disableAssemblyAnalyzer)
380                 .addOption(disablePythonDistributionAnalyzer)
381                 .addOption(disablePythonPackageAnalyzer)
382                 .addOption(disableNuspecAnalyzer)
383                 .addOption(disableCentralAnalyzer)
384                 .addOption(disableNexusAnalyzer)
385                 .addOption(nexusUrl)
386                 .addOption(nexusUsesProxy)
387                 .addOption(additionalZipExtensions)
388                 .addOption(pathToMono);
389     }
390 
391     /**
392      * Adds the deprecated command line options to the given options collection. These are split out for purposes of not including
393      * them in the help message. We need to add the deprecated options so as not to break existing scripts.
394      *
395      * @param options a collection of command line arguments
396      * @throws IllegalArgumentException thrown if there is an exception
397      */
398     @SuppressWarnings("static-access")
399     private void addDeprecatedOptions(final Options options) throws IllegalArgumentException {
400 
401         final Option proxyServer = OptionBuilder.withArgName("url").hasArg().withLongOpt(ARGUMENT.PROXY_URL)
402                 .withDescription("The proxy url argument is deprecated, use proxyserver instead.")
403                 .create();
404 
405         options.addOption(proxyServer);
406     }
407 
408     /**
409      * Determines if the 'version' command line argument was passed in.
410      *
411      * @return whether or not the 'version' command line argument was passed in
412      */
413     public boolean isGetVersion() {
414         return (line != null) && line.hasOption(ARGUMENT.VERSION);
415     }
416 
417     /**
418      * Determines if the 'help' command line argument was passed in.
419      *
420      * @return whether or not the 'help' command line argument was passed in
421      */
422     public boolean isGetHelp() {
423         return (line != null) && line.hasOption(ARGUMENT.HELP);
424     }
425 
426     /**
427      * Determines if the 'scan' command line argument was passed in.
428      *
429      * @return whether or not the 'scan' command line argument was passed in
430      */
431     public boolean isRunScan() {
432         return (line != null) && isValid && line.hasOption(ARGUMENT.SCAN);
433     }
434 
435     /**
436      * Returns true if the disableJar command line argument was specified.
437      *
438      * @return true if the disableJar command line argument was specified; otherwise false
439      */
440     public boolean isJarDisabled() {
441         return (line != null) && line.hasOption(ARGUMENT.DISABLE_JAR);
442     }
443 
444     /**
445      * Returns true if the disableArchive command line argument was specified.
446      *
447      * @return true if the disableArchive command line argument was specified; otherwise false
448      */
449     public boolean isArchiveDisabled() {
450         return (line != null) && line.hasOption(ARGUMENT.DISABLE_ARCHIVE);
451     }
452 
453     /**
454      * Returns true if the disableNuspec command line argument was specified.
455      *
456      * @return true if the disableNuspec command line argument was specified; otherwise false
457      */
458     public boolean isNuspecDisabled() {
459         return (line != null) && line.hasOption(ARGUMENT.DISABLE_NUSPEC);
460     }
461 
462     /**
463      * Returns true if the disableAssembly command line argument was specified.
464      *
465      * @return true if the disableAssembly command line argument was specified; otherwise false
466      */
467     public boolean isAssemblyDisabled() {
468         return (line != null) && line.hasOption(ARGUMENT.DISABLE_ASSEMBLY);
469     }
470 
471     /**
472      * Returns true if the disablePyDist command line argument was specified.
473      *
474      * @return true if the disablePyDist command line argument was specified; otherwise false
475      */
476     public boolean isPythonDistributionDisabled() {
477         return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_DIST);
478     }
479 
480     /**
481      * Returns true if the disablePyPkg command line argument was specified.
482      *
483      * @return true if the disablePyPkg command line argument was specified; otherwise false
484      */
485     public boolean isPythonPackageDisabled() {
486         return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_PKG);
487     }
488 
489     /**
490      * Returns true if the disableNexus command line argument was specified.
491      *
492      * @return true if the disableNexus command line argument was specified; otherwise false
493      */
494     public boolean isNexusDisabled() {
495         return (line != null) && line.hasOption(ARGUMENT.DISABLE_NEXUS);
496     }
497 
498     /**
499      * Returns true if the disableCentral command line argument was specified.
500      *
501      * @return true if the disableCentral command line argument was specified; otherwise false
502      */
503     public boolean isCentralDisabled() {
504         return (line != null) && line.hasOption(ARGUMENT.DISABLE_CENTRAL);
505     }
506 
507     /**
508      * Returns the url to the nexus server if one was specified.
509      *
510      * @return the url to the nexus server; if none was specified this will return null;
511      */
512     public String getNexusUrl() {
513         if (line == null || !line.hasOption(ARGUMENT.NEXUS_URL)) {
514             return null;
515         } else {
516             return line.getOptionValue(ARGUMENT.NEXUS_URL);
517         }
518     }
519 
520     /**
521      * Returns true if the Nexus Analyzer should use the configured proxy to connect to Nexus; otherwise false is returned.
522      *
523      * @return true if the Nexus Analyzer should use the configured proxy to connect to Nexus; otherwise false
524      */
525     public boolean isNexusUsesProxy() {
526         // If they didn't specify whether Nexus needs to use the proxy, we should
527         // still honor the property if it's set.
528         if (line == null || !line.hasOption(ARGUMENT.NEXUS_USES_PROXY)) {
529             try {
530                 return Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY);
531             } catch (InvalidSettingException ise) {
532                 return true;
533             }
534         } else {
535             return Boolean.parseBoolean(line.getOptionValue(ARGUMENT.NEXUS_USES_PROXY));
536         }
537     }
538 
539     /**
540      * Displays the command line help message to the standard output.
541      */
542     public void printHelp() {
543         final HelpFormatter formatter = new HelpFormatter();
544         final Options options = new Options();
545         addStandardOptions(options);
546         if (line != null && line.hasOption(ARGUMENT.ADVANCED_HELP)) {
547             addAdvancedOptions(options);
548         }
549         final String helpMsg = String.format("%n%s"
550                 + " can be used to identify if there are any known CVE vulnerabilities in libraries utilized by an application. "
551                 + "%s will automatically update required data from the Internet, such as the CVE and CPE data files from nvd.nist.gov.%n%n",
552                 Settings.getString("application.name", "DependencyCheck"),
553                 Settings.getString("application.name", "DependencyCheck"));
554 
555         formatter.printHelp(Settings.getString("application.name", "DependencyCheck"),
556                 helpMsg,
557                 options,
558                 "",
559                 true);
560     }
561 
562     /**
563      * Retrieves the file command line parameter(s) specified for the 'scan' argument.
564      *
565      * @return the file paths specified on the command line for scan
566      */
567     public String[] getScanFiles() {
568         return line.getOptionValues(ARGUMENT.SCAN);
569     }
570 
571     /**
572      * Retrieves the list of excluded file patterns specified by the 'exclude' argument.
573      *
574      * @return the excluded file patterns
575      */
576     public String[] getExcludeList() {
577         return line.getOptionValues(ARGUMENT.EXCLUDE);
578     }
579 
580     /**
581      * Returns the directory to write the reports to specified on the command line.
582      *
583      * @return the path to the reports directory.
584      */
585     public String getReportDirectory() {
586         return line.getOptionValue(ARGUMENT.OUT, ".");
587     }
588 
589     /**
590      * Returns the path to Mono for .NET Assembly analysis on non-windows systems.
591      *
592      * @return the path to Mono
593      */
594     public String getPathToMono() {
595         return line.getOptionValue(ARGUMENT.PATH_TO_MONO);
596     }
597 
598     /**
599      * Returns the output format specified on the command line. Defaults to HTML if no format was specified.
600      *
601      * @return the output format name.
602      */
603     public String getReportFormat() {
604         return line.getOptionValue(ARGUMENT.OUTPUT_FORMAT, "HTML");
605     }
606 
607     /**
608      * Returns the application name specified on the command line.
609      *
610      * @return the application name.
611      */
612     public String getApplicationName() {
613         return line.getOptionValue(ARGUMENT.APP_NAME);
614     }
615 
616     /**
617      * Returns the connection timeout.
618      *
619      * @return the connection timeout
620      */
621     public String getConnectionTimeout() {
622         return line.getOptionValue(ARGUMENT.CONNECTION_TIMEOUT);
623     }
624 
625     /**
626      * Returns the proxy server.
627      *
628      * @return the proxy server
629      */
630     public String getProxyServer() {
631 
632         String server = line.getOptionValue(ARGUMENT.PROXY_SERVER);
633         if (server == null) {
634             server = line.getOptionValue(ARGUMENT.PROXY_URL);
635             if (server != null) {
636                 LOGGER.warning("An old command line argument 'proxyurl' was detected; use proxyserver instead");
637             }
638         }
639         return server;
640     }
641 
642     /**
643      * Returns the proxy port.
644      *
645      * @return the proxy port
646      */
647     public String getProxyPort() {
648         return line.getOptionValue(ARGUMENT.PROXY_PORT);
649     }
650 
651     /**
652      * Returns the proxy username.
653      *
654      * @return the proxy username
655      */
656     public String getProxyUsername() {
657         return line.getOptionValue(ARGUMENT.PROXY_USERNAME);
658     }
659 
660     /**
661      * Returns the proxy password.
662      *
663      * @return the proxy password
664      */
665     public String getProxyPassword() {
666         return line.getOptionValue(ARGUMENT.PROXY_PASSWORD);
667     }
668 
669     /**
670      * Get the value of dataDirectory.
671      *
672      * @return the value of dataDirectory
673      */
674     public String getDataDirectory() {
675         return line.getOptionValue(ARGUMENT.DATA_DIRECTORY);
676     }
677 
678     /**
679      * Returns the properties file specified on the command line.
680      *
681      * @return the properties file specified on the command line
682      */
683     public File getPropertiesFile() {
684         final String path = line.getOptionValue(ARGUMENT.PROP);
685         if (path != null) {
686             return new File(path);
687         }
688         return null;
689     }
690 
691     /**
692      * Returns the path to the verbose log file.
693      *
694      * @return the path to the verbose log file
695      */
696     public String getVerboseLog() {
697         return line.getOptionValue(ARGUMENT.VERBOSE_LOG);
698     }
699 
700     /**
701      * Returns the path to the suppression file.
702      *
703      * @return the path to the suppression file
704      */
705     public String getSuppressionFile() {
706         return line.getOptionValue(ARGUMENT.SUPPRESSION_FILE);
707     }
708 
709     /**
710      * <p>
711      * Prints the manifest information to standard output.</p>
712      * <ul><li>Implementation-Title: ${pom.name}</li>
713      * <li>Implementation-Version: ${pom.version}</li></ul>
714      */
715     public void printVersionInfo() {
716         final String version = String.format("%s version %s",
717                 Settings.getString(Settings.KEYS.APPLICATION_VAME, "dependency-check"),
718                 Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown"));
719         System.out.println(version);
720     }
721 
722     /**
723      * Checks if the auto update feature has been disabled. If it has been disabled via the command line this will return false.
724      *
725      * @return <code>true</code> if auto-update is allowed; otherwise <code>false</code>
726      */
727     public boolean isAutoUpdate() {
728         return (line == null) || !line.hasOption(ARGUMENT.DISABLE_AUTO_UPDATE);
729     }
730 
731     /**
732      * Checks if the update only flag has been set.
733      *
734      * @return <code>true</code> if the update only flag has been set; otherwise <code>false</code>.
735      */
736     public boolean isUpdateOnly() {
737         return (line == null) || line.hasOption(ARGUMENT.UPDATE_ONLY);
738     }
739 
740     /**
741      * Returns the database driver name if specified; otherwise null is returned.
742      *
743      * @return the database driver name if specified; otherwise null is returned
744      */
745     public String getDatabaseDriverName() {
746         return line.getOptionValue(ARGUMENT.DB_DRIVER);
747     }
748 
749     /**
750      * Returns the database driver path if specified; otherwise null is returned.
751      *
752      * @return the database driver name if specified; otherwise null is returned
753      */
754     public String getDatabaseDriverPath() {
755         return line.getOptionValue(ARGUMENT.DB_DRIVER_PATH);
756     }
757 
758     /**
759      * Returns the database connection string if specified; otherwise null is returned.
760      *
761      * @return the database connection string if specified; otherwise null is returned
762      */
763     public String getConnectionString() {
764         return line.getOptionValue(ARGUMENT.CONNECTION_STRING);
765     }
766 
767     /**
768      * Returns the database database user name if specified; otherwise null is returned.
769      *
770      * @return the database database user name if specified; otherwise null is returned
771      */
772     public String getDatabaseUser() {
773         return line.getOptionValue(ARGUMENT.DB_NAME);
774     }
775 
776     /**
777      * Returns the database database password if specified; otherwise null is returned.
778      *
779      * @return the database database password if specified; otherwise null is returned
780      */
781     public String getDatabasePassword() {
782         return line.getOptionValue(ARGUMENT.DB_PASSWORD);
783     }
784 
785     /**
786      * Returns the additional Extensions if specified; otherwise null is returned.
787      *
788      * @return the additional Extensions; otherwise null is returned
789      */
790     public String getAdditionalZipExtensions() {
791         return line.getOptionValue(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS);
792     }
793 
794     /**
795      * A collection of static final strings that represent the possible command line arguments.
796      */
797     public static class ARGUMENT {
798 
799         /**
800          * The long CLI argument name specifying the directory/file to scan.
801          */
802         public static final String SCAN = "scan";
803         /**
804          * The short CLI argument name specifying the directory/file to scan.
805          */
806         public static final String SCAN_SHORT = "s";
807         /**
808          * The long CLI argument name specifying that the CPE/CVE/etc. data should not be automatically updated.
809          */
810         public static final String DISABLE_AUTO_UPDATE = "noupdate";
811         /**
812          * The short CLI argument name specifying that the CPE/CVE/etc. data should not be automatically updated.
813          */
814         public static final String DISABLE_AUTO_UPDATE_SHORT = "n";
815         /**
816          * The long CLI argument name specifying that only the update phase should be executed; no scan should be run.
817          */
818         public static final String UPDATE_ONLY = "updateonly";
819         /**
820          * The long CLI argument name specifying the directory to write the reports to.
821          */
822         public static final String OUT = "out";
823         /**
824          * The short CLI argument name specifying the directory to write the reports to.
825          */
826         public static final String OUT_SHORT = "o";
827         /**
828          * The long CLI argument name specifying the output format to write the reports to.
829          */
830         public static final String OUTPUT_FORMAT = "format";
831         /**
832          * The short CLI argument name specifying the output format to write the reports to.
833          */
834         public static final String OUTPUT_FORMAT_SHORT = "f";
835         /**
836          * The long CLI argument name specifying the name of the application to be scanned.
837          */
838         public static final String APP_NAME = "app";
839         /**
840          * The short CLI argument name specifying the name of the application to be scanned.
841          */
842         public static final String APP_NAME_SHORT = "a";
843         /**
844          * The long CLI argument name asking for help.
845          */
846         public static final String HELP = "help";
847         /**
848          * The long CLI argument name asking for advanced help.
849          */
850         public static final String ADVANCED_HELP = "advancedHelp";
851         /**
852          * The short CLI argument name asking for help.
853          */
854         public static final String HELP_SHORT = "h";
855         /**
856          * The long CLI argument name asking for the version.
857          */
858         public static final String VERSION_SHORT = "v";
859         /**
860          * The short CLI argument name asking for the version.
861          */
862         public static final String VERSION = "version";
863         /**
864          * The CLI argument name indicating the proxy port.
865          */
866         public static final String PROXY_PORT = "proxyport";
867         /**
868          * The CLI argument name indicating the proxy server.
869          */
870         public static final String PROXY_SERVER = "proxyserver";
871         /**
872          * The CLI argument name indicating the proxy url.
873          *
874          * @deprecated use {@link org.owasp.dependencycheck.cli.CliParser.ArgumentName#PROXY_SERVER} instead
875          */
876         @Deprecated
877         public static final String PROXY_URL = "proxyurl";
878         /**
879          * The CLI argument name indicating the proxy username.
880          */
881         public static final String PROXY_USERNAME = "proxyuser";
882         /**
883          * The CLI argument name indicating the proxy password.
884          */
885         public static final String PROXY_PASSWORD = "proxypass";
886         /**
887          * The short CLI argument name indicating the connection timeout.
888          */
889         public static final String CONNECTION_TIMEOUT_SHORT = "c";
890         /**
891          * The CLI argument name indicating the connection timeout.
892          */
893         public static final String CONNECTION_TIMEOUT = "connectiontimeout";
894         /**
895          * The short CLI argument name for setting the location of an additional properties file.
896          */
897         public static final String PROP_SHORT = "P";
898         /**
899          * The CLI argument name for setting the location of an additional properties file.
900          */
901         public static final String PROP = "propertyfile";
902         /**
903          * The CLI argument name for setting the location of the data directory.
904          */
905         public static final String DATA_DIRECTORY = "data";
906         /**
907          * The short CLI argument name for setting the location of the data directory.
908          */
909         public static final String DATA_DIRECTORY_SHORT = "d";
910         /**
911          * The CLI argument name for setting the location of the data directory.
912          */
913         public static final String VERBOSE_LOG = "log";
914         /**
915          * The short CLI argument name for setting the location of the data directory.
916          */
917         public static final String VERBOSE_LOG_SHORT = "l";
918         /**
919          * The CLI argument name for setting the location of the suppression file.
920          */
921         public static final String SUPPRESSION_FILE = "suppression";
922         /**
923          * Disables the Jar Analyzer.
924          */
925         public static final String DISABLE_JAR = "disableJar";
926         /**
927          * Disables the Archive Analyzer.
928          */
929         public static final String DISABLE_ARCHIVE = "disableArchive";
930         /**
931          * Disables the Python Distribution Analyzer.
932          */
933         public static final String DISABLE_PY_DIST = "disablePyDist";
934         /**
935          * Disables the Python Package Analyzer.
936          */
937         public static final String DISABLE_PY_PKG = "disablePyPkg";
938         /**
939          * Disables the Assembly Analyzer.
940          */
941         public static final String DISABLE_ASSEMBLY = "disableAssembly";
942         /**
943          * Disables the Nuspec Analyzer.
944          */
945         public static final String DISABLE_NUSPEC = "disableNuspec";
946         /**
947          * Disables the Central Analyzer.
948          */
949         public static final String DISABLE_CENTRAL = "disableCentral";
950         /**
951          * Disables the Nexus Analyzer.
952          */
953         public static final String DISABLE_NEXUS = "disableNexus";
954         /**
955          * The URL of the nexus server.
956          */
957         public static final String NEXUS_URL = "nexus";
958         /**
959          * Whether or not the defined proxy should be used when connecting to Nexus.
960          */
961         public static final String NEXUS_USES_PROXY = "nexusUsesProxy";
962         /**
963          * The CLI argument name for setting the connection string.
964          */
965         public static final String CONNECTION_STRING = "connectionString";
966         /**
967          * The CLI argument name for setting the database user name.
968          */
969         public static final String DB_NAME = "dbUser";
970         /**
971          * The CLI argument name for setting the database password.
972          */
973         public static final String DB_PASSWORD = "dbPassword";
974         /**
975          * The CLI argument name for setting the database driver name.
976          */
977         public static final String DB_DRIVER = "dbDriverName";
978         /**
979          * The CLI argument name for setting the path to the database driver; in case it is not on the class path.
980          */
981         public static final String DB_DRIVER_PATH = "dbDriverPath";
982         /**
983          * The CLI argument name for setting the path to mono for .NET Assembly analysis on non-windows systems.
984          */
985         public static final String PATH_TO_MONO = "mono";
986         /**
987          * The CLI argument name for setting extra extensions.
988          */
989         public static final String ADDITIONAL_ZIP_EXTENSIONS = "zipExtensions";
990         /**
991          * Exclude path argument.
992          */
993         public static final String EXCLUDE = "exclude";
994     }
995 }