Module | Jabber::Caps |
In: |
lib/xmpp4r/caps/c.rb
lib/xmpp4r/caps/helper/helper.rb lib/xmpp4r/caps/helper/generator.rb |
NS_CAPS | = | 'http://jabber.org/protocol/caps' |
Implementation of the algorithm defined at: www.xmpp.org/extensions/xep-0115.html#ver-gen
# 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 a ver hash from a Jabber::Discovery::IqQueryDiscoInfo result
query: | [Jabber::Discovery::IqQueryDiscoInfo] |
# 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
# 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