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;
13import android.content.ContentValues;
14import android.content.Context;
15import android.database.Cursor;
16import android.net.Uri;
17import android.util.Log;
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 Log.d("xmppService","ending otr session with "+getContactJid());
244 try {
245 this.otrSession.endSession();
246 this.resetOtrSession();
247 } catch (OtrException e) {
248 this.resetOtrSession();
249 }
250 }
251 }
252 }
253
254 public boolean hasValidOtrSession() {
255 return this.otrSession != null;
256 }
257
258 public String getOtrFingerprint() {
259 if (this.otrFingerprint == null) {
260 try {
261 DSAPublicKey remotePubKey = (DSAPublicKey) getOtrSession()
262 .getRemotePublicKey();
263 StringBuilder builder = new StringBuilder(
264 new OtrCryptoEngineImpl().getFingerprint(remotePubKey));
265 builder.insert(8, " ");
266 builder.insert(17, " ");
267 builder.insert(26, " ");
268 builder.insert(35, " ");
269 this.otrFingerprint = builder.toString();
270 } catch (OtrCryptoException e) {
271
272 }
273 }
274 return this.otrFingerprint;
275 }
276
277 public synchronized MucOptions getMucOptions() {
278 if (this.mucOptions == null) {
279 this.mucOptions = new MucOptions(this.getAccount());
280 }
281 this.mucOptions.setConversation(this);
282 return this.mucOptions;
283 }
284
285 public void resetMucOptions() {
286 this.mucOptions = null;
287 }
288
289 public void setContactJid(String jid) {
290 this.contactJid = jid;
291 }
292
293 public void setNextPresence(String presence) {
294 this.nextPresence = presence;
295 }
296
297 public String getNextPresence() {
298 return this.nextPresence;
299 }
300
301 public int getLatestEncryption() {
302 int latestEncryption = this.getLatestMessage().getEncryption();
303 if ((latestEncryption == Message.ENCRYPTION_DECRYPTED) || (latestEncryption == Message.ENCRYPTION_DECRYPTION_FAILED)) {
304 return Message.ENCRYPTION_PGP;
305 } else {
306 return latestEncryption;
307 }
308 }
309
310 public int getNextEncryption() {
311 if (this.nextMessageEncryption == -1) {
312 return this.getLatestEncryption();
313 }
314 return this.nextMessageEncryption;
315 }
316
317 public void setNextEncryption(int encryption) {
318 this.nextMessageEncryption = encryption;
319 }
320
321 public String getNextMessage() {
322 if (this.nextMessage==null) {
323 return "";
324 } else {
325 return this.nextMessage;
326 }
327 }
328
329 public void setNextMessage(String message) {
330 this.nextMessage = message;
331 }
332}