Module: Gitlab::Utils
- Extended by:
- Utils
- Included in:
- API::Helpers, Utils
- Defined in:
- lib/gitlab/utils.rb,
lib/gitlab/utils/gzip.rb,
lib/gitlab/utils/markdown.rb,
lib/gitlab/utils/override.rb,
lib/gitlab/utils/deep_size.rb,
lib/gitlab/utils/measuring.rb,
lib/gitlab/utils/merge_hash.rb,
lib/gitlab/utils/usage_data.rb,
lib/gitlab/utils/inline_hash.rb,
lib/gitlab/utils/strong_memoize.rb,
lib/gitlab/utils/lazy_attributes.rb,
lib/gitlab/utils/safe_inline_hash.rb,
lib/gitlab/utils/log_limited_array.rb,
lib/gitlab/utils/sanitize_node_link.rb,
lib/gitlab/utils/json_size_estimator.rb
Defined Under Namespace
Modules: Gzip, InlineHash, LazyAttributes, LogLimitedArray, Markdown, MergeHash, Override, SanitizeNodeLink, StrongMemoize, UsageData
Classes: DeepSize, JsonSizeEstimator, Measuring, SafeInlineHash
Instance Method Summary
collapse
Instance Method Details
#allowlisted?(absolute_path, allowlist) ⇒ Boolean
23
24
25
26
27
28
29
|
# File 'lib/gitlab/utils.rb', line 23
def allowlisted?(absolute_path, allowlist)
path = absolute_path.downcase
allowlist.map(&:downcase).any? do |allowed_path|
path.start_with?(allowed_path)
end
end
|
#append_path(host, path) ⇒ Object
Append path to host, making sure there's one single / in between
67
68
69
|
# File 'lib/gitlab/utils.rb', line 67
def append_path(host, path)
"#{host.to_s.sub(%r{\/+$}, '')}/#{path.to_s.sub(%r{^\/+}, '')}"
end
|
#boolean_to_yes_no(bool) ⇒ Object
107
108
109
110
111
112
113
|
# File 'lib/gitlab/utils.rb', line 107
def boolean_to_yes_no(bool)
if bool
'Yes'
else
'No'
end
end
|
#bytes_to_megabytes(bytes) ⇒ Object
142
143
144
|
# File 'lib/gitlab/utils.rb', line 142
def bytes_to_megabytes(bytes)
bytes.to_f / Numeric::MEGABYTE
end
|
#check_allowed_absolute_path!(path, allowlist) ⇒ Object
31
32
33
34
35
36
|
# File 'lib/gitlab/utils.rb', line 31
def check_allowed_absolute_path!(path, allowlist)
return unless Pathname.new(path).absolute?
return if allowlisted?(path, allowlist)
raise StandardError, "path #{path} is not allowed"
end
|
#check_path_traversal!(path) ⇒ Object
12
13
14
15
16
17
18
19
20
21
|
# File 'lib/gitlab/utils.rb', line 12
def check_path_traversal!(path)
path = decode_path(path)
path_regex = /(\A(\.{1,2})\z|\A\.\.[\/\\]|[\/\\]\.\.\z|[\/\\]\.\.[\/\\]|\n)/
if path.match?(path_regex)
raise PathTraversalAttackError.new('Invalid path')
end
path
end
|
#decode_path(encoded_path) ⇒ Object
38
39
40
41
42
43
44
45
|
# File 'lib/gitlab/utils.rb', line 38
def decode_path(encoded_path)
decoded = CGI.unescape(encoded_path)
if decoded != CGI.unescape(decoded)
raise StandardError, "path #{encoded_path} is not allowed"
end
decoded
end
|
#deep_indifferent_access(data) ⇒ Object
158
159
160
161
162
163
164
165
166
|
# File 'lib/gitlab/utils.rb', line 158
def deep_indifferent_access(data)
if data.is_a?(Array)
data.map(&method(:deep_indifferent_access))
elsif data.is_a?(Hash)
data.with_indifferent_access
else
data
end
end
|
#ensure_array_from_string(string_or_array) ⇒ Object
Used in EE Accepts either an Array or a String and returns an array
152
153
154
155
156
|
# File 'lib/gitlab/utils.rb', line 152
def ensure_array_from_string(string_or_array)
return string_or_array if string_or_array.is_a?(Array)
string_or_array.split(',').map(&:strip)
end
|
#ensure_utf8_size(str, bytes:) ⇒ Object
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
# File 'lib/gitlab/utils.rb', line 51
def ensure_utf8_size(str, bytes:)
raise ArgumentError, 'Empty string provided!' if str.empty?
raise ArgumentError, 'Negative string size provided!' if bytes < 0
truncated = str.each_char.each_with_object(+'') do |char, object|
if object.bytesize + char.bytesize > bytes
break object
else
object.concat(char)
end
end
truncated + ('0' * (bytes - truncated.bytesize))
end
|
#force_utf8(str) ⇒ Object
47
48
49
|
# File 'lib/gitlab/utils.rb', line 47
def force_utf8(str)
str.dup.force_encoding(Encoding::UTF_8)
end
|
#ms_to_round_sec(ms) ⇒ Object
146
147
148
|
# File 'lib/gitlab/utils.rb', line 146
def ms_to_round_sec(ms)
(ms.to_f / 1000).round(6)
end
|
#multiple_key_invert(hash) ⇒ Object
Invert a hash, collecting all keys that map to a given value in an array.
Unlike `Hash#invert`, where the last encountered pair wins, and which has the type `Hash[k, v] => Hash[v, k]`, `multiple_key_invert` does not lose any information, has the type `Hash[k, v] => Hash[v, Array]`, and the original hash can always be reconstructed.
example:
multiple_key_invert({ a: 1, b: 2, c: 1 })
196
197
198
199
200
|
# File 'lib/gitlab/utils.rb', line 196
def multiple_key_invert(hash)
hash.flat_map { |k, v| Array.wrap(v).zip([k].cycle) }
.group_by(&:first)
.transform_values { |kvs| kvs.map(&:last) }
end
|
#nlbr(str) ⇒ Object
Converts newlines into HTML line break elements
91
92
93
|
# File 'lib/gitlab/utils.rb', line 91
def nlbr(str)
ActionView::Base.full_sanitizer.sanitize(+str, tags: []).gsub(/\r?\n/, '<br>').html_safe
end
|
#parse_url(uri_string) ⇒ Object
Converts a string to an Addressable::URI object. If the string is not a valid URI, it returns nil. Param uri_string should be a String object. This method returns an Addressable::URI object or nil.
179
180
181
182
|
# File 'lib/gitlab/utils.rb', line 179
def parse_url(uri_string)
Addressable::URI.parse(uri_string)
rescue Addressable::URI::InvalidURIError, TypeError
end
|
#random_string ⇒ Object
115
116
117
|
# File 'lib/gitlab/utils.rb', line 115
def random_string
Random.rand(Float::MAX.to_i).to_s(36)
end
|
#remove_line_breaks(str) ⇒ Object
95
96
97
|
# File 'lib/gitlab/utils.rb', line 95
def remove_line_breaks(str)
str.gsub(/\r?\n/, '')
end
|
#slugify(str) ⇒ Object
A slugified version of the string, suitable for inclusion in URLs and domain names. Rules:
* Lowercased
* Anything not matching [a-z0-9-] is replaced with a -
* Maximum length is 63 bytes
* First/Last Character is not a hyphen
78
79
80
81
82
|
# File 'lib/gitlab/utils.rb', line 78
def slugify(str)
str.downcase
.gsub(/[^a-z0-9]/, '-')[0..62]
.gsub(/(\A-+|-+\z)/, '')
end
|
#stable_sort_by(list) ⇒ Object
This sort is stable (see en.wikipedia.org/wiki/Sorting_algorithm#Stability) contrary to the bare Ruby sort_by method. Using just sort_by leads to instability across different platforms (e.g., x86_64-linux and x86_64-darwin18) which in turn leads to different sorting results for the equal elements across these platforms. This method uses a list item's original index position to break ties.
208
209
210
|
# File 'lib/gitlab/utils.rb', line 208
def stable_sort_by(list)
list.sort_by.with_index { |x, idx| [yield(x), idx] }
end
|
#string_to_ip_object(str) ⇒ Object
168
169
170
171
172
173
|
# File 'lib/gitlab/utils.rb', line 168
def string_to_ip_object(str)
return unless str
IPAddr.new(str)
rescue IPAddr::InvalidAddressError
end
|
#to_boolean(value, default: nil) ⇒ Object
99
100
101
102
103
104
105
|
# File 'lib/gitlab/utils.rb', line 99
def to_boolean(value, default: nil)
return value if [true, false].include?(value)
return true if value =~ /^(true|t|yes|y|1|on)$/i
return false if value =~ /^(false|f|no|n|0|off)$/i
default
end
|
#to_exclusive_sentence(array) ⇒ Object
Wraps ActiveSupport's Array#to_sentence to convert the given array to a comma-separated sentence joined with localized 'or' Strings instead of 'and'.
86
87
88
|
# File 'lib/gitlab/utils.rb', line 86
def to_exclusive_sentence(array)
array.to_sentence(two_words_connector: _(' or '), last_word_connector: _(', or '))
end
|
#try_megabytes_to_bytes(size) ⇒ Object
136
137
138
139
140
|
# File 'lib/gitlab/utils.rb', line 136
def try_megabytes_to_bytes(size)
Integer(size).megabytes
rescue ArgumentError
size
end
|
#which(cmd, env = ENV) ⇒ Object
123
124
125
126
127
128
129
130
131
132
133
134
|
# File 'lib/gitlab/utils.rb', line 123
def which(cmd, env = ENV)
exts = env['PATHEXT'] ? env['PATHEXT'].split(';') : ['']
env['PATH'].split(File::PATH_SEPARATOR).each do |path|
exts.each do |ext|
exe = File.join(path, "#{cmd}#{ext}")
return exe if File.executable?(exe) && !File.directory?(exe)
end
end
nil
end
|