ruby-openid 2.0.4 → 2.1.2

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

Potentially problematic release.


This version of ruby-openid might be problematic. Click here for more details.

Files changed (58) hide show
  1. data/CHANGELOG +65 -28
  2. data/LICENSE +4 -1
  3. data/README +19 -12
  4. data/UPGRADE +5 -0
  5. data/examples/README +8 -22
  6. data/examples/active_record_openid_store/XXX_add_open_id_store_to_db.rb +6 -6
  7. data/examples/active_record_openid_store/lib/association.rb +2 -1
  8. data/examples/active_record_openid_store/lib/openid_ar_store.rb +3 -3
  9. data/examples/rails_openid/app/controllers/consumer_controller.rb +11 -5
  10. data/lib/openid.rb +4 -0
  11. data/lib/openid/association.rb +7 -7
  12. data/lib/openid/consumer/checkid_request.rb +11 -0
  13. data/lib/openid/consumer/discovery.rb +12 -3
  14. data/lib/openid/consumer/idres.rb +35 -43
  15. data/lib/openid/extension.rb +9 -1
  16. data/lib/openid/extensions/pape.rb +22 -25
  17. data/lib/openid/extensions/sreg.rb +1 -0
  18. data/lib/openid/fetchers.rb +25 -5
  19. data/lib/openid/kvform.rb +8 -5
  20. data/lib/openid/kvpost.rb +6 -5
  21. data/lib/openid/message.rb +53 -34
  22. data/lib/openid/server.rb +87 -52
  23. data/lib/openid/trustroot.rb +25 -17
  24. data/lib/openid/util.rb +19 -4
  25. data/lib/openid/yadis/discovery.rb +3 -3
  26. data/lib/openid/yadis/htmltokenizer.rb +8 -5
  27. data/lib/openid/yadis/parsehtml.rb +22 -14
  28. data/lib/openid/yadis/xrds.rb +6 -9
  29. data/test/data/linkparse.txt +1 -1
  30. data/test/data/test1-parsehtml.txt +24 -0
  31. data/test/data/trustroot.txt +8 -2
  32. data/test/test_association.rb +7 -7
  33. data/test/test_associationmanager.rb +1 -1
  34. data/test/test_extension.rb +46 -0
  35. data/test/test_idres.rb +81 -21
  36. data/test/test_kvform.rb +5 -5
  37. data/test/test_message.rb +61 -3
  38. data/test/test_pape.rb +36 -22
  39. data/test/test_server.rb +190 -12
  40. data/test/test_sreg.rb +0 -1
  41. data/test/test_trustroot.rb +1 -0
  42. data/test/test_yadis_discovery.rb +13 -0
  43. metadata +3 -19
  44. data/examples/rails_openid/app/views/consumer/start.rhtml +0 -8
  45. data/examples/rails_openid_login_generator/USAGE +0 -23
  46. data/examples/rails_openid_login_generator/gemspec +0 -13
  47. data/examples/rails_openid_login_generator/openid_login_generator.rb +0 -36
  48. data/examples/rails_openid_login_generator/templates/README +0 -116
  49. data/examples/rails_openid_login_generator/templates/controller.rb +0 -113
  50. data/examples/rails_openid_login_generator/templates/controller_test.rb +0 -0
  51. data/examples/rails_openid_login_generator/templates/helper.rb +0 -2
  52. data/examples/rails_openid_login_generator/templates/openid_login_system.rb +0 -87
  53. data/examples/rails_openid_login_generator/templates/user.rb +0 -14
  54. data/examples/rails_openid_login_generator/templates/user_test.rb +0 -0
  55. data/examples/rails_openid_login_generator/templates/users.yml +0 -0
  56. data/examples/rails_openid_login_generator/templates/view_login.rhtml +0 -15
  57. data/examples/rails_openid_login_generator/templates/view_logout.rhtml +0 -10
  58. data/examples/rails_openid_login_generator/templates/view_welcome.rhtml +0 -9
@@ -19,9 +19,17 @@ module OpenID
19
19
  # message, or create a new message containing only those
20
20
  # arguments. Returns the message with added extension args.
21
21
  def to_message(message = nil)
22
+ if message.nil?
23
+ # warnings.warn('Passing None to Extension.toMessage is deprecated. '
24
+ # 'Creating a message assuming you want OpenID 2.',
25
+ # DeprecationWarning, stacklevel=2)
26
+ Message.new(OPENID2_NS)
27
+ end
22
28
  message = Message.new if message.nil?
23
29
 
24
- message.namespaces.add_alias(@ns_uri, @ns_alias)
30
+ implicit = message.is_openid1()
31
+
32
+ message.namespaces.add_alias(@ns_uri, @ns_alias, implicit)
25
33
  # XXX python ignores keyerror if m.ns.getAlias(uri) == alias
26
34
 
27
35
  message.update_args(@ns_uri, get_extension_args)
@@ -14,7 +14,7 @@ module OpenID
14
14
  'http://schemas.openid.net/pape/policies/2007/06/multi-factor'
15
15
  AUTH_PHISHING_RESISTANT =
16
16
  'http://schemas.openid.net/pape/policies/2007/06/phishing-resistant'
17
-
17
+ TIME_VALIDATOR = /\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ/
18
18
  # A Provider Authentication Policy request, sent from a relying
19
19
  # party to a provider
20
20
  class Request < Extension
@@ -86,12 +86,12 @@ module OpenID
86
86
  # A Provider Authentication Policy response, sent from a provider
87
87
  # to a relying party
88
88
  class Response < Extension
89
- attr_accessor :ns_alias, :auth_policies, :auth_age, :nist_auth_level
90
- def initialize(auth_policies=[], auth_age=nil, nist_auth_level=nil)
89
+ attr_accessor :ns_alias, :auth_policies, :auth_time, :nist_auth_level
90
+ def initialize(auth_policies=[], auth_time=nil, nist_auth_level=nil)
91
91
  @ns_alias = 'pape'
92
92
  @ns_uri = NS_URI
93
93
  @auth_policies = auth_policies
94
- @auth_age = auth_age
94
+ @auth_time = auth_time
95
95
  @nist_auth_level = nist_auth_level
96
96
  end
97
97
 
@@ -104,6 +104,7 @@ module OpenID
104
104
  # Create a Response object from an OpenID::Consumer::SuccessResponse
105
105
  def self.from_success_response(success_response)
106
106
  args = success_response.get_signed_ns(NS_URI)
107
+ return nil if args.nil?
107
108
  pape_resp = new
108
109
  pape_resp.parse_extension_args(args)
109
110
  return pape_resp
@@ -115,7 +116,7 @@ module OpenID
115
116
  # encountered
116
117
  def parse_extension_args(args, strict=false)
117
118
  policies_str = args['auth_policies']
118
- if policies_str
119
+ if policies_str and policies_str != 'none'
119
120
  @auth_policies = policies_str.split(' ')
120
121
  end
121
122
 
@@ -138,28 +139,24 @@ module OpenID
138
139
  end
139
140
  end
140
141
 
141
- auth_age_str = args['auth_age']
142
- if auth_age_str
143
- # special handling of zero to handle to_i behavior
144
- if auth_age_str.strip == '0'
145
- auth_age = 0
146
- else
147
- auth_age = auth_age_str.to_i
148
- # if it's zero here we have a bad value
149
- if auth_age == 0
150
- auth_age = nil
151
- end
152
- end
153
- if auth_age and auth_age >= 0
154
- @auth_age = auth_age
142
+ auth_time_str = args['auth_time']
143
+ if auth_time_str
144
+ # validate time string
145
+ if auth_time_str =~ TIME_VALIDATOR
146
+ @auth_time = auth_time_str
155
147
  elsif strict
156
- raise ArgumentError, "auth_age must be a non-negative integer, not #{auth_age_str.inspect}"
148
+ raise ArgumentError, "auth_time must be in RFC3339 format"
157
149
  end
158
150
  end
159
151
  end
160
152
 
161
153
  def get_extension_args
162
- ns_args = {'auth_policies' => @auth_policies.join(' ')}
154
+ ns_args = {}
155
+ if @auth_policies.empty?
156
+ ns_args['auth_policies'] = 'none'
157
+ else
158
+ ns_args['auth_policies'] = @auth_policies.join(' ')
159
+ end
163
160
  if @nist_auth_level
164
161
  unless (0..4).member? @nist_auth_level
165
162
  raise ArgumentError, "nist_auth_level must be an integer 0 through 4, not #{@nist_auth_level.inspect}"
@@ -167,11 +164,11 @@ module OpenID
167
164
  ns_args['nist_auth_level'] = @nist_auth_level.to_s
168
165
  end
169
166
 
170
- if @auth_age
171
- if @auth_age < 0
172
- raise ArgumentError, "auth_age must be a non-negative integer, not #{@auth_age.inspect}"
167
+ if @auth_time
168
+ unless @auth_time =~ TIME_VALIDATOR
169
+ raise ArgumentError, "auth_time must be in RFC3339 format"
173
170
  end
174
- ns_args['auth_age'] = @auth_age.to_s
171
+ ns_args['auth_time'] = @auth_time
175
172
  end
176
173
  return ns_args
177
174
  end
@@ -246,6 +246,7 @@ module OpenID
246
246
  ns_uri = OpenID::get_sreg_ns(success_response.message)
247
247
  if signed_only
248
248
  args = success_response.get_signed_ns(ns_uri)
249
+ return nil if args.nil? # No signed args, so fail
249
250
  else
250
251
  args = success_response.message.get_args(ns_uri)
251
252
  end
@@ -10,6 +10,8 @@ rescue LoadError
10
10
  require 'net/http'
11
11
  end
12
12
 
13
+ MAX_RESPONSE_KB = 1024
14
+
13
15
  module Net
14
16
  class HTTP
15
17
  def post_connection_check(hostname)
@@ -115,14 +117,17 @@ module OpenID
115
117
  USER_AGENT = "ruby-openid/#{OpenID::VERSION} (#{RUBY_PLATFORM})"
116
118
 
117
119
  REDIRECT_LIMIT = 5
120
+ TIMEOUT = 60
118
121
 
119
122
  attr_accessor :ca_file
123
+ attr_accessor :timeout
120
124
 
121
125
  # I can fetch through a HTTP proxy; arguments are as for Net::HTTP::Proxy.
122
126
  def initialize(proxy_addr=nil, proxy_port=nil,
123
127
  proxy_user=nil, proxy_pass=nil)
124
128
  @ca_file = nil
125
129
  @proxy = Net::HTTP::Proxy(proxy_addr, proxy_port, proxy_user, proxy_pass)
130
+ @timeout = TIMEOUT
126
131
  end
127
132
 
128
133
  def supports_ssl?(conn)
@@ -130,7 +135,10 @@ module OpenID
130
135
  end
131
136
 
132
137
  def make_http(uri)
133
- @proxy.new(uri.host, uri.port)
138
+ http = @proxy.new(uri.host, uri.port)
139
+ http.read_timeout = @timeout
140
+ http.open_timeout = @timeout
141
+ return http
134
142
  end
135
143
 
136
144
  def set_verified(conn, verify)
@@ -173,14 +181,18 @@ module OpenID
173
181
  def fetch(url, body=nil, headers=nil, redirect_limit=REDIRECT_LIMIT)
174
182
  unparsed_url = url.dup
175
183
  url = URI::parse(url)
184
+ if url.nil?
185
+ raise FetchingError, "Invalid URL: #{unparsed_url}"
186
+ end
176
187
 
177
188
  headers ||= {}
178
189
  headers['User-agent'] ||= USER_AGENT
179
-
180
- conn = make_connection(url)
181
- response = nil
190
+ headers['Range'] ||= "0-#{MAX_RESPONSE_KB*1024}"
182
191
 
183
192
  begin
193
+ conn = make_connection(url)
194
+ response = nil
195
+
184
196
  response = conn.start {
185
197
  # Check the certificate against the URL's hostname
186
198
  if supports_ssl?(conn) and conn.use_ssl?
@@ -194,6 +206,8 @@ module OpenID
194
206
  conn.request_post(url.request_uri, body, headers)
195
207
  end
196
208
  }
209
+ rescue RuntimeError => why
210
+ raise why
197
211
  rescue OpenSSL::SSL::SSLError => why
198
212
  raise SSLFetchingError, "Error connecting to SSL URL #{url}: #{why}"
199
213
  rescue FetchingError => why
@@ -210,7 +224,13 @@ module OpenID
210
224
  raise HTTPRedirectLimitReached.new(
211
225
  "Too many redirects, not fetching #{response['location']}")
212
226
  end
213
- return fetch(response['location'], body, headers, redirect_limit - 1)
227
+ begin
228
+ return fetch(response['location'], body, headers, redirect_limit - 1)
229
+ rescue HTTPRedirectLimitReached => e
230
+ raise e
231
+ rescue FetchingError => why
232
+ raise FetchingError, "Error encountered in redirect from #{url}: #{why}"
233
+ end
214
234
  else
215
235
  return HTTPResponse._from_net_response(response, unparsed_url)
216
236
  end
data/lib/openid/kvform.rb CHANGED
@@ -1,6 +1,9 @@
1
1
 
2
2
  module OpenID
3
3
 
4
+ class KVFormError < Exception
5
+ end
6
+
4
7
  module Util
5
8
 
6
9
  def Util.seq_to_kv(seq, strict=false)
@@ -13,7 +16,7 @@ module OpenID
13
16
  err = lambda { |msg|
14
17
  msg = "seq_to_kv warning: #{msg}: #{seq.inspect}"
15
18
  if strict
16
- raise ArgumentError, msg
19
+ raise KVFormError, msg
17
20
  else
18
21
  Util.log(msg)
19
22
  end
@@ -27,11 +30,11 @@ module OpenID
27
30
  end
28
31
 
29
32
  if !k.index("\n").nil?
30
- raise ArgumentError, "Invalid input for seq_to_kv: key contains newline: #{k.inspect}"
33
+ raise KVFormError, "Invalid input for seq_to_kv: key contains newline: #{k.inspect}"
31
34
  end
32
35
 
33
36
  if !k.index(":").nil?
34
- raise ArgumentError, "Invalid input for seq_to_kv: key contains colon: #{k.inspect}"
37
+ raise KVFormError, "Invalid input for seq_to_kv: key contains colon: #{k.inspect}"
35
38
  end
36
39
 
37
40
  if k.strip() != k
@@ -44,7 +47,7 @@ module OpenID
44
47
  end
45
48
 
46
49
  if !v.index("\n").nil?
47
- raise ArgumentError, "Invalid input for seq_to_kv: value contains newline: #{v.inspect}"
50
+ raise KVFormError, "Invalid input for seq_to_kv: value contains newline: #{v.inspect}"
48
51
  end
49
52
 
50
53
  if v.strip() != v
@@ -66,7 +69,7 @@ module OpenID
66
69
  err = lambda { |msg|
67
70
  msg = "kv_to_seq warning: #{msg}: #{data.inspect}"
68
71
  if strict
69
- raise ArgumentError, msg
72
+ raise KVFormError, msg
70
73
  else
71
74
  Util.log(msg)
72
75
  end
data/lib/openid/kvpost.rb CHANGED
@@ -7,19 +7,18 @@ module OpenID
7
7
  class ServerError < OpenIDError
8
8
  attr_reader :error_text, :error_code, :message
9
9
 
10
- def initialize(error_text, error_code, message, server_url)
10
+ def initialize(error_text, error_code, message)
11
11
  super(error_text)
12
12
  @error_text = error_text
13
13
  @error_code = error_code
14
- @server_url = server_url
15
14
  @message = message
16
15
  end
17
16
 
18
- def self.from_message(msg, server_url)
17
+ def self.from_message(msg)
19
18
  error_text = msg.get_arg(OPENID_NS, 'error',
20
19
  '<no error message supplied>')
21
20
  error_code = msg.get_arg(OPENID_NS, 'error_code')
22
- return self.new(error_text, error_code, msg, server_url)
21
+ return self.new(error_text, error_code, msg)
23
22
  end
24
23
  end
25
24
 
@@ -34,8 +33,10 @@ module OpenID
34
33
  case response.code.to_i
35
34
  when 200
36
35
  return msg
36
+ when 206
37
+ return msg
37
38
  when 400
38
- raise ServerError.from_message(msg, server_url)
39
+ raise ServerError.from_message(msg)
39
40
  else
40
41
  error_message = "bad status code from server #{server_url}: "\
41
42
  "#{response.code}"
@@ -9,8 +9,10 @@ module OpenID
9
9
  # OpenID 1.x extension, and so a special case.
10
10
  SREG_URI = 'http://openid.net/sreg/1.0'
11
11
 
12
- # The OpenID 1.x namespace URI
12
+ # The OpenID 1.x namespace URIs
13
13
  OPENID1_NS = 'http://openid.net/signon/1.0'
14
+ OPENID11_NS = 'http://openid.net/signon/1.1'
15
+ OPENID1_NAMESPACES = [OPENID1_NS, OPENID11_NS]
14
16
 
15
17
  # The OpenID 2.0 namespace URI
16
18
  OPENID2_NS = 'http://specs.openid.net/auth/2.0'
@@ -54,6 +56,10 @@ module OpenID
54
56
  # Raised when an alias or namespace URI has already been registered.
55
57
  class NamespaceAliasRegistrationError < Exception; end
56
58
 
59
+ # Raised if openid.ns is not a recognized value.
60
+ # See Message class variable @@allowed_openid_namespaces
61
+ class InvalidOpenIDNamespace < Exception; end
62
+
57
63
  class Message
58
64
  attr_reader :namespaces
59
65
 
@@ -87,19 +93,24 @@ module OpenID
87
93
  @@registered_aliases[alias_] = namespace_uri
88
94
  end
89
95
 
90
- @@allowed_openid_namespaces = [OPENID1_NS, OPENID2_NS]
96
+ @@allowed_openid_namespaces = [OPENID1_NS, OPENID2_NS, OPENID11_NS]
91
97
 
92
- def initialize(openid_namspace=nil)
98
+ # Raises InvalidNamespaceError if you try to instantiate a Message
99
+ # with a namespace not in the above allowed list
100
+ def initialize(openid_namespace=nil)
93
101
  @args = {}
94
102
  @namespaces = NamespaceMap.new
95
- if openid_namspace
96
- self.set_openid_namespace(openid_namspace)
103
+ if openid_namespace
104
+ implicit = OPENID1_NAMESPACES.member? openid_namespace
105
+ self.set_openid_namespace(openid_namespace, implicit)
97
106
  else
98
107
  @openid_ns_uri = nil
99
108
  end
100
109
  end
101
110
 
102
111
  # Construct a Message containing a set of POST arguments.
112
+ # Raises InvalidNamespaceError if you try to instantiate a Message
113
+ # with a namespace not in the above allowed list
103
114
  def Message.from_post_args(args)
104
115
  m = Message.new
105
116
  openid_args = {}
@@ -123,12 +134,16 @@ module OpenID
123
134
  end
124
135
 
125
136
  # Construct a Message from a parsed KVForm message.
137
+ # Raises InvalidNamespaceError if you try to instantiate a Message
138
+ # with a namespace not in the above allowed list
126
139
  def Message.from_openid_args(openid_args)
127
140
  m = Message.new
128
141
  m._from_openid_args(openid_args)
129
142
  return m
130
143
  end
131
144
 
145
+ # Raises InvalidNamespaceError if you try to instantiate a Message
146
+ # with a namespace not in the above allowed list
132
147
  def _from_openid_args(openid_args)
133
148
  ns_args = []
134
149
 
@@ -143,47 +158,46 @@ module OpenID
143
158
  if ns_alias == 'ns'
144
159
  @namespaces.add_alias(value, ns_key)
145
160
  elsif ns_alias == NULL_NAMESPACE and ns_key == 'ns'
146
- @namespaces.add_alias(value, NULL_NAMESPACE)
161
+ set_openid_namespace(value, false)
147
162
  else
148
163
  ns_args << [ns_alias, ns_key, value]
149
164
  end
150
165
  }
151
166
 
152
- # ensure that there is an OpenID namespace definition
153
- openid_ns_uri = @namespaces.get_namespace_uri(NULL_NAMESPACE)
154
- openid_ns_uri = OPENID1_NS unless openid_ns_uri
155
-
156
- self.set_openid_namespace(openid_ns_uri)
167
+ # implicitly set an OpenID 1 namespace
168
+ unless get_openid_namespace
169
+ set_openid_namespace(OPENID1_NS, true)
170
+ end
157
171
 
158
172
  # put the pairs into the appropriate namespaces
159
173
  ns_args.each { |ns_alias, ns_key, value|
160
174
  ns_uri = @namespaces.get_namespace_uri(ns_alias)
161
175
  unless ns_uri
162
- # only try to map an alias to a default if it's an
163
- # OpenID 1.x namespace
164
- @@registered_aliases.each { |_alias, _uri|
165
- if _alias == ns_alias
166
- ns_uri = _uri
167
- break
168
- end
169
- }
170
-
176
+ ns_uri = _get_default_namespace(ns_alias)
171
177
  unless ns_uri
172
- ns_uri = openid_ns_uri
178
+ ns_uri = get_openid_namespace
173
179
  ns_key = "#{ns_alias}.#{ns_key}"
174
180
  else
175
- @namespaces.add_alias(ns_uri, ns_alias)
181
+ @namespaces.add_alias(ns_uri, ns_alias, true)
176
182
  end
177
183
  end
178
184
  self.set_arg(ns_uri, ns_key, value)
179
185
  }
180
186
  end
181
187
 
182
- def set_openid_namespace(openid_ns_uri)
188
+ def _get_default_namespace(mystery_alias)
189
+ # only try to map an alias to a default if it's an
190
+ # OpenID 1.x namespace
191
+ if is_openid1
192
+ @@registered_aliases[mystery_alias]
193
+ end
194
+ end
195
+
196
+ def set_openid_namespace(openid_ns_uri, implicit)
183
197
  if !@@allowed_openid_namespaces.include?(openid_ns_uri)
184
- raise ArgumentError, "Invalid null namespace: #{openid_ns_uri}"
198
+ raise InvalidOpenIDNamespace, "Invalid null namespace: #{openid_ns_uri}"
185
199
  end
186
- @namespaces.add_alias(openid_ns_uri, NULL_NAMESPACE)
200
+ @namespaces.add_alias(openid_ns_uri, NULL_NAMESPACE, implicit)
187
201
  @openid_ns_uri = openid_ns_uri
188
202
  end
189
203
 
@@ -192,7 +206,7 @@ module OpenID
192
206
  end
193
207
 
194
208
  def is_openid1
195
- return @openid_ns_uri == OPENID1_NS
209
+ return OPENID1_NAMESPACES.member?(@openid_ns_uri)
196
210
  end
197
211
 
198
212
  def is_openid2
@@ -214,16 +228,15 @@ module OpenID
214
228
 
215
229
  # add namespace defs to the output
216
230
  @namespaces.each { |ns_uri, ns_alias|
231
+ if @namespaces.implicit?(ns_uri)
232
+ next
233
+ end
217
234
  if ns_alias == NULL_NAMESPACE
218
- if ns_uri != OPENID1_NS
219
- args['openid.ns'] = ns_uri
220
- end
235
+ ns_key = 'openid.ns'
221
236
  else
222
- if get_openid_namespace != OPENID1_NS
223
- ns_key = 'openid.ns.' + ns_alias
224
- args[ns_key] = ns_uri
225
- end
237
+ ns_key = 'openid.ns.' + ns_alias
226
238
  end
239
+ args[ns_key] = ns_uri
227
240
  }
228
241
 
229
242
  @args.each { |k, value|
@@ -447,6 +460,7 @@ module OpenID
447
460
  def initialize
448
461
  @alias_to_namespace = {}
449
462
  @namespace_to_alias = {}
463
+ @implicit_namespaces = []
450
464
  end
451
465
 
452
466
  def get_alias(namespace_uri)
@@ -458,7 +472,7 @@ module OpenID
458
472
  end
459
473
 
460
474
  # Add an alias from this namespace URI to the alias.
461
- def add_alias(namespace_uri, desired_alias)
475
+ def add_alias(namespace_uri, desired_alias, implicit=false)
462
476
  # Check that desired_alias is not an openid protocol field as
463
477
  # per the spec.
464
478
  Util.assert(!OPENID_PROTOCOL_FIELDS.include?(desired_alias),
@@ -487,6 +501,7 @@ module OpenID
487
501
 
488
502
  @alias_to_namespace[desired_alias] = namespace_uri
489
503
  @namespace_to_alias[namespace_uri] = desired_alias
504
+ @implicit_namespaces << namespace_uri if implicit
490
505
  return desired_alias
491
506
  end
492
507
 
@@ -526,6 +541,10 @@ module OpenID
526
541
  return @namespace_to_alias.keys()
527
542
  end
528
543
 
544
+ def implicit?(namespace_uri)
545
+ return @implicit_namespaces.member?(namespace_uri)
546
+ end
547
+
529
548
  def aliases
530
549
  # Return an iterator over the aliases
531
550
  return @alias_to_namespace.keys()