caps: handle multiple data forms of extened service discovery information

This commit is contained in:
Florian Schmaus 2020-04-18 22:56:24 +02:00
parent 5e921e6393
commit e79710840b
1 changed files with 36 additions and 40 deletions

View File

@ -19,6 +19,7 @@ package org.jivesoftware.smackx.caps;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
@ -664,8 +665,6 @@ public final class EntityCapsManager extends Manager {
// be "broken" implementation in the wild, so we *always* transform to lowercase. // be "broken" implementation in the wild, so we *always* transform to lowercase.
hash = hash.toLowerCase(Locale.US); hash = hash.toLowerCase(Locale.US);
DataForm extendedInfo = DataForm.from(discoverInfo);
// 1. Initialize an empty string S ('sb' in this method). // 1. Initialize an empty string S ('sb' in this method).
StringBuilder sb = new StringBuilder(); // Use StringBuilder as we don't StringBuilder sb = new StringBuilder(); // Use StringBuilder as we don't
// need thread-safe StringBuffer // need thread-safe StringBuffer
@ -705,50 +704,47 @@ public final class EntityCapsManager extends Manager {
sb.append('<'); sb.append('<');
} }
// only use the data form for calculation is it has a hidden FORM_TYPE List<DataForm> extendedInfos = discoverInfo.getExtensions(DataForm.class);
// field for (DataForm extendedInfo : extendedInfos) {
// see XEP-0115 5.4 step 3.6 if (!extendedInfo.hasHiddenFormTypeField()) {
if (extendedInfo != null && extendedInfo.hasHiddenFormTypeField()) { // Only use the data form for calculation is it has a hidden FORM_TYPE field.
synchronized (extendedInfo) { // See XEP-0115 5.4 step 3.f
// 6. If the service discovery information response includes continue;
// XEP-0128 data forms, sort the forms by the FORM_TYPE (i.e., }
// by the XML character data of the <value/> element).
SortedSet<FormField> fs = new TreeSet<>(new Comparator<FormField>() {
@Override
public int compare(FormField f1, FormField f2) {
return f1.getVariable().compareTo(f2.getVariable());
}
});
FormField ft = null; // 6. If the service discovery information response includes
// XEP-0128 data forms, sort the forms by the FORM_TYPE (i.e.,
for (FormField f : extendedInfo.getFields()) { // by the XML character data of the <value/> element).
if (!f.getVariable().equals("FORM_TYPE")) { SortedSet<FormField> fs = new TreeSet<>(new Comparator<FormField>() {
fs.add(f); @Override
} else { public int compare(FormField f1, FormField f2) {
ft = f; return f1.getVariable().compareTo(f2.getVariable());
}
} }
});
// Add FORM_TYPE values for (FormField f : extendedInfo.getFields()) {
if (ft != null) { if (!f.getVariable().equals("FORM_TYPE")) {
formFieldValuesToCaps(ft.getValues(), sb); fs.add(f);
}
// 7. 3. For each field other than FORM_TYPE:
// 1. Append the value of the "var" attribute, followed by the
// '<' character.
// 2. Sort values by the XML character data of the <value/>
// element.
// 3. For each <value/> element, append the XML character data,
// followed by the '<' character.
for (FormField f : fs) {
sb.append(f.getVariable());
sb.append('<');
formFieldValuesToCaps(f.getValues(), sb);
} }
} }
// Add FORM_TYPE values
formFieldValuesToCaps(Collections.singletonList(extendedInfo.getFormType()), sb);
// 7. 3. For each field other than FORM_TYPE:
// 1. Append the value of the "var" attribute, followed by the
// '<' character.
// 2. Sort values by the XML character data of the <value/>
// element.
// 3. For each <value/> element, append the XML character data,
// followed by the '<' character.
for (FormField f : fs) {
sb.append(f.getVariable());
sb.append('<');
formFieldValuesToCaps(f.getValues(), sb);
}
} }
// 8. Ensure that S is encoded according to the UTF-8 encoding (RFC // 8. Ensure that S is encoded according to the UTF-8 encoding (RFC
// 3269). // 3269).
// 9. Compute the verification string by hashing S using the algorithm // 9. Compute the verification string by hashing S using the algorithm