use of org.jivesoftware.smackx.xdata.packet.DataForm in project Smack by igniterealtime.
the class EntityCapsManager method generateVerificationString.
/**
* Generates a XEP-115 Verification String
*
* @see <a href="http://xmpp.org/extensions/xep-0115.html#ver">XEP-115
* Verification String</a>
*
* @param discoverInfo
* @param hash
* the used hash function, if null, default hash will be used
* @return The generated verification String or null if the hash is not
* supported
*/
protected static CapsVersionAndHash generateVerificationString(DiscoverInfo discoverInfo, String hash) {
if (hash == null) {
hash = DEFAULT_HASH;
}
// SUPPORTED_HASHES uses the format of MessageDigest, which is uppercase, e.g. "SHA-1" instead of "sha-1"
MessageDigest md = SUPPORTED_HASHES.get(hash.toUpperCase(Locale.US));
if (md == null)
return null;
// Then transform the hash to lowercase, as this value will be put on the wire within the caps element's hash
// attribute. I'm not sure if the standard is case insensitive here, but let's assume that even it is, there could
// be "broken" implementation in the wild, so we *always* transform to lowercase.
hash = hash.toLowerCase(Locale.US);
DataForm extendedInfo = DataForm.from(discoverInfo);
// 1. Initialize an empty string S ('sb' in this method).
// Use StringBuilder as we don't
StringBuilder sb = new StringBuilder();
// need thread-safe StringBuffer
// 2. Sort the service discovery identities by category and then by
// type and then by xml:lang
// (if it exists), formatted as CATEGORY '/' [TYPE] '/' [LANG] '/'
// [NAME]. Note that each slash is included even if the LANG or
// NAME is not included (in accordance with XEP-0030, the category and
// type MUST be included.
SortedSet<DiscoverInfo.Identity> sortedIdentities = new TreeSet<DiscoverInfo.Identity>();
for (DiscoverInfo.Identity i : discoverInfo.getIdentities()) sortedIdentities.add(i);
// followed by the '<' character.
for (DiscoverInfo.Identity identity : sortedIdentities) {
sb.append(identity.getCategory());
sb.append('/');
sb.append(identity.getType());
sb.append('/');
sb.append(identity.getLanguage() == null ? "" : identity.getLanguage());
sb.append('/');
sb.append(identity.getName() == null ? "" : identity.getName());
sb.append('<');
}
// 4. Sort the supported service discovery features.
SortedSet<String> features = new TreeSet<String>();
for (Feature f : discoverInfo.getFeatures()) features.add(f.getVar());
// character
for (String f : features) {
sb.append(f);
sb.append('<');
}
// see XEP-0115 5.4 step 3.6
if (extendedInfo != null && extendedInfo.hasHiddenFormTypeField()) {
synchronized (extendedInfo) {
// 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).
SortedSet<FormField> fs = new TreeSet<FormField>(new Comparator<FormField>() {
@Override
public int compare(FormField f1, FormField f2) {
return f1.getVariable().compareTo(f2.getVariable());
}
});
FormField ft = null;
for (FormField f : extendedInfo.getFields()) {
if (!f.getVariable().equals("FORM_TYPE")) {
fs.add(f);
} else {
ft = f;
}
}
// Add FORM_TYPE values
if (ft != null) {
formFieldValuesToCaps(ft.getValues(), sb);
}
// 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
// 3269).
// 9. Compute the verification string by hashing S using the algorithm
// specified in the 'hash' attribute (e.g., SHA-1 as defined in RFC
// 3174).
// The hashed data MUST be generated with binary output and
// encoded using Base64 as specified in Section 4 of RFC 4648
// (note: the Base64 output MUST NOT include whitespace and MUST set
// padding bits to zero).
byte[] bytes;
try {
bytes = sb.toString().getBytes(StringUtils.UTF8);
} catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
byte[] digest;
synchronized (md) {
digest = md.digest(bytes);
}
String version = Base64.encodeToString(digest);
return new CapsVersionAndHash(version, hash);
}
use of org.jivesoftware.smackx.xdata.packet.DataForm in project Smack by igniterealtime.
the class StreamNegotiator method createInitiationAccept.
/**
* Creates the initiation acceptance stanza(/packet) to forward to the stream
* initiator.
*
* @param streamInitiationOffer The offer from the stream initiator to connect for a stream.
* @param namespaces The namespace that relates to the accepted means of transfer.
* @return The response to be forwarded to the initiator.
*/
protected static StreamInitiation createInitiationAccept(StreamInitiation streamInitiationOffer, String[] namespaces) {
StreamInitiation response = new StreamInitiation();
response.setTo(streamInitiationOffer.getFrom());
response.setFrom(streamInitiationOffer.getTo());
response.setType(IQ.Type.result);
response.setStanzaId(streamInitiationOffer.getStanzaId());
DataForm form = new DataForm(DataForm.Type.submit);
FormField field = new FormField(FileTransferNegotiator.STREAM_DATA_FIELD_NAME);
for (String namespace : namespaces) {
field.addValue(namespace);
}
form.addField(field);
response.setFeatureNegotiationForm(form);
return response;
}
use of org.jivesoftware.smackx.xdata.packet.DataForm in project Smack by igniterealtime.
the class DataFormProvider method parse.
@Override
public DataForm parse(XmlPullParser parser, int initialDepth) throws Exception {
DataForm.Type dataFormType = DataForm.Type.fromString(parser.getAttributeValue("", "type"));
DataForm dataForm = new DataForm(dataFormType);
outerloop: while (true) {
int eventType = parser.next();
switch(eventType) {
case XmlPullParser.START_TAG:
String name = parser.getName();
String namespace = parser.getNamespace();
switch(name) {
case "instructions":
dataForm.addInstruction(parser.nextText());
break;
case "title":
dataForm.setTitle(parser.nextText());
break;
case "field":
dataForm.addField(parseField(parser));
break;
case "item":
dataForm.addItem(parseItem(parser));
break;
case "reported":
dataForm.setReportedData(parseReported(parser));
break;
// See XEP-133 Example 32 for a corner case where the data form contains this extension.
case RosterPacket.ELEMENT:
if (namespace.equals(RosterPacket.NAMESPACE)) {
dataForm.addExtensionElement(RosterPacketProvider.INSTANCE.parse(parser));
}
break;
// See XEP-141 Data Forms Layout
case DataLayout.ELEMENT:
if (namespace.equals(DataLayout.NAMESPACE)) {
dataForm.addExtensionElement(DataLayoutProvider.parse(parser));
}
break;
}
break;
case XmlPullParser.END_TAG:
if (parser.getDepth() == initialDepth) {
break outerloop;
}
break;
}
}
return dataForm;
}
use of org.jivesoftware.smackx.xdata.packet.DataForm in project Smack by igniterealtime.
the class UserSearch method buildDataForm.
private static void buildDataForm(SimpleUserSearch search, String instructions, XmlPullParser parser) throws Exception {
DataForm dataForm = new DataForm(DataForm.Type.form);
boolean done = false;
dataForm.setTitle("User Search");
dataForm.addInstruction(instructions);
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG && !parser.getNamespace().equals("jabber:x:data")) {
String name = parser.getName();
FormField field = new FormField(name);
// Handle hard coded values.
if (name.equals("first")) {
field.setLabel("First Name");
} else if (name.equals("last")) {
field.setLabel("Last Name");
} else if (name.equals("email")) {
field.setLabel("Email Address");
} else if (name.equals("nick")) {
field.setLabel("Nickname");
}
field.setType(FormField.Type.text_single);
dataForm.addField(field);
} else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals("query")) {
done = true;
}
} else if (eventType == XmlPullParser.START_TAG && parser.getNamespace().equals("jabber:x:data")) {
PacketParserUtils.addExtensionElement(search, parser);
done = true;
}
}
if (search.getExtension("x", "jabber:x:data") == null) {
search.addExtension(dataForm);
}
}
use of org.jivesoftware.smackx.xdata.packet.DataForm in project xabber-android by redsolution.
the class CapabilitiesManager method calculateString.
private String calculateString(DiscoverInfo discoverInfo) {
StringBuilder s = new StringBuilder();
SortedSet<String> identities = new TreeSet<>();
for (DiscoverInfo.Identity identity : discoverInfo.getIdentities()) {
StringBuilder builder = new StringBuilder();
builder.append(identity.getCategory());
builder.append("/");
String type = identity.getType();
if (type != null) {
builder.append(type);
}
builder.append("/");
String lang = identity.getLanguage();
if (lang != null) {
builder.append(lang);
}
builder.append("/");
String name = identity.getName();
if (name != null) {
builder.append(name);
}
identities.add(builder.toString());
}
for (String identity : identities) {
s.append(identity);
s.append("<");
}
SortedSet<String> features = new TreeSet<>();
for (DiscoverInfo.Feature feature : discoverInfo.getFeatures()) {
features.add(feature.getVar());
}
for (String feature : features) {
s.append(feature);
s.append("<");
}
// Maps prepared value to FORM_TYPE key.
// Extensions with equal FORM_TYPEs are not allowed.
SortedMap<String, String> extendeds = new TreeMap<>();
for (ExtensionElement packetExtension : discoverInfo.getExtensions()) {
if (packetExtension instanceof DataForm) {
DataForm dataForm = (DataForm) packetExtension;
// Fields with equal var are allowed for fixed type.
SortedSet<FormField> formFields = new TreeSet<>(new Comparator<FormField>() {
@Override
public int compare(FormField f1, FormField f2) {
// Var may not exists for fixed type.
String s1 = f1.getVariable();
String s2 = f2.getVariable();
return (s1 == null ? "" : s1).compareTo(s2 == null ? "" : s2);
}
});
String formType = null;
for (FormField formField : dataForm.getFields()) {
if (FORM_TYPE.equals(formField.getVariable())) {
if (formField.getType() != FormField.Type.hidden) {
continue;
}
for (String value : formField.getValues()) {
formType = value;
}
} else {
formFields.add(formField);
}
}
if (formType == null) {
continue;
}
StringBuilder builder = new StringBuilder();
builder.append(formType);
builder.append("<");
for (FormField formField : formFields) {
builder.append(formField.getVariable());
builder.append("<");
SortedSet<String> values = new TreeSet<>();
for (String value : formField.getValues()) {
values.add(value);
}
for (String value : values) {
builder.append(value);
builder.append("<");
}
}
extendeds.put(formType, builder.toString());
}
}
for (Entry<String, String> extended : extendeds.entrySet()) {
s.append(extended.getValue());
}
return s.toString();
}
Aggregations