C0 code coverage information
Generated on Fri Jul 11 15:55:31 -0700 2008 with rcov 0.7.0
Code reported as executed by Ruby looks like this...
and this: this line is also marked as covered.
Lines considered as run by rcov, but not reported by Ruby, look like this,
and this: these lines were inferred by rcov (using simple heuristics).
Finally, here's a line marked as not executed.
1 require 'openid/extension'
2 require 'openid/util'
3 require 'openid/message'
4
5 module OpenID
6 module SReg
7 DATA_FIELDS = {
8 'fullname'=>'Full Name',
9 'nickname'=>'Nickname',
10 'dob'=>'Date of Birth',
11 'email'=>'E-mail Address',
12 'gender'=>'Gender',
13 'postcode'=>'Postal Code',
14 'country'=>'Country',
15 'language'=>'Language',
16 'timezone'=>'Time Zone',
17 }
18
19 NS_URI_1_0 = 'http://openid.net/sreg/1.0'
20 NS_URI_1_1 = 'http://openid.net/extensions/sreg/1.1'
21 NS_URI = NS_URI_1_1
22
23 begin
24 Message.register_namespace_alias(NS_URI_1_1, 'sreg')
25 rescue NamespaceAliasRegistrationError => e
26 Util.log(e)
27 end
28
29 # raise ArgumentError if fieldname is not in the defined sreg fields
30 def OpenID.check_sreg_field_name(fieldname)
31 unless DATA_FIELDS.member? fieldname
32 raise ArgumentError, "#{fieldname} is not a defined simple registration field"
33 end
34 end
35
36 # Does the given endpoint advertise support for simple registration?
37 def OpenID.supports_sreg?(endpoint)
38 endpoint.uses_extension(NS_URI_1_1) || endpoint.uses_extension(NS_URI_1_0)
39 end
40
41 # Extract the simple registration namespace URI from the given
42 # OpenID message. Handles OpenID 1 and 2, as well as both sreg
43 # namespace URIs found in the wild, as well as missing namespace
44 # definitions (for OpenID 1)
45 def OpenID.get_sreg_ns(message)
46 [NS_URI_1_1, NS_URI_1_0].each{|ns|
47 if message.namespaces.get_alias(ns)
48 return ns
49 end
50 }
51 # try to add an alias, since we didn't find one
52 ns = NS_URI_1_1
53 begin
54 message.namespaces.add_alias(ns, 'sreg')
55 rescue IndexError
56 raise NamespaceError
57 end
58 return ns
59 end
60
61 # The simple registration namespace was not found and could not
62 # be created using the expected name (there's another extension
63 # using the name 'sreg')
64 #
65 # This is not <em>illegal</em>, for OpenID 2, although it probably
66 # indicates a problem, since it's not expected that other extensions
67 # will re-use the alias that is in use for OpenID 1.
68 #
69 # If this is an OpenID 1 request, then there is no recourse. This
70 # should not happen unless some code has modified the namespaces for
71 # the message that is being processed.
72 class NamespaceError < ArgumentError
73 end
74
75 # An object to hold the state of a simple registration request.
76 class Request < Extension
77 attr_reader :optional, :required, :ns_uri
78 attr_accessor :policy_url
79 def initialize(required = nil, optional = nil, policy_url = nil, ns_uri = NS_URI)
80 super()
81
82 @policy_url = policy_url
83 @ns_uri = ns_uri
84 @ns_alias = 'sreg'
85 @required = []
86 @optional = []
87
88 if required
89 request_fields(required, true, true)
90 end
91 if optional
92 request_fields(optional, false, true)
93 end
94 end
95
96 # Create a simple registration request that contains the
97 # fields that were requested in the OpenID request with the
98 # given arguments
99 # Takes an OpenID::CheckIDRequest, returns an OpenID::Sreg::Request
100 # return nil if the extension was not requested.
101 def self.from_openid_request(request)
102 # Since we're going to mess with namespace URI mapping, don't
103 # mutate the object that was passed in.
104 message = request.message.copy
105 ns_uri = OpenID::get_sreg_ns(message)
106 args = message.get_args(ns_uri)
107 return nil if args == {}
108 req = new(nil,nil,nil,ns_uri)
109 req.parse_extension_args(args)
110 return req
111 end
112
113 # Parse the unqualified simple registration request
114 # parameters and add them to this object.
115 #
116 # This method is essentially the inverse of
117 # getExtensionArgs. This method restores the serialized simple
118 # registration request fields.
119 #
120 # If you are extracting arguments from a standard OpenID
121 # checkid_* request, you probably want to use fromOpenIDRequest,
122 # which will extract the sreg namespace and arguments from the
123 # OpenID request. This method is intended for cases where the
124 # OpenID server needs more control over how the arguments are
125 # parsed than that method provides.
126 def parse_extension_args(args, strict = false)
127 required_items = args['required']
128 unless required_items.nil? or required_items.empty?
129 required_items.split(',').each{|field_name|
130 begin
131 request_field(field_name, true, strict)
132 rescue ArgumentError
133 raise if strict
134 end
135 }
136 end
137
138 optional_items = args['optional']
139 unless optional_items.nil? or optional_items.empty?
140 optional_items.split(',').each{|field_name|
141 begin
142 request_field(field_name, false, strict)
143 rescue ArgumentError
144 raise if strict
145 end
146 }
147 end
148 @policy_url = args['policy_url']
149 end
150
151 # A list of all of the simple registration fields that were
152 # requested, whether they were required or optional.
153 def all_requested_fields
154 @required + @optional
155 end
156
157 # Have any simple registration fields been requested?
158 def were_fields_requested?
159 !all_requested_fields.empty?
160 end
161
162 # Request the specified field from the OpenID user
163 # field_name: the unqualified simple registration field name
164 # required: whether the given field should be presented
165 # to the user as being a required to successfully complete
166 # the request
167 # strict: whether to raise an exception when a field is
168 # added to a request more than once
169 # Raises ArgumentError if the field_name is not a simple registration
170 # field, or if strict is set and a field is added more than once
171 def request_field(field_name, required=false, strict=false)
172 OpenID::check_sreg_field_name(field_name)
173
174 if strict
175 if (@required + @optional).member? field_name
176 raise ArgumentError, 'That field has already been requested'
177 end
178 else
179 return if @required.member? field_name
180 if @optional.member? field_name
181 if required
182 @optional.delete field_name
183 else
184 return
185 end
186 end
187 end
188 if required
189 @required << field_name
190 else
191 @optional << field_name
192 end
193 end
194
195 # Add the given list of fields to the request.
196 def request_fields(field_names, required = false, strict = false)
197 raise ArgumentError unless field_names.respond_to?(:each) and
198 field_names[0].is_a?(String)
199 field_names.each{|fn|request_field(fn, required, strict)}
200 end
201
202 # Get a hash of unqualified simple registration arguments
203 # representing this request.
204 # This method is essentially the inverse of parse_extension_args.
205 # This method serializes the simple registration request fields.
206 def get_extension_args
207 args = {}
208 args['required'] = @required.join(',') unless @required.empty?
209 args['optional'] = @optional.join(',') unless @optional.empty?
210 args['policy_url'] = @policy_url unless @policy_url.nil?
211 return args
212 end
213
214 def member?(field_name)
215 all_requested_fields.member?(field_name)
216 end
217
218 end
219
220 # Represents the data returned in a simple registration response
221 # inside of an OpenID id_res response. This object will be
222 # created by the OpenID server, added to the id_res response
223 # object, and then extracted from the id_res message by the Consumer.
224 class Response < Extension
225 attr_reader :ns_uri, :data
226
227 def initialize(data = {}, ns_uri=NS_URI)
228 @ns_alias = 'sreg'
229 @data = data
230 @ns_uri = ns_uri
231 end
232
233 # Take a Request and a hash of simple registration
234 # values and create a Response object containing that data.
235 def self.extract_response(request, data)
236 arf = request.all_requested_fields
237 resp_data = data.reject{|k,v| !arf.member?(k) || v.nil? }
238 new(resp_data, request.ns_uri)
239 end
240
241 # Create an Response object from an
242 # OpenID::Consumer::SuccessResponse from consumer.complete
243 # If you set the signed_only parameter to false, unsigned data from
244 # the id_res message from the server will be processed.
245 def self.from_success_response(success_response, signed_only = true)
246 ns_uri = OpenID::get_sreg_ns(success_response.message)
247 if signed_only
248 args = success_response.get_signed_ns(ns_uri)
249 return nil if args.nil? # No signed args, so fail
250 else
251 args = success_response.message.get_args(ns_uri)
252 end
253 args.reject!{|k,v| !DATA_FIELDS.member?(k) }
254 new(args, ns_uri)
255 end
256
257 # Get the fields to put in the simple registration namespace
258 # when adding them to an id_res message.
259 def get_extension_args
260 return @data
261 end
262
263 # Read-only hashlike interface.
264 # Raises an exception if the field name is bad
265 def [](field_name)
266 OpenID::check_sreg_field_name(field_name)
267 data[field_name]
268 end
269
270 def empty?
271 @data.empty?
272 end
273 # XXX is there more to a hashlike interface I should add?
274 end
275 end
276 end
277
Generated using the rcov code coverage analysis tool for Ruby version 0.7.0.