1package eu.siacs.conversations.parser;
2
3import android.util.Log;
4import net.java.otr4j.session.Session;
5import net.java.otr4j.session.SessionStatus;
6import eu.siacs.conversations.entities.Account;
7import eu.siacs.conversations.entities.Conversation;
8import eu.siacs.conversations.entities.Message;
9import eu.siacs.conversations.services.XmppConnectionService;
10import eu.siacs.conversations.utils.CryptoHelper;
11import eu.siacs.conversations.xml.Element;
12import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
13
14public class MessageParser extends AbstractParser {
15
16 public MessageParser(XmppConnectionService service) {
17 super(service);
18 }
19
20 public Message parseChat(MessagePacket packet, Account account) {
21 Log.d("xmppService","received message: "+packet.toString());
22 String[] fromParts = packet.getFrom().split("/");
23 Conversation conversation = mXmppConnectionService
24 .findOrCreateConversation(account, fromParts[0], false);
25 conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
26 updateLastseen(packet, account,true);
27 String pgpBody = getPgpBody(packet);
28 Message finishedMessage;
29 if (pgpBody != null) {
30 finishedMessage = new Message(conversation, packet.getFrom(), pgpBody,
31 Message.ENCRYPTION_PGP, Message.STATUS_RECIEVED);
32 } else {
33 finishedMessage = new Message(conversation, packet.getFrom(),
34 packet.getBody(), Message.ENCRYPTION_NONE,
35 Message.STATUS_RECIEVED);
36 }
37 finishedMessage.setTime(getTimestamp(packet));
38 return finishedMessage;
39 }
40
41 public Message parseOtrChat(MessagePacket packet, Account account) {
42 boolean properlyAddressed = (packet.getTo().split("/").length == 2)
43 || (account.countPresences() == 1);
44 String[] fromParts = packet.getFrom().split("/");
45 Conversation conversation = mXmppConnectionService
46 .findOrCreateConversation(account, fromParts[0], false);
47 updateLastseen(packet, account,true);
48 String body = packet.getBody();
49 if (!conversation.hasValidOtrSession()) {
50 if (properlyAddressed) {
51 conversation.startOtrSession(
52 mXmppConnectionService.getApplicationContext(),
53 fromParts[1], false);
54 } else {
55 return null;
56 }
57 } else {
58 String foreignPresence = conversation.getOtrSession()
59 .getSessionID().getUserID();
60 if (!foreignPresence.equals(fromParts[1])) {
61 conversation.resetOtrSession();
62 if (properlyAddressed) {
63 conversation.startOtrSession(
64 mXmppConnectionService.getApplicationContext(),
65 fromParts[1], false);
66 } else {
67 return null;
68 }
69 }
70 }
71 try {
72 Session otrSession = conversation.getOtrSession();
73 SessionStatus before = otrSession.getSessionStatus();
74 body = otrSession.transformReceiving(body);
75 SessionStatus after = otrSession.getSessionStatus();
76 if ((before != after) && (after == SessionStatus.ENCRYPTED)) {
77 mXmppConnectionService.onOtrSessionEstablished(conversation);
78 } else if ((before != after) && (after == SessionStatus.FINISHED)) {
79 conversation.resetOtrSession();
80 }
81 if ((body == null) || (body.isEmpty())) {
82 return null;
83 }
84 if (body.startsWith(CryptoHelper.FILETRANSFER)) {
85 String key = body.substring(CryptoHelper.FILETRANSFER.length());
86 conversation.setSymmetricKey(CryptoHelper.hexToBytes(key));
87 Log.d("xmppService","new symmetric key: "+CryptoHelper.bytesToHex(conversation.getSymmetricKey()));
88 return null;
89 }
90 conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
91 Message finishedMessage = new Message(conversation, packet.getFrom(), body,
92 Message.ENCRYPTION_OTR, Message.STATUS_RECIEVED);
93 finishedMessage.setTime(getTimestamp(packet));
94 return finishedMessage;
95 } catch (Exception e) {
96 conversation.resetOtrSession();
97 return null;
98 }
99 }
100
101 public Message parseGroupchat(MessagePacket packet, Account account) {
102 int status;
103 String[] fromParts = packet.getFrom().split("/");
104 Conversation conversation = mXmppConnectionService
105 .findOrCreateConversation(account, fromParts[0], true);
106 if (packet.hasChild("subject")) {
107 conversation.getMucOptions().setSubject(
108 packet.findChild("subject").getContent());
109 mXmppConnectionService.updateUi(conversation, false);
110 return null;
111 }
112 if ((fromParts.length == 1)) {
113 return null;
114 }
115 String counterPart = fromParts[1];
116 if (counterPart.equals(conversation.getMucOptions().getNick())) {
117 if (mXmppConnectionService.markMessage(conversation,
118 packet.getId(), Message.STATUS_SEND)) {
119 return null;
120 } else {
121 status = Message.STATUS_SEND;
122 }
123 } else {
124 status = Message.STATUS_RECIEVED;
125 }
126 String pgpBody = getPgpBody(packet);
127 conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
128 Message finishedMessage;
129 if (pgpBody == null) {
130 finishedMessage = new Message(conversation, counterPart, packet.getBody(),
131 Message.ENCRYPTION_NONE, status);
132 } else {
133 finishedMessage= new Message(conversation, counterPart, pgpBody,
134 Message.ENCRYPTION_PGP, status);
135 }
136 finishedMessage.setTime(getTimestamp(packet));
137 return finishedMessage;
138 }
139
140 public Message parseCarbonMessage(MessagePacket packet, Account account) {
141 int status;
142 String fullJid;
143 Element forwarded;
144 if (packet.hasChild("received")) {
145 forwarded = packet.findChild("received").findChild("forwarded");
146 status = Message.STATUS_RECIEVED;
147 } else if (packet.hasChild("sent")) {
148 forwarded = packet.findChild("sent").findChild("forwarded");
149 status = Message.STATUS_SEND;
150 } else {
151 return null;
152 }
153 if (forwarded == null) {
154 return null;
155 }
156 Element message = forwarded.findChild("message");
157 if ((message == null) || (!message.hasChild("body")))
158 return null; // either malformed or boring
159 if (status == Message.STATUS_RECIEVED) {
160 fullJid = message.getAttribute("from");
161 updateLastseen(message, account,true);
162 } else {
163 fullJid = message.getAttribute("to");
164 }
165 String[] parts = fullJid.split("/");
166 Conversation conversation = mXmppConnectionService
167 .findOrCreateConversation(account, parts[0], false);
168 conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
169 String pgpBody = getPgpBody(message);
170 Message finishedMessage;
171 if (pgpBody != null) {
172 finishedMessage = new Message(conversation, fullJid, pgpBody,Message.ENCRYPTION_PGP, status);
173 } else {
174 String body = message.findChild("body").getContent();
175 finishedMessage= new Message(conversation, fullJid, body,Message.ENCRYPTION_NONE, status);
176 }
177 finishedMessage.setTime(getTimestamp(message));
178 return finishedMessage;
179 }
180
181 public void parseError(MessagePacket packet, Account account) {
182 String[] fromParts = packet.getFrom().split("/");
183 mXmppConnectionService.markMessage(account, fromParts[0],
184 packet.getId(), Message.STATUS_SEND_FAILED);
185 }
186
187 public void parseNormal(MessagePacket packet, Account account) {
188 if (packet.hasChild("displayed","urn:xmpp:chat-markers:0")) {
189 String id = packet.findChild("displayed","urn:xmpp:chat-markers:0").getAttribute("id");
190 String[] fromParts = packet.getFrom().split("/");
191 updateLastseen(packet, account,true);
192 mXmppConnectionService.markMessage(account,fromParts[0], id, Message.STATUS_SEND_DISPLAYED);
193 } else if (packet.hasChild("received","urn:xmpp:chat-markers:0")) {
194 String id = packet.findChild("received","urn:xmpp:chat-markers:0").getAttribute("id");
195 String[] fromParts = packet.getFrom().split("/");
196 updateLastseen(packet, account,false);
197 mXmppConnectionService.markMessage(account,fromParts[0], id, Message.STATUS_SEND_RECEIVED);
198 } else if (packet.hasChild("x")) {
199 Element x = packet.findChild("x");
200 if (x.hasChild("invite")) {
201 Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, packet.getFrom(),
202 true);
203 mXmppConnectionService.updateUi(conversation, false);
204 }
205
206 }
207 }
208
209 private String getPgpBody(Element message) {
210 Element child = message.findChild("x", "jabber:x:encrypted");
211 if (child == null) {
212 return null;
213 } else {
214 return child.getContent();
215 }
216 }
217
218 private String getMarkableMessageId(Element message) {
219 if (message.hasChild("markable", "urn:xmpp:chat-markers:0")) {
220 return message.getAttribute("id");
221 } else {
222 return null;
223 }
224 }
225
226
227}