C0 code coverage information

Generated on Fri Jul 11 15:55:29 -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.
Name Total lines Lines of code Total coverage Code coverage
lib/openid/trustroot.rb 349 220
79.7% 
71.8% 
  1 require 'uri'
  2 require 'openid/urinorm'
  3 
  4 module OpenID
  5 
  6   class RealmVerificationRedirected < Exception
  7     # Attempting to verify this realm resulted in a redirect.
  8     def initialize(relying_party_url, rp_url_after_redirects)
  9       @relying_party_url = relying_party_url
 10       @rp_url_after_redirects = rp_url_after_redirects
 11     end
 12 
 13     def to_s
 14       return "Attempting to verify #{@relying_party_url} resulted in " +
 15         "redirect to #{@rp_url_after_redirects}"
 16     end
 17   end
 18 
 19   module TrustRoot
 20     TOP_LEVEL_DOMAINS = %w'
 21       ac ad ae aero af ag ai al am an ao aq ar arpa as asia at
 22       au aw ax az ba bb bd be bf bg bh bi biz bj bm bn bo br bs bt
 23       bv bw by bz ca cat cc cd cf cg ch ci ck cl cm cn co com coop
 24       cr cu cv cx cy cz de dj dk dm do dz ec edu ee eg er es et eu
 25       fi fj fk fm fo fr ga gb gd ge gf gg gh gi gl gm gn gov gp gq
 26       gr gs gt gu gw gy hk hm hn hr ht hu id ie il im in info int
 27       io iq ir is it je jm jo jobs jp ke kg kh ki km kn kp kr kw
 28       ky kz la lb lc li lk lr ls lt lu lv ly ma mc md me mg mh mil
 29       mk ml mm mn mo mobi mp mq mr ms mt mu museum mv mw mx my mz
 30       na name nc ne net nf ng ni nl no np nr nu nz om org pa pe pf
 31       pg ph pk pl pm pn pr pro ps pt pw py qa re ro rs ru rw sa sb
 32       sc sd se sg sh si sj sk sl sm sn so sr st su sv sy sz tc td
 33       tel tf tg th tj tk tl tm tn to tp tr travel tt tv tw tz ua
 34       ug uk us uy uz va vc ve vg vi vn vu wf ws xn--0zwm56d
 35       xn--11b5bs3a9aj6g xn--80akhbyknj4f xn--9t4b11yi5a
 36       xn--deba0ad xn--g6w251d xn--hgbk6aj7f53bba
 37       xn--hlcj6aya9esc7a xn--jxalpdlp xn--kgbechtv xn--zckzah ye
 38       yt yu za zm zw'
 39 
 40     ALLOWED_PROTOCOLS = ['http', 'https']
 41 
 42     # The URI for relying party discovery, used in realm verification.
 43     #
 44     # XXX: This should probably live somewhere else (like in
 45     # OpenID or OpenID::Yadis somewhere)
 46     RP_RETURN_TO_URL_TYPE = 'http://specs.openid.net/auth/2.0/return_to'
 47 
 48     # If the endpoint is a relying party OpenID return_to endpoint,
 49     # return the endpoint URL. Otherwise, return None.
 50     #
 51     # This function is intended to be used as a filter for the Yadis
 52     # filtering interface.
 53     #
 54     # endpoint: An XRDS BasicServiceEndpoint, as returned by
 55     # performing Yadis dicovery.
 56     #
 57     # returns the endpoint URL or None if the endpoint is not a
 58     # relying party endpoint.
 59     def TrustRoot._extract_return_url(endpoint)
 60       if endpoint.matchTypes([RP_RETURN_TO_URL_TYPE])
 61         return endpoint.uri
 62       else
 63         return nil
 64       end
 65     end
 66 
 67     # Is the return_to URL under one of the supplied allowed
 68     # return_to URLs?
 69     def TrustRoot.return_to_matches(allowed_return_to_urls, return_to)
 70       allowed_return_to_urls.each { |allowed_return_to|
 71         # A return_to pattern works the same as a realm, except that
 72         # it's not allowed to use a wildcard. We'll model this by
 73         # parsing it as a realm, and not trying to match it if it has
 74         # a wildcard.
 75 
 76         return_realm = TrustRoot.parse(allowed_return_to)
 77         if (# Parses as a trust root
 78             !return_realm.nil? and
 79 
 80             # Does not have a wildcard
 81             !return_realm.wildcard and
 82 
 83             # Matches the return_to that we passed in with it
 84             return_realm.validate_url(return_to)
 85             )
 86           return true
 87         end
 88       }
 89 
 90       # No URL in the list matched
 91       return false
 92     end
 93 
 94     # Given a relying party discovery URL return a list of return_to
 95     # URLs.
 96     def TrustRoot.get_allowed_return_urls(relying_party_url)
 97       rp_url_after_redirects, return_to_urls = services.get_service_endpoints(
 98         relying_party_url, _extract_return_url)
 99 
100       if rp_url_after_redirects != relying_party_url
101         # Verification caused a redirect
102         raise RealmVerificationRedirected.new(
103                 relying_party_url, rp_url_after_redirects)
104       end
105 
106       return return_to_urls
107     end
108 
109     # Verify that a return_to URL is valid for the given realm.
110     #
111     # This function builds a discovery URL, performs Yadis discovery
112     # on it, makes sure that the URL does not redirect, parses out
113     # the return_to URLs, and finally checks to see if the current
114     # return_to URL matches the return_to.
115     #
116     # raises DiscoveryFailure when Yadis discovery fails returns
117     # true if the return_to URL is valid for the realm
118     def TrustRoot.verify_return_to(realm_str, return_to, _vrfy=nil)
119       # _vrfy parameter is there to make testing easier
120       if _vrfy.nil?
121         _vrfy = self.method('get_allowed_return_urls')
122       end
123 
124       if !(_vrfy.is_a?(Proc) or _vrfy.is_a?(Method))
125         raise ArgumentError, "_vrfy must be a Proc or Method"
126       end
127 
128       realm = TrustRoot.parse(realm_str)
129       if realm.nil?
130         # The realm does not parse as a URL pattern
131         return false
132       end
133 
134       begin
135         allowable_urls = _vrfy.call(realm.build_discovery_url())
136       rescue RealmVerificationRedirected => err
137         Util.log(err.to_s)
138         return false
139       end
140 
141       if return_to_matches(allowable_urls, return_to)
142         return true
143       else
144         Util.log("Failed to validate return_to #{return_to} for " +
145             "realm #{realm_str}, was not in #{allowable_urls}")
146         return false
147       end
148     end
149 
150     class TrustRoot
151 
152       attr_reader :unparsed, :proto, :wildcard, :host, :port, :path
153 
154       @@empty_re = Regexp.new('^http[s]*:\/\/\*\/$')
155 
156       def TrustRoot._build_path(path, query=nil, frag=nil)
157         s = path.dup
158 
159         frag = nil if frag == ''
160         query = nil if query == ''
161 
162         if query
163           s << "?" << query
164         end
165 
166         if frag
167           s << "#" << frag
168         end
169 
170         return s
171       end
172 
173       def TrustRoot._parse_url(url)
174         begin
175           url = URINorm.urinorm(url)
176         rescue URI::InvalidURIError => err
177           nil
178         end
179 
180         begin
181           parsed = URI::parse(url)
182         rescue URI::InvalidURIError
183           return nil
184         end
185 
186         path = TrustRoot._build_path(parsed.path,
187                                      parsed.query,
188                                      parsed.fragment)
189 
190         return [parsed.scheme || '', parsed.host || '',
191                 parsed.port || '', path || '']
192       end
193 
194       def TrustRoot.parse(trust_root)
195         trust_root = trust_root.dup
196         unparsed = trust_root.dup
197 
198         # look for wildcard
199         wildcard = (not trust_root.index('://*.').nil?)
200         trust_root.sub!('*.', '') if wildcard
201 
202         # handle http://*/ case
203         if not wildcard and @@empty_re.match(trust_root)
204           proto = trust_root.split(':')[0]
205           port = proto == 'http' ? 80 : 443
206           return new(unparsed, proto, true, '', port, '/')
207         end
208 
209         parts = TrustRoot._parse_url(trust_root)
210         return nil if parts.nil?
211 
212         proto, host, port, path = parts
213 
214         # check for URI fragment
215         if path and !path.index('#').nil?
216           return nil
217         end
218 
219         return nil unless ['http', 'https'].member?(proto)
220         return new(unparsed, proto, wildcard, host, port, path)
221       end
222 
223       def TrustRoot.check_sanity(trust_root_string)
224         trust_root = TrustRoot.parse(trust_root_string)
225         if trust_root.nil?
226           return false
227         else
228           return trust_root.sane?
229         end
230       end
231 
232       # quick func for validating a url against a trust root.  See the
233       # TrustRoot class if you need more control.
234       def self.check_url(trust_root, url)
235         tr = self.parse(trust_root)
236         return (!tr.nil? and tr.validate_url(url))
237       end
238 
239       # Return a discovery URL for this realm.
240       #
241       # This function does not check to make sure that the realm is
242       # valid. Its behaviour on invalid inputs is undefined.
243       #
244       # return_to:: The relying party return URL of the OpenID
245       # authentication request
246       #
247       # Returns the URL upon which relying party discovery should be
248       # run in order to verify the return_to URL
249       def build_discovery_url
250         if self.wildcard
251           # Use "www." in place of the star
252           www_domain = 'www.' + @host
253           port = (!@port.nil? and ![80, 443].member?(@port)) ? (":" + @port.to_s) : ''
254           return "#{@proto}://#{www_domain}#{port}#{@path}"
255         else
256           return @unparsed
257         end
258       end
259 
260       def initialize(unparsed, proto, wildcard, host, port, path)
261         @unparsed = unparsed
262         @proto = proto
263         @wildcard = wildcard
264         @host = host
265         @port = port
266         @path = path
267       end
268 
269       def sane?
270         return true if @host == 'localhost'
271 
272         host_parts = @host.split('.')
273 
274         # a note: ruby string split does not put an empty string at
275         # the end of the list if the split element is last.  for
276         # example, 'foo.com.'.split('.') => ['foo','com'].  Mentioned
277         # because the python code differs here.
278 
279         return false if host_parts.length == 0
280 
281         # no adjacent dots
282         return false if host_parts.member?('')
283 
284         # last part must be a tld
285         tld = host_parts[-1]
286         return false unless TOP_LEVEL_DOMAINS.member?(tld)
287 
288         return false if host_parts.length == 1
289 
290         if @wildcard
291           if tld.length == 2 and host_parts[-2].length <= 3
292             # It's a 2-letter tld with a short second to last segment
293             # so there needs to be more than two segments specified
294             # (e.g. *.co.uk is insane)
295             return host_parts.length > 2
296           end
297         end
298 
299         return true
300       end
301 
302       def validate_url(url)
303         parts = TrustRoot._parse_url(url)
304         return false if parts.nil?
305 
306         proto, host, port, path = parts
307 
308         return false unless proto == @proto
309         return false unless port == @port
310         return false unless host.index('*').nil?
311 
312         if !@wildcard
313           if host != @host
314             return false
315           end
316         elsif ((@host != '') and
317                (!host.ends_with?('.' + @host)) and
318                (host != @host))
319           return false
320         end
321 
322         if path != @path
323           path_len = @path.length
324           trust_prefix = @path[0...path_len]
325           url_prefix = path[0...path_len]
326 
327           # must be equal up to the length of the path, at least
328           if trust_prefix != url_prefix
329             return false
330           end
331 
332           # These characters must be on the boundary between the end
333           # of the trust root's path and the start of the URL's path.
334           if !@path.index('?').nil?
335             allowed = '&'
336           else
337             allowed = '?/'
338           end
339 
340           return (!allowed.index(@path[-1]).nil? or
341                   !allowed.index(path[path_len]).nil?)
342         end
343 
344         return true
345       end
346     end
347   end
348 end
349 

Generated using the rcov code coverage analysis tool for Ruby version 0.7.0.

Valid XHTML 1.0! Valid CSS!