private string CalculateVer(DiscoNode n) { if (m_hash == null) { return(null); } // 1. Initialize an empty string S. StringBuilder S = new StringBuilder(); // 2. Sort the service discovery identities [16] by category and then by type // (if it exists) and then by xml:lang (if it exists), formatted as // CATEGORY '/' [TYPE] '/' [LANG] '/' [NAME]. Note that each slash is // included even if the TYPE, LANG, or NAME is not included. Ident[] ids = n.GetIdentities(); Array.Sort(ids); // 3. For each identity, append the 'category/type/lang/name' to S, followed by // the '<' character. foreach (Ident id in ids) { S.Append(id.Key); S.Append(SEP); } // 4. Sort the supported service discovery features. string[] features = n.FeatureNames; Array.Sort(features); // 5. For each feature, append the feature to S, followed by the '<' character. foreach (string feature in features) { S.Append(feature); S.Append(SEP); } // 6. If the service discovery information response includes XEP-0128 data forms, // sort the forms by the FORM_TYPE (i.e., by the XML character // data of the <value/> element). Data[] ext = n.Extensions; if (ext != null) { Array.Sort(ext, new FormTypeComparer()); foreach (Data x in ext) { // For each extended service discovery information form: // 1. Append the XML character data of the FORM_TYPE field's <value/> // element, followed by the '<' character. S.Append(x.FormType); S.Append(SEP); // 2. Sort the fields by the value of the "var" attribute. bedrock.collections.Tree fields = new bedrock.collections.Tree(); foreach (Field f in x.GetFields()) { fields[f.Var] = f; } // 3. For each field: foreach (System.Collections.DictionaryEntry entry in fields) { Field f = (Field)entry.Value; if (f.Var == "FORM_TYPE") { continue; } // 1. Append the value of the "var" attribute, followed by the '<' character. S.Append(f.Var); S.Append(SEP); // 2. Sort values by the XML character data of the <value/> element. string[] values = f.Vals; Array.Sort(values); foreach (string v in values) { // 3. For each <value/> element, append the XML character data, followed by the '<' character. S.Append(v); S.Append(SEP); } } } } // Ensure that S is encoded according to the UTF-8 encoding (RFC 3269 [16]). byte[] input = Encoding.UTF8.GetBytes(S.ToString()); // Compute the verification string by hashing S using the algorithm specified // in the 'hash' attribute (e.g., SHA-1 as defined in RFC 3174 [17]). The hashed // data MUST be generated with binary output and encoded using Base64 as specified // in Section 4 of RFC 4648 [18] (note: the Base64 output MUST NOT include // whitespace and MUST set padding bits to zero). [19] HashAlgorithm hasher = GetHasher(m_hash); byte[] hash = hasher.ComputeHash(input, 0, input.Length); return(Convert.ToBase64String(hash)); }
private string CalculateVer(DiscoNode n) { if (m_hash == null) return null; // 1. Initialize an empty string S. StringBuilder S = new StringBuilder(); // 2. Sort the service discovery identities [16] by category and then by type // (if it exists) and then by xml:lang (if it exists), formatted as // CATEGORY '/' [TYPE] '/' [LANG] '/' [NAME]. Note that each slash is // included even if the TYPE, LANG, or NAME is not included. Ident[] ids = n.GetIdentities(); Array.Sort(ids); // 3. For each identity, append the 'category/type/lang/name' to S, followed by // the '<' character. foreach (Ident id in ids) { S.Append(id.Key); S.Append(SEP); } // 4. Sort the supported service discovery features. string[] features = n.FeatureNames; Array.Sort(features); // 5. For each feature, append the feature to S, followed by the '<' character. foreach (string feature in features) { S.Append(feature); S.Append(SEP); } // 6. If the service discovery information response includes XEP-0128 data forms, // sort the forms by the FORM_TYPE (i.e., by the XML character // data of the <value/> element). Data[] ext = n.Extensions; if (ext != null) { Array.Sort(ext, new FormTypeComparer()); foreach (Data x in ext) { // For each extended service discovery information form: // 1. Append the XML character data of the FORM_TYPE field's <value/> // element, followed by the '<' character. S.Append(x.FormType); S.Append(SEP); // 2. Sort the fields by the value of the "var" attribute. bedrock.collections.Tree fields = new bedrock.collections.Tree(); foreach (Field f in x.GetFields()) fields[f.Var] = f; // 3. For each field: foreach (System.Collections.DictionaryEntry entry in fields) { Field f = (Field)entry.Value; if (f.Var == "FORM_TYPE") continue; // 1. Append the value of the "var" attribute, followed by the '<' character. S.Append(f.Var); S.Append(SEP); // 2. Sort values by the XML character data of the <value/> element. string[] values = f.Vals; Array.Sort(values); foreach (string v in values) { // 3. For each <value/> element, append the XML character data, followed by the '<' character. S.Append(v); S.Append(SEP); } } } } // Ensure that S is encoded according to the UTF-8 encoding (RFC 3269 [16]). byte[] input = Encoding.UTF8.GetBytes(S.ToString()); // Compute the verification string by hashing S using the algorithm specified // in the 'hash' attribute (e.g., SHA-1 as defined in RFC 3174 [17]). The hashed // data MUST be generated with binary output and encoded using Base64 as specified // in Section 4 of RFC 4648 [18] (note: the Base64 output MUST NOT include // whitespace and MUST set padding bits to zero). [19] HashAlgorithm hasher = GetHasher(m_hash); byte[] hash = hasher.ComputeHash(input, 0, input.Length); return Convert.ToBase64String(hash); }