mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-12-22 20:47:57 +01:00
Add XEP-0231: Bits of Binary implementation
Fixes SMACK-737
This commit is contained in:
parent
70e860fe27
commit
c688acaa0f
16 changed files with 997 additions and 0 deletions
|
@ -68,6 +68,7 @@ Smack Extensions and currently supported XEPs of smack-extensions
|
|||
| Delayed Delivery | [XEP-0203](http://xmpp.org/extensions/xep-0203.html) | Extension for communicating the fact that an XML stanza has been delivered with a delay. |
|
||||
| XMPP Over BOSH | [XEP-0206](http://xmpp.org/extensions/xep-0206.html) | Use Bidirectional-streams Over Synchronous HTTP (BOSH) to transport XMPP stanzas. |
|
||||
| Attention | [XEP-0224](http://xmpp.org/extensions/xep-0224.html) | Getting attention of another user. |
|
||||
| Bits of Binary | [XEP-0231](http://xmpp.org/extensions/xep-0231.html) | Including or referring to small bits of binary data in an XML stanza. |
|
||||
| Last Message Correction | [XEP-0308](http://xmpp.org/extensions/xep-0308.html) | Provides a method for indicating that a message is a correction of the last sent message. |
|
||||
| [Group Chat Invitations](invitation.md) | n/a | Send invitations to other users to join a group chat room. |
|
||||
| [Jive Properties](properties.md) | n/a | TODO |
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016 Fernando Ramirez
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.bob;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||
|
||||
/**
|
||||
* Bits of Binary data class.
|
||||
*
|
||||
* @author Fernando Ramirez
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0231.html">XEP-0231: Bits of
|
||||
* Binary</a>
|
||||
*/
|
||||
public class BoBData {
|
||||
|
||||
private final long maxAge;
|
||||
private final String type;
|
||||
private final byte[] content;
|
||||
|
||||
/**
|
||||
* BoB data constructor.
|
||||
*
|
||||
* @param maxAge
|
||||
* @param type
|
||||
* @param content
|
||||
*/
|
||||
public BoBData(long maxAge, String type, byte[] content) {
|
||||
this.maxAge = maxAge;
|
||||
this.type = type;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the max age.
|
||||
*
|
||||
* @return the max age
|
||||
*/
|
||||
public long getMaxAge() {
|
||||
return maxAge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type.
|
||||
*
|
||||
* @return the type
|
||||
*/
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the content.
|
||||
*
|
||||
* @return the content
|
||||
*/
|
||||
public byte[] getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the content in a Base64 encoded String.
|
||||
*
|
||||
* @return the content in a Base64 encoded String
|
||||
*/
|
||||
public String getBase64Encoded() {
|
||||
byte[] bytes = Base64.encode(content);
|
||||
try {
|
||||
return new String(bytes, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new IllegalStateException("UTF-8 is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016 Fernando Ramirez
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.bob;
|
||||
|
||||
/**
|
||||
* Bits of Binary hash class.
|
||||
*
|
||||
* @author Fernando Ramirez
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0231.html">XEP-0231: Bits of
|
||||
* Binary</a>
|
||||
*/
|
||||
public class BoBHash {
|
||||
|
||||
private final String hash;
|
||||
private final String hashType;
|
||||
|
||||
/**
|
||||
* BoB hash constructor.
|
||||
*
|
||||
* @param hash
|
||||
* @param hashType
|
||||
*/
|
||||
public BoBHash(String hash, String hashType) {
|
||||
this.hash = hash;
|
||||
this.hashType = hashType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hash.
|
||||
*
|
||||
* @return the hash
|
||||
*/
|
||||
public String getHash() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hash type.
|
||||
*
|
||||
* @return the hash type
|
||||
*/
|
||||
public String getHashType() {
|
||||
return hashType;
|
||||
}
|
||||
|
||||
/**
|
||||
* BoB hash to src attribute string.
|
||||
*
|
||||
* @return src attribute string
|
||||
*/
|
||||
public String toSrc() {
|
||||
return "cid:" + toCid();
|
||||
}
|
||||
|
||||
/**
|
||||
* BoB hash to cid attribute string.
|
||||
*
|
||||
* @return cid attribute string
|
||||
*/
|
||||
public String toCid() {
|
||||
return this.hashType + "+" + this.hash + "@bob.xmpp.org";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get BoB hash from src attribute string.
|
||||
*
|
||||
* @param src
|
||||
* @return the BoB hash
|
||||
*/
|
||||
public static BoBHash fromSrc(String src) {
|
||||
String hashType = src.substring(src.lastIndexOf("cid:") + 4, src.indexOf("+"));
|
||||
String hash = src.substring(src.indexOf("+") + 1, src.indexOf("@bob.xmpp.org"));
|
||||
return new BoBHash(hash, hashType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get BoB hash from cid attribute string.
|
||||
*
|
||||
* @param cid
|
||||
* @return the BoB hash
|
||||
*/
|
||||
public static BoBHash fromCid(String cid) {
|
||||
String hashType = cid.substring(0, cid.indexOf("+"));
|
||||
String hash = cid.substring(cid.indexOf("+") + 1, cid.indexOf("@bob.xmpp.org"));
|
||||
return new BoBHash(hash, hashType);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016 Fernando Ramirez
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.bob;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import org.jivesoftware.smack.ConnectionCreationListener;
|
||||
import org.jivesoftware.smack.Manager;
|
||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
import org.jivesoftware.smack.SmackException.NotLoggedInException;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPConnectionRegistry;
|
||||
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
||||
import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler;
|
||||
import org.jivesoftware.smack.iqrequest.IQRequestHandler.Mode;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.packet.IQ.Type;
|
||||
import org.jivesoftware.smackx.bob.element.BoBIQ;
|
||||
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
||||
import org.jxmpp.jid.Jid;
|
||||
|
||||
/**
|
||||
* Bits of Binary manager class.
|
||||
*
|
||||
* @author Fernando Ramirez
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0231.html">XEP-0231: Bits of
|
||||
* Binary</a>
|
||||
*/
|
||||
public final class BoBManager extends Manager {
|
||||
|
||||
public static final String NAMESPACE = "urn:xmpp:bob";
|
||||
public static BoBSaverManager bobSaverManager;
|
||||
|
||||
static {
|
||||
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
|
||||
@Override
|
||||
public void connectionCreated(XMPPConnection connection) {
|
||||
getInstanceFor(connection, bobSaverManager);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static final Map<XMPPConnection, BoBManager> INSTANCES = new WeakHashMap<>();
|
||||
|
||||
/**
|
||||
* Get the singleton instance of BoBManager.
|
||||
*
|
||||
* @param connection
|
||||
* @param saverManager
|
||||
* @return the instance of BoBManager
|
||||
*/
|
||||
public static synchronized BoBManager getInstanceFor(XMPPConnection connection, BoBSaverManager saverManager) {
|
||||
if (saverManager == null) {
|
||||
bobSaverManager = new DefaultBoBSaverManager();
|
||||
} else {
|
||||
bobSaverManager = saverManager;
|
||||
}
|
||||
|
||||
BoBManager bobManager = INSTANCES.get(connection);
|
||||
if (bobManager == null) {
|
||||
bobManager = new BoBManager(connection);
|
||||
INSTANCES.put(connection, bobManager);
|
||||
}
|
||||
|
||||
return bobManager;
|
||||
}
|
||||
|
||||
private BoBManager(XMPPConnection connection) {
|
||||
super(connection);
|
||||
ServiceDiscoveryManager serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(connection);
|
||||
serviceDiscoveryManager.addFeature(NAMESPACE);
|
||||
|
||||
connection.registerIQRequestHandler(
|
||||
new AbstractIqRequestHandler(BoBIQ.ELEMENT, BoBIQ.NAMESPACE, Type.get, Mode.sync) {
|
||||
@Override
|
||||
public IQ handleIQRequest(IQ iqRequest) {
|
||||
BoBIQ getBoBIQ = (BoBIQ) iqRequest;
|
||||
|
||||
BoBData bobData = bobSaverManager.getBoB(getBoBIQ.getBoBHash());
|
||||
BoBIQ responseBoBIQ = null;
|
||||
try {
|
||||
responseBoBIQ = responseBoB(getBoBIQ, bobData);
|
||||
} catch (NotConnectedException | NotLoggedInException | InterruptedException e) {
|
||||
}
|
||||
|
||||
return responseBoBIQ;
|
||||
}
|
||||
});
|
||||
|
||||
connection.registerIQRequestHandler(
|
||||
new AbstractIqRequestHandler(BoBIQ.ELEMENT, BoBIQ.NAMESPACE, Type.result, Mode.sync) {
|
||||
@Override
|
||||
public IQ handleIQRequest(IQ iqRequest) {
|
||||
BoBIQ resultBoBIQ = (BoBIQ) iqRequest;
|
||||
bobSaverManager.addBoB(resultBoBIQ.getBoBHash(), resultBoBIQ.getBoBData());
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if Bits of Binary is supported by the server.
|
||||
*
|
||||
* @return true if Bits of Binary is supported by the server.
|
||||
* @throws NoResponseException
|
||||
* @throws XMPPErrorException
|
||||
* @throws NotConnectedException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public boolean isSupportedByServer()
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
return ServiceDiscoveryManager.getInstanceFor(connection()).serverSupportsFeature(NAMESPACE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request BoB data.
|
||||
*
|
||||
* @param to
|
||||
* @param bobHash
|
||||
* @return the BoB data
|
||||
* @throws NotLoggedInException
|
||||
* @throws NoResponseException
|
||||
* @throws XMPPErrorException
|
||||
* @throws NotConnectedException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public BoBData requestBoB(Jid to, BoBHash bobHash) throws NotLoggedInException, NoResponseException,
|
||||
XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
BoBIQ requestBoBIQ = new BoBIQ(bobHash);
|
||||
requestBoBIQ.setType(Type.get);
|
||||
requestBoBIQ.setTo(to);
|
||||
|
||||
XMPPConnection connection = getAuthenticatedConnectionOrThrow();
|
||||
BoBIQ responseBoBIQ = connection.createPacketCollectorAndSend(requestBoBIQ).nextResultOrThrow();
|
||||
return responseBoBIQ.getBoBData();
|
||||
}
|
||||
|
||||
private BoBIQ responseBoB(BoBIQ requestBoBIQ, BoBData bobData)
|
||||
throws NotConnectedException, InterruptedException, NotLoggedInException {
|
||||
BoBIQ responseBoBIQ = new BoBIQ(requestBoBIQ.getBoBHash(), bobData);
|
||||
responseBoBIQ.setType(Type.result);
|
||||
responseBoBIQ.setTo(requestBoBIQ.getFrom());
|
||||
return responseBoBIQ;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016 Fernando Ramirez
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.bob;
|
||||
|
||||
/**
|
||||
* Bits of Binary Saver Manager interface.
|
||||
*
|
||||
* @author Fernando Ramirez
|
||||
*
|
||||
*/
|
||||
public interface BoBSaverManager {
|
||||
|
||||
public void addBoB(BoBHash bobHash, BoBData bobData);
|
||||
|
||||
public void removeBoB(BoBHash bobHash);
|
||||
|
||||
public BoBData getBoB(BoBHash bobHash);
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016 Fernando Ramirez
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.bob;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Default Bits of Binary Saver Manager class.
|
||||
*
|
||||
* @author Fernando Ramirez
|
||||
*
|
||||
*/
|
||||
public class DefaultBoBSaverManager implements BoBSaverManager {
|
||||
|
||||
HashMap<BoBHash, BoBData> bobs = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void addBoB(BoBHash bobHash, BoBData bobData) {
|
||||
bobs.put(bobHash, bobData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeBoB(BoBHash bobHash) {
|
||||
bobs.remove(bobHash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoBData getBoB(BoBHash bobHash) {
|
||||
return bobs.get(bobHash);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016 Fernando Ramirez
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.bob.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
import org.jivesoftware.smackx.bob.BoBHash;
|
||||
import org.jivesoftware.smackx.xhtmlim.XHTMLText;
|
||||
import org.jivesoftware.smackx.xhtmlim.packet.XHTMLExtension;
|
||||
|
||||
/**
|
||||
* Bits of Binary extension element.
|
||||
*
|
||||
* @author Fernando Ramirez
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0231.html">XEP-0231: Bits of
|
||||
* Binary</a>
|
||||
*/
|
||||
public class BoBExtension extends XHTMLExtension {
|
||||
|
||||
private final BoBHash bobHash;
|
||||
private final String alt;
|
||||
private final String paragraph;
|
||||
|
||||
/**
|
||||
* Bits of Binary extension constructor.
|
||||
*
|
||||
* @param bobHash
|
||||
* @param alt
|
||||
* @param paragraph
|
||||
*/
|
||||
public BoBExtension(BoBHash bobHash, String alt, String paragraph) {
|
||||
this.bobHash = bobHash;
|
||||
this.alt = alt;
|
||||
this.paragraph = paragraph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the BoB hash.
|
||||
*
|
||||
* @return the BoB hash
|
||||
*/
|
||||
public BoBHash getBoBHash() {
|
||||
return bobHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the alt field.
|
||||
*
|
||||
* @return the alt field
|
||||
*/
|
||||
public String getAlt() {
|
||||
return alt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XmlStringBuilder toXML() {
|
||||
XmlStringBuilder xml = new XmlStringBuilder(this);
|
||||
xml.rightAngleBracket();
|
||||
|
||||
xml.halfOpenElement(Message.BODY);
|
||||
xml.xmlnsAttribute(XHTMLText.NAMESPACE);
|
||||
xml.rightAngleBracket();
|
||||
|
||||
xml.openElement(XHTMLText.P);
|
||||
xml.optEscape(paragraph);
|
||||
|
||||
xml.halfOpenElement(XHTMLText.IMG);
|
||||
xml.optAttribute("alt", alt);
|
||||
xml.attribute("src", bobHash.toSrc());
|
||||
xml.closeEmptyElement();
|
||||
|
||||
xml.closeElement(XHTMLText.P);
|
||||
xml.closeElement(Message.BODY);
|
||||
xml.closeElement(this);
|
||||
return xml;
|
||||
}
|
||||
|
||||
public static BoBExtension from(Message message) {
|
||||
return message.getExtension(ELEMENT, NAMESPACE);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016 Fernando Ramirez
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.bob.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smackx.bob.BoBData;
|
||||
import org.jivesoftware.smackx.bob.BoBHash;
|
||||
import org.jivesoftware.smackx.bob.BoBManager;
|
||||
|
||||
/**
|
||||
* Bits of Binary IQ class.
|
||||
*
|
||||
* @author Fernando Ramirez
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0231.html">XEP-0231: Bits of
|
||||
* Binary</a>
|
||||
*/
|
||||
public class BoBIQ extends IQ {
|
||||
|
||||
/**
|
||||
* data element.
|
||||
*/
|
||||
public static final String ELEMENT = "data";
|
||||
|
||||
/**
|
||||
* the IQ NAMESPACE.
|
||||
*/
|
||||
public static final String NAMESPACE = BoBManager.NAMESPACE;
|
||||
|
||||
private final BoBHash bobHash;
|
||||
private final BoBData bobData;
|
||||
|
||||
/**
|
||||
* Bits of Binary IQ constructor.
|
||||
*
|
||||
* @param bobHash
|
||||
* @param bobData
|
||||
*/
|
||||
public BoBIQ(BoBHash bobHash, BoBData bobData) {
|
||||
super(ELEMENT, NAMESPACE);
|
||||
this.bobHash = bobHash;
|
||||
this.bobData = bobData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bits of Binary IQ constructor.
|
||||
*
|
||||
* @param bobHash
|
||||
*/
|
||||
public BoBIQ(BoBHash bobHash) {
|
||||
this(bobHash, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the BoB hash.
|
||||
*
|
||||
* @return the BoB hash
|
||||
*/
|
||||
public BoBHash getBoBHash() {
|
||||
return bobHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the BoB data.
|
||||
*
|
||||
* @return the BoB data
|
||||
*/
|
||||
public BoBData getBoBData() {
|
||||
return bobData;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
|
||||
xml.attribute("cid", bobHash.toCid());
|
||||
|
||||
if (bobData != null) {
|
||||
xml.attribute("max-age", String.valueOf(bobData.getMaxAge()));
|
||||
xml.attribute("type", bobData.getType());
|
||||
xml.rightAngleBracket();
|
||||
xml.escape(bobData.getBase64Encoded());
|
||||
} else {
|
||||
xml.setEmptyElement();
|
||||
}
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016 Fernando Ramirez
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/**
|
||||
* Bits of Binary elements.
|
||||
*
|
||||
* @author Fernando Ramirez
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0231.html">XEP-0231: Bits of
|
||||
* Binary</a>
|
||||
*/
|
||||
package org.jivesoftware.smackx.bob.element;
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016 Fernando Ramirez
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/**
|
||||
* Classes and interfaces of Bits of Binary.
|
||||
*
|
||||
* @author Fernando Ramirez
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0231.html">XEP-0231: Bits of
|
||||
* Binary</a>
|
||||
*/
|
||||
package org.jivesoftware.smackx.bob;
|
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016 Fernando Ramirez
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.bob.provider;
|
||||
|
||||
import org.jivesoftware.smack.provider.ExtensionElementProvider;
|
||||
import org.jivesoftware.smackx.bob.BoBHash;
|
||||
import org.jivesoftware.smackx.bob.element.BoBExtension;
|
||||
import org.jivesoftware.smackx.xhtmlim.XHTMLText;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
/**
|
||||
* Bits of Binary extension provider class.
|
||||
*
|
||||
* @author Fernando Ramirez
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0231.html">XEP-0231: Bits of
|
||||
* Binary</a>
|
||||
*/
|
||||
public class BoBExtensionProvider extends ExtensionElementProvider<BoBExtension> {
|
||||
|
||||
@Override
|
||||
public BoBExtension parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
BoBHash bobHash = null;
|
||||
String alt = null;
|
||||
|
||||
outerloop: while (true) {
|
||||
int eventType = parser.next();
|
||||
|
||||
switch (eventType) {
|
||||
|
||||
case XmlPullParser.START_TAG:
|
||||
if (parser.getName().equals(XHTMLText.IMG)) {
|
||||
alt = parser.getAttributeValue("", "alt");
|
||||
|
||||
String src = parser.getAttributeValue("", "src");
|
||||
bobHash = BoBHash.fromSrc(src);
|
||||
}
|
||||
break;
|
||||
|
||||
case XmlPullParser.END_TAG:
|
||||
if (parser.getDepth() == initialDepth) {
|
||||
break outerloop;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return new BoBExtension(bobHash, alt, null);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016 Fernando Ramirez
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.bob.provider;
|
||||
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||
import org.jivesoftware.smackx.bob.BoBData;
|
||||
import org.jivesoftware.smackx.bob.BoBHash;
|
||||
import org.jivesoftware.smackx.bob.element.BoBIQ;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
/**
|
||||
* Bits of Binary IQ provider class.
|
||||
*
|
||||
* @author Fernando Ramirez
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0231.html">XEP-0231: Bits of
|
||||
* Binary</a>
|
||||
*/
|
||||
public class BoBIQProvider extends IQProvider<BoBIQ> {
|
||||
|
||||
@Override
|
||||
public BoBIQ parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
BoBHash bobHash = null;
|
||||
BoBData bobData = null;
|
||||
|
||||
parser.next();
|
||||
|
||||
if (parser.getName().equals(BoBIQ.ELEMENT)) {
|
||||
String cid = parser.getAttributeValue("", "cid");
|
||||
bobHash = BoBHash.fromCid(cid);
|
||||
|
||||
String dataType = parser.getAttributeValue("", "type");
|
||||
String maxAgeString = parser.getAttributeValue("", "max-age");
|
||||
|
||||
long maxAge = 0;
|
||||
if (maxAgeString != null) {
|
||||
maxAge = Long.parseLong(maxAgeString);
|
||||
}
|
||||
|
||||
String base64EncodedData = null;
|
||||
try {
|
||||
base64EncodedData = parser.nextText();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
if (base64EncodedData != null && dataType != null) {
|
||||
byte[] base64EncodedDataBytes = base64EncodedData.getBytes();
|
||||
bobData = new BoBData(maxAge, dataType, Base64.decode(base64EncodedDataBytes));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return new BoBIQ(bobHash, bobData);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016 Fernando Ramirez
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/**
|
||||
* Bits of Binary providers.
|
||||
*
|
||||
* @author Fernando Ramirez
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0231.html">XEP-0231: Bits of
|
||||
* Binary</a>
|
||||
*/
|
||||
package org.jivesoftware.smackx.bob.provider;
|
|
@ -537,4 +537,16 @@
|
|||
<className>org.jivesoftware.smackx.blocking.provider.BlockedErrorExtensionProvider</className>
|
||||
</extensionProvider>
|
||||
|
||||
<!-- XEP-0231: Bits of Binary -->
|
||||
<extensionProvider>
|
||||
<elementName>html</elementName>
|
||||
<namespace>http://jabber.org/protocol/xhtml-im</namespace>
|
||||
<className>org.jivesoftware.smackx.bob.provider.BoBExtensionProvider</className>
|
||||
</extensionProvider>
|
||||
<iqProvider>
|
||||
<elementName>data</elementName>
|
||||
<namespace>urn:xmpp:bob</namespace>
|
||||
<className>org.jivesoftware.smackx.bob.provider.BoBIQProvider</className>
|
||||
</iqProvider>
|
||||
|
||||
</smackProviders>
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016 Fernando Ramirez
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.bob;
|
||||
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.packet.Message.Type;
|
||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||
import org.jivesoftware.smackx.bob.element.BoBExtension;
|
||||
import org.jivesoftware.smackx.bob.provider.BoBExtensionProvider;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.jxmpp.jid.impl.JidCreate;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
public class BoBExtensionTest {
|
||||
|
||||
String sampleMessageWithBoBExtension = "<message to='macbeth@chat.shakespeare.lit' id='sarasa' type='groupchat'>"
|
||||
+ "<body>Yet here's a spot.</body>" + "<html xmlns='http://jabber.org/protocol/xhtml-im'>"
|
||||
+ "<body xmlns='http://www.w3.org/1999/xhtml'>"
|
||||
+ "<img alt='A spot' src='cid:sha1+8f35fef110ffc5df08d579a50083ff9308fb6242@bob.xmpp.org'/>" + "</body>"
|
||||
+ "</html>" + "</message>";
|
||||
|
||||
String sampleBoBExtension = "<html xmlns='http://jabber.org/protocol/xhtml-im'>"
|
||||
+ "<body xmlns='http://www.w3.org/1999/xhtml'>"
|
||||
+ "<img alt='A spot' src='cid:sha1+8f35fef110ffc5df08d579a50083ff9308fb6242@bob.xmpp.org'/>" + "</body>"
|
||||
+ "</html>";
|
||||
|
||||
@Test
|
||||
public void checkBoBMessageExtension() throws Exception {
|
||||
Message message = (Message) PacketParserUtils.parseStanza(sampleMessageWithBoBExtension);
|
||||
|
||||
BoBHash bobHash = new BoBHash("8f35fef110ffc5df08d579a50083ff9308fb6242", "sha1");
|
||||
|
||||
Message createdMessage = new Message(JidCreate.from("macbeth@chat.shakespeare.lit"));
|
||||
createdMessage.setStanzaId("sarasa");
|
||||
createdMessage.setType(Type.groupchat);
|
||||
createdMessage.setBody("Yet here's a spot.");
|
||||
createdMessage.addExtension(new BoBExtension(bobHash, "A spot", null));
|
||||
|
||||
Assert.assertEquals(message.toXML().toString(), createdMessage.toXML().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkBoBExtensionProvider() throws Exception {
|
||||
XmlPullParser parser = PacketParserUtils.getParserFor(sampleBoBExtension);
|
||||
BoBExtension bobExtension = new BoBExtensionProvider().parse(parser);
|
||||
|
||||
Assert.assertEquals("A spot", bobExtension.getAlt());
|
||||
Assert.assertEquals("sha1", bobExtension.getBoBHash().getHashType());
|
||||
Assert.assertEquals("8f35fef110ffc5df08d579a50083ff9308fb6242", bobExtension.getBoBHash().getHash());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016 Fernando Ramirez
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.bob;
|
||||
|
||||
import org.jivesoftware.smack.packet.IQ.Type;
|
||||
import org.jivesoftware.smack.test.util.SmackTestSuite;
|
||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||
import org.jivesoftware.smackx.bob.element.BoBIQ;
|
||||
import org.jivesoftware.smackx.bob.provider.BoBIQProvider;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.jxmpp.jid.impl.JidCreate;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
public class BoBIQTest extends SmackTestSuite {
|
||||
|
||||
String sampleBoBIQRequest = "<iq to='ladymacbeth@shakespeare.lit/castle' id='sarasa' type='get'>"
|
||||
+ "<data xmlns='urn:xmpp:bob' cid='sha1+8f35fef110ffc5df08d579a50083ff9308fb6242@bob.xmpp.org'/>" + "</iq>";
|
||||
|
||||
String sampleBoBIQResponse = "<iq to='doctor@shakespeare.lit/pda' id='sarasa' type='result'>"
|
||||
+ "<data xmlns='urn:xmpp:bob' cid='sha1+8f35fef110ffc5df08d579a50083ff9308fb6242@bob.xmpp.org' "
|
||||
+ "max-age='86400' type='image/png'>" + "c2FyYXNhZGUyMzU0ajI=" + "</data>" + "</iq>";
|
||||
|
||||
@Test
|
||||
public void checkBoBIQRequest() throws Exception {
|
||||
XmlPullParser parser = PacketParserUtils.getParserFor(sampleBoBIQRequest);
|
||||
BoBIQ bobIQ = new BoBIQProvider().parse(parser);
|
||||
bobIQ.setStanzaId("sarasa");
|
||||
bobIQ.setTo(JidCreate.from("ladymacbeth@shakespeare.lit/castle"));
|
||||
bobIQ.setType(Type.get);
|
||||
|
||||
BoBHash bobHash = new BoBHash("8f35fef110ffc5df08d579a50083ff9308fb6242", "sha1");
|
||||
|
||||
BoBIQ createdBoBIQ = new BoBIQ(bobHash);
|
||||
createdBoBIQ.setStanzaId("sarasa");
|
||||
createdBoBIQ.setTo(JidCreate.from("ladymacbeth@shakespeare.lit/castle"));
|
||||
createdBoBIQ.setType(Type.get);
|
||||
|
||||
Assert.assertEquals(sampleBoBIQRequest, createdBoBIQ.toXML().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkBoBIQResponse() throws Exception {
|
||||
XmlPullParser parser = PacketParserUtils.getParserFor(sampleBoBIQResponse);
|
||||
BoBIQ bobIQ = new BoBIQProvider().parse(parser);
|
||||
bobIQ.setStanzaId("sarasa");
|
||||
bobIQ.setTo(JidCreate.from("doctor@shakespeare.lit/pda"));
|
||||
bobIQ.setType(Type.result);
|
||||
|
||||
BoBHash bobHash = new BoBHash("8f35fef110ffc5df08d579a50083ff9308fb6242", "sha1");
|
||||
BoBData bobData = new BoBData(86400, "image/png", "sarasade2354j2".getBytes());
|
||||
|
||||
BoBIQ createdBoBIQ = new BoBIQ(bobHash, bobData);
|
||||
createdBoBIQ.setStanzaId("sarasa");
|
||||
createdBoBIQ.setTo(JidCreate.from("doctor@shakespeare.lit/pda"));
|
||||
createdBoBIQ.setType(Type.result);
|
||||
|
||||
Assert.assertEquals(bobIQ.getBoBHash().getHash(), createdBoBIQ.getBoBHash().getHash());
|
||||
Assert.assertEquals(bobIQ.getBoBHash().getHashType(), createdBoBIQ.getBoBHash().getHashType());
|
||||
Assert.assertEquals(bobIQ.getBoBData().getMaxAge(), createdBoBIQ.getBoBData().getMaxAge());
|
||||
Assert.assertEquals(bobIQ.getBoBData().getType(), createdBoBIQ.getBoBData().getType());
|
||||
Assert.assertEquals(bobIQ.getBoBData().getBase64Encoded(), createdBoBIQ.getBoBData().getBase64Encoded());
|
||||
Assert.assertEquals(bobIQ.toXML().toString(), createdBoBIQ.toXML().toString());
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue