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