from_message (OpenID::Server::CheckIDRequest)

    # File lib/openid/server.rb, line 490
          def self.from_message(message, op_endpoint)
            obj = self.allocate
            obj.message = message
            obj.op_endpoint = op_endpoint
            mode = message.get_arg(OPENID_NS, 'mode')
            if mode == "checkid_immediate"
              obj.immediate = true
              obj.mode = "checkid_immediate"
            else
              obj.immediate = false
              obj.mode = "checkid_setup"
            end

            obj.return_to = message.get_arg(OPENID_NS, 'return_to')
            if message.is_openid1 and !obj.return_to
              msg = sprintf("Missing required field 'return_to' from %s",
                            message)
              raise ProtocolError.new(message, msg)
            end

            obj.identity = message.get_arg(OPENID_NS, 'identity')
            obj.claimed_id = message.get_arg(OPENID_NS, 'claimed_id')
            if message.is_openid1()
              if !obj.identity
                s = "OpenID 1 message did not contain openid.identity"
                raise ProtocolError.new(message, s)
              end
            else
              if obj.identity and not obj.claimed_id
                s = ("OpenID 2.0 message contained openid.identity but not " +
                     "claimed_id")
                raise ProtocolError.new(message, s)
              elsif obj.claimed_id and not obj.identity
                s = ("OpenID 2.0 message contained openid.claimed_id but not " +
                     "identity")
                raise ProtocolError.new(message, s)
              end
            end

            # There's a case for making self.trust_root be a TrustRoot
            # here.  But if TrustRoot isn't currently part of the "public"
            # API, I'm not sure it's worth doing.
            if message.is_openid1
              trust_root_param = 'trust_root'
            else
              trust_root_param = 'realm'
            end
            trust_root = message.get_arg(OPENID_NS, trust_root_param)
            trust_root = obj.return_to if (trust_root.nil? || trust_root.empty?)
            obj.trust_root = trust_root

            if !message.is_openid1 and !obj.return_to and !obj.trust_root
              raise ProtocolError.new(message, "openid.realm required when " +
                                      "openid.return_to absent")
            end

            obj.assoc_handle = message.get_arg(OPENID_NS, 'assoc_handle')

            # Using TrustRoot.parse here is a bit misleading, as we're not
            # parsing return_to as a trust root at all.  However, valid
            # URLs are valid trust roots, so we can use this to get an
            # idea if it is a valid URL.  Not all trust roots are valid
            # return_to URLs, however (particularly ones with wildcards),
            # so this is still a little sketchy.
            if obj.return_to and \
              !TrustRoot::TrustRoot.parse(obj.return_to)
              raise MalformedReturnURL.new(message, obj.return_to)
            end

            # I first thought that checking to see if the return_to is
            # within the trust_root is premature here, a
            # logic-not-decoding thing.  But it was argued that this is
            # really part of data validation.  A request with an invalid
            # trust_root/return_to is broken regardless of application,
            # right?
            if !obj.trust_root_valid()
              raise UntrustedReturnURL.new(message, obj.return_to, obj.trust_root)
            end

            return obj
          end