ruby-openid2 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +136 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/CONTRIBUTING.md +54 -0
- data/LICENSE.txt +210 -0
- data/README.md +81 -0
- data/SECURITY.md +15 -0
- data/lib/hmac/hmac.rb +110 -0
- data/lib/hmac/sha1.rb +11 -0
- data/lib/hmac/sha2.rb +25 -0
- data/lib/openid/association.rb +246 -0
- data/lib/openid/consumer/associationmanager.rb +354 -0
- data/lib/openid/consumer/checkid_request.rb +179 -0
- data/lib/openid/consumer/discovery.rb +516 -0
- data/lib/openid/consumer/discovery_manager.rb +144 -0
- data/lib/openid/consumer/html_parse.rb +142 -0
- data/lib/openid/consumer/idres.rb +513 -0
- data/lib/openid/consumer/responses.rb +147 -0
- data/lib/openid/consumer/session.rb +36 -0
- data/lib/openid/consumer.rb +406 -0
- data/lib/openid/cryptutil.rb +112 -0
- data/lib/openid/dh.rb +84 -0
- data/lib/openid/extension.rb +38 -0
- data/lib/openid/extensions/ax.rb +552 -0
- data/lib/openid/extensions/oauth.rb +88 -0
- data/lib/openid/extensions/pape.rb +170 -0
- data/lib/openid/extensions/sreg.rb +268 -0
- data/lib/openid/extensions/ui.rb +49 -0
- data/lib/openid/fetchers.rb +277 -0
- data/lib/openid/kvform.rb +113 -0
- data/lib/openid/kvpost.rb +62 -0
- data/lib/openid/message.rb +555 -0
- data/lib/openid/protocolerror.rb +7 -0
- data/lib/openid/server.rb +1571 -0
- data/lib/openid/store/filesystem.rb +260 -0
- data/lib/openid/store/interface.rb +73 -0
- data/lib/openid/store/memcache.rb +109 -0
- data/lib/openid/store/memory.rb +79 -0
- data/lib/openid/store/nonce.rb +72 -0
- data/lib/openid/trustroot.rb +597 -0
- data/lib/openid/urinorm.rb +72 -0
- data/lib/openid/util.rb +119 -0
- data/lib/openid/version.rb +5 -0
- data/lib/openid/yadis/accept.rb +141 -0
- data/lib/openid/yadis/constants.rb +16 -0
- data/lib/openid/yadis/discovery.rb +151 -0
- data/lib/openid/yadis/filters.rb +192 -0
- data/lib/openid/yadis/htmltokenizer.rb +290 -0
- data/lib/openid/yadis/parsehtml.rb +50 -0
- data/lib/openid/yadis/services.rb +44 -0
- data/lib/openid/yadis/xrds.rb +160 -0
- data/lib/openid/yadis/xri.rb +86 -0
- data/lib/openid/yadis/xrires.rb +87 -0
- data/lib/openid.rb +27 -0
- data/lib/ruby-openid.rb +1 -0
- data.tar.gz.sig +0 -0
- metadata +331 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,555 @@
|
|
1
|
+
require_relative "util"
|
2
|
+
require_relative "kvform"
|
3
|
+
|
4
|
+
module OpenID
|
5
|
+
IDENTIFIER_SELECT = "http://specs.openid.net/auth/2.0/identifier_select"
|
6
|
+
|
7
|
+
# URI for Simple Registration extension, the only commonly deployed
|
8
|
+
# OpenID 1.x extension, and so a special case.
|
9
|
+
SREG_URI = "http://openid.net/sreg/1.0"
|
10
|
+
|
11
|
+
# The OpenID 1.x namespace URIs
|
12
|
+
OPENID1_NS = "http://openid.net/signon/1.0"
|
13
|
+
OPENID11_NS = "http://openid.net/signon/1.1"
|
14
|
+
OPENID1_NAMESPACES = [OPENID1_NS, OPENID11_NS]
|
15
|
+
|
16
|
+
# The OpenID 2.0 namespace URI
|
17
|
+
OPENID2_NS = "http://specs.openid.net/auth/2.0"
|
18
|
+
|
19
|
+
# The namespace consisting of pairs with keys that are prefixed with
|
20
|
+
# "openid." but not in another namespace.
|
21
|
+
NULL_NAMESPACE = :null_namespace
|
22
|
+
|
23
|
+
# The null namespace, when it is an allowed OpenID namespace
|
24
|
+
OPENID_NS = :openid_namespace
|
25
|
+
|
26
|
+
# The top-level namespace, excluding all pairs with keys that start
|
27
|
+
# with "openid."
|
28
|
+
BARE_NS = :bare_namespace
|
29
|
+
|
30
|
+
# Limit, in bytes, of identity provider and return_to URLs,
|
31
|
+
# including response payload. See OpenID 1.1 specification,
|
32
|
+
# Appendix D.
|
33
|
+
OPENID1_URL_LIMIT = 2047
|
34
|
+
|
35
|
+
# All OpenID protocol fields. Used to check namespace aliases.
|
36
|
+
OPENID_PROTOCOL_FIELDS = %w[
|
37
|
+
ns
|
38
|
+
mode
|
39
|
+
error
|
40
|
+
return_to
|
41
|
+
contact
|
42
|
+
reference
|
43
|
+
signed
|
44
|
+
assoc_type
|
45
|
+
session_type
|
46
|
+
dh_modulus
|
47
|
+
dh_gen
|
48
|
+
dh_consumer_public
|
49
|
+
claimed_id
|
50
|
+
identity
|
51
|
+
realm
|
52
|
+
invalidate_handle
|
53
|
+
op_endpoint
|
54
|
+
response_nonce
|
55
|
+
sig
|
56
|
+
assoc_handle
|
57
|
+
trust_root
|
58
|
+
openid
|
59
|
+
]
|
60
|
+
|
61
|
+
# Sentinel used for Message implementation to indicate that getArg
|
62
|
+
# should raise an exception instead of returning a default.
|
63
|
+
NO_DEFAULT = :no_default
|
64
|
+
|
65
|
+
# Raised if the generic OpenID namespace is accessed when there
|
66
|
+
# is no OpenID namespace set for this message.
|
67
|
+
class UndefinedOpenIDNamespace < Exception; end
|
68
|
+
|
69
|
+
# Raised when an alias or namespace URI has already been registered.
|
70
|
+
class NamespaceAliasRegistrationError < Exception; end
|
71
|
+
|
72
|
+
# Raised if openid.ns is not a recognized value.
|
73
|
+
# See Message class variable @@allowed_openid_namespaces
|
74
|
+
class InvalidOpenIDNamespace < Exception; end
|
75
|
+
|
76
|
+
class Message
|
77
|
+
attr_reader :namespaces
|
78
|
+
|
79
|
+
# Raised when key lookup fails
|
80
|
+
class KeyNotFound < IndexError; end
|
81
|
+
|
82
|
+
# Namespace / alias registration map. See
|
83
|
+
# register_namespace_alias.
|
84
|
+
@@registered_aliases = {}
|
85
|
+
|
86
|
+
# Registers a (namespace URI, alias) mapping in a global namespace
|
87
|
+
# alias map. Raises NamespaceAliasRegistrationError if either the
|
88
|
+
# namespace URI or alias has already been registered with a
|
89
|
+
# different value. This function is required if you want to use a
|
90
|
+
# namespace with an OpenID 1 message.
|
91
|
+
def self.register_namespace_alias(namespace_uri, alias_)
|
92
|
+
return if @@registered_aliases[alias_] == namespace_uri
|
93
|
+
|
94
|
+
if @@registered_aliases.values.include?(namespace_uri)
|
95
|
+
raise NamespaceAliasRegistrationError,
|
96
|
+
'Namespace uri #{namespace_uri} already registered'
|
97
|
+
end
|
98
|
+
|
99
|
+
if @@registered_aliases.member?(alias_)
|
100
|
+
raise NamespaceAliasRegistrationError,
|
101
|
+
'Alias #{alias_} already registered'
|
102
|
+
end
|
103
|
+
|
104
|
+
@@registered_aliases[alias_] = namespace_uri
|
105
|
+
end
|
106
|
+
|
107
|
+
@@allowed_openid_namespaces = [OPENID1_NS, OPENID2_NS, OPENID11_NS]
|
108
|
+
|
109
|
+
# Raises InvalidNamespaceError if you try to instantiate a Message
|
110
|
+
# with a namespace not in the above allowed list
|
111
|
+
def initialize(openid_namespace = nil)
|
112
|
+
@args = {}
|
113
|
+
@namespaces = NamespaceMap.new
|
114
|
+
if openid_namespace
|
115
|
+
implicit = OPENID1_NAMESPACES.member?(openid_namespace)
|
116
|
+
set_openid_namespace(openid_namespace, implicit)
|
117
|
+
else
|
118
|
+
@openid_ns_uri = nil
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Construct a Message containing a set of POST arguments.
|
123
|
+
# Raises InvalidNamespaceError if you try to instantiate a Message
|
124
|
+
# with a namespace not in the above allowed list
|
125
|
+
def self.from_post_args(args)
|
126
|
+
m = Message.new
|
127
|
+
openid_args = {}
|
128
|
+
args.each do |key, value|
|
129
|
+
if value.is_a?(Array)
|
130
|
+
raise ArgumentError, "Query dict must have one value for each key, " +
|
131
|
+
"not lists of values. Query is #{args.inspect}"
|
132
|
+
end
|
133
|
+
|
134
|
+
prefix, rest = key.split(".", 2)
|
135
|
+
|
136
|
+
if prefix != "openid" or rest.nil?
|
137
|
+
m.set_arg(BARE_NS, key, value)
|
138
|
+
else
|
139
|
+
openid_args[rest] = value
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
m._from_openid_args(openid_args)
|
144
|
+
m
|
145
|
+
end
|
146
|
+
|
147
|
+
# Construct a Message from a parsed KVForm message.
|
148
|
+
# Raises InvalidNamespaceError if you try to instantiate a Message
|
149
|
+
# with a namespace not in the above allowed list
|
150
|
+
def self.from_openid_args(openid_args)
|
151
|
+
m = Message.new
|
152
|
+
m._from_openid_args(openid_args)
|
153
|
+
m
|
154
|
+
end
|
155
|
+
|
156
|
+
# Raises InvalidNamespaceError if you try to instantiate a Message
|
157
|
+
# with a namespace not in the above allowed list
|
158
|
+
def _from_openid_args(openid_args)
|
159
|
+
ns_args = []
|
160
|
+
|
161
|
+
# resolve namespaces
|
162
|
+
openid_args.each do |rest, value|
|
163
|
+
ns_alias, ns_key = rest.split(".", 2)
|
164
|
+
if ns_key.nil?
|
165
|
+
ns_alias = NULL_NAMESPACE
|
166
|
+
ns_key = rest
|
167
|
+
end
|
168
|
+
|
169
|
+
if ns_alias == "ns"
|
170
|
+
@namespaces.add_alias(value, ns_key)
|
171
|
+
elsif ns_alias == NULL_NAMESPACE and ns_key == "ns"
|
172
|
+
set_openid_namespace(value, false)
|
173
|
+
else
|
174
|
+
ns_args << [ns_alias, ns_key, value]
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
# implicitly set an OpenID 1 namespace
|
179
|
+
set_openid_namespace(OPENID1_NS, true) unless get_openid_namespace
|
180
|
+
|
181
|
+
# put the pairs into the appropriate namespaces
|
182
|
+
ns_args.each do |ns_alias, ns_key, value|
|
183
|
+
ns_uri = @namespaces.get_namespace_uri(ns_alias)
|
184
|
+
unless ns_uri
|
185
|
+
ns_uri = _get_default_namespace(ns_alias)
|
186
|
+
if ns_uri
|
187
|
+
@namespaces.add_alias(ns_uri, ns_alias, true)
|
188
|
+
else
|
189
|
+
ns_uri = get_openid_namespace
|
190
|
+
ns_key = "#{ns_alias}.#{ns_key}"
|
191
|
+
end
|
192
|
+
end
|
193
|
+
set_arg(ns_uri, ns_key, value)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def _get_default_namespace(mystery_alias)
|
198
|
+
# only try to map an alias to a default if it's an
|
199
|
+
# OpenID 1.x namespace
|
200
|
+
@@registered_aliases[mystery_alias] if is_openid1
|
201
|
+
end
|
202
|
+
|
203
|
+
def set_openid_namespace(openid_ns_uri, implicit)
|
204
|
+
unless @@allowed_openid_namespaces.include?(openid_ns_uri)
|
205
|
+
raise InvalidOpenIDNamespace, "Invalid null namespace: #{openid_ns_uri}"
|
206
|
+
end
|
207
|
+
|
208
|
+
@namespaces.add_alias(openid_ns_uri, NULL_NAMESPACE, implicit)
|
209
|
+
@openid_ns_uri = openid_ns_uri
|
210
|
+
end
|
211
|
+
|
212
|
+
def get_openid_namespace
|
213
|
+
@openid_ns_uri
|
214
|
+
end
|
215
|
+
|
216
|
+
def is_openid1
|
217
|
+
OPENID1_NAMESPACES.member?(@openid_ns_uri)
|
218
|
+
end
|
219
|
+
|
220
|
+
def is_openid2
|
221
|
+
@openid_ns_uri == OPENID2_NS
|
222
|
+
end
|
223
|
+
|
224
|
+
# Create a message from a KVForm string
|
225
|
+
def self.from_kvform(kvform_string)
|
226
|
+
Message.from_openid_args(Util.kv_to_dict(kvform_string))
|
227
|
+
end
|
228
|
+
|
229
|
+
def copy
|
230
|
+
Marshal.load(Marshal.dump(self))
|
231
|
+
end
|
232
|
+
|
233
|
+
# Return all arguments with "openid." in from of namespaced arguments.
|
234
|
+
def to_post_args
|
235
|
+
args = {}
|
236
|
+
|
237
|
+
# add namespace defs to the output
|
238
|
+
@namespaces.each do |ns_uri, ns_alias|
|
239
|
+
next if @namespaces.implicit?(ns_uri)
|
240
|
+
|
241
|
+
ns_key = if ns_alias == NULL_NAMESPACE
|
242
|
+
"openid.ns"
|
243
|
+
else
|
244
|
+
"openid.ns." + ns_alias
|
245
|
+
end
|
246
|
+
args[ns_key] = ns_uri
|
247
|
+
end
|
248
|
+
|
249
|
+
@args.each do |k, value|
|
250
|
+
ns_uri, ns_key = k
|
251
|
+
key = get_key(ns_uri, ns_key)
|
252
|
+
args[key] = value
|
253
|
+
end
|
254
|
+
|
255
|
+
args
|
256
|
+
end
|
257
|
+
|
258
|
+
# Return all namespaced arguments, failing if any non-namespaced arguments
|
259
|
+
# exist.
|
260
|
+
def to_args
|
261
|
+
post_args = to_post_args
|
262
|
+
kvargs = {}
|
263
|
+
post_args.each do |k, v|
|
264
|
+
if !k.start_with?("openid.")
|
265
|
+
raise ArgumentError,
|
266
|
+
"This message can only be encoded as a POST, because it contains arguments that are not prefixed with 'openid.'"
|
267
|
+
else
|
268
|
+
kvargs[k[7..-1]] = v
|
269
|
+
end
|
270
|
+
end
|
271
|
+
kvargs
|
272
|
+
end
|
273
|
+
|
274
|
+
# Generate HTML form markup that contains the values in this
|
275
|
+
# message, to be HTTP POSTed as x-www-form-urlencoded UTF-8.
|
276
|
+
def to_form_markup(action_url, form_tag_attrs = nil, submit_text = "Continue")
|
277
|
+
form_tag_attr_map = {}
|
278
|
+
|
279
|
+
if form_tag_attrs
|
280
|
+
form_tag_attrs.each do |name, attr|
|
281
|
+
form_tag_attr_map[name] = attr
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
form_tag_attr_map["action"] = action_url
|
286
|
+
form_tag_attr_map["method"] = "post"
|
287
|
+
form_tag_attr_map["accept-charset"] = "UTF-8"
|
288
|
+
form_tag_attr_map["enctype"] = "application/x-www-form-urlencoded"
|
289
|
+
|
290
|
+
markup = "<form "
|
291
|
+
|
292
|
+
form_tag_attr_map.each do |k, v|
|
293
|
+
markup += " #{k}=\"#{v}\""
|
294
|
+
end
|
295
|
+
|
296
|
+
markup += ">\n"
|
297
|
+
|
298
|
+
to_post_args.each do |k, v|
|
299
|
+
markup += "<input type='hidden' name='#{k}' value='#{OpenID::Util.html_encode(v)}' />\n"
|
300
|
+
end
|
301
|
+
markup += "<input type='submit' value='#{submit_text}' />\n"
|
302
|
+
markup += "\n</form>"
|
303
|
+
markup
|
304
|
+
end
|
305
|
+
|
306
|
+
# Generate a GET URL with the paramters in this message attacked as
|
307
|
+
# query parameters.
|
308
|
+
def to_url(base_url)
|
309
|
+
Util.append_args(base_url, to_post_args)
|
310
|
+
end
|
311
|
+
|
312
|
+
# Generate a KVForm string that contains the parameters in this message.
|
313
|
+
# This will fail is the message contains arguments outside of the
|
314
|
+
# "openid." prefix.
|
315
|
+
def to_kvform
|
316
|
+
Util.dict_to_kv(to_args)
|
317
|
+
end
|
318
|
+
|
319
|
+
# Generate an x-www-urlencoded string.
|
320
|
+
def to_url_encoded
|
321
|
+
args = to_post_args.map.sort
|
322
|
+
Util.urlencode(args)
|
323
|
+
end
|
324
|
+
|
325
|
+
# Convert an input value into the internally used values of this obejct.
|
326
|
+
def _fix_ns(namespace)
|
327
|
+
if namespace == OPENID_NS
|
328
|
+
raise UndefinedOpenIDNamespace, "OpenID namespace not set" unless @openid_ns_uri
|
329
|
+
|
330
|
+
namespace = @openid_ns_uri
|
331
|
+
|
332
|
+
end
|
333
|
+
|
334
|
+
return namespace if namespace == BARE_NS
|
335
|
+
|
336
|
+
unless namespace.is_a?(String)
|
337
|
+
raise ArgumentError, "Namespace must be BARE_NS, OPENID_NS or " \
|
338
|
+
"a string. Got #{namespace.inspect}"
|
339
|
+
end
|
340
|
+
|
341
|
+
if namespace.index(":").nil?
|
342
|
+
msg = "OpenID 2.0 namespace identifiers SHOULD be URIs. " \
|
343
|
+
"Got #{namespace.inspect}"
|
344
|
+
Util.log(msg)
|
345
|
+
|
346
|
+
if namespace == "sreg"
|
347
|
+
msg = "Using #{SREG_URI} instead of \"sreg\" as namespace"
|
348
|
+
Util.log(msg)
|
349
|
+
return SREG_URI
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
namespace
|
354
|
+
end
|
355
|
+
|
356
|
+
def has_key?(namespace, ns_key)
|
357
|
+
namespace = _fix_ns(namespace)
|
358
|
+
@args.member?([namespace, ns_key])
|
359
|
+
end
|
360
|
+
|
361
|
+
# Get the key for a particular namespaced argument
|
362
|
+
def get_key(namespace, ns_key)
|
363
|
+
namespace = _fix_ns(namespace)
|
364
|
+
return ns_key if namespace == BARE_NS
|
365
|
+
|
366
|
+
ns_alias = @namespaces.get_alias(namespace)
|
367
|
+
|
368
|
+
# no alias is defined, so no key can exist
|
369
|
+
return if ns_alias.nil?
|
370
|
+
|
371
|
+
tail = if ns_alias == NULL_NAMESPACE
|
372
|
+
ns_key
|
373
|
+
else
|
374
|
+
"#{ns_alias}.#{ns_key}"
|
375
|
+
end
|
376
|
+
|
377
|
+
"openid." + tail
|
378
|
+
end
|
379
|
+
|
380
|
+
# Get a value for a namespaced key.
|
381
|
+
def get_arg(namespace, key, default = nil)
|
382
|
+
namespace = _fix_ns(namespace)
|
383
|
+
@args.fetch([namespace, key]) do
|
384
|
+
raise KeyNotFound, "<#{namespace}>#{key} not in this message" if default == NO_DEFAULT
|
385
|
+
|
386
|
+
default
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
# Get the arguments that are defined for this namespace URI.
|
391
|
+
def get_args(namespace)
|
392
|
+
namespace = _fix_ns(namespace)
|
393
|
+
args = {}
|
394
|
+
@args.each do |k, v|
|
395
|
+
pair_ns, ns_key = k
|
396
|
+
args[ns_key] = v if pair_ns == namespace
|
397
|
+
end
|
398
|
+
args
|
399
|
+
end
|
400
|
+
|
401
|
+
# Set multiple key/value pairs in one call.
|
402
|
+
def update_args(namespace, updates)
|
403
|
+
namespace = _fix_ns(namespace)
|
404
|
+
updates.each { |k, v| set_arg(namespace, k, v) }
|
405
|
+
end
|
406
|
+
|
407
|
+
# Set a single argument in this namespace
|
408
|
+
def set_arg(namespace, key, value)
|
409
|
+
namespace = _fix_ns(namespace)
|
410
|
+
@args[[namespace, key].freeze] = value
|
411
|
+
@namespaces.add(namespace) if namespace != BARE_NS
|
412
|
+
end
|
413
|
+
|
414
|
+
# Remove a single argument from this namespace.
|
415
|
+
def del_arg(namespace, key)
|
416
|
+
namespace = _fix_ns(namespace)
|
417
|
+
_key = [namespace, key]
|
418
|
+
@args.delete(_key)
|
419
|
+
end
|
420
|
+
|
421
|
+
def ==(other)
|
422
|
+
other.is_a?(self.class) && @args == other.instance_eval { @args }
|
423
|
+
end
|
424
|
+
|
425
|
+
def get_aliased_arg(aliased_key, default = nil)
|
426
|
+
return get_openid_namespace if aliased_key == "ns"
|
427
|
+
|
428
|
+
ns_alias, key = aliased_key.split(".", 2)
|
429
|
+
if ns_alias == "ns"
|
430
|
+
uri = @namespaces.get_namespace_uri(key)
|
431
|
+
return (uri.nil? ? default : uri) unless uri.nil? and default == NO_DEFAULT
|
432
|
+
|
433
|
+
raise KeyNotFound, "Namespace #{key} not defined when looking " \
|
434
|
+
"for #{aliased_key}"
|
435
|
+
|
436
|
+
end
|
437
|
+
|
438
|
+
if key.nil?
|
439
|
+
key = aliased_key
|
440
|
+
ns = nil
|
441
|
+
else
|
442
|
+
ns = @namespaces.get_namespace_uri(ns_alias)
|
443
|
+
end
|
444
|
+
|
445
|
+
if ns.nil?
|
446
|
+
key = aliased_key
|
447
|
+
ns = get_openid_namespace
|
448
|
+
end
|
449
|
+
|
450
|
+
get_arg(ns, key, default)
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
# Maintains a bidirectional map between namespace URIs and aliases.
|
455
|
+
class NamespaceMap
|
456
|
+
def initialize
|
457
|
+
@alias_to_namespace = {}
|
458
|
+
@namespace_to_alias = {}
|
459
|
+
@implicit_namespaces = []
|
460
|
+
end
|
461
|
+
|
462
|
+
def get_alias(namespace_uri)
|
463
|
+
@namespace_to_alias[namespace_uri]
|
464
|
+
end
|
465
|
+
|
466
|
+
def get_namespace_uri(namespace_alias)
|
467
|
+
@alias_to_namespace[namespace_alias]
|
468
|
+
end
|
469
|
+
|
470
|
+
# Add an alias from this namespace URI to the alias.
|
471
|
+
def add_alias(namespace_uri, desired_alias, implicit = false)
|
472
|
+
# Check that desired_alias is not an openid protocol field as
|
473
|
+
# per the spec.
|
474
|
+
Util.truthy_assert(
|
475
|
+
!OPENID_PROTOCOL_FIELDS.include?(desired_alias),
|
476
|
+
"#{desired_alias} is not an allowed namespace alias",
|
477
|
+
)
|
478
|
+
|
479
|
+
# check that there is not a namespace already defined for the
|
480
|
+
# desired alias
|
481
|
+
current_namespace_uri = @alias_to_namespace.fetch(desired_alias, nil)
|
482
|
+
if current_namespace_uri and current_namespace_uri != namespace_uri
|
483
|
+
raise IndexError,
|
484
|
+
"Cannot map #{namespace_uri} to alias #{desired_alias}. #{current_namespace_uri} is already mapped to alias #{desired_alias}"
|
485
|
+
end
|
486
|
+
|
487
|
+
# Check that desired_alias does not contain a period as per the
|
488
|
+
# spec.
|
489
|
+
if desired_alias.is_a?(String)
|
490
|
+
Util.truthy_assert(
|
491
|
+
desired_alias.index(".").nil?,
|
492
|
+
"#{desired_alias} must not contain a dot",
|
493
|
+
)
|
494
|
+
end
|
495
|
+
|
496
|
+
# check that there is not already a (different) alias for this
|
497
|
+
# namespace URI.
|
498
|
+
_alias = @namespace_to_alias[namespace_uri]
|
499
|
+
if _alias and _alias != desired_alias
|
500
|
+
raise IndexError,
|
501
|
+
"Cannot map #{namespace_uri} to alias #{desired_alias}. It is already mapped to alias #{_alias}"
|
502
|
+
end
|
503
|
+
|
504
|
+
@alias_to_namespace[desired_alias] = namespace_uri
|
505
|
+
@namespace_to_alias[namespace_uri] = desired_alias
|
506
|
+
@implicit_namespaces << namespace_uri if implicit
|
507
|
+
desired_alias
|
508
|
+
end
|
509
|
+
|
510
|
+
# Add this namespace URI to the mapping, without caring what alias
|
511
|
+
# it ends up with.
|
512
|
+
def add(namespace_uri)
|
513
|
+
# see if this namepace is already mapped to an alias
|
514
|
+
_alias = @namespace_to_alias[namespace_uri]
|
515
|
+
return _alias if _alias
|
516
|
+
|
517
|
+
# Fall back to generating a numberical alias
|
518
|
+
i = 0
|
519
|
+
while true
|
520
|
+
_alias = "ext" + i.to_s
|
521
|
+
begin
|
522
|
+
add_alias(namespace_uri, _alias)
|
523
|
+
rescue IndexError
|
524
|
+
i += 1
|
525
|
+
else
|
526
|
+
return _alias
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
raise StandardError, "Unreachable"
|
531
|
+
end
|
532
|
+
|
533
|
+
def member?(namespace_uri)
|
534
|
+
@namespace_to_alias.has_key?(namespace_uri)
|
535
|
+
end
|
536
|
+
|
537
|
+
def each(&block)
|
538
|
+
@namespace_to_alias.each(&block)
|
539
|
+
end
|
540
|
+
|
541
|
+
def namespace_uris
|
542
|
+
# Return an iterator over the namespace URIs
|
543
|
+
@namespace_to_alias.keys
|
544
|
+
end
|
545
|
+
|
546
|
+
def implicit?(namespace_uri)
|
547
|
+
@implicit_namespaces.member?(namespace_uri)
|
548
|
+
end
|
549
|
+
|
550
|
+
def aliases
|
551
|
+
# Return an iterator over the aliases
|
552
|
+
@alias_to_namespace.keys
|
553
|
+
end
|
554
|
+
end
|
555
|
+
end
|