ndr_support 5.4.2 → 5.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
- SHA1:
3
- metadata.gz: 07ba3c21f982adf4857b352bf87e1046dd393090
4
- data.tar.gz: 5dd49f19587d0071d82565e1912a775ec065d986
2
+ SHA256:
3
+ metadata.gz: 6e21f71716e6733363c47fb4fb1f457ec616a913902729cb40fa8a227a77d530
4
+ data.tar.gz: 9b251bf890fb3d835c256fe81d136d51327e749970c21bad0a77529e12655384
5
5
  SHA512:
6
- metadata.gz: 58504a8eabba9ab32fb4ab2a0e6f935101614f92c7bcd7eb6db606d3404394290cd8f6f8d7921d7606ca42c1924e1183a7301882558a912c15c39c5644484088
7
- data.tar.gz: cdcbd43264a63a9427bfdca4c5e0f57e51a8d29fb3273e247d7c06004dba86d98b788effc60823b33e8ba1950ef60ab78217cb4cdba6b67ff2b6d5174c99ce67
6
+ metadata.gz: f603f2982d2615bfc0a4b1963f324ee633a1e9fa8248c575ae52a74403b3dc514a1cbec13b2f162f351e297d6d3df50e9cd8ace0692571f3f8202603fd969598
7
+ data.tar.gz: 9c3248c3286b5eba6ebf757a8e1f43958c585718f768de8798be3d482a5cfda28e36dfba1286782d9701d587aa3bc7465828f5c576e17bf0ccce377ce974743f
@@ -0,0 +1,21 @@
1
+ ## [Unreleased]
2
+ *no unreleased changes*
3
+
4
+ ## 5.5.0 / 2018-11-16
5
+ ### Added
6
+ * Add `ThreatScanner` to wrap ClamAV for virus detection (#10)
7
+
8
+ ### Fixed
9
+ * Added missing bank holidays for 2017-2019 (#9)
10
+
11
+ ## 5.4.2 / 2018-08-06
12
+ ### Fixed
13
+ * Fix Daterange equality comparisons
14
+
15
+ ## 5.4.1 / 2018-07-09
16
+ ### Fixed
17
+ * ensure Range#exclude? is available
18
+
19
+ ## 5.4.0 / 2018-05-09
20
+ ### Added
21
+ * Support Rails 5.2
@@ -14,6 +14,10 @@ file safety:
14
14
  risk. As a secondary protection, it''s excluded from the .gem file by ndr_support.gemspec'
15
15
  reviewed_by: brian.shand
16
16
  safe_revision: c88f5ac8c12fd657bb142144e0d3afaa7f9bc361
17
+ CHANGELOG.md:
18
+ comments:
19
+ reviewed_by: josh.pencheon
20
+ safe_revision: ea1f7dc9a164981570ee2ad7c38197fdb17a6880
17
21
  CODE_OF_CONDUCT.md:
18
22
  comments:
19
23
  reviewed_by: timgentry
@@ -57,15 +61,15 @@ file safety:
57
61
  lib/ndr_support.rb:
58
62
  comments:
59
63
  reviewed_by: josh.pencheon
60
- safe_revision: 2685f35c907af6968a69eabb5ab9424b490d0f40
64
+ safe_revision: ed8ff421cc9353456af13a37049a07ce2545aac1
61
65
  lib/ndr_support/array.rb:
62
66
  comments:
63
67
  reviewed_by: pauleves
64
68
  safe_revision: 4a4ed24d2cfe7e1736baadf4cf6e0fece6823be1
65
69
  lib/ndr_support/concerns/working_days.rb:
66
70
  comments:
67
- reviewed_by: pauleves
68
- safe_revision: 5f9c98dcad6f6889d2431eb98cf07b1f5c3e57be
71
+ reviewed_by: josh.pencheon
72
+ safe_revision: e5671bd9435490d521028d02bc91ccb47c74c580
69
73
  lib/ndr_support/date_and_time_extensions.rb:
70
74
  comments:
71
75
  reviewed_by: josh.pencheon
@@ -138,14 +142,18 @@ file safety:
138
142
  comments:
139
143
  reviewed_by: timgentry
140
144
  safe_revision: 62337584a32e5c30c2e9af7cd998a9df684885cc
145
+ lib/ndr_support/threat_scanner.rb:
146
+ comments:
147
+ reviewed_by: josh.pencheon
148
+ safe_revision: ed8ff421cc9353456af13a37049a07ce2545aac1
141
149
  lib/ndr_support/utf8_encoding.rb:
142
150
  comments:
143
- reviewed_by: timgentry
144
- safe_revision: 29595e6431587ff9b7db6e3ad3abbb3577bff99c
151
+ reviewed_by: josh.pencheon
152
+ safe_revision: 8e024a4bacfd36e172aad4b800f1960faae0b4b6
145
153
  lib/ndr_support/utf8_encoding/control_characters.rb:
146
154
  comments:
147
- reviewed_by: timgentry
148
- safe_revision: d210b982841611381a0df02d8f2db9c13e41e42f
155
+ reviewed_by: josh.pencheon
156
+ safe_revision: 8e024a4bacfd36e172aad4b800f1960faae0b4b6
149
157
  lib/ndr_support/utf8_encoding/force_binary.rb:
150
158
  comments:
151
159
  reviewed_by: timgentry
@@ -156,16 +164,16 @@ file safety:
156
164
  safe_revision: f7adf44fc2772e1926df37abfd9041d41c303328
157
165
  lib/ndr_support/version.rb:
158
166
  comments:
159
- reviewed_by: brian.shand
160
- safe_revision: a4ba32dcdab4a08db5851767282008ca3e7d8672
167
+ reviewed_by: josh.pencheon
168
+ safe_revision: ea1f7dc9a164981570ee2ad7c38197fdb17a6880
161
169
  lib/ndr_support/yaml/serialization_migration.rb:
162
170
  comments:
163
171
  reviewed_by: timgentry
164
172
  safe_revision: 29595e6431587ff9b7db6e3ad3abbb3577bff99c
165
173
  ndr_support.gemspec:
166
174
  comments:
167
- reviewed_by: brian.shand
168
- safe_revision: e8d08f6466acbdd4cbd6cbf90f1cfa45ffd656ec
175
+ reviewed_by: josh.pencheon
176
+ safe_revision: c197b91c07807345f2caf07ec4c14d8b9cbb4e53
169
177
  test/array_test.rb:
170
178
  comments:
171
179
  reviewed_by: timgentry
@@ -236,8 +244,12 @@ file safety:
236
244
  safe_revision: 1955bf30ffe581610981f0148569e252cba02926
237
245
  test/test_helper.rb:
238
246
  comments:
239
- reviewed_by: brian.shand
240
- safe_revision: 4533a155924f8a1415dd64e251a7f8311ece3bd8
247
+ reviewed_by: josh.pencheon
248
+ safe_revision: 34ae80f2952f0bfd18688541862774cbaaa6c5f5
249
+ test/threat_scanner_test.rb:
250
+ comments:
251
+ reviewed_by: josh.pencheon
252
+ safe_revision: ed8ff421cc9353456af13a37049a07ce2545aac1
241
253
  test/utf8_encoding/control_characters_test.rb:
242
254
  comments:
243
255
  reviewed_by: timgentry
@@ -13,6 +13,7 @@ require 'ndr_support/safe_file'
13
13
  require 'ndr_support/safe_path'
14
14
  require 'ndr_support/string/cleaning'
15
15
  require 'ndr_support/string/conversions'
16
+ require 'ndr_support/threat_scanner'
16
17
  require 'ndr_support/utf8_encoding'
17
18
  require 'ndr_support/version'
18
19
  require 'ndr_support/yaml/serialization_migration'
@@ -50,6 +50,33 @@ module WorkingDays
50
50
  '2016-08-29', # Monday - Summer bank holiday
51
51
  '2016-12-26', # Monday - Boxing Day
52
52
  '2016-12-27', # Tuesday - Christmas Day (substitute day)
53
+ # 2017
54
+ '2017-01-02', # Monday - New Year's Day
55
+ '2017-04-14', # Friday - Good Friday
56
+ '2017-04-17', # Monday - Easter Monday
57
+ '2017-05-01', # Monday - Early May bank holiday
58
+ '2017-05-29', # Monday - Spring bank holiday
59
+ '2017-08-28', # Monday - Summer bank holiday
60
+ '2017-12-25', # Monday - Christmas Day
61
+ '2017-12-26', # Tuesday - Boxing Day
62
+ # 2018
63
+ '2018-01-01', # Monday - New Year's Day
64
+ '2018-03-30', # Friday - Good Friday
65
+ '2018-04-02', # Monday - Easter Monday
66
+ '2018-05-07', # Monday - Early May bank holiday
67
+ '2018-05-28', # Monday - Spring bank holiday
68
+ '2018-08-27', # Monday - Summer bank holiday
69
+ '2018-12-25', # Tuesday - Christmas Day
70
+ '2018-12-26', # Wednesday - Boxing Day
71
+ # 2019
72
+ '2019-01-01', # Tuesday - New Year's Day
73
+ '2019-04-19', # Friday - Good Friday
74
+ '2019-04-22', # Monday - Easter Monday
75
+ '2019-05-06', # Monday - Early May bank holiday
76
+ '2019-05-27', # Monday - Spring bank holiday
77
+ '2019-08-26', # Monday - Summer bank holiday
78
+ '2019-12-25', # Wednesday - Christmas Day
79
+ '2019-12-26', # Thursday - Boxing Day
53
80
  ].map { |str| Date.parse(str) }
54
81
 
55
82
  # How many complete working days there are until the given
@@ -0,0 +1,64 @@
1
+ require 'English'
2
+
3
+ # Runs a virus/malware check against the given path, using ClamAV.
4
+ #
5
+ # Sample usage:
6
+ #
7
+ # # Call with a file object:
8
+ # ThreatScanner.new(@unknown_tempfile).check!
9
+ #
10
+ # # ...or with a path:
11
+ # ThreatScanner.new('path/to/README').check!
12
+ #
13
+ class ThreatScanner
14
+ class Error < StandardError; end
15
+
16
+ class MissingFileError < Error; end
17
+ class MissingScannerError < Error; end
18
+ class ScannerOperationError < Error; end
19
+ class ThreatDetectedError < Error; end
20
+
21
+ def self.installed?
22
+ system('which clamdscan > /dev/null 2>&1')
23
+ end
24
+
25
+ attr_reader :path
26
+
27
+ def initialize(path)
28
+ @path = path.respond_to?(:path) ? path.path : path
29
+ end
30
+
31
+ # Returns true if the given file is deemed safe, and false if it could not
32
+ # be checked. Raises if a threat is detected, or the file did not exist.
33
+ def check
34
+ check!
35
+ rescue MissingScannerError, ScannerOperationError
36
+ false
37
+ end
38
+
39
+ # Returns true if the given file is deemed safe, and raises an exception
40
+ # otherwise (if the file is unsafe / does not exist / scanner broke etc).
41
+ def check!
42
+ check_existence! && check_installed! && run_scanner!
43
+ end
44
+
45
+ private
46
+
47
+ def check_existence!
48
+ File.exist?(@path) || raise(MissingFileError, "#{@path} does not exist!")
49
+ end
50
+
51
+ def check_installed!
52
+ self.class.installed? || raise(MissingScannerError, 'no scanner is available')
53
+ end
54
+
55
+ def run_scanner!
56
+ `clamdscan --fdpass --quiet #{Shellwords.escape(@path)}`
57
+
58
+ case $CHILD_STATUS.exitstatus
59
+ when 0 then true
60
+ when 1 then raise(ThreatDetectedError, "possible virus detected at #{@path}!")
61
+ else raise(ScannerOperationError, 'the scan was unable to complete')
62
+ end
63
+ end
64
+ end
@@ -16,6 +16,9 @@ module UTF8Encoding
16
16
  # How should unmappable characters be escaped, when forcing encoding?
17
17
  REPLACEMENT_SCHEME = lambda { |char| '0x' + char.ord.to_s(16).rjust(2, '0') }
18
18
 
19
+ UTF8 = 'UTF-8'.freeze
20
+ BINARY = 'BINARY'.freeze
21
+
19
22
  # Returns a new string with valid UTF-8 encoding,
20
23
  # or raises an exception if encoding fails.
21
24
  def ensure_utf8(string, source_encoding = nil)
@@ -51,7 +54,7 @@ module UTF8Encoding
51
54
  ensure_utf8!(string, source_encoding)
52
55
  rescue UTF8CoercionError
53
56
  # ...before going back-to-basics, and replacing things that don't map:
54
- string.encode!('UTF-8', 'BINARY', :fallback => REPLACEMENT_SCHEME)
57
+ string.encode!(UTF8, BINARY, :fallback => REPLACEMENT_SCHEME)
55
58
  end
56
59
 
57
60
  private
@@ -60,7 +63,7 @@ module UTF8Encoding
60
63
  candidates.detect do |encoding|
61
64
  begin
62
65
  # Attempt to encode as UTF-8 from source `encoding`:
63
- string.encode!('UTF-8', encoding)
66
+ string.encode!(UTF8, encoding)
64
67
  # If that worked, we're done; otherwise, move on.
65
68
  string.valid_encoding?
66
69
  rescue EncodingError
@@ -5,9 +5,7 @@ module UTF8Encoding
5
5
  # escaped, using standard replacement scheme.
6
6
  module ControlCharacters
7
7
  # The range of characters we consider:
8
- CONTROL_CHARACTERS = /[\x00-\x1f]|\x7f/
9
- # Exceptions that are allowed:
10
- ALLOWED_CONTROL_CHARACTERS = %W( \x09 \x0a \x0d )
8
+ CONTROL_CHARACTERS = /[\x00-\x08]|[\x0b-\x0c]|[\x0e-\x1f]|\x7f/
11
9
 
12
10
  # Recursively escape any control characters in `object`.
13
11
  def escape_control_chars_in_object!(object)
@@ -31,11 +29,7 @@ module UTF8Encoding
31
29
  # Escapes in-place any control characters in `string`, before returning it.
32
30
  def escape_control_chars!(string)
33
31
  string.gsub!(CONTROL_CHARACTERS) do |character|
34
- if ALLOWED_CONTROL_CHARACTERS.include?(character)
35
- character
36
- else
37
- UTF8Encoding::REPLACEMENT_SCHEME[character]
38
- end
32
+ UTF8Encoding::REPLACEMENT_SCHEME[character]
39
33
  end
40
34
  string
41
35
  end
@@ -3,5 +3,5 @@
3
3
  # This defines the NdrSupport version. If you change it, rebuild and commit the gem.
4
4
  # Use "rake build" to build the gem, see rake -T for all bundler rake tasks.
5
5
  module NdrSupport
6
- VERSION = '5.4.2'
6
+ VERSION = '5.5.0'
7
7
  end
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
32
32
  spec.add_development_dependency 'minitest', '>= 5.0.0'
33
33
  spec.add_development_dependency 'mocha', '~> 1.1'
34
34
 
35
- spec.add_development_dependency 'ndr_dev_support', '~> 3.0'
35
+ spec.add_development_dependency 'ndr_dev_support', '~> 3.1', '>= 3.1.3'
36
36
  spec.add_development_dependency 'guard'
37
37
  spec.add_development_dependency 'listen', '< 3.1' # Bundle 1.12 should be (but isn't) resolving Ruby 2.1 issue
38
38
  spec.add_development_dependency 'guard-rubocop'
@@ -3,7 +3,7 @@ SimpleCov.start
3
3
 
4
4
  require 'minitest/autorun'
5
5
  require 'minitest/unit'
6
- require 'mocha/mini_test'
6
+ require 'mocha/minitest'
7
7
 
8
8
  require 'active_record'
9
9
  require 'active_support/time'
@@ -0,0 +1,75 @@
1
+ require 'test_helper'
2
+
3
+ # This tests our ThreatScanner extension
4
+ class ThreatScannerTest < Minitest::Test
5
+ def setup
6
+ @tempfile = Tempfile.new
7
+ @scanner = ThreatScanner.new(@tempfile)
8
+
9
+ ThreatScanner.stubs(installed?: true)
10
+ ThreatScanner.any_instance.stubs(:`)
11
+ end
12
+
13
+ def teardown
14
+ @tempfile.close!
15
+ end
16
+
17
+ test 'can be initialised with a file' do
18
+ assert_equal @tempfile.path, @scanner.path
19
+ end
20
+
21
+ test 'can be initialised with a path' do
22
+ scanner = ThreatScanner.new(@tempfile.path)
23
+ assert_equal @tempfile.path, scanner.path
24
+ end
25
+
26
+ test 'returns true if no threat is detected (when being strict)' do
27
+ Process::Status.any_instance.stubs(exitstatus: 0)
28
+ assert_equal true, @scanner.check!
29
+ end
30
+
31
+ test 'raises if a threat is detected (when being strict)' do
32
+ Process::Status.any_instance.stubs(exitstatus: 1)
33
+ assert_raises(ThreatScanner::ThreatDetectedError) { @scanner.check! }
34
+ end
35
+
36
+ test 'raises if the file does not exist (when being strict)' do
37
+ @tempfile.close!
38
+ assert_raises(ThreatScanner::MissingFileError) { @scanner.check! }
39
+ end
40
+
41
+ test 'raises if ClamAV is not installed (when being strict)' do
42
+ ThreatScanner.stubs(installed?: false)
43
+ assert_raises(ThreatScanner::MissingScannerError) { @scanner.check! }
44
+ end
45
+
46
+ test 'raises if there is an operational error (when being strict)' do
47
+ Process::Status.any_instance.stubs(exitstatus: 2)
48
+ assert_raises(ThreatScanner::ScannerOperationError) { @scanner.check! }
49
+ end
50
+
51
+ test 'returns true if no threat is detected (when being relaxed)' do
52
+ Process::Status.any_instance.stubs(exitstatus: 0)
53
+ assert_equal true, @scanner.check
54
+ end
55
+
56
+ test 'raises if a threat is detected (when being relaxed)' do
57
+ Process::Status.any_instance.stubs(exitstatus: 1)
58
+ assert_raises(ThreatScanner::ThreatDetectedError) { @scanner.check }
59
+ end
60
+
61
+ test 'raises if the file does not exist (when being relaxed)' do
62
+ @tempfile.close!
63
+ assert_raises(ThreatScanner::MissingFileError) { @scanner.check }
64
+ end
65
+
66
+ test 'returns false if ClamAV is not installed (when being relaxed)' do
67
+ ThreatScanner.stubs(installed?: false)
68
+ assert_equal false, @scanner.check
69
+ end
70
+
71
+ test 'returns false if there is an operational error (when being relaxed)' do
72
+ Process::Status.any_instance.stubs(exitstatus: 2)
73
+ assert_equal false, @scanner.check
74
+ end
75
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ndr_support
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.4.2
4
+ version: 5.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - NCRS Development Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-07 00:00:00.000000000 Z
11
+ date: 2018-11-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -112,14 +112,20 @@ dependencies:
112
112
  requirements:
113
113
  - - "~>"
114
114
  - !ruby/object:Gem::Version
115
- version: '3.0'
115
+ version: '3.1'
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: 3.1.3
116
119
  type: :development
117
120
  prerelease: false
118
121
  version_requirements: !ruby/object:Gem::Requirement
119
122
  requirements:
120
123
  - - "~>"
121
124
  - !ruby/object:Gem::Version
122
- version: '3.0'
125
+ version: '3.1'
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: 3.1.3
123
129
  - !ruby/object:Gem::Dependency
124
130
  name: guard
125
131
  requirement: !ruby/object:Gem::Requirement
@@ -226,6 +232,7 @@ extra_rdoc_files: []
226
232
  files:
227
233
  - ".gitignore"
228
234
  - ".rubocop.yml"
235
+ - CHANGELOG.md
229
236
  - CODE_OF_CONDUCT.md
230
237
  - Gemfile
231
238
  - Guardfile
@@ -258,6 +265,7 @@ files:
258
265
  - lib/ndr_support/string/cleaning.rb
259
266
  - lib/ndr_support/string/conversions.rb
260
267
  - lib/ndr_support/tasks.rb
268
+ - lib/ndr_support/threat_scanner.rb
261
269
  - lib/ndr_support/utf8_encoding.rb
262
270
  - lib/ndr_support/utf8_encoding/control_characters.rb
263
271
  - lib/ndr_support/utf8_encoding/force_binary.rb
@@ -283,6 +291,7 @@ files:
283
291
  - test/string/cleaning_test.rb
284
292
  - test/string/conversions_test.rb
285
293
  - test/test_helper.rb
294
+ - test/threat_scanner_test.rb
286
295
  - test/utf8_encoding/control_characters_test.rb
287
296
  - test/utf8_encoding/force_binary_test.rb
288
297
  - test/utf8_encoding_test.rb
@@ -307,7 +316,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
307
316
  version: '0'
308
317
  requirements: []
309
318
  rubyforge_project:
310
- rubygems_version: 2.5.2.3
319
+ rubygems_version: 2.7.6
311
320
  signing_key:
312
321
  specification_version: 4
313
322
  summary: NDR Support library
@@ -330,6 +339,7 @@ test_files:
330
339
  - test/string/cleaning_test.rb
331
340
  - test/string/conversions_test.rb
332
341
  - test/test_helper.rb
342
+ - test/threat_scanner_test.rb
333
343
  - test/utf8_encoding/control_characters_test.rb
334
344
  - test/utf8_encoding/force_binary_test.rb
335
345
  - test/utf8_encoding_test.rb