uri 0.10.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of uri might be problematic. Click here for more details.

@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: false
2
+ # = uri/http.rb
3
+ #
4
+ # Author:: Akira Yamada <akira@ruby-lang.org>
5
+ # License:: You can redistribute it and/or modify it under the same term as Ruby.
6
+ # Revision:: $Id$
7
+ #
8
+ # See URI for general documentation
9
+ #
10
+
11
+ require_relative 'generic'
12
+
13
+ module URI
14
+
15
+ #
16
+ # The syntax of HTTP URIs is defined in RFC1738 section 3.3.
17
+ #
18
+ # Note that the Ruby URI library allows HTTP URLs containing usernames and
19
+ # passwords. This is not legal as per the RFC, but used to be
20
+ # supported in Internet Explorer 5 and 6, before the MS04-004 security
21
+ # update. See <URL:http://support.microsoft.com/kb/834489>.
22
+ #
23
+ class HTTP < Generic
24
+ # A Default port of 80 for URI::HTTP.
25
+ DEFAULT_PORT = 80
26
+
27
+ # An Array of the available components for URI::HTTP.
28
+ COMPONENT = %i[
29
+ scheme
30
+ userinfo host port
31
+ path
32
+ query
33
+ fragment
34
+ ].freeze
35
+
36
+ #
37
+ # == Description
38
+ #
39
+ # Creates a new URI::HTTP object from components, with syntax checking.
40
+ #
41
+ # The components accepted are userinfo, host, port, path, query, and
42
+ # fragment.
43
+ #
44
+ # The components should be provided either as an Array, or as a Hash
45
+ # with keys formed by preceding the component names with a colon.
46
+ #
47
+ # If an Array is used, the components must be passed in the
48
+ # order <code>[userinfo, host, port, path, query, fragment]</code>.
49
+ #
50
+ # Example:
51
+ #
52
+ # uri = URI::HTTP.build(host: 'www.example.com', path: '/foo/bar')
53
+ #
54
+ # uri = URI::HTTP.build([nil, "www.example.com", nil, "/path",
55
+ # "query", 'fragment'])
56
+ #
57
+ # Currently, if passed userinfo components this method generates
58
+ # invalid HTTP URIs as per RFC 1738.
59
+ #
60
+ def self.build(args)
61
+ tmp = Util.make_components_hash(self, args)
62
+ super(tmp)
63
+ end
64
+
65
+ #
66
+ # == Description
67
+ #
68
+ # Returns the full path for an HTTP request, as required by Net::HTTP::Get.
69
+ #
70
+ # If the URI contains a query, the full path is URI#path + '?' + URI#query.
71
+ # Otherwise, the path is simply URI#path.
72
+ #
73
+ # Example:
74
+ #
75
+ # uri = URI::HTTP.build(path: '/foo/bar', query: 'test=true')
76
+ # uri.request_uri # => "/foo/bar?test=true"
77
+ #
78
+ def request_uri
79
+ return unless @path
80
+
81
+ url = @query ? "#@path?#@query" : @path.dup
82
+ url.start_with?(?/.freeze) ? url : ?/ + url
83
+ end
84
+ end
85
+
86
+ @@schemes['HTTP'] = HTTP
87
+
88
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: false
2
+ # = uri/https.rb
3
+ #
4
+ # Author:: Akira Yamada <akira@ruby-lang.org>
5
+ # License:: You can redistribute it and/or modify it under the same term as Ruby.
6
+ # Revision:: $Id$
7
+ #
8
+ # See URI for general documentation
9
+ #
10
+
11
+ require_relative 'http'
12
+
13
+ module URI
14
+
15
+ # The default port for HTTPS URIs is 443, and the scheme is 'https:' rather
16
+ # than 'http:'. Other than that, HTTPS URIs are identical to HTTP URIs;
17
+ # see URI::HTTP.
18
+ class HTTPS < HTTP
19
+ # A Default port of 443 for URI::HTTPS
20
+ DEFAULT_PORT = 443
21
+ end
22
+ @@schemes['HTTPS'] = HTTPS
23
+ end
@@ -0,0 +1,261 @@
1
+ # frozen_string_literal: false
2
+ # = uri/ldap.rb
3
+ #
4
+ # Author::
5
+ # Takaaki Tateishi <ttate@jaist.ac.jp>
6
+ # Akira Yamada <akira@ruby-lang.org>
7
+ # License::
8
+ # URI::LDAP is copyrighted free software by Takaaki Tateishi and Akira Yamada.
9
+ # You can redistribute it and/or modify it under the same term as Ruby.
10
+ # Revision:: $Id$
11
+ #
12
+ # See URI for general documentation
13
+ #
14
+
15
+ require_relative 'generic'
16
+
17
+ module URI
18
+
19
+ #
20
+ # LDAP URI SCHEMA (described in RFC2255).
21
+ #--
22
+ # ldap://<host>/<dn>[?<attrs>[?<scope>[?<filter>[?<extensions>]]]]
23
+ #++
24
+ class LDAP < Generic
25
+
26
+ # A Default port of 389 for URI::LDAP.
27
+ DEFAULT_PORT = 389
28
+
29
+ # An Array of the available components for URI::LDAP.
30
+ COMPONENT = [
31
+ :scheme,
32
+ :host, :port,
33
+ :dn,
34
+ :attributes,
35
+ :scope,
36
+ :filter,
37
+ :extensions,
38
+ ].freeze
39
+
40
+ # Scopes available for the starting point.
41
+ #
42
+ # * SCOPE_BASE - the Base DN
43
+ # * SCOPE_ONE - one level under the Base DN, not including the base DN and
44
+ # not including any entries under this
45
+ # * SCOPE_SUB - subtrees, all entries at all levels
46
+ #
47
+ SCOPE = [
48
+ SCOPE_ONE = 'one',
49
+ SCOPE_SUB = 'sub',
50
+ SCOPE_BASE = 'base',
51
+ ].freeze
52
+
53
+ #
54
+ # == Description
55
+ #
56
+ # Creates a new URI::LDAP object from components, with syntax checking.
57
+ #
58
+ # The components accepted are host, port, dn, attributes,
59
+ # scope, filter, and extensions.
60
+ #
61
+ # The components should be provided either as an Array, or as a Hash
62
+ # with keys formed by preceding the component names with a colon.
63
+ #
64
+ # If an Array is used, the components must be passed in the
65
+ # order <code>[host, port, dn, attributes, scope, filter, extensions]</code>.
66
+ #
67
+ # Example:
68
+ #
69
+ # uri = URI::LDAP.build({:host => 'ldap.example.com',
70
+ # :dn => '/dc=example'})
71
+ #
72
+ # uri = URI::LDAP.build(["ldap.example.com", nil,
73
+ # "/dc=example;dc=com", "query", nil, nil, nil])
74
+ #
75
+ def self.build(args)
76
+ tmp = Util::make_components_hash(self, args)
77
+
78
+ if tmp[:dn]
79
+ tmp[:path] = tmp[:dn]
80
+ end
81
+
82
+ query = []
83
+ [:extensions, :filter, :scope, :attributes].collect do |x|
84
+ next if !tmp[x] && query.size == 0
85
+ query.unshift(tmp[x])
86
+ end
87
+
88
+ tmp[:query] = query.join('?')
89
+
90
+ return super(tmp)
91
+ end
92
+
93
+ #
94
+ # == Description
95
+ #
96
+ # Creates a new URI::LDAP object from generic URI components as per
97
+ # RFC 2396. No LDAP-specific syntax checking is performed.
98
+ #
99
+ # Arguments are +scheme+, +userinfo+, +host+, +port+, +registry+, +path+,
100
+ # +opaque+, +query+, and +fragment+, in that order.
101
+ #
102
+ # Example:
103
+ #
104
+ # uri = URI::LDAP.new("ldap", nil, "ldap.example.com", nil, nil,
105
+ # "/dc=example;dc=com", nil, "query", nil)
106
+ #
107
+ # See also URI::Generic.new.
108
+ #
109
+ def initialize(*arg)
110
+ super(*arg)
111
+
112
+ if @fragment
113
+ raise InvalidURIError, 'bad LDAP URL'
114
+ end
115
+
116
+ parse_dn
117
+ parse_query
118
+ end
119
+
120
+ # Private method to cleanup +dn+ from using the +path+ component attribute.
121
+ def parse_dn
122
+ @dn = @path[1..-1]
123
+ end
124
+ private :parse_dn
125
+
126
+ # Private method to cleanup +attributes+, +scope+, +filter+, and +extensions+
127
+ # from using the +query+ component attribute.
128
+ def parse_query
129
+ @attributes = nil
130
+ @scope = nil
131
+ @filter = nil
132
+ @extensions = nil
133
+
134
+ if @query
135
+ attrs, scope, filter, extensions = @query.split('?')
136
+
137
+ @attributes = attrs if attrs && attrs.size > 0
138
+ @scope = scope if scope && scope.size > 0
139
+ @filter = filter if filter && filter.size > 0
140
+ @extensions = extensions if extensions && extensions.size > 0
141
+ end
142
+ end
143
+ private :parse_query
144
+
145
+ # Private method to assemble +query+ from +attributes+, +scope+, +filter+, and +extensions+.
146
+ def build_path_query
147
+ @path = '/' + @dn
148
+
149
+ query = []
150
+ [@extensions, @filter, @scope, @attributes].each do |x|
151
+ next if !x && query.size == 0
152
+ query.unshift(x)
153
+ end
154
+ @query = query.join('?')
155
+ end
156
+ private :build_path_query
157
+
158
+ # Returns dn.
159
+ def dn
160
+ @dn
161
+ end
162
+
163
+ # Private setter for dn +val+.
164
+ def set_dn(val)
165
+ @dn = val
166
+ build_path_query
167
+ @dn
168
+ end
169
+ protected :set_dn
170
+
171
+ # Setter for dn +val+.
172
+ def dn=(val)
173
+ set_dn(val)
174
+ val
175
+ end
176
+
177
+ # Returns attributes.
178
+ def attributes
179
+ @attributes
180
+ end
181
+
182
+ # Private setter for attributes +val+.
183
+ def set_attributes(val)
184
+ @attributes = val
185
+ build_path_query
186
+ @attributes
187
+ end
188
+ protected :set_attributes
189
+
190
+ # Setter for attributes +val+.
191
+ def attributes=(val)
192
+ set_attributes(val)
193
+ val
194
+ end
195
+
196
+ # Returns scope.
197
+ def scope
198
+ @scope
199
+ end
200
+
201
+ # Private setter for scope +val+.
202
+ def set_scope(val)
203
+ @scope = val
204
+ build_path_query
205
+ @scope
206
+ end
207
+ protected :set_scope
208
+
209
+ # Setter for scope +val+.
210
+ def scope=(val)
211
+ set_scope(val)
212
+ val
213
+ end
214
+
215
+ # Returns filter.
216
+ def filter
217
+ @filter
218
+ end
219
+
220
+ # Private setter for filter +val+.
221
+ def set_filter(val)
222
+ @filter = val
223
+ build_path_query
224
+ @filter
225
+ end
226
+ protected :set_filter
227
+
228
+ # Setter for filter +val+.
229
+ def filter=(val)
230
+ set_filter(val)
231
+ val
232
+ end
233
+
234
+ # Returns extensions.
235
+ def extensions
236
+ @extensions
237
+ end
238
+
239
+ # Private setter for extensions +val+.
240
+ def set_extensions(val)
241
+ @extensions = val
242
+ build_path_query
243
+ @extensions
244
+ end
245
+ protected :set_extensions
246
+
247
+ # Setter for extensions +val+.
248
+ def extensions=(val)
249
+ set_extensions(val)
250
+ val
251
+ end
252
+
253
+ # Checks if URI has a path.
254
+ # For URI::LDAP this will return +false+.
255
+ def hierarchical?
256
+ false
257
+ end
258
+ end
259
+
260
+ @@schemes['LDAP'] = LDAP
261
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: false
2
+ # = uri/ldap.rb
3
+ #
4
+ # License:: You can redistribute it and/or modify it under the same term as Ruby.
5
+ #
6
+ # See URI for general documentation
7
+ #
8
+
9
+ require_relative 'ldap'
10
+
11
+ module URI
12
+
13
+ # The default port for LDAPS URIs is 636, and the scheme is 'ldaps:' rather
14
+ # than 'ldap:'. Other than that, LDAPS URIs are identical to LDAP URIs;
15
+ # see URI::LDAP.
16
+ class LDAPS < LDAP
17
+ # A Default port of 636 for URI::LDAPS
18
+ DEFAULT_PORT = 636
19
+ end
20
+ @@schemes['LDAPS'] = LDAPS
21
+ end
@@ -0,0 +1,294 @@
1
+ # frozen_string_literal: false
2
+ # = uri/mailto.rb
3
+ #
4
+ # Author:: Akira Yamada <akira@ruby-lang.org>
5
+ # License:: You can redistribute it and/or modify it under the same term as Ruby.
6
+ # Revision:: $Id$
7
+ #
8
+ # See URI for general documentation
9
+ #
10
+
11
+ require_relative 'generic'
12
+
13
+ module URI
14
+
15
+ #
16
+ # RFC6068, the mailto URL scheme.
17
+ #
18
+ class MailTo < Generic
19
+ include REGEXP
20
+
21
+ # A Default port of nil for URI::MailTo.
22
+ DEFAULT_PORT = nil
23
+
24
+ # An Array of the available components for URI::MailTo.
25
+ COMPONENT = [ :scheme, :to, :headers ].freeze
26
+
27
+ # :stopdoc:
28
+ # "hname" and "hvalue" are encodings of an RFC 822 header name and
29
+ # value, respectively. As with "to", all URL reserved characters must
30
+ # be encoded.
31
+ #
32
+ # "#mailbox" is as specified in RFC 822 [RFC822]. This means that it
33
+ # consists of zero or more comma-separated mail addresses, possibly
34
+ # including "phrase" and "comment" components. Note that all URL
35
+ # reserved characters in "to" must be encoded: in particular,
36
+ # parentheses, commas, and the percent sign ("%"), which commonly occur
37
+ # in the "mailbox" syntax.
38
+ #
39
+ # Within mailto URLs, the characters "?", "=", "&" are reserved.
40
+
41
+ # ; RFC 6068
42
+ # hfields = "?" hfield *( "&" hfield )
43
+ # hfield = hfname "=" hfvalue
44
+ # hfname = *qchar
45
+ # hfvalue = *qchar
46
+ # qchar = unreserved / pct-encoded / some-delims
47
+ # some-delims = "!" / "$" / "'" / "(" / ")" / "*"
48
+ # / "+" / "," / ";" / ":" / "@"
49
+ #
50
+ # ; RFC3986
51
+ # unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
52
+ # pct-encoded = "%" HEXDIG HEXDIG
53
+ HEADER_REGEXP = /\A(?<hfield>(?:%\h\h|[!$'-.0-;@-Z_a-z~])*=(?:%\h\h|[!$'-.0-;@-Z_a-z~])*)(?:&\g<hfield>)*\z/
54
+ # practical regexp for email address
55
+ # https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address
56
+ EMAIL_REGEXP = /\A[a-zA-Z0-9.!\#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\z/
57
+ # :startdoc:
58
+
59
+ #
60
+ # == Description
61
+ #
62
+ # Creates a new URI::MailTo object from components, with syntax checking.
63
+ #
64
+ # Components can be provided as an Array or Hash. If an Array is used,
65
+ # the components must be supplied as <code>[to, headers]</code>.
66
+ #
67
+ # If a Hash is used, the keys are the component names preceded by colons.
68
+ #
69
+ # The headers can be supplied as a pre-encoded string, such as
70
+ # <code>"subject=subscribe&cc=address"</code>, or as an Array of Arrays
71
+ # like <code>[['subject', 'subscribe'], ['cc', 'address']]</code>.
72
+ #
73
+ # Examples:
74
+ #
75
+ # require 'uri'
76
+ #
77
+ # m1 = URI::MailTo.build(['joe@example.com', 'subject=Ruby'])
78
+ # m1.to_s # => "mailto:joe@example.com?subject=Ruby"
79
+ #
80
+ # m2 = URI::MailTo.build(['john@example.com', [['Subject', 'Ruby'], ['Cc', 'jack@example.com']]])
81
+ # m2.to_s # => "mailto:john@example.com?Subject=Ruby&Cc=jack@example.com"
82
+ #
83
+ # m3 = URI::MailTo.build({:to => 'listman@example.com', :headers => [['subject', 'subscribe']]})
84
+ # m3.to_s # => "mailto:listman@example.com?subject=subscribe"
85
+ #
86
+ def self.build(args)
87
+ tmp = Util.make_components_hash(self, args)
88
+
89
+ case tmp[:to]
90
+ when Array
91
+ tmp[:opaque] = tmp[:to].join(',')
92
+ when String
93
+ tmp[:opaque] = tmp[:to].dup
94
+ else
95
+ tmp[:opaque] = ''
96
+ end
97
+
98
+ if tmp[:headers]
99
+ query =
100
+ case tmp[:headers]
101
+ when Array
102
+ tmp[:headers].collect { |x|
103
+ if x.kind_of?(Array)
104
+ x[0] + '=' + x[1..-1].join
105
+ else
106
+ x.to_s
107
+ end
108
+ }.join('&')
109
+ when Hash
110
+ tmp[:headers].collect { |h,v|
111
+ h + '=' + v
112
+ }.join('&')
113
+ else
114
+ tmp[:headers].to_s
115
+ end
116
+ unless query.empty?
117
+ tmp[:opaque] << '?' << query
118
+ end
119
+ end
120
+
121
+ super(tmp)
122
+ end
123
+
124
+ #
125
+ # == Description
126
+ #
127
+ # Creates a new URI::MailTo object from generic URL components with
128
+ # no syntax checking.
129
+ #
130
+ # This method is usually called from URI::parse, which checks
131
+ # the validity of each component.
132
+ #
133
+ def initialize(*arg)
134
+ super(*arg)
135
+
136
+ @to = nil
137
+ @headers = []
138
+
139
+ # The RFC3986 parser does not normally populate opaque
140
+ @opaque = "?#{@query}" if @query && !@opaque
141
+
142
+ unless @opaque
143
+ raise InvalidComponentError,
144
+ "missing opaque part for mailto URL"
145
+ end
146
+ to, header = @opaque.split('?', 2)
147
+ # allow semicolon as a addr-spec separator
148
+ # http://support.microsoft.com/kb/820868
149
+ unless /\A(?:[^@,;]+@[^@,;]+(?:\z|[,;]))*\z/ =~ to
150
+ raise InvalidComponentError,
151
+ "unrecognised opaque part for mailtoURL: #{@opaque}"
152
+ end
153
+
154
+ if arg[10] # arg_check
155
+ self.to = to
156
+ self.headers = header
157
+ else
158
+ set_to(to)
159
+ set_headers(header)
160
+ end
161
+ end
162
+
163
+ # The primary e-mail address of the URL, as a String.
164
+ attr_reader :to
165
+
166
+ # E-mail headers set by the URL, as an Array of Arrays.
167
+ attr_reader :headers
168
+
169
+ # Checks the to +v+ component.
170
+ def check_to(v)
171
+ return true unless v
172
+ return true if v.size == 0
173
+
174
+ v.split(/[,;]/).each do |addr|
175
+ # check url safety as path-rootless
176
+ if /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*\z/ !~ addr
177
+ raise InvalidComponentError,
178
+ "an address in 'to' is invalid as URI #{addr.dump}"
179
+ end
180
+
181
+ # check addr-spec
182
+ # don't s/\+/ /g
183
+ addr.gsub!(/%\h\h/, URI::TBLDECWWWCOMP_)
184
+ if EMAIL_REGEXP !~ addr
185
+ raise InvalidComponentError,
186
+ "an address in 'to' is invalid as uri-escaped addr-spec #{addr.dump}"
187
+ end
188
+ end
189
+
190
+ true
191
+ end
192
+ private :check_to
193
+
194
+ # Private setter for to +v+.
195
+ def set_to(v)
196
+ @to = v
197
+ end
198
+ protected :set_to
199
+
200
+ # Setter for to +v+.
201
+ def to=(v)
202
+ check_to(v)
203
+ set_to(v)
204
+ v
205
+ end
206
+
207
+ # Checks the headers +v+ component against either
208
+ # * HEADER_REGEXP
209
+ def check_headers(v)
210
+ return true unless v
211
+ return true if v.size == 0
212
+ if HEADER_REGEXP !~ v
213
+ raise InvalidComponentError,
214
+ "bad component(expected opaque component): #{v}"
215
+ end
216
+
217
+ true
218
+ end
219
+ private :check_headers
220
+
221
+ # Private setter for headers +v+.
222
+ def set_headers(v)
223
+ @headers = []
224
+ if v
225
+ v.split('&').each do |x|
226
+ @headers << x.split(/=/, 2)
227
+ end
228
+ end
229
+ end
230
+ protected :set_headers
231
+
232
+ # Setter for headers +v+.
233
+ def headers=(v)
234
+ check_headers(v)
235
+ set_headers(v)
236
+ v
237
+ end
238
+
239
+ # Constructs String from URI.
240
+ def to_s
241
+ @scheme + ':' +
242
+ if @to
243
+ @to
244
+ else
245
+ ''
246
+ end +
247
+ if @headers.size > 0
248
+ '?' + @headers.collect{|x| x.join('=')}.join('&')
249
+ else
250
+ ''
251
+ end +
252
+ if @fragment
253
+ '#' + @fragment
254
+ else
255
+ ''
256
+ end
257
+ end
258
+
259
+ # Returns the RFC822 e-mail text equivalent of the URL, as a String.
260
+ #
261
+ # Example:
262
+ #
263
+ # require 'uri'
264
+ #
265
+ # uri = URI.parse("mailto:ruby-list@ruby-lang.org?Subject=subscribe&cc=myaddr")
266
+ # uri.to_mailtext
267
+ # # => "To: ruby-list@ruby-lang.org\nSubject: subscribe\nCc: myaddr\n\n\n"
268
+ #
269
+ def to_mailtext
270
+ to = URI.decode_www_form_component(@to)
271
+ head = ''
272
+ body = ''
273
+ @headers.each do |x|
274
+ case x[0]
275
+ when 'body'
276
+ body = URI.decode_www_form_component(x[1])
277
+ when 'to'
278
+ to << ', ' + URI.decode_www_form_component(x[1])
279
+ else
280
+ head << URI.decode_www_form_component(x[0]).capitalize + ': ' +
281
+ URI.decode_www_form_component(x[1]) + "\n"
282
+ end
283
+ end
284
+
285
+ "To: #{to}
286
+ #{head}
287
+ #{body}
288
+ "
289
+ end
290
+ alias to_rfc822text to_mailtext
291
+ end
292
+
293
+ @@schemes['MAILTO'] = MailTo
294
+ end