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
        
        
        
        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')
        
        
        
        
        
        
        if obj.return_to and \
          !TrustRoot::TrustRoot.parse(obj.return_to)
          raise MalformedReturnURL.new(message, obj.return_to)
        end
        
        
        
        
        
        
        if !obj.trust_root_valid()
          raise UntrustedReturnURL.new(message, obj.return_to, obj.trust_root)
        end
        return obj
      end