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 +5 -5
- data/CHANGELOG.md +41 -0
- data/code_safety.yml +55 -39
- data/gemfiles/Gemfile.rails60 +6 -0
- data/lib/ndr_support.rb +3 -0
- data/lib/ndr_support/concerns/working_days.rb +64 -9
- data/lib/ndr_support/date_and_time_extensions.rb +1 -3
- data/lib/ndr_support/daterange.rb +24 -5
- data/lib/ndr_support/integer/working_days.rb +11 -0
- data/lib/ndr_support/string/conversions.rb +3 -4
- data/lib/ndr_support/threat_scanner.rb +64 -0
- data/lib/ndr_support/utf8_encoding.rb +5 -2
- data/lib/ndr_support/utf8_encoding/control_characters.rb +2 -8
- data/lib/ndr_support/version.rb +1 -1
- data/lib/ndr_support/working_days.rb +5 -0
- data/ndr_support.gemspec +5 -5
- data/test/concerns/working_days_test.rb +18 -0
- data/test/daterange_test.rb +44 -0
- data/test/integer/working_days_test.rb +14 -0
- data/test/string/conversions_test.rb +13 -3
- data/test/test_helper.rb +1 -1
- data/test/threat_scanner_test.rb +75 -0
- metadata +33 -22
- data/gemfiles/Gemfile.rails42 +0 -6
- data/gemfiles/Gemfile.rails50 +0 -6
- data/gemfiles/Gemfile.rails51 +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e06c6fad074bb00f7ba16334d194b9fcf369147688dbd1f22dcd1cca86e71073
|
4
|
+
data.tar.gz: 7ede15deb1aec6e6ee02d627437eb7c94810755dbcb717db9212c17c2f09ca3e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3b03a27b86891d3cb52dcf3fab222cf3bd42b05cb859918142dd6791a6dc18e5ebba0075911d9d177e7451a5b447b0cf6324455641f913ebb86c78808cf5843
|
7
|
+
data.tar.gz: e5d89586818d5a50a1c3211086ce812d485e90b3080c46986be570ec32e7c740f6d5c312a8580ef727243c5910b60d5acd13f8e94276e0fa07dbf922879a9a85
|
data/CHANGELOG.md
ADDED
@@ -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
|
data/code_safety.yml
CHANGED
@@ -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:
|
16
|
-
safe_revision:
|
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
|
-
|
49
|
+
gemfiles/Gemfile.rails60:
|
58
50
|
comments:
|
59
51
|
reviewed_by: josh.pencheon
|
60
|
-
safe_revision:
|
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:
|
68
|
-
safe_revision:
|
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:
|
68
|
+
safe_revision: c1158eccb843b637b4dd82815dc7c081f12b93e4
|
73
69
|
lib/ndr_support/daterange.rb:
|
74
70
|
comments:
|
75
|
-
reviewed_by:
|
76
|
-
safe_revision:
|
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:
|
136
|
-
safe_revision:
|
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:
|
144
|
-
safe_revision:
|
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:
|
148
|
-
safe_revision:
|
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:
|
160
|
-
safe_revision:
|
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:
|
168
|
-
safe_revision:
|
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:
|
176
|
-
safe_revision:
|
183
|
+
reviewed_by: josh.pencheon
|
184
|
+
safe_revision: fe6c3beff445e3c84ed0c89f08e1ab10bfb00587
|
177
185
|
test/daterange_test.rb:
|
178
186
|
comments:
|
179
|
-
reviewed_by:
|
180
|
-
safe_revision:
|
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:
|
236
|
-
safe_revision:
|
247
|
+
reviewed_by: ollietulloch
|
248
|
+
safe_revision: 9a4b8e53f477725c2c2be5000b3c9e66f07d7389
|
237
249
|
test/test_helper.rb:
|
238
250
|
comments:
|
239
|
-
reviewed_by:
|
240
|
-
safe_revision:
|
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
|
data/lib/ndr_support.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
85
|
-
|
86
|
-
|
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
|
-
|
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
|
@@ -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..
|
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 =~ /[
|
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 =~
|
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
|
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/
|
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!(
|
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!(
|
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
|
-
|
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
|
data/lib/ndr_support/version.rb
CHANGED
data/ndr_support.gemspec
CHANGED
@@ -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', '>=
|
24
|
-
spec.add_dependency 'activesupport', '>=
|
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'
|
26
|
+
spec.add_development_dependency 'bundler'
|
27
27
|
spec.add_development_dependency 'rake', '~> 10.0'
|
28
28
|
|
29
|
-
spec.required_ruby_version = '>= 2.
|
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', '~>
|
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
|
data/test/daterange_test.rb
CHANGED
@@ -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
|
-
|
244
|
-
|
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/
|
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
|
data/test/test_helper.rb
CHANGED
@@ -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
|
+
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:
|
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:
|
19
|
+
version: 5.2.0
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
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:
|
29
|
+
version: 5.2.0
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
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:
|
39
|
+
version: 5.2.0
|
40
40
|
- - "<"
|
41
41
|
- !ruby/object:Gem::Version
|
42
|
-
version: '
|
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:
|
49
|
+
version: 5.2.0
|
50
50
|
- - "<"
|
51
51
|
- !ruby/object:Gem::Version
|
52
|
-
version: '
|
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: '
|
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: '
|
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: '
|
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: '
|
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.
|
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
|
-
|
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
|
data/gemfiles/Gemfile.rails42
DELETED
data/gemfiles/Gemfile.rails50
DELETED