# =XMPP4R - XMPP Library for Ruby # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option. # Website::http://home.gna.org/xmpp4r/ require 'xmpp4r/xmlstanza' require 'xmpp4r/jid' require 'digest/sha1' module Jabber ## # IQ: Information/Query # (see RFC3920 - 9.2.3 # # A class used to build/parse IQ requests/responses class Iq < XMLStanza @@element_classes = {} ## # Build a new stanza # type:: [Symbol] or nil, see Iq#type # to:: [JID] Recipient def initialize(type = nil, to = nil) super("iq") if not to.nil? set_to(to) end if not type.nil? set_type(type) end end ## # Get the type of the Iq stanza # # The following values are allowed: # * :get # * :set # * :result # * :error # result:: [Symbol] or nil def type case super when 'get' then :get when 'set' then :set when 'result' then :result when 'error' then :error else nil end end ## # Set the type of the Iq stanza (see Iq#type) # v:: [Symbol] or nil def type=(v) case v when :get then super('get') when :set then super('set') when :result then super('result') when :error then super('error') else super(nil) end end ## # Set the type of the Iq stanza (chaining-friendly) # v:: [Symbol] or nil def set_type(v) self.type = v self end ## # Returns the iq's query child, or nil # result:: [IqQuery] def query first_element('query') end ## # Delete old elements named newquery.name # # newquery:: [REXML::Element] will be added def query=(newquery) delete_elements(newquery.name) add(newquery) end ## # Returns the iq's query's namespace, or nil # result:: [String] def queryns e = first_element('query') if e return e.namespace else return nil end end ## # Returns the iq's child, or nil # result:: [IqVcard] def vcard first_element('vCard') end ## # Create a new iq from a stanza, # copies all attributes and children from xmlstanza # xmlstanza:: [REXML::Element] Source stanza # return:: [Iq] New stanza def Iq.import(xmlstanza) Iq::new.import(xmlstanza) end ## # Add an element to the Iq stanza # element:: [REXML::Element] Element to add. # Will be automatically converted (imported) to # a class registered with add_elementclass def typed_add(element) if element.kind_of?(REXML::Element) && @@element_classes.has_key?(element.name) super(@@element_classes[element.name]::import(element)) else super(element) end end ## # Create a new Iq stanza with an unspecified query child # ( has no namespace) def Iq.new_query(type = nil, to = nil) iq = Iq::new(type, to) query = IqQuery::new iq.add(query) iq end ## # Create a new jabber:iq:auth set Stanza. def Iq.new_authset(jid, password) iq = Iq::new(:set) query = IqQuery::new query.add_namespace('jabber:iq:auth') query.add(REXML::Element::new('username').add_text(jid.node)) query.add(REXML::Element::new('password').add_text(password)) query.add(REXML::Element::new('resource').add_text(jid.resource)) if not jid.resource.nil? iq.add(query) iq end ## # Create a new jabber:iq:auth set Stanza for Digest authentication def Iq.new_authset_digest(jid, session_id, password) iq = Iq::new(:set) query = IqQuery::new query.add_namespace('jabber:iq:auth') query.add(REXML::Element::new('username').add_text(jid.node)) query.add(REXML::Element::new('digest').add_text(Digest::SHA1.hexdigest(session_id + password))) query.add(REXML::Element::new('resource').add_text(jid.resource)) if not jid.resource.nil? iq.add(query) iq end ## # Create a new jabber:iq:register set stanza for service/server registration # username:: [String] (Element will be ommited if unset) # password:: [String] (Element will be ommited if unset) def Iq.new_register(username=nil, password=nil) iq = Iq::new(:set) query = IqQuery::new query.add_namespace('jabber:iq:register') query.add(REXML::Element::new('username').add_text(username)) if username query.add(REXML::Element::new('password').add_text(password)) if password iq.add(query) iq end ## # Create a new jabber:iq:roster get Stanza. # # IqQueryRoster is unused here because possibly not require'd def Iq.new_rosterget iq = Iq::new(:get) query = IqQuery::new query.add_namespace('jabber:iq:roster') iq.add(query) iq end ## # Create a new jabber:iq:roster get Stanza. def Iq.new_browseget iq = Iq::new(:get) query = IqQuery::new query.add_namespace('jabber:iq:browse') iq.add(query) iq end ## # Create a new jabber:iq:roster set Stanza. def Iq.new_rosterset iq = Iq::new(:set) query = IqQuery::new query.add_namespace('jabber:iq:roster') iq.add(query) iq end ## # Add a class by name. # Elements with this name will be automatically converted # to the specific class. # Used for , , etc. # name:: [String] Element name # elementclass:: [Class] Target class def Iq.add_elementclass(name, elementclass) @@element_classes[name] = elementclass end end end # Actually these should be included at the top, # but then they would be unable to call Iq.add_elementclass # because it hasn't just been defined. require 'xmpp4r/query' require 'xmpp4r/vcard/iq/vcard'