aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/de/thedevstack/conversationsplus/generator
diff options
context:
space:
mode:
authorsteckbrief <steckbrief@chefmail.de>2015-05-03 22:25:46 +0200
committerlookshe <github@lookshe.org>2015-06-19 09:46:40 +0200
commit7382e3af9769f76fe4e19934a59e45a3f9858332 (patch)
treec37cdb03dfaeaccde7c8dd7c79887bf0de278f83 /src/main/java/de/thedevstack/conversationsplus/generator
parentb3b4a2902e37fb072e800f5dff0392755f5d4501 (diff)
renaming eu.siacs.conversations to de.thedevstack.conversationsplus
"renaming eu.siacs.conversations to de.thedevstack.conversationsplus" package renaming completed
Diffstat (limited to 'src/main/java/de/thedevstack/conversationsplus/generator')
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/generator/AbstractGenerator.java91
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/generator/IqGenerator.java189
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/generator/MessageGenerator.java187
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/generator/PresenceGenerator.java57
4 files changed, 524 insertions, 0 deletions
diff --git a/src/main/java/de/thedevstack/conversationsplus/generator/AbstractGenerator.java b/src/main/java/de/thedevstack/conversationsplus/generator/AbstractGenerator.java
new file mode 100644
index 00000000..cb56228d
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/generator/AbstractGenerator.java
@@ -0,0 +1,91 @@
+package de.thedevstack.conversationsplus.generator;
+
+import android.util.Base64;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import de.tzur.conversations.Settings;
+import de.thedevstack.conversationsplus.services.XmppConnectionService;
+import de.thedevstack.conversationsplus.utils.PhoneHelper;
+
+public abstract class AbstractGenerator {
+ private final String[] FEATURES = {
+ "urn:xmpp:jingle:1",
+ "urn:xmpp:jingle:apps:file-transfer:3",
+ "urn:xmpp:jingle:transports:s5b:1",
+ "urn:xmpp:jingle:transports:ibb:1",
+ "http://jabber.org/protocol/muc",
+ "jabber:x:conference",
+ "http://jabber.org/protocol/caps",
+ "http://jabber.org/protocol/disco#info",
+ "urn:xmpp:avatar:metadata+notify",
+ "urn:xmpp:ping",
+ "jabber:iq:version",
+ "http://jabber.org/protocol/chatstates"};
+ private final String[] MESSAGE_CONFIRMATION_FEATURES = {
+ "urn:xmpp:chat-markers:0",
+ "urn:xmpp:receipts"
+ };
+ private String mVersion = null;
+ public final String IDENTITY_NAME = "Conversations";
+ public final String IDENTITY_TYPE = "phone";
+
+ private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
+
+ protected XmppConnectionService mXmppConnectionService;
+
+ protected AbstractGenerator(XmppConnectionService service) {
+ this.mXmppConnectionService = service;
+ }
+
+ protected String getIdentityVersion() {
+ if (mVersion == null) {
+ this.mVersion = PhoneHelper.getVersionName(mXmppConnectionService);
+ }
+ return this.mVersion;
+ }
+
+ protected String getIdentityName() {
+ return IDENTITY_NAME + " " + getIdentityVersion();
+ }
+
+ public String getCapHash() {
+ StringBuilder s = new StringBuilder();
+ s.append("client/" + IDENTITY_TYPE + "//" + getIdentityName() + "<");
+ MessageDigest md;
+ try {
+ md = MessageDigest.getInstance("SHA-1");
+ } catch (NoSuchAlgorithmException e) {
+ return null;
+ }
+
+ for (String feature : getFeatures()) {
+ s.append(feature + "<");
+ }
+ byte[] sha1 = md.digest(s.toString().getBytes());
+ return new String(Base64.encode(sha1, Base64.DEFAULT)).trim();
+ }
+
+ public static String getTimestamp(long time) {
+ DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
+ return DATE_FORMAT.format(time);
+ }
+
+ public List<String> getFeatures() {
+ ArrayList<String> features = new ArrayList<>();
+ features.addAll(Arrays.asList(FEATURES));
+ if (Settings.CONFIRM_MESSAGE_RECEIVED) {
+ features.addAll(Arrays.asList(MESSAGE_CONFIRMATION_FEATURES));
+ }
+ Collections.sort(features);
+ return features;
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/generator/IqGenerator.java b/src/main/java/de/thedevstack/conversationsplus/generator/IqGenerator.java
new file mode 100644
index 00000000..ccba1e1d
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/generator/IqGenerator.java
@@ -0,0 +1,189 @@
+package de.thedevstack.conversationsplus.generator;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.thedevstack.conversationsplus.entities.Account;
+import de.thedevstack.conversationsplus.entities.Conversation;
+import de.thedevstack.conversationsplus.services.MessageArchiveService;
+import de.thedevstack.conversationsplus.services.XmppConnectionService;
+import de.thedevstack.conversationsplus.utils.Xmlns;
+import de.thedevstack.conversationsplus.xml.Element;
+import de.thedevstack.conversationsplus.xmpp.forms.Data;
+import de.thedevstack.conversationsplus.xmpp.jid.Jid;
+import de.thedevstack.conversationsplus.xmpp.pep.Avatar;
+import de.thedevstack.conversationsplus.xmpp.stanzas.IqPacket;
+
+public class IqGenerator extends AbstractGenerator {
+
+ public IqGenerator(final XmppConnectionService service) {
+ super(service);
+ }
+
+ public IqPacket discoResponse(final IqPacket request) {
+ final IqPacket packet = new IqPacket(IqPacket.TYPE.RESULT);
+ packet.setId(request.getId());
+ packet.setTo(request.getFrom());
+ final Element query = packet.addChild("query",
+ "http://jabber.org/protocol/disco#info");
+ query.setAttribute("node", request.query().getAttribute("node"));
+ final Element identity = query.addChild("identity");
+ identity.setAttribute("category", "client");
+ identity.setAttribute("type", IDENTITY_TYPE);
+ identity.setAttribute("name", getIdentityName());
+ for (final String feature : getFeatures()) {
+ query.addChild("feature").setAttribute("var", feature);
+ }
+ return packet;
+ }
+
+ public IqPacket versionResponse(final IqPacket request) {
+ final IqPacket packet = request.generateResponse(IqPacket.TYPE.RESULT);
+ Element query = packet.query("jabber:iq:version");
+ query.addChild("name").setContent(IDENTITY_NAME);
+ query.addChild("version").setContent(getIdentityVersion());
+ return packet;
+ }
+
+ protected IqPacket publish(final String node, final Element item) {
+ final IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
+ final Element pubsub = packet.addChild("pubsub",
+ "http://jabber.org/protocol/pubsub");
+ final Element publish = pubsub.addChild("publish");
+ publish.setAttribute("node", node);
+ publish.addChild(item);
+ return packet;
+ }
+
+ protected IqPacket retrieve(String node, Element item) {
+ final IqPacket packet = new IqPacket(IqPacket.TYPE.GET);
+ final Element pubsub = packet.addChild("pubsub",
+ "http://jabber.org/protocol/pubsub");
+ final Element items = pubsub.addChild("items");
+ items.setAttribute("node", node);
+ if (item != null) {
+ items.addChild(item);
+ }
+ return packet;
+ }
+
+ public IqPacket publishAvatar(Avatar avatar) {
+ final Element item = new Element("item");
+ item.setAttribute("id", avatar.sha1sum);
+ final Element data = item.addChild("data", "urn:xmpp:avatar:data");
+ data.setContent(avatar.image);
+ return publish("urn:xmpp:avatar:data", item);
+ }
+
+ public IqPacket publishAvatarMetadata(final Avatar avatar) {
+ final Element item = new Element("item");
+ item.setAttribute("id", avatar.sha1sum);
+ final Element metadata = item
+ .addChild("metadata", "urn:xmpp:avatar:metadata");
+ final Element info = metadata.addChild("info");
+ info.setAttribute("bytes", avatar.size);
+ info.setAttribute("id", avatar.sha1sum);
+ info.setAttribute("height", avatar.height);
+ info.setAttribute("width", avatar.height);
+ info.setAttribute("type", avatar.type);
+ return publish("urn:xmpp:avatar:metadata", item);
+ }
+
+ public IqPacket retrieveAvatar(final Avatar avatar) {
+ final Element item = new Element("item");
+ item.setAttribute("id", avatar.sha1sum);
+ final IqPacket packet = retrieve("urn:xmpp:avatar:data", item);
+ packet.setTo(avatar.owner);
+ return packet;
+ }
+
+ public IqPacket retrieveAvatarMetaData(final Jid to) {
+ final IqPacket packet = retrieve("urn:xmpp:avatar:metadata", null);
+ if (to != null) {
+ packet.setTo(to);
+ }
+ return packet;
+ }
+
+ public IqPacket queryMessageArchiveManagement(final MessageArchiveService.Query mam) {
+ final IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
+ final Element query = packet.query("urn:xmpp:mam:0");
+ query.setAttribute("queryid",mam.getQueryId());
+ final Data data = new Data();
+ data.setFormType("urn:xmpp:mam:0");
+ if (mam.muc()) {
+ packet.setTo(mam.getWith());
+ } else if (mam.getWith()!=null) {
+ data.put("with", mam.getWith().toString());
+ }
+ data.put("start",getTimestamp(mam.getStart()));
+ data.put("end",getTimestamp(mam.getEnd()));
+ query.addChild(data);
+ if (mam.getPagingOrder() == MessageArchiveService.PagingOrder.REVERSE) {
+ query.addChild("set", "http://jabber.org/protocol/rsm").addChild("before").setContent(mam.getReference());
+ } else if (mam.getReference() != null) {
+ query.addChild("set", "http://jabber.org/protocol/rsm").addChild("after").setContent(mam.getReference());
+ }
+ return packet;
+ }
+ public IqPacket generateGetBlockList() {
+ final IqPacket iq = new IqPacket(IqPacket.TYPE.GET);
+ iq.addChild("blocklist", Xmlns.BLOCKING);
+
+ return iq;
+ }
+
+ public IqPacket generateSetBlockRequest(final Jid jid) {
+ final IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
+ final Element block = iq.addChild("block", Xmlns.BLOCKING);
+ block.addChild("item").setAttribute("jid", jid.toBareJid().toString());
+ return iq;
+ }
+
+ public IqPacket generateSetUnblockRequest(final Jid jid) {
+ final IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
+ final Element block = iq.addChild("unblock", Xmlns.BLOCKING);
+ block.addChild("item").setAttribute("jid", jid.toBareJid().toString());
+ return iq;
+ }
+
+ public IqPacket generateSetPassword(final Account account, final String newPassword) {
+ final IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
+ packet.setTo(account.getServer());
+ final Element query = packet.addChild("query", Xmlns.REGISTER);
+ final Jid jid = account.getJid();
+ query.addChild("username").setContent(jid.getLocalpart());
+ query.addChild("password").setContent(newPassword);
+ return packet;
+ }
+
+ public IqPacket changeAffiliation(Conversation conference, Jid jid, String affiliation) {
+ List<Jid> jids = new ArrayList<>();
+ jids.add(jid);
+ return changeAffiliation(conference,jids,affiliation);
+ }
+
+ public IqPacket changeAffiliation(Conversation conference, List<Jid> jids, String affiliation) {
+ IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
+ packet.setTo(conference.getJid().toBareJid());
+ packet.setFrom(conference.getAccount().getJid());
+ Element query = packet.query("http://jabber.org/protocol/muc#admin");
+ for(Jid jid : jids) {
+ Element item = query.addChild("item");
+ item.setAttribute("jid", jid.toString());
+ item.setAttribute("affiliation", affiliation);
+ }
+ return packet;
+ }
+
+ public IqPacket changeRole(Conversation conference, String nick, String role) {
+ IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
+ packet.setTo(conference.getJid().toBareJid());
+ packet.setFrom(conference.getAccount().getJid());
+ Element item = packet.query("http://jabber.org/protocol/muc#admin").addChild("item");
+ item.setAttribute("nick", nick);
+ item.setAttribute("role", role);
+ return packet;
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/generator/MessageGenerator.java b/src/main/java/de/thedevstack/conversationsplus/generator/MessageGenerator.java
new file mode 100644
index 00000000..41b41882
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/generator/MessageGenerator.java
@@ -0,0 +1,187 @@
+package de.thedevstack.conversationsplus.generator;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import net.java.otr4j.OtrException;
+import net.java.otr4j.session.Session;
+import de.thedevstack.conversationsplus.entities.Account;
+import de.thedevstack.conversationsplus.entities.Conversation;
+import de.thedevstack.conversationsplus.entities.Message;
+import de.thedevstack.conversationsplus.services.XmppConnectionService;
+import de.thedevstack.conversationsplus.xml.Element;
+import de.thedevstack.conversationsplus.xmpp.chatstate.ChatState;
+import de.thedevstack.conversationsplus.xmpp.jid.Jid;
+import de.thedevstack.conversationsplus.xmpp.stanzas.MessagePacket;
+
+public class MessageGenerator extends AbstractGenerator {
+ public MessageGenerator(XmppConnectionService service) {
+ super(service);
+ }
+
+ private MessagePacket preparePacket(Message message, boolean addDelay) {
+ Conversation conversation = message.getConversation();
+ Account account = conversation.getAccount();
+ MessagePacket packet = new MessagePacket();
+ if (conversation.getMode() == Conversation.MODE_SINGLE) {
+ packet.setTo(message.getCounterpart());
+ packet.setType(MessagePacket.TYPE_CHAT);
+ packet.addChild("markable", "urn:xmpp:chat-markers:0");
+ if (this.mXmppConnectionService.indicateReceived()) {
+ packet.addChild("request", "urn:xmpp:receipts");
+ }
+ } else if (message.getType() == Message.TYPE_PRIVATE) {
+ packet.setTo(message.getCounterpart());
+ packet.setType(MessagePacket.TYPE_CHAT);
+ if (this.mXmppConnectionService.indicateReceived()) {
+ packet.addChild("request", "urn:xmpp:receipts");
+ }
+ } else {
+ packet.setTo(message.getCounterpart().toBareJid());
+ packet.setType(MessagePacket.TYPE_GROUPCHAT);
+ }
+ packet.setFrom(account.getJid());
+ packet.setId(message.getUuid());
+ if (addDelay) {
+ addDelay(packet, message.getTimeSent());
+ }
+ return packet;
+ }
+
+ private void addDelay(MessagePacket packet, long timestamp) {
+ final SimpleDateFormat mDateFormat = new SimpleDateFormat(
+ "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
+ mDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ Element delay = packet.addChild("delay", "urn:xmpp:delay");
+ Date date = new Date(timestamp);
+ delay.setAttribute("stamp", mDateFormat.format(date));
+ }
+
+ public MessagePacket generateOtrChat(Message message) {
+ return generateOtrChat(message, false);
+ }
+
+ public MessagePacket generateOtrChat(Message message, boolean addDelay) {
+ Session otrSession = message.getConversation().getOtrSession();
+ if (otrSession == null) {
+ return null;
+ }
+ MessagePacket packet = preparePacket(message, addDelay);
+ packet.addChild("private", "urn:xmpp:carbons:2");
+ packet.addChild("no-copy", "urn:xmpp:hints");
+ try {
+ packet.setBody(otrSession.transformSending(message.getBody())[0]);
+ return packet;
+ } catch (OtrException e) {
+ return null;
+ }
+ }
+
+ public MessagePacket generateChat(Message message) {
+ return generateChat(message, false);
+ }
+
+ public MessagePacket generateChat(Message message, boolean addDelay) {
+ MessagePacket packet = preparePacket(message, addDelay);
+ packet.setBody(message.getBody());
+ return packet;
+ }
+
+ public MessagePacket generatePgpChat(Message message) {
+ return generatePgpChat(message, false);
+ }
+
+ public MessagePacket generatePgpChat(Message message, boolean addDelay) {
+ MessagePacket packet = preparePacket(message, addDelay);
+ packet.setBody("This is an XEP-0027 encryted message");
+ if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
+ packet.addChild("x", "jabber:x:encrypted").setContent(
+ message.getEncryptedBody());
+ } else if (message.getEncryption() == Message.ENCRYPTION_PGP) {
+ packet.addChild("x", "jabber:x:encrypted").setContent(
+ message.getBody());
+ }
+ return packet;
+ }
+
+ public MessagePacket generateChatState(Conversation conversation) {
+ final Account account = conversation.getAccount();
+ MessagePacket packet = new MessagePacket();
+ packet.setTo(conversation.getJid().toBareJid());
+ packet.setFrom(account.getJid());
+ packet.addChild(ChatState.toElement(conversation.getOutgoingChatState()));
+ return packet;
+ }
+
+ public MessagePacket confirm(final Account account, final Jid to, final String id) {
+ MessagePacket packet = new MessagePacket();
+ packet.setType(MessagePacket.TYPE_NORMAL);
+ packet.setTo(to);
+ packet.setFrom(account.getJid());
+ Element received = packet.addChild("displayed",
+ "urn:xmpp:chat-markers:0");
+ received.setAttribute("id", id);
+ return packet;
+ }
+
+ public MessagePacket conferenceSubject(Conversation conversation,
+ String subject) {
+ MessagePacket packet = new MessagePacket();
+ packet.setType(MessagePacket.TYPE_GROUPCHAT);
+ packet.setTo(conversation.getJid().toBareJid());
+ Element subjectChild = new Element("subject");
+ subjectChild.setContent(subject);
+ packet.addChild(subjectChild);
+ packet.setFrom(conversation.getAccount().getJid().toBareJid());
+ return packet;
+ }
+
+ public MessagePacket directInvite(final Conversation conversation, final Jid contact) {
+ MessagePacket packet = new MessagePacket();
+ packet.setType(MessagePacket.TYPE_NORMAL);
+ packet.setTo(contact);
+ packet.setFrom(conversation.getAccount().getJid());
+ Element x = packet.addChild("x", "jabber:x:conference");
+ x.setAttribute("jid", conversation.getJid().toBareJid().toString());
+ return packet;
+ }
+
+ public MessagePacket invite(Conversation conversation, Jid contact) {
+ MessagePacket packet = new MessagePacket();
+ packet.setTo(conversation.getJid().toBareJid());
+ packet.setFrom(conversation.getAccount().getJid());
+ Element x = new Element("x");
+ x.setAttribute("xmlns", "http://jabber.org/protocol/muc#user");
+ Element invite = new Element("invite");
+ invite.setAttribute("to", contact.toBareJid().toString());
+ x.addChild(invite);
+ packet.addChild(x);
+ return packet;
+ }
+
+ public MessagePacket received(Account account,
+ MessagePacket originalMessage, String namespace) {
+ MessagePacket receivedPacket = new MessagePacket();
+ receivedPacket.setType(MessagePacket.TYPE_NORMAL);
+ receivedPacket.setTo(originalMessage.getFrom());
+ receivedPacket.setFrom(account.getJid());
+ Element received = receivedPacket.addChild("received", namespace);
+ received.setAttribute("id", originalMessage.getId());
+ return receivedPacket;
+ }
+
+ public MessagePacket generateOtrError(Jid to, String id) {
+ MessagePacket packet = new MessagePacket();
+ packet.setType(MessagePacket.TYPE_ERROR);
+ packet.setAttribute("id",id);
+ packet.setTo(to);
+ Element error = packet.addChild("error");
+ error.setAttribute("code","406");
+ error.setAttribute("type","modify");
+ error.addChild("not-acceptable","urn:ietf:params:xml:ns:xmpp-stanzas");
+ error.addChild("text").setContent("unreadable OTR message received");
+ return packet;
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/generator/PresenceGenerator.java b/src/main/java/de/thedevstack/conversationsplus/generator/PresenceGenerator.java
new file mode 100644
index 00000000..27fdd501
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/generator/PresenceGenerator.java
@@ -0,0 +1,57 @@
+package de.thedevstack.conversationsplus.generator;
+
+import de.thedevstack.conversationsplus.entities.Account;
+import de.thedevstack.conversationsplus.entities.Contact;
+import de.thedevstack.conversationsplus.services.XmppConnectionService;
+import de.thedevstack.conversationsplus.xml.Element;
+import de.thedevstack.conversationsplus.xmpp.stanzas.PresencePacket;
+
+public class PresenceGenerator extends AbstractGenerator {
+
+ public PresenceGenerator(XmppConnectionService service) {
+ super(service);
+ }
+
+ private PresencePacket subscription(String type, Contact contact) {
+ PresencePacket packet = new PresencePacket();
+ packet.setAttribute("type", type);
+ packet.setTo(contact.getJid());
+ packet.setFrom(contact.getAccount().getJid().toBareJid());
+ return packet;
+ }
+
+ public PresencePacket requestPresenceUpdatesFrom(Contact contact) {
+ return subscription("subscribe", contact);
+ }
+
+ public PresencePacket stopPresenceUpdatesFrom(Contact contact) {
+ return subscription("unsubscribe", contact);
+ }
+
+ public PresencePacket stopPresenceUpdatesTo(Contact contact) {
+ return subscription("unsubscribed", contact);
+ }
+
+ public PresencePacket sendPresenceUpdatesTo(Contact contact) {
+ return subscription("subscribed", contact);
+ }
+
+ public PresencePacket sendPresence(Account account) {
+ PresencePacket packet = new PresencePacket();
+ packet.setFrom(account.getJid());
+ String sig = account.getPgpSignature();
+ if (sig != null) {
+ packet.addChild("status").setContent("online");
+ packet.addChild("x", "jabber:x:signed").setContent(sig);
+ }
+ String capHash = getCapHash();
+ if (capHash != null) {
+ Element cap = packet.addChild("c",
+ "http://jabber.org/protocol/caps");
+ cap.setAttribute("hash", "sha-1");
+ cap.setAttribute("node", "http://conversions.im");
+ cap.setAttribute("ver", capHash);
+ }
+ return packet;
+ }
+} \ No newline at end of file