Compare commits

..

146 Commits

Author SHA1 Message Date
Jeremy Long
f333ef76d9 version 1.2.6
Former-commit-id: d32ff0d840fc1d1a3153da73158adc125a589efc
2014-11-16 09:44:11 -05:00
Jeremy Long
af5ba6854e minor format change
Former-commit-id: 138be9fe55a362d21021b428b36ac65e621fd88a
2014-11-16 09:43:26 -05:00
Jeremy Long
8b7ce06793 initial version
Former-commit-id: efb4fec83ee9d788b3a5b21c683f52dd91113ec0
2014-11-16 08:25:13 -05:00
Jeremy Long
297a5e516f switched to using commons.io.FileUtils to delete files
Former-commit-id: e63309f20e7af759233db5486acc85f2c5c6806d
2014-11-16 08:24:55 -05:00
Jeremy Long
92b11526be updated log messages
Former-commit-id: 4f58ed64efbee2a2d604bdc5bd51394e152bd408
2014-11-16 08:24:17 -05:00
Jeremy Long
299350f655 correctly closed streams when extracting a gzip archive
Former-commit-id: 0a0c917cc3e4c4a004823fba9b7f8ab53f90d557
2014-11-16 06:21:02 -05:00
Jeremy Long
127eafc9b3 removed unused field
Former-commit-id: f44e6398f946abe2faa8ab1b2e3813a6831b9c66
2014-11-16 06:20:27 -05:00
Jeremy Long
ad1ad3a997 turned off checkstyle for a few lines
Former-commit-id: 62bf63649427363c0d86bd72acbb76a9772d1da3
2014-11-16 06:20:07 -05:00
Jeremy Long
82151c5b3f initial version of the test for DownloadTask
Former-commit-id: 5c82a5dda739525be25eed5ee763effe839758d0
2014-11-15 08:23:54 -05:00
Jeremy Long
90457c89ff updated NVD CVE URLs to use gzipped files
Former-commit-id: ca3c5ec40458f200a19cfcda36d518cf4de5a65a
2014-11-15 08:23:13 -05:00
Jeremy Long
3f3ac86d38 minor change to test cases
Former-commit-id: bbfc241e7576b508af819f7fe66892da0511e549
2014-11-15 08:22:43 -05:00
Jeremy Long
aa126039e5 updated NVD CVE URLs to use gzipped files
Former-commit-id: 25c0c2e5df3a6626fae5401209fac93b105b3392
2014-11-15 08:21:44 -05:00
Jeremy Long
662815b1ee added an extract phase if the downloaded file is a .gz
Former-commit-id: 0385e9a7922bc18eccb3b3075cc866c462ae6f2b
2014-11-15 08:21:03 -05:00
Jeremy Long
243c36849c noop
Former-commit-id: e155fa37527c62925bdb7e52d539329e3f9ebabe
2014-11-15 08:20:15 -05:00
Jeremy Long
52d5baaf3f reformated and added checkstyle corrections
Former-commit-id: c68e06287fdd09768c9fade7e534ca421899c9c5
2014-11-12 16:04:23 -05:00
Jeremy Long
89217f778e added package-info
Former-commit-id: 78bd4ce6243fadc58524ec48bb0d964205e044cd
2014-11-12 15:44:43 -05:00
Jeremy Long
9bc9bc9169 made enabled final
Former-commit-id: ded2d5de559091d8383ec26941f166018c33bb7a
2014-11-12 15:44:18 -05:00
Jeremy Long
6b73430473 added javadoc and changes suggested by checkstyle
Former-commit-id: 5f216b873b2d1845747fa4a77159399e818aef5a
2014-11-12 15:43:36 -05:00
Jeremy Long
5ca5bca3df updated javadoc
Former-commit-id: 7b00991a0cf90ca34c8c54b8297014b01e676b04
2014-11-11 15:13:01 -05:00
Jeremy Long
89ab382a18 added additional tests for compareto(version)
Former-commit-id: 0a02681251a30e6b675461b7487198a1cc7eb850
2014-11-11 14:43:47 -05:00
Jeremy Long
bad425c0d7 added test for isAffected
Former-commit-id: 36a6d28ff03e41307574ee40381b0833c5c4ab01
2014-11-11 14:43:15 -05:00
Jeremy Long
cdbbb1b94c made isAffected protected instead of private so that tests could be added
Former-commit-id: e7fd58900b4c8ebbaf06d476870defa4fc921628
2014-11-11 14:42:34 -05:00
Jeremy Long
0a9d8a9b22 reformated and changed logging level from info to fine
Former-commit-id: 035ca7c4d83322734f16f0b51f695bf7e4caa7b0
2014-11-11 14:41:40 -05:00
Jeremy Long
e662041d06 reformated and changed isEnabled to a getter by adding checkEnabled that is called during initialization
Former-commit-id: 3bfb0dd2da37d718708d047e425fb8b125dddf34
2014-11-11 14:41:08 -05:00
Jeremy Long
155464bc87 reformated and changed isEnabled to a getter by adding checkEnabled that is called during initialization
Former-commit-id: d5c1224709469fccacfad7e22cf5a44eecdcab36
2014-11-11 14:40:48 -05:00
Jeremy Long
06cd811ae4 fixed xlint unchecked call warnings
Former-commit-id: b74ee0e63568b7b222f0459ad66a7e281b2f2e2f
2014-11-11 13:41:20 -05:00
Jeremy Long
1b31268f59 Merge branch 'colezlaw-master'
Former-commit-id: fdb3a7414550752692ed807d71782f54cabbdac6
2014-11-10 05:41:10 -05:00
Will Stranathan
b57ef7291f No more separate proxy configuration for Central search. Renamed everything to do with Solr to Central.
Former-commit-id: 4bcee86abf4415bfafc386d10018d9fcb2f6cec4
2014-11-09 21:07:26 -05:00
Jeremy Long
c3bf6aa3f8 updated documentation to reflect change with NexusAnalyzer
Former-commit-id: 6a16bb3fc9f45a77d030d4d0f9999b764fd6fa12
2014-11-09 20:07:22 -05:00
Jeremy Long
d2fa14bbe2 updated documentation to reflect change with NexusAnalyzer
Former-commit-id: bbe1286d3ff9e4886b2eb52fe0ff04962922dd06
2014-11-09 20:06:32 -05:00
Jeremy Long
9b6e55e90c Merge branch 'colezlaw-master'
Former-commit-id: 80adf73356e1a2d24a53cf0f20af1356638084d8
2014-11-09 19:54:03 -05:00
Jeremy Long
afb07b651f Merge branch 'master' of github.com:colezlaw/DependencyCheck into colezlaw-master
Former-commit-id: 1158591ef47032ceed72654ebde6ef5f20782f75
2014-11-09 19:53:26 -05:00
Jeremy Long
e6806fdf2b patch to resolve issue #137 - the output path can be a file name if the format is not ALL
Former-commit-id: 05c638b21f09842781e105259ff58819e4bd3e8c
2014-11-09 19:52:42 -05:00
Will Stranathan
e5ff2cff4e Squashed commits for the new Solr/Central Search capability
Former-commit-id: 28ca3ca0ff5de4e097082f6f73003c0a67455efd
2014-11-08 10:54:02 -05:00
Will Stranathan
17d7d47b9a Renamed Solr to Central search
Former-commit-id: b8bdca6be89497f9baf29c8762803b4652e4974b
2014-11-08 10:53:17 -05:00
Will Stranathan
64e32061ab Re-making due to merge conflict from origin
Former-commit-id: 34a9f3410131b51048ee7f89e8aed2189dafe7fb
2014-11-08 08:50:53 -05:00
Will Stranathan
931110ba6c Initial checkin of work on a Solr analyzer which will replace Nexus on Internet checks
Former-commit-id: 09337f6416fa3140c00413426e17e39c4a1fadc6
2014-11-08 08:47:42 -05:00
Jeremy Long
d90e7820cd improved file path validation and error handling
Former-commit-id: 20d4011b031ac956e9803e807de75e7e505172ae
2014-11-08 06:08:21 -05:00
Jeremy Long
824898dba5 patch for issue #155
Former-commit-id: 57b144d94354c48c9bebabae2cc3d0c120fd2138
2014-11-07 06:42:54 -05:00
Jeremy Long
761dd61ed4 added additional test jar for issue #155
Former-commit-id: 0f8bf0a058eb263f13bd5d0d4262255153201eb5
2014-11-07 06:42:00 -05:00
Jeremy Long
89c63e6d87 checkstyle corrections
Former-commit-id: 77b519236f1afe7ad8eab0407d055e7f9ab4745f
2014-11-05 21:52:52 -05:00
Jeremy Long
a2361f9327 checkstyle corrections
Former-commit-id: b0ad94a8b1ce31891f788fd44e1a9df59775a691
2014-11-05 21:42:32 -05:00
Jeremy Long
ea15205be8 pmd corrections
Former-commit-id: 7cdc5b009285b9b428d4e731cb4b493a24453a9f
2014-11-05 21:31:00 -05:00
Jeremy Long
0a45048535 checkstyle corrections
Former-commit-id: 8807237a0a38f390298a19507ed55d9df156663f
2014-11-05 21:24:34 -05:00
Jeremy Long
1c51655ce3 checkstyle corrections
Former-commit-id: b7acf0b29d86a17f03f996d8d4b7a47e3a9f5eb9
2014-11-05 21:08:34 -05:00
Jeremy Long
7749f0da7c updated to exclude apache ant code from checkstyle
Former-commit-id: 06ab2cb9c3b15c182dac3cd1d0580f6002d607f8
2014-11-05 21:07:08 -05:00
Jeremy Long
5695238f95 updated to exclude apache ant code from PMD and findbugs
Former-commit-id: ce8b95e5f7ba4a98036cce46edc066ff2f2afb79
2014-11-05 21:06:23 -05:00
Jeremy Long
e1feeb7e21 removed failing test case
Former-commit-id: ab7f81d133a7c8cbfed52300e3f31a92121206b7
2014-11-05 19:18:41 -05:00
Jeremy Long
84fecaf040 updated documentation to show that Ant style paths and excludes can now be used
Former-commit-id: be99efc13478905e282d292986821a1851d0f389
2014-11-05 06:26:58 -05:00
Jeremy Long
da77727673 changes to support Ant style paths to resolve issue #153
Former-commit-id: b1666d6652891c4b012457fd5de7f8230938fb45
2014-11-05 06:20:15 -05:00
Jeremy Long
f8c913a3e8 small modification to warnings
Former-commit-id: 1ee729d27fdd7f394df0ea00efcb9f5e2bf663cd
2014-11-05 06:19:43 -05:00
Jeremy Long
2024881ee1 fixed logging level when files cannot be deleted
Former-commit-id: d62acbe447b5cc78b992d910c9431c006e658b2e
2014-11-05 06:19:14 -05:00
Jeremy Long
35ed3a51e5 initial version of InvalidScanPathException
Former-commit-id: a1f909f4e3988ae2f5f00fe72033bfdd7ef89676
2014-11-05 06:17:27 -05:00
Jeremy Long
24b1c4d0a4 removed wild card pattern matching during scan
Former-commit-id: 183963237c378641467f7277f68ba74156442485
2014-11-04 05:50:58 -05:00
Jeremy Long
7ec2458fb5 moved CliParser
Former-commit-id: 69ea743196109849d078df8f7071af0a3027fe99
2014-11-04 05:33:18 -05:00
Jeremy Long
175feaea23 added a modified copy of DirectoryScanner from Apache Ant to resolve issue #153
Former-commit-id: e37eb42cc574e4255533a0e7fbe78f5ed0c83146
2014-11-04 05:27:46 -05:00
Jeremy Long
dda6cf728b added suppression for opendj-ldap-sdk to fix issue #165
Former-commit-id: e8dc84bea2350eb5539475cf77650fafb118f3a4
2014-11-01 07:08:00 -04:00
Jeremy Long
a7fd410b01 stopped trimming org and com off of the groupid so it is consistent with other analyzers
Former-commit-id: c22d3b7af9af00c28ee0df80ba706f70399b80ef
2014-11-01 06:51:05 -04:00
Jeremy Long
d281c36733 updated suppression rule for jersey-client
Former-commit-id: 81920e19da3c29de46207c2132f225cb8c77a840
2014-11-01 06:35:28 -04:00
Jeremy Long
dc91e44c0a added jersey-client 1.11.1 as an optional test dependency
Former-commit-id: d837418656cbfd857adb90662a4d2604fd77a78e
2014-11-01 06:35:05 -04:00
Jeremy Long
7967a858f4 Merge branch 'ctrl-alt-dev-master'
Former-commit-id: 18b9ce0c578195a3275c4cb54ed14f6aff953d2b
2014-10-25 08:10:14 -04:00
Jeremy Long
2081407e38 added pom evidence to dependency - yes, this moves some analysis to the plugin; but in this case that is okay and will allow future enhancements
Former-commit-id: f69fd0701a8db1ab729199c4090dee1cd023d114
2014-10-25 08:09:45 -04:00
Jeremy Long
976eabd527 noop
Former-commit-id: 8c867c80dfb8180ba308837a09b33ac17fd8273a
2014-10-25 08:08:26 -04:00
Jeremy Long
b6d6a5de2b minor changes to clean up test cases
Former-commit-id: 62d409fa6f50d3bbec881277a4604acca7278faa
2014-10-25 08:07:56 -04:00
Jeremy Long
2d58cfe0ce fixed link to the NVD
Former-commit-id: 73ca530e569d4376999c155a8bc1256d935209bf
2014-10-25 08:07:20 -04:00
Jeremy Long
9df8bdff5f cleaned up code to use isEmpty instead of "".equals(string)
Former-commit-id: 8469f91a948ab2ab5b0ce61865a0b11cd6d11717
2014-10-25 08:06:56 -04:00
Jeremy Long
c86b821951 suppressed warning on unchecked cast
Former-commit-id: 633151a31b613071c7bd3e939c6a5c16864b8b88
2014-10-25 08:06:15 -04:00
Jeremy Long
4def086bf9 removed comments
Former-commit-id: 2c48f5b93a97a0642fbc37edd603b0d0baca4368
2014-10-25 08:05:26 -04:00
Jeremy Long
885c890d7d changed the analyzer to use the actual file name rather then the display name
Former-commit-id: 9cc348aaef8fac5e6c64220d94428f168ea8855b
2014-10-25 08:05:01 -04:00
Jeremy Long
06060a6694 improved error handling of invalid search strings
Former-commit-id: 97250e44b27e009b2480d25f8c2ebb7566038086
2014-10-25 08:04:33 -04:00
Jeremy Long
70667814f6 changed display name of files contained in archives so that it doesn't look like an invalid path
Former-commit-id: db3a7edadef81dd7e66c68cf0f4cdf43e12936b6
2014-10-25 08:03:47 -04:00
Jeremy Long
766b7a940c changed scan methods to return a list of dependencies instead of void
Former-commit-id: f0fd1e06708de3159acff0147968b5508a54fc05
2014-10-25 08:02:36 -04:00
Jeremy Long
0c37586357 added Xlint:unchecked
Former-commit-id: e26970bf2cd4606b777bddfc806ba74227da9cba
2014-10-25 08:00:11 -04:00
Jeremy Long
b4aa55ce1f Merge branch 'master' of github.com:ctrl-alt-dev/DependencyCheck into ctrl-alt-dev-master
Former-commit-id: 4d1ab5ecacf0ca7354f57d3a49accd5a173e0a26
2014-10-24 05:36:40 -04:00
Jeremy Long
109443ce77 changed the name property of dependencies identified within an archive
Former-commit-id: 5d778afea68c881efea628d9ecc28596d3cbc9d6
2014-10-23 06:09:39 -04:00
Will Stranathan
5f38741831 Initial checkin of work on a Solr analyzer which will replace Nexus on Internet checks
Former-commit-id: 7b51d0cb1d23122bc73261424b66df24f72370cd
2014-10-22 22:35:03 -04:00
Jeremy Long
c6f391501d added test case for patch to issue #156
Former-commit-id: 8fa1de0566760a41d65614921f4bb764178151f8
2014-10-22 21:43:23 -04:00
Jeremy Long
d1f3105fbd added appropriate sorting to resolve issue #156
Former-commit-id: b5d0dd3e9d337417ea3483b491035009269eaa5c
2014-10-22 21:42:51 -04:00
Jeremy Long
8f88ca9d3d corrected compareTo to use file path, not just file name
Former-commit-id: 98e19c402cd5824aed4b3b4923b7ef72359752cf
2014-10-22 21:12:40 -04:00
Erik Hooijmeijer
f9e4ca0cc2 corrected javadoc
Former-commit-id: 3e0533a8a36afcacb647610f352bfd854e505272
2014-10-22 19:10:54 +02:00
Erik Hooijmeijer
5caf023677 added excludeInternalGroupIds configuration parameter that allows the exclusion of groupIds of internal projects. This is to speed up analysis as internal projects have no public vulnerabilites nor a sonatype listing but do frequently have names that collide with other libraries. The parameter can have multiple values, e.g. <excludeInternalGroupIds><groupId>nl.someinteral.project</groupId><groupId>org.another.one</groupId></excludeInternalGroupIds>
Former-commit-id: ffa0716366c6c7b65d1181f2bd945472b75b5483
2014-10-22 19:08:33 +02:00
Erik Hooijmeijer
35c2f4873c values from the project pom.xml are now taken into account as well
Former-commit-id: ca6c5b40f09959f162b337f2cb4268a57ce46d3d
2014-10-21 20:09:54 +02:00
Jeremy Long
1ed7bab375 additional updates for issue #162, if no pom is present in the jar, but it exists in the repo the pom from the repo will be used
Former-commit-id: 0d1603f45420b57b00149764acca1fe5bd3f3c83
2014-10-17 20:55:58 -04:00
Jeremy Long
f0d1bfb777 added an additional suppression for issue #162
Former-commit-id: 9c3403814b15cbcdebdc9e0d43253016548efb23
2014-10-16 06:57:24 -04:00
Jeremy Long
42519ac843 version 1.2.6-SNAPSHOT
Former-commit-id: 0b301bfa4a942e43976a34195a32982000f34d12
2014-10-14 06:28:14 -04:00
Jeremy Long
8869e13385 Merge pull request #161 from hansjoachim/exceptionTests
Uses ExpectedException to test for exceptions

Former-commit-id: 38f9b007311032db7edec0e1c345130409518855
2014-10-13 05:47:54 -04:00
Hans Joachim Desserud
8f9cbfe806 Unrelated: remove unused before/after
Former-commit-id: 68524208b8c0a197e9682aceec25cff0bc30ff56
2014-10-12 18:29:27 +02:00
Hans Joachim Desserud
6481938626 Test for exceptions with ExpectedException
Former-commit-id: 47c6c559196b4c10a5deb3698805ff7276f0aa83
2014-10-12 18:27:03 +02:00
Jeremy Long
9c7cc2acbf corrected the documentation
Former-commit-id: 428b6b3e07ed250ac11fb6c917c90888c0d20246
2014-10-10 20:03:36 -04:00
Jeremy Long
89a57d4ed3 removed velocity-tools to close issue #160
Former-commit-id: 5ca46405a5aa7521bd0a0de54500d848156491a6
2014-10-10 06:36:47 -04:00
Jeremy Long
732378592b corrected link to the unfortunate realities pdf
Former-commit-id: 285bcfd78f00fa514d3f96b5dcbac2fd18384177
2014-10-08 06:47:27 -04:00
Jeremy Long
19dc46660b corrected link to the unfortunate realities pdf
Former-commit-id: 75332bd18e6ac3ecac5dddda2f3945ae4003bd06
2014-10-08 06:21:55 -04:00
Jeremy Long
4aad3471af fixed javadoc
Former-commit-id: 2402251f2157864ee3c51dd571cb9d21e17856e6
2014-10-08 06:21:20 -04:00
Jeremy Long
92bd305b00 version 1.2.5
Former-commit-id: b3fe4ea80c4286684eda15a3b9f46cebc4f09ee8
2014-09-16 19:47:17 -04:00
Jeremy Long
f71eb09f74 updated sample report
Former-commit-id: 1de33769f71be8c86116b4a17d8282c69e0abed6
2014-09-16 19:47:07 -04:00
Jeremy Long
83d4a7bc18 moved test case dependency,jersey client, to the allTests profile
Former-commit-id: 58da4d9c21803362133f74c168aea256c51a5824
2014-09-16 05:24:43 -04:00
Jeremy Long
29595324c4 added suppression rules for jersey-client
Former-commit-id: cb8f4081c6d0fc2128a3a3dfda294a541c16adec
2014-09-13 07:10:17 -04:00
Jeremy Long
f9064e526f added test jar to the extended profile test dependencies
Former-commit-id: b24966e3936afd9337dbea5476a696ddf46efc65
2014-09-13 07:09:54 -04:00
Jeremy Long
93ec2e8639 fixed javadoc
Former-commit-id: d06907a74a6fd4cf9ac5e5774af63eda5aba02b3
2014-09-13 05:50:49 -04:00
Jeremy Long
0e2a31709a added test cases to ensure setting the base flag will prevent the identifier from being added to the suppressedIdentifiers collection
Former-commit-id: d369797a3b14fc2c42621d273d6f314e968848b9
2014-09-13 05:45:05 -04:00
Jeremy Long
c785b39eda added assertion to validate that the base flag is being processed
Former-commit-id: 0364e57af8f548d010f17f948492e9472433c675
2014-09-13 05:44:09 -04:00
Jeremy Long
8fab2f58da added the base property and skipped adding the vulnerability or identifier to the suppressed collection if this is a base suppression rule
Former-commit-id: a668d7d8b9345b6ad44bfff1ced4ab783a1f90d8
2014-09-13 05:43:16 -04:00
Jeremy Long
e44ee3bfe1 added parsing of the base flag
Former-commit-id: 02f533177846bcd4a98b31f851e91f438e1ddeaa
2014-09-13 05:42:01 -04:00
Jeremy Long
62065c9d28 corrected the removal of an identifier so that iterator.remove was correctly used
Former-commit-id: 252507772242cc7ff42ef9f310cfca3bec7cb075
2014-09-13 05:41:26 -04:00
Jeremy Long
c76275275f added the base=true flag to all base suppressions
Former-commit-id: ac77f3fc4ff80c182b7736554a1960e186e67d69
2014-09-13 05:40:37 -04:00
Jeremy Long
257f78879d added base attribute to suppression rules
Former-commit-id: bcadbd75b99471a56d604c2f158570305e9b4010
2014-09-13 05:40:06 -04:00
Jeremy Long
894263809c added base flag to one suppression entry
Former-commit-id: 7d6bbf36e5e35c2ee2fe8c901281996a34706036
2014-09-13 05:39:38 -04:00
Jeremy Long
c503935d6a updated to correctly close the ObjectOutputStream based on guidance from the CERT Java Secure Coding Standard
Former-commit-id: 1c7b929055f273d49b1203c117d7bb12162cfdb2
2014-09-12 06:36:00 -04:00
Jeremy Long
d4756c9eb8 updated base suppression list to include sandbox:sandbox - a php app
Former-commit-id: 087a4c5af2afd03a1d4703d2e1e5a1607a2e7ac9
2014-09-12 06:34:23 -04:00
Jeremy Long
0004767775 added fix for issue #147 to address springsource, non-core spring, jars being idenified as cpe://a:springsource:springframwork
Former-commit-id: 0a3182123be78a3f450cdef0bcc395907d27730a
2014-09-10 17:55:04 -04:00
Jeremy Long
74908642c7 added test dependency
Former-commit-id: fa4846dfa384639114f32ed3b7a0d91347b8dabf
2014-09-10 17:39:31 -04:00
Jeremy Long
aadfb71c98 fixed test case by removing a temporary test entry in DetermineCPE_full
Former-commit-id: 0f91c7b8e1d536c9d15176dc2d9a439da4e8ccdc
2014-09-10 17:37:54 -04:00
Jeremy Long
1244af649d updated to improve CPE matching so that if a broad match occured (cpe with no version number) we use the highest confidence version when generating the CPE identifier
Former-commit-id: 6e8c87a71522b1ca7cfa9d72ca419a792d1b17e7
2014-09-09 15:10:08 -04:00
Jeremy Long
7bd48cc811 updated version analysis to reduce false positives and increase accurate detection
Former-commit-id: 6097160434b7e98182738706790d82cdbd867175
2014-09-09 15:07:28 -04:00
Jeremy Long
8f3ce38418 re-ordered operations so that a new lucene index is no longer created on each call to calDetermineCPE_full
Former-commit-id: e2af1d893b47afe1ed36d1ab1e6840d47757b509
2014-09-07 08:28:44 -04:00
Jeremy Long
1b2d9b4245 fixed minor display bug
Former-commit-id: 65e1adcdc7677490907ee6eca68bf1174d355a3c
2014-09-07 07:20:45 -04:00
Jeremy Long
c6b2b34fde removed duplicative test of downloading XML
Former-commit-id: 97d1371609af2cc9583b0ac071a8606c93a34fbe
2014-09-07 06:59:50 -04:00
Jeremy Long
e58fc13fdb additional looping corrections in determineCPE() to break early if an identifier is found
Former-commit-id: 4ec4ffe598d9870a793da8980bb863633c1967d7
2014-09-06 19:09:38 -04:00
Jeremy Long
922d53d2e4 Increased the confidence on the pom artifact and groupid
Former-commit-id: b052b50353197e0f7cb419e6f618f2320da11183
2014-09-06 19:08:22 -04:00
Jeremy Long
fec53b3951 corrected looping in determineCPE()
Former-commit-id: 329f20687223f38273b2e23601b05fcea2b9122f
2014-09-06 06:37:12 -04:00
Jeremy Long
e72e2c6a02 corrected documention error with the reporting sets
Former-commit-id: ab503e5a710a69624a3216edea880e614b003ba8
2014-09-01 08:19:46 -04:00
Jeremy Long
08d001ee05 checkstyle corrections
Former-commit-id: ecc262c75890ef4c8760cb41e7948cb6decdf5d5
2014-09-01 08:13:53 -04:00
Jeremy Long
99d8a07f4a updated documentation as part of resolution for issue #144
Former-commit-id: f47171e52e22e75c582bed47c9d0e9df3945e148
2014-09-01 08:13:34 -04:00
Jeremy Long
eef565134b update to correct issue #79 - the internal report format is no longer supported
Former-commit-id: 4dc9a83008a75d97f3838aa1a41f1d93eb39f2de
2014-09-01 07:39:54 -04:00
Jeremy Long
9d78293437 fix for issue #128 - the application will no longer throw an exception on large files when generating the hash digest
Former-commit-id: aae811e5d10ca0ee5ac7316fa992b5c45e43d2be
2014-09-01 07:30:04 -04:00
Jeremy Long
fc0a556e5f checkstyle and findbugs corrections
Former-commit-id: 2bf90876b7c88bccb93135a0be43f01e49c3cd30
2014-08-30 15:51:24 -04:00
Jeremy Long
b6b070584f checkstyle corrections, added javadoc, etc.
Former-commit-id: 2b806cb8527a627d400644465bcf9f04d687d729
2014-08-30 15:19:52 -04:00
Jeremy Long
e13225eee6 initial version of aggreation completed for issue #19 - some cleanup still needs to happen before final release
Former-commit-id: 98c9af3004e2c725d0dca5d6847b65a4646c6a73
2014-08-30 07:50:27 -04:00
Jeremy Long
da20fb2922 added velocity-tools to base suppression as it should not be reported as struts
Former-commit-id: 4649d95a091def05ae249da42aa7d6f845b14d59
2014-08-30 07:48:02 -04:00
Jeremy Long
459c2beb12 noop
Former-commit-id: a51d953d0c60c39d845d69d66c87db8b904382c4
2014-08-29 05:41:31 -04:00
Jeremy Long
f1cc44dead removed the externalReport option
Former-commit-id: 4cc3ec2638140f8320eb8946d2154dae330786b0
2014-08-29 05:38:40 -04:00
Jeremy Long
d24cfdc382 resolved merge conflict
Former-commit-id: 4806c0c99bd35d64135ee22a12018e6a92c54059
2014-08-16 07:41:55 -04:00
Jeremy Long
ae4cc543f6 corrected outputFile name to correctly use the target directory from project.getBuild().getDirectory()
Former-commit-id: 7ef2ca45e502e945e7356f9c63845eb4e7b532fc
2014-08-16 07:30:34 -04:00
Jeremy Long
abdb3d17f9 added initial plumbing to support report aggregation per issue #19 - report aggregation is still not complete
Former-commit-id: df248d0c1a7f3628653717029f034a46afde742b
2014-08-16 07:29:35 -04:00
Jeremy Long
4095c5da38 made serializable
Former-commit-id: 27d8084ea981766791df05c5e9ef61dbe40ba32c
2014-08-16 07:27:28 -04:00
Jeremy Long
78fab728e4 added an additional generate method
Former-commit-id: 44b78b525da45918f3b4bc77b368f88e49361c95
2014-08-15 06:22:54 -04:00
Jeremy Long
52097a6867 initial version of the ReportAggregationMojo
Former-commit-id: e15575413d625c6b5c5f3d73f5a739e1890eec27
2014-08-15 06:02:04 -04:00
Jeremy Long
cb990b55b5 added the apache 2.0 license to the header
Former-commit-id: f7d5558f565abe9c3e1a04f79666137e4f67e017
2014-08-15 06:00:30 -04:00
Jeremy Long
5070fe303a added the configuration value mavenSettingsProxyId to inform users that if you have multiple proxies defined in settings.xml you can choose which one should be used
Former-commit-id: 20fa4a92d446fd30a882e07c37897907fb1638b1
2014-08-15 05:59:39 -04:00
Jeremy Long
b4405ebf3e minor changes to the TOC table - removed # of related dependencies and renamed CVE Impact to Highest Severity to clear up ambiguity
Former-commit-id: b8b14ab120d889057864eb6f93cadad9773b9171
2014-08-15 05:58:10 -04:00
Jeremy Long
d9e6bf5068 Merge pull request #145 from erik-wramner/fix-maven-proxy-bug
Modified Maven plugin to use proxy host as is, not as an URL. This works...

Former-commit-id: 53e28e6799ef13ca3d88ed00aaa1e0c3f24aa04b
2014-08-15 05:37:14 -04:00
erik-wramner
6822188f52 Modified Maven plugin to use proxy host as is, not as an URL. This works correctly for our proxy server with Maven 3.
Former-commit-id: 02e97e359b1c5d6d9f1dc9149c9fbed510d31559
2014-08-10 12:15:00 +02:00
Jeremy Long
15858d03ff moved reporting functions from the core maven plugin to a utility class
Former-commit-id: d63d2a7a5031038b9f86bbe94fc4a198374bd9f3
2014-08-08 14:44:26 -04:00
Jeremy Long
814a733258 moved reporting functions from the core maven plugin to a utility class
Former-commit-id: 0d8507b8534320189ea5f36d0fc1cac7d0843c0f
2014-08-08 14:43:00 -04:00
Jeremy Long
3ce85d8ca9 rework of report generation and added fix for proxy (patch for proxy was from Erik Wramner) to close issue #136
Former-commit-id: afc81123b31189618ade397b830bf421db2918f8
2014-08-08 14:42:23 -04:00
Jeremy Long
d3bff2f39d version 1.2.5-SNAPSHOT
Former-commit-id: 85ed1238022348f1e9496ffe3c95d4ff8e3d09c3
2014-08-05 18:55:30 -04:00
116 changed files with 13374 additions and 2981 deletions

3
.gitignore vendored
View File

@@ -7,6 +7,9 @@
# Eclipse project files
.classpath
.project
.settings
maven-eclipse.xml
.externalToolBuilders
# Netbeans configuration
nb-configuration.xml
/target/

View File

@@ -15,13 +15,12 @@ limitations under the License.
Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.2.4</version>
<version>1.2.6</version>
</parent>
<artifactId>dependency-check-ant</artifactId>

View File

@@ -46,17 +46,17 @@ Note, that specific analyzers will automatically disable themselves if no file
types that they support are detected - so specifically disabling them may not
be needed.
Property | Description | Default Value
------------------------|------------------------------------|------------------
archiveAnalyzerEnabled | Sets whether the Archive Analyzer will be used. | true
Property | Description | Default Value
------------------------|---------------------------------------------------------------------------|------------------
archiveAnalyzerEnabled | Sets whether the Archive Analyzer will be used. | true
zipExtensions | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. | &nbsp;
jarAnalyzer | Sets whether Jar Analyzer will be used. | true
nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used. | true
nexusUrl | Defines the Nexus URL. | https://repository.sonatype.org/service/local/
jarAnalyzer | Sets whether Jar Analyzer will be used. | true
nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used. | true
nexusUrl | Defines the Nexus Pro URL. If not set the Nexus Analyzer will be disabled. | &nbsp;
nexusUsesProxy | Whether or not the defined proxy should be used when connecting to Nexus. | true
nuspecAnalyzerEnabled | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | true
assemblyAnalyzerEnabled | Sets whether or not the .NET Assembly Analyzer should be used. | true
pathToMono | The path to Mono for .NET assembly analysis on non-windows systems | &nbsp;
nuspecAnalyzerEnabled | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | true
assemblyAnalyzerEnabled | Sets whether or not the .NET Assembly Analyzer should be used. | true
pathToMono | The path to Mono for .NET assembly analysis on non-windows systems. | &nbsp;
Advanced Configuration
====================

View File

@@ -15,13 +15,12 @@ limitations under the License.
Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.2.4</version>
<version>1.2.6</version>
</parent>
<artifactId>dependency-check-cli</artifactId>
@@ -287,12 +286,12 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.7</version>
<version>1.8.1</version>
<configuration>
<programs>
<program>
<mainClass>org.owasp.dependencycheck.App</mainClass>
<name>dependency-check</name>
<id>dependency-check</id>
</program>
</programs>
<assembleDirectory>${project.build.directory}/release</assembleDirectory>

View File

@@ -2,10 +2,8 @@
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2
http://maven.apache.org/xsd/assembly-1.1.2.xsd
"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2
http://maven.apache.org/xsd/assembly-1.1.2.xsd"
>
<id>release</id>
<formats>

View File

@@ -21,15 +21,19 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.cli.ParseException;
import org.owasp.dependencycheck.cli.CliParser;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.org.apache.tools.ant.DirectoryScanner;
import org.owasp.dependencycheck.reporting.ReportGenerator;
import org.owasp.dependencycheck.utils.LogUtils;
import org.owasp.dependencycheck.utils.Settings;
@@ -93,7 +97,11 @@ public class App {
cli.printVersionInfo();
} else if (cli.isRunScan()) {
populateSettings(cli);
runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getApplicationName(), cli.getScanFiles());
try {
runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getApplicationName(), cli.getScanFiles(), cli.getExcludeList());
} catch (InvalidScanPathException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, "An invalid scan path was detected; unable to scan '//*' paths");
}
} else {
cli.printHelp();
}
@@ -106,18 +114,71 @@ public class App {
* @param outputFormat the output format of the report
* @param applicationName the application name for the report
* @param files the files/directories to scan
* @param excludes the patterns for files/directories to exclude
*
* @throws InvalidScanPathException thrown if the path to scan starts with "//"
*/
private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files) {
Engine scanner = null;
private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files,
String[] excludes) throws InvalidScanPathException {
Engine engine = null;
try {
scanner = new Engine();
for (String file : files) {
scanner.scan(file);
engine = new Engine();
List<String> antStylePaths = new ArrayList<String>();
if (excludes == null || excludes.length == 0) {
for (String file : files) {
if (file.contains("*") || file.contains("?")) {
antStylePaths.add(file);
} else {
engine.scan(file);
}
}
} else {
antStylePaths = Arrays.asList(files);
}
scanner.analyzeDependencies();
final List<Dependency> dependencies = scanner.getDependencies();
final Set<File> paths = new HashSet<File>();
for (String file : antStylePaths) {
final DirectoryScanner scanner = new DirectoryScanner();
String include = file.replace('\\', '/');
File baseDir;
if (include.startsWith("//")) {
throw new InvalidScanPathException("Unable to scan paths specified by //");
} else if (include.startsWith("./")) {
baseDir = new File(".");
include = include.substring(2);
} else if (include.startsWith("/")) {
baseDir = new File("/");
include = include.substring(1);
} else if (include.contains("/")) {
final int pos = include.indexOf('/');
final String tmp = include.substring(0, pos);
if (tmp.contains("*") || tmp.contains("?")) {
baseDir = new File(".");
} else {
baseDir = new File(tmp);
include = include.substring(pos + 1);
}
} else { //no path info - must just be a file in the working directory
baseDir = new File(".");
}
scanner.setBasedir(baseDir);
scanner.setIncludes(include);
if (excludes != null && excludes.length > 0) {
scanner.addExcludes(excludes);
}
scanner.scan();
if (scanner.getIncludedFilesCount() > 0) {
for (String s : scanner.getIncludedFiles()) {
final File f = new File(baseDir, s);
paths.add(f);
}
}
}
engine.scan(paths);
engine.analyzeDependencies();
final List<Dependency> dependencies = engine.getDependencies();
DatabaseProperties prop = null;
CveDB cve = null;
try {
@@ -131,7 +192,7 @@ public class App {
cve.close();
}
}
final ReportGenerator report = new ReportGenerator(applicationName, dependencies, scanner.getAnalyzers(), prop);
final ReportGenerator report = new ReportGenerator(applicationName, dependencies, engine.getAnalyzers(), prop);
try {
report.generateReports(reportDirectory, outputFormat);
} catch (IOException ex) {
@@ -145,8 +206,8 @@ public class App {
LOGGER.log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped");
LOGGER.log(Level.FINE, "", ex);
} finally {
if (scanner != null) {
scanner.cleanup();
if (engine != null) {
engine.cleanup();
}
}
}

View File

@@ -15,7 +15,7 @@
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.cli;
package org.owasp.dependencycheck;
import java.io.File;
import java.io.FileNotFoundException;
@@ -134,14 +134,33 @@ public final class CliParser {
* @throws FileNotFoundException is thrown if the path being validated does not exist.
*/
private void validatePathExists(String path, String argumentName) throws FileNotFoundException {
if (!path.contains("*.")) {
if (path == null) {
isValid = false;
final String msg = String.format("Invalid '%s' argument: null", argumentName);
throw new FileNotFoundException(msg);
} else if (!path.contains("*") && !path.contains("?")) {
final File f = new File(path);
if (!f.exists()) {
isValid = false;
final String msg = String.format("Invalid '%s' argument: '%s'", argumentName, path);
throw new FileNotFoundException(msg);
if ("o".equals(argumentName.substring(0, 1).toLowerCase()) && !"ALL".equals(this.getReportFormat().toUpperCase())) {
final String checkPath = path.toLowerCase();
if (checkPath.endsWith(".html") || checkPath.endsWith(".xml") || checkPath.endsWith(".htm")) {
if (!f.getParentFile().isDirectory()) {
isValid = false;
final String msg = String.format("Invalid '%s' argument: '%s'", argumentName, path);
throw new FileNotFoundException(msg);
}
}
} else {
if (!f.exists()) {
isValid = false;
final String msg = String.format("Invalid '%s' argument: '%s'", argumentName, path);
throw new FileNotFoundException(msg);
}
}
} // else { // TODO add a validation for *.zip extensions rather then relying on the engine to validate it.
} else if (path.startsWith("//") || path.startsWith("\\\\")) {
isValid = false;
final String msg = String.format("Invalid '%s' argument: '%s'%nUnable to scan paths that start with '//'.", argumentName, path);
throw new FileNotFoundException(msg);
}
}
/**
@@ -151,7 +170,6 @@ public final class CliParser {
*/
@SuppressWarnings("static-access")
private Options createCommandLineOptions() {
final Options options = new Options();
addStandardOptions(options);
addAdvancedOptions(options);
@@ -184,16 +202,22 @@ public final class CliParser {
.create(ARGUMENT.APP_NAME_SHORT);
final Option path = OptionBuilder.withArgName("path").hasArg().withLongOpt(ARGUMENT.SCAN)
.withDescription("The path to scan - this option can be specified multiple times. To limit the scan"
+ " to specific file types *.[ext] can be added to the end of the path.")
.withDescription("The path to scan - this option can be specified multiple times. Ant style"
+ " paths are supported (e.g. path/**/*.jar).")
.create(ARGUMENT.SCAN_SHORT);
final Option excludes = OptionBuilder.withArgName("pattern").hasArg().withLongOpt(ARGUMENT.EXCLUDE)
.withDescription("Specify and exclusion pattern. This option can be specified multiple times"
+ " and it accepts Ant style excludsions.")
.create();
final Option props = OptionBuilder.withArgName("file").hasArg().withLongOpt(ARGUMENT.PROP)
.withDescription("A property file to load.")
.create(ARGUMENT.PROP_SHORT);
final Option out = OptionBuilder.withArgName("folder").hasArg().withLongOpt(ARGUMENT.OUT)
.withDescription("The folder to write reports to. This defaults to the current directory.")
final Option out = OptionBuilder.withArgName("path").hasArg().withLongOpt(ARGUMENT.OUT)
.withDescription("The folder to write reports to. This defaults to the current directory. "
+ "It is possible to set this to a specific file name if the format argument is not set to ALL.")
.create(ARGUMENT.OUT_SHORT);
final Option outputFormat = OptionBuilder.withArgName("format").hasArg().withLongOpt(ARGUMENT.OUTPUT_FORMAT)
@@ -212,7 +236,11 @@ public final class CliParser {
final OptionGroup og = new OptionGroup();
og.addOption(path);
final OptionGroup exog = new OptionGroup();
exog.addOption(excludes);
options.addOptionGroup(og)
.addOptionGroup(exog)
.addOption(out)
.addOption(outputFormat)
.addOption(appName)
@@ -297,7 +325,7 @@ public final class CliParser {
.create();
final Option nexusUrl = OptionBuilder.withArgName("url").hasArg().withLongOpt(ARGUMENT.NEXUS_URL)
.withDescription("The url to the Nexus Server.")
.withDescription("The url to the Nexus Pro Server. If not set the Nexus Analyzer will be disabled.")
.create();
final Option nexusUsesProxy = OptionBuilder.withArgName("true/false").hasArg().withLongOpt(ARGUMENT.NEXUS_USES_PROXY)
@@ -479,7 +507,6 @@ public final class CliParser {
options,
"",
true);
}
/**
@@ -491,6 +518,15 @@ public final class CliParser {
return line.getOptionValues(ARGUMENT.SCAN);
}
/**
* Retrieves the list of excluded file patterns specified by the 'exclude' argument.
*
* @return the excluded file patterns
*/
public String[] getExcludeList() {
return line.getOptionValues(ARGUMENT.EXCLUDE);
}
/**
* Returns the directory to write the reports to specified on the command line.
*
@@ -877,5 +913,9 @@ public final class CliParser {
* The CLI argument name for setting extra extensions.
*/
public static final String ADDITIONAL_ZIP_EXTENSIONS = "zipExtensions";
/**
* Exclude path argument.
*/
public static final String EXCLUDE = "exclude";
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2014 OWASP.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.owasp.dependencycheck;
/**
* Thrown if an invalid path is encountered.
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
class InvalidScanPathException extends Exception {
/**
* Creates a new InvalidScanPathException.
*/
public InvalidScanPathException() {
super();
}
/**
* Creates a new InvalidScanPathException.
*
* @param msg a message for the exception
*/
public InvalidScanPathException(String msg) {
super(msg);
}
/**
* Creates a new InvalidScanPathException.
*
* @param ex the cause of the exception
*/
public InvalidScanPathException(Throwable ex) {
super(ex);
}
/**
* Creates a new InvalidScanPathException.
*
* @param msg a message for the exception
* @param ex the cause of the exception
*/
public InvalidScanPathException(String msg, Throwable ex) {
super(msg, ex);
}
}

View File

@@ -1,12 +0,0 @@
/**
* <html>
* <head>
* <title>org.owasp.dependencycheck.cli</title>
* </head>
* <body>
* Includes utility classes such as the CLI Parser,
* </body>
* </html>
*/
package org.owasp.dependencycheck.cli;

View File

@@ -6,8 +6,9 @@ The following table lists the command line arguments:
Short | Argument&nbsp;Name&nbsp;&nbsp; | Parameter | Description | Requirement
-------|-----------------------|-----------------|-------------|------------
\-a | \-\-app | \<name\> | The name of the application being scanned. This is a required argument. | Required
\-s | \-\-scan | \<path\> | The path to scan \- this option can be specified multiple times. It is also possible to specify specific file types that should be scanned by supplying a scan path of '[path]/[to]/[scan]/*.zip'. The wild card can only be used to denote any file-name with a specific extension. | Required
\-o | \-\-out | \<folder\> | The folder to write reports to. This defaults to the current directory. | Optional
\-s | \-\-scan | \<path\> | The path to scan \- this option can be specified multiple times. It is also possible to specify Ant style paths (e.g. directory/**/*.jar). | Required
| \-\-exclude | \<pattern\> | The path patterns to exclude from the scan \- this option can be specified multiple times. This accepts Ant style path patterns (e.g. **/exclude/**) . | Optional
\-o | \-\-out | \<path\> | The folder to write reports to. This defaults to the current directory. If the format is not set to ALL one could specify a specific file name. | Optional
\-f | \-\-format | \<format\> | The output format to write to (XML, HTML, VULN, ALL). The default is HTML. | Required
\-l | \-\-log | \<file\> | The file path to write verbose logging information. | Optional
\-n | \-\-noupdate | | Disables the automatic updating of the CPE data. | Optional
@@ -18,26 +19,25 @@ Short | Argument&nbsp;Name&nbsp;&nbsp; | Parameter | Description | Requir
Advanced Options
================
Short | Argument&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Parameter | Description | Default&nbsp;Value
-------|-----------------------|-----------------|-------------|---------------
| \-\-disableArchive | | Sets whether the Archive Analyzer will be used. | false
Short | Argument&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Parameter | Description | Default&nbsp;Value
-------|-----------------------|-----------------|-----------------------------------------------------------------------------|---------------
| \-\-disableArchive | | Sets whether the Archive Analyzer will be used. | false
| \-\-zipExtensions | \<strings\> | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. | &nbsp;
| \-\-disableJar | | Sets whether Jar Analyzer will be used. | false
| \-\-disableNexus | | Sets whether Nexus Analyzer will be used. | false
| \-\-disableNexus | | Disable the Nexus Analyzer. | &nbsp;
| \-\-nexus | \<url\> | The url to the Nexus Server. | https://repository.sonatype.org/service/local/
| \-\-nexusUsesProxy | \<true\|false\> | Whether or not the defined proxy should be used when connecting to Nexus. | true
| \-\-disableNuspec | | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | false
| \-\-disableAssembly | | Sets whether or not the .NET Assembly Analyzer should be used. | false
| \-\-pathToMono | \<path\> | The path to Mono for .NET Assembly analysis on non-windows systems. | &nbsp;
| \-\-proxyserver | \<server\> | The proxy server to use when downloading resources. | &nbsp;
| \-\-proxyport | \<port\> | The proxy port to use when downloading resources. | &nbsp;
| \-\-disableJar | | Sets whether Jar Analyzer will be used. | false
| \-\-disableNexus | | Sets whether Nexus Analyzer will be used. | false
| \-\-nexus | \<url\> | The url to the Nexus Pro Server. If not set the Nexus Analyzer will be disabled. | &nbsp;
| \-\-nexusUsesProxy | \<true\|false\> | Whether or not the defined proxy should be used when connecting to Nexus. | true
| \-\-disableNuspec | | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | false
| \-\-disableAssembly | | Sets whether or not the .NET Assembly Analyzer should be used. | false
| \-\-pathToMono | \<path\> | The path to Mono for .NET Assembly analysis on non-windows systems. | &nbsp;
| \-\-proxyserver | \<server\> | The proxy server to use when downloading resources. | &nbsp;
| \-\-proxyport | \<port\> | The proxy port to use when downloading resources. | &nbsp;
| \-\-connectiontimeout | \<timeout\> | The connection timeout (in milliseconds) to use when downloading resources. | &nbsp;
| \-\-proxypass | \<pass\> | The proxy password to use when downloading resources. | &nbsp;
| \-\-proxyuser | \<user\> | The proxy username to use when downloading resources. | &nbsp;
| \-\-connectionString | \<connStr\> | The connection string to the database. | &nbsp;
| \-\-dbDriverName | \<driver\> | The database driver name. | &nbsp;
| \-\-proxypass | \<pass\> | The proxy password to use when downloading resources. | &nbsp;
| \-\-proxyuser | \<user\> | The proxy username to use when downloading resources. | &nbsp;
| \-\-connectionString | \<connStr\> | The connection string to the database. | &nbsp;
| \-\-dbDriverName | \<driver\> | The database driver name. | &nbsp;
| \-\-dbDriverPath | \<path\> | The path to the database driver; note, this does not need to be set unless the JAR is outside of the class path. | &nbsp;
| \-\-dbPassword | \<password\> | The password for connecting to the database. | &nbsp;
| \-\-dbUser | \<user\> | The username used to connect to the database. | &nbsp;
| \-\-dbPassword | \<password\> | The password for connecting to the database. | &nbsp;
| \-\-dbUser | \<user\> | The username used to connect to the database. | &nbsp;
\-d | \-\-data | \<path\> | The location of the data directory used to store persistent data. This option should generally not be set. | &nbsp;

View File

@@ -15,8 +15,9 @@
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.cli;
package org.owasp.dependencycheck;
import org.owasp.dependencycheck.CliParser;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;

View File

@@ -20,7 +20,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.2.4</version>
<version>1.2.6</version>
</parent>
<artifactId>dependency-check-core</artifactId>
@@ -400,6 +400,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<version>3.1</version>
<configuration>
<showDeprecation>false</showDeprecation>
<compilerArgument>-Xlint:unchecked</compilerArgument>
<source>1.6</source>
<target>1.6</target>
</configuration>
@@ -418,6 +419,12 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<version>4.3.1</version>
<scope>test</scope>
</dependency>
<!--dependency>
<groupId>org.jmockit</groupId>
<artifactId>jmockit</artifactId>
<version>1.12</version>
<scope>test</scope>
</dependency-->
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>annotations</artifactId>
@@ -464,50 +471,6 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-tools</artifactId>
<version>2.0</version>
<!-- very limited use of the velocity-tools, not all of the dependencies are needed-->
<exclusions>
<exclusion>
<groupId>commons-chain</groupId>
<artifactId>commons-chain</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
</exclusion>
<exclusion>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
</exclusion>
<exclusion>
<groupId>sslext</groupId>
<artifactId>sslext</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.struts</groupId>
<artifactId>struts-core</artifactId>
</exclusion>
<exclusion>
<groupId>antlr</groupId>
<artifactId>antlr</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.struts</groupId>
<artifactId>struts-taglib</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.struts</groupId>
<artifactId>struts-tiles</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
@@ -621,6 +584,13 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.1.0.RELEASE</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
</dependencies>
<profiles>
<profile>
@@ -737,6 +707,28 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.12</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.11.1</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.2.8-02</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
</dependencies>
</profile>
</profiles>

View File

@@ -18,6 +18,7 @@
package org.owasp.dependencycheck;
import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashSet;
@@ -52,7 +53,7 @@ import org.owasp.dependencycheck.utils.Settings;
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class Engine {
public class Engine implements Serializable {
/**
* The list of dependencies.
@@ -61,19 +62,19 @@ public class Engine {
/**
* A Map of analyzers grouped by Analysis phase.
*/
private final EnumMap<AnalysisPhase, List<Analyzer>> analyzers;
private final transient EnumMap<AnalysisPhase, List<Analyzer>> analyzers;
/**
* A Map of analyzers grouped by Analysis phase.
*/
private final Set<FileTypeAnalyzer> fileTypeAnalyzers;
private final transient Set<FileTypeAnalyzer> fileTypeAnalyzers;
/**
* The ClassLoader to use when dynamically loading Analyzer and Update services.
*/
private ClassLoader serviceClassLoader;
private transient ClassLoader serviceClassLoader;
/**
* The Logger for use throughout the class.
*/
private static final Logger LOGGER = Logger.getLogger(Engine.class.getName());
private static final transient Logger LOGGER = Logger.getLogger(Engine.class.getName());
/**
* Creates a new Engine.
@@ -167,142 +168,171 @@ public class Engine {
* Scans an array of files or directories. If a directory is specified, it will be scanned recursively. Any
* dependencies identified are added to the dependency collection.
*
* @since v0.3.2.5
* @param paths an array of paths to files or directories to be analyzed
* @return the list of dependencies scanned
*
* @param paths an array of paths to files or directories to be analyzed.
* @since v0.3.2.5
*/
public void scan(String[] paths) {
public List<Dependency> scan(String[] paths) {
final List<Dependency> deps = new ArrayList<Dependency>();
for (String path : paths) {
final File file = new File(path);
scan(file);
final List<Dependency> d = scan(file);
if (d != null) {
deps.addAll(d);
}
}
return deps;
}
/**
* Scans a given file or directory. If a directory is specified, it will be scanned recursively. Any dependencies
* identified are added to the dependency collection.
*
* @param path the path to a file or directory to be analyzed.
* @param path the path to a file or directory to be analyzed
* @return the list of dependencies scanned
*/
public void scan(String path) {
if (path.matches("^.*[\\/]\\*\\.[^\\/:*|?<>\"]+$")) {
final String[] parts = path.split("\\*\\.");
final String[] ext = new String[]{parts[parts.length - 1]};
final File dir = new File(path.substring(0, path.length() - ext[0].length() - 2));
if (dir.isDirectory()) {
final List<File> files = (List<File>) org.apache.commons.io.FileUtils.listFiles(dir, ext, true);
scan(files);
} else {
final String msg = String.format("Invalid file path provided to scan '%s'", path);
LOGGER.log(Level.SEVERE, msg);
}
} else {
final File file = new File(path);
scan(file);
}
public List<Dependency> scan(String path) {
final File file = new File(path);
return scan(file);
}
/**
* Scans an array of files or directories. If a directory is specified, it will be scanned recursively. Any
* dependencies identified are added to the dependency collection.
*
* @since v0.3.2.5
*
* @param files an array of paths to files or directories to be analyzed.
* @return the list of dependencies
*
* @since v0.3.2.5
*/
public void scan(File[] files) {
public List<Dependency> scan(File[] files) {
final List<Dependency> deps = new ArrayList<Dependency>();
for (File file : files) {
scan(file);
final List<Dependency> d = scan(file);
if (d != null) {
deps.addAll(d);
}
}
return deps;
}
/**
* Scans a list of files or directories. If a directory is specified, it will be scanned recursively. Any
* dependencies identified are added to the dependency collection.
*
* @since v0.3.2.5
* @param files a set of paths to files or directories to be analyzed
* @return the list of dependencies scanned
*
* @param files a set of paths to files or directories to be analyzed.
* @since v0.3.2.5
*/
public void scan(Set<File> files) {
public List<Dependency> scan(Set<File> files) {
final List<Dependency> deps = new ArrayList<Dependency>();
for (File file : files) {
scan(file);
final List<Dependency> d = scan(file);
if (d != null) {
deps.addAll(d);
}
}
return deps;
}
/**
* Scans a list of files or directories. If a directory is specified, it will be scanned recursively. Any
* dependencies identified are added to the dependency collection.
*
* @since v0.3.2.5
* @param files a set of paths to files or directories to be analyzed
* @return the list of dependencies scanned
*
* @param files a set of paths to files or directories to be analyzed.
* @since v0.3.2.5
*/
public void scan(List<File> files) {
public List<Dependency> scan(List<File> files) {
final List<Dependency> deps = new ArrayList<Dependency>();
for (File file : files) {
scan(file);
final List<Dependency> d = scan(file);
if (d != null) {
deps.addAll(d);
}
}
return deps;
}
/**
* Scans a given file or directory. If a directory is specified, it will be scanned recursively. Any dependencies
* identified are added to the dependency collection.
*
* @param file the path to a file or directory to be analyzed
* @return the list of dependencies scanned
*
* @since v0.3.2.4
*
* @param file the path to a file or directory to be analyzed.
*/
public void scan(File file) {
public List<Dependency> scan(File file) {
if (file.exists()) {
if (file.isDirectory()) {
scanDirectory(file);
return scanDirectory(file);
} else {
scanFile(file);
final Dependency d = scanFile(file);
if (d != null) {
final List<Dependency> deps = new ArrayList<Dependency>();
deps.add(d);
return deps;
}
}
}
return null;
}
/**
* Recursively scans files and directories. Any dependencies identified are added to the dependency collection.
*
* @param dir the directory to scan.
* @param dir the directory to scan
* @return the list of Dependency objects scanned
*/
protected void scanDirectory(File dir) {
protected List<Dependency> scanDirectory(File dir) {
final File[] files = dir.listFiles();
final List<Dependency> deps = new ArrayList<Dependency>();
if (files != null) {
for (File f : files) {
if (f.isDirectory()) {
scanDirectory(f);
final List<Dependency> d = scanDirectory(f);
if (d != null) {
deps.addAll(d);
}
} else {
scanFile(f);
final Dependency d = scanFile(f);
deps.add(d);
}
}
}
return deps;
}
/**
* Scans a specified file. If a dependency is identified it is added to the dependency collection.
*
* @param file The file to scan.
* @param file The file to scan
* @return the scanned dependency
*/
protected void scanFile(File file) {
protected Dependency scanFile(File file) {
if (!file.isFile()) {
final String msg = String.format("Path passed to scanFile(File) is not a file: %s. Skipping the file.", file.toString());
LOGGER.log(Level.FINE, msg);
return;
return null;
}
final String fileName = file.getName();
final String extension = FileUtils.getFileExtension(fileName);
Dependency dependency = null;
if (extension != null) {
if (supportsExtension(extension)) {
final Dependency dependency = new Dependency(file);
dependency = new Dependency(file);
dependencies.add(dependency);
}
} else {
final String msg = String.format("No file extension found on file '%s'. The file was not analyzed.",
file.toString());
final String msg = String.format("No file extension found on file '%s'. The file was not analyzed.", file.toString());
LOGGER.log(Level.FINEST, msg);
}
return dependency;
}
/**
@@ -438,8 +468,7 @@ public class Engine {
} catch (UpdateException ex) {
LOGGER.log(Level.WARNING,
"Unable to update Cached Web DataSource, using local data instead. Results may not include recent vulnerabilities.");
LOGGER.log(Level.FINE,
String.format("Unable to update details for %s", source.getClass().getName()), ex);
LOGGER.log(Level.FINE, String.format("Unable to update details for %s", source.getClass().getName()), ex);
}
}
}

View File

@@ -110,7 +110,7 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
static {
final String additionalZipExt = Settings.getString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS);
if (additionalZipExt != null) {
final HashSet ext = new HashSet<String>(Arrays.asList(additionalZipExt));
final HashSet<String> ext = new HashSet<String>(Arrays.asList(additionalZipExt));
ZIPPABLES.addAll(ext);
}
EXTENSIONS.addAll(ZIPPABLES);
@@ -186,7 +186,7 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
if (tempFileLocation != null && tempFileLocation.exists()) {
LOGGER.log(Level.FINE, "Attempting to delete temporary files");
final boolean success = FileUtils.delete(tempFileLocation);
if (!success && tempFileLocation != null & tempFileLocation.exists()) {
if (!success && tempFileLocation != null && tempFileLocation.exists() && tempFileLocation.list().length > 0) {
LOGGER.log(Level.WARNING, "Failed to delete some temporary files, see the log for more details");
}
}
@@ -221,9 +221,8 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
final String displayPath = String.format("%s%s",
dependency.getFilePath(),
d.getActualFilePath().substring(tmpDir.getAbsolutePath().length()));
final String displayName = String.format("%s%s%s",
final String displayName = String.format("%s: %s",
dependency.getFileName(),
File.separator,
d.getFileName());
d.setFilePath(displayPath);
d.setFileName(displayName);

View File

@@ -120,9 +120,11 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
// Try evacuating the error stream
rdr = new BufferedReader(new InputStreamReader(proc.getErrorStream(), "UTF-8"));
String line = null;
// CheckStyle:VisibilityModifier OFF
while (rdr.ready() && (line = rdr.readLine()) != null) {
LOGGER.log(Level.WARNING, "analyzer.AssemblyAnalyzer.grokassembly.stderr", line);
}
// CheckStyle:VisibilityModifier ON
int rc = 0;
doc = builder.parse(proc.getInputStream());
@@ -233,9 +235,11 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
final Process p = pb.start();
// Try evacuating the error stream
rdr = new BufferedReader(new InputStreamReader(p.getErrorStream(), "UTF-8"));
// CheckStyle:VisibilityModifier OFF
while (rdr.ready() && rdr.readLine() != null) {
// We expect this to complain
}
// CheckStyle:VisibilityModifier ON
final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(p.getInputStream());
final XPath xpath = XPathFactory.newInstance().newXPath();
final String error = xpath.evaluate("/assembly/error", doc);

View File

@@ -170,29 +170,10 @@ public class CPEAnalyzer implements Analyzer {
* @throws ParseException is thrown when the Lucene query cannot be parsed.
*/
protected void determineCPE(Dependency dependency) throws CorruptIndexException, IOException, ParseException {
Confidence confidence = Confidence.HIGHEST;
String vendors = addEvidenceWithoutDuplicateTerms("", dependency.getVendorEvidence(), confidence);
String products = addEvidenceWithoutDuplicateTerms("", dependency.getProductEvidence(), confidence);
/* bug fix for #40 - version evidence is not showing up as "used" in the reports if there is no
* CPE identified. As such, we are "using" the evidence and ignoring the results. */
addEvidenceWithoutDuplicateTerms("", dependency.getVersionEvidence(), confidence);
int ctr = 0;
do {
if (!vendors.isEmpty() && !products.isEmpty()) {
final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getProductEvidence().getWeighting(),
dependency.getVendorEvidence().getWeighting());
for (IndexEntry e : entries) {
if (verifyEntry(e, dependency)) {
final String vendor = e.getVendor();
final String product = e.getProduct();
determineIdentifiers(dependency, vendor, product);
}
}
}
confidence = reduceConfidence(confidence);
//TODO test dojo-war against this. we shold get dojo-toolkit:dojo-toolkit AND dojo-toolkit:toolkit
String vendors = "";
String products = "";
for (Confidence confidence : Confidence.values()) {
if (dependency.getVendorEvidence().contains(confidence)) {
vendors = addEvidenceWithoutDuplicateTerms(vendors, dependency.getVendorEvidence(), confidence);
}
@@ -201,10 +182,28 @@ public class CPEAnalyzer implements Analyzer {
}
/* bug fix for #40 - version evidence is not showing up as "used" in the reports if there is no
* CPE identified. As such, we are "using" the evidence and ignoring the results. */
if (dependency.getVersionEvidence().contains(confidence)) {
addEvidenceWithoutDuplicateTerms("", dependency.getVersionEvidence(), confidence);
// if (dependency.getVersionEvidence().contains(confidence)) {
// addEvidenceWithoutDuplicateTerms("", dependency.getVersionEvidence(), confidence);
// }
if (!vendors.isEmpty() && !products.isEmpty()) {
final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getProductEvidence().getWeighting(),
dependency.getVendorEvidence().getWeighting());
if (entries == null) {
continue;
}
boolean identifierAdded = false;
for (IndexEntry e : entries) {
if (verifyEntry(e, dependency)) {
final String vendor = e.getVendor();
final String product = e.getProduct();
identifierAdded |= determineIdentifiers(dependency, vendor, product, confidence);
}
}
if (identifierAdded) {
break;
}
}
} while ((++ctr) < 4);
}
}
/**
@@ -239,22 +238,6 @@ public class CPEAnalyzer implements Analyzer {
return sb.toString().trim();
}
/**
* Reduces the given confidence by one level. This returns LOW if the confidence passed in is not HIGH.
*
* @param c the confidence to reduce.
* @return One less then the confidence passed in.
*/
private Confidence reduceConfidence(final Confidence c) {
if (c == Confidence.HIGHEST) {
return Confidence.HIGH;
} else if (c == Confidence.HIGH) {
return Confidence.MEDIUM;
} else {
return Confidence.LOW;
}
}
/**
* <p>
* Searches the Lucene CPE index to identify possible CPE entries associated with the supplied vendor, product, and
@@ -269,27 +252,24 @@ public class CPEAnalyzer implements Analyzer {
* @param vendorWeightings a list of strings to use to add weighting factors to the vendor field
* @param productWeightings Adds a list of strings that will be used to add weighting factors to the product search
* @return a list of possible CPE values
* @throws CorruptIndexException when the Lucene index is corrupt
* @throws IOException when the Lucene index is not found
* @throws ParseException when the generated query is not valid
*/
protected List<IndexEntry> searchCPE(String vendor, String product,
Set<String> vendorWeightings, Set<String> productWeightings)
throws CorruptIndexException, IOException, ParseException {
Set<String> vendorWeightings, Set<String> productWeightings) {
final ArrayList<IndexEntry> ret = new ArrayList<IndexEntry>(MAX_QUERY_RESULTS);
final String searchString = buildSearch(vendor, product, vendorWeightings, productWeightings);
if (searchString == null) {
return ret;
}
final TopDocs docs = cpe.search(searchString, MAX_QUERY_RESULTS);
for (ScoreDoc d : docs.scoreDocs) {
if (d.score >= 0.08) {
final Document doc = cpe.getDocument(d.doc);
final IndexEntry entry = new IndexEntry();
entry.setVendor(doc.get(Fields.VENDOR));
entry.setProduct(doc.get(Fields.PRODUCT));
try {
final TopDocs docs = cpe.search(searchString, MAX_QUERY_RESULTS);
for (ScoreDoc d : docs.scoreDocs) {
if (d.score >= 0.08) {
final Document doc = cpe.getDocument(d.doc);
final IndexEntry entry = new IndexEntry();
entry.setVendor(doc.get(Fields.VENDOR));
entry.setProduct(doc.get(Fields.PRODUCT));
// if (d.score < 0.08) {
// System.out.print(entry.getVendor());
// System.out.print(":");
@@ -297,13 +277,23 @@ public class CPEAnalyzer implements Analyzer {
// System.out.print(":");
// System.out.println(d.score);
// }
entry.setSearchScore(d.score);
if (!ret.contains(entry)) {
ret.add(entry);
entry.setSearchScore(d.score);
if (!ret.contains(entry)) {
ret.add(entry);
}
}
}
return ret;
} catch (ParseException ex) {
final String msg = String.format("Unable to parse: %s", searchString);
LOGGER.log(Level.WARNING, "An error occured querying the CPE data. See the log for more details.");
LOGGER.log(Level.INFO, msg, ex);
} catch (IOException ex) {
final String msg = String.format("IO Error with search string: %s", searchString);
LOGGER.log(Level.WARNING, "An error occured reading CPE data. See the log for more details.");
LOGGER.log(Level.INFO, msg, ex);
}
return ret;
return null;
}
/**
@@ -508,14 +498,21 @@ public class CPEAnalyzer implements Analyzer {
* @param dependency the Dependency being analyzed
* @param vendor the vendor for the CPE being analyzed
* @param product the product for the CPE being analyzed
* @param currentConfidence the current confidence being used during analysis
* @return <code>true</code> if an identifier was added to the dependency; otherwise <code>false</code>
* @throws UnsupportedEncodingException is thrown if UTF-8 is not supported
*/
private void determineIdentifiers(Dependency dependency, String vendor, String product) throws UnsupportedEncodingException {
protected boolean determineIdentifiers(Dependency dependency, String vendor, String product,
Confidence currentConfidence) throws UnsupportedEncodingException {
final Set<VulnerableSoftware> cpes = cve.getCPEs(vendor, product);
DependencyVersion bestGuess = new DependencyVersion("-");
Confidence bestGuessConf = null;
boolean hasBroadMatch = false;
final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>();
for (Confidence conf : Confidence.values()) {
// if (conf.compareTo(currentConfidence) > 0) {
// break;
// }
for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) {
final DependencyVersion evVer = DependencyVersionUtil.parseVersion(evidence.getValue());
if (evVer == null) {
@@ -528,9 +525,12 @@ public class CPEAnalyzer implements Analyzer {
} else {
dbVer = DependencyVersionUtil.parseVersion(vs.getVersion());
}
if (dbVer == null //special case, no version specified - everything is vulnerable
|| evVer.equals(dbVer)) { //yeah! exact match
if (dbVer == null) { //special case, no version specified - everything is vulnerable
hasBroadMatch = true;
final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8"));
final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.BROAD_MATCH, conf);
collected.add(match);
} else if (evVer.equals(dbVer)) { //yeah! exact match
final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8"));
final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf);
collected.add(match);
@@ -556,7 +556,11 @@ public class CPEAnalyzer implements Analyzer {
}
}
final String cpeName = String.format("cpe:/a:%s:%s:%s", vendor, product, bestGuess.toString());
final String url = null;
String url = null;
if (hasBroadMatch) { //if we have a broad match we can add the URL to the best guess.
final String cpeUrlName = String.format("cpe:/a:%s:%s", vendor, product);
url = String.format(NVD_SEARCH_URL, URLEncoder.encode(cpeUrlName, "UTF-8"));
}
if (bestGuessConf == null) {
bestGuessConf = Confidence.LOW;
}
@@ -566,6 +570,7 @@ public class CPEAnalyzer implements Analyzer {
Collections.sort(collected);
final IdentifierConfidence bestIdentifierQuality = collected.get(0).getConfidence();
final Confidence bestEvidenceQuality = collected.get(0).getEvidenceConfidence();
boolean identifierAdded = false;
for (IdentifierMatch m : collected) {
if (bestIdentifierQuality.equals(m.getConfidence())
&& bestEvidenceQuality.equals(m.getEvidenceConfidence())) {
@@ -576,8 +581,10 @@ public class CPEAnalyzer implements Analyzer {
i.setConfidence(bestEvidenceQuality);
}
dependency.addIdentifier(i);
identifierAdded = true;
}
}
return identifierAdded;
}
/**
@@ -592,7 +599,12 @@ public class CPEAnalyzer implements Analyzer {
/**
* A best guess for the CPE.
*/
BEST_GUESS
BEST_GUESS,
/**
* The entire vendor/product group must be added (without a guess at version) because there is a CVE with a VS
* that only specifies vendor/product.
*/
BROAD_MATCH
}
/**

View File

@@ -0,0 +1,201 @@
/*
* This file is part of dependency-check-core.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.analyzer;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.data.central.CentralSearch;
import org.owasp.dependencycheck.data.nexus.MavenArtifact;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
/**
* Analyzer which will attempt to locate a dependency, and the GAV information, by querying Central for the dependency's
* SHA-1 digest.
*
* @author colezlaw
*/
public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(CentralAnalyzer.class.getName());
/**
* The name of the analyzer.
*/
private static final String ANALYZER_NAME = "Central Analyzer";
/**
* The phase in which this analyzer runs.
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
/**
* The types of files on which this will work.
*/
private static final Set<String> SUPPORTED_EXTENSIONS = newHashSet("jar");
/**
* The analyzer should be disabled if there are errors, so this is a flag to determine if such an error has
* occurred.
*/
private boolean errorFlag = false;
/**
* The searcher itself.
*/
private CentralSearch searcher;
/**
* Field indicating if the analyzer is enabled.
*/
private final boolean enabled = checkEnabled();
/**
* Determine whether to enable this analyzer or not.
*
* @return whether the analyzer should be enabled
*/
@Override
public boolean isEnabled() {
return enabled;
}
/**
* Determines if this analyzer is enabled.
*
* @return <code>true</code> if the analyzer is enabled; otherwise <code>false</code>
*/
private boolean checkEnabled() {
boolean retval = false;
try {
if (Settings.getBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED)) {
if (!Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED)
|| NexusAnalyzer.DEFAULT_URL.equals(Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL))) {
LOGGER.info("Enabling the Central analyzer");
retval = true;
} else {
LOGGER.info("Nexus analyzer is enabled, disabling the Central Analyzer");
}
} else {
LOGGER.info("Central analyzer disabled");
}
} catch (InvalidSettingException ise) {
LOGGER.warning("Invalid setting. Disabling the Central analyzer");
}
return retval;
}
/**
* Initializes the analyzer once before any analysis is performed.
*
* @throws Exception if there's an error during initialization
*/
@Override
public void initializeFileTypeAnalyzer() throws Exception {
LOGGER.fine("Initializing Central analyzer");
LOGGER.fine(String.format("Central analyzer enabled: %s", isEnabled()));
if (isEnabled()) {
final String searchUrl = Settings.getString(Settings.KEYS.ANALYZER_CENTRAL_URL);
LOGGER.fine(String.format("Central Analyzer URL: %s", searchUrl));
searcher = new CentralSearch(new URL(searchUrl));
}
}
/**
* Returns the analyzer's name.
*
* @return the name of the analyzer
*/
@Override
public String getName() {
return ANALYZER_NAME;
}
/**
* Returns the key used in the properties file to to reference the analyzer's enabled property.
*
* @return the analyzer's enabled property setting key.
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_CENTRAL_ENABLED;
}
/**
* Returns the analysis phase under which the analyzer runs.
*
* @return the phase under which the analyzer runs
*/
@Override
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}
/**
* Returns the extensions for which this Analyzer runs.
*
* @return the extensions for which this Analyzer runs
*/
@Override
public Set<String> getSupportedExtensions() {
return SUPPORTED_EXTENSIONS;
}
/**
* Performs the analysis.
*
* @param dependency the dependency to analyze
* @param engine the engine
* @throws AnalysisException when there's an exception during analysis
*/
@Override
public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
if (errorFlag || !isEnabled()) {
return;
}
try {
final List<MavenArtifact> mas = searcher.searchSha1(dependency.getSha1sum());
final Confidence confidence = mas.size() > 1 ? Confidence.HIGH : Confidence.HIGHEST;
for (MavenArtifact ma : mas) {
LOGGER.fine(String.format("Central analyzer found artifact (%s) for dependency (%s)", ma.toString(), dependency.getFileName()));
dependency.addAsEvidence("central", ma, confidence);
}
} catch (IllegalArgumentException iae) {
LOGGER.info(String.format("invalid sha1-hash on %s", dependency.getFileName()));
} catch (FileNotFoundException fnfe) {
LOGGER.fine(String.format("Artifact not found in repository: '%s", dependency.getFileName()));
} catch (IOException ioe) {
LOGGER.log(Level.FINE, "Could not connect to Central search", ioe);
errorFlag = true;
}
}
}

View File

@@ -112,7 +112,7 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
while (subIterator.hasNext()) {
final Dependency nextDependency = subIterator.next();
if (hashesMatch(dependency, nextDependency)) {
if (isCore(dependency, nextDependency)) {
if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) {
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
} else {
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
@@ -390,4 +390,43 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
}
return false;
}
/**
* Determines which path is shortest; if path lengths are equal then we use compareTo of the string method to
* determine if the first path is smaller.
*
* @param left the first path to compare
* @param right the second path to compare
* @return <code>true</code> if the leftPath is the shortest; otherwise <code>false</code>
*/
protected boolean firstPathIsShortest(String left, String right) {
final String leftPath = left.replace('\\', '/');
final String rightPath = right.replace('\\', '/');
final int leftCount = countChar(leftPath, '/');
final int rightCount = countChar(rightPath, '/');
if (leftCount == rightCount) {
return leftPath.compareTo(rightPath) <= 0;
} else {
return leftCount < rightCount;
}
}
/**
* Counts the number of times the character is present in the string.
*
* @param string the string to count the characters in
* @param c the character to count
* @return the number of times the character is present in the string
*/
private int countChar(String string, char c) {
int count = 0;
final int max = string.length();
for (int i = 0; i < max; i++) {
if (c == string.charAt(i)) {
count++;
}
}
return count;
}
}

View File

@@ -86,12 +86,46 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
removeJreEntries(dependency);
removeBadMatches(dependency);
removeBadSpringMatches(dependency);
removeWrongVersionMatches(dependency);
removeSpuriousCPE(dependency);
removeDuplicativeEntriesFromJar(dependency, engine);
addFalseNegativeCPEs(dependency);
}
/**
* Removes inaccurate matches on springframework CPEs.
*
* @param dependency the dependency to test for and remove known inaccurate CPE matches
*/
private void removeBadSpringMatches(Dependency dependency) {
String mustContain = null;
for (Identifier i : dependency.getIdentifiers()) {
if ("maven".contains(i.getType())) {
if (i.getValue() != null && i.getValue().startsWith("org.springframework.")) {
final int endPoint = i.getValue().indexOf(":", 19);
if (endPoint >= 0) {
mustContain = i.getValue().substring(19, endPoint).toLowerCase();
break;
}
}
}
}
if (mustContain != null) {
final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
while (itr.hasNext()) {
final Identifier i = itr.next();
if ("cpe".contains(i.getType())
&& i.getValue() != null
&& i.getValue().startsWith("cpe:/a:springsource:")
&& !i.getValue().toLowerCase().contains(mustContain)) {
itr.remove();
//dependency.getIdentifiers().remove(i);
}
}
}
}
/**
* <p>
* Intended to remove spurious CPE entries. By spurious we mean duplicate, less specific CPE entries.</p>

View File

@@ -73,7 +73,7 @@ public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer {
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
//strip any path information that may get added by ArchiveAnalyzer, etc.
final File f = new File(dependency.getFileName());
final File f = dependency.getActualFile();
String fileName = f.getName();
//remove file extension

View File

@@ -293,13 +293,27 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
LOGGER.log(Level.FINE, msg, ex);
return false;
}
File externalPom = null;
if (pomEntries.isEmpty()) {
return false;
if (dependency.getActualFilePath().matches(".*\\.m2.repository\\b.*")) {
String pomPath = dependency.getActualFilePath();
pomPath = pomPath.substring(0, pomPath.lastIndexOf('.')) + ".pom";
externalPom = new File(pomPath);
if (externalPom.isFile()) {
pomEntries.add(pomPath);
} else {
return false;
}
} else {
return false;
}
}
for (String path : pomEntries) {
Properties pomProperties = null;
try {
pomProperties = retrievePomProperties(path, jar);
if (externalPom == null) {
pomProperties = retrievePomProperties(path, jar);
}
} catch (IOException ex) {
LOGGER.log(Level.FINEST, "ignore this, failed reading a non-existent pom.properties", ex);
}
@@ -313,11 +327,11 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
final String displayPath = String.format("%s%s%s",
dependency.getFilePath(),
File.separator,
path); //.replaceAll("[\\/]", File.separator));
path);
final String displayName = String.format("%s%s%s",
dependency.getFileName(),
File.separator,
path); //.replaceAll("[\\/]", File.separator));
path);
newDependency.setFileName(displayName);
newDependency.setFilePath(displayPath);
@@ -325,7 +339,11 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
engine.getDependencies().add(newDependency);
Collections.sort(engine.getDependencies());
} else {
pom = retrievePom(path, jar);
if (externalPom == null) {
pom = retrievePom(path, jar);
} else {
pom = retrievePom(externalPom);
}
foundSomething |= setPomEvidence(dependency, pom, pomProperties, classes);
}
} catch (AnalysisException ex) {
@@ -523,6 +541,41 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
return model;
}
/**
* Reads in the specified POM and converts it to a Model.
*
* @param file the pom.xml file
* @return returns a
* @throws AnalysisException is thrown if there is an exception extracting or parsing the POM
* {@link org.owasp.dependencycheck.jaxb.pom.generated.Model} object
*/
private Model retrievePom(File file) throws AnalysisException {
Model model = null;
try {
final FileInputStream stream = new FileInputStream(file);
final InputStreamReader reader = new InputStreamReader(stream, "UTF-8");
final InputSource xml = new InputSource(reader);
final SAXSource source = new SAXSource(xml);
model = readPom(source);
} catch (SecurityException ex) {
final String msg = String.format("Unable to parse pom '%s'; invalid signature", file.getPath());
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, null, ex);
throw new AnalysisException(ex);
} catch (IOException ex) {
final String msg = String.format("Unable to parse pom '%s'(IO Exception)", file.getPath());
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, "", ex);
throw new AnalysisException(ex);
} catch (Throwable ex) {
final String msg = String.format("Unexpected error during parsing of the pom '%s'", file.getPath());
LOGGER.log(Level.WARNING, msg);
LOGGER.log(Level.FINE, "", ex);
throw new AnalysisException(ex);
}
return model;
}
/**
* Retrieves the specified POM from a jar file and converts it to a Model.
*
@@ -583,11 +636,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
final String originalGroupID = groupid;
if (groupid != null && !groupid.isEmpty()) {
if (groupid.startsWith("org.") || groupid.startsWith("com.")) {
groupid = groupid.substring(4);
}
foundSomething = true;
dependency.getVendorEvidence().addEvidence("pom", "groupid", groupid, Confidence.HIGH);
dependency.getVendorEvidence().addEvidence("pom", "groupid", groupid, Confidence.HIGHEST);
dependency.getProductEvidence().addEvidence("pom", "groupid", groupid, Confidence.LOW);
addMatchingValues(classes, groupid, dependency.getVendorEvidence());
addMatchingValues(classes, groupid, dependency.getProductEvidence());
@@ -616,7 +666,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
artifactid = artifactid.substring(4);
}
foundSomething = true;
dependency.getProductEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.HIGH);
dependency.getProductEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.HIGHEST);
dependency.getVendorEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.LOW);
addMatchingValues(classes, artifactid, dependency.getVendorEvidence());
addMatchingValues(classes, artifactid, dependency.getProductEvidence());

View File

@@ -30,7 +30,7 @@ import org.owasp.dependencycheck.data.nexus.MavenArtifact;
import org.owasp.dependencycheck.data.nexus.NexusSearch;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Identifier;
import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
/**
@@ -49,6 +49,11 @@ import org.owasp.dependencycheck.utils.Settings;
*/
public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The default URL - this will be used by the CentralAnalyzer to determine whether to enable this.
*/
public static final String DEFAULT_URL = "https://repository.sonatype.org/service/local/";
/**
* The logger.
*/
@@ -74,6 +79,47 @@ public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
*/
private NexusSearch searcher;
/**
* Field indicating if the analyzer is enabled.
*/
private final boolean enabled = checkEnabled();
/**
* Determines if this analyzer is enabled
*
* @return <code>true</code> if the analyzer is enabled; otherwise <code>false</code>
*/
private boolean checkEnabled() {
/* Enable this analyzer ONLY if the Nexus URL has been set to something
other than the default one (if it's the default one, we'll use the
central one) and it's enabled by the user.
*/
boolean retval = false;
try {
if ((!DEFAULT_URL.equals(Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL)))
&& Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED)) {
LOGGER.info("Enabling Nexus analyzer");
retval = true;
} else {
LOGGER.info("Nexus analyzer disabled, using Central instead");
}
} catch (InvalidSettingException ise) {
LOGGER.warning("Invalid setting. Disabling Nexus analyzer");
}
return retval;
}
/**
* Determine whether to enable this analyzer or not.
*
* @return whether the analyzer should be enabled
*/
@Override
public boolean isEnabled() {
return enabled;
}
/**
* Initializes the analyzer once before any analysis is performed.
*
@@ -150,31 +196,12 @@ public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
*/
@Override
public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
if (!isEnabled()) {
return;
}
try {
final MavenArtifact ma = searcher.searchSha1(dependency.getSha1sum());
if (ma.getGroupId() != null && !"".equals(ma.getGroupId())) {
dependency.getVendorEvidence().addEvidence("nexus", "groupid", ma.getGroupId(), Confidence.HIGH);
}
if (ma.getArtifactId() != null && !"".equals(ma.getArtifactId())) {
dependency.getProductEvidence().addEvidence("nexus", "artifactid", ma.getArtifactId(), Confidence.HIGH);
}
if (ma.getVersion() != null && !"".equals(ma.getVersion())) {
dependency.getVersionEvidence().addEvidence("nexus", "version", ma.getVersion(), Confidence.HIGH);
}
if (ma.getArtifactUrl() != null && !"".equals(ma.getArtifactUrl())) {
boolean found = false;
for (Identifier i : dependency.getIdentifiers()) {
if ("maven".equals(i.getType()) && i.getValue().equals(ma.toString())) {
found = true;
i.setConfidence(Confidence.HIGHEST);
i.setUrl(ma.getArtifactUrl());
break;
}
}
if (!found) {
dependency.addIdentifier("maven", ma.toString(), ma.getArtifactUrl(), Confidence.HIGHEST);
}
}
dependency.addAsEvidence("nexus", ma, Confidence.HIGH);
} catch (IllegalArgumentException iae) {
//dependency.addAnalysisException(new AnalysisException("Invalid SHA-1"));
LOGGER.info(String.format("invalid sha-1 hash on %s", dependency.getFileName()));

View File

@@ -0,0 +1,151 @@
/*
* This file is part of dependency-check-core.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.central;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.owasp.dependencycheck.data.nexus.MavenArtifact;
import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.utils.URLConnectionFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
/**
* Class of methods to search Maven Central via Central.
*
* @author colezlaw
*/
public class CentralSearch {
/**
* The URL for the Central service
*/
private final URL rootURL;
/**
* Whether to use the Proxy when making requests
*/
private boolean useProxy;
/**
* Used for logging.
*/
private static final Logger LOGGER = Logger.getLogger(CentralSearch.class.getName());
/**
* Creates a NexusSearch for the given repository URL.
*
* @param rootURL the URL of the repository on which searches should execute. Only parameters are added to this (so
* it should end in /select)
*/
public CentralSearch(URL rootURL) {
this.rootURL = rootURL;
if (null != Settings.getString(Settings.KEYS.PROXY_SERVER)) {
useProxy = true;
LOGGER.fine("Using proxy");
} else {
useProxy = false;
LOGGER.fine("Not using proxy");
}
}
/**
* Searches the configured Central URL for the given sha1 hash. If the artifact is found, a
* <code>MavenArtifact</code> is populated with the GAV.
*
* @param sha1 the SHA-1 hash string for which to search
* @return the populated Maven GAV.
* @throws IOException if it's unable to connect to the specified repository or if the specified artifact is not
* found.
*/
public List<MavenArtifact> searchSha1(String sha1) throws IOException {
if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) {
throw new IllegalArgumentException("Invalid SHA1 format");
}
final URL url = new URL(rootURL + String.format("?q=1:\"%s\"&wt=xml", sha1));
LOGGER.fine(String.format("Searching Central url %s", url.toString()));
// Determine if we need to use a proxy. The rules:
// 1) If the proxy is set, AND the setting is set to true, use the proxy
// 2) Otherwise, don't use the proxy (either the proxy isn't configured,
// or proxy is specifically set to false)
final HttpURLConnection conn = URLConnectionFactory.createHttpURLConnection(url, useProxy);
conn.setDoOutput(true);
// JSON would be more elegant, but there's not currently a dependency
// on JSON, so don't want to add one just for this
conn.addRequestProperty("Accept", "application/xml");
conn.connect();
if (conn.getResponseCode() == 200) {
boolean missing = false;
try {
final DocumentBuilder builder = DocumentBuilderFactory
.newInstance().newDocumentBuilder();
final Document doc = builder.parse(conn.getInputStream());
final XPath xpath = XPathFactory.newInstance().newXPath();
final String numFound = xpath.evaluate("/response/result/@numFound", doc);
if ("0".equals(numFound)) {
missing = true;
} else {
final ArrayList<MavenArtifact> result = new ArrayList<MavenArtifact>();
final NodeList docs = (NodeList) xpath.evaluate("/response/result/doc", doc, XPathConstants.NODESET);
for (int i = 0; i < docs.getLength(); i++) {
final String g = xpath.evaluate("./str[@name='g']", docs.item(i));
LOGGER.finest(String.format("GroupId: %s", g));
final String a = xpath.evaluate("./str[@name='a']", docs.item(i));
LOGGER.finest(String.format("ArtifactId: %s", a));
final String v = xpath.evaluate("./str[@name='v']", docs.item(i));
LOGGER.finest(String.format("Version: %s", v));
result.add(new MavenArtifact(g, a, v, url.toString()));
}
return result;
}
} catch (Throwable e) {
// Anything else is jacked up XML stuff that we really can't recover
// from well
throw new IOException(e.getMessage(), e);
}
if (missing) {
throw new FileNotFoundException("Artifact not found in Central");
}
} else {
final String msg = String.format("Could not connect to Central received response code: %d %s",
conn.getResponseCode(), conn.getResponseMessage());
LOGGER.fine(msg);
throw new IOException(msg);
}
return null;
}
}

View File

@@ -0,0 +1,14 @@
/**
* <html>
* <head>
* <title>org.owasp.dependencycheck.data.central</title>
* </head>
* <body>
* <p>
* Contains classes related to searching Maven Central.</p>
* <p>
* These are used to abstract Maven Central searching away from OWASP Dependency Check so they can be reused elsewhere.</p>
* </body>
* </html>
*/
package org.owasp.dependencycheck.data.central;

View File

@@ -54,6 +54,7 @@ import org.owasp.dependencycheck.utils.Pair;
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public final class CpeMemoryIndex {
/**
* The logger.
*/
@@ -160,7 +161,7 @@ public final class CpeMemoryIndex {
*/
@SuppressWarnings("unchecked")
private Analyzer createSearchingAnalyzer() {
final Map fieldAnalyzers = new HashMap();
final Map<String, Analyzer> fieldAnalyzers = new HashMap<String, Analyzer>();
fieldAnalyzers.put(Fields.DOCUMENT_KEY, new KeywordAnalyzer());
productSearchFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION);
vendorSearchFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION);

View File

@@ -29,10 +29,12 @@ import java.util.logging.Logger;
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public final class CweDB {
/**
* The Logger.
*/
private static final Logger LOGGER = Logger.getLogger(CweDB.class.getName());
/**
* Empty private constructor as this is a utility class.
*/
@@ -55,7 +57,9 @@ public final class CweDB {
final String filePath = "data/cwe.hashmap.serialized";
final InputStream input = CweDB.class.getClassLoader().getResourceAsStream(filePath);
oin = new ObjectInputStream(input);
return (HashMap<String, String>) oin.readObject();
@SuppressWarnings("unchecked")
final HashMap<String, String> ret = (HashMap<String, String>) oin.readObject();
return ret;
} catch (ClassNotFoundException ex) {
LOGGER.log(Level.WARNING, "Unable to load CWE data. This should not be an issue.");
LOGGER.log(Level.FINE, null, ex);

View File

@@ -306,14 +306,14 @@ public class CveDB {
* @throws DatabaseException thrown when there is an error retrieving the data from the DB
*/
public Set<Pair<String, String>> getVendorProductList() throws DatabaseException {
final HashSet data = new HashSet<Pair<String, String>>();
final Set<Pair<String, String>> data = new HashSet<Pair<String, String>>();
ResultSet rs = null;
PreparedStatement ps = null;
try {
ps = getConnection().prepareStatement(SELECT_VENDOR_PRODUCT_LIST);
rs = ps.executeQuery();
while (rs.next()) {
data.add(new Pair(rs.getString(1), rs.getString(2)));
data.add(new Pair<String, String>(rs.getString(1), rs.getString(2)));
}
} catch (SQLException ex) {
final String msg = "An unexpected SQL Exception occurred; please see the verbose log for more details.";
@@ -731,7 +731,7 @@ public class CveDB {
* @param previous a flag indicating if previous versions of the product are vulnerable
* @return true if the identified version is affected, otherwise false
*/
private boolean isAffected(String vendor, String product, DependencyVersion identifiedVersion, String cpeId, String previous) {
protected boolean isAffected(String vendor, String product, DependencyVersion identifiedVersion, String cpeId, String previous) {
boolean affected = false;
final boolean isStruts = "apache".equals(vendor) && "struts".equals(product);
final DependencyVersion v = parseDependencyVersion(cpeId);

View File

@@ -142,8 +142,8 @@ public class DatabaseProperties {
*
* @return a map of the database meta data
*/
public Map getMetaData() {
final TreeMap map = new TreeMap();
public Map<String, String> getMetaData() {
final TreeMap<String, String> map = new TreeMap<String, String>();
for (Entry<Object, Object> entry : properties.entrySet()) {
final String key = (String) entry.getKey();
if (!"version".equals(key)) {
@@ -156,10 +156,10 @@ public class DatabaseProperties {
map.put(key, formatted);
} catch (Throwable ex) { //deliberately being broad in this catch clause
LOGGER.log(Level.FINE, "Unable to parse timestamp from DB", ex);
map.put(key, entry.getValue());
map.put(key, (String) entry.getValue());
}
} else {
map.put(key, entry.getValue());
map.put(key, (String) entry.getValue());
}
}
}

View File

@@ -18,6 +18,9 @@
package org.owasp.dependencycheck.data.update.task;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.Callable;
@@ -25,6 +28,8 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.GZIPInputStream;
import org.apache.commons.io.FileUtils;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.data.update.NvdCveInfo;
import org.owasp.dependencycheck.data.update.exception.UpdateException;
@@ -195,10 +200,18 @@ public class DownloadTask implements Callable<Future<ProcessTask>> {
LOGGER.log(Level.FINE, null, ex);
return null;
}
if (url1.toExternalForm().endsWith(".xml.gz")) {
extractGzip(first);
}
if (url2.toExternalForm().endsWith(".xml.gz")) {
extractGzip(second);
}
msg = String.format("Download Complete for NVD CVE - %s", nvdCveInfo.getId());
LOGGER.log(Level.INFO, msg);
if (this.processorService == null) {
return null;
}
final ProcessTask task = new ProcessTask(cveDB, this, settings);
return this.processorService.submit(task);
@@ -237,4 +250,48 @@ public class DownloadTask implements Callable<Future<ProcessTask>> {
}
}
}
/**
* Extracts the file contained in a gzip archive. The extracted file is placed in the exact same path as the file
* specified.
*
* @param file the archive file
* @throws FileNotFoundException thrown if the file does not exist
* @throws IOException thrown if there is an error extracting the file.
*/
private void extractGzip(File file) throws FileNotFoundException, IOException {
final String originalPath = file.getPath();
File gzip = new File(originalPath + ".gz");
if (gzip.isFile()) {
gzip.delete();
}
if (!file.renameTo(gzip)) {
throw new IOException("Unable to rename '" + file.getPath() + "'");
}
final File newfile = new File(originalPath);
final byte[] buffer = new byte[4096];
GZIPInputStream cin = null;
FileOutputStream out = null;
try {
cin = new GZIPInputStream(new FileInputStream(gzip));
out = new FileOutputStream(newfile);
int len;
while ((len = cin.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
} finally {
if (cin != null) {
cin.close();
}
if (out != null) {
out.close();
}
if (gzip.isFile()) {
FileUtils.deleteQuietly(gzip);
}
}
}
}

View File

@@ -19,12 +19,14 @@ package org.owasp.dependencycheck.dependency;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.security.NoSuchAlgorithmException;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.owasp.dependencycheck.data.nexus.MavenArtifact;
import org.owasp.dependencycheck.utils.Checksum;
import org.owasp.dependencycheck.utils.FileUtils;
@@ -35,7 +37,7 @@ import org.owasp.dependencycheck.utils.FileUtils;
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class Dependency implements Comparable<Dependency> {
public class Dependency implements Serializable, Comparable<Dependency> {
/**
* The logger.
@@ -315,6 +317,41 @@ public class Dependency implements Comparable<Dependency> {
this.identifiers.add(i);
}
/**
* Adds the maven artifact as evidence.
*
* @param source The source of the evidence
* @param mavenArtifact The maven artifact
* @param confidence The confidence level of this evidence
*/
public void addAsEvidence(String source, MavenArtifact mavenArtifact, Confidence confidence) {
if (mavenArtifact.getGroupId() != null && !mavenArtifact.getGroupId().isEmpty()) {
this.getVendorEvidence().addEvidence(source, "groupid", mavenArtifact.getGroupId(), confidence);
}
if (mavenArtifact.getArtifactId() != null && !mavenArtifact.getArtifactId().isEmpty()) {
this.getProductEvidence().addEvidence(source, "artifactid", mavenArtifact.getArtifactId(), confidence);
}
if (mavenArtifact.getVersion() != null && !mavenArtifact.getVersion().isEmpty()) {
this.getVersionEvidence().addEvidence(source, "version", mavenArtifact.getVersion(), confidence);
}
if (mavenArtifact.getArtifactUrl() != null && !mavenArtifact.getArtifactUrl().isEmpty()) {
boolean found = false;
for (Identifier i : this.getIdentifiers()) {
if ("maven".equals(i.getType()) && i.getValue().equals(mavenArtifact.toString())) {
found = true;
i.setConfidence(Confidence.HIGHEST);
i.setUrl(mavenArtifact.getArtifactUrl());
LOGGER.fine(String.format("Already found identifier %s. Confidence set to highest", i.getValue()));
break;
}
}
if (!found) {
LOGGER.fine(String.format("Adding new maven identifier %s", mavenArtifact.toString()));
this.addIdentifier("maven", mavenArtifact.toString(), mavenArtifact.getArtifactUrl(), Confidence.HIGHEST);
}
}
}
/**
* Adds an entry to the list of detected Identifiers for the dependency file.
*
@@ -323,6 +360,7 @@ public class Dependency implements Comparable<Dependency> {
public void addIdentifier(Identifier identifier) {
this.identifiers.add(identifier);
}
/**
* A set of identifiers that have been suppressed.
*/
@@ -440,6 +478,7 @@ public class Dependency implements Comparable<Dependency> {
public EvidenceCollection getVersionEvidence() {
return this.versionEvidence;
}
/**
* The description of the JAR file.
*/
@@ -462,6 +501,7 @@ public class Dependency implements Comparable<Dependency> {
public void setDescription(String description) {
this.description = description;
}
/**
* The license that this dependency uses.
*/
@@ -484,6 +524,7 @@ public class Dependency implements Comparable<Dependency> {
public void setLicense(String license) {
this.license = license;
}
/**
* A list of vulnerabilities for this dependency.
*/
@@ -539,6 +580,7 @@ public class Dependency implements Comparable<Dependency> {
public void addVulnerability(Vulnerability vulnerability) {
this.vulnerabilities.add(vulnerability);
}
/**
* A collection of related dependencies.
*/
@@ -578,7 +620,7 @@ public class Dependency implements Comparable<Dependency> {
* @return an integer representing the natural ordering
*/
public int compareTo(Dependency o) {
return this.getFileName().compareToIgnoreCase(o.getFileName());
return this.getFilePath().compareToIgnoreCase(o.getFilePath());
}
/**

View File

@@ -17,12 +17,14 @@
*/
package org.owasp.dependencycheck.dependency;
import java.io.Serializable;
/**
* Evidence is a piece of information about a Dependency.
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class Evidence implements Comparable<Evidence> {
public class Evidence implements Serializable, Comparable<Evidence> {
/**
* Creates a new Evidence object.

View File

@@ -17,6 +17,7 @@
*/
package org.owasp.dependencycheck.dependency;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.util.HashSet;
import java.util.Iterator;
@@ -36,7 +37,7 @@ import org.owasp.dependencycheck.utils.UrlStringUtils;
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class EvidenceCollection implements Iterable<Evidence> {
public class EvidenceCollection implements Serializable, Iterable<Evidence> {
/**
* The logger.

View File

@@ -17,11 +17,13 @@
*/
package org.owasp.dependencycheck.dependency;
import java.io.Serializable;
/**
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class Identifier implements Comparable<Identifier> {
public class Identifier implements Serializable, Comparable<Identifier> {
/**
* Constructs a new Identifier with the specified data.

View File

@@ -167,15 +167,28 @@ public class ReportGenerator {
*/
public void generateReports(String outputDir, String outputFormat) throws IOException, Exception {
final String format = outputFormat.toUpperCase();
final String pathToCheck = outputDir.toLowerCase();
if (format.matches("^(XML|HTML|VULN|ALL)$")) {
if ("XML".equalsIgnoreCase(format)) {
generateReports(outputDir, Format.XML);
if (pathToCheck.endsWith(".xml")) {
generateReport("XmlReport", outputDir);
} else {
generateReports(outputDir, Format.XML);
}
}
if ("HTML".equalsIgnoreCase(format)) {
generateReports(outputDir, Format.HTML);
if (pathToCheck.endsWith(".html") || pathToCheck.endsWith(".htm")) {
generateReport("HtmlReport", outputDir);
} else {
generateReports(outputDir, Format.HTML);
}
}
if ("VULN".equalsIgnoreCase(format)) {
generateReports(outputDir, Format.VULN);
if (pathToCheck.endsWith(".html") || pathToCheck.endsWith(".htm")) {
generateReport("VulnReport", outputDir);
} else {
generateReports(outputDir, Format.VULN);
}
}
if ("ALL".equalsIgnoreCase(format)) {
generateReports(outputDir, Format.ALL);

View File

@@ -103,6 +103,12 @@ public class SuppressionHandler extends DefaultHandler {
currentText = new StringBuffer();
if (SUPPRESS.equals(qName)) {
rule = new SuppressionRule();
final String base = currentAttributes.getValue("base");
if (base != null) {
rule.setBase(Boolean.parseBoolean(base));
} else {
rule.setBase(false);
}
}
}

View File

@@ -26,11 +26,6 @@ import java.io.IOException;
*/
public class SuppressionParseException extends IOException {
/**
* The serial version UID.
*/
private static final long serialVersionUID = 1L;
/**
* Creates a new SuppressionParseException.
*/
@@ -50,7 +45,7 @@ public class SuppressionParseException extends IOException {
/**
* Creates a new SuppressionParseException.
*
* @param ex the cause of the download failure.
* @param ex the cause of the parse exception
*/
public SuppressionParseException(Throwable ex) {
super(ex);
@@ -60,7 +55,7 @@ public class SuppressionParseException extends IOException {
* Creates a new SuppressionParseException.
*
* @param msg a message for the exception.
* @param ex the cause of the download failure.
* @param ex the cause of the parse exception
*/
public SuppressionParseException(String msg, Throwable ex) {
super(msg, ex);

View File

@@ -266,6 +266,30 @@ public class SuppressionRule {
return gav != null;
}
/**
* A flag indicating whether or not the suppression rule is a core/base rule that should not be included in the
* resulting report in the "suppressed" section.
*/
private boolean base;
/**
* Get the value of base.
*
* @return the value of base
*/
public boolean isBase() {
return base;
}
/**
* Set the value of base.
*
* @param base new value of base
*/
public void setBase(boolean base) {
this.base = base;
}
/**
* Processes a given dependency to determine if any CPE, CVE, CWE, or CVSS scores should be suppressed. If any
* should be, they are removed from the dependency.
@@ -300,7 +324,9 @@ public class SuppressionRule {
final Identifier i = itr.next();
for (PropertyType c : this.cpe) {
if (identifierMatches("cpe", c, i)) {
dependency.addSuppressedIdentifier(i);
if (!isBase()) {
dependency.addSuppressedIdentifier(i);
}
itr.remove();
break;
}
@@ -339,7 +365,9 @@ public class SuppressionRule {
}
}
if (remove) {
dependency.addSuppressedVulnerability(v);
if (!isBase()) {
dependency.addSuppressedVulnerability(v);
}
itr.remove();
}
}

View File

@@ -54,7 +54,9 @@ public final class DBUtils {
int id = 0;
try {
rs = statement.getGeneratedKeys();
rs.next();
if (!rs.next()) {
throw new DatabaseException("Unable to get primary key for inserted row");
}
id = rs.getInt(1);
} catch (SQLException ex) {
throw new DatabaseException("Unable to get primary key for inserted row");

View File

@@ -65,7 +65,7 @@ public class DependencyVersion implements Iterable, Comparable<DependencyVersion
public final void parseVersion(String version) {
versionParts = new ArrayList<String>();
if (version != null) {
final Pattern rx = Pattern.compile("(\\d+|[a-z]+\\d+|(release|beta|alpha)$)");
final Pattern rx = Pattern.compile("(\\d+[a-z]{1,3}$|[a-z]+\\d+|\\d+|(release|beta|alpha)$)");
final Matcher matcher = rx.matcher(version.toLowerCase());
while (matcher.find()) {
versionParts.add(matcher.group());
@@ -189,17 +189,23 @@ public class DependencyVersion implements Iterable, Comparable<DependencyVersion
if (version == null) {
return false;
}
boolean ret = true;
int max = (this.versionParts.size() < version.versionParts.size())
? this.versionParts.size() : version.versionParts.size();
if (max > 3) {
max = 3;
if (Math.abs(this.versionParts.size() - version.versionParts.size()) >= 3) {
return false;
}
final int max = (this.versionParts.size() < version.versionParts.size())
? this.versionParts.size() : version.versionParts.size();
boolean ret = true;
for (int i = 0; i < max; i++) {
if (this.versionParts.get(i) == null || !this.versionParts.get(i).equals(version.versionParts.get(i))) {
final String thisVersion = this.versionParts.get(i);
final String otherVersion = version.getVersionParts().get(i);
if (i >= 3) {
if (thisVersion.compareToIgnoreCase(otherVersion) >= 0) {
ret = false;
break;
}
} else if (!thisVersion.equals(otherVersion)) {
ret = false;
break;
}

View File

@@ -32,7 +32,7 @@ public final class DependencyVersionUtil {
/**
* Regular expression to extract version numbers from file names.
*/
private static final Pattern RX_VERSION = Pattern.compile("\\d+(\\.\\d{1,6})+(\\.?([_-](release|beta|alpha)|[a-zA-Z_-]{1,3}\\d{1,8}))?");
private static final Pattern RX_VERSION = Pattern.compile("\\d+(\\.\\d{1,6})+(\\.?([_-](release|beta|alpha|\\d+)|[a-zA-Z_-]{1,3}\\d{0,8}))?");
/**
* Regular expression to extract a single version number without periods. This is a last ditch effort just to check
* in case we are missing a version number using the previous regex.

View File

@@ -8,6 +8,7 @@ org.owasp.dependencycheck.analyzer.CpeSuppressionAnalyzer
org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer
org.owasp.dependencycheck.analyzer.NvdCveAnalyzer
org.owasp.dependencycheck.analyzer.VulnerabilitySuppressionAnalyzer
org.owasp.dependencycheck.analyzer.CentralAnalyzer
org.owasp.dependencycheck.analyzer.NexusAnalyzer
org.owasp.dependencycheck.analyzer.NuspecAnalyzer
org.owasp.dependencycheck.analyzer.AssemblyAnalyzer

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://www.owasp.org/index.php/OWASP_Dependency_Check_Suppression">
<suppress>
<suppress base="true">
<notes><![CDATA[
This suppresses false positives identified on spring security.
]]></notes>
@@ -9,7 +9,16 @@
<cpe>cpe:/a:springsource:spring_framework</cpe>
<cpe>cpe:/a:vmware:springsource_spring_framework</cpe>
</suppress>
<suppress>
<suppress base="true">
<notes><![CDATA[
This suppresses false positives identified on spring security.
]]></notes>
<filePath regex="true">.*spring-security-[^\\/]*\.jar$</filePath>
<cpe>cpe:/a:mod_security:mod_security</cpe>
<cpe>cpe:/a:springsource:spring_framework</cpe>
<cpe>cpe:/a:vmware:springsource_spring_framework</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
This suppreses additional false positives for the xstream library that occur because spring has a copy of this library.
com.springsource.com.thoughtworks.xstream-1.3.1.jar
@@ -17,4 +26,40 @@
<gav regex="true">com\.thoughtworks\.xstream:xstream:.*</gav>
<cpe>cpe:/a:springsource:spring_framework</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
Suppresses false positives on velocity tools.
]]></notes>
<gav regex="true">org\.apache\.velocity:velocity-tools:.*</gav>
<cpe>cpe:/a:apache:struts</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
Sandbox is a php blog platform and should not be flagged as a CPE for java or .net dependencies.
]]></notes>
<filePath regex="true">.*\.(jar|dll|exe|ear|war|pom)</filePath>
<cpe>cpe:/a:sandbox:sandbox</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
Suppresses false positives on Jersey core client.
]]></notes>
<gav regex="true">(com\.sun\.jersey|org\.glassfish\.jersey\.core):jersey-(client|common):.*</gav>
<cpe>cpe:/a:oracle:glassfish</cpe>
<cpe>cpe:/a:oracle:oracle_client</cpe>
</suppress>
<suppress>
<notes><![CDATA[
Suppresses false positives on the grizzly-framework
]]></notes>
<gav regex="true">org\.glassfish\.grizzly:grizzly-framework:.*</gav>
<cpe>cpe:/a:oracle:glassfish</cpe>
</suppress>
<suppress>
<notes><![CDATA[
Suppresses false positives on the grizzly-framework
]]></notes>
<gav regex="true">org\.forgerock\.opendj:opendj-ldap-sdk:.*</gav>
<cpe>cpe:/a:ldap_project:ldap</cpe>
</suppress>
</suppressions>

View File

@@ -40,11 +40,16 @@ data.driver_path=
cve.url.modified.validfordays=7
# the path to the modified nvd cve xml file.
cve.url-1.2.modified=http://nvd.nist.gov/download/nvdcve-modified.xml
cve.url-2.0.modified=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml
cve.url-1.2.modified=https://nvd.nist.gov/download/nvdcve-Modified.xml.gz
#cve.url-1.2.modified=http://nvd.nist.gov/download/nvdcve-modified.xml
cve.url-2.0.modified=https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-Modified.xml.gz
#cve.url-2.0.modified=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml
cve.startyear=2002
cve.url-2.0.base=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml
cve.url-1.2.base=http://nvd.nist.gov/download/nvdcve-%d.xml
cve.url-1.2.base=https://nvd.nist.gov/download/nvdcve-%d.xml.gz
#cve.url-1.2.base=http://nvd.nist.gov/download/nvdcve-%d.xml
cve.url-2.0.base=https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml.gz
#cve.url-2.0.base=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml
# file type analyzer settings:
analyzer.archive.enabled=true
@@ -58,3 +63,7 @@ analyzer.nexus.url=https://repository.sonatype.org/service/local/
# If set to true, the proxy will still ONLY be used if the proxy properties (proxy.url, proxy.port)
# are configured
analyzer.nexus.proxy=true
# the URL for searching search.maven.org for SHA-1 and whether it's enabled
analyzer.central.enabled=true
analyzer.central.url=http://search.maven.org/solrsearch/select

View File

@@ -50,6 +50,7 @@
<xs:element name="cvssBelow" type="dc:cvssScoreType"/>
</xs:choice>
</xs:sequence>
<xs:attribute name="base" use="optional" type="xs:boolean" default="false"/>
</xs:complexType>
</xs:element>
</xs:sequence>

View File

@@ -33,8 +33,8 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
</script>
<script type="text/javascript">
$(document).ready(function() {
$(".expandable").click(function (e) {
e = e || window.event;
$(".expandable").click(function (event) {
e = event || window.event;
var h = e.target || e.srcElement;
var content = "#content" + h.id.substr(6);
var header = "#" + h.id;
@@ -56,6 +56,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
$(header).addClass("expandablesubsection");
$(header).removeClass("collaspablesubsection");
}
return false;
});
});
@@ -533,24 +534,22 @@ arising out of or in connection with the use of this tool, the analysis performe
<li class="scaninfo hidden"><i>$enc.html($prop.key)</i>: $enc.html($prop.value)</li>
#end
</ul><br/>
Display:&nbsp;<a href="#" title="Click to toggle display" onclick="return toggleDisplay(this,'.notvulnerable', 'Showing Vulnerable Dependencies', 'Showing All Dependencies'); return false;">Showing Vulnerable Dependencies</a><br/><br/>
Display:&nbsp;<a href="#" title="Click to toggle display" onclick="return toggleDisplay(this, '.notvulnerable', 'Showing Vulnerable Dependencies', 'Showing All Dependencies'); return false;">Showing Vulnerable Dependencies</a><br/><br/>
#set($lnkcnt=0)
<table class="lined">
<tr style="text-align:left">
<th title="The name of the dependency">Dependency</th>
<th title="The number of related dependencies">#&nbsp;Related</th>
<th title="The Common Platform Enumeration">CPE</th>
<th title="The Maven GAV Coordinates">GAV</th>
<th title="The highest CVE Impact">CVE&nbsp;Impact</th>
<th title="The number of Common Vulnerability and Exposure (CVE) entries">CVE&nbsp;Count</th>
<th title="The confidence rating dependency-check has for the identified CPE">CPE&nbsp;Confidence</th>
<th title="The count of evidence used to identify the CPE">Evidence&nbsp;Count</th>
<th title="The highest CVE Severity">Highest Severity</th>
<th title="The number of Common Vulnerability and Exposure (CVE) entries">CVE Count</th>
<th title="The confidence rating dependency-check has for the identified CPE">CPE Confidence</th>
<th title="The count of evidence used to identify the CPE">Evidence Count</th>
</tr>
#foreach($dependency in $dependencies)
#set($lnkcnt=$lnkcnt+1)
<tr class="#if($dependency.getVulnerabilities().size()==0)notvulnerable#else vulnerable#end">
<td><a href="#l${lnkcnt}_$enc.html($enc.url($dependency.Sha1sum))">$enc.html($dependency.DisplayFileName)</a></td>
<td>$dependency.getRelatedDependencies().size()</td>
#set($mavenlink="")
#set($cpeIdCount=0)
#set($cpeIdConf="")
@@ -754,7 +753,7 @@ arising out of or in connection with the use of this tool, the analysis performe
<li class="vs$vsctr"><a target="_blank" href="https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=$enc.url($vuln.matchedCPE)">$enc.html($vuln.matchedCPE)</a> #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end</li>
</ul></p>
#else
<p>Vulnerable Software &amp; Versions:&nbsp;(<a href="#" onclick="toggleDisplay(this,'.vs$vsctr'); return false;">show all</a>)<ul>
<p>Vulnerable Software &amp; Versions:&nbsp;(<a href="#" onclick="return toggleDisplay(this,'.vs$vsctr', 'show all', 'show less');">show all</a>)<ul>
<li class="vs$vsctr"><a target="_blank" href="https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=$enc.url($vuln.matchedCPE)">$enc.html($vuln.matchedCPE)</a> #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end</li>
<li class="vs$vsctr">...</li>
#foreach($vs in $vuln.getVulnerableSoftware())
@@ -888,7 +887,7 @@ arising out of or in connection with the use of this tool, the analysis performe
git st<li class="vs$vsctr"><a target="_blank" href="https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=$enc.url($vuln.matchedCPE)">$enc.html($vuln.matchedCPE)</a> #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end</li>
</ul></p>
#else
<p>Vulnerable Software &amp; Versions:&nbsp;(<a href="#" onclick="toggleDisplay(this,'.vs$vsctr'); return false;">show all</a>)<ul>
<p>Vulnerable Software &amp; Versions:&nbsp;(<a href="#" onclick="return toggleDisplay(this,'.vs$vsctr', 'show all', 'show less');">show all</a>)<ul>
<li class="vs$vsctr"><a target="_blank" href="https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=$enc.url($vuln.matchedCPE)">$enc.html($vuln.matchedCPE)</a> #if($vuln.hasMatchedAllPreviousCPE()) and all previous versions#end</li>
<li class="vs$vsctr">...</li>
#foreach($vs in $vuln.getVulnerableSoftware())
@@ -907,6 +906,6 @@ arising out of or in connection with the use of this tool, the analysis performe
## END SUPPRESSED VULNERABILITIES
</div>
</div>
<div><br/><br/>This report contains data retrieved from the <a href="nvd.nist.gov">National Vulnerability Database</a>.</div>
<div><br/><br/>This report contains data retrieved from the <a href="http://nvd.nist.gov">National Vulnerability Database</a>.</div>
</body>
</html>

View File

@@ -236,6 +236,6 @@ arising out of or in connection with the use of this tool, the analysis performe
</tbody>
</table>
</div>
<p><br/><br/>This report contains data retrieved from the <a href="nvd.nist.gov">National Vulnerability Database</a>.</p>
<p><br/><br/>This report contains data retrieved from the <a href="http://nvd.nist.gov">National Vulnerability Database</a>.</p>
</body>
</html>

View File

@@ -23,7 +23,6 @@ import org.junit.Before;
import org.junit.Test;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.reporting.ReportGenerator;
import org.owasp.dependencycheck.utils.Settings;
@@ -42,26 +41,6 @@ public class EngineIntegrationTest extends BaseTest {
public void tearDown() {
}
/**
* Test of scan method, of class Engine.
*
* @throws Exception is thrown when an exception occurs.
*/
@Test
public void testScan() throws Exception {
String testClasses = "target/test-classes/*.zip";
boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
Engine instance = new Engine();
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
instance.scan(testClasses);
assertTrue(instance.getDependencies().size() > 0);
for (Dependency d : instance.getDependencies()) {
assertTrue("non-zip file collected " + d.getFileName(), d.getFileName().toLowerCase().endsWith(".zip"));
}
instance.cleanup();
}
/**
* Test running the entire engine.
*
@@ -70,10 +49,10 @@ public class EngineIntegrationTest extends BaseTest {
@Test
public void testEngine() throws Exception {
String testClasses = "target/test-classes";
// boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
// Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
Engine instance = new Engine();
// Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
instance.scan(testClasses);
assertTrue(instance.getDependencies().size() > 0);
instance.analyzeDependencies();
@@ -81,8 +60,7 @@ public class EngineIntegrationTest extends BaseTest {
cveDB.open();
DatabaseProperties dbProp = cveDB.getDatabaseProperties();
cveDB.close();
ReportGenerator rg = new ReportGenerator("DependencyCheck",
instance.getDependencies(), instance.getAnalyzers(), dbProp);
ReportGenerator rg = new ReportGenerator("DependencyCheck", instance.getDependencies(), instance.getAnalyzers(), dbProp);
rg.generateReports("./target/", "ALL");
instance.cleanup();
}

View File

@@ -40,7 +40,7 @@ public class ArchiveAnalyzerIntegrationTest extends AbstractDatabaseTestCase {
@Test
public void testGetSupportedExtensions() {
ArchiveAnalyzer instance = new ArchiveAnalyzer();
Set expResult = new HashSet<String>();
Set<String> expResult = new HashSet<String>();
expResult.add("zip");
expResult.add("war");
expResult.add("ear");

View File

@@ -25,9 +25,11 @@ import java.util.Set;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.queryparser.classic.ParseException;
import org.junit.Assert;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.owasp.dependencycheck.data.cpe.AbstractDatabaseTestCase;
import org.owasp.dependencycheck.data.cpe.IndexEntry;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Identifier;
@@ -81,12 +83,24 @@ public class CPEAnalyzerIntegrationTest extends AbstractDatabaseTestCase {
*/
@Test
public void testDetermineCPE_full() throws Exception {
callDetermineCPE_full("hazelcast-2.5.jar", null);
callDetermineCPE_full("spring-context-support-2.5.5.jar", "cpe:/a:vmware:springsource_spring_framework:2.5.5");
callDetermineCPE_full("spring-core-3.0.0.RELEASE.jar", "cpe:/a:vmware:springsource_spring_framework:3.0.0");
callDetermineCPE_full("org.mortbay.jetty.jar", "cpe:/a:mortbay_jetty:jetty:4.2");
callDetermineCPE_full("jaxb-xercesImpl-1.5.jar", null);
callDetermineCPE_full("ehcache-core-2.2.0.jar", null);
CPEAnalyzer instance = new CPEAnalyzer();
instance.open();
FileNameAnalyzer fnAnalyzer = new FileNameAnalyzer();
JarAnalyzer jarAnalyzer = new JarAnalyzer();
HintAnalyzer hAnalyzer = new HintAnalyzer();
FalsePositiveAnalyzer fp = new FalsePositiveAnalyzer();
try {
//callDetermineCPE_full("struts2-core-2.3.16.3.jar", "cpe:/a:apache:struts:2.3.16.3", instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("hazelcast-2.5.jar", null, instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("spring-context-support-2.5.5.jar", "cpe:/a:vmware:springsource_spring_framework:2.5.5", instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("spring-core-3.0.0.RELEASE.jar", "cpe:/a:vmware:springsource_spring_framework:3.0.0", instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("org.mortbay.jetty.jar", "cpe:/a:mortbay_jetty:jetty:4.2", instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("jaxb-xercesImpl-1.5.jar", null, instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("ehcache-core-2.2.0.jar", null, instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
} finally {
instance.close();
}
}
/**
@@ -94,25 +108,16 @@ public class CPEAnalyzerIntegrationTest extends AbstractDatabaseTestCase {
*
* @throws Exception is thrown when an exception occurs
*/
public void callDetermineCPE_full(String depName, String expResult) throws Exception {
public void callDetermineCPE_full(String depName, String expResult, CPEAnalyzer instance, FileNameAnalyzer fnAnalyzer, JarAnalyzer jarAnalyzer, HintAnalyzer hAnalyzer, FalsePositiveAnalyzer fp) throws Exception {
File file = new File(this.getClass().getClassLoader().getResource(depName).getPath());
Dependency dep = new Dependency(file);
FileNameAnalyzer fnAnalyzer = new FileNameAnalyzer();
fnAnalyzer.analyze(dep, null);
JarAnalyzer jarAnalyzer = new JarAnalyzer();
jarAnalyzer.analyze(dep, null);
HintAnalyzer hAnalyzer = new HintAnalyzer();
hAnalyzer.analyze(dep, null);
CPEAnalyzer instance = new CPEAnalyzer();
instance.open();
instance.analyze(dep, null);
instance.close();
FalsePositiveAnalyzer fp = new FalsePositiveAnalyzer();
fp.analyze(dep, null);
if (expResult != null) {
@@ -180,6 +185,30 @@ public class CPEAnalyzerIntegrationTest extends AbstractDatabaseTestCase {
//Assert.assertTrue("Incorrect match - spring", spring.getIdentifiers().get(0).getValue().equals(expResultSpring));
}
/**
* Test of determineIdentifiers method, of class CPEAnalyzer.
*
* @throws Exception is thrown when an exception occurs
*/
@Test
public void testDetermineIdentifiers() throws Exception {
Dependency openssl = new Dependency();
openssl.getVendorEvidence().addEvidence("test", "vendor", "openssl", Confidence.HIGHEST);
openssl.getProductEvidence().addEvidence("test", "product", "openssl", Confidence.HIGHEST);
openssl.getVersionEvidence().addEvidence("test", "version", "1.0.1c", Confidence.HIGHEST);
CPEAnalyzer instance = new CPEAnalyzer();
instance.open();
instance.determineIdentifiers(openssl, "openssl", "openssl", Confidence.HIGHEST);
instance.close();
String expResult = "cpe:/a:openssl:openssl:1.0.1c";
Identifier expIdentifier = new Identifier("cpe", expResult, expResult);
assertTrue(openssl.getIdentifiers().contains(expIdentifier));
}
/**
* Test of searchCPE method, of class CPEAnalyzer.
*
@@ -190,12 +219,12 @@ public class CPEAnalyzerIntegrationTest extends AbstractDatabaseTestCase {
String vendor = "apache software foundation";
String product = "struts 2 core";
String version = "2.1.2";
String expResult = "cpe:/a:apache:struts:2.1.2";
String expVendor = "apache";
String expProduct = "struts";
CPEAnalyzer instance = new CPEAnalyzer();
instance.open();
//TODO - yeah, not a very good test as the results are the same with or without weighting...
Set<String> productWeightings = new HashSet<String>(1);
productWeightings.add("struts2");
@@ -203,9 +232,16 @@ public class CPEAnalyzerIntegrationTest extends AbstractDatabaseTestCase {
vendorWeightings.add("apache");
List<IndexEntry> result = instance.searchCPE(vendor, product, productWeightings, vendorWeightings);
//TODO fix this assert
//Assert.assertEquals(expResult, result.get(0).getName());
instance.close();
boolean found = false;
for (IndexEntry entry : result) {
if (expVendor.equals(entry.getVendor()) && expProduct.equals(entry.getProduct())) {
found = true;
break;
}
}
assertTrue("apache:struts was not identified", found);
}
}

View File

@@ -86,4 +86,40 @@ public class DependencyBundlingAnalyzerTest extends BaseTest {
assertEquals(expResult, result);
}
@Test
public void testFirstPathIsShortest() {
DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer();
String left = "./a/c.jar";
String right = "./d/e/f.jar";
boolean expResult = true;
boolean result = instance.firstPathIsShortest(left, right);
assertEquals(expResult, result);
left = "./a/b/c.jar";
right = "./d/e/f.jar";
expResult = true;
result = instance.firstPathIsShortest(left, right);
assertEquals(expResult, result);
left = "./d/b/c.jar";
right = "./a/e/f.jar";
expResult = false;
result = instance.firstPathIsShortest(left, right);
assertEquals(expResult, result);
left = "./a/b/c.jar";
right = "./d/f.jar";
expResult = false;
result = instance.firstPathIsShortest(left, right);
assertEquals(expResult, result);
left = "./a/b/c.jar";
right = "./a/b/c.jar";
expResult = true;
result = instance.firstPathIsShortest(left, right);
assertEquals(expResult, result);
}
}

View File

@@ -93,7 +93,7 @@ public class JarAnalyzerTest extends BaseTest {
@Test
public void testGetSupportedExtensions() {
JarAnalyzer instance = new JarAnalyzer();
Set expResult = new HashSet();
Set<String> expResult = new HashSet<String>();
expResult.add("jar");
expResult.add("war");
Set result = instance.getSupportedExtensions();

View File

@@ -38,7 +38,7 @@ public class JavaScriptAnalyzerTest extends BaseTest {
@Test
public void testGetSupportedExtensions() {
JavaScriptAnalyzer instance = new JavaScriptAnalyzer();
Set expResult = new HashSet<String>();
Set<String> expResult = new HashSet<String>();
expResult.add("js");
Set result = instance.getSupportedExtensions();
assertEquals(expResult, result);

View File

@@ -0,0 +1,63 @@
package org.owasp.dependencycheck.data.central;
import org.junit.Before;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.data.nexus.MavenArtifact;
import org.owasp.dependencycheck.utils.Settings;
import java.io.FileNotFoundException;
import java.net.URL;
import java.util.List;
import java.util.logging.Logger;
import static org.junit.Assert.*;
/**
* Created by colezlaw on 10/13/14.
*/
public class CentralSearchTest extends BaseTest {
private static final Logger LOGGER = Logger.getLogger(CentralSearchTest.class.getName());
private CentralSearch searcher;
@Before
public void setUp() throws Exception {
String centralUrl = Settings.getString(Settings.KEYS.ANALYZER_CENTRAL_URL);
LOGGER.fine(centralUrl);
searcher = new CentralSearch(new URL(centralUrl));
}
@Test(expected = IllegalArgumentException.class)
public void testNullSha1() throws Exception { searcher.searchSha1(null); }
@Test(expected = IllegalArgumentException.class)
public void testMalformedSha1() throws Exception {
searcher.searchSha1("invalid");
}
// This test does generate network traffic and communicates with a host
// you may not be able to reach. Remove the @Ignore annotation if you want to
// test it anyway
@Test
public void testValidSha1() throws Exception {
List<MavenArtifact> ma = searcher.searchSha1("9977a8d04e75609cf01badc4eb6a9c7198c4c5ea");
assertEquals("Incorrect group", "org.apache.maven.plugins", ma.get(0).getGroupId());
assertEquals("Incorrect artifact", "maven-compiler-plugin", ma.get(0).getArtifactId());
assertEquals("Incorrect version", "3.1", ma.get(0).getVersion());
}
// This test does generate network traffic and communicates with a host
// you may not be able to reach. Remove the @Ignore annotation if you want to
// test it anyway
@Test(expected = FileNotFoundException.class)
public void testMissingSha1() throws Exception {
searcher.searchSha1("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
}
// This test should give us multiple results back from Central
@Test
public void testMultipleReturns() throws Exception {
List<MavenArtifact> ma = searcher.searchSha1("94A9CE681A42D0352B3AD22659F67835E560D107");
assertTrue(ma.size() > 1);
}
}

View File

@@ -19,9 +19,11 @@ package org.owasp.dependencycheck.data.nvdcve;
import java.util.List;
import java.util.Set;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
import org.owasp.dependencycheck.utils.DependencyVersion;
/**
*
@@ -72,4 +74,21 @@ public class CveDBIntegrationTest extends BaseDBTestCase {
instance.close();
}
}
/**
* Test of isAffected method, of class CveDB.
*/
@Test
public void testIsAffected() throws Exception {
String vendor = "openssl";
String product = "openssl";
DependencyVersion identifiedVersion = new DependencyVersion("1.0.1o");
String cpeId = "cpe:/a:openssl:openssl:1.0.1e";
String previous = "y";
CveDB instance = new CveDB();
assertFalse(instance.isAffected(vendor, product, identifiedVersion, cpeId, previous));
}
}

View File

@@ -0,0 +1,75 @@
/*
* This file is part of dependency-check-core.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.update.task;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertNull;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.data.update.NvdCveInfo;
import org.owasp.dependencycheck.utils.Settings;
/**
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class DownloadTaskTest {
public DownloadTaskTest() {
}
@BeforeClass
public static void setUpClass() {
}
@AfterClass
public static void tearDownClass() {
}
@Before
public void setUp() {
Settings.initialize();
}
@After
public void tearDown() {
Settings.cleanup();
}
/**
* Test of call method, of class DownloadTask.
*/
@Test
public void testCall() throws Exception {
NvdCveInfo cve = new NvdCveInfo();
cve.setId("modified");
cve.setNeedsUpdate(true);
cve.setUrl(Settings.getString(Settings.KEYS.CVE_MODIFIED_20_URL));
cve.setOldSchemaVersionUrl(Settings.getString(Settings.KEYS.CVE_MODIFIED_12_URL));
ExecutorService processExecutor = null;
CveDB cveDB = null;
DownloadTask instance = new DownloadTask(cve, processExecutor, cveDB, Settings.getInstance());;
Future<ProcessTask> result = instance.call();
assertNull(result);
}
}

View File

@@ -23,10 +23,12 @@ import java.util.Set;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.data.nexus.MavenArtifact;
/**
*
@@ -152,7 +154,7 @@ public class DependencyTest {
public void testGetMd5sum() {
File file = new File(this.getClass().getClassLoader().getResource("struts2-core-2.1.2.jar").getPath());
Dependency instance = new Dependency(file);
// assertEquals("89CE9E36AA9A9E03F1450936D2F4F8DD0F961F8B", result.getSha1sum());
//assertEquals("89CE9E36AA9A9E03F1450936D2F4F8DD0F961F8B", result.getSha1sum());
String expResult = "C30B57142E1CCBC1EFD5CD15F307358F";
String result = instance.getMd5sum();
assertEquals(expResult, result);
@@ -294,4 +296,34 @@ public class DependencyTest {
EvidenceCollection result = instance.getVersionEvidence();
assertTrue(true); //this is just a getter setter pair.
}
/**
* Test of addAsEvidence method, of class Dependency.
*/
@Test
public void testAddAsEvidence() {
Dependency instance = new Dependency();
MavenArtifact mavenArtifact = new MavenArtifact("group", "artifact", "version", "url");
instance.addAsEvidence("pom", mavenArtifact, Confidence.HIGH);
assertTrue(instance.getEvidence().contains(Confidence.HIGH));
assertFalse(instance.getEvidence().getEvidence("pom", "groupid").isEmpty());
assertFalse(instance.getEvidence().getEvidence("pom", "artifactid").isEmpty());
assertFalse(instance.getEvidence().getEvidence("pom", "version").isEmpty());
assertFalse(instance.getIdentifiers().isEmpty());
}
/**
* Test of addAsEvidence method, of class Dependency.
*/
@Test
public void testAddAsEvidenceWithEmptyArtefact() {
Dependency instance = new Dependency();
MavenArtifact mavenArtifact = new MavenArtifact(null, null, null, null);
instance.addAsEvidence("pom", mavenArtifact, Confidence.HIGH);
assertFalse(instance.getEvidence().contains(Confidence.HIGH));
assertTrue(instance.getEvidence().getEvidence("pom", "groupid").isEmpty());
assertTrue(instance.getEvidence().getEvidence("pom", "artifactid").isEmpty());
assertTrue(instance.getEvidence().getEvidence("pom", "version").isEmpty());
assertTrue(instance.getIdentifiers().isEmpty());
}
}

View File

@@ -88,7 +88,15 @@ public class SuppressionHandlerTest {
xmlReader.parse(in);
List result = handler.getSuppressionRules();
List<SuppressionRule> result = handler.getSuppressionRules();
assertTrue(result.size() > 3);
int baseCount = 0;
for (SuppressionRule r : result) {
if (r.isBase()) {
baseCount++;
}
}
assertTrue(baseCount > 0);
}
}

View File

@@ -146,6 +146,17 @@ public class SuppressionRuleTest {
List<String> result = instance.getCve();
assertEquals(cve, result);
}
/**
* Test of base property, of class SuppressionRule.
*/
@Test
public void testBase() {
SuppressionRule instance = new SuppressionRule();
assertFalse(instance.isBase());
instance.setBase(true);
assertTrue(instance.isBase());
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Ignored duplicate tests, left in, as empty tests, so IDE doesn't re-generate them">
@@ -424,33 +435,33 @@ public class SuppressionRuleTest {
instance.setSha1(sha1);
instance.addCwe("287");
instance.process(dependency);
assertTrue(dependency.getVulnerabilities().size() == 1);
assertEquals(1, dependency.getVulnerabilities().size());
dependency.setSha1sum(sha1);
instance.process(dependency);
assertTrue(dependency.getVulnerabilities().isEmpty());
assertTrue(dependency.getSuppressedVulnerabilities().size() == 1);
assertEquals(1, dependency.getSuppressedVulnerabilities().size());
//cvss
dependency.addVulnerability(v);
instance = new SuppressionRule();
instance.addCvssBelow(5f);
instance.process(dependency);
assertTrue(dependency.getVulnerabilities().size() == 1);
assertEquals(1, dependency.getVulnerabilities().size());
instance.addCvssBelow(8f);
instance.process(dependency);
assertTrue(dependency.getVulnerabilities().isEmpty());
assertTrue(dependency.getSuppressedVulnerabilities().size() == 1);
assertEquals(1, dependency.getSuppressedVulnerabilities().size());
//cve
dependency.addVulnerability(v);
instance = new SuppressionRule();
instance.addCve("CVE-2012-1337");
instance.process(dependency);
assertTrue(dependency.getVulnerabilities().size() == 1);
assertEquals(1, dependency.getVulnerabilities().size());
instance.addCve("CVE-2013-1337");
instance.process(dependency);
assertTrue(dependency.getVulnerabilities().isEmpty());
assertTrue(dependency.getSuppressedVulnerabilities().size() == 1);
assertEquals(1, dependency.getSuppressedVulnerabilities().size());
//cpe
instance = new SuppressionRule();
@@ -468,18 +479,21 @@ public class SuppressionRuleTest {
instance.setFilePath(pt);
instance.process(dependency);
assertTrue(dependency.getIdentifiers().isEmpty());
assertTrue(dependency.getSuppressedIdentifiers().size() == 1);
assertEquals(1, dependency.getSuppressedIdentifiers().size());
instance = new SuppressionRule();
dependency.addIdentifier("cpe", "cpe:/a:microsoft:.net_framework:4.0", "some url not needed for this test");
dependency.addIdentifier("cpe", "cpe:/a:microsoft:.net_framework:4.5", "some url not needed for this test");
dependency.addIdentifier("cpe", "cpe:/a:microsoft:.net_framework:5.0", "some url not needed for this test");
pt = new PropertyType();
pt.setValue("cpe:/a:microsoft:.net_framework");
instance.addCpe(pt);
assertTrue(dependency.getIdentifiers().size() == 3);
instance.setBase(true);
assertEquals(3, dependency.getIdentifiers().size());
assertEquals(1, dependency.getSuppressedIdentifiers().size());
instance.process(dependency);
assertTrue(dependency.getIdentifiers().isEmpty());
assertTrue(dependency.getSuppressedIdentifiers().size() == 3);
assertEquals(1, dependency.getSuppressedIdentifiers().size());
}
/**

View File

@@ -134,14 +134,14 @@ public class DependencyVersionTest {
@Test
public void testMatchesAtLeastThreeLevels() {
DependencyVersion instance = new DependencyVersion("1.2.3.4");
DependencyVersion version = new DependencyVersion("1.2.3.5");
DependencyVersion instance = new DependencyVersion("2.3.16.3");
DependencyVersion version = new DependencyVersion("2.3.16.4");
//true tests
assertEquals(true, instance.matchesAtLeastThreeLevels(version));
version = new DependencyVersion("1.2");
version = new DependencyVersion("2.3");
assertEquals(true, instance.matchesAtLeastThreeLevels(version));
//false tests
version = new DependencyVersion("1.2.2.5");
version = new DependencyVersion("2.3.16.1");
assertEquals(false, instance.matchesAtLeastThreeLevels(version));
version = new DependencyVersion("2");
assertEquals(false, instance.matchesAtLeastThreeLevels(version));
@@ -165,6 +165,14 @@ public class DependencyVersionTest {
version = new DependencyVersion("1.2.3.1");
assertEquals(-1, instance.compareTo(version));
instance = new DependencyVersion("1.0.1n");
version = new DependencyVersion("1.0.1m");
assertEquals(1, instance.compareTo(version));
version = new DependencyVersion("1.0.1n");
assertEquals(0, instance.compareTo(version));
version = new DependencyVersion("1.0.1o");
assertEquals(-1, instance.compareTo(version));
DependencyVersion[] dv = new DependencyVersion[7];
dv[0] = new DependencyVersion("2.1.3");
dv[1] = new DependencyVersion("2.1.3.r2");

View File

@@ -54,13 +54,13 @@ public class DependencyVersionUtilTest {
* Test of parseVersion method, of class DependencyVersionUtil.
*/
@Test
public void testParseVersionFromFileName() {
public void testParseVersion() {
final String[] fileName = {"something-0.9.5.jar", "lib2-1.1.jar", "lib1.5r4-someflag-R26.jar",
"lib-1.2.5-dev-20050313.jar", "testlib_V4.4.0.jar", "lib-core-2.0.0-RC1-SNAPSHOT.jar",
"lib-jsp-2.0.1_R114940.jar", "dev-api-2.3.11_R121413.jar", "lib-api-3.7-SNAPSHOT.jar",
"-", "", "1.3-beta", "6"};
"-", "", "1.3-beta", "6", "openssl1.0.1c", "jsf-impl-2.2.8-02.jar"};
final String[] expResult = {"0.9.5", "1.1", "1.5.r4", "1.2.5", "4.4.0", "2.0.0.rc1",
"2.0.1.r114940", "2.3.11.r121413", "3.7", "-", null, "1.3.beta", "6"};
"2.0.1.r114940", "2.3.11.r121413", "3.7", "-", null, "1.3.beta", "6", "1.0.1c", "2.2.8.02"};
for (int i = 0; i < fileName.length; i++) {
final DependencyVersion version = DependencyVersionUtil.parseVersion(fileName[i]);

View File

@@ -47,11 +47,16 @@ cpe.meta.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-di
cve.url.modified.validfordays=7
# the path to the modified nvd cve xml file.
cve.url-1.2.modified=http://nvd.nist.gov/download/nvdcve-modified.xml
cve.url-2.0.modified=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml
cve.startyear=2014
cve.url-2.0.base=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml
cve.url-1.2.base=http://nvd.nist.gov/download/nvdcve-%d.xml
cve.url-1.2.modified=https://nvd.nist.gov/download/nvdcve-Modified.xml.gz
#cve.url-1.2.modified=http://nvd.nist.gov/download/nvdcve-modified.xml
cve.url-2.0.modified=https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-Modified.xml.gz
#cve.url-2.0.modified=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml
cve.url-1.2.base=https://nvd.nist.gov/download/nvdcve-%d.xml.gz
#cve.url-1.2.base=http://nvd.nist.gov/download/nvdcve-%d.xml
cve.url-2.0.base=https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml.gz
#cve.url-2.0.base=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml
# the URL for searching Nexus for SHA-1 hashes and whether it's enabled
analyzer.nexus.enabled=true
@@ -59,3 +64,7 @@ analyzer.nexus.url=https://repository.sonatype.org/service/local/
# If set to true, the proxy will still ONLY be used if the proxy properties (proxy.url, proxy.port)
# are configured
analyzer.nexus.proxy=true
# the URL for searching search.maven.org for SHA-1 and whether it's enabled
analyzer.central.enabled=true
analyzer.central.url=http://search.maven.org/solrsearch/select

View File

@@ -10,7 +10,7 @@
<filePath>c:\path\to\some.jar</filePath>
<cpe>cpe:/a:csv:csv:1.0</cpe>
</suppress>
<suppress>
<suppress base="true">
<notes><![CDATA[
This suppresses any jboss:jboss cpe for any test.jar in any directory.
]]></notes>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.2.4</version>
<version>1.2.6</version>
</parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-jenkins</artifactId>

View File

@@ -22,7 +22,7 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.2.4</version>
<version>1.2.6</version>
</parent>
<artifactId>dependency-check-maven</artifactId>

View File

@@ -0,0 +1,462 @@
/*
* This file is part of dependency-check-maven.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.maven;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.reporting.MavenReport;
import org.apache.maven.reporting.MavenReportException;
/**
* <p>
* This is an abstract reporting mojo that enables report aggregation. Some of the code in the this class was copied
* from the CoberturaReportMojo (http://mojo.codehaus.org/cobertura-maven-plugin/, version 2.6). The authors of the
* CoberturaReportMojo were <a href="will.gwaltney@sas.com">Will Gwaltney</a> and
* <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>. There working example of how to do report aggregation was
* invaluable.</p>
* <p>
* An important point about using this abstract class is that it is intended for one to write some form of serialized
* data (via the {@link org.owasp.dependencycheck.maven.ReportAggregationMojo#writeDataFile() }; note that the
* <code>writeDataFile()</code> function is called automatically after either {@link org.owasp.dependencycheck.maven.ReportAggregationMojo#executeNonAggregateReport(org.apache.maven.doxia.sink.Sink,
* org.apache.maven.doxia.sink.SinkFactory, java.util.Locale)
* } or {@link org.owasp.dependencycheck.maven.ReportAggregationMojo#executeAggregateReport(org.apache.maven.doxia.sink.Sink,
* org.apache.maven.doxia.sink.SinkFactory, java.util.Locale)
* } are called. When <code>executeAggregateReport()</code> is implemented, one can call {@link org.owasp.dependencycheck.maven.ReportAggregationMojo#getChildDataFiles()
* } to obtain a list of the data files to aggregate.</p>
*
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public abstract class ReportAggregationMojo extends AbstractMojo implements MavenReport {
/**
* The Maven Project Object.
*/
@Component
private MavenProject project;
/**
* Logger field reference.
*/
private static final Logger LOGGER = Logger.getLogger(ReportAggregationMojo.class.getName());
/**
* List of Maven project of the current build
*/
@Parameter(readonly = true, required = true, property = "reactorProjects")
private List<MavenProject> reactorProjects;
/**
* Generate aggregate reports in multi-module projects.
*/
@Parameter(property = "aggregate", defaultValue = "false")
private boolean aggregate;
/**
* Sets whether or not the external report format should be used.
*/
@Parameter(property = "metaFileName", defaultValue = "dependency-check.ser", required = true)
private String dataFileName;
/**
* Specifies the destination directory for the generated Dependency-Check report. This generally maps to
* "target/site".
*/
@Parameter(property = "reportOutputDirectory", defaultValue = "${project.reporting.outputDirectory}", required = true)
private File reportOutputDirectory;
/**
* Sets the Reporting output directory.
*
* @param directory the output directory
*/
@Override
public void setReportOutputDirectory(File directory) {
reportOutputDirectory = directory;
}
/**
* Returns the output directory.
*
* @return the output directory
*/
@Override
public File getReportOutputDirectory() {
return reportOutputDirectory;
}
/**
* Returns the output directory for the given project.
*
* @param project the Maven project to get the output directory for
* @return the output directory for the given project
*/
public File getReportOutputDirectory(MavenProject project) {
final Object o = project.getContextValue(getOutputDirectoryContextKey());
if (o != null && o instanceof File) {
return (File) o;
}
return null;
}
/**
* Returns whether this is an external report. This method always returns true.
*
* @return <code>true</code>
*/
@Override
public final boolean isExternalReport() {
return true;
}
/**
* The collection of child projects.
*/
private final Map<MavenProject, Set<MavenProject>> projectChildren = new HashMap<MavenProject, Set<MavenProject>>();
/**
* Called before execute; allows for any setup that is needed. If this is overridden you must call
* </code>super.preExecute()</code>.
*
* @throws MojoExecutionException thrown if there is an issue executing the mojo
* @throws MojoFailureException thrown if there is an issue executing the mojo
*/
protected void preExecute() throws MojoExecutionException, MojoFailureException {
buildAggregateInfo();
}
/**
* Called when the mojo is being executed.
*
* @throws MojoExecutionException thrown if there is an issue executing the mojo
* @throws MojoFailureException thrown if there is an issue executing the mojo
*/
protected abstract void performExecute() throws MojoExecutionException, MojoFailureException;
/**
* Runs after the mojo has executed. This implementation will call <code>writeDataFile()</code>. As such, it is
* important that if this method is overriden that <code>super.postExecute()</code> is called.
*
* @throws MojoExecutionException thrown if there is an issue executing the mojo
* @throws MojoFailureException thrown if there is an issue executing the mojo
*/
protected void postExecute() throws MojoExecutionException, MojoFailureException {
final File written = writeDataFile();
if (written != null) {
project.setContextValue(getDataFileContextKey(), written.getAbsolutePath());
}
}
/**
* Returns the key used to store the path to the data file that is saved by <code>writeDataFile()</code>. This key
* is used in the <code>MavenProject.(set|get)ContextValue</code>.
*
* @return the key used to store the path to the data file
*/
protected String getDataFileContextKey() {
return "dependency-check-path-" + this.getDataFileName();
}
/**
* Returns the key used to store the path to the output directory. When generating the report in the
* <code>executeAggregateReport()</code> the output directory should be obtained by using this key.
*
* @return the key used to store the path to the output directory
*/
protected String getOutputDirectoryContextKey() {
return "dependency-output-dir-" + this.getDataFileName();
}
/**
* Is called by Maven to execute the mojo.
*
* @throws MojoExecutionException thrown if there is an issue executing the mojo
* @throws MojoFailureException thrown if there is an issue executing the mojo
*/
public final void execute() throws MojoExecutionException, MojoFailureException {
try {
preExecute();
performExecute();
} finally {
postExecute();
}
}
/**
* Runs prior to the site report generation.
*
* @throws MavenReportException if a maven report exception occurs
*/
protected void preGenerate() throws MavenReportException {
buildAggregateInfo();
project.setContextValue(getOutputDirectoryContextKey(), getReportOutputDirectory());
}
/**
* Executes after the site report has been generated.
*
* @throws MavenReportException if a maven report exception occurs
*/
protected void postGenerate() throws MavenReportException {
final File written = writeDataFile();
if (written != null) {
project.setContextValue(getDataFileContextKey(), written.getAbsolutePath());
}
}
/**
* Generates the non aggregate report.
*
* @param locale the locale to use when generating the report
* @throws MavenReportException if a maven report exception occurs
*/
protected abstract void executeNonAggregateReport(Locale locale) throws MavenReportException;
/**
* Generates the aggregate Site Report.
*
* @param project the maven project used to generate the aggregate report
* @param locale the locale to use when generating the report
* @throws MavenReportException if a maven report exception occurs
*/
protected abstract void executeAggregateReport(MavenProject project, Locale locale) throws MavenReportException;
/**
* Generates the Dependency-Check Site Report.
*
* @param sink the sink to write the report to
* @param locale the locale to use when generating the report
* @throws MavenReportException if a maven report exception occurs
* @deprecated use {@link #generate(org.apache.maven.doxia.sink.Sink, java.util.Locale) instead.
*/
@Deprecated
public final void generate(@SuppressWarnings("deprecation") org.codehaus.doxia.sink.Sink sink, Locale locale) throws MavenReportException {
generate((Sink) sink, locale);
}
/**
* Generates the Dependency-Check Site Report.
*
* @param sink the sink to write the report to
* @param locale the locale to use when generating the report
* @throws MavenReportException if a maven report exception occurs
*/
public final void generate(Sink sink, Locale locale) throws MavenReportException {
try {
preGenerate();
if (canGenerateNonAggregateReport()) {
executeNonAggregateReport(locale);
}
if (canGenerateAggregateReport()) {
for (MavenProject proj : reactorProjects) {
if (!isMultiModule(proj)) {
continue;
}
executeAggregateReport(proj, locale);
}
}
} finally {
postGenerate();
}
}
/**
* Returns whether or not the mojo can generate a non-aggregate report for this project.
*
* @return <code>true</code> if a non-aggregate report can be generated, otherwise <code>false</code>
*/
protected abstract boolean canGenerateNonAggregateReport();
/**
* Returns whether or not we can generate any aggregate reports at this time.
*
* @return <code>true</code> if an aggregate report can be generated, otherwise <code>false</code>
*/
protected abstract boolean canGenerateAggregateReport();
/**
* Returns the name of the data file that contains the serialized data.
*
* @return the name of the data file that contains the serialized data
*/
protected String getDataFileName() {
return dataFileName;
}
/**
* Writes the data file to disk in the target directory.
*
* @return the File object referencing the data file that was written
*/
protected abstract File writeDataFile();
/**
* Collects the information needed for building aggregate reports.
*/
private void buildAggregateInfo() {
// build parent-child map
for (MavenProject proj : reactorProjects) {
Set<MavenProject> depList = projectChildren.get(proj.getParent());
if (depList == null) {
depList = new HashSet<MavenProject>();
projectChildren.put(proj.getParent(), depList);
}
depList.add(proj);
}
}
/**
* Returns a list containing all the recursive, non-pom children of the given project, never <code>null</code>.
*
* @return a list of child projects
*/
protected List<MavenProject> getAllChildren() {
return getAllChildren(project);
}
/**
* Returns a list containing all the recursive, non-pom children of the given project, never <code>null</code>.
*
* @param parentProject the parent project to collect the child project references
* @return a list of child projects
*/
protected List<MavenProject> getAllChildren(MavenProject parentProject) {
final Set<MavenProject> children = projectChildren.get(parentProject);
if (children == null) {
return Collections.emptyList();
}
final List<MavenProject> result = new ArrayList<MavenProject>();
for (MavenProject child : children) {
if (isMultiModule(child)) {
result.addAll(getAllChildren(child));
} else {
result.add(child);
}
}
return result;
}
/**
* Returns a list of data files that were produced by the direct children of the given MavenProject.
*
* @param project the Maven project to obtain the child data files from
* @return a list of the data files
*/
protected List<File> getAllChildDataFiles(MavenProject project) {
final List<MavenProject> children = getAllChildren(project);
return getDataFiles(children);
}
/**
* Returns any existing output files from the given list of projects.
*
* @param projects the list of projects to obtain the output files from
* @return a list of output files
*/
protected List<File> getDataFiles(List<MavenProject> projects) {
final List<File> files = new ArrayList<File>();
for (MavenProject proj : projects) {
final Object path = project.getContextValue(getDataFileContextKey());
if (path == null) {
final String msg = String.format("Unable to aggregate data for '%s' - aggregate data file was not generated",
proj.getName());
LOGGER.warning(msg);
} else {
final File outputFile = new File((String) path);
if (outputFile.exists()) {
files.add(outputFile);
} else {
if (!isMultiModule(project)) {
final String msg = String.format("Unable to aggregate data for '%s' - missing data file '%s'",
proj.getName(), outputFile.getPath());
LOGGER.warning(msg);
}
}
}
}
return files;
}
/**
* Test if the project has pom packaging
*
* @param mavenProject Project to test
* @return <code>true</code> if it has a pom packaging; otherwise <code>false</code>
*/
protected boolean isMultiModule(MavenProject mavenProject) {
return "pom".equals(mavenProject.getPackaging());
}
/**
* Test if the current project has pom packaging
*
* @return <code>true</code> if it has a pom packaging; otherwise <code>false</code>
*/
protected boolean isMultiModule() {
return isMultiModule(project);
}
/**
* Check whether the current project is the last project in a multi-module build. If the maven build is not a
* multi-module project then this will always return true.
*
* @return <code>true</code> if the current project is the last project in a multi-module build; otherwise
* <code>false</code>
*/
protected boolean isLastProject() {
return project.equals(reactorProjects.get(reactorProjects.size() - 1));
}
/**
* Returns whether or not the mojo is configured to perform report aggregation.
*
* @return <code>true</code> if report aggregation is enabled; otherwise <code>false</code>
*/
public boolean isAggregate() {
return aggregate;
}
/**
* Returns a reference to the current project. This method is used instead of auto-binding the project via component
* annotation in concrete implementations of this. If the child has a <code>@Component MavenProject project;</code>
* defined then the abstract class (i.e. this class) will not have access to the current project (just the way Maven
* works with the binding).
*
* @return returns a reference to the current project
*/
protected MavenProject getProject() {
return project;
}
}

View File

@@ -0,0 +1,456 @@
/*
* This file is part of dependency-check-maven.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.maven;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.maven.doxia.sink.Sink;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Evidence;
import org.owasp.dependencycheck.dependency.Identifier;
import org.owasp.dependencycheck.dependency.Reference;
import org.owasp.dependencycheck.dependency.Vulnerability;
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
import org.owasp.dependencycheck.reporting.ReportGenerator;
/**
* A utility class that encapsulates the report generation for dependency-check-maven.
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
final class ReportingUtil {
/**
* Logger field reference.
*/
private static final Logger LOGGER = Logger.getLogger(ReportingUtil.class.getName());
/**
* Empty private constructor for this utility class.
*/
private ReportingUtil() {
}
/**
* Generates the reports for a given dependency-check engine.
*
* @param engine a dependency-check engine
* @param outDirectory the directory to write the reports to
* @param projectName the name of the project that a report is being generated for
* @param format the format of the report to generate
*/
static void generateExternalReports(Engine engine, File outDirectory, String projectName, String format) {
DatabaseProperties prop = null;
CveDB cve = null;
try {
cve = new CveDB();
cve.open();
prop = cve.getDatabaseProperties();
} catch (DatabaseException ex) {
LOGGER.log(Level.FINE, "Unable to retrieve DB Properties", ex);
} finally {
if (cve != null) {
cve.close();
}
}
final ReportGenerator r = new ReportGenerator(projectName, engine.getDependencies(), engine.getAnalyzers(), prop);
try {
r.generateReports(outDirectory.getCanonicalPath(), format);
} catch (IOException ex) {
LOGGER.log(Level.SEVERE,
"Unexpected exception occurred during analysis; please see the verbose error log for more details.");
LOGGER.log(Level.FINE, null, ex);
} catch (Throwable ex) {
LOGGER.log(Level.SEVERE,
"Unexpected exception occurred during analysis; please see the verbose error log for more details.");
LOGGER.log(Level.FINE, null, ex);
}
}
/**
* Generates a dependency-check report using the Maven Site format.
*
* @param engine the engine used to scan the dependencies
* @param sink the sink to write the data to
* @param projectName the name of the project
*/
static void generateMavenSiteReport(final Engine engine, Sink sink, String projectName) {
final List<Dependency> dependencies = engine.getDependencies();
writeSiteReportHeader(sink, projectName);
writeSiteReportTOC(sink, dependencies);
int cnt = 0;
for (Dependency d : dependencies) {
writeSiteReportDependencyHeader(sink, d);
cnt = writeSiteReportDependencyEvidenceUsed(d, cnt, sink);
cnt = writeSiteReportDependencyRelatedDependencies(d, cnt, sink);
writeSiteReportDependencyIdentifiers(d, sink);
writeSiteReportDependencyVulnerabilities(d, sink, cnt);
}
sink.body_();
}
// <editor-fold defaultstate="collapsed" desc="various writeXXXXX methods to generate the Site Report">
/**
* Writes the vulnerabilities to the site report.
*
* @param d the dependency
* @param sink the sink to write the data to
* @param collapsibleHeaderCount the collapsible header count
*/
private static void writeSiteReportDependencyVulnerabilities(Dependency d, Sink sink, int collapsibleHeaderCount) {
int cnt = collapsibleHeaderCount;
if (d.getVulnerabilities() != null && !d.getVulnerabilities().isEmpty()) {
for (Vulnerability v : d.getVulnerabilities()) {
sink.paragraph();
sink.bold();
try {
sink.link("http://web.nvd.nist.gov/view/vuln/detail?vulnId=" + URLEncoder.encode(v.getName(), "US-ASCII"));
sink.text(v.getName());
sink.link_();
sink.bold_();
} catch (UnsupportedEncodingException ex) {
sink.text(v.getName());
sink.bold_();
sink.lineBreak();
sink.text("http://web.nvd.nist.gov/view/vuln/detail?vulnId=" + v.getName());
}
sink.paragraph_();
sink.paragraph();
sink.text("Severity: ");
if (v.getCvssScore() < 4.0) {
sink.text("Low");
} else {
if (v.getCvssScore() >= 7.0) {
sink.text("High");
} else {
sink.text("Medium");
}
}
sink.lineBreak();
sink.text("CVSS Score: " + v.getCvssScore());
if (v.getCwe() != null && !v.getCwe().isEmpty()) {
sink.lineBreak();
sink.text("CWE: ");
sink.text(v.getCwe());
}
sink.paragraph_();
sink.paragraph();
sink.text(v.getDescription());
if (v.getReferences() != null && !v.getReferences().isEmpty()) {
sink.list();
for (Reference ref : v.getReferences()) {
sink.listItem();
sink.text(ref.getSource());
sink.text(" - ");
sink.link(ref.getUrl());
sink.text(ref.getName());
sink.link_();
sink.listItem_();
}
sink.list_();
}
sink.paragraph_();
if (v.getVulnerableSoftware() != null && !v.getVulnerableSoftware().isEmpty()) {
sink.paragraph();
cnt += 1;
sink.rawText("Vulnerable Software <a href=\"javascript:toggleElement(this, 'vulnSoft" + cnt + "')\">[-]</a>");
sink.rawText("<div id=\"vulnSoft" + cnt + "\" style=\"display:block\">");
sink.list();
for (VulnerableSoftware vs : v.getVulnerableSoftware()) {
sink.listItem();
try {
sink.link("http://web.nvd.nist.gov/view/vuln/search-results?cpe=" + URLEncoder.encode(vs.getName(), "US-ASCII"));
sink.text(vs.getName());
sink.link_();
if (vs.hasPreviousVersion()) {
sink.text(" and all previous versions.");
}
} catch (UnsupportedEncodingException ex) {
sink.text(vs.getName());
if (vs.hasPreviousVersion()) {
sink.text(" and all previous versions.");
}
sink.text(" (http://web.nvd.nist.gov/view/vuln/search-results?cpe=" + vs.getName() + ")");
}
sink.listItem_();
}
sink.list_();
sink.rawText("</div>");
sink.paragraph_();
}
}
}
}
/**
* Writes the identifiers to the site report.
*
* @param d the dependency
* @param sink the sink to write the data to
*/
private static void writeSiteReportDependencyIdentifiers(Dependency d, Sink sink) {
if (d.getIdentifiers() != null && !d.getIdentifiers().isEmpty()) {
sink.sectionTitle4();
sink.text("Identifiers");
sink.sectionTitle4_();
sink.list();
for (Identifier i : d.getIdentifiers()) {
sink.listItem();
sink.text(i.getType());
sink.text(": ");
if (i.getUrl() != null && i.getUrl().length() > 0) {
sink.link(i.getUrl());
sink.text(i.getValue());
sink.link_();
} else {
sink.text(i.getValue());
}
if (i.getDescription() != null && i.getDescription().length() > 0) {
sink.lineBreak();
sink.text(i.getDescription());
}
sink.listItem_();
}
sink.list_();
}
}
/**
* Writes the related dependencies to the site report.
*
* @param d the dependency
* @param sink the sink to write the data to
* @param collapsibleHeaderCount the collapsible header count
* @return the collapsible header count
*/
private static int writeSiteReportDependencyRelatedDependencies(Dependency d, int collapsibleHeaderCount, Sink sink) {
int cnt = collapsibleHeaderCount;
if (d.getRelatedDependencies() != null && !d.getRelatedDependencies().isEmpty()) {
cnt += 1;
sink.sectionTitle4();
sink.rawText("Related Dependencies <a href=\"javascript:toggleElement(this, 'related" + cnt + "')\">[+]</a>");
sink.sectionTitle4_();
sink.rawText("<div id=\"related" + cnt + "\" style=\"display:none\">");
sink.list();
for (Dependency r : d.getRelatedDependencies()) {
sink.listItem();
sink.text(r.getFileName());
sink.list();
writeListItem(sink, "File Path: " + r.getFilePath());
writeListItem(sink, "SHA1: " + r.getSha1sum());
writeListItem(sink, "MD5: " + r.getMd5sum());
sink.list_();
sink.listItem_();
}
sink.list_();
sink.rawText("</div>");
}
return cnt;
}
/**
* Writes the evidence used to the site report.
*
* @param d the dependency
* @param sink the sink to write the data to
* @param collapsibleHeaderCount the collapsible header count
* @return the collapsible header count
*/
private static int writeSiteReportDependencyEvidenceUsed(Dependency d, int collapsibleHeaderCount, Sink sink) {
int cnt = collapsibleHeaderCount;
final Set<Evidence> evidence = d.getEvidenceForDisplay();
if (evidence != null && evidence.size() > 0) {
cnt += 1;
sink.sectionTitle4();
sink.rawText("Evidence Collected <a href=\"javascript:toggleElement(this, 'evidence" + cnt + "')\">[+]</a>");
sink.sectionTitle4_();
sink.rawText("<div id=\"evidence" + cnt + "\" style=\"display:none\">");
sink.table();
sink.tableRow();
writeTableHeaderCell(sink, "Source");
writeTableHeaderCell(sink, "Name");
writeTableHeaderCell(sink, "Value");
sink.tableRow_();
for (Evidence e : evidence) {
sink.tableRow();
writeTableCell(sink, e.getSource());
writeTableCell(sink, e.getName());
writeTableCell(sink, e.getValue());
sink.tableRow_();
}
sink.table_();
sink.rawText("</div>");
}
return cnt;
}
/**
* Writes the dependency header to the site report.
*
* @param d the dependency
* @param sink the sink to write the data to
*/
private static void writeSiteReportDependencyHeader(Sink sink, Dependency d) {
sink.sectionTitle2();
sink.anchor("sha1" + d.getSha1sum());
sink.text(d.getFileName());
sink.anchor_();
sink.sectionTitle2_();
if (d.getDescription() != null && d.getDescription().length() > 0) {
sink.paragraph();
sink.bold();
sink.text("Description: ");
sink.bold_();
sink.text(d.getDescription());
sink.paragraph_();
}
if (d.getLicense() != null && d.getLicense().length() > 0) {
sink.paragraph();
sink.bold();
sink.text("License: ");
sink.bold_();
if (d.getLicense().startsWith("http://") && !d.getLicense().contains(" ")) {
sink.link(d.getLicense());
sink.text(d.getLicense());
sink.link_();
} else {
sink.text(d.getLicense());
}
sink.paragraph_();
}
}
/**
* Adds a list item to the site report.
*
* @param sink the sink to write the data to
* @param text the text to write
*/
private static void writeListItem(Sink sink, String text) {
sink.listItem();
sink.text(text);
sink.listItem_();
}
/**
* Adds a table cell to the site report.
*
* @param sink the sink to write the data to
* @param text the text to write
*/
private static void writeTableCell(Sink sink, String text) {
sink.tableCell();
sink.text(text);
sink.tableCell_();
}
/**
* Adds a table header cell to the site report.
*
* @param sink the sink to write the data to
* @param text the text to write
*/
private static void writeTableHeaderCell(Sink sink, String text) {
sink.tableHeaderCell();
sink.text(text);
sink.tableHeaderCell_();
}
/**
* Writes the TOC for the site report.
*
* @param sink the sink to write the data to
* @param dependencies the dependencies that are being reported on
*/
private static void writeSiteReportTOC(Sink sink, final List<Dependency> dependencies) {
sink.list();
for (Dependency d : dependencies) {
sink.listItem();
sink.link("#sha1" + d.getSha1sum());
sink.text(d.getFileName());
sink.link_();
if (!d.getVulnerabilities().isEmpty()) {
sink.rawText(" <font style=\"color:red\">•</font>");
}
if (!d.getRelatedDependencies().isEmpty()) {
sink.list();
for (Dependency r : d.getRelatedDependencies()) {
writeListItem(sink, r.getFileName());
}
sink.list_();
}
sink.listItem_();
}
sink.list_();
}
/**
* Writes the site report header.
*
* @param sink the sink to write the data to
* @param projectName the name of the project
*/
private static void writeSiteReportHeader(Sink sink, String projectName) {
sink.head();
sink.title();
sink.text("Dependency-Check Report: " + projectName);
sink.title_();
sink.head_();
sink.body();
sink.rawText("<script type=\"text/javascript\">");
sink.rawText("function toggleElement(el, targetId) {");
sink.rawText("if (el.innerText == '[+]') {");
sink.rawText(" el.innerText = '[-]';");
sink.rawText(" document.getElementById(targetId).style.display='block';");
sink.rawText("} else {");
sink.rawText(" el.innerText = '[+]';");
sink.rawText(" document.getElementById(targetId).style.display='none';");
sink.rawText("}");
sink.rawText("}");
sink.rawText("</script>");
sink.section1();
sink.sectionTitle1();
sink.text("Project: " + projectName);
sink.sectionTitle1_();
sink.date();
final Date now = new Date();
sink.text(DateFormat.getDateTimeInstance().format(now));
sink.date_();
sink.section1_();
}
// </editor-fold>
}

View File

@@ -4,8 +4,8 @@ The following properties can be set on the dependency-check-maven plugin.
Property | Description | Default Value
---------------------|------------------------------------|------------------
aggregate | Sets whether report aggregation will be performed for multi-module site reports. This option only affects the report generation when configured within the reporting section. | false
autoUpdate | Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. | true
externalReport | When using as a Site plugin this parameter sets whether or not the external report format should be used. | false
outputDirectory | The location to write the report(s). Note, this is not used if generating the report as part of a `mvn site` build | 'target'
failBuildOnCVSS | Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which means since the CVSS scores are 0-10, by default the build will never fail. | 11
format | The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the Site plugin unless the externalReport is set to true. | HTML
@@ -23,38 +23,44 @@ Note, that specific analyzers will automatically disable themselves if no file
types that they support are detected - so specifically disabling them may not
be needed.
Property | Description | Default Value
------------------------|------------------------------------|------------------
archiveAnalyzerEnabled | Sets whether the Archive Analyzer will be used. | true
Property | Description | Default Value
------------------------|---------------------------------------------------------------------------|------------------
archiveAnalyzerEnabled | Sets whether the Archive Analyzer will be used. | true
zipExtensions | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. | &nbsp;
jarAnalyzer | Sets whether Jar Analyzer will be used. | true
nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used. | true
nexusUrl | Defines the Nexus URL. | https://repository.sonatype.org/service/local/
jarAnalyzer | Sets whether Jar Analyzer will be used. | true
nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used. | true
nexusUrl | Defines the Nexus Pro Server URL. If not set the Nexus Analyzer will be disabled. | &nbsp;
nexusUsesProxy | Whether or not the defined proxy should be used when connecting to Nexus. | true
nuspecAnalyzerEnabled | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | true
assemblyAnalyzerEnabled | Sets whether or not the .NET Assembly Analyzer should be used. | true
pathToMono | The path to Mono for .NET assembly analysis on non-windows systems | &nbsp;
nuspecAnalyzerEnabled | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | true
assemblyAnalyzerEnabled | Sets whether or not the .NET Assembly Analyzer should be used. | true
pathToMono | The path to Mono for .NET assembly analysis on non-windows systems. | &nbsp;
Advanced Configuration
====================
The following properties can be configured in the plugin. However, they are less frequently changed. One exception
may be the cvedUrl properties, which can be used to host a mirror of the NVD within an enterprise environment.
Property | Description | Default Value
---------------------|-------------------------------------------------------------------------|------------------
cveUrl12Modified | URL for the modified CVE 1.2 | http://nvd.nist.gov/download/nvdcve-modified.xml
cveUrl20Modified | URL for the modified CVE 2.0 | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml
cveUrl12Base | Base URL for each year's CVE 1.2, the %d will be replaced with the year | http://nvd.nist.gov/download/nvdcve-%d.xml
cveUrl20Base | Base URL for each year's CVE 2.0, the %d will be replaced with the year | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml
connectionTimeout | The URL Connection Timeout. | &nbsp;
dataDirectory | Data directory to hold SQL CVEs contents. This should generally not be changed. | &nbsp;
Property | Description | Default Value
---------------------|--------------------------------------------------------------------------|------------------
cveUrl12Modified | URL for the modified CVE 1.2. | http://nvd.nist.gov/download/nvdcve-modified.xml
cveUrl20Modified | URL for the modified CVE 2.0. | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml
cveUrl12Base | Base URL for each year's CVE 1.2, the %d will be replaced with the year. | http://nvd.nist.gov/download/nvdcve-%d.xml
cveUrl20Base | Base URL for each year's CVE 2.0, the %d will be replaced with the year. | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml
connectionTimeout | Sets the URL Connection Timeout used when downloading external data. | &nbsp;
dataDirectory | Sets the data directory to hold SQL CVEs contents. This should generally not be changed. | &nbsp;
databaseDriverName | The name of the database driver. Example: org.h2.Driver. | &nbsp;
databaseDriverPath | The path to the database driver JAR file; only used if the driver is not in the class path. | &nbsp;
connectionString | The connection string used to connect to the database. | &nbsp;
databaseUser | The username used when connecting to the database. | &nbsp;
databasePassword | The password used when connecting to the database. | &nbsp;
metaFileName | Sets the name of the file to use for storing the metadata about the project. | dependency-check.ser
Proxy Configuration
====================
Use [Maven's settings](https://maven.apache.org/settings.html#Proxies) to configure a proxy server.
Use [Maven's settings](https://maven.apache.org/settings.html#Proxies) to configure a proxy server. If multiple proxies
are configured in the Maven settings file you must tell dependency-check which proxy to use with the following property:
Property | Description | Default Value
---------------------|--------------------------------------------------------------------------------------|------------------
mavenSettingsProxyId | The id for the proxy, configured via settings.xml, that dependency-check should use. | &nbsp;

View File

@@ -17,7 +17,9 @@ Create the DependencyCheck-report.html in the target directory
```xml
<project>
...
<build>
...
<plugins>
...
<plugin>
@@ -41,11 +43,48 @@ Create the DependencyCheck-report.html in the target directory
```
$H$H$H Example 2:
Create an aggregated dependency-check report within the site
```xml
<project>
...
<reporting>
...
<plugins>
...
<plugin>
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>${project.version}</version>
<configuration>
<aggregate>true</aggregate>
</configuration>
<reportSets>
<reportSet>
<reports>
<report>check</report>
</reports>
</reportSet>
</reportSets>
</plugin>
</plugin>
...
</plugins>
...
</reporting>
...
</project>
```
$H$H$H Example 3:
Create the DependencyCheck-report.html and fail the build for CVSS greater then 8
```xml
<project>
...
<build>
...
<plugins>
...
<plugin>
@@ -71,44 +110,14 @@ Create the DependencyCheck-report.html and fail the build for CVSS greater then
</project>
```
$H$H$H Example 3:
Create the dependency-check report within the site
```xml
<project>
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<configuration>
<reportPlugins>
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>${project.version}</version>
<configuration>
<externalReport>false</externalReport>
</configuration>
</plugin>
</reportPlugins>
</configuration>
</plugin>
...
</plugins>
...
</build>
...
</project>
```
$H$H$H Example 4:
Create the DependencyCheck-report.html and skip artifacts no bundled in distribution (Provided and Runtime scope)
Create the DependencyCheck-report.html and skip artifacts not bundled in distribution (Provided and Runtime scope)
```xml
<project>
...
<build>
...
<plugins>
...
<plugin>
@@ -140,7 +149,9 @@ Create the DependencyCheck-report.html and use internal mirroring of CVE content
```xml
<project>
...
<build>
...
<plugins>
...
<plugin>

View File

@@ -21,7 +21,7 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.2.4</version>
<version>1.2.6</version>
</parent>
<artifactId>dependency-check-utils</artifactId>
@@ -249,6 +249,9 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved.
<targetJdk>1.6</targetJdk>
<linkXref>true</linkXref>
<sourceEncoding>utf-8</sourceEncoding>
<excludes>
<exclude>**/org/owasp/dependencycheck/org/apache/**/*.java</exclude>
</excludes>
<rulesets>
<ruleset>../src/main/config/dcrules.xml</ruleset>
<ruleset>/rulesets/java/basic.xml</ruleset>
@@ -261,6 +264,9 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved.
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<onlyAnalyze>org.owasp.dependencycheck.utils.*</onlyAnalyze>
</configuration>
</plugin>
</reportPlugins>
</configuration>

View File

@@ -0,0 +1,153 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant;
/**
* Signals an error condition during a build
*/
public class BuildException extends RuntimeException {
private static final long serialVersionUID = -5419014565354664240L;
/** Location in the build file where the exception occurred */
private Location location = Location.UNKNOWN_LOCATION;
/**
* Constructs a build exception with no descriptive information.
*/
public BuildException() {
super();
}
/**
* Constructs an exception with the given descriptive message.
*
* @param message A description of or information about the exception.
* Should not be <code>null</code>.
*/
public BuildException(String message) {
super(message);
}
/**
* Constructs an exception with the given message and exception as
* a root cause.
*
* @param message A description of or information about the exception.
* Should not be <code>null</code> unless a cause is specified.
* @param cause The exception that might have caused this one.
* May be <code>null</code>.
*/
public BuildException(String message, Throwable cause) {
super(message, cause);
}
/**
* Constructs an exception with the given message and exception as
* a root cause and a location in a file.
*
* @param msg A description of or information about the exception.
* Should not be <code>null</code> unless a cause is specified.
* @param cause The exception that might have caused this one.
* May be <code>null</code>.
* @param location The location in the project file where the error
* occurred. Must not be <code>null</code>.
*/
public BuildException(String msg, Throwable cause, Location location) {
this(msg, cause);
this.location = location;
}
/**
* Constructs an exception with the given exception as a root cause.
*
* @param cause The exception that might have caused this one.
* Should not be <code>null</code>.
*/
public BuildException(Throwable cause) {
super(cause);
}
/**
* Constructs an exception with the given descriptive message and a
* location in a file.
*
* @param message A description of or information about the exception.
* Should not be <code>null</code>.
* @param location The location in the project file where the error
* occurred. Must not be <code>null</code>.
*/
public BuildException(String message, Location location) {
super(message);
this.location = location;
}
/**
* Constructs an exception with the given exception as
* a root cause and a location in a file.
*
* @param cause The exception that might have caused this one.
* Should not be <code>null</code>.
* @param location The location in the project file where the error
* occurred. Must not be <code>null</code>.
*/
public BuildException(Throwable cause, Location location) {
this(cause);
this.location = location;
}
/**
* Returns the nested exception, if any.
*
* @return the nested exception, or <code>null</code> if no
* exception is associated with this one
* @deprecated Use {@link #getCause} instead.
*/
public Throwable getException() {
return getCause();
}
/**
* Returns the location of the error and the error message.
*
* @return the location of the error and the error message
*/
public String toString() {
return location.toString() + getMessage();
}
/**
* Sets the file location where the error occurred.
*
* @param location The file location where the error occurred.
* Must not be <code>null</code>.
*/
public void setLocation(Location location) {
this.location = location;
}
/**
* Returns the file location where the error occurred.
*
* @return the file location where the error occurred.
*/
public Location getLocation() {
return location;
}
}

View File

@@ -0,0 +1,158 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant;
import java.io.File;
/**
* An interface used to describe the actions required of any type of
* directory scanner.
*
*/
public interface FileScanner {
/**
* Adds default exclusions to the current exclusions set.
*/
void addDefaultExcludes();
/**
* Returns the base directory to be scanned.
* This is the directory which is scanned recursively.
*
* @return the base directory to be scanned
*/
File getBasedir();
/**
* Returns the names of the directories which matched at least one of the
* include patterns and at least one of the exclude patterns.
* The names are relative to the base directory.
*
* @return the names of the directories which matched at least one of the
* include patterns and at least one of the exclude patterns.
*/
String[] getExcludedDirectories();
/**
* Returns the names of the files which matched at least one of the
* include patterns and at least one of the exclude patterns.
* The names are relative to the base directory.
*
* @return the names of the files which matched at least one of the
* include patterns and at least one of the exclude patterns.
*
*/
String[] getExcludedFiles();
/**
* Returns the names of the directories which matched at least one of the
* include patterns and none of the exclude patterns.
* The names are relative to the base directory.
*
* @return the names of the directories which matched at least one of the
* include patterns and none of the exclude patterns.
*/
String[] getIncludedDirectories();
/**
* Returns the names of the files which matched at least one of the
* include patterns and none of the exclude patterns.
* The names are relative to the base directory.
*
* @return the names of the files which matched at least one of the
* include patterns and none of the exclude patterns.
*/
String[] getIncludedFiles();
/**
* Returns the names of the directories which matched none of the include
* patterns. The names are relative to the base directory.
*
* @return the names of the directories which matched none of the include
* patterns.
*/
String[] getNotIncludedDirectories();
/**
* Returns the names of the files which matched none of the include
* patterns. The names are relative to the base directory.
*
* @return the names of the files which matched none of the include
* patterns.
*/
String[] getNotIncludedFiles();
/**
* Scans the base directory for files which match at least one include
* pattern and don't match any exclude patterns.
*
* @exception IllegalStateException if the base directory was set
* incorrectly (i.e. if it is <code>null</code>, doesn't exist,
* or isn't a directory).
*/
void scan() throws IllegalStateException;
/**
* Sets the base directory to be scanned. This is the directory which is
* scanned recursively. All '/' and '\' characters should be replaced by
* <code>File.separatorChar</code>, so the separator used need not match
* <code>File.separatorChar</code>.
*
* @param basedir The base directory to scan.
* Must not be <code>null</code>.
*/
void setBasedir(String basedir);
/**
* Sets the base directory to be scanned. This is the directory which is
* scanned recursively.
*
* @param basedir The base directory for scanning.
* Should not be <code>null</code>.
*/
void setBasedir(File basedir);
/**
* Sets the list of exclude patterns to use.
*
* @param excludes A list of exclude patterns.
* May be <code>null</code>, indicating that no files
* should be excluded. If a non-<code>null</code> list is
* given, all elements must be non-<code>null</code>.
*/
void setExcludes(String[] excludes);
/**
* Sets the list of include patterns to use.
*
* @param includes A list of include patterns.
* May be <code>null</code>, indicating that all files
* should be included. If a non-<code>null</code>
* list is given, all elements must be
* non-<code>null</code>.
*/
void setIncludes(String[] includes);
/**
* Sets whether or not the file system should be regarded as case sensitive.
*
* @param isCaseSensitive whether or not the file system should be
* regarded as a case sensitive one
*/
void setCaseSensitive(boolean isCaseSensitive);
}

View File

@@ -0,0 +1,178 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant;
import java.io.Serializable;
import org.owasp.dependencycheck.org.apache.tools.ant.util.FileUtils;
import org.xml.sax.Locator;
/**
* Stores the location of a piece of text within a file (file name,
* line number and column number). Note that the column number is
* currently ignored.
*
*/
public class Location implements Serializable {
private static final long serialVersionUID = 1L;
/** Name of the file. */
private final String fileName;
/** Line number within the file. */
private final int lineNumber;
/** Column number within the file. */
private final int columnNumber;
/** Location to use when one is needed but no information is available */
public static final Location UNKNOWN_LOCATION = new Location();
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
/**
* Creates an "unknown" location.
*/
private Location() {
this(null, 0, 0);
}
/**
* Creates a location consisting of a file name but no line number or
* column number.
*
* @param fileName The name of the file. May be <code>null</code>,
* in which case the location is equivalent to
* {@link #UNKNOWN_LOCATION UNKNOWN_LOCATION}.
*/
public Location(String fileName) {
this(fileName, 0, 0);
}
/**
* Creates a location from the SAX locator using the system ID as
* the filename.
*
* @param loc Must not be <code>null</code>.
*
* @since Ant 1.6
*/
public Location(Locator loc) {
this(loc.getSystemId(), loc.getLineNumber(), loc.getColumnNumber());
}
/**
* Creates a location consisting of a file name, line number and
* column number.
*
* @param fileName The name of the file. May be <code>null</code>,
* in which case the location is equivalent to
* {@link #UNKNOWN_LOCATION UNKNOWN_LOCATION}.
*
* @param lineNumber Line number within the file. Use 0 for unknown
* positions within a file.
* @param columnNumber Column number within the line.
*/
public Location(String fileName, int lineNumber, int columnNumber) {
if (fileName != null && fileName.startsWith("file:")) {
this.fileName = FILE_UTILS.fromURI(fileName);
} else {
this.fileName = fileName;
}
this.lineNumber = lineNumber;
this.columnNumber = columnNumber;
}
/**
* @return the filename portion of the location
* @since Ant 1.6
*/
public String getFileName() {
return fileName;
}
/**
* @return the line number
* @since Ant 1.6
*/
public int getLineNumber() {
return lineNumber;
}
/**
* @return the column number
* @since Ant 1.7
*/
public int getColumnNumber() {
return columnNumber;
}
/**
* Returns the file name, line number, a colon and a trailing space.
* An error message can be appended easily. For unknown locations, an
* empty string is returned.
*
* @return a String of the form <code>"fileName:lineNumber: "</code>
* if both file name and line number are known,
* <code>"fileName: "</code> if only the file name is known,
* and the empty string for unknown locations.
*/
public String toString() {
StringBuffer buf = new StringBuffer();
if (fileName != null) {
buf.append(fileName);
if (lineNumber != 0) {
buf.append(":");
buf.append(lineNumber);
}
buf.append(": ");
}
return buf.toString();
}
/**
* Equality operation.
* @param other the object to compare to.
* @return true if the other object contains the same information
* as this object.
* @since Ant 1.6.3
*/
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (other == null) {
return false;
}
if (!(other.getClass() == getClass())) {
return false;
}
return toString().equals(other.toString());
}
/**
* Hash operation.
* @return a hash code value for this location.
* @since Ant 1.6.3
*/
public int hashCode() {
return toString().hashCode();
}
}

View File

@@ -0,0 +1,165 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant;
import java.io.File;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import org.owasp.dependencycheck.org.apache.tools.ant.taskdefs.condition.Os;
/**
* A Path tokenizer takes a path and returns the components that make up
* that path.
*
* The path can use path separators of either ':' or ';' and file separators
* of either '/' or '\'.
*
*/
public class PathTokenizer {
/**
* A tokenizer to break the string up based on the ':' or ';' separators.
*/
private StringTokenizer tokenizer;
/**
* A String which stores any path components which have been read ahead
* due to DOS filesystem compensation.
*/
private String lookahead = null;
/**
* A boolean that determines if we are running on Novell NetWare, which
* exhibits slightly different path name characteristics (multi-character
* volume / drive names)
*/
private boolean onNetWare = Os.isFamily("netware");
/**
* Flag to indicate whether or not we are running on a platform with a
* DOS style filesystem
*/
private boolean dosStyleFilesystem;
/**
* Constructs a path tokenizer for the specified path.
*
* @param path The path to tokenize. Must not be <code>null</code>.
*/
public PathTokenizer(String path) {
if (onNetWare) {
// For NetWare, use the boolean=true mode, so we can use delimiter
// information to make a better decision later.
tokenizer = new StringTokenizer(path, ":;", true);
} else {
// on Windows and Unix, we can ignore delimiters and still have
// enough information to tokenize correctly.
tokenizer = new StringTokenizer(path, ":;", false);
}
dosStyleFilesystem = File.pathSeparatorChar == ';';
}
/**
* Tests if there are more path elements available from this tokenizer's
* path. If this method returns <code>true</code>, then a subsequent call
* to nextToken will successfully return a token.
*
* @return <code>true</code> if and only if there is at least one token
* in the string after the current position; <code>false</code> otherwise.
*/
public boolean hasMoreTokens() {
if (lookahead != null) {
return true;
}
return tokenizer.hasMoreTokens();
}
/**
* Returns the next path element from this tokenizer.
*
* @return the next path element from this tokenizer.
*
* @exception NoSuchElementException if there are no more elements in this
* tokenizer's path.
*/
public String nextToken() throws NoSuchElementException {
String token = null;
if (lookahead != null) {
token = lookahead;
lookahead = null;
} else {
token = tokenizer.nextToken().trim();
}
if (!onNetWare) {
if (token.length() == 1 && Character.isLetter(token.charAt(0))
&& dosStyleFilesystem
&& tokenizer.hasMoreTokens()) {
// we are on a dos style system so this path could be a drive
// spec. We look at the next token
String nextToken = tokenizer.nextToken().trim();
if (nextToken.startsWith("\\") || nextToken.startsWith("/")) {
// we know we are on a DOS style platform and the next path
// starts with a slash or backslash, so we know this is a
// drive spec
token += ":" + nextToken;
} else {
// store the token just read for next time
lookahead = nextToken;
}
}
} else {
// we are on NetWare, tokenizing is handled a little differently,
// due to the fact that NetWare has multiple-character volume names.
if (token.equals(File.pathSeparator) || token.equals(":")) {
// ignore ";" and get the next token
token = tokenizer.nextToken().trim();
}
if (tokenizer.hasMoreTokens()) {
// this path could be a drive spec, so look at the next token
String nextToken = tokenizer.nextToken().trim();
// make sure we aren't going to get the path separator next
if (!nextToken.equals(File.pathSeparator)) {
if (nextToken.equals(":")) {
if (!token.startsWith("/") && !token.startsWith("\\")
&& !token.startsWith(".")
&& !token.startsWith("..")) {
// it indeed is a drive spec, get the next bit
String oneMore = tokenizer.nextToken().trim();
if (!oneMore.equals(File.pathSeparator)) {
token += ":" + oneMore;
} else {
token += ":";
lookahead = oneMore;
}
}
// implicit else: ignore the ':' since we have either a
// UNIX or a relative path
} else {
// store the token just read for next time
lookahead = nextToken;
}
}
}
}
return token;
}
}

View File

@@ -0,0 +1,161 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant;
/**
* Base class for components of a project, including tasks and data types. Provides common facilities.
*
*/
public abstract class ProjectComponent implements Cloneable {
// // CheckStyle:VisibilityModifier OFF - bc
// /**
// * Project object of this component.
// * @deprecated since 1.6.x.
// * You should not be directly accessing this variable directly.
// * You should access project object via the getProject()
// * or setProject() accessor/mutators.
// */
// protected Project project;
/**
* Location within the build file of this task definition.
*
* @deprecated since 1.6.x. You should not be accessing this variable directly. Please use the
* {@link #getLocation()} method.
*/
protected Location location = Location.UNKNOWN_LOCATION;
/**
* Description of this component, if any.
*
* @deprecated since 1.6.x. You should not be accessing this variable directly.
*/
protected String description;
// CheckStyle:VisibilityModifier ON
/**
* Sole constructor.
*/
public ProjectComponent() {
}
// /**
// * Sets the project object of this component. This method is used by
// * Project when a component is added to it so that the component has
// * access to the functions of the project. It should not be used
// * for any other purpose.
// *
// * @param project Project in whose scope this component belongs.
// * Must not be <code>null</code>.
// */
// public void setProject(Project project) {
// this.project = project;
// }
//
// /**
// * Returns the project to which this component belongs.
// *
// * @return the components's project.
// */
// public Project getProject() {
// return project;
// }
/**
* Returns the file/location where this task was defined.
*
* @return the file/location where this task was defined. Should not return <code>null</code>.
* Location.UNKNOWN_LOCATION is used for unknown locations.
*
* @see Location#UNKNOWN_LOCATION
*/
public Location getLocation() {
return location;
}
/**
* Sets the file/location where this task was defined.
*
* @param location The file/location where this task was defined. Should not be <code>null</code>--use
* Location.UNKNOWN_LOCATION if the location isn't known.
*
* @see Location#UNKNOWN_LOCATION
*/
public void setLocation(Location location) {
this.location = location;
}
/**
* Sets a description of the current action. This may be used for logging purposes.
*
* @param desc Description of the current action. May be <code>null</code>, indicating that no description is
* available.
*
*/
public void setDescription(String desc) {
description = desc;
}
/**
* Returns the description of the current action.
*
* @return the description of the current action, or <code>null</code> if no description is available.
*/
public String getDescription() {
return description;
}
/**
* Logs a message with the default (INFO) priority.
*
* @param msg The message to be logged. Should not be <code>null</code>.
*/
public void log(String msg) {
// log(msg, Project.MSG_INFO);
}
/**
* Logs a message with the given priority.
*
* @param msg The message to be logged. Should not be <code>null</code>.
* @param msgLevel the message priority at which this message is to be logged.
*/
public void log(String msg, int msgLevel) {
// if (getProject() != null) {
// getProject().log(msg, msgLevel);
// } else {
// // 'reasonable' default, if the component is used without
// // a Project ( for example as a standalone Bean ).
// // Most ant components can be used this way.
// if (msgLevel <= Project.MSG_INFO) {
// System.err.println(msg);
// }
// }
}
/**
* @since Ant 1.7
* @return a shallow copy of this projectcomponent.
* @throws CloneNotSupportedException does not happen, but is declared to allow subclasses to do so.
*/
public Object clone() throws CloneNotSupportedException {
ProjectComponent pc = (ProjectComponent) super.clone();
pc.setLocation(getLocation());
//pc.setProject(getProject());
return pc;
}
}

View File

@@ -0,0 +1,530 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant.launch;
import java.net.MalformedURLException;
import java.net.URL;
import java.io.File;
import java.io.FilenameFilter;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.Locale;
import org.owasp.dependencycheck.org.apache.tools.ant.util.FileUtils;
// CheckStyle:LineLengthCheck OFF - urls are long!
/**
* The Locator is a utility class which is used to find certain items
* in the environment.
*
* It is used at boot time in the launcher, and cannot make use of any of Ant's other classes.
*
* This is a surprisingly brittle piece of code, and has had lots of bugs filed against it.
* {@link <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=42275">running ant off a network share can cause Ant to fail</a>}
* {@link <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=8031">use File.toURI().toURL().toExternalForm()</a>}
* {@link <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=42222">Locator implementation not encoding URI strings properly: spaces in paths</a>}
* It also breaks Eclipse 3.3 Betas
* {@link <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=183283">Exception if installation path has spaces</a>}
*
* Be very careful when making changes to this class, as a break will upset a lot of people.
* @since Ant 1.6
*/
// CheckStyle:LineLengthCheck ON - urls are long!
public final class Locator {
private static final int NIBBLE = 4;
private static final int NIBBLE_MASK = 0xF;
private static final int ASCII_SIZE = 128;
private static final int BYTE_SIZE = 256;
private static final int WORD = 16;
private static final int SPACE = 0x20;
private static final int DEL = 0x7F;
/**
* encoding used to represent URIs
*/
public static final String URI_ENCODING = "UTF-8";
// stolen from org.apache.xerces.impl.XMLEntityManager#getUserDir()
// of the Xerces-J team
// which ASCII characters need to be escaped
private static boolean[] gNeedEscaping = new boolean[ASCII_SIZE];
// the first hex character if a character needs to be escaped
private static char[] gAfterEscaping1 = new char[ASCII_SIZE];
// the second hex character if a character needs to be escaped
private static char[] gAfterEscaping2 = new char[ASCII_SIZE];
private static char[] gHexChs = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
/** Error string used when an invalid uri is seen */
public static final String ERROR_NOT_FILE_URI
= "Can only handle valid file: URIs, not ";
// initialize the above 3 arrays
static {
for (int i = 0; i < SPACE; i++) {
gNeedEscaping[i] = true;
gAfterEscaping1[i] = gHexChs[i >> NIBBLE];
gAfterEscaping2[i] = gHexChs[i & NIBBLE_MASK];
}
gNeedEscaping[DEL] = true;
gAfterEscaping1[DEL] = '7';
gAfterEscaping2[DEL] = 'F';
char[] escChs = {' ', '<', '>', '#', '%', '"', '{', '}',
'|', '\\', '^', '~', '[', ']', '`'};
int len = escChs.length;
char ch;
for (int i = 0; i < len; i++) {
ch = escChs[i];
gNeedEscaping[ch] = true;
gAfterEscaping1[ch] = gHexChs[ch >> NIBBLE];
gAfterEscaping2[ch] = gHexChs[ch & NIBBLE_MASK];
}
}
/**
* Not instantiable
*/
private Locator() {
}
/**
* Find the directory or jar file the class has been loaded from.
*
* @param c the class whose location is required.
* @return the file or jar with the class or null if we cannot
* determine the location.
*
* @since Ant 1.6
*/
public static File getClassSource(Class<?> c) {
String classResource = c.getName().replace('.', '/') + ".class";
return getResourceSource(c.getClassLoader(), classResource);
}
/**
* Find the directory or jar a given resource has been loaded from.
*
* @param c the classloader to be consulted for the source.
* @param resource the resource whose location is required.
*
* @return the file with the resource source or null if
* we cannot determine the location.
*
* @since Ant 1.6
*/
public static File getResourceSource(ClassLoader c, String resource) {
if (c == null) {
c = Locator.class.getClassLoader();
}
URL url = null;
if (c == null) {
url = ClassLoader.getSystemResource(resource);
} else {
url = c.getResource(resource);
}
if (url != null) {
String u = url.toString();
try {
if (u.startsWith("jar:file:")) {
return new File(fromJarURI(u));
} else if (u.startsWith("file:")) {
int tail = u.indexOf(resource);
String dirName = u.substring(0, tail);
return new File(fromURI(dirName));
}
} catch (IllegalArgumentException e) {
//unable to determine the URI for reasons unknown.
return null;
}
}
return null;
}
/**
* Constructs a file path from a <code>file:</code> URI.
*
* <p>Will be an absolute path if the given URI is absolute.</p>
*
* <p>Prior to Java 1.4,<!-- TODO is JDK version actually relevant? -->
* swallows '%' that are not followed by two characters.</p>
*
* See <a href="http://www.w3.org/TR/xml11/#dt-sysid">dt-sysid</a>
* which makes some mention of how
* characters not supported by URI Reference syntax should be escaped.
*
* @param uri the URI designating a file in the local filesystem.
* @return the local file system path for the file.
* @throws IllegalArgumentException if the URI is malformed or not a legal file: URL
* @since Ant 1.6
*/
public static String fromURI(String uri) {
return fromURIJava13(uri);
// #buzilla8031: first try Java 1.4.
// TODO should use java.net.URI now that we can rely on 1.4...
// but check for UNC-related regressions, e.g. #42275
// (and remember that \\server\share\file -> file:////server/share/file
// rather than -> file://server/share/file as it should;
// fixed only in JDK 7's java.nio.file.Path.toUri)
// return fromUriJava14(uri);
}
/**
* Java1.4+ code to extract the path from the URI.
* @param uri
* @return null if a conversion was not possible
*/
/* currently unused:
private static String fromUriJava14(String uri) {
// Also check for properly formed URIs. Ant formerly recommended using
// nonsense URIs such as "file:./foo.xml" in XML includes. You shouldn't
// do that (just "foo.xml" is correct) but for compatibility we special-case
// things when the path is not absolute, and fall back to the old parsing behavior.
if (uri.startsWith("file:/")) {
try {
File f = new File(URI.create(encodeURI(uri)));
//bug #42227 forgot to decode before returning
return decodeUri(f.getAbsolutePath());
} catch (IllegalArgumentException e) {
// Bad URI, pass this on.
// no, this is downgraded to a warning after various
// JRE bugs surfaced. Hand off
// to our built in code on a failure
//throw new IllegalArgumentException(
// "Bad URI " + uri + ":" + e.getMessage(), e);
e.printStackTrace();
} catch (Exception e) {
// Unexpected exception? Should not happen.
e.printStackTrace();
}
}
return null;
}
*/
/**
* @param uri uri to expand
* @return the decoded URI
* @since Ant1.7.1
*/
private static String fromURIJava13(String uri) {
// Fallback method for Java 1.3 or earlier.
URL url = null;
try {
url = new URL(uri);
} catch (MalformedURLException emYouEarlEx) {
// Ignore malformed exception
}
if (url == null || !("file".equals(url.getProtocol()))) {
throw new IllegalArgumentException(ERROR_NOT_FILE_URI + uri);
}
StringBuffer buf = new StringBuffer(url.getHost());
if (buf.length() > 0) {
buf.insert(0, File.separatorChar).insert(0, File.separatorChar);
}
String file = url.getFile();
int queryPos = file.indexOf('?');
buf.append((queryPos < 0) ? file : file.substring(0, queryPos));
uri = buf.toString().replace('/', File.separatorChar);
if (File.pathSeparatorChar == ';' && uri.startsWith("\\") && uri.length() > 2
&& Character.isLetter(uri.charAt(1)) && uri.lastIndexOf(':') > -1) {
uri = uri.substring(1);
}
String path = null;
try {
path = decodeUri(uri);
//consider adding the current directory. This is not done when
//the path is a UNC name
String cwd = System.getProperty("user.dir");
int posi = cwd.indexOf(':');
boolean pathStartsWithFileSeparator = path.startsWith(File.separator);
boolean pathStartsWithUNC = path.startsWith("" + File.separator + File.separator);
if ((posi > 0) && pathStartsWithFileSeparator && !pathStartsWithUNC) {
path = cwd.substring(0, posi + 1) + path;
}
} catch (UnsupportedEncodingException exc) {
// not sure whether this is clean, but this method is
// declared not to throw exceptions.
throw new IllegalStateException(
"Could not convert URI " + uri + " to path: "
+ exc.getMessage());
}
return path;
}
/**
* Crack a JAR URI.
* This method is public for testing; we may delete it without any warning -it is not part of Ant's stable API.
* @param uri uri to expand; contains jar: somewhere in it
* @return the decoded URI
* @since Ant1.7.1
*/
public static String fromJarURI(String uri) {
int pling = uri.indexOf("!/");
String jarName = uri.substring("jar:".length(), pling);
return fromURI(jarName);
}
/**
* Decodes an Uri with % characters.
* The URI is escaped
* @param uri String with the uri possibly containing % characters.
* @return The decoded Uri
* @throws UnsupportedEncodingException if UTF-8 is not available
* @since Ant 1.7
*/
public static String decodeUri(String uri) throws UnsupportedEncodingException {
if (uri.indexOf('%') == -1) {
return uri;
}
ByteArrayOutputStream sb = new ByteArrayOutputStream(uri.length());
CharacterIterator iter = new StringCharacterIterator(uri);
for (char c = iter.first(); c != CharacterIterator.DONE;
c = iter.next()) {
if (c == '%') {
char c1 = iter.next();
if (c1 != CharacterIterator.DONE) {
int i1 = Character.digit(c1, WORD);
char c2 = iter.next();
if (c2 != CharacterIterator.DONE) {
int i2 = Character.digit(c2, WORD);
sb.write((char) ((i1 << NIBBLE) + i2));
}
}
} else if (c >= 0x0000 && c < 0x0080) {
sb.write(c);
} else { // #50543
byte[] bytes = String.valueOf(c).getBytes(URI_ENCODING);
sb.write(bytes, 0, bytes.length);
}
}
return sb.toString(URI_ENCODING);
}
/**
* Encodes an Uri with % characters.
* The URI is escaped
* @param path String to encode.
* @return The encoded string, according to URI norms
* @throws UnsupportedEncodingException if UTF-8 is not available
* @since Ant 1.7
*/
public static String encodeURI(String path) throws UnsupportedEncodingException {
int i = 0;
int len = path.length();
int ch = 0;
StringBuffer sb = null;
for (; i < len; i++) {
ch = path.charAt(i);
// if it's not an ASCII character, break here, and use UTF-8 encoding
if (ch >= ASCII_SIZE) {
break;
}
if (gNeedEscaping[ch]) {
if (sb == null) {
sb = new StringBuffer(path.substring(0, i));
}
sb.append('%');
sb.append(gAfterEscaping1[ch]);
sb.append(gAfterEscaping2[ch]);
// record the fact that it's escaped
} else if (sb != null) {
sb.append((char) ch);
}
}
// we saw some non-ascii character
if (i < len) {
if (sb == null) {
sb = new StringBuffer(path.substring(0, i));
}
// get UTF-8 bytes for the remaining sub-string
byte[] bytes = null;
byte b;
bytes = path.substring(i).getBytes(URI_ENCODING);
len = bytes.length;
// for each byte
for (i = 0; i < len; i++) {
b = bytes[i];
// for non-ascii character: make it positive, then escape
if (b < 0) {
ch = b + BYTE_SIZE;
sb.append('%');
sb.append(gHexChs[ch >> NIBBLE]);
sb.append(gHexChs[ch & NIBBLE_MASK]);
} else if (gNeedEscaping[b]) {
sb.append('%');
sb.append(gAfterEscaping1[b]);
sb.append(gAfterEscaping2[b]);
} else {
sb.append((char) b);
}
}
}
return sb == null ? path : sb.toString();
}
/**
* Convert a File to a URL.
* File.toURL() does not encode characters like #.
* File.toURI() has been introduced in java 1.4, so
* Ant cannot use it (except by reflection) <!-- TODO no longer true -->
* FileUtils.toURI() cannot be used by Locator.java
* Implemented this way.
* File.toURL() adds file: and changes '\' to '/' for dos OSes
* encodeURI converts characters like ' ' and '#' to %DD
* @param file the file to convert
* @return URL the converted File
* @throws MalformedURLException on error
* @deprecated since 1.9, use {@link FileUtils#getFileURL(File)}
*/
@Deprecated
public static URL fileToURL(File file)
throws MalformedURLException {
return new URL(file.toURI().toASCIIString());
}
/**
* Get the File necessary to load the Sun compiler tools. If the classes
* are available to this class, then no additional URL is required and
* null is returned. This may be because the classes are explicitly in the
* class path or provided by the JVM directly.
*
* @return the tools jar as a File if required, null otherwise.
*/
public static File getToolsJar() {
// firstly check if the tools jar is already in the classpath
boolean toolsJarAvailable = false;
try {
// just check whether this throws an exception
Class.forName("com.sun.tools.javac.Main");
toolsJarAvailable = true;
} catch (Exception e) {
try {
Class.forName("sun.tools.javac.Main");
toolsJarAvailable = true;
} catch (Exception e2) {
// ignore
}
}
if (toolsJarAvailable) {
return null;
}
// couldn't find compiler - try to find tools.jar
// based on java.home setting
String libToolsJar
= File.separator + "lib" + File.separator + "tools.jar";
String javaHome = System.getProperty("java.home");
File toolsJar = new File(javaHome + libToolsJar);
if (toolsJar.exists()) {
// Found in java.home as given
return toolsJar;
}
if (javaHome.toLowerCase(Locale.ENGLISH).endsWith(File.separator + "jre")) {
javaHome = javaHome.substring(
0, javaHome.length() - "/jre".length());
toolsJar = new File(javaHome + libToolsJar);
}
if (!toolsJar.exists()) {
System.out.println("Unable to locate tools.jar. "
+ "Expected to find it in " + toolsJar.getPath());
return null;
}
return toolsJar;
}
/**
* Get an array of URLs representing all of the jar files in the
* given location. If the location is a file, it is returned as the only
* element of the array. If the location is a directory, it is scanned for
* jar files.
*
* @param location the location to scan for Jars.
*
* @return an array of URLs for all jars in the given location.
*
* @exception MalformedURLException if the URLs for the jars cannot be
* formed.
*/
public static URL[] getLocationURLs(File location)
throws MalformedURLException {
return getLocationURLs(location, new String[]{".jar"});
}
/**
* Get an array of URLs representing all of the files of a given set of
* extensions in the given location. If the location is a file, it is
* returned as the only element of the array. If the location is a
* directory, it is scanned for matching files.
*
* @param location the location to scan for files.
* @param extensions an array of extension that are to match in the
* directory search.
*
* @return an array of URLs of matching files.
* @exception MalformedURLException if the URLs for the files cannot be
* formed.
*/
public static URL[] getLocationURLs(File location,
final String[] extensions)
throws MalformedURLException {
URL[] urls = new URL[0];
if (!location.exists()) {
return urls;
}
if (!location.isDirectory()) {
urls = new URL[1];
String path = location.getPath();
String littlePath = path.toLowerCase(Locale.ENGLISH);
for (int i = 0; i < extensions.length; ++i) {
if (littlePath.endsWith(extensions[i])) {
urls[0] = fileToURL(location);
break;
}
}
return urls;
}
File[] matches = location.listFiles(
new FilenameFilter() {
public boolean accept(File dir, String name) {
String littleName = name.toLowerCase(Locale.ENGLISH);
for (int i = 0; i < extensions.length; ++i) {
if (littleName.endsWith(extensions[i])) {
return true;
}
}
return false;
}
});
urls = new URL[matches.length];
for (int i = 0; i < matches.length; ++i) {
urls[i] = fileToURL(matches[i]);
}
return urls;
}
}

View File

@@ -0,0 +1,14 @@
/**
* <html>
* <head>
* <title>org.owasp.dependencycheck.org.apache.tools.ant.launch</title>
* </head>
* <body>
* This is a copy of classes within Apache Ant. The DirectoryScanner
* is needed by dependency-check. However, we did not want to make
* Ant a dependency. As such, a few files were copied and slightly
* modified to remove any references to the Ant Project class.
* </body>
* </html>
*/
package org.owasp.dependencycheck.org.apache.tools.ant.launch;

View File

@@ -0,0 +1,14 @@
/**
* <html>
* <head>
* <title>org.owasp.dependencycheck.org.apache.tools.ant</title>
* </head>
* <body>
* This is a copy of classes within Apache Ant. The DirectoryScanner
* is needed by dependency-check. However, we did not want to make
* Ant a dependency. As such, a few files were copied and slightly
* modified to remove any references to the Ant Project class.
* </body>
* </html>
*/
package org.owasp.dependencycheck.org.apache.tools.ant;

View File

@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant.taskdefs.condition;
import org.owasp.dependencycheck.org.apache.tools.ant.BuildException;
/**
* Interface for conditions to use inside the &lt;condition&gt; task.
*
*/
public interface Condition {
/**
* Is this condition true?
* @return true if the condition is true
* @exception BuildException if an error occurs
*/
boolean eval() throws BuildException;
}

View File

@@ -0,0 +1,321 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant.taskdefs.condition;
import java.util.Locale;
import org.owasp.dependencycheck.org.apache.tools.ant.BuildException;
/**
* Condition that tests the OS type.
*
* @since Ant 1.4
*/
public class Os implements Condition {
private static final String OS_NAME =
System.getProperty("os.name").toLowerCase(Locale.ENGLISH);
private static final String OS_ARCH =
System.getProperty("os.arch").toLowerCase(Locale.ENGLISH);
private static final String OS_VERSION =
System.getProperty("os.version").toLowerCase(Locale.ENGLISH);
private static final String PATH_SEP =
System.getProperty("path.separator");
/**
* OS family to look for
*/
private String family;
/**
* Name of OS
*/
private String name;
/**
* version of OS
*/
private String version;
/**
* OS architecture
*/
private String arch;
/**
* OS family that can be tested for. {@value}
*/
public static final String FAMILY_WINDOWS = "windows";
/**
* OS family that can be tested for. {@value}
*/
public static final String FAMILY_9X = "win9x";
/**
* OS family that can be tested for. {@value}
*/
public static final String FAMILY_NT = "winnt";
/**
* OS family that can be tested for. {@value}
*/
public static final String FAMILY_OS2 = "os/2";
/**
* OS family that can be tested for. {@value}
*/
public static final String FAMILY_NETWARE = "netware";
/**
* OS family that can be tested for. {@value}
*/
public static final String FAMILY_DOS = "dos";
/**
* OS family that can be tested for. {@value}
*/
public static final String FAMILY_MAC = "mac";
/**
* OS family that can be tested for. {@value}
*/
public static final String FAMILY_TANDEM = "tandem";
/**
* OS family that can be tested for. {@value}
*/
public static final String FAMILY_UNIX = "unix";
/**
* OS family that can be tested for. {@value}
*/
public static final String FAMILY_VMS = "openvms";
/**
* OS family that can be tested for. {@value}
*/
public static final String FAMILY_ZOS = "z/os";
/** OS family that can be tested for. {@value} */
public static final String FAMILY_OS400 = "os/400";
/**
* OpenJDK is reported to call MacOS X "Darwin"
* @see https://issues.apache.org/bugzilla/show_bug.cgi?id=44889
* @see https://issues.apache.org/jira/browse/HADOOP-3318
*/
private static final String DARWIN = "darwin";
/**
* Default constructor
*
*/
public Os() {
//default
}
/**
* Constructor that sets the family attribute
* @param family a String value
*/
public Os(String family) {
setFamily(family);
}
/**
* Sets the desired OS family type
*
* @param f The OS family type desired<br>
* Possible values:<br>
* <ul>
* <li>dos</li>
* <li>mac</li>
* <li>netware</li>
* <li>os/2</li>
* <li>tandem</li>
* <li>unix</li>
* <li>windows</li>
* <li>win9x</li>
* <li>z/os</li>
* <li>os/400</li>
* </ul>
*/
public void setFamily(String f) {
family = f.toLowerCase(Locale.ENGLISH);
}
/**
* Sets the desired OS name
*
* @param name The OS name
*/
public void setName(String name) {
this.name = name.toLowerCase(Locale.ENGLISH);
}
/**
* Sets the desired OS architecture
*
* @param arch The OS architecture
*/
public void setArch(String arch) {
this.arch = arch.toLowerCase(Locale.ENGLISH);
}
/**
* Sets the desired OS version
*
* @param version The OS version
*/
public void setVersion(String version) {
this.version = version.toLowerCase(Locale.ENGLISH);
}
/**
* Determines if the OS on which Ant is executing matches the type of
* that set in setFamily.
* @return true if the os matches.
* @throws BuildException if there is an error.
* @see Os#setFamily(String)
*/
public boolean eval() throws BuildException {
return isOs(family, name, arch, version);
}
/**
* Determines if the OS on which Ant is executing matches the
* given OS family.
* @param family the family to check for
* @return true if the OS matches
* @since 1.5
*/
public static boolean isFamily(String family) {
return isOs(family, null, null, null);
}
/**
* Determines if the OS on which Ant is executing matches the
* given OS name.
*
* @param name the OS name to check for
* @return true if the OS matches
* @since 1.7
*/
public static boolean isName(String name) {
return isOs(null, name, null, null);
}
/**
* Determines if the OS on which Ant is executing matches the
* given OS architecture.
*
* @param arch the OS architecture to check for
* @return true if the OS matches
* @since 1.7
*/
public static boolean isArch(String arch) {
return isOs(null, null, arch, null);
}
/**
* Determines if the OS on which Ant is executing matches the
* given OS version.
*
* @param version the OS version to check for
* @return true if the OS matches
* @since 1.7
*/
public static boolean isVersion(String version) {
return isOs(null, null, null, version);
}
/**
* Determines if the OS on which Ant is executing matches the
* given OS family, name, architecture and version
*
* @param family The OS family
* @param name The OS name
* @param arch The OS architecture
* @param version The OS version
* @return true if the OS matches
* @since 1.7
*/
public static boolean isOs(String family, String name, String arch,
String version) {
boolean retValue = false;
if (family != null || name != null || arch != null
|| version != null) {
boolean isFamily = true;
boolean isName = true;
boolean isArch = true;
boolean isVersion = true;
if (family != null) {
//windows probing logic relies on the word 'windows' in
//the OS
boolean isWindows = OS_NAME.indexOf(FAMILY_WINDOWS) > -1;
boolean is9x = false;
boolean isNT = false;
if (isWindows) {
//there are only four 9x platforms that we look for
is9x = (OS_NAME.indexOf("95") >= 0
|| OS_NAME.indexOf("98") >= 0
|| OS_NAME.indexOf("me") >= 0
//wince isn't really 9x, but crippled enough to
//be a muchness. Ant doesnt run on CE, anyway.
|| OS_NAME.indexOf("ce") >= 0);
isNT = !is9x;
}
if (family.equals(FAMILY_WINDOWS)) {
isFamily = isWindows;
} else if (family.equals(FAMILY_9X)) {
isFamily = isWindows && is9x;
} else if (family.equals(FAMILY_NT)) {
isFamily = isWindows && isNT;
} else if (family.equals(FAMILY_OS2)) {
isFamily = OS_NAME.indexOf(FAMILY_OS2) > -1;
} else if (family.equals(FAMILY_NETWARE)) {
isFamily = OS_NAME.indexOf(FAMILY_NETWARE) > -1;
} else if (family.equals(FAMILY_DOS)) {
isFamily = PATH_SEP.equals(";") && !isFamily(FAMILY_NETWARE);
} else if (family.equals(FAMILY_MAC)) {
isFamily = OS_NAME.indexOf(FAMILY_MAC) > -1
|| OS_NAME.indexOf(DARWIN) > -1;
} else if (family.equals(FAMILY_TANDEM)) {
isFamily = OS_NAME.indexOf("nonstop_kernel") > -1;
} else if (family.equals(FAMILY_UNIX)) {
isFamily = PATH_SEP.equals(":")
&& !isFamily(FAMILY_VMS)
&& (!isFamily(FAMILY_MAC) || OS_NAME.endsWith("x")
|| OS_NAME.indexOf(DARWIN) > -1);
} else if (family.equals(FAMILY_ZOS)) {
isFamily = OS_NAME.indexOf(FAMILY_ZOS) > -1
|| OS_NAME.indexOf("os/390") > -1;
} else if (family.equals(FAMILY_OS400)) {
isFamily = OS_NAME.indexOf(FAMILY_OS400) > -1;
} else if (family.equals(FAMILY_VMS)) {
isFamily = OS_NAME.indexOf(FAMILY_VMS) > -1;
} else {
throw new BuildException(
"Don\'t know how to detect os family \""
+ family + "\"");
}
}
if (name != null) {
isName = name.equals(OS_NAME);
}
if (arch != null) {
isArch = arch.equals(OS_ARCH);
}
if (version != null) {
isVersion = version.equals(OS_VERSION);
}
retValue = isFamily && isName && isArch && isVersion;
}
return retValue;
}
}

View File

@@ -0,0 +1,14 @@
/**
* <html>
* <head>
* <title>org.owasp.dependencycheck.org.apache.tools.ant.taskdefs.condition</title>
* </head>
* <body>
* This is a copy of classes within Apache Ant. The DirectoryScanner
* is needed by dependency-check. However, we did not want to make
* Ant a dependency. As such, a few files were copied and slightly
* modified to remove any references to the Ant Project class.
* </body>
* </html>
*/
package org.owasp.dependencycheck.org.apache.tools.ant.taskdefs.condition;

View File

@@ -0,0 +1,353 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant.types;
import org.owasp.dependencycheck.org.apache.tools.ant.BuildException;
import org.owasp.dependencycheck.org.apache.tools.ant.ProjectComponent;
/**
* Base class for those classes that can appear inside the build file as stand alone data types.
*
* <p>
* This class handles the common description attribute and provides a default implementation for reference handling and
* checking for circular references that is appropriate for types that can not be nested inside elements of the same
* type (i.e. &lt;patternset&gt; but not &lt;path&gt;).</p>
*
*/
public abstract class DataType extends ProjectComponent implements Cloneable {
// CheckStyle:VisibilityModifier OFF
/**
* Value to the refid attribute.
*
* @deprecated since 1.7. The user should not be directly referencing variable. Please use {@link #getRefid}
* instead.
*/
protected Reference ref;
/**
* Are we sure we don't hold circular references?
*
* <p>
* Subclasses are responsible for setting this value to false if we'd need to investigate this condition (usually
* because a child element has been added that is a subclass of DataType).</p>
*
* @deprecated since 1.7. The user should not be directly referencing variable. Please use {@link #setChecked} or
* {@link #isChecked} instead.
*/
protected boolean checked = true;
// CheckStyle:VisibilityModifier ON
/**
* Has the refid attribute of this element been set?
*
* @return true if the refid attribute has been set
*/
public boolean isReference() {
return ref != null;
}
/**
* Set the value of the refid attribute.
*
* <p>
* Subclasses may need to check whether any other attributes have been set as well or child elements have been
* created and thus override this method. if they do the must call <code>super.setRefid</code>.</p>
*
* @param ref the reference to use
*/
public void setRefid(final Reference ref) {
this.ref = ref;
checked = false;
}
// /**
// * Gets as descriptive as possible a name used for this datatype instance.
// *
// * @return <code>String</code> name.
// */
// protected String getDataTypeName() {
// return ComponentHelper.getElementName(getProject(), this, true);
// }
// /**
// * Convenience method.
// * @since Ant 1.7
// */
// protected void dieOnCircularReference() {
// dieOnCircularReference(getProject());
// }
//
// /**
// * Convenience method.
// * @param p the Ant Project instance against which to resolve references.
// * @since Ant 1.7
// */
// protected void dieOnCircularReference(Project p) {
// if (checked || !isReference()) {
// return;
// }
// dieOnCircularReference(new IdentityStack<Object>(this), p);
// }
//
// /**
// * Check to see whether any DataType we hold references to is
// * included in the Stack (which holds all DataType instances that
// * directly or indirectly reference this instance, including this
// * instance itself).
// *
// * <p>If one is included, throw a BuildException created by {@link
// * #circularReference circularReference}.</p>
// *
// * <p>This implementation is appropriate only for a DataType that
// * cannot hold other DataTypes as children.</p>
// *
// * <p>The general contract of this method is that it shouldn't do
// * anything if {@link #checked <code>checked</code>} is true and
// * set it to true on exit.</p>
// * @param stack the stack of references to check.
// * @param project the project to use to dereference the references.
// * @throws BuildException on error.
// */
// protected void dieOnCircularReference(final Stack<Object> stack,
// final Project project)
// throws BuildException {
//
// if (checked || !isReference()) {
// return;
// }
// Object o = ref.getReferencedObject(project);
//
// if (o instanceof DataType) {
// IdentityStack<Object> id = IdentityStack.getInstance(stack);
//
// if (id.contains(o)) {
// throw circularReference();
// } else {
// id.push(o);
// ((DataType) o).dieOnCircularReference(id, project);
// id.pop();
// }
// }
// checked = true;
// }
// /**
// * Allow DataTypes outside org.apache.tools.ant.types to indirectly call dieOnCircularReference on nested DataTypes.
// *
// * @param dt the DataType to check.
// * @param stk the stack of references to check.
// * @param p the project to use to dereference the references.
// * @throws BuildException on error.
// * @since Ant 1.7
// */
// public static void invokeCircularReferenceCheck(DataType dt, Stack<Object> stk,
// Project p) {
// dt.dieOnCircularReference(stk, p);
// }
//
// /**
// * Allow DataTypes outside org.apache.tools.ant.types to indirectly call dieOnCircularReference on nested DataTypes.
// *
// * <p>
// * Pushes dt on the stack, runs dieOnCircularReference and pops it again.</p>
// *
// * @param dt the DataType to check.
// * @param stk the stack of references to check.
// * @param p the project to use to dereference the references.
// * @throws BuildException on error.
// * @since Ant 1.8.0
// */
// public static void pushAndInvokeCircularReferenceCheck(DataType dt,
// Stack<Object> stk,
// Project p) {
// stk.push(dt);
// dt.dieOnCircularReference(stk, p);
// stk.pop();
// }
// /**
// * Performs the check for circular references and returns the referenced object.
// *
// * @return the dereferenced object.
// * @throws BuildException if the reference is invalid (circular ref, wrong class, etc).
// * @since Ant 1.7
// */
// protected Object getCheckedRef() {
// return getCheckedRef(getProject());
// }
//
// /**
// * Performs the check for circular references and returns the referenced object.
// *
// * @param p the Ant Project instance against which to resolve references.
// * @return the dereferenced object.
// * @throws BuildException if the reference is invalid (circular ref, wrong class, etc).
// * @since Ant 1.7
// */
// protected Object getCheckedRef(Project p) {
// return getCheckedRef(getClass(), getDataTypeName(), p);
// }
//
// /**
// * Performs the check for circular references and returns the referenced object.
// *
// * @param requiredClass the class that this reference should be a subclass of.
// * @param dataTypeName the name of the datatype that the reference should be (error message use only).
// * @return the dereferenced object.
// * @throws BuildException if the reference is invalid (circular ref, wrong class, etc).
// */
// protected <T> T getCheckedRef(final Class<T> requiredClass,
// final String dataTypeName) {
// return getCheckedRef(requiredClass, dataTypeName, getProject());
// }
//
// /**
// * Performs the check for circular references and returns the referenced object. This version allows the fallback
// * Project instance to be specified.
// *
// * @param requiredClass the class that this reference should be a subclass of.
// * @param dataTypeName the name of the datatype that the reference should be (error message use only).
// * @param project the fallback Project instance for dereferencing.
// * @return the dereferenced object.
// * @throws BuildException if the reference is invalid (circular ref, wrong class, etc), or if <code>project</code>
// * is <code>null</code>.
// * @since Ant 1.7
// */
// protected <T> T getCheckedRef(final Class<T> requiredClass,
// final String dataTypeName, final Project project) {
// if (project == null) {
// throw new BuildException("No Project specified");
// }
// dieOnCircularReference(project);
// Object o = ref.getReferencedObject(project);
// if (!(requiredClass.isAssignableFrom(o.getClass()))) {
// log("Class " + o.getClass() + " is not a subclass of " + requiredClass,
// Project.MSG_VERBOSE);
// String msg = ref.getRefId() + " doesn\'t denote a " + dataTypeName;
// throw new BuildException(msg);
// }
// @SuppressWarnings("unchecked")
// final T result = (T) o;
// return result;
// }
/**
* Creates an exception that indicates that refid has to be the only attribute if it is set.
*
* @return the exception to throw
*/
protected BuildException tooManyAttributes() {
return new BuildException("You must not specify more than one "
+ "attribute when using refid");
}
/**
* Creates an exception that indicates that this XML element must not have child elements if the refid attribute is
* set.
*
* @return the exception to throw
*/
protected BuildException noChildrenAllowed() {
return new BuildException("You must not specify nested elements "
+ "when using refid");
}
/**
* Creates an exception that indicates the user has generated a loop of data types referencing each other.
*
* @return the exception to throw
*/
protected BuildException circularReference() {
return new BuildException("This data type contains a circular "
+ "reference.");
}
/**
* The flag that is used to indicate that circular references have been checked.
*
* @return true if circular references have been checked
*/
protected boolean isChecked() {
return checked;
}
/**
* Set the flag that is used to indicate that circular references have been checked.
*
* @param checked if true, if circular references have been checked
*/
protected void setChecked(final boolean checked) {
this.checked = checked;
}
/**
* get the reference set on this object
*
* @return the reference or null
*/
public Reference getRefid() {
return ref;
}
/**
* check that it is ok to set attributes, i.e that no reference is defined
*
* @since Ant 1.6
* @throws BuildException if not allowed
*/
protected void checkAttributesAllowed() {
if (isReference()) {
throw tooManyAttributes();
}
}
/**
* check that it is ok to add children, i.e that no reference is defined
*
* @since Ant 1.6
* @throws BuildException if not allowed
*/
protected void checkChildrenAllowed() {
if (isReference()) {
throw noChildrenAllowed();
}
}
/**
* Basic DataType toString().
*
* @return this DataType formatted as a String.
*/
public String toString() {
String d = getDescription();
//return d == null ? getDataTypeName() : getDataTypeName() + " " + d;
return d == null ? "DataType" : d;
}
/**
* @since Ant 1.7
* @return a shallow copy of this DataType.
* @throws CloneNotSupportedException if there is a problem.
*/
public Object clone() throws CloneNotSupportedException {
DataType dt = (DataType) super.clone();
dt.setDescription(getDescription());
if (getRefid() != null) {
dt.setRefid(getRefid());
}
dt.setChecked(isChecked());
return dt;
}
}

View File

@@ -0,0 +1,126 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant.types;
/**
* Class to hold a reference to another object in the project.
*
*/
public class Reference {
private String refid;
//private Project project;
/**
* Create a reference.
*
* @deprecated since 1.7. Please use {@link Reference#Reference(Project,String)} instead.
*/
public Reference() {
}
/**
* Create a reference to a named ID.
*
* @param id the name of this reference
* @deprecated since 1.7. Please use {@link Reference#Reference(Project,String)} instead.
*/
public Reference(String id) {
setRefId(id);
}
//
// /**
// * Create a reference to a named ID in a particular project.
// * @param p the project this reference is associated with
// * @param id the name of this reference
// * @since Ant 1.6.3
// */
// public Reference(Project p, String id) {
// setRefId(id);
// setProject(p);
// }
/**
* Set the reference id. Should not normally be necessary; use {@link Reference#Reference(Project, String)}.
*
* @param id the reference id to use
*/
public void setRefId(String id) {
refid = id;
}
/**
* Get the reference id of this reference.
*
* @return the reference id
*/
public String getRefId() {
return refid;
}
// /**
// * Set the associated project. Should not normally be necessary;
// * use {@link Reference#Reference(Project,String)}.
// * @param p the project to use
// * @since Ant 1.6.3
// */
// public void setProject(Project p) {
// this.project = p;
// }
//
// /**
// * Get the associated project, if any; may be null.
// * @return the associated project
// * @since Ant 1.6.3
// */
// public Project getProject() {
// return project;
// }
// /**
// * Resolve the reference, using the associated project if
// * it set, otherwise use the passed in project.
// * @param fallback the fallback project to use if the project attribute of
// * reference is not set.
// * @return the dereferenced object.
// * @throws BuildException if the reference cannot be dereferenced.
// */
// public Object getReferencedObject(Project fallback) throws BuildException {
// if (refid == null) {
// throw new BuildException("No reference specified");
// }
//
// Object o = project == null ? fallback.getReference(refid) : project.getReference(refid);
// if (o == null) {
// throw new BuildException("Reference " + refid + " not found.");
// }
// return o;
// }
// /**
// * Resolve the reference, looking in the associated project.
// * @see Project#getReference
// * @return the dereferenced object.
// * @throws BuildException if the project is null or the reference cannot be dereferenced
// * @since Ant 1.6.3
// */
// public Object getReferencedObject() throws BuildException {
// if (project == null) {
// throw new BuildException("No project set on reference to " + refid);
// }
// return getReferencedObject(project);
// }
}

View File

@@ -0,0 +1,462 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant.types;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.Iterator;
import java.util.NoSuchElementException;
import org.owasp.dependencycheck.org.apache.tools.ant.types.resources.FileProvider;
/**
* Describes a "File-like" resource (File, ZipEntry, etc.).
*
* This class is meant to be used by classes needing to record path and date/time information about a file, a zip entry
* or some similar resource (URL, archive in a version control repository, ...).
*
* @since Ant 1.5.2
* @see org.apache.tools.ant.types.resources.Touchable
*/
public class Resource extends DataType implements Comparable<Resource>, ResourceCollection {
/**
* Constant unknown size
*/
public static final long UNKNOWN_SIZE = -1;
/**
* Constant unknown datetime for getLastModified
*/
public static final long UNKNOWN_DATETIME = 0L;
/**
* Magic number
*/
protected static final int MAGIC = getMagicNumber("Resource".getBytes());
private static final int NULL_NAME = getMagicNumber("null name".getBytes());
/**
* Create a "magic number" for use in hashCode calculations.
*
* @param seed byte[] to seed with.
* @return a magic number as int.
*/
protected static int getMagicNumber(byte[] seed) {
return new BigInteger(seed).intValue();
}
private String name = null;
private Boolean exists = null;
private Long lastmodified = null;
private Boolean directory = null;
private Long size = null;
/**
* Default constructor.
*/
public Resource() {
}
/**
* Only sets the name.
*
* <p>
* This is a dummy, used for not existing resources.</p>
*
* @param name relative path of the resource. Expects &quot;/&quot; to be used as the directory separator.
*/
public Resource(String name) {
this(name, false, 0, false);
}
/**
* Sets the name, lastmodified flag, and exists flag.
*
* @param name relative path of the resource. Expects &quot;/&quot; to be used as the directory separator.
* @param exists if true, this resource exists.
* @param lastmodified the last modification time of this resource.
*/
public Resource(String name, boolean exists, long lastmodified) {
this(name, exists, lastmodified, false);
}
/**
* Sets the name, lastmodified flag, exists flag, and directory flag.
*
* @param name relative path of the resource. Expects &quot;/&quot; to be used as the directory separator.
* @param exists if true the resource exists
* @param lastmodified the last modification time of the resource
* @param directory if true, this resource is a directory
*/
public Resource(String name, boolean exists, long lastmodified, boolean directory) {
this(name, exists, lastmodified, directory, UNKNOWN_SIZE);
}
/**
* Sets the name, lastmodified flag, exists flag, directory flag, and size.
*
* @param name relative path of the resource. Expects &quot;/&quot; to be used as the directory separator.
* @param exists if true the resource exists
* @param lastmodified the last modification time of the resource
* @param directory if true, this resource is a directory
* @param size the size of this resource.
*/
public Resource(String name, boolean exists, long lastmodified, boolean directory, long size) {
this.name = name;
setName(name);
setExists(exists);
setLastModified(lastmodified);
setDirectory(directory);
setSize(size);
}
/**
* Name attribute will contain the path of a file relative to the root directory of its fileset or the recorded path
* of a zip entry.
*
* <p>
* example for a file with fullpath /var/opt/adm/resource.txt in a file set with root dir /var/opt it will be
* adm/resource.txt.</p>
*
* <p>
* &quot;/&quot; will be used as the directory separator.</p>
*
* @return the name of this resource.
*/
public String getName() {
//return isReference() ? ((Resource) getCheckedRef()).getName() : name;
return name;
}
/**
* Set the name of this Resource.
*
* @param name relative path of the resource. Expects &quot;/&quot; to be used as the directory separator.
*/
public void setName(String name) {
checkAttributesAllowed();
this.name = name;
}
/**
* The exists attribute tells whether a resource exists.
*
* @return true if this resource exists.
*/
public boolean isExists() {
// if (isReference()) {
// return ((Resource) getCheckedRef()).isExists();
// }
//default true:
return exists == null || exists.booleanValue();
}
/**
* Set the exists attribute.
*
* @param exists if true, this resource exists.
*/
public void setExists(boolean exists) {
checkAttributesAllowed();
this.exists = exists ? Boolean.TRUE : Boolean.FALSE;
}
/**
* Tells the modification time in milliseconds since 01.01.1970 (the "epoch").
*
* @return the modification time, if that is meaningful (e.g. for a file resource which exists); 0 if the resource
* does not exist, to mirror the behavior of {@link java.io.File#lastModified}; or 0 if the notion of modification
* time is meaningless for this class of resource (e.g. an inline string)
*/
public long getLastModified() {
// if (isReference()) {
// return ((Resource) getCheckedRef()).getLastModified();
// }
if (!isExists() || lastmodified == null) {
return UNKNOWN_DATETIME;
}
long result = lastmodified.longValue();
return result < UNKNOWN_DATETIME ? UNKNOWN_DATETIME : result;
}
/**
* Set the last modification attribute.
*
* @param lastmodified the modification time in milliseconds since 01.01.1970.
*/
public void setLastModified(long lastmodified) {
checkAttributesAllowed();
this.lastmodified = new Long(lastmodified);
}
/**
* Tells if the resource is a directory.
*
* @return boolean flag indicating if the resource is a directory.
*/
public boolean isDirectory() {
// if (isReference()) {
// return ((Resource) getCheckedRef()).isDirectory();
// }
//default false:
return directory != null && directory.booleanValue();
}
/**
* Set the directory attribute.
*
* @param directory if true, this resource is a directory.
*/
public void setDirectory(boolean directory) {
checkAttributesAllowed();
this.directory = directory ? Boolean.TRUE : Boolean.FALSE;
}
/**
* Set the size of this Resource.
*
* @param size the size, as a long.
* @since Ant 1.6.3
*/
public void setSize(long size) {
checkAttributesAllowed();
this.size = new Long(size > UNKNOWN_SIZE ? size : UNKNOWN_SIZE);
}
/**
* Get the size of this Resource.
*
* @return the size, as a long, 0 if the Resource does not exist (for compatibility with java.io.File), or
* UNKNOWN_SIZE if not known.
* @since Ant 1.6.3
*/
public long getSize() {
// if (isReference()) {
// return ((Resource) getCheckedRef()).getSize();
// }
return isExists()
? (size != null ? size.longValue() : UNKNOWN_SIZE)
: 0L;
}
/**
* Clone this Resource.
*
* @return copy of this.
*/
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new UnsupportedOperationException(
"CloneNotSupportedException for a Resource caught. "
+ "Derived classes must support cloning.");
}
}
/**
* Delegates to a comparison of names.
*
* @param other the object to compare to.
* @return a negative integer, zero, or a positive integer as this Resource is less than, equal to, or greater than
* the specified Resource.
* @since Ant 1.6
*/
public int compareTo(Resource other) {
// if (isReference()) {
// return ((Resource) getCheckedRef()).compareTo(other);
// }
return toString().compareTo(other.toString());
}
/**
* Implement basic Resource equality.
*
* @param other the object to check against.
* @return true if the specified Object is equal to this Resource.
* @since Ant 1.7
*/
public boolean equals(Object other) {
// if (isReference()) {
// return getCheckedRef().equals(other);
// }
return other != null && other.getClass().equals(getClass())
&& compareTo((Resource) other) == 0;
}
/**
* Get the hash code for this Resource.
*
* @return hash code as int.
* @since Ant 1.7
*/
public int hashCode() {
// if (isReference()) {
// return getCheckedRef().hashCode();
// }
String name = getName();
return MAGIC * (name == null ? NULL_NAME : name.hashCode());
}
/**
* Get an InputStream for the Resource.
*
* @return an InputStream containing this Resource's content.
* @throws IOException if unable to provide the content of this Resource as a stream.
* @throws UnsupportedOperationException if InputStreams are not supported for this Resource type.
* @since Ant 1.7
*/
public InputStream getInputStream() throws IOException {
// if (isReference()) {
// return ((Resource) getCheckedRef()).getInputStream();
// }
throw new UnsupportedOperationException();
}
/**
* Get an OutputStream for the Resource.
*
* @return an OutputStream to which content can be written.
* @throws IOException if unable to provide the content of this Resource as a stream.
* @throws UnsupportedOperationException if OutputStreams are not supported for this Resource type.
* @since Ant 1.7
*/
public OutputStream getOutputStream() throws IOException {
// if (isReference()) {
// return ((Resource) getCheckedRef()).getOutputStream();
// }
throw new UnsupportedOperationException();
}
/**
* Fulfill the ResourceCollection contract.
*
* @return an Iterator of Resources.
* @since Ant 1.7
*/
public Iterator<Resource> iterator() {
//return isReference() ? ((Resource) getCheckedRef()).iterator()
// : new Iterator<Resource>() {
return new Iterator<Resource>() {
private boolean done = false;
public boolean hasNext() {
return !done;
}
public Resource next() {
if (done) {
throw new NoSuchElementException();
}
done = true;
return Resource.this;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
/**
* Fulfill the ResourceCollection contract.
*
* @return the size of this ResourceCollection.
* @since Ant 1.7
*/
public int size() {
//return isReference() ? ((Resource) getCheckedRef()).size() : 1;
return 1;
}
/**
* Fulfill the ResourceCollection contract.
*
* @return whether this Resource is a FileProvider.
* @since Ant 1.7
*/
public boolean isFilesystemOnly() {
// return (isReference() && ((Resource) getCheckedRef()).isFilesystemOnly())
// || this.as(FileProvider.class) != null;
return this.as(FileProvider.class) != null;
}
/**
* Get the string representation of this Resource.
*
* @return this Resource formatted as a String.
* @since Ant 1.7
*/
public String toString() {
// if (isReference()) {
// return getCheckedRef().toString();
// }
String n = getName();
return n == null ? "(anonymous)" : n;
}
/**
* Get a long String representation of this Resource. This typically should be the value of <code>toString()</code>
* prefixed by a type description.
*
* @return this Resource formatted as a long String.
* @since Ant 1.7
*/
public final String toLongString() {
// return isReference() ? ((Resource) getCheckedRef()).toLongString()
// : getDataTypeName() + " \"" + toString() + '"';
return toString();
}
/**
* Overrides the base version.
*
* @param r the Reference to set.
*/
public void setRefid(Reference r) {
if (name != null
|| exists != null
|| lastmodified != null
|| directory != null
|| size != null) {
throw tooManyAttributes();
}
super.setRefid(r);
}
/**
* Returns a view of this resource that implements the interface given as the argument or null if there is no such
* view.
*
* <p>
* This allows extension interfaces to be added to resources without growing the number of permutations of
* interfaces decorators/adapters need to implement.</p>
*
* <p>
* This implementation of the method will return the current instance itself if it can be assigned to the given
* class.</p>
*
* @since Ant 1.8.0
*/
public <T> T as(Class<T> clazz) {
return clazz.isAssignableFrom(getClass()) ? clazz.cast(this) : null;
}
}

View File

@@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant.types;
import java.util.Iterator;
import org.owasp.dependencycheck.org.apache.tools.ant.types.resources.FileProvider;
/**
* Interface describing a collection of Resources.
* @since Ant 1.7
*/
public interface ResourceCollection extends Iterable<Resource> {
/**
* Gets the contents of this collection.
* @return all resources in the collection
*/
Iterator<Resource> iterator();
/**
* Learn the number of contained Resources.
* @return number of elements as int.
*/
int size();
/**
* Indicate whether this ResourceCollection is composed entirely of
* Resources accessible via local filesystem conventions. If true,
* all resources returned from this collection should
* respond with a {@link FileProvider} when asked via {@link Resource#as}.
* @return whether this is a filesystem-only resource collection.
*/
boolean isFilesystemOnly();
}

View File

@@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant.types;
/**
* this interface should be implemented by classes (Scanners) needing
* to deliver information about resources.
*
* @since Ant 1.5.2
*/
public interface ResourceFactory {
/**
* Query a resource (file, zipentry, ...) by name
*
* @param name relative path of the resource about which
* information is sought. Expects &quot;/&quot; to be used as the
* directory separator.
* @return instance of Resource; the exists attribute of Resource
* will tell whether the sought resource exists
*/
Resource getResource(String name);
}

View File

@@ -0,0 +1,14 @@
/**
* <html>
* <head>
* <title>org.owasp.dependencycheck.org.apache.tools.ant.types</title>
* </head>
* <body>
* This is a copy of classes within Apache Ant. The DirectoryScanner
* is needed by dependency-check. However, we did not want to make
* Ant a dependency. As such, a few files were copied and slightly
* modified to remove any references to the Ant Project class.
* </body>
* </html>
*/
package org.owasp.dependencycheck.org.apache.tools.ant.types;

View File

@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant.types.resources;
import java.io.IOException;
import java.io.OutputStream;
/**
* Interface to be implemented by "appendable" resources.
* @since Ant 1.8
*/
public interface Appendable {
/**
* Get an appending OutputStream.
* @return OutputStream
* @throws IOException if anything goes wrong
*/
OutputStream getAppendOutputStream() throws IOException;
}

View File

@@ -0,0 +1,36 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant.types.resources;
import java.io.File;
/**
* This is an interface that resources that can provide a file should implement.
* This is a refactoring of {@link FileResource}, to allow other resources
* to act as sources of files (and to make components that only support
* file-based resources from only support FileResource resources.
* @since Ant 1.8
*/
public interface FileProvider {
/**
* Get the file represented by this Resource.
* @return the file.
*/
File getFile();
}

View File

@@ -0,0 +1,414 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant.types.resources;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.owasp.dependencycheck.org.apache.tools.ant.BuildException;
import org.owasp.dependencycheck.org.apache.tools.ant.types.Reference;
import org.owasp.dependencycheck.org.apache.tools.ant.types.Resource;
import org.owasp.dependencycheck.org.apache.tools.ant.types.ResourceFactory;
import org.owasp.dependencycheck.org.apache.tools.ant.util.FileUtils;
/**
* A Resource representation of a File.
*
* @since Ant 1.7
*/
public class FileResource extends Resource implements Touchable, FileProvider,
ResourceFactory, Appendable {
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
private static final int NULL_FILE
= Resource.getMagicNumber("null file".getBytes());
private File file;
private File baseDir;
/**
* Default constructor.
*/
public FileResource() {
}
/**
* Construct a new FileResource using the specified basedir and relative name.
*
* @param b the basedir as File.
* @param name the relative filename.
*/
public FileResource(File b, String name) {
this.baseDir = b;
this.file = FILE_UTILS.resolveFile(b, name);
}
/**
* Construct a new FileResource from a File.
*
* @param f the File represented.
*/
public FileResource(File f) {
setFile(f);
}
// /**
// * Create a new FileResource.
// * @param p Project
// * @param f File represented
// * @since Ant 1.8
// */
// public FileResource(Project p, File f) {
// this(f);
// setProject(p);
// }
//
// /**
// * Constructor for Ant attribute introspection.
// * @param p the Project against which to resolve <code>s</code>.
// * @param s the absolute or Project-relative filename as a String.
// * @see org.apache.tools.ant.IntrospectionHelper
// */
// public FileResource(Project p, String s) {
// this(p, p.resolveFile(s));
// }
/**
* Set the File for this FileResource.
*
* @param f the File to be represented.
*/
public void setFile(File f) {
checkAttributesAllowed();
file = f;
if (f != null && (getBaseDir() == null || !FILE_UTILS.isLeadingPath(getBaseDir(), f))) {
setBaseDir(f.getParentFile());
}
}
/**
* Get the file represented by this FileResource.
*
* @return the File.
*/
public File getFile() {
// if (isReference()) {
// return ((FileResource) getCheckedRef()).getFile();
// }
// dieOnCircularReference();
synchronized (this) {
if (file == null) {
//try to resolve file set via basedir/name property setters:
File d = getBaseDir();
String n = super.getName();
if (n != null) {
setFile(FILE_UTILS.resolveFile(d, n));
}
}
}
return file;
}
/**
* Set the basedir for this FileResource.
*
* @param b the basedir as File.
*/
public void setBaseDir(File b) {
checkAttributesAllowed();
baseDir = b;
}
/**
* Return the basedir to which the name is relative.
*
* @return the basedir as File.
*/
public File getBaseDir() {
// if (isReference()) {
// return ((FileResource) getCheckedRef()).getBaseDir();
// }
// dieOnCircularReference();
return baseDir;
}
/**
* Overrides the super version.
*
* @param r the Reference to set.
*/
public void setRefid(Reference r) {
if (file != null || baseDir != null) {
throw tooManyAttributes();
}
super.setRefid(r);
}
/**
* Get the name of this FileResource. If the basedir is set, the name will be relative to that. Otherwise the
* basename only will be returned.
*
* @return the name of this resource.
*/
public String getName() {
// if (isReference()) {
// return ((Resource) getCheckedRef()).getName();
// }
File b = getBaseDir();
return b == null ? getNotNullFile().getName()
: FILE_UTILS.removeLeadingPath(b, getNotNullFile());
}
/**
* Learn whether this file exists.
*
* @return true if this resource exists.
*/
public boolean isExists() {
// return isReference() ? ((Resource) getCheckedRef()).isExists()
// : getNotNullFile().exists();
return getNotNullFile().exists();
}
/**
* Get the modification time in milliseconds since 01.01.1970 .
*
* @return 0 if the resource does not exist.
*/
public long getLastModified() {
// return isReference()
// ? ((Resource) getCheckedRef()).getLastModified()
// : getNotNullFile().lastModified();
return getNotNullFile().lastModified();
}
/**
* Learn whether the resource is a directory.
*
* @return boolean flag indicating if the resource is a directory.
*/
public boolean isDirectory() {
// return isReference() ? ((Resource) getCheckedRef()).isDirectory()
// : getNotNullFile().isDirectory();
return getNotNullFile().isDirectory();
}
/**
* Get the size of this Resource.
*
* @return the size, as a long, 0 if the Resource does not exist.
*/
public long getSize() {
// return isReference() ? ((Resource) getCheckedRef()).getSize()
// : getNotNullFile().length();
return getNotNullFile().length();
}
/**
* Return an InputStream for reading the contents of this Resource.
*
* @return an InputStream object.
* @throws IOException if an error occurs.
*/
public InputStream getInputStream() throws IOException {
// return isReference()
// ? ((Resource) getCheckedRef()).getInputStream()
// : new FileInputStream(getNotNullFile());
return new FileInputStream(getNotNullFile());
}
/**
* Get an OutputStream for the Resource.
*
* @return an OutputStream to which content can be written.
* @throws IOException if unable to provide the content of this Resource as a stream.
* @throws UnsupportedOperationException if OutputStreams are not supported for this Resource type.
*/
public OutputStream getOutputStream() throws IOException {
// if (isReference()) {
// return ((FileResource) getCheckedRef()).getOutputStream();
// }
return getOutputStream(false);
}
/**
* {@inheritDoc}
*/
public OutputStream getAppendOutputStream() throws IOException {
// if (isReference()) {
// return ((FileResource) getCheckedRef()).getAppendOutputStream();
// }
return getOutputStream(true);
}
private OutputStream getOutputStream(boolean append) throws IOException {
File f = getNotNullFile();
if (f.exists()) {
if (f.isFile() && !append) {
f.delete();
}
} else {
File p = f.getParentFile();
if (p != null && !(p.exists())) {
p.mkdirs();
}
}
return append ? new FileOutputStream(f.getAbsolutePath(), true) : new FileOutputStream(f);
}
/**
* Compare this FileResource to another Resource.
*
* @param another the other Resource against which to compare.
* @return a negative integer, zero, or a positive integer as this FileResource is less than, equal to, or greater
* than the specified Resource.
*/
public int compareTo(Resource another) {
// if (isReference()) {
// return ((Resource) getCheckedRef()).compareTo(another);
// }
if (this.equals(another)) {
return 0;
}
FileProvider otherFP = another.as(FileProvider.class);
if (otherFP != null) {
File f = getFile();
if (f == null) {
return -1;
}
File of = otherFP.getFile();
if (of == null) {
return 1;
}
return f.compareTo(of);
}
return super.compareTo(another);
}
/**
* Compare another Object to this FileResource for equality.
*
* @param another the other Object to compare.
* @return true if another is a FileResource representing the same file.
*/
public boolean equals(Object another) {
if (this == another) {
return true;
}
// if (isReference()) {
// return getCheckedRef().equals(another);
// }
if (another == null || !(another.getClass().equals(getClass()))) {
return false;
}
FileResource otherfr = (FileResource) another;
return getFile() == null
? otherfr.getFile() == null
: getFile().equals(otherfr.getFile());
}
/**
* Get the hash code for this Resource.
*
* @return hash code as int.
*/
public int hashCode() {
// if (isReference()) {
// return getCheckedRef().hashCode();
// }
return MAGIC * (getFile() == null ? NULL_FILE : getFile().hashCode());
}
/**
* Get the string representation of this Resource.
*
* @return this FileResource formatted as a String.
*/
public String toString() {
// if (isReference()) {
// return getCheckedRef().toString();
// }
if (file == null) {
return "(unbound file resource)";
}
String absolutePath = file.getAbsolutePath();
return FILE_UTILS.normalize(absolutePath).getAbsolutePath();
}
/**
* Fulfill the ResourceCollection contract.
*
* @return whether this Resource is a FileResource.
*/
public boolean isFilesystemOnly() {
// if (isReference()) {
// return ((FileResource) getCheckedRef()).isFilesystemOnly();
// }
// dieOnCircularReference();
return true;
}
/**
* Implement the Touchable interface.
*
* @param modTime new last modification time.
*/
public void touch(long modTime) {
// if (isReference()) {
// ((FileResource) getCheckedRef()).touch(modTime);
// return;
// }
if (!getNotNullFile().setLastModified(modTime)) {
//log("Failed to change file modification time", Project.MSG_WARN);
}
}
/**
* Get the file represented by this FileResource, ensuring it is not null.
*
* @return the not-null File.
* @throws BuildException if file is null.
*/
protected File getNotNullFile() {
if (getFile() == null) {
throw new BuildException("file attribute is null!");
}
// dieOnCircularReference();
return getFile();
}
/**
* Create a new resource that matches a relative or absolute path. If the current instance has a compatible baseDir
* attribute, it is copied.
*
* @param path relative/absolute path to a resource
* @return a new resource of type FileResource
* @throws BuildException if desired
* @since Ant1.8
*/
public Resource getResource(String path) {
File newfile = FILE_UTILS.resolveFile(getFile(), path);
FileResource fileResource = new FileResource(newfile);
if (FILE_UTILS.isLeadingPath(getBaseDir(), newfile)) {
fileResource.setBaseDir(getBaseDir());
}
return fileResource;
}
}

View File

@@ -0,0 +1,32 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant.types.resources;
/**
* Interface to be implemented by "touchable" resources;
* that is, those whose modification time can be altered.
* @since Ant 1.7
*/
public interface Touchable {
/**
* Method called to "touch" the resource.
* @param modTime the time to set the modified "field" of the resource,
* measured in milliseconds since the epoch.
*/
void touch(long modTime);
}

View File

@@ -0,0 +1,14 @@
/**
* <html>
* <head>
* <title>org.owasp.dependencycheck.org.apache.tools.ant.types.resources</title>
* </head>
* <body>
* This is a copy of classes within Apache Ant. The DirectoryScanner
* is needed by dependency-check. However, we did not want to make
* Ant a dependency. As such, a few files were copied and slightly
* modified to remove any references to the Ant Project class.
* </body>
* </html>
*/
package org.owasp.dependencycheck.org.apache.tools.ant.types.resources;

View File

@@ -0,0 +1,48 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant.types.selectors;
import java.io.File;
import org.owasp.dependencycheck.org.apache.tools.ant.BuildException;
/**
* This is the interface to be used by all selectors.
*
* @since 1.5
*/
public interface FileSelector {
/**
* Method that each selector will implement to create their
* selection behaviour. If there is a problem with the setup
* of a selector, it can throw a BuildException to indicate
* the problem.
*
* @param basedir A java.io.File object for the base directory
* @param filename The name of the file to check
* @param file A File object for this filename
* @return whether the file should be selected or not
* @exception BuildException if the selector was not configured correctly
*/
boolean isSelected(File basedir, String filename, File file)
throws BuildException;
}

View File

@@ -0,0 +1,49 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant.types.selectors;
/**
* An interface used to describe the actions required by any type of
* directory scanner that supports Selectors.
*
* @since 1.5
*/
public interface SelectorScanner {
/**
* Sets the selectors the scanner should use.
*
* @param selectors the list of selectors
*/
void setSelectors(FileSelector[] selectors);
/**
* Directories which were selected out of a scan.
*
* @return list of directories not selected
*/
String[] getDeselectedDirectories();
/**
* Files which were selected out of a scan.
*
* @return list of files not selected
*/
String[] getDeselectedFiles();
}

View File

@@ -0,0 +1,695 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant.types.selectors;
import java.io.File;
import java.util.StringTokenizer;
import java.util.Vector;
import org.owasp.dependencycheck.org.apache.tools.ant.types.Resource;
import org.owasp.dependencycheck.org.apache.tools.ant.util.FileUtils;
/**
* <p>This is a utility class used by selectors and DirectoryScanner. The
* functionality more properly belongs just to selectors, but unfortunately
* DirectoryScanner exposed these as protected methods. Thus we have to
* support any subclasses of DirectoryScanner that may access these methods.
* </p>
* <p>This is a Singleton.</p>
*
* @since 1.5
*/
public final class SelectorUtils {
/**
* The pattern that matches an arbitrary number of directories.
* @since Ant 1.8.0
*/
public static final String DEEP_TREE_MATCH = "**";
private static final SelectorUtils instance = new SelectorUtils();
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
/**
* Private Constructor
*/
private SelectorUtils() {
}
/**
* Retrieves the instance of the Singleton.
* @return singleton instance
*/
public static SelectorUtils getInstance() {
return instance;
}
/**
* Tests whether or not a given path matches the start of a given
* pattern up to the first "**".
* <p>
* This is not a general purpose test and should only be used if you
* can live with false positives. For example, <code>pattern=**\a</code>
* and <code>str=b</code> will yield <code>true</code>.
*
* @param pattern The pattern to match against. Must not be
* <code>null</code>.
* @param str The path to match, as a String. Must not be
* <code>null</code>.
*
* @return whether or not a given path matches the start of a given
* pattern up to the first "**".
*/
public static boolean matchPatternStart(String pattern, String str) {
return matchPatternStart(pattern, str, true);
}
/**
* Tests whether or not a given path matches the start of a given
* pattern up to the first "**".
* <p>
* This is not a general purpose test and should only be used if you
* can live with false positives. For example, <code>pattern=**\a</code>
* and <code>str=b</code> will yield <code>true</code>.
*
* @param pattern The pattern to match against. Must not be
* <code>null</code>.
* @param str The path to match, as a String. Must not be
* <code>null</code>.
* @param isCaseSensitive Whether or not matching should be performed
* case sensitively.
*
* @return whether or not a given path matches the start of a given
* pattern up to the first "**".
*/
public static boolean matchPatternStart(String pattern, String str,
boolean isCaseSensitive) {
// When str starts with a File.separator, pattern has to start with a
// File.separator.
// When pattern starts with a File.separator, str has to start with a
// File.separator.
if (str.startsWith(File.separator)
!= pattern.startsWith(File.separator)) {
return false;
}
String[] patDirs = tokenizePathAsArray(pattern);
String[] strDirs = tokenizePathAsArray(str);
return matchPatternStart(patDirs, strDirs, isCaseSensitive);
}
/**
* Tests whether or not a given path matches the start of a given
* pattern up to the first "**".
* <p>
* This is not a general purpose test and should only be used if you
* can live with false positives. For example, <code>pattern=**\a</code>
* and <code>str=b</code> will yield <code>true</code>.
*
* @param patDirs The tokenized pattern to match against. Must not be
* <code>null</code>.
* @param strDirs The tokenized path to match. Must not be
* <code>null</code>.
* @param isCaseSensitive Whether or not matching should be performed
* case sensitively.
*
* @return whether or not a given path matches the start of a given
* pattern up to the first "**".
*/
static boolean matchPatternStart(String[] patDirs, String[] strDirs,
boolean isCaseSensitive) {
int patIdxStart = 0;
int patIdxEnd = patDirs.length - 1;
int strIdxStart = 0;
int strIdxEnd = strDirs.length - 1;
// up to first '**'
while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
String patDir = patDirs[patIdxStart];
if (patDir.equals(DEEP_TREE_MATCH)) {
break;
}
if (!match(patDir, strDirs[strIdxStart], isCaseSensitive)) {
return false;
}
patIdxStart++;
strIdxStart++;
}
// CheckStyle:SimplifyBooleanReturnCheck OFF
// Check turned off as the code needs the comments for the various
// code paths.
if (strIdxStart > strIdxEnd) {
// String is exhausted
return true;
} else if (patIdxStart > patIdxEnd) {
// String not exhausted, but pattern is. Failure.
return false;
} else {
// pattern now holds ** while string is not exhausted
// this will generate false positives but we can live with that.
return true;
}
}
/**
* Tests whether or not a given path matches a given pattern.
*
* If you need to call this method multiple times with the same
* pattern you should rather use TokenizedPath
*
* @see TokenizedPath
*
* @param pattern The pattern to match against. Must not be
* <code>null</code>.
* @param str The path to match, as a String. Must not be
* <code>null</code>.
*
* @return <code>true</code> if the pattern matches against the string,
* or <code>false</code> otherwise.
*/
public static boolean matchPath(String pattern, String str) {
String[] patDirs = tokenizePathAsArray(pattern);
return matchPath(patDirs, tokenizePathAsArray(str), true);
}
/**
* Tests whether or not a given path matches a given pattern.
*
* If you need to call this method multiple times with the same
* pattern you should rather use TokenizedPattern
*
* @see TokenizedPattern
*
* @param pattern The pattern to match against. Must not be
* <code>null</code>.
* @param str The path to match, as a String. Must not be
* <code>null</code>.
* @param isCaseSensitive Whether or not matching should be performed
* case sensitively.
*
* @return <code>true</code> if the pattern matches against the string,
* or <code>false</code> otherwise.
*/
public static boolean matchPath(String pattern, String str,
boolean isCaseSensitive) {
String[] patDirs = tokenizePathAsArray(pattern);
return matchPath(patDirs, tokenizePathAsArray(str), isCaseSensitive);
}
/**
* Core implementation of matchPath. It is isolated so that it
* can be called from TokenizedPattern.
*/
static boolean matchPath(String[] tokenizedPattern, String[] strDirs,
boolean isCaseSensitive) {
int patIdxStart = 0;
int patIdxEnd = tokenizedPattern.length - 1;
int strIdxStart = 0;
int strIdxEnd = strDirs.length - 1;
// up to first '**'
while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
String patDir = tokenizedPattern[patIdxStart];
if (patDir.equals(DEEP_TREE_MATCH)) {
break;
}
if (!match(patDir, strDirs[strIdxStart], isCaseSensitive)) {
return false;
}
patIdxStart++;
strIdxStart++;
}
if (strIdxStart > strIdxEnd) {
// String is exhausted
for (int i = patIdxStart; i <= patIdxEnd; i++) {
if (!tokenizedPattern[i].equals(DEEP_TREE_MATCH)) {
return false;
}
}
return true;
} else {
if (patIdxStart > patIdxEnd) {
// String not exhausted, but pattern is. Failure.
return false;
}
}
// up to last '**'
while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
String patDir = tokenizedPattern[patIdxEnd];
if (patDir.equals(DEEP_TREE_MATCH)) {
break;
}
if (!match(patDir, strDirs[strIdxEnd], isCaseSensitive)) {
return false;
}
patIdxEnd--;
strIdxEnd--;
}
if (strIdxStart > strIdxEnd) {
// String is exhausted
for (int i = patIdxStart; i <= patIdxEnd; i++) {
if (!tokenizedPattern[i].equals(DEEP_TREE_MATCH)) {
return false;
}
}
return true;
}
while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
int patIdxTmp = -1;
for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
if (tokenizedPattern[i].equals(DEEP_TREE_MATCH)) {
patIdxTmp = i;
break;
}
}
if (patIdxTmp == patIdxStart + 1) {
// '**/**' situation, so skip one
patIdxStart++;
continue;
}
// Find the pattern between padIdxStart & padIdxTmp in str between
// strIdxStart & strIdxEnd
int patLength = (patIdxTmp - patIdxStart - 1);
int strLength = (strIdxEnd - strIdxStart + 1);
int foundIdx = -1;
strLoop:
for (int i = 0; i <= strLength - patLength; i++) {
for (int j = 0; j < patLength; j++) {
String subPat = tokenizedPattern[patIdxStart + j + 1];
String subStr = strDirs[strIdxStart + i + j];
if (!match(subPat, subStr, isCaseSensitive)) {
continue strLoop;
}
}
foundIdx = strIdxStart + i;
break;
}
if (foundIdx == -1) {
return false;
}
patIdxStart = patIdxTmp;
strIdxStart = foundIdx + patLength;
}
for (int i = patIdxStart; i <= patIdxEnd; i++) {
if (!tokenizedPattern[i].equals(DEEP_TREE_MATCH)) {
return false;
}
}
return true;
}
/**
* Tests whether or not a string matches against a pattern.
* The pattern may contain two special characters:<br>
* '*' means zero or more characters<br>
* '?' means one and only one character
*
* @param pattern The pattern to match against.
* Must not be <code>null</code>.
* @param str The string which must be matched against the pattern.
* Must not be <code>null</code>.
*
* @return <code>true</code> if the string matches against the pattern,
* or <code>false</code> otherwise.
*/
public static boolean match(String pattern, String str) {
return match(pattern, str, true);
}
/**
* Tests whether or not a string matches against a pattern.
* The pattern may contain two special characters:<br>
* '*' means zero or more characters<br>
* '?' means one and only one character
*
* @param pattern The pattern to match against.
* Must not be <code>null</code>.
* @param str The string which must be matched against the pattern.
* Must not be <code>null</code>.
* @param caseSensitive Whether or not matching should be performed
* case sensitively.
*
*
* @return <code>true</code> if the string matches against the pattern,
* or <code>false</code> otherwise.
*/
public static boolean match(String pattern, String str,
boolean caseSensitive) {
char[] patArr = pattern.toCharArray();
char[] strArr = str.toCharArray();
int patIdxStart = 0;
int patIdxEnd = patArr.length - 1;
int strIdxStart = 0;
int strIdxEnd = strArr.length - 1;
char ch;
boolean containsStar = false;
for (int i = 0; i < patArr.length; i++) {
if (patArr[i] == '*') {
containsStar = true;
break;
}
}
if (!containsStar) {
// No '*'s, so we make a shortcut
if (patIdxEnd != strIdxEnd) {
return false; // Pattern and string do not have the same size
}
for (int i = 0; i <= patIdxEnd; i++) {
ch = patArr[i];
if (ch != '?') {
if (different(caseSensitive, ch, strArr[i])) {
return false; // Character mismatch
}
}
}
return true; // String matches against pattern
}
if (patIdxEnd == 0) {
return true; // Pattern contains only '*', which matches anything
}
// Process characters before first star
while (true) {
ch = patArr[patIdxStart];
if (ch == '*' || strIdxStart > strIdxEnd) {
break;
}
if (ch != '?') {
if (different(caseSensitive, ch, strArr[strIdxStart])) {
return false; // Character mismatch
}
}
patIdxStart++;
strIdxStart++;
}
if (strIdxStart > strIdxEnd) {
// All characters in the string are used. Check if only '*'s are
// left in the pattern. If so, we succeeded. Otherwise failure.
return allStars(patArr, patIdxStart, patIdxEnd);
}
// Process characters after last star
while (true) {
ch = patArr[patIdxEnd];
if (ch == '*' || strIdxStart > strIdxEnd) {
break;
}
if (ch != '?') {
if (different(caseSensitive, ch, strArr[strIdxEnd])) {
return false; // Character mismatch
}
}
patIdxEnd--;
strIdxEnd--;
}
if (strIdxStart > strIdxEnd) {
// All characters in the string are used. Check if only '*'s are
// left in the pattern. If so, we succeeded. Otherwise failure.
return allStars(patArr, patIdxStart, patIdxEnd);
}
// process pattern between stars. padIdxStart and patIdxEnd point
// always to a '*'.
while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
int patIdxTmp = -1;
for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
if (patArr[i] == '*') {
patIdxTmp = i;
break;
}
}
if (patIdxTmp == patIdxStart + 1) {
// Two stars next to each other, skip the first one.
patIdxStart++;
continue;
}
// Find the pattern between padIdxStart & padIdxTmp in str between
// strIdxStart & strIdxEnd
int patLength = (patIdxTmp - patIdxStart - 1);
int strLength = (strIdxEnd - strIdxStart + 1);
int foundIdx = -1;
strLoop:
for (int i = 0; i <= strLength - patLength; i++) {
for (int j = 0; j < patLength; j++) {
ch = patArr[patIdxStart + j + 1];
if (ch != '?') {
if (different(caseSensitive, ch,
strArr[strIdxStart + i + j])) {
continue strLoop;
}
}
}
foundIdx = strIdxStart + i;
break;
}
if (foundIdx == -1) {
return false;
}
patIdxStart = patIdxTmp;
strIdxStart = foundIdx + patLength;
}
// All characters in the string are used. Check if only '*'s are left
// in the pattern. If so, we succeeded. Otherwise failure.
return allStars(patArr, patIdxStart, patIdxEnd);
}
private static boolean allStars(char[] chars, int start, int end) {
for (int i = start; i <= end; ++i) {
if (chars[i] != '*') {
return false;
}
}
return true;
}
private static boolean different(
boolean caseSensitive, char ch, char other) {
return caseSensitive
? ch != other
: Character.toUpperCase(ch) != Character.toUpperCase(other);
}
/**
* Breaks a path up into a Vector of path elements, tokenizing on
* <code>File.separator</code>.
*
* @param path Path to tokenize. Must not be <code>null</code>.
*
* @return a Vector of path elements from the tokenized path
*/
public static Vector<String> tokenizePath(String path) {
return tokenizePath(path, File.separator);
}
/**
* Breaks a path up into a Vector of path elements, tokenizing on
*
* @param path Path to tokenize. Must not be <code>null</code>.
* @param separator the separator against which to tokenize.
*
* @return a Vector of path elements from the tokenized path
* @since Ant 1.6
*/
public static Vector<String> tokenizePath(String path, String separator) {
Vector<String> ret = new Vector<String>();
if (FileUtils.isAbsolutePath(path)) {
String[] s = FILE_UTILS.dissect(path);
ret.add(s[0]);
path = s[1];
}
StringTokenizer st = new StringTokenizer(path, separator);
while (st.hasMoreTokens()) {
ret.addElement(st.nextToken());
}
return ret;
}
/**
* Same as {@link #tokenizePath tokenizePath} but hopefully faster.
*/
/*package*/ static String[] tokenizePathAsArray(String path) {
String root = null;
if (FileUtils.isAbsolutePath(path)) {
String[] s = FILE_UTILS.dissect(path);
root = s[0];
path = s[1];
}
char sep = File.separatorChar;
int start = 0;
int len = path.length();
int count = 0;
for (int pos = 0; pos < len; pos++) {
if (path.charAt(pos) == sep) {
if (pos != start) {
count++;
}
start = pos + 1;
}
}
if (len != start) {
count++;
}
String[] l = new String[count + ((root == null) ? 0 : 1)];
if (root != null) {
l[0] = root;
count = 1;
} else {
count = 0;
}
start = 0;
for (int pos = 0; pos < len; pos++) {
if (path.charAt(pos) == sep) {
if (pos != start) {
String tok = path.substring(start, pos);
l[count++] = tok;
}
start = pos + 1;
}
}
if (len != start) {
String tok = path.substring(start);
l[count/*++*/] = tok;
}
return l;
}
/**
* Returns dependency information on these two files. If src has been
* modified later than target, it returns true. If target doesn't exist,
* it likewise returns true. Otherwise, target is newer than src and
* is not out of date, thus the method returns false. It also returns
* false if the src file doesn't even exist, since how could the
* target then be out of date.
*
* @param src the original file
* @param target the file being compared against
* @param granularity the amount in seconds of slack we will give in
* determining out of dateness
* @return whether the target is out of date
*/
public static boolean isOutOfDate(File src, File target, int granularity) {
if (!src.exists()) {
return false;
}
if (!target.exists()) {
return true;
}
if ((src.lastModified() - granularity) > target.lastModified()) {
return true;
}
return false;
}
/**
* Returns dependency information on these two resources. If src has been
* modified later than target, it returns true. If target doesn't exist,
* it likewise returns true. Otherwise, target is newer than src and
* is not out of date, thus the method returns false. It also returns
* false if the src file doesn't even exist, since how could the
* target then be out of date.
*
* @param src the original resource
* @param target the resource being compared against
* @param granularity the int amount in seconds of slack we will give in
* determining out of dateness
* @return whether the target is out of date
*/
public static boolean isOutOfDate(Resource src, Resource target,
int granularity) {
return isOutOfDate(src, target, (long) granularity);
}
/**
* Returns dependency information on these two resources. If src has been
* modified later than target, it returns true. If target doesn't exist,
* it likewise returns true. Otherwise, target is newer than src and
* is not out of date, thus the method returns false. It also returns
* false if the src file doesn't even exist, since how could the
* target then be out of date.
*
* @param src the original resource
* @param target the resource being compared against
* @param granularity the long amount in seconds of slack we will give in
* determining out of dateness
* @return whether the target is out of date
*/
public static boolean isOutOfDate(Resource src, Resource target, long granularity) {
long sourceLastModified = src.getLastModified();
long targetLastModified = target.getLastModified();
return src.isExists()
&& (sourceLastModified == Resource.UNKNOWN_DATETIME
|| targetLastModified == Resource.UNKNOWN_DATETIME
|| (sourceLastModified - granularity) > targetLastModified);
}
/**
* "Flattens" a string by removing all whitespace (space, tab, linefeed,
* carriage return, and formfeed). This uses StringTokenizer and the
* default set of tokens as documented in the single argument constructor.
*
* @param input a String to remove all whitespace.
* @return a String that has had all whitespace removed.
*/
public static String removeWhitespace(String input) {
StringBuffer result = new StringBuffer();
if (input != null) {
StringTokenizer st = new StringTokenizer(input);
while (st.hasMoreTokens()) {
result.append(st.nextToken());
}
}
return result.toString();
}
/**
* Tests if a string contains stars or question marks
* @param input a String which one wants to test for containing wildcard
* @return true if the string contains at least a star or a question mark
*/
public static boolean hasWildcards(String input) {
return (input.indexOf('*') != -1 || input.indexOf('?') != -1);
}
/**
* removes from a pattern all tokens to the right containing wildcards
* @param input the input string
* @return the leftmost part of the pattern without wildcards
*/
public static String rtrimWildcardTokens(String input) {
return new TokenizedPattern(input).rtrimWildcardTokens().toString();
}
}

View File

@@ -0,0 +1,219 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant.types.selectors;
import java.io.File;
import org.owasp.dependencycheck.org.apache.tools.ant.BuildException;
import org.owasp.dependencycheck.org.apache.tools.ant.util.FileUtils;
import org.owasp.dependencycheck.org.apache.tools.ant.util.SymbolicLinkUtils;
/**
* Container for a path that has been split into its components.
* @since 1.8.0
*/
public class TokenizedPath {
/**
* Instance that holds no tokens at all.
*/
public static final TokenizedPath EMPTY_PATH =
new TokenizedPath("", new String[0]);
/** Helper. */
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
/** Helper. */
private static final SymbolicLinkUtils SYMLINK_UTILS =
SymbolicLinkUtils.getSymbolicLinkUtils();
/** iterations for case-sensitive scanning. */
private static final boolean[] CS_SCAN_ONLY = new boolean[] {true};
/** iterations for non-case-sensitive scanning. */
private static final boolean[] CS_THEN_NON_CS = new boolean[] {true, false};
private final String path;
private final String[] tokenizedPath;
/**
* Initialize the TokenizedPath by parsing it.
* @param path The path to tokenize. Must not be
* <code>null</code>.
*/
public TokenizedPath(String path) {
this(path, SelectorUtils.tokenizePathAsArray(path));
}
/**
* Creates a new path as a child of another path.
*
* @param parent the parent path
* @param child the child, must not contain the file separator
*/
public TokenizedPath(TokenizedPath parent, String child) {
if (parent.path.length() > 0
&& parent.path.charAt(parent.path.length() - 1)
!= File.separatorChar) {
path = parent.path + File.separatorChar + child;
} else {
path = parent.path + child;
}
tokenizedPath = new String[parent.tokenizedPath.length + 1];
System.arraycopy(parent.tokenizedPath, 0, tokenizedPath, 0,
parent.tokenizedPath.length);
tokenizedPath[parent.tokenizedPath.length] = child;
}
/* package */ TokenizedPath(String path, String[] tokens) {
this.path = path;
this.tokenizedPath = tokens;
}
/**
* @return The original path String
*/
public String toString() {
return path;
}
/**
* The depth (or length) of a path.
*/
public int depth() {
return tokenizedPath.length;
}
/* package */ String[] getTokens() {
return tokenizedPath;
}
/**
* From <code>base</code> traverse the filesystem in order to find
* a file that matches the given name.
*
* @param base base File (dir).
* @param cs whether to scan case-sensitively.
* @return File object that points to the file in question or null.
*/
public File findFile(File base, final boolean cs) {
String[] tokens = tokenizedPath;
if (FileUtils.isAbsolutePath(path)) {
if (base == null) {
String[] s = FILE_UTILS.dissect(path);
base = new File(s[0]);
tokens = SelectorUtils.tokenizePathAsArray(s[1]);
} else {
File f = FILE_UTILS.normalize(path);
String s = FILE_UTILS.removeLeadingPath(base, f);
if (s.equals(f.getAbsolutePath())) {
//removing base from path yields no change; path
//not child of base
return null;
}
tokens = SelectorUtils.tokenizePathAsArray(s);
}
}
return findFile(base, tokens, cs);
}
/**
* Do we have to traverse a symlink when trying to reach path from
* basedir?
* @param base base File (dir).
*/
public boolean isSymlink(File base) {
for (int i = 0; i < tokenizedPath.length; i++) {
try {
if ((base != null
&& SYMLINK_UTILS.isSymbolicLink(base, tokenizedPath[i]))
||
(base == null
&& SYMLINK_UTILS.isSymbolicLink(tokenizedPath[i]))
) {
return true;
}
base = new File(base, tokenizedPath[i]);
} catch (java.io.IOException ioe) {
String msg = "IOException caught while checking "
+ "for links, couldn't get canonical path!";
// will be caught and redirected to Ant's logging system
System.err.println(msg);
}
}
return false;
}
/**
* true if the original paths are equal.
*/
public boolean equals(Object o) {
return o instanceof TokenizedPath
&& path.equals(((TokenizedPath) o).path);
}
public int hashCode() {
return path.hashCode();
}
/**
* From <code>base</code> traverse the filesystem in order to find
* a file that matches the given stack of names.
*
* @param base base File (dir) - must not be null.
* @param pathElements array of path elements (dirs...file).
* @param cs whether to scan case-sensitively.
* @return File object that points to the file in question or null.
*/
private static File findFile(File base, final String[] pathElements,
final boolean cs) {
for (int current = 0; current < pathElements.length; current++) {
if (!base.isDirectory()) {
return null;
}
String[] files = base.list();
if (files == null) {
throw new BuildException("IO error scanning directory "
+ base.getAbsolutePath());
}
boolean found = false;
boolean[] matchCase = cs ? CS_SCAN_ONLY : CS_THEN_NON_CS;
for (int i = 0; !found && i < matchCase.length; i++) {
for (int j = 0; !found && j < files.length; j++) {
if (matchCase[i]
? files[j].equals(pathElements[current])
: files[j].equalsIgnoreCase(pathElements[current])) {
base = new File(base, files[j]);
found = true;
}
}
}
if (!found) {
return null;
}
}
return pathElements.length == 0 && !base.isDirectory() ? null : base;
}
/**
* Creates a TokenizedPattern from the same tokens that make up
* this path.
*/
public TokenizedPattern toPattern() {
return new TokenizedPattern(path, tokenizedPath);
}
}

View File

@@ -0,0 +1,177 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant.types.selectors;
import java.io.File;
/**
* Provides reusable path pattern matching. PathPattern is preferable
* to equivalent SelectorUtils methods if you need to execute multiple
* matching with the same pattern because here the pattern itself will
* be parsed only once.
* @see SelectorUtils#matchPath(String, String)
* @see SelectorUtils#matchPath(String, String, boolean)
* @since 1.8.0
*/
public class TokenizedPattern {
/**
* Instance that holds no tokens at all.
*/
public static final TokenizedPattern EMPTY_PATTERN =
new TokenizedPattern("", new String[0]);
private final String pattern;
private final String[] tokenizedPattern;
/**
* Initialize the PathPattern by parsing it.
* @param pattern The pattern to match against. Must not be
* <code>null</code>.
*/
public TokenizedPattern(String pattern) {
this(pattern, SelectorUtils.tokenizePathAsArray(pattern));
}
TokenizedPattern(String pattern, String[] tokens) {
this.pattern = pattern;
this.tokenizedPattern = tokens;
}
/**
* Tests whether or not a given path matches a given pattern.
*
* @param path The path to match, as a String. Must not be
* <code>null</code>.
* @param isCaseSensitive Whether or not matching should be performed
* case sensitively.
*
* @return <code>true</code> if the pattern matches against the string,
* or <code>false</code> otherwise.
*/
public boolean matchPath(TokenizedPath path, boolean isCaseSensitive) {
return SelectorUtils.matchPath(tokenizedPattern, path.getTokens(),
isCaseSensitive);
}
/**
* Tests whether or not this pattern matches the start of
* a path.
*/
public boolean matchStartOf(TokenizedPath path,
boolean caseSensitive) {
return SelectorUtils.matchPatternStart(tokenizedPattern,
path.getTokens(), caseSensitive);
}
/**
* @return The pattern String
*/
public String toString() {
return pattern;
}
public String getPattern() {
return pattern;
}
/**
* true if the original patterns are equal.
*/
public boolean equals(Object o) {
return o instanceof TokenizedPattern
&& pattern.equals(((TokenizedPattern) o).pattern);
}
public int hashCode() {
return pattern.hashCode();
}
/**
* The depth (or length) of a pattern.
*/
public int depth() {
return tokenizedPattern.length;
}
/**
* Does the tokenized pattern contain the given string?
*/
public boolean containsPattern(String pat) {
for (int i = 0; i < tokenizedPattern.length; i++) {
if (tokenizedPattern[i].equals(pat)) {
return true;
}
}
return false;
}
/**
* Returns a new TokenizedPath where all tokens of this pattern to
* the right containing wildcards have been removed
* @return the leftmost part of the pattern without wildcards
*/
public TokenizedPath rtrimWildcardTokens() {
StringBuilder sb = new StringBuilder();
int newLen = 0;
for (; newLen < tokenizedPattern.length; newLen++) {
if (SelectorUtils.hasWildcards(tokenizedPattern[newLen])) {
break;
}
if (newLen > 0
&& sb.charAt(sb.length() - 1) != File.separatorChar) {
sb.append(File.separator);
}
sb.append(tokenizedPattern[newLen]);
}
if (newLen == 0) {
return TokenizedPath.EMPTY_PATH;
}
String[] newPats = new String[newLen];
System.arraycopy(tokenizedPattern, 0, newPats, 0, newLen);
return new TokenizedPath(sb.toString(), newPats);
}
/**
* true if the last token equals the given string.
*/
public boolean endsWith(String s) {
return tokenizedPattern.length > 0
&& tokenizedPattern[tokenizedPattern.length - 1].equals(s);
}
/**
* Returns a new pattern without the last token of this pattern.
*/
public TokenizedPattern withoutLastToken() {
if (tokenizedPattern.length == 0) {
throw new IllegalStateException("cant strip a token from nothing");
} else if (tokenizedPattern.length == 1) {
return EMPTY_PATTERN;
} else {
String toStrip = tokenizedPattern[tokenizedPattern.length - 1];
int index = pattern.lastIndexOf(toStrip);
String[] tokens = new String[tokenizedPattern.length - 1];
System.arraycopy(tokenizedPattern, 0, tokens, 0,
tokenizedPattern.length - 1);
return new TokenizedPattern(pattern.substring(0, index), tokens);
}
}
}

View File

@@ -0,0 +1,14 @@
/**
* <html>
* <head>
* <title>org.owasp.dependencycheck.org.apache.tools.ant.types.selectors</title>
* </head>
* <body>
* This is a copy of classes within Apache Ant. The DirectoryScanner
* is needed by dependency-check. However, we did not want to make
* Ant a dependency. As such, a few files were copied and slightly
* modified to remove any references to the Ant Project class.
* </body>
* </html>
*/
package org.owasp.dependencycheck.org.apache.tools.ant.types.selectors;

View File

@@ -0,0 +1,265 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.owasp.dependencycheck.org.apache.tools.ant.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Vector;
// CheckStyle:HideUtilityClassConstructorCheck OFF - bc
/**
* A set of helper methods related to collection manipulation.
*
* @since Ant 1.5
*/
public class CollectionUtils {
/**
* Collections.emptyList() is Java5+.
*/
@SuppressWarnings("rawtypes")
@Deprecated
public static final List EMPTY_LIST = Collections.EMPTY_LIST;
/**
* Please use Vector.equals() or List.equals().
* @param v1 the first vector.
* @param v2 the second vector.
* @return true if the vectors are equal.
* @since Ant 1.5
* @deprecated since 1.6.x.
*/
public static boolean equals(Vector<?> v1, Vector<?> v2) {
if (v1 == v2) {
return true;
}
if (v1 == null || v2 == null) {
return false;
}
return v1.equals(v2);
}
/**
* Dictionary does not have an equals.
* Please use Map.equals().
*
* <p>Follows the equals contract of Java 2's Map.</p>
* @param d1 the first directory.
* @param d2 the second directory.
* @return true if the directories are equal.
* @since Ant 1.5
* @deprecated since 1.6.x.
*/
public static boolean equals(Dictionary<?, ?> d1, Dictionary<?, ?> d2) {
if (d1 == d2) {
return true;
}
if (d1 == null || d2 == null) {
return false;
}
if (d1.size() != d2.size()) {
return false;
}
Enumeration<?> e1 = d1.keys();
while (e1.hasMoreElements()) {
Object key = e1.nextElement();
Object value1 = d1.get(key);
Object value2 = d2.get(key);
if (value2 == null || !value1.equals(value2)) {
return false;
}
}
// don't need the opposite check as the Dictionaries have the
// same size, so we've also covered all keys of d2 already.
return true;
}
/**
* Creates a comma separated list of all values held in the given
* collection.
*
* @since Ant 1.8.0
*/
public static String flattenToString(Collection<?> c) {
final StringBuilder sb = new StringBuilder();
for (Object o : c) {
if (sb.length() != 0) {
sb.append(",");
}
sb.append(o);
}
return sb.toString();
}
/**
* Dictionary does not know the putAll method. Please use Map.putAll().
* @param m1 the to directory.
* @param m2 the from directory.
* @since Ant 1.6
* @deprecated since 1.6.x.
*/
public static <K, V> void putAll(Dictionary<? super K, ? super V> m1, Dictionary<? extends K, ? extends V> m2) {
for (Enumeration<? extends K> it = m2.keys(); it.hasMoreElements();) {
K key = it.nextElement();
m1.put(key, m2.get(key));
}
}
/**
* An empty enumeration.
* @since Ant 1.6
*/
public static final class EmptyEnumeration<E> implements Enumeration<E> {
/** Constructor for the EmptyEnumeration */
public EmptyEnumeration() {
}
/**
* @return false always.
*/
public boolean hasMoreElements() {
return false;
}
/**
* @return nothing.
* @throws NoSuchElementException always.
*/
public E nextElement() throws NoSuchElementException {
throw new NoSuchElementException();
}
}
/**
* Append one enumeration to another.
* Elements are evaluated lazily.
* @param e1 the first enumeration.
* @param e2 the subsequent enumeration.
* @return an enumeration representing e1 followed by e2.
* @since Ant 1.6.3
*/
public static <E> Enumeration<E> append(Enumeration<E> e1, Enumeration<E> e2) {
return new CompoundEnumeration<E>(e1, e2);
}
/**
* Adapt the specified Iterator to the Enumeration interface.
* @param iter the Iterator to adapt.
* @return an Enumeration.
*/
public static <E> Enumeration<E> asEnumeration(final Iterator<E> iter) {
return new Enumeration<E>() {
public boolean hasMoreElements() {
return iter.hasNext();
}
public E nextElement() {
return iter.next();
}
};
}
/**
* Adapt the specified Enumeration to the Iterator interface.
* @param e the Enumeration to adapt.
* @return an Iterator.
*/
public static <E> Iterator<E> asIterator(final Enumeration<E> e) {
return new Iterator<E>() {
public boolean hasNext() {
return e.hasMoreElements();
}
public E next() {
return e.nextElement();
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
/**
* Returns a collection containing all elements of the iterator.
*
* @since Ant 1.8.0
*/
public static <T> Collection<T> asCollection(final Iterator<? extends T> iter) {
List<T> l = new ArrayList<T>();
while (iter.hasNext()) {
l.add(iter.next());
}
return l;
}
private static final class CompoundEnumeration<E> implements Enumeration<E> {
private final Enumeration<E> e1, e2;
public CompoundEnumeration(Enumeration<E> e1, Enumeration<E> e2) {
this.e1 = e1;
this.e2 = e2;
}
public boolean hasMoreElements() {
return e1.hasMoreElements() || e2.hasMoreElements();
}
public E nextElement() throws NoSuchElementException {
if (e1.hasMoreElements()) {
return e1.nextElement();
} else {
return e2.nextElement();
}
}
}
/**
* Counts how often the given Object occurs in the given
* collection using equals() for comparison.
*
* @since Ant 1.8.0
*/
public static int frequency(Collection<?> c, Object o) {
// same as Collections.frequency introduced with JDK 1.5
int freq = 0;
if (c != null) {
for (Iterator<?> i = c.iterator(); i.hasNext(); ) {
Object test = i.next();
if (o == null ? test == null : o.equals(test)) {
freq++;
}
}
}
return freq;
}
}

Some files were not shown because too many files have changed in this diff Show More