Module: Jabber::Caps

Module | Jabber::Caps
In: | lib/xmpp4r/caps/c.rb lib/xmpp4r/caps/helper/generator.rb lib/xmpp4r/caps/helper/helper.rb

### Methods

generate_ver generate_ver_from_discoinfo generate_ver_str

### Classes and Modules

Class Jabber::Caps::C
Class Jabber::Caps::Helper

### Constants

NS_CAPS | = | 'http://jabber.org/protocol/caps'

### Public Class methods

generate_ver(identities, features, forms=[], hash='sha-1')

Implementation of the algorithm defined at: www.xmpp.org/extensions/xep-0115.html#ver-gen

[Source]

         # File lib/xmpp4r/caps/helper/generator.rb, line 114
    114:     def self.generate_ver(identities, features, forms=[], hash='sha-1')
    115:       s = generate_ver_str(identities, features, forms)
    116:
    117:       # 9. Compute the verification string by hashing S using the
    118:       # algorithm specified in the 'hash' attribute (e.g., SHA-1 as
    119:       # defined in RFC 3174 [17]). The hashed data MUST be generated
    120:       # with binary output and encoded using Base64 as specified in
    121:       # Section 4 of RFC 4648 [18] (note: the Base64 output MUST NOT
    122:       # include whitespace and MUST set padding bits to zero). [19]
    123:
    124:       # See http://www.iana.org/assignments/hash-function-text-names
    125:       hash_klass = case hash
    126:                      when 'md2' then nil
    127:                      when 'md5' then Digest::MD5
    128:                      when 'sha-1' then Digest::SHA1
    129:                      when 'sha-224' then nil
    130:                      when 'sha-256' then Digest::SHA256
    131:                      when 'sha-384' then Digest::SHA384
    132:                      when 'sha-512' then Digest::SHA512
    133:                    end
    134:       if hash_klass
    135:         Base64::encode64(hash_klass::digest(s)).strip
    136:       else
    137:         nil
    138:       end
    139:     end

generate_ver_from_discoinfo(query, hash='sha-1')

Generate a ver hash from a Jabber::Discovery::IqQueryDiscoInfo result

query: | [Jabber::Discovery::IqQueryDiscoInfo]

[Source]

         # File lib/xmpp4r/caps/helper/generator.rb, line 144
    144:     def self.generate_ver_from_discoinfo(query, hash='sha-1')
    145:       identities = []
    146:       features = []
    147:       forms = []
    148:       query.each_element do |element|
    149:         if element.kind_of? Discovery::Identity
    150:           identities << element
    151:         elsif element.kind_of? Discovery::Feature
    152:           features << element
    153:         elsif element.kind_of? Dataforms::XData
    154:           forms << element
    155:         end
    156:       end
    157:       generate_ver(identities, features, forms, hash)
    158:     end

generate_ver_str(identities, features, forms=[])

[Source]

         # File lib/xmpp4r/caps/helper/generator.rb, line 14
     14:     def self.generate_ver_str(identities, features, forms=[])
     15:       # 1.  Initialize an empty string S.
     16:       s = ''
     17:
     18:       # 2. Sort the service discovery identities [14] by category and
     19:       # then by type (if it exists) and then by xml:lang (if it
     20:       # exists), formatted as CATEGORY '/' [TYPE] '/' [LANG] '/'
     21:       # [NAME]. Note that each slash is included even if the TYPE,
     22:       # LANG, or NAME is not included.
     23:       identities.sort! do |identity1,identity2|
     24:         cmp_result = nil
     25:         [:category, :type, :xml_lang, :iname].each do |field|
     26:           value1 = identity1.send(field)
     27:           value2 = identity2.send(field)
     28:
     29:           if value1 != value2
     30:             cmp_result = value1 <=> value2
     31:             break
     32:           end
     33:         end
     34:
     35:
     36:         cmp_result
     37:       end
     38:
     39:       # 3. For each identity, append the 'category/type/lang/name' to
     40:       # S, followed by the '<' character.
     41:       s += identities.collect do |identity|
     42:         [:category, :type, :xml_lang, :iname].collect do |field|
     43:           identity.send(field).to_s
     44:         end.join('/') + '<'
     45:       end.join
     46:
     47:       # 4. Sort the supported service discovery features. [15]
     48:       features.sort! do |feature1,feature2|
     49:         feature1.var <=> feature2.var
     50:       end
     51:
     52:       # 5. For each feature, append the feature to S, followed by the
     53:       # '<' character.
     54:       s += features.collect do |feature|
     55:         feature.var.to_s + '<'
     56:       end.join
     57:
     58:       # 6. If the service discovery information response includes
     59:       # XEP-0128 data forms, sort the forms by the FORM_TYPE (i.e., by
     60:       # the XML character data of the <value/> element).
     61:       forms.sort! do |form1,form2|
     62:         fform_type1 = form1.field('FORM_TYPE')
     63:         fform_type2 = form2.field('FORM_TYPE')
     64:         form_type1 = fform_type1 ? fform_type1.values.to_s : nil
     65:         form_type2 = fform_type2 ? fform_type2.values.to_s : nil
     66:         form_type1 <=> form_type2
     67:       end
     68:
     69:       # 7. For each extended service discovery information form:
     70:       forms.each do |form|
     71:         # 7.1. Append the XML character data of the FORM_TYPE field's
     72:         # <value/> element, followed by the '<' character.
     73:         fform_type = form.field('FORM_TYPE')
     74:         form_type = fform_type ? fform_type.values.to_s : nil
     75:         s += "#{form_type}<"
     76:
     77:         # 7.2. Sort the fields by the value of the "var" attribute.
     78:         fields = form.fields(false).sort do |field1,field2|
     79:           field1.var <=> field2.var
     80:         end
     81:
     82:         # 7.3. For each field:
     83:
     84:         fields.each do |field|
     85:           # 7.3.1. Append the value of the "var" attribute, followed by
     86:           # the '<' character.
     87:           s += "#{field.var}<"
     88:
     89:           # 7.3.2. Sort values by the XML character data of the <value/>
     90:           # element.
     91:           values = field.values.sort do |value1,value2|
     92:             value1 <=> value2
     93:           end
     94:
     95:           # 7.3.3. For each <value/> element, append the XML character
     96:           # data, followed by the '<' character.
     97:           s += values.collect do |value|
     98:             "#{value}<"
     99:           end.join
    100:         end
    101:       end
    102:
    103:       # 8. Ensure that S is encoded according to the UTF-8 encoding
    104:       # (RFC 3269 [16]).
    105:
    106:       # (given in XMPP4R)
    107:
    108:       s
    109:     end

[Validate]