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