nvd_feed_api 0.3.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 158649a33021b95393055afc6861185443aeae4665cc6acd86814f29a866d8f0
4
- data.tar.gz: 75ca47cdcece6352581ed8ddfe9339ce393e48199ba4c895e6e49e05e959b08b
3
+ metadata.gz: 0365df5462570fa4b9483e27ef5d6b7edf48cde8599c199932b86bda75c7790d
4
+ data.tar.gz: 52c270979c88f7154edd2c06f9dcec28c9fccffd3ff0606f6bda817a2f6ffd6a
5
5
  SHA512:
6
- metadata.gz: 66c08b3167c12da6168331f84caa557d945ebb16c76e565cefa6ac44c7960e5eb8bae840a2231c16d2cc9ef982bd13eb9b68289dff66dbee4af0c115a45e20f4
7
- data.tar.gz: 2729e066d04f9f29e9fd3fbd76c88cb3c208c2a82eab331e3202fca9a42a7f658d7645f7d3c17f5df770c54b1eb8e084b611f6e23eefab90c7e4cada90e114f0
6
+ metadata.gz: aceb9c1aa76e74ad7d87329900417abccd5c01f47a9fb76cdddf870e00654257dacf9506eb3b87e4cb9148a2ae2829191e2357ae56f4af4cd35b904073bb89fe
7
+ data.tar.gz: cfb064247356ab4f559d6b50cb997a7f332ab26f1172dafab8baf2ab5d30c204da7594a438b710e671204633cc77c6ca66a1c5f1056f2da721a69760b65faab8
@@ -0,0 +1,3 @@
1
+ github: noraj
2
+ issuehunt: noraj
3
+ ko_fi: noraj
data/.gitlab-ci.yml CHANGED
@@ -15,7 +15,8 @@ before_script:
15
15
  # install make, gcc for building gem native extension (commonmarker)
16
16
  # libc-dev for musl-dev dependency (stdlib.h) needed by gcc
17
17
  - apk --no-cache add coreutils git make gcc libc-dev
18
- - bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby
18
+ - bundle config set path 'vendor' # Set dependencies install dir to ./vendor/ruby
19
+ - bundle install -j $(nproc) # Install dependencies into ./vendor/ruby
19
20
  - bundle exec rake install # install the gem
20
21
 
21
22
  # Anchors: https://docs.gitlab.com/ee/ci/yaml/README.html#anchors
@@ -25,25 +26,13 @@ before_script:
25
26
  - bundle exec rubocop
26
27
  - bundle exec rake test
27
28
 
28
- test:2.4:
29
+ test:3.4:
29
30
  <<: *job_definition
30
- image: ruby:2.4-alpine
31
-
32
- test:2.5:
33
- <<: *job_definition
34
- image: ruby:2.5-alpine
35
-
36
- test:2.6:
37
- <<: *job_definition
38
- image: ruby:2.6-alpine
39
-
40
- test:2.7:
41
- <<: *job_definition
42
- image: ruby:2.7-alpine
31
+ image: ruby:3.4-alpine
43
32
 
44
33
  pages:
45
34
  stage: deploy
46
- image: ruby:2.4-alpine
35
+ image: ruby:3.4-alpine
47
36
  script:
48
37
  - bundle exec yard doc
49
38
  - mkdir public
data/.rubocop.yml CHANGED
@@ -1,6 +1,10 @@
1
1
  AllCops:
2
- TargetRubyVersion: 2.7
2
+ TargetRubyVersion: 3.1
3
3
  NewCops: enable
4
+ SuggestExtensions: false
5
+
6
+ plugins:
7
+ - rubocop-minitest
4
8
 
5
9
  Layout/HashAlignment:
6
10
  EnforcedHashRocketStyle: table
@@ -25,7 +29,7 @@ Metrics/ClassLength:
25
29
  Enabled: false
26
30
 
27
31
  Metrics/CyclomaticComplexity:
28
- Max: 20
32
+ Max: 25
29
33
 
30
34
  Metrics/MethodLength:
31
35
  Max: 100
@@ -33,14 +37,17 @@ Metrics/MethodLength:
33
37
  Metrics/PerceivedComplexity:
34
38
  Enabled: false
35
39
 
40
+ Minitest/MultipleAssertions:
41
+ Enabled: false
42
+
36
43
  Naming/VariableName:
37
44
  EnforcedStyle: snake_case
38
45
 
39
46
  Security/JSONLoad:
40
47
  Enabled: false
41
48
 
42
- Style/FrozenStringLiteralComment:
43
- EnforcedStyle: never
49
+ Style/CaseLikeIf:
50
+ Enabled: true
44
51
 
45
52
  Style/PerlBackrefs:
46
53
  AutoCorrect: false
data/.tool-versions CHANGED
@@ -1 +1 @@
1
- ruby 2.7.1
1
+ ruby 3.4.1
data/.yardopts CHANGED
@@ -1,6 +1,8 @@
1
1
  --protected
2
2
  --private
3
3
  --output-dir doc/
4
+ --markup markdown
5
+ --markup-provider commonmarker
4
6
  -
5
7
  --main README.md
6
8
  LICENSE.txt
data/Gemfile CHANGED
@@ -1,4 +1,33 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
- # Specify your gem's dependencies in .gemspec
4
5
  gemspec
6
+
7
+ group :runtime, :cli do
8
+ gem 'archive-zip', '~> 0.11'
9
+ gem 'nokogiri', '~> 1.11'
10
+ gem 'oj', '>= 3.7.8', '<4'
11
+ end
12
+
13
+ group :development, :install do
14
+ gem 'bundler', '~> 2.1'
15
+ end
16
+
17
+ group :development, :test do
18
+ gem 'minitest', '~> 5.25'
19
+ gem 'rake', '~> 13.2'
20
+ end
21
+
22
+ group :development, :lint do
23
+ gem 'rubocop', '~> 1.71'
24
+ gem 'rubocop-minitest', '~> 0.36'
25
+ end
26
+
27
+ group :development, :docs do
28
+ gem 'commonmarker', '~> 2.0' # for markdown support in YARD
29
+ gem 'logger', '< 2.0'
30
+ # gem 'yard', ['>= 0.9.27', '< 0.10']
31
+ # https://github.com/lsegal/yard/issues/1528
32
+ gem 'yard', github: 'ParadoxV5/yard', ref: '9e869c940859570b07b81c5eadd6070e76f6291e', branch: 'commonmarker-1.0'
33
+ end
data/Gemfile.lock CHANGED
@@ -1,9 +1,17 @@
1
+ GIT
2
+ remote: https://github.com/ParadoxV5/yard.git
3
+ revision: 9e869c940859570b07b81c5eadd6070e76f6291e
4
+ ref: 9e869c940859570b07b81c5eadd6070e76f6291e
5
+ branch: commonmarker-1.0
6
+ specs:
7
+ yard (0.9.36)
8
+
1
9
  PATH
2
10
  remote: .
3
11
  specs:
4
- nvd_feed_api (0.3.1)
12
+ nvd_feed_api (0.5.0)
5
13
  archive-zip (~> 0.11)
6
- nokogiri (~> 1.10)
14
+ nokogiri (~> 1.11)
7
15
  oj (>= 3.7.8, < 4)
8
16
 
9
17
  GEM
@@ -11,57 +19,100 @@ GEM
11
19
  specs:
12
20
  archive-zip (0.12.0)
13
21
  io-like (~> 0.3.0)
14
- ast (2.4.1)
15
- commonmarker (0.21.0)
16
- ruby-enum (~> 0.5)
17
- concurrent-ruby (1.1.7)
18
- github-markup (3.0.4)
19
- i18n (1.8.5)
20
- concurrent-ruby (~> 1.0)
22
+ ast (2.4.3)
23
+ bigdecimal (3.1.9)
24
+ commonmarker (2.2.0)
25
+ rb_sys (~> 0.9)
26
+ commonmarker (2.2.0-aarch64-linux)
27
+ commonmarker (2.2.0-aarch64-linux-musl)
28
+ commonmarker (2.2.0-arm64-darwin)
29
+ commonmarker (2.2.0-x86_64-darwin)
30
+ commonmarker (2.2.0-x86_64-linux)
31
+ commonmarker (2.2.0-x86_64-linux-musl)
21
32
  io-like (0.3.1)
22
- mini_portile2 (2.4.0)
23
- minitest (5.14.2)
24
- nokogiri (1.10.10)
25
- mini_portile2 (~> 2.4.0)
26
- oj (3.10.14)
27
- parallel (1.19.2)
28
- parser (2.7.1.5)
33
+ json (2.10.2)
34
+ language_server-protocol (3.17.0.4)
35
+ lint_roller (1.1.0)
36
+ logger (1.6.6)
37
+ minitest (5.25.5)
38
+ nokogiri (1.18.6-aarch64-linux-gnu)
39
+ racc (~> 1.4)
40
+ nokogiri (1.18.6-aarch64-linux-musl)
41
+ racc (~> 1.4)
42
+ nokogiri (1.18.6-arm-linux-gnu)
43
+ racc (~> 1.4)
44
+ nokogiri (1.18.6-arm-linux-musl)
45
+ racc (~> 1.4)
46
+ nokogiri (1.18.6-arm64-darwin)
47
+ racc (~> 1.4)
48
+ nokogiri (1.18.6-x86_64-darwin)
49
+ racc (~> 1.4)
50
+ nokogiri (1.18.6-x86_64-linux-gnu)
51
+ racc (~> 1.4)
52
+ nokogiri (1.18.6-x86_64-linux-musl)
53
+ racc (~> 1.4)
54
+ oj (3.16.10)
55
+ bigdecimal (>= 3.0)
56
+ ostruct (>= 0.2)
57
+ ostruct (0.6.1)
58
+ parallel (1.26.3)
59
+ parser (3.3.7.3)
29
60
  ast (~> 2.4.1)
30
- rainbow (3.0.0)
31
- rake (13.0.1)
32
- redcarpet (3.5.0)
33
- regexp_parser (1.8.1)
34
- rexml (3.2.4)
35
- rubocop (0.92.0)
61
+ racc
62
+ prism (1.4.0)
63
+ racc (1.8.1)
64
+ rainbow (3.1.1)
65
+ rake (13.2.1)
66
+ rake-compiler-dock (1.9.1)
67
+ rb_sys (0.9.111)
68
+ rake-compiler-dock (= 1.9.1)
69
+ regexp_parser (2.10.0)
70
+ rubocop (1.75.1)
71
+ json (~> 2.3)
72
+ language_server-protocol (~> 3.17.0.2)
73
+ lint_roller (~> 1.1.0)
36
74
  parallel (~> 1.10)
37
- parser (>= 2.7.1.5)
75
+ parser (>= 3.3.0.2)
38
76
  rainbow (>= 2.2.2, < 4.0)
39
- regexp_parser (>= 1.7)
40
- rexml
41
- rubocop-ast (>= 0.5.0)
77
+ regexp_parser (>= 2.9.3, < 3.0)
78
+ rubocop-ast (>= 1.43.0, < 2.0)
42
79
  ruby-progressbar (~> 1.7)
43
- unicode-display_width (>= 1.4.0, < 2.0)
44
- rubocop-ast (0.7.1)
45
- parser (>= 2.7.1.5)
46
- ruby-enum (0.8.0)
47
- i18n
48
- ruby-progressbar (1.10.1)
49
- unicode-display_width (1.7.0)
50
- yard (0.9.25)
80
+ unicode-display_width (>= 2.4.0, < 4.0)
81
+ rubocop-ast (1.43.0)
82
+ parser (>= 3.3.7.2)
83
+ prism (~> 1.4)
84
+ rubocop-minitest (0.37.1)
85
+ lint_roller (~> 1.1)
86
+ rubocop (>= 1.72.1, < 2.0)
87
+ rubocop-ast (>= 1.38.0, < 2.0)
88
+ ruby-progressbar (1.13.0)
89
+ unicode-display_width (3.1.4)
90
+ unicode-emoji (~> 4.0, >= 4.0.4)
91
+ unicode-emoji (4.0.4)
51
92
 
52
93
  PLATFORMS
53
- ruby
94
+ aarch64-linux-gnu
95
+ aarch64-linux-musl
96
+ arm-linux-gnu
97
+ arm-linux-musl
98
+ arm64-darwin
99
+ x86_64-darwin
100
+ x86_64-linux-gnu
101
+ x86_64-linux-musl
54
102
 
55
103
  DEPENDENCIES
104
+ archive-zip (~> 0.11)
56
105
  bundler (~> 2.1)
57
- commonmarker (~> 0.21)
58
- github-markup (~> 3.0)
59
- minitest (~> 5.14)
106
+ commonmarker (~> 2.0)
107
+ logger (< 2.0)
108
+ minitest (~> 5.25)
109
+ nokogiri (~> 1.11)
60
110
  nvd_feed_api!
61
- rake (~> 13.0)
62
- redcarpet (~> 3.5)
63
- rubocop (~> 0.92)
64
- yard (~> 0.9)
111
+ oj (>= 3.7.8, < 4)
112
+ rake (~> 13.2)
113
+ rubocop (~> 1.71)
114
+ rubocop-minitest (~> 0.36)
115
+ yard!
65
116
 
66
117
  BUNDLED WITH
67
- 2.1.4
118
+ 2.6.2
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rake/testtask'
2
4
  require 'bundler/gem_tasks'
3
5
 
data/bin/nvd_feed_api CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'nvd_feed_api'
4
5
 
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'bundler/setup'
4
5
  require 'nvd_feed_api'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Ruby internal
2
4
  require 'digest'
3
5
  require 'net/https'
@@ -13,7 +15,7 @@ class NVDFeedScraper
13
15
  class Feed
14
16
  class << self
15
17
  # Get / set default feed storage location, where will be stored JSON feeds and archives by default.
16
- # @return [String] default feed storage location. Default to +/tmp/+.
18
+ # @return [String] default feed storage location. Default to `/tmp/`.
17
19
  # @example
18
20
  # NVDFeedScraper::Feed.default_storage_location = '/srv/downloads/'
19
21
  attr_accessor :default_storage_location
@@ -69,11 +71,11 @@ class NVDFeedScraper
69
71
  # f.json_file # => "/tmp/nvdcve-1.0-2014.json"
70
72
  attr_reader :json_file
71
73
 
72
- # @return [String] the type of the feed, should always be +CVE+.
74
+ # @return [String] the type of the feed, should always be `CVE`.
73
75
  # @note Return nil if not previously loaded by {#json_pull}.
74
76
  attr_reader :data_type
75
77
 
76
- # @return [String] the format of the feed, should always be +MITRE+.
78
+ # @return [String] the format of the feed, should always be `MITRE`.
77
79
  # @note Return nil if not previously loaded by {#json_pull}.
78
80
  attr_reader :data_format
79
81
 
@@ -96,7 +98,7 @@ class NVDFeedScraper
96
98
  # @param gz_url [String] see {#gz_url}.
97
99
  # @param zip_url [String] see {#zip_url}.
98
100
  def initialize(name, updated, meta_url, gz_url, zip_url)
99
- # Frome meta file
101
+ # From meta file
100
102
  @name = name
101
103
  @updated = updated
102
104
  @meta_url = meta_url
@@ -146,7 +148,7 @@ class NVDFeedScraper
146
148
  # Download the JSON feed and fill the attribute.
147
149
  # @param opts [Hash] see {#download_file}.
148
150
  # @return [String] the path of the saved JSON file. Default use {Feed#default_storage_location}.
149
- # @note Will downlaod and save the zip of the JSON file, unzip and save it. This massively consume time.
151
+ # @note Will download and save the zip of the JSON file, unzip and save it. This massively consume time.
150
152
  # @see #json_file
151
153
  def json_pull(opts = {})
152
154
  opts[:destination_path] ||= Feed.default_storage_location
@@ -229,7 +231,8 @@ class NVDFeedScraper
229
231
  raise 'no argument provided, 1 or more expected' if arg_cve.empty?
230
232
 
231
233
  if arg_cve.length == 1
232
- if arg_cve[0].is_a?(String)
234
+ case arg_cve[0]
235
+ when String
233
236
  raise "bad CVE name (#{arg_cve[0]})" unless /^CVE-[0-9]{4}-[0-9]{4,}$/i.match?(arg_cve[0])
234
237
 
235
238
  doc = Oj::Doc.open(File.read(@json_file))
@@ -241,7 +244,7 @@ class NVDFeedScraper
241
244
  end
242
245
  end
243
246
  doc.close
244
- elsif arg_cve[0].is_a?(Array)
247
+ when Array
245
248
  return_value = []
246
249
  # Sorting CVE can allow us to parse quicker
247
250
  # Upcase to be sure include? works
@@ -363,27 +366,23 @@ class NVDFeedScraper
363
366
  uri = URI(file_url)
364
367
  filename = uri.path.split('/').last
365
368
  destination_file = destination_path + filename
366
- unless opts[:sha256].nil?
367
- if File.file?(destination_file)
368
- # Verify hash to see if it is the latest
369
- computed_h = Digest::SHA256.file(destination_file)
370
- skip_download = true if opts[:sha256].casecmp(computed_h.hexdigest).zero?
371
- end
369
+ if !opts[:sha256].nil? && File.file?(destination_file)
370
+ # Verify hash to see if it is the latest
371
+ computed_h = Digest::SHA256.file(destination_file)
372
+ skip_download = true if opts[:sha256].casecmp(computed_h.hexdigest).zero?
372
373
  end
373
374
  unless skip_download
374
375
  res = Net::HTTP.get_response(uri)
375
376
  raise "#{file_url} ended with #{res.code} #{res.message}" unless res.is_a?(Net::HTTPSuccess)
376
377
 
377
- File.open(destination_file, 'wb') do |file|
378
- file.write(res.body)
379
- end
378
+ File.binwrite(destination_file, res.body)
380
379
  end
381
380
  return destination_file
382
381
  end
383
382
 
384
383
  # Update the feed
385
384
  # @param fresh_feed [Feed] the fresh feed from which the feed will be updated.
386
- # @return [Boolean] +true+ if the feed was updated, +false+ if it wasn't.
385
+ # @return [Boolean] `true` if the feed was updated, `false` if it wasn't.
387
386
  # @note Is not intended to be used directly, use {NVDFeedScraper#update_feeds} instead.
388
387
  def update!(fresh_feed)
389
388
  return_value = false
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Ruby internal
2
4
  require 'net/https'
3
5
 
@@ -76,17 +78,16 @@ class NVDFeedScraper
76
78
  # Parse the meta file from the URL and set the attributes.
77
79
  # @overload parse
78
80
  # Parse the meta file from the URL and set the attributes.
79
- # @return [Integer] Returns +0+ when there is no error.
81
+ # @return [Integer] Returns `0` when there is no error.
80
82
  # @overload parse(url)
81
83
  # Set the URL of the meta file of the feed and
82
84
  # parse the meta file from the URL and set the attributes.
83
85
  # @param url [String] see {Feed.meta_url}
84
- # @return [Integer] Returns +0+ when there is no error.
86
+ # @return [Integer] Returns `0` when there is no error.
85
87
  def parse(*arg)
86
- if arg.empty?
87
- elsif arg.length == 1 # arg = url
88
+ if arg.length == 1 # arg = url
88
89
  self.url = arg[0]
89
- else
90
+ elsif arg.length > 1
90
91
  raise 'Too much arguments'
91
92
  end
92
93
 
@@ -96,7 +97,7 @@ class NVDFeedScraper
96
97
 
97
98
  meta = Net::HTTP.get(uri)
98
99
 
99
- meta = Hash[meta.split.map { |x| x.split(':', 2) }]
100
+ meta = meta.split.to_h { |x| x.split(':', 2) }
100
101
 
101
102
  raise 'no lastModifiedDate attribute found' unless meta['lastModifiedDate']
102
103
  raise 'no valid size attribute found' unless /[0-9]+/.match?(meta['size'])
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module NvdFeedApi
2
- VERSION = '0.3.1'.freeze
4
+ VERSION = '0.5.0'
3
5
  end
data/lib/nvd_feed_api.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # @author Alexandre ZANNI <alexandre.zanni@engineer.com>
2
4
 
3
5
  # Ruby internal
@@ -18,7 +20,7 @@ require 'nvd_feed_api/feed'
18
20
  # scraper.feeds("CVE-2007")
19
21
  # cve2007, cve2015 = scraper.feeds("CVE-2007", "CVE-2015")
20
22
  class NVDFeedScraper
21
- BASE = 'https://nvd.nist.gov'.freeze
23
+ BASE = 'https://nvd.nist.gov'
22
24
  # The NVD url where is located the data feeds.
23
25
  URL = "#{BASE}/vuln/data-feeds".freeze
24
26
  # Load constants
@@ -42,14 +44,15 @@ class NVDFeedScraper
42
44
  tmp_feeds = {}
43
45
  doc.css('#vuln-feed-table table.xml-feed-table tr[data-testid]').each do |tr|
44
46
  num, type = tr.attr('data-testid')[13..].split('-')
45
- if type == 'meta'
47
+ case type
48
+ when 'meta'
46
49
  tmp_feeds[num] = {}
47
50
  tmp_feeds[num][:name] = tr.css('td')[0].text
48
51
  tmp_feeds[num][:updated] = tr.css('td')[1].text
49
52
  tmp_feeds[num][:meta] = BASE + tr.css('td')[2].css('> a').attr('href').value
50
- elsif type == 'gz'
53
+ when 'gz'
51
54
  tmp_feeds[num][:gz] = BASE + tr.css('td > a').attr('href').value
52
- elsif type == 'zip'
55
+ when 'zip'
53
56
  tmp_feeds[num][:zip] = BASE + tr.css('td > a').attr('href').value
54
57
  @feeds.push(Feed.new(tmp_feeds[num][:name],
55
58
  tmp_feeds[num][:updated],
@@ -90,12 +93,13 @@ class NVDFeedScraper
90
93
  if arg_feeds.empty?
91
94
  return_value = @feeds
92
95
  elsif arg_feeds.length == 1
93
- if arg_feeds[0].is_a?(String)
96
+ case arg_feeds[0]
97
+ when String
94
98
  @feeds.each do |feed| # feed is an object
95
99
  return_value = feed if arg_feeds.include?(feed.name)
96
100
  end
97
101
  # if nothing found return nil
98
- elsif arg_feeds[0].is_a?(Array)
102
+ when Array
99
103
  raise 'one of the provided arguments is not a String' unless arg_feeds[0].all? { |x| x.is_a?(String) }
100
104
 
101
105
  # Sorting CVE can allow us to parse quicker
@@ -130,11 +134,7 @@ class NVDFeedScraper
130
134
  def available_feeds
131
135
  raise 'call scrap method before using available_feeds method' if @feeds.nil?
132
136
 
133
- feed_names = []
134
- @feeds.each do |feed| # feed is an objet
135
- feed_names.push(feed.name)
136
- end
137
- feed_names
137
+ @feeds.map(&:name)
138
138
  end
139
139
 
140
140
  # Search for CVE in all year feeds.
@@ -164,7 +164,8 @@ class NVDFeedScraper
164
164
  raise 'no argument provided, 1 or more expected' if arg_cve.empty?
165
165
 
166
166
  if arg_cve.length == 1
167
- if arg_cve[0].is_a?(String)
167
+ case arg_cve[0]
168
+ when String
168
169
  raise 'bad CVE name' unless /^CVE-[0-9]{4}-[0-9]{4,}$/i.match?(arg_cve[0])
169
170
 
170
171
  year = /^CVE-([0-9]{4})-[0-9]{4,}$/i.match(arg_cve[0]).captures[0]
@@ -185,7 +186,7 @@ class NVDFeedScraper
185
186
  f = feeds(matched_feed)
186
187
  f.json_pull
187
188
  return_value = f.cve(arg_cve[0])
188
- elsif arg_cve[0].is_a?(Array)
189
+ when Array
189
190
  raise 'one of the provided arguments is not a String' unless arg_cve[0].all? { |x| x.is_a?(String) }
190
191
  raise 'bad CVE name' unless arg_cve[0].all? { |x| /^CVE-[0-9]{4}-[0-9]{4,}$/i.match?(x) }
191
192
 
@@ -208,7 +209,7 @@ class NVDFeedScraper
208
209
 
209
210
  matched_feeds = feeds_to_match.intersection(feed_names)
210
211
  # and now that the intersection is done remove those virtual feeds and add CVE-2002 instead if needed
211
- unless matched_feeds.intersection(virtual_feeds.to_set).empty?
212
+ if matched_feeds.intersect?(virtual_feeds.to_set)
212
213
  matched_feeds.subtract(virtual_feeds)
213
214
  matched_feeds.add('CVE-2002')
214
215
  end
@@ -216,9 +217,10 @@ class NVDFeedScraper
216
217
  feeds_arr.each do |feed|
217
218
  feed.json_pull
218
219
  cves_obj = feed.cve(cves_to_find.select { |cve| cve.include?(feed.name) })
219
- if cves_obj.is_a?(Hash)
220
+ case cves_obj
221
+ when Hash
220
222
  return_value.push(cves_obj)
221
- elsif cves_obj.is_a?(Array)
223
+ when Array
222
224
  return_value.push(*cves_obj)
223
225
  else
224
226
  raise 'cve() method of the feed instance returns wrong value'
@@ -238,16 +240,16 @@ class NVDFeedScraper
238
240
  # @overload update_feeds(feed)
239
241
  # One feed.
240
242
  # @param feed [Feed] feed object to update.
241
- # @return [Boolean] +true+ if the feed was updated, +false+ if it wasn't.
243
+ # @return [Boolean] `true` if the feed was updated, `false` if it wasn't.
242
244
  # @overload update_feeds(feed_arr)
243
245
  # An array of feed.
244
246
  # @param feed_arr [Array<Feed>] array of feed objects to update.
245
- # @return [Array<Boolean>] +true+ if the feed was updated, +false+ if it wasn't.
247
+ # @return [Array<Boolean>] `true` if the feed was updated, `false` if it wasn't.
246
248
  # @overload update_feeds(feed, *)
247
249
  # Multiple feeds.
248
250
  # @param feed [Feed] feed object to update.
249
251
  # @param * [Feed] As many feed objects as you want.
250
- # @return [Array<Boolean>] +true+ if the feed was updated, +false+ if it wasn't.
252
+ # @return [Array<Boolean>] `true` if the feed was updated, `false` if it wasn't.
251
253
  # @example
252
254
  # s = NVDFeedScraper.new
253
255
  # s.scrap
@@ -259,11 +261,12 @@ class NVDFeedScraper
259
261
 
260
262
  scrap
261
263
  if arg_feed.length == 1
262
- if arg_feed[0].is_a?(Feed)
264
+ case arg_feed[0]
265
+ when Feed
263
266
  new_feed = feeds(arg_feed[0].name)
264
267
  # update attributes
265
268
  return_value = arg_feed[0].update!(new_feed)
266
- elsif arg_feed[0].is_a?(Array)
269
+ when Array
267
270
  return_value = []
268
271
  arg_feed[0].each do |f|
269
272
  res = update_feeds(f)
data/nvd_feed_api.gemspec CHANGED
@@ -1,12 +1,11 @@
1
- lib = File.expand_path('lib', __dir__)
2
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require 'nvd_feed_api/version'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/nvd_feed_api/version'
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'nvd_feed_api'
7
7
  s.version = NvdFeedApi::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
- s.date = '2020-10-03'
10
9
  s.summary = 'API for NVD CVE feeds'
11
10
  s.description = 'A simple API for NVD CVE feeds'
12
11
  s.authors = ['Alexandre ZANNI']
@@ -16,31 +15,23 @@ Gem::Specification.new do |s|
16
15
 
17
16
  s.files = `git ls-files`.split("\n")
18
17
  s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
19
- s.test_files = s.files.grep(%r{^(test)/})
20
18
  s.require_paths = ['lib']
21
19
 
22
20
  s.metadata = {
23
- 'yard.run' => 'yard',
24
- 'bug_tracker_uri' => 'https://gitlab.com/noraj/nvd_api/issues',
25
- 'changelog_uri' => 'https://noraj.gitlab.io/nvd_api/file.CHANGELOG.html',
26
- 'documentation_uri' => 'https://noraj.gitlab.io/nvd_api/',
27
- 'homepage_uri' => 'https://noraj.gitlab.io/nvd_api/',
28
- 'source_code_uri' => 'https://gitlab.com/noraj/nvd_api/tree/master',
29
- 'wiki_uri' => 'https://gitlab.com/noraj/nvd_api/wikis/home'
21
+ 'yard.run' => 'yard',
22
+ 'bug_tracker_uri' => 'https://gitlab.com/noraj/nvd_api/issues',
23
+ 'changelog_uri' => 'https://noraj.gitlab.io/nvd_api/file.CHANGELOG.html',
24
+ 'documentation_uri' => 'https://noraj.gitlab.io/nvd_api/',
25
+ 'homepage_uri' => 'https://noraj.gitlab.io/nvd_api/',
26
+ 'source_code_uri' => 'https://gitlab.com/noraj/nvd_api/tree/master',
27
+ 'wiki_uri' => 'https://gitlab.com/noraj/nvd_api/wikis/home',
28
+ 'funding_uri' => 'https://github.com/sponsors/noraj',
29
+ 'rubygems_mfa_required' => 'true'
30
30
  }
31
31
 
32
- s.required_ruby_version = '~> 2.4'
32
+ s.required_ruby_version = ['>= 3.1.0', '< 4.0']
33
33
 
34
34
  s.add_dependency('archive-zip', '~> 0.11')
35
- s.add_dependency('nokogiri', '~> 1.10')
35
+ s.add_dependency('nokogiri', '~> 1.11')
36
36
  s.add_dependency('oj', '>= 3.7.8', '<4')
37
-
38
- s.add_development_dependency('bundler', '~> 2.1')
39
- s.add_development_dependency('commonmarker', '~> 0.21') # for GMF support in YARD
40
- s.add_development_dependency('github-markup', '~> 3.0') # for GMF support in YARD
41
- s.add_development_dependency('minitest', '~> 5.14')
42
- s.add_development_dependency('rake', '~> 13.0')
43
- s.add_development_dependency('redcarpet', '~> 3.5') # for GMF support in YARD
44
- s.add_development_dependency('rubocop', '~> 0.92')
45
- s.add_development_dependency('yard', '~> 0.9')
46
37
  end
data/pages/CHANGELOG.md CHANGED
@@ -1,4 +1,24 @@
1
- # [0.3.0] - 22 January 2019
1
+ # [0.5.0] - 30 March 2025
2
+
3
+ - Breaking changes:
4
+ - Drop support for Ruby 2.7 and 3.0
5
+ - Chore:
6
+ - Add support for Ruby 3.2 & 3.3 & 3.4
7
+ - Update dependencies
8
+ - Add freeze literal string comment
9
+
10
+ # [0.4.0] - 31 January 2021
11
+
12
+ - Dependencies:
13
+ - Update to yard [v0.9.27](https://github.com/lsegal/yard/releases/tag/v0.9.27)
14
+ - Move from Redcarpet to CommonMarker markdown provider
15
+ - Move doc syntax from Rdoc to markdown
16
+ - Move dev dependencies from gemspec to gemfile
17
+ - Chore:
18
+ - Add support for Ruby 3.1
19
+ - Update rubocop rules
20
+
21
+ # [0.3.1] - 13 October 2020
2
22
 
3
23
  [0.3.1]: https://gitlab.com/noraj/nvd_api/tags/v0.3.1
4
24
 
@@ -6,6 +26,8 @@
6
26
  - update dependencies
7
27
  - update rubocop rules
8
28
 
29
+ # [0.3.0] - 22 January 2019
30
+
9
31
  [0.3.0]: https://gitlab.com/noraj/nvd_api/tags/v0.3.0
10
32
 
11
33
  - update dependencies: updated gemspec, ruby 2.6 support, fix gem doc flag, fix oj crash (seg fault)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'minitest/autorun'
2
4
  require 'nvd_feed_api'
3
5
  require 'date'
@@ -78,7 +80,7 @@ class NVDAPITest < Minitest::Test
78
80
  f2017, f2016, f_modified = @s.feeds('CVE-2017', 'CVE-2016', 'CVE-Modified')
79
81
  # one arg
80
82
  # can't use assert_instance_of because there is no boolean class
81
- assert(['TrueClass', 'FalseClass'].include?(@s.update_feeds(f2017).class.to_s), "update_feeds doesn't return a boolean")
83
+ assert_includes(['TrueClass', 'FalseClass'], @s.update_feeds(f2017).class.to_s, "update_feeds doesn't return a boolean")
82
84
  # two args
83
85
  assert_instance_of(Array, @s.update_feeds(f2017, f2016), "update_feeds doesn't return an array")
84
86
  refute_empty(@s.update_feeds(f2017, f2016), 'update_feeds returns an empty array')
@@ -90,7 +92,7 @@ class NVDAPITest < Minitest::Test
90
92
  err = assert_raises(RuntimeError) do
91
93
  @s.update_feeds(1)
92
94
  end
93
- assert_equal(err.message, 'the provided argument 1 is not a Feed or an Array')
95
+ assert_equal('the provided argument 1 is not a Feed or an Array', err.message)
94
96
  ## empty array
95
97
  assert_empty(@s.update_feeds([]))
96
98
  end
@@ -102,6 +104,7 @@ class NVDAPITest < Minitest::Test
102
104
  assert_instance_of(String, default_val, "default_storage_location doesn't return a string")
103
105
  # check new value
104
106
  new_val = '/srv/downloads/'
107
+
105
108
  assert_equal(new_val, NVDFeedScraper::Feed.default_storage_location = new_val, 'the new value was not set properly')
106
109
  # put the default value back / restore context
107
110
  NVDFeedScraper::Feed.default_storage_location = default_val
@@ -137,10 +140,12 @@ class NVDAPITest < Minitest::Test
137
140
  # Test json_file
138
141
  assert_nil(f.json_file)
139
142
  f.json_pull
143
+
140
144
  assert_instance_of(String, f.json_file, "json_file doesn't return a string")
141
145
  refute_empty(f.json_file, 'json_file is empty')
142
146
  # Test meta (after json_pull)
143
147
  f.meta_pull
148
+
144
149
  assert_instance_of(NVDFeedScraper::Meta, f.meta, "meta doesn't return a Meta object")
145
150
 
146
151
  # Test data (require json_pull)
@@ -161,6 +166,7 @@ class NVDAPITest < Minitest::Test
161
166
  def test_feed_available_cves
162
167
  f = @s.feeds('CVE-2011')
163
168
  f.json_pull
169
+
164
170
  assert_instance_of(Array, f.available_cves, "available_cves doesn't return an array")
165
171
  refute_empty(f.available_cves, 'available_cves returns an empty array')
166
172
  end
@@ -199,6 +205,7 @@ class NVDAPITest < Minitest::Test
199
205
  def test_feed_download_gz
200
206
  f = @s.feeds('CVE-2013')
201
207
  return_value = f.download_gz
208
+
202
209
  assert_instance_of(String, return_value, "download_gz doesn't return a string")
203
210
  refute_empty(return_value, 'download_gz returns an empty string')
204
211
  assert(File.file?(return_value), 'download_gz returns an unexisting file')
@@ -207,6 +214,7 @@ class NVDAPITest < Minitest::Test
207
214
  def test_feed_download_zip
208
215
  f = @s.feeds('CVE-2003')
209
216
  return_value = f.download_zip
217
+
210
218
  assert_instance_of(String, return_value, "download_zip doesn't return a string")
211
219
  refute_empty(return_value, 'download_zip returns an empty string')
212
220
  assert(File.file?(return_value), 'download_zip returns an unexisting file')
@@ -215,6 +223,7 @@ class NVDAPITest < Minitest::Test
215
223
  def test_feed_json_pull
216
224
  f = @s.feeds('CVE-2004')
217
225
  return_value = f.json_pull
226
+
218
227
  assert_instance_of(String, return_value, "json_pull doesn't return a string")
219
228
  refute_empty(return_value, 'json_pull returns an empty string')
220
229
  assert(File.file?(return_value), 'json_pull returns an unexisting file')
@@ -222,6 +231,7 @@ class NVDAPITest < Minitest::Test
222
231
 
223
232
  def test_feed_meta_pull
224
233
  f = @s.feeds('CVE-2005')
234
+
225
235
  assert_instance_of(NVDFeedScraper::Meta, f.meta_pull, "meta_pull doesn't return a Meta object")
226
236
  end
227
237
 
@@ -231,7 +241,7 @@ class NVDAPITest < Minitest::Test
231
241
  f_new = @s.feeds('CVE-2006')
232
242
  # Right arg
233
243
  # can't use assert_instance_of because there is no boolean class
234
- assert(['TrueClass', 'FalseClass'].include?(f.update!(f_new).class.to_s), "update! doesn't return a boolean")
244
+ assert_includes(['TrueClass', 'FalseClass'], f.update!(f_new).class.to_s, "update! doesn't return a boolean")
235
245
  # Bad arg
236
246
  err = assert_raises(RuntimeError) do
237
247
  f.update!('bad_arg')
@@ -241,18 +251,21 @@ class NVDAPITest < Minitest::Test
241
251
 
242
252
  def test_meta_parse_noarg
243
253
  m = NVDFeedScraper::Meta.new('https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-2015.meta')
254
+
244
255
  assert_equal(0, m.parse, 'parse method return nothing')
245
256
  end
246
257
 
247
258
  def test_meta_parse_witharg
248
259
  m = NVDFeedScraper::Meta.new
249
260
  meta_url = 'https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-2015.meta'
261
+
250
262
  assert_equal(0, m.parse(meta_url), 'parse method return nothing')
251
263
  end
252
264
 
253
265
  def test_meta_url_setter
254
266
  m = NVDFeedScraper::Meta.new
255
267
  meta_url = 'https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-2015.meta'
268
+
256
269
  assert_equal(meta_url, m.url = meta_url, 'the meta URL is not set correctly')
257
270
  end
258
271
 
@@ -263,22 +276,22 @@ class NVDAPITest < Minitest::Test
263
276
  m.parse
264
277
  # Test gz_size
265
278
  assert_instance_of(String, m.gz_size, "Meta gz_size method doesn't return a string")
266
- assert(m.gz_size.match?(/[0-9]+/), 'Meta gz_size is not an integer')
279
+ assert_match(/[0-9]+/, m.gz_size, 'Meta gz_size is not an integer')
267
280
  # Test last_modified_date
268
281
  assert_instance_of(String, m.last_modified_date, "Meta last_modified_date method doesn't return a string")
269
282
  ## Date and time of day for calendar date (extended) '%FT%T%:z'
270
283
  assert(Date.rfc3339(m.last_modified_date), 'Meta last_modified_date is not a rfc3339 date')
271
284
  # Test sha256
272
285
  assert_instance_of(String, m.sha256, "Meta sha256 method doesn't return a string")
273
- assert(m.sha256.match?(/[0-9A-F]{64}/), 'Meta sha256 is not a sha256 string matching /[0-9A-F]{64}/')
286
+ assert_match(/[0-9A-F]{64}/, m.sha256, 'Meta sha256 is not a sha256 string matching /[0-9A-F]{64}/')
274
287
  # Test size
275
288
  assert_instance_of(String, m.size, "Meta size method doesn't return a string")
276
- assert(m.size.match?(/[0-9]+/), 'Meta size is not an integer')
289
+ assert_match(/[0-9]+/, m.size, 'Meta size is not an integer')
277
290
  # Test url
278
291
  assert_instance_of(String, m.url, "Meta url method doesn't return a string")
279
292
  assert_equal(meta_url, m.url, 'The Meta url was modified')
280
293
  # Test zip_size
281
294
  assert_instance_of(String, m.zip_size, "Meta zip_size method doesn't return a string")
282
- assert(m.zip_size.match?(/[0-9]+/), 'Meta zip_size is not an integer')
295
+ assert_match(/[0-9]+/, m.zip_size, 'Meta zip_size is not an integer')
283
296
  end
284
297
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nvd_feed_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexandre ZANNI
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2020-10-03 00:00:00.000000000 Z
10
+ date: 2025-03-30 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: archive-zip
@@ -30,14 +29,14 @@ dependencies:
30
29
  requirements:
31
30
  - - "~>"
32
31
  - !ruby/object:Gem::Version
33
- version: '1.10'
32
+ version: '1.11'
34
33
  type: :runtime
35
34
  prerelease: false
36
35
  version_requirements: !ruby/object:Gem::Requirement
37
36
  requirements:
38
37
  - - "~>"
39
38
  - !ruby/object:Gem::Version
40
- version: '1.10'
39
+ version: '1.11'
41
40
  - !ruby/object:Gem::Dependency
42
41
  name: oj
43
42
  requirement: !ruby/object:Gem::Requirement
@@ -58,118 +57,6 @@ dependencies:
58
57
  - - "<"
59
58
  - !ruby/object:Gem::Version
60
59
  version: '4'
61
- - !ruby/object:Gem::Dependency
62
- name: bundler
63
- requirement: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - "~>"
66
- - !ruby/object:Gem::Version
67
- version: '2.1'
68
- type: :development
69
- prerelease: false
70
- version_requirements: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - "~>"
73
- - !ruby/object:Gem::Version
74
- version: '2.1'
75
- - !ruby/object:Gem::Dependency
76
- name: commonmarker
77
- requirement: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - "~>"
80
- - !ruby/object:Gem::Version
81
- version: '0.21'
82
- type: :development
83
- prerelease: false
84
- version_requirements: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - "~>"
87
- - !ruby/object:Gem::Version
88
- version: '0.21'
89
- - !ruby/object:Gem::Dependency
90
- name: github-markup
91
- requirement: !ruby/object:Gem::Requirement
92
- requirements:
93
- - - "~>"
94
- - !ruby/object:Gem::Version
95
- version: '3.0'
96
- type: :development
97
- prerelease: false
98
- version_requirements: !ruby/object:Gem::Requirement
99
- requirements:
100
- - - "~>"
101
- - !ruby/object:Gem::Version
102
- version: '3.0'
103
- - !ruby/object:Gem::Dependency
104
- name: minitest
105
- requirement: !ruby/object:Gem::Requirement
106
- requirements:
107
- - - "~>"
108
- - !ruby/object:Gem::Version
109
- version: '5.14'
110
- type: :development
111
- prerelease: false
112
- version_requirements: !ruby/object:Gem::Requirement
113
- requirements:
114
- - - "~>"
115
- - !ruby/object:Gem::Version
116
- version: '5.14'
117
- - !ruby/object:Gem::Dependency
118
- name: rake
119
- requirement: !ruby/object:Gem::Requirement
120
- requirements:
121
- - - "~>"
122
- - !ruby/object:Gem::Version
123
- version: '13.0'
124
- type: :development
125
- prerelease: false
126
- version_requirements: !ruby/object:Gem::Requirement
127
- requirements:
128
- - - "~>"
129
- - !ruby/object:Gem::Version
130
- version: '13.0'
131
- - !ruby/object:Gem::Dependency
132
- name: redcarpet
133
- requirement: !ruby/object:Gem::Requirement
134
- requirements:
135
- - - "~>"
136
- - !ruby/object:Gem::Version
137
- version: '3.5'
138
- type: :development
139
- prerelease: false
140
- version_requirements: !ruby/object:Gem::Requirement
141
- requirements:
142
- - - "~>"
143
- - !ruby/object:Gem::Version
144
- version: '3.5'
145
- - !ruby/object:Gem::Dependency
146
- name: rubocop
147
- requirement: !ruby/object:Gem::Requirement
148
- requirements:
149
- - - "~>"
150
- - !ruby/object:Gem::Version
151
- version: '0.92'
152
- type: :development
153
- prerelease: false
154
- version_requirements: !ruby/object:Gem::Requirement
155
- requirements:
156
- - - "~>"
157
- - !ruby/object:Gem::Version
158
- version: '0.92'
159
- - !ruby/object:Gem::Dependency
160
- name: yard
161
- requirement: !ruby/object:Gem::Requirement
162
- requirements:
163
- - - "~>"
164
- - !ruby/object:Gem::Version
165
- version: '0.9'
166
- type: :development
167
- prerelease: false
168
- version_requirements: !ruby/object:Gem::Requirement
169
- requirements:
170
- - - "~>"
171
- - !ruby/object:Gem::Version
172
- version: '0.9'
173
60
  description: A simple API for NVD CVE feeds
174
61
  email: alexandre.zanni@europe.com
175
62
  executables:
@@ -179,6 +66,7 @@ executables:
179
66
  extensions: []
180
67
  extra_rdoc_files: []
181
68
  files:
69
+ - ".github/FUNDING.yml"
182
70
  - ".gitignore"
183
71
  - ".gitlab-ci.yml"
184
72
  - ".gitlab/CONTRIBUTING.md"
@@ -218,24 +106,26 @@ metadata:
218
106
  homepage_uri: https://noraj.gitlab.io/nvd_api/
219
107
  source_code_uri: https://gitlab.com/noraj/nvd_api/tree/master
220
108
  wiki_uri: https://gitlab.com/noraj/nvd_api/wikis/home
221
- post_install_message:
109
+ funding_uri: https://github.com/sponsors/noraj
110
+ rubygems_mfa_required: 'true'
222
111
  rdoc_options: []
223
112
  require_paths:
224
113
  - lib
225
114
  required_ruby_version: !ruby/object:Gem::Requirement
226
115
  requirements:
227
- - - "~>"
116
+ - - ">="
228
117
  - !ruby/object:Gem::Version
229
- version: '2.4'
118
+ version: 3.1.0
119
+ - - "<"
120
+ - !ruby/object:Gem::Version
121
+ version: '4.0'
230
122
  required_rubygems_version: !ruby/object:Gem::Requirement
231
123
  requirements:
232
124
  - - ">="
233
125
  - !ruby/object:Gem::Version
234
126
  version: '0'
235
127
  requirements: []
236
- rubygems_version: 3.1.2
237
- signing_key:
128
+ rubygems_version: 3.6.2
238
129
  specification_version: 4
239
130
  summary: API for NVD CVE feeds
240
- test_files:
241
- - test/test_nvd_feed_api.rb
131
+ test_files: []