ndr_support 5.4.2 → 5.7.0

Sign up to get free protection for your applications and to get access to all the features.
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'