1package eu.siacs.conversations.entities;
2
3import java.security.interfaces.DSAPublicKey;
4import java.util.ArrayList;
5import java.util.List;
6
7import net.java.otr4j.OtrException;
8import net.java.otr4j.crypto.OtrCryptoEngineImpl;
9import net.java.otr4j.crypto.OtrCryptoException;
10import net.java.otr4j.session.SessionID;
11import net.java.otr4j.session.SessionImpl;
12import net.java.otr4j.session.SessionStatus;
13
14import android.content.ContentValues;
15import android.content.Context;
16import android.database.Cursor;
17import android.net.Uri;
18
19public class Conversation extends AbstractEntity {
20
21 private static final long serialVersionUID = -6727528868973996739L;
22
23 public static final String TABLENAME = "conversations";
24
25 public static final int STATUS_AVAILABLE = 0;
26 public static final int STATUS_ARCHIVED = 1;
27 public static final int STATUS_DELETED = 2;
28
29 public static final int MODE_MULTI = 1;
30 public static final int MODE_SINGLE = 0;
31
32 public static final String NAME = "name";
33 public static final String ACCOUNT = "accountUuid";
34 public static final String CONTACT = "contactUuid";
35 public static final String CONTACTJID = "contactJid";
36 public static final String STATUS = "status";
37 public static final String CREATED = "created";
38 public static final String MODE = "mode";
39
40 private String name;
41 private String contactUuid;
42 private String accountUuid;
43 private String contactJid;
44 private int status;
45 private long created;
46 private int mode;
47
48 private String nextPresence;
49
50 private transient List<Message> messages = null;
51 private transient Account account = null;
52
53 private transient SessionImpl otrSession;
54
55 private transient String otrFingerprint = null;
56
57 private int nextMessageEncryption = -1;
58 private String nextMessage;
59
60 private transient MucOptions mucOptions = null;
61
62 public Conversation(String name, Account account, String contactJid,
63 int mode) {
64 this(java.util.UUID.randomUUID().toString(), name, null, account
65 .getUuid(), contactJid, System.currentTimeMillis(),
66 STATUS_AVAILABLE, mode);
67 this.account = account;
68 }
69
70 public Conversation(String uuid, String name, String contactUuid,
71 String accountUuid, String contactJid, long created, int status,
72 int mode) {
73 this.uuid = uuid;
74 this.name = name;
75 this.contactUuid = contactUuid;
76 this.accountUuid = accountUuid;
77 this.contactJid = contactJid;
78 this.created = created;
79 this.status = status;
80 this.mode = mode;
81 }
82
83 public List<Message> getMessages() {
84 if (messages == null)
85 this.messages = new ArrayList<Message>(); // prevent null pointer
86
87 // populate with Conversation (this)
88
89 for (Message msg : messages) {
90 msg.setConversation(this);
91 }
92
93 return messages;
94 }
95
96 public boolean isRead() {
97 if ((this.messages == null) || (this.messages.size() == 0))
98 return true;
99 return this.messages.get(this.messages.size() - 1).isRead();
100 }
101
102 public void markRead() {
103 if (this.messages == null)
104 return;
105 for (int i = this.messages.size() - 1; i >= 0; --i) {
106 if (messages.get(i).isRead())
107 return;
108 this.messages.get(i).markRead();
109 }
110 }
111
112 public Message getLatestMessage() {
113 if ((this.messages == null) || (this.messages.size() == 0)) {
114 Message message = new Message(this, "", Message.ENCRYPTION_NONE);
115 message.setTime(getCreated());
116 return message;
117 } else {
118 Message message = this.messages.get(this.messages.size() - 1);
119 message.setConversation(this);
120 return message;
121 }
122 }
123
124 public void setMessages(List<Message> msgs) {
125 this.messages = msgs;
126 }
127
128 public String getName(boolean useSubject) {
129 if ((getMode() == MODE_MULTI) && (getMucOptions().getSubject() != null) && useSubject) {
130 return getMucOptions().getSubject();
131 } else {
132 return this.getContact().getDisplayName();
133 }
134 }
135
136 public String getProfilePhotoString() {
137 return this.getContact().getProfilePhoto();
138 }
139
140 public String getAccountUuid() {
141 return this.accountUuid;
142 }
143
144 public Account getAccount() {
145 return this.account;
146 }
147
148 public Contact getContact() {
149 return this.account.getRoster().getContact(this.contactJid);
150 }
151
152 public void setAccount(Account account) {
153 this.account = account;
154 }
155
156 public String getContactJid() {
157 return this.contactJid;
158 }
159
160 public Uri getProfilePhotoUri() {
161 if (this.getProfilePhotoString() != null) {
162 return Uri.parse(this.getProfilePhotoString());
163 }
164 return null;
165 }
166
167 public int getStatus() {
168 return this.status;
169 }
170
171 public long getCreated() {
172 return this.created;
173 }
174
175 public ContentValues getContentValues() {
176 ContentValues values = new ContentValues();
177 values.put(UUID, uuid);
178 values.put(NAME, name);
179 values.put(CONTACT, contactUuid);
180 values.put(ACCOUNT, accountUuid);
181 values.put(CONTACTJID, contactJid);
182 values.put(CREATED, created);
183 values.put(STATUS, status);
184 values.put(MODE, mode);
185 return values;
186 }
187
188 public static Conversation fromCursor(Cursor cursor) {
189 return new Conversation(cursor.getString(cursor.getColumnIndex(UUID)),
190 cursor.getString(cursor.getColumnIndex(NAME)),
191 cursor.getString(cursor.getColumnIndex(CONTACT)),
192 cursor.getString(cursor.getColumnIndex(ACCOUNT)),
193 cursor.getString(cursor.getColumnIndex(CONTACTJID)),
194 cursor.getLong(cursor.getColumnIndex(CREATED)),
195 cursor.getInt(cursor.getColumnIndex(STATUS)),
196 cursor.getInt(cursor.getColumnIndex(MODE)));
197 }
198
199 public void setStatus(int status) {
200 this.status = status;
201 }
202
203 public int getMode() {
204 return this.mode;
205 }
206
207 public void setMode(int mode) {
208 this.mode = mode;
209 }
210
211 public SessionImpl startOtrSession(Context context, String presence, boolean sendStart) {
212 if (this.otrSession != null) {
213 return this.otrSession;
214 } else {
215 SessionID sessionId = new SessionID(this.getContactJid(), presence,
216 "xmpp");
217 this.otrSession = new SessionImpl(sessionId, getAccount().getOtrEngine(
218 context));
219 try {
220 if (sendStart) {
221 this.otrSession.startSession();
222 return this.otrSession;
223 }
224 return this.otrSession;
225 } catch (OtrException e) {
226 return null;
227 }
228 }
229
230 }
231
232 public SessionImpl getOtrSession() {
233 return this.otrSession;
234 }
235
236 public void resetOtrSession() {
237 this.otrSession = null;
238 }
239
240 public void endOtrIfNeeded() {
241 if (this.otrSession != null) {
242 if (this.otrSession.getSessionStatus() == SessionStatus.ENCRYPTED) {
243 try {
244 this.otrSession.endSession();
245 this.resetOtrSession();
246 } catch (OtrException e) {
247 this.resetOtrSession();
248 }
249 }
250 }
251 }
252
253 public boolean hasValidOtrSession() {
254 if (this.otrSession == null) {
255 return false;
256 } else {
257 String foreignPresence = this.otrSession.getSessionID().getUserID();
258 if (getContact()==null) {
259 return true;
260 } else {
261 if (!getContact().getPresences().containsKey(foreignPresence)) {
262 this.resetOtrSession();
263 return false;
264 }
265 return true;
266 }
267 }
268 }
269
270 public String getOtrFingerprint() {
271 if (this.otrFingerprint == null) {
272 try {
273 DSAPublicKey remotePubKey = (DSAPublicKey) getOtrSession()
274 .getRemotePublicKey();
275 StringBuilder builder = new StringBuilder(
276 new OtrCryptoEngineImpl().getFingerprint(remotePubKey));
277 builder.insert(8, " ");
278 builder.insert(17, " ");
279 builder.insert(26, " ");
280 builder.insert(35, " ");
281 this.otrFingerprint = builder.toString();
282 } catch (OtrCryptoException e) {
283
284 }
285 }
286 return this.otrFingerprint;
287 }
288
289 public synchronized MucOptions getMucOptions() {
290 if (this.mucOptions == null) {
291 this.mucOptions = new MucOptions();
292 }
293 this.mucOptions.setConversation(this);
294 return this.mucOptions;
295 }
296
297 public void resetMucOptions() {
298 this.mucOptions = null;
299 }
300
301 public void setContactJid(String jid) {
302 this.contactJid = jid;
303 }
304
305 public void setNextPresence(String presence) {
306 this.nextPresence = presence;
307 }
308
309 public String getNextPresence() {
310 return this.nextPresence;
311 }
312
313 public int getLatestEncryption() {
314 int latestEncryption = this.getLatestMessage().getEncryption();
315 if ((latestEncryption == Message.ENCRYPTION_DECRYPTED) || (latestEncryption == Message.ENCRYPTION_DECRYPTION_FAILED)) {
316 return Message.ENCRYPTION_PGP;
317 } else {
318 return latestEncryption;
319 }
320 }
321
322 public int getNextEncryption() {
323 if (this.nextMessageEncryption == -1) {
324 return this.getLatestEncryption();
325 }
326 return this.nextMessageEncryption;
327 }
328
329 public void setNextEncryption(int encryption) {
330 this.nextMessageEncryption = encryption;
331 }
332
333 public String getNextMessage() {
334 if (this.nextMessage==null) {
335 return "";
336 } else {
337 return this.nextMessage;
338 }
339 }
340
341 public void setNextMessage(String message) {
342 this.nextMessage = message;
343 }
344}