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