use of org.jivesoftware.smackx.xdata.packet.DataForm in project Smack by igniterealtime.
the class RetrieveFormFieldsTest method checkAddAdditionalFieldsStanza.
@Test
public void checkAddAdditionalFieldsStanza() throws Exception {
FormField field1 = FormField.builder("urn:example:xmpp:free-text-search").setValue("Hi").build();
FormField field2 = FormField.jidSingleBuilder("urn:example:xmpp:stanza-content").setValue(JidTestUtil.BARE_JID_1).build();
MamQueryArgs mamQueryArgs = MamQueryArgs.builder().withAdditionalFormField(field1).withAdditionalFormField(field2).build();
DataForm dataForm = mamQueryArgs.getDataForm(MamVersion.MAM2);
String dataFormResult = dataForm.toXML().toString();
assertXmlSimilar(additionalFieldsStanza, dataFormResult);
}
use of org.jivesoftware.smackx.xdata.packet.DataForm in project Smack by igniterealtime.
the class ResultsLimitTest method checkResultsLimit.
@Test
public void checkResultsLimit() throws Exception {
DataForm dataForm = getNewMamForm();
MamQueryIQ mamQueryIQ = new MamQueryIQ(MamVersion.MAM2, queryId, dataForm);
mamQueryIQ.setType(IQ.Type.set);
mamQueryIQ.setStanzaId("sarasa");
MamQueryArgs mamQueryArgs = MamQueryArgs.builder().setResultPageSize(10).build();
mamQueryArgs.maybeAddRsmSet(mamQueryIQ);
assertEquals(resultsLimitStanza, mamQueryIQ.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
}
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 TODO javadoc me please
* @param hash TODO javadoc me please
* the used hash function, if null, default hash will be used
* @return The generated verification String or null if the hash is not
* supported
*/
static CapsVersionAndHash generateVerificationString(DiscoverInfoView 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);
// 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<>();
sortedIdentities.addAll(discoverInfo.getIdentities());
// 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<>();
for (Feature f : discoverInfo.getFeatures()) features.add(f.getVar());
// character
for (String f : features) {
sb.append(f);
sb.append('<');
}
List<DataForm> extendedInfos = discoverInfo.getExtensions(DataForm.class);
for (DataForm extendedInfo : extendedInfos) {
if (!extendedInfo.hasHiddenFormTypeField()) {
// See XEP-0115 5.4 step 3.f
continue;
}
// 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<>(new Comparator<FormField>() {
@Override
public int compare(FormField f1, FormField f2) {
return f1.getFieldName().compareTo(f2.getFieldName());
}
});
for (FormField f : extendedInfo.getFields()) {
if (!f.getFieldName().equals("FORM_TYPE")) {
fs.add(f);
}
}
// Add FORM_TYPE values
formFieldValuesToCaps(Collections.singletonList(extendedInfo.getFormType()), sb);
// followed by the '<' character.
for (FormField f : fs) {
sb.append(f.getFieldName());
sb.append('<');
formFieldValuesToCaps(f.getRawValueCharSequences(), 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 = sb.toString().getBytes(StandardCharsets.UTF_8);
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 EntityCapsManager method updateLocalEntityCaps.
/**
* Updates the local user Entity Caps information with the data provided
*
* If we are connected and there was already a presence send, another
* presence is send to inform others about your new Entity Caps node string.
*/
private void updateLocalEntityCaps(DiscoverInfo synthesizedDiscoveryInfo) {
XMPPConnection connection = connection();
DiscoverInfoBuilder discoverInfoBuilder = synthesizedDiscoveryInfo.asBuilder("synthesized-disco-info-result");
// getLocalNodeVer() will return a result only after currentCapsVersion is set. Therefore
// set it first and then call getLocalNodeVer()
currentCapsVersion = generateVerificationString(discoverInfoBuilder);
final String localNodeVer = getLocalNodeVer();
discoverInfoBuilder.setNode(localNodeVer);
final DiscoverInfo discoverInfo = discoverInfoBuilder.build();
addDiscoverInfoByNode(localNodeVer, discoverInfo);
if (lastLocalCapsVersions.size() > 10) {
CapsVersionAndHash oldCapsVersion = lastLocalCapsVersions.poll();
sdm.removeNodeInformationProvider(entityNode + '#' + oldCapsVersion.version);
}
lastLocalCapsVersions.add(currentCapsVersion);
if (connection != null)
JID_TO_NODEVER_CACHE.put(connection.getUser(), new NodeVerHash(entityNode, currentCapsVersion));
final List<Identity> identities = new LinkedList<>(ServiceDiscoveryManager.getInstanceFor(connection).getIdentities());
sdm.setNodeInformationProvider(localNodeVer, new AbstractNodeInformationProvider() {
List<String> features = sdm.getFeatures();
List<DataForm> packetExtensions = sdm.getExtendedInfo();
@Override
public List<String> getNodeFeatures() {
return features;
}
@Override
public List<Identity> getNodeIdentities() {
return identities;
}
@Override
public List<DataForm> getNodePacketExtensions() {
return packetExtensions;
}
});
}
use of org.jivesoftware.smackx.xdata.packet.DataForm in project Smack by igniterealtime.
the class ServiceDiscoveryManager method addExtendedInfo.
/**
* Registers extended discovery information of this XMPP entity. When this
* client is queried for its information this data form will be returned as
* specified by XEP-0128.
* <p>
*
* Since no stanza is actually sent to the server it is safe to perform this
* operation before logging to the server. In fact, you may want to
* configure the extended info before logging to the server so that the
* information is already available if it is required upon login.
*
* @param extendedInfo the data form that contains the extend service discovery information.
* @return the old data form which got replaced (if any)
* @since 4.4.0
*/
public DataForm addExtendedInfo(DataForm extendedInfo) {
String formType = extendedInfo.getFormType();
StringUtils.requireNotNullNorEmpty(formType, "The data form must have a form type set");
DataForm removedDataForm;
synchronized (this) {
removedDataForm = DataForm.remove(extendedInfos, formType);
extendedInfos.add(extendedInfo);
// Notify others of a state change of SDM. In order to keep the state consistent, this
// method is synchronized
renewEntityCapsVersion();
}
return removedDataForm;
}
Aggregations