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