ndr_support 5.4.2 → 5.7.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: e06c6fad074bb00f7ba16334d194b9fcf369147688dbd1f22dcd1cca86e71073
4
+ data.tar.gz: 7ede15deb1aec6e6ee02d627437eb7c94810755dbcb717db9212c17c2f09ca3e
5
5
  SHA512:
6
- metadata.gz: 58504a8eabba9ab32fb4ab2a0e6f935101614f92c7bcd7eb6db606d3404394290cd8f6f8d7921d7606ca42c1924e1183a7301882558a912c15c39c5644484088
7
- data.tar.gz: cdcbd43264a63a9427bfdca4c5e0f57e51a8d29fb3273e247d7c06004dba86d98b788effc60823b33e8ba1950ef60ab78217cb4cdba6b67ff2b6d5174c99ce67
6
+ metadata.gz: f3b03a27b86891d3cb52dcf3fab222cf3bd42b05cb859918142dd6791a6dc18e5ebba0075911d9d177e7451a5b447b0cf6324455641f913ebb86c78808cf5843
7
+ data.tar.gz: e5d89586818d5a50a1c3211086ce812d485e90b3080c46986be570ec32e7c740f6d5c312a8580ef727243c5910b60d5acd13f8e94276e0fa07dbf922879a9a85
@@ -0,0 +1,41 @@
1
+ ## [Unreleased]
2
+ *no unreleased changes*
3
+
4
+ ## 5.7.0 / 2020-06-30
5
+ ## Added
6
+ * Handle three char months in Daterange
7
+
8
+ ## 5.6.1 / 2020-01-02
9
+ ## Fixed
10
+ * Fix issue with 2020 public holiday
11
+ * Support 2021 public holidays
12
+ * Ensure dateranges up to 2030 are supported
13
+
14
+ ## 5.6.0 / 2019-08-29
15
+ ### Added
16
+ * Add `Integer#working_days_since`. (#11)
17
+
18
+ ## 5.5.1 / 2019-05-15
19
+ ### Fixed
20
+ * Support Ruby 2.6, Rails 6.0. Minimum Ruby/Rails versions are now 2.5/5.2
21
+ * Warn when WorkingDays lookup is getting stale
22
+ * Improved date parsing in `String#to_date`
23
+
24
+ ## 5.5.0 / 2018-11-16
25
+ ### Added
26
+ * Add `ThreatScanner` to wrap ClamAV for virus detection (#10)
27
+
28
+ ### Fixed
29
+ * Added missing bank holidays for 2017-2019 (#9)
30
+
31
+ ## 5.4.2 / 2018-08-06
32
+ ### Fixed
33
+ * Fix Daterange equality comparisons
34
+
35
+ ## 5.4.1 / 2018-07-09
36
+ ### Fixed
37
+ * ensure Range#exclude? is available
38
+
39
+ ## 5.4.0 / 2018-05-09
40
+ ### Added
41
+ * Support Rails 5.2
@@ -12,8 +12,12 @@ file safety:
12
12
  comments: 'diff failed; reviewed whole file. Revision c88f5ac8c12fd657bb142144e0d3afaa7f9bc361:
13
13
  Slack notification secret is public/private key encrypted, so not a disclosure
14
14
  risk. As a secondary protection, it''s excluded from the .gem file by ndr_support.gemspec'
15
- reviewed_by: brian.shand
16
- safe_revision: c88f5ac8c12fd657bb142144e0d3afaa7f9bc361
15
+ reviewed_by: josh.pencheon
16
+ safe_revision: 0cfcfac5ddcd721a67dcd23f04cbf6bc2278b922
17
+ CHANGELOG.md:
18
+ comments:
19
+ reviewed_by: ollietulloch
20
+ safe_revision: ce582c10aa4ddddcd22f907d6228cc7bb324a280
17
21
  CODE_OF_CONDUCT.md:
18
22
  comments:
19
23
  reviewed_by: timgentry
@@ -38,42 +42,34 @@ file safety:
38
42
  comments:
39
43
  reviewed_by: timgentry
40
44
  safe_revision: e33e9dae7f38bc449ce9276515a539836dbbbd53
41
- gemfiles/Gemfile.rails42:
42
- comments:
43
- reviewed_by: pauleves
44
- safe_revision: f76ad0fe72d42b1ff37553c8194935a8b93a6848
45
- gemfiles/Gemfile.rails50:
46
- comments:
47
- reviewed_by: josh.pencheon
48
- safe_revision: 55ed1c2a18b9cc4d1d996ee69419f5ee38f87746
49
- gemfiles/Gemfile.rails51:
50
- comments:
51
- reviewed_by: brian.shand
52
- safe_revision: 4e87fd9d64fc0f15b359ba60fc48cda54453c647
53
45
  gemfiles/Gemfile.rails52:
54
46
  comments:
55
47
  reviewed_by: josh.pencheon
56
48
  safe_revision: 8a6bedae77d33d0db1b67eaed7972870b6afc993
57
- lib/ndr_support.rb:
49
+ gemfiles/Gemfile.rails60:
58
50
  comments:
59
51
  reviewed_by: josh.pencheon
60
- safe_revision: 2685f35c907af6968a69eabb5ab9424b490d0f40
52
+ safe_revision: 0cfcfac5ddcd721a67dcd23f04cbf6bc2278b922
53
+ lib/ndr_support.rb:
54
+ comments:
55
+ reviewed_by: brian.shand
56
+ safe_revision: 44fbdf72f47f4022c7dc9148150ebc18589dac8f
61
57
  lib/ndr_support/array.rb:
62
58
  comments:
63
59
  reviewed_by: pauleves
64
60
  safe_revision: 4a4ed24d2cfe7e1736baadf4cf6e0fece6823be1
65
61
  lib/ndr_support/concerns/working_days.rb:
66
62
  comments:
67
- reviewed_by: pauleves
68
- safe_revision: 5f9c98dcad6f6889d2431eb98cf07b1f5c3e57be
63
+ reviewed_by: josh.pencheon
64
+ safe_revision: fe6c3beff445e3c84ed0c89f08e1ab10bfb00587
69
65
  lib/ndr_support/date_and_time_extensions.rb:
70
66
  comments:
71
67
  reviewed_by: josh.pencheon
72
- safe_revision: 3553509e52b3697d361cfa4c6f8a67754ed942d3
68
+ safe_revision: c1158eccb843b637b4dd82815dc7c081f12b93e4
73
69
  lib/ndr_support/daterange.rb:
74
70
  comments:
75
- reviewed_by: brian.shand
76
- safe_revision: c7ed8bc16be8ec803dfaeb3473fbc538b54587ec
71
+ reviewed_by: ollietulloch
72
+ safe_revision: 9a4b8e53f477725c2c2be5000b3c9e66f07d7389
77
73
  lib/ndr_support/hash.rb:
78
74
  comments:
79
75
  reviewed_by: pauleves
@@ -90,6 +86,10 @@ file safety:
90
86
  comments:
91
87
  reviewed_by: josh.pencheon
92
88
  safe_revision: 2685f35c907af6968a69eabb5ab9424b490d0f40
89
+ lib/ndr_support/integer/working_days.rb:
90
+ comments:
91
+ reviewed_by: josh.pencheon
92
+ safe_revision: c1158eccb843b637b4dd82815dc7c081f12b93e4
93
93
  lib/ndr_support/nil.rb:
94
94
  comments:
95
95
  reviewed_by: pauleves
@@ -132,20 +132,24 @@ file safety:
132
132
  safe_revision: 60cc69774d5aff92252558feae9604544def7583
133
133
  lib/ndr_support/string/conversions.rb:
134
134
  comments:
135
- reviewed_by: brian.shand
136
- safe_revision: 0a06fed3e7530185497f786decdb77a62d35e101
135
+ reviewed_by: ollietulloch
136
+ safe_revision: 9a4b8e53f477725c2c2be5000b3c9e66f07d7389
137
137
  lib/ndr_support/tasks.rb:
138
138
  comments:
139
139
  reviewed_by: timgentry
140
140
  safe_revision: 62337584a32e5c30c2e9af7cd998a9df684885cc
141
+ lib/ndr_support/threat_scanner.rb:
142
+ comments:
143
+ reviewed_by: josh.pencheon
144
+ safe_revision: ed8ff421cc9353456af13a37049a07ce2545aac1
141
145
  lib/ndr_support/utf8_encoding.rb:
142
146
  comments:
143
- reviewed_by: timgentry
144
- safe_revision: 29595e6431587ff9b7db6e3ad3abbb3577bff99c
147
+ reviewed_by: josh.pencheon
148
+ safe_revision: 8e024a4bacfd36e172aad4b800f1960faae0b4b6
145
149
  lib/ndr_support/utf8_encoding/control_characters.rb:
146
150
  comments:
147
- reviewed_by: timgentry
148
- safe_revision: d210b982841611381a0df02d8f2db9c13e41e42f
151
+ reviewed_by: josh.pencheon
152
+ safe_revision: 8e024a4bacfd36e172aad4b800f1960faae0b4b6
149
153
  lib/ndr_support/utf8_encoding/force_binary.rb:
150
154
  comments:
151
155
  reviewed_by: timgentry
@@ -156,28 +160,32 @@ file safety:
156
160
  safe_revision: f7adf44fc2772e1926df37abfd9041d41c303328
157
161
  lib/ndr_support/version.rb:
158
162
  comments:
159
- reviewed_by: brian.shand
160
- safe_revision: a4ba32dcdab4a08db5851767282008ca3e7d8672
163
+ reviewed_by: ollietulloch
164
+ safe_revision: ce582c10aa4ddddcd22f907d6228cc7bb324a280
165
+ lib/ndr_support/working_days.rb:
166
+ comments:
167
+ reviewed_by: josh.pencheon
168
+ safe_revision: c1158eccb843b637b4dd82815dc7c081f12b93e4
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: c685e94ddb1cf2814eb145e87a4c8bc6bced59fb
169
177
  test/array_test.rb:
170
178
  comments:
171
179
  reviewed_by: timgentry
172
180
  safe_revision: 2a5d30674dc9dde336e1dbbbf3c8a98905647432
173
181
  test/concerns/working_days_test.rb:
174
182
  comments:
175
- reviewed_by: timgentry
176
- safe_revision: 506a317e59d0ccb5b32d813b74d822f35a55cea9
183
+ reviewed_by: josh.pencheon
184
+ safe_revision: fe6c3beff445e3c84ed0c89f08e1ab10bfb00587
177
185
  test/daterange_test.rb:
178
186
  comments:
179
- reviewed_by: brian.shand
180
- safe_revision: c7ed8bc16be8ec803dfaeb3473fbc538b54587ec
187
+ reviewed_by: ollietulloch
188
+ safe_revision: 9a4b8e53f477725c2c2be5000b3c9e66f07d7389
181
189
  test/hash_test.rb:
182
190
  comments:
183
191
  reviewed_by: timgentry
@@ -190,6 +198,10 @@ file safety:
190
198
  comments:
191
199
  reviewed_by: josh.pencheon
192
200
  safe_revision: 2685f35c907af6968a69eabb5ab9424b490d0f40
201
+ test/integer/working_days_test.rb:
202
+ comments:
203
+ reviewed_by: josh.pencheon
204
+ safe_revision: c1158eccb843b637b4dd82815dc7c081f12b93e4
193
205
  test/nil_test.rb:
194
206
  comments:
195
207
  reviewed_by: timgentry
@@ -232,12 +244,16 @@ file safety:
232
244
  safe_revision: 60cc69774d5aff92252558feae9604544def7583
233
245
  test/string/conversions_test.rb:
234
246
  comments:
235
- reviewed_by: brian.shand
236
- safe_revision: 1955bf30ffe581610981f0148569e252cba02926
247
+ reviewed_by: ollietulloch
248
+ safe_revision: 9a4b8e53f477725c2c2be5000b3c9e66f07d7389
237
249
  test/test_helper.rb:
238
250
  comments:
239
- reviewed_by: brian.shand
240
- safe_revision: 4533a155924f8a1415dd64e251a7f8311ece3bd8
251
+ reviewed_by: josh.pencheon
252
+ safe_revision: 34ae80f2952f0bfd18688541862774cbaaa6c5f5
253
+ test/threat_scanner_test.rb:
254
+ comments:
255
+ reviewed_by: josh.pencheon
256
+ safe_revision: ed8ff421cc9353456af13a37049a07ce2545aac1
241
257
  test/utf8_encoding/control_characters_test.rb:
242
258
  comments:
243
259
  reviewed_by: timgentry
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec path: '..'
4
+
5
+ gem 'activerecord', '~> 6.0.0rc1'
6
+ gem 'activesupport', '~> 6.0.0rc1'
@@ -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'
@@ -20,3 +21,5 @@ require 'ndr_support/yaml/serialization_migration'
20
21
  module NdrSupport
21
22
  # Your code goes here...
22
23
  end
24
+
25
+ WorkingDays.check_lookup
@@ -3,6 +3,8 @@ require 'active_support/time'
3
3
  # This module contains logic for #working_days_until, #weekday?, and #public_holiday?.
4
4
  module WorkingDays
5
5
  WEEK_DAYS = 1..5
6
+
7
+ # TODO: could we use https://github.com/alphagov/gds-api-adapters ?
6
8
  HOLIDAYS = [ # Sourced from https://www.gov.uk/bank-holidays
7
9
  # 2012
8
10
  '2012-01-02', # Monday - New Year's Day (substitute day)
@@ -50,14 +52,66 @@ module WorkingDays
50
52
  '2016-08-29', # Monday - Summer bank holiday
51
53
  '2016-12-26', # Monday - Boxing Day
52
54
  '2016-12-27', # Tuesday - Christmas Day (substitute day)
55
+ # 2017
56
+ '2017-01-02', # Monday - New Year's Day
57
+ '2017-04-14', # Friday - Good Friday
58
+ '2017-04-17', # Monday - Easter Monday
59
+ '2017-05-01', # Monday - Early May bank holiday
60
+ '2017-05-29', # Monday - Spring bank holiday
61
+ '2017-08-28', # Monday - Summer bank holiday
62
+ '2017-12-25', # Monday - Christmas Day
63
+ '2017-12-26', # Tuesday - Boxing Day
64
+ # 2018
65
+ '2018-01-01', # Monday - New Year's Day
66
+ '2018-03-30', # Friday - Good Friday
67
+ '2018-04-02', # Monday - Easter Monday
68
+ '2018-05-07', # Monday - Early May bank holiday
69
+ '2018-05-28', # Monday - Spring bank holiday
70
+ '2018-08-27', # Monday - Summer bank holiday
71
+ '2018-12-25', # Tuesday - Christmas Day
72
+ '2018-12-26', # Wednesday - Boxing Day
73
+ # 2019
74
+ '2019-01-01', # Tuesday - New Year's Day
75
+ '2019-04-19', # Friday - Good Friday
76
+ '2019-04-22', # Monday - Easter Monday
77
+ '2019-05-06', # Monday - Early May bank holiday
78
+ '2019-05-27', # Monday - Spring bank holiday
79
+ '2019-08-26', # Monday - Summer bank holiday
80
+ '2019-12-25', # Wednesday - Christmas Day
81
+ '2019-12-26', # Thursday - Boxing Day
82
+ # 2020
83
+ '2020-01-01', # Wednesday - New Year's Day
84
+ '2020-04-10', # Friday - Good Friday
85
+ '2020-04-13', # Monday - Easter Monday
86
+ '2020-05-08', # Friday - Early May bank holiday (moved from Monday)
87
+ '2020-05-25', # Monday - Spring bank holiday
88
+ '2020-08-31', # Monday - Summer bank holiday
89
+ '2020-12-25', # Friday - Christmas Day
90
+ '2020-12-28', # Monday - Boxing Day (substitute day)
91
+ # 2021
92
+ '2021-01-01', # Friday - New Year’s Day
93
+ '2021-04-02', # Friday - Good Friday
94
+ '2021-04-05', # Monday - Easter Monday
95
+ '2021-05-03', # Monday - Early May bank holiday
96
+ '2021-05-31', # Monday - Spring bank holiday
97
+ '2021-08-30', # Monday - Summer bank holiday
98
+ '2021-12-27', # Monday - Christmas Day
99
+ '2021-12-28', # Tuesday - Boxing Day
53
100
  ].map { |str| Date.parse(str) }
54
101
 
102
+ def self.check_lookup
103
+ return true if HOLIDAYS.max >= 1.year.from_now
104
+
105
+ warn "NdrSupport's WorkingDays extension has under a year of future data. Check for updates?"
106
+ false
107
+ end
108
+
55
109
  # How many complete working days there are until the given
56
110
  # `other`. Returns negative number if `other` is earlier.
57
111
  def working_days_until(other)
58
112
  return -other.working_days_until(self) if other < self
59
113
 
60
- whole_days_to(other).count do |day|
114
+ count_whole_days_to(other) do |day|
61
115
  day.weekday? && !day.public_holiday?
62
116
  end
63
117
  end
@@ -66,7 +120,7 @@ module WorkingDays
66
120
  # `other`. Returns negative number if `other` is earlier.
67
121
  def weekdays_until(other)
68
122
  return -other.weekdays_until(self) if other < self
69
- whole_days_to(other).count(&:weekday?)
123
+ count_whole_days_to(other, &:weekday?)
70
124
  end
71
125
 
72
126
  # Is this a weekday?
@@ -81,14 +135,15 @@ module WorkingDays
81
135
 
82
136
  private
83
137
 
84
- def whole_days_to(other)
85
- [self].tap do |days|
86
- loop do
87
- next_day = days.last + 1.day
88
- next_day <= other ? days.push(next_day) : break
89
- end
138
+ def count_whole_days_to(other, &block)
139
+ day = self + 1.day
140
+ count = 0
90
141
 
91
- days.shift # Drop `self` off the front
142
+ while day <= other
143
+ count += 1 if block.call(day)
144
+ day += 1.day
92
145
  end
146
+
147
+ count
93
148
  end
94
149
  end
@@ -1,8 +1,6 @@
1
1
  require 'yaml'
2
2
  require 'date'
3
-
4
- require 'ndr_support/concerns/working_days'
5
- [Time, Date, DateTime].each { |klass| klass.send(:include, WorkingDays) }
3
+ require 'ndr_support/working_days'
6
4
 
7
5
  class Date
8
6
  # to_iso output must be SQL safe for security reasons
@@ -6,7 +6,7 @@ require 'ndr_support/integer/julian_date_conversions'
6
6
  class Daterange
7
7
  attr_reader :date1, :date2, :source
8
8
 
9
- OKYEARS = 1880..2020
9
+ OKYEARS = 1880..2030
10
10
 
11
11
  def self.extract(dates_string)
12
12
  dates_string.to_s.split(',').map { |str| new(str) }
@@ -135,12 +135,12 @@ class Daterange
135
135
 
136
136
  # Update our attribute values using a string representation of the date(s).
137
137
  # +s+ consists of one or more dates separated with spaces.
138
- # Each date can be in various formats, e.g. d/m/yyyy, ddmmyyyy, yyyy-mm-dd.
139
- # Each date can omit days or months, e.g. yyyy, dd/yyyy, yyyy-mm
138
+ # Each date can be in various formats, e.g. d/m/yyyy, ddmmyyyy, yyyy-mm-dd, dd-mon-yyyy
139
+ # Each date can omit days or months, e.g. yyyy, dd/yyyy, yyyy-mm, mon-yyyy
140
140
  def source=(s)
141
141
  @source = s
142
142
  ss = s.upcase.sub(/TO/, ' ') # accept default _to_s format
143
- if ss =~ /[^0-9\-\/\. ]/ # only allow digits, hyphen, slash, dot, space
143
+ if ss =~ /[^\w0-9\-\/\. ]/i # only allow letters, digits, hyphen, slash, dot, space
144
144
  @date1 = @date2 = nil
145
145
  else
146
146
  da = [] # temporary array of arrays of dates
@@ -184,7 +184,9 @@ class Daterange
184
184
  # e.g year only or year/month only) and return an array of 1..3 integers
185
185
  # representing the year, month and day
186
186
  def date_string_parts(ds)
187
- if ds =~ /([\/\.\-])/ # find a slash or dot or hyphen
187
+ if ds =~ /\A(\d{1,2}[\/\.\-])?\w{3}[\/\.\-]\d{4}\z/i # dd[-/.]mon[-/.]yyyy or mon[-/.]yyyy
188
+ result = handle_three_char_months(ds)
189
+ elsif ds =~ /([\/\.\-])/ # find a slash or dot or hyphen
188
190
  delimiter = $1
189
191
  result = ds.split(delimiter)
190
192
  elsif ds.length == 8 # ddmmyyyy
@@ -200,4 +202,21 @@ class Daterange
200
202
  result.reverse! unless delimiter == '-' # change to YMD if not ISO format
201
203
  result.collect(&:to_i)
202
204
  end
205
+
206
+ def handle_three_char_months(datestring)
207
+ delimiter = datestring.match(%r{[\/\.\-]})[0]
208
+ components = datestring.split(delimiter)
209
+
210
+ if datestring =~ /\A\d{1,2}#{delimiter}\w{3}#{delimiter}\d{4}\z/i
211
+ month = abbreviated_month_index_for(components[1])
212
+ month.nil? ? [] : [components.first, month, components.last]
213
+ elsif datestring =~ /\A\w{3}#{delimiter}\d{4}\z/i
214
+ month = abbreviated_month_index_for(components.first)
215
+ month.nil? ? [] : [month, components.last]
216
+ end
217
+ end
218
+
219
+ def abbreviated_month_index_for(string)
220
+ Date::ABBR_MONTHNAMES.index(string.capitalize)
221
+ end
203
222
  end
@@ -0,0 +1,11 @@
1
+ # Mixin for working_days
2
+ class Integer
3
+ # Returns a date of the number of working days since a given date
4
+ def working_days_since(date)
5
+ times do
6
+ date = date.next
7
+ date = date.next while date.public_holiday? || !date.weekday?
8
+ end
9
+ date
10
+ end
11
+ end
@@ -85,7 +85,6 @@ class String
85
85
  # Try to convert the string value into a date.
86
86
  # If given a pattern, use it to parse date, otherwise use default setting to parse it
87
87
  def to_date(pattern = nil)
88
- return '' if empty? # TODO: check if this is used... :/
89
88
  return nil if blank?
90
89
 
91
90
  pattern = '%d%m%Y' if 'ddmmyyyy' == pattern
@@ -112,13 +111,13 @@ class String
112
111
 
113
112
  if ['yyyy/dd/mm', 'mm/dd/yyyy'].include?(pattern)
114
113
  month, day = day, month
115
- elsif 8 == length && self !~ /\d{8}/
114
+ elsif 8 == length && self =~ /\A\d{2}[^A-Z0-9]\d{2}[^A-Z0-9]\d{2}\z/i
116
115
  # dd/mm/yy, rather than yyyymmdd
117
116
  year, day = day, year
118
117
  year += 100 if year <= Ourdate.today.year % 100
119
118
  year += 1900
120
- elsif 9 == length
121
- # dd/mmm/yy, rare case.
119
+ elsif 9 == length && self =~ /\A\d{2}[^A-Z0-9][A-Z]{3}[^A-Z0-9]\d{2}\z/i
120
+ # dd/mon/yy, rare case.
122
121
  year += 100 if year <= Ourdate.today.year % 100
123
122
  year += 1900
124
123
  end
@@ -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.7.0'
7
7
  end
@@ -0,0 +1,5 @@
1
+ require 'date'
2
+ require 'ndr_support/concerns/working_days'
3
+ require 'ndr_support/integer/working_days'
4
+
5
+ [Time, Date, DateTime].each { |klass| klass.send(:include, WorkingDays) }
@@ -20,19 +20,19 @@ Gem::Specification.new do |spec|
20
20
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
21
  spec.require_paths = ['lib']
22
22
 
23
- spec.add_dependency 'activerecord', '>= 4.0.13', '< 5.3'
24
- spec.add_dependency 'activesupport', '>= 4.0.13', '< 5.3'
23
+ spec.add_dependency 'activerecord', '>= 5.2.0', '< 7'
24
+ spec.add_dependency 'activesupport', '>= 5.2.0', '< 7'
25
25
 
26
- spec.add_development_dependency 'bundler', '~> 1.7'
26
+ spec.add_development_dependency 'bundler'
27
27
  spec.add_development_dependency 'rake', '~> 10.0'
28
28
 
29
- spec.required_ruby_version = '>= 2.1.0'
29
+ spec.required_ruby_version = '>= 2.5.0'
30
30
 
31
31
  # Avoid std-lib minitest (which has different namespace)
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', '~> 5.4', '>= 5.4.5'
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'
@@ -119,4 +119,22 @@ class WorkingDaysTest < Minitest::Test
119
119
  assert_equal 253, @normal_time.working_days_until(@normal_time + 1.year)
120
120
  assert_equal 253, @normal_date_time.working_days_until(@normal_date_time + 1.year)
121
121
  end
122
+
123
+ test 'against GOV.UK holidays' do
124
+ require 'net/http'
125
+ require 'json'
126
+
127
+ url = 'https://www.gov.uk/bank-holidays/england-and-wales.json'
128
+ response = Net::HTTP.get(URI(url))
129
+
130
+ events = JSON.parse(response)['events']
131
+ events.each do |event|
132
+ event_date = event['date']
133
+ parsed_date = Date.parse(event_date)
134
+
135
+ assert parsed_date.public_holiday?, "#{event_date} should be a public holiday"
136
+ # next if parsed_date.public_holiday?
137
+ # puts "'#{event_date}', # #{parsed_date.strftime('%A')} - #{event['title']}"
138
+ end
139
+ end
122
140
  end
@@ -63,6 +63,12 @@ class DaterangeTest < Minitest::Test
63
63
  assert_equal '1880 2020', dr.source
64
64
  end
65
65
 
66
+ def test_year_range_future
67
+ s = 2.years.from_now.strftime('%Y')
68
+ dr = Daterange.new(s)
69
+ assert_equal s, dr.to_s, "Daterange should support future years up to #{s}"
70
+ end
71
+
66
72
  def test_hyphen_month_input_style
67
73
  dr = Daterange.new('2000-05')
68
74
  assert_equal '05.2000', dr.to_s
@@ -220,4 +226,42 @@ class DaterangeTest < Minitest::Test
220
226
  refute_equal dr1, nil
221
227
  refute_equal dr1, 0
222
228
  end
229
+
230
+ def test_three_char_months
231
+ dr1 = Daterange.new('01-APR-2020')
232
+ assert_equal '01.04.2020', dr1.date1.to_s
233
+ assert_equal '01.04.2020', dr1.date2.to_s
234
+
235
+ dr2 = Daterange.new('APR-2020')
236
+ assert_equal '01.04.2020', dr2.date1.to_s
237
+ assert_equal '30.04.2020', dr2.date2.to_s
238
+
239
+ dr3 = Daterange.new('JAN-2020 TO apr-2020')
240
+ assert_equal '01.01.2020', dr3.date1.to_s
241
+ assert_equal '30.04.2020', dr3.date2.to_s
242
+
243
+ dr4 = Daterange.new('20-JAN-2020 TO 12-Apr-2020')
244
+ assert_equal '20.01.2020', dr4.date1.to_s
245
+ assert_equal '12.04.2020', dr4.date2.to_s
246
+
247
+ dr5 = Daterange.new('01-BOB-2020')
248
+ assert_nil dr5.date1
249
+ assert_nil dr5.date2
250
+
251
+ dr6 = Daterange.new('01/APR/2020')
252
+ assert_equal '01.04.2020', dr6.date1.to_s
253
+ assert_equal '01.04.2020', dr6.date2.to_s
254
+
255
+ dr7 = Daterange.new('APR/2020')
256
+ assert_equal '01.04.2020', dr7.date1.to_s
257
+ assert_equal '30.04.2020', dr7.date2.to_s
258
+
259
+ dr8 = Daterange.new('JAN/2020 TO apr.2020')
260
+ assert_equal '01.01.2020', dr8.date1.to_s
261
+ assert_equal '30.04.2020', dr8.date2.to_s
262
+
263
+ dr9 = Daterange.new('20.JAN.2020 TO 12/Apr/2020')
264
+ assert_equal '20.01.2020', dr9.date1.to_s
265
+ assert_equal '12.04.2020', dr9.date2.to_s
266
+ end
223
267
  end
@@ -0,0 +1,14 @@
1
+ require 'test_helper'
2
+
3
+ # This tests our Integer working days extension
4
+ class Integer::WorkingDaysTest < Minitest::Test
5
+ test 'Integer should be extended with #working_days_since' do
6
+ assert 1.respond_to?(:working_days_since)
7
+ end
8
+
9
+ test 'Integer#working_days_since should behave correctly' do
10
+ assert_equal Date.new(2019, 12, 23), 1.working_days_since(Date.new(2019, 12, 20))
11
+ assert_equal Date.new(2019, 12, 27), 3.working_days_since(Date.new(2019, 12, 20))
12
+ assert_equal Date.new(2019, 12, 30), 4.working_days_since(Date.new(2019, 12, 20))
13
+ end
14
+ end
@@ -58,6 +58,10 @@ class String::ConversionsTest < Minitest::Test
58
58
  assert_ymd [2001, 3, 2], '02/03/2001'.to_date
59
59
  assert_ymd [2010, 7, 11], '2010-07-11'.to_date
60
60
 
61
+ assert_ymd [2001, 3, 2], '2.3.2001'.to_date
62
+ assert_ymd [2001, 3, 2], '2/3/2001'.to_date
63
+ assert_ymd [2010, 7, 11], '2010-7-11'.to_date
64
+
61
65
  assert_ymd [2001, 2, 3], '2001/02/03'.to_date('yyyy/mm/dd')
62
66
  assert_ymd [2001, 2, 3], '2001/03/02'.to_date('yyyy/dd/mm')
63
67
  assert_ymd [2001, 2, 3], '2001-02-03'.to_date('yyyy-mm-dd')
@@ -240,8 +244,8 @@ class String::ConversionsTest < Minitest::Test
240
244
  assert_equal Ourdate.build_datetime(1998, 02, 13), '1998-02-13'.to_date('%Y-%m-%d')
241
245
  assert_equal Ourdate.build_datetime(1998, 05, 03), '1998-05-03'.to_date('%Y-%m-%d')
242
246
 
243
- assert ''.to_date('%Y-%m-%d').blank?
244
- assert ' '.to_date('%Y-%m-%d').blank?
247
+ assert_nil ''.to_date('%Y-%m-%d') # Should behave like Rails-defined to_date
248
+ assert_nil ' '.to_date('%Y-%m-%d')
245
249
  end
246
250
 
247
251
  test '%d-%m-%Y string to_date' do
@@ -307,7 +311,7 @@ class String::ConversionsTest < Minitest::Test
307
311
  assert_equal Ourdate.build_datetime(2008, 05, 03), '03/05/08'.to_date
308
312
  end
309
313
 
310
- test 'inferred dd/mmm/yy string to_date' do
314
+ test 'inferred dd/mon/yy string to_date' do
311
315
  # pre_epoch
312
316
  assert_equal Ourdate.build_datetime(1945, 02, 13), '13/FEB/45'.to_date
313
317
  assert_equal Ourdate.build_datetime(1945, 06, 03), '03/JUN/45'.to_date
@@ -334,6 +338,12 @@ class String::ConversionsTest < Minitest::Test
334
338
  assert_equal Ourdate.build_datetime(2008, 05, 03), '03/05/2008 13:38'.to_date
335
339
  end
336
340
 
341
+ test 'incorrectly formatted string to_date' do
342
+ assert_nil '10-1975'.to_date
343
+ assert_nil '10.1975A'.to_date
344
+ assert_nil '10.1975AA'.to_date
345
+ end
346
+
337
347
  test 'to_boolean' do
338
348
  assert_equal true, 'true'.to_boolean
339
349
  assert_equal true, 'yes'.to_boolean
@@ -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.7.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: 2020-06-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,54 +16,54 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 4.0.13
19
+ version: 5.2.0
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '5.3'
22
+ version: '7'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: 4.0.13
29
+ version: 5.2.0
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '5.3'
32
+ version: '7'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: activesupport
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
- version: 4.0.13
39
+ version: 5.2.0
40
40
  - - "<"
41
41
  - !ruby/object:Gem::Version
42
- version: '5.3'
42
+ version: '7'
43
43
  type: :runtime
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
46
46
  requirements:
47
47
  - - ">="
48
48
  - !ruby/object:Gem::Version
49
- version: 4.0.13
49
+ version: 5.2.0
50
50
  - - "<"
51
51
  - !ruby/object:Gem::Version
52
- version: '5.3'
52
+ version: '7'
53
53
  - !ruby/object:Gem::Dependency
54
54
  name: bundler
55
55
  requirement: !ruby/object:Gem::Requirement
56
56
  requirements:
57
- - - "~>"
57
+ - - ">="
58
58
  - !ruby/object:Gem::Version
59
- version: '1.7'
59
+ version: '0'
60
60
  type: :development
61
61
  prerelease: false
62
62
  version_requirements: !ruby/object:Gem::Requirement
63
63
  requirements:
64
- - - "~>"
64
+ - - ">="
65
65
  - !ruby/object:Gem::Version
66
- version: '1.7'
66
+ version: '0'
67
67
  - !ruby/object:Gem::Dependency
68
68
  name: rake
69
69
  requirement: !ruby/object:Gem::Requirement
@@ -112,14 +112,20 @@ dependencies:
112
112
  requirements:
113
113
  - - "~>"
114
114
  - !ruby/object:Gem::Version
115
- version: '3.0'
115
+ version: '5.4'
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: 5.4.5
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: '5.4'
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: 5.4.5
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
@@ -233,10 +240,8 @@ files:
233
240
  - README.md
234
241
  - Rakefile
235
242
  - code_safety.yml
236
- - gemfiles/Gemfile.rails42
237
- - gemfiles/Gemfile.rails50
238
- - gemfiles/Gemfile.rails51
239
243
  - gemfiles/Gemfile.rails52
244
+ - gemfiles/Gemfile.rails60
240
245
  - lib/ndr_support.rb
241
246
  - lib/ndr_support/array.rb
242
247
  - lib/ndr_support/concerns/working_days.rb
@@ -246,6 +251,7 @@ files:
246
251
  - lib/ndr_support/integer/calculations.rb
247
252
  - lib/ndr_support/integer/julian_date_conversions.rb
248
253
  - lib/ndr_support/integer/rounding.rb
254
+ - lib/ndr_support/integer/working_days.rb
249
255
  - lib/ndr_support/nil.rb
250
256
  - lib/ndr_support/obfuscator.rb
251
257
  - lib/ndr_support/ourdate.rb
@@ -258,11 +264,13 @@ files:
258
264
  - lib/ndr_support/string/cleaning.rb
259
265
  - lib/ndr_support/string/conversions.rb
260
266
  - lib/ndr_support/tasks.rb
267
+ - lib/ndr_support/threat_scanner.rb
261
268
  - lib/ndr_support/utf8_encoding.rb
262
269
  - lib/ndr_support/utf8_encoding/control_characters.rb
263
270
  - lib/ndr_support/utf8_encoding/force_binary.rb
264
271
  - lib/ndr_support/utf8_encoding/object_support.rb
265
272
  - lib/ndr_support/version.rb
273
+ - lib/ndr_support/working_days.rb
266
274
  - lib/ndr_support/yaml/serialization_migration.rb
267
275
  - ndr_support.gemspec
268
276
  - test/array_test.rb
@@ -271,6 +279,7 @@ files:
271
279
  - test/hash_test.rb
272
280
  - test/integer/calculations_test.rb
273
281
  - test/integer/rounding_test.rb
282
+ - test/integer/working_days_test.rb
274
283
  - test/nil_test.rb
275
284
  - test/obfuscator_test.rb
276
285
  - test/ourdate_test.rb
@@ -283,6 +292,7 @@ files:
283
292
  - test/string/cleaning_test.rb
284
293
  - test/string/conversions_test.rb
285
294
  - test/test_helper.rb
295
+ - test/threat_scanner_test.rb
286
296
  - test/utf8_encoding/control_characters_test.rb
287
297
  - test/utf8_encoding/force_binary_test.rb
288
298
  - test/utf8_encoding_test.rb
@@ -299,15 +309,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
299
309
  requirements:
300
310
  - - ">="
301
311
  - !ruby/object:Gem::Version
302
- version: 2.1.0
312
+ version: 2.5.0
303
313
  required_rubygems_version: !ruby/object:Gem::Requirement
304
314
  requirements:
305
315
  - - ">="
306
316
  - !ruby/object:Gem::Version
307
317
  version: '0'
308
318
  requirements: []
309
- rubyforge_project:
310
- rubygems_version: 2.5.2.3
319
+ rubygems_version: 3.0.3
311
320
  signing_key:
312
321
  specification_version: 4
313
322
  summary: NDR Support library
@@ -318,6 +327,7 @@ test_files:
318
327
  - test/hash_test.rb
319
328
  - test/integer/calculations_test.rb
320
329
  - test/integer/rounding_test.rb
330
+ - test/integer/working_days_test.rb
321
331
  - test/nil_test.rb
322
332
  - test/obfuscator_test.rb
323
333
  - test/ourdate_test.rb
@@ -330,6 +340,7 @@ test_files:
330
340
  - test/string/cleaning_test.rb
331
341
  - test/string/conversions_test.rb
332
342
  - test/test_helper.rb
343
+ - test/threat_scanner_test.rb
333
344
  - test/utf8_encoding/control_characters_test.rb
334
345
  - test/utf8_encoding/force_binary_test.rb
335
346
  - test/utf8_encoding_test.rb
@@ -1,6 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec path: '..'
4
-
5
- gem 'activerecord', '~> 4.2.0'
6
- gem 'activesupport', '~> 4.2.0'
@@ -1,6 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec path: '..'
4
-
5
- gem 'activerecord', '~> 5.0.0'
6
- gem 'activesupport', '~> 5.0.0'
@@ -1,9 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec path: '..'
4
-
5
- # Minitest 5.10.2 doesn't work with Rails version
6
- gem 'minitest', '< 5.10.2'
7
-
8
- gem 'activerecord', '~> 5.1.0'
9
- gem 'activesupport', '~> 5.1.0'