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 void startOtrSession(Context context, String presence) {
222 Log.d("xmppService", "starting otr session with " + presence);
223 SessionID sessionId = new SessionID(this.getContactJid(), presence,
224 "xmpp");
225 this.otrSession = new SessionImpl(sessionId, getAccount().getOtrEngine(
226 context));
227 try {
228 this.otrSession.startSession();
229 } catch (OtrException e) {
230 Log.d("xmppServic", "couldnt start otr");
231 }
232 }
233
234 public SessionImpl getOtrSession() {
235 return this.otrSession;
236 }
237
238 public void resetOtrSession() {
239 this.otrSession = null;
240 }
241
242 public void endOtrIfNeeded() {
243 if (this.otrSession != null) {
244 if (this.otrSession.getSessionStatus() == SessionStatus.ENCRYPTED) {
245 try {
246 this.otrSession.endSession();
247 this.resetOtrSession();
248 } catch (OtrException e) {
249 this.resetOtrSession();
250 }
251 }
252 }
253 }
254
255 public boolean hasValidOtrSession() {
256 if (this.otrSession == null) {
257 return false;
258 } else {
259 String foreignPresence = this.otrSession.getSessionID().getUserID();
260 if (!getContact().getPresences().containsKey(foreignPresence)) {
261 this.resetOtrSession();
262 return false;
263 }
264 return true;
265 }
266 }
267
268 public String getOtrFingerprint() {
269 if (this.otrFingerprint == null) {
270 try {
271 DSAPublicKey remotePubKey = (DSAPublicKey) getOtrSession()
272 .getRemotePublicKey();
273 StringBuilder builder = new StringBuilder(
274 new OtrCryptoEngineImpl().getFingerprint(remotePubKey));
275 builder.insert(8, " ");
276 builder.insert(17, " ");
277 builder.insert(26, " ");
278 builder.insert(35, " ");
279 this.otrFingerprint = builder.toString();
280 } catch (OtrCryptoException e) {
281
282 }
283 }
284 return this.otrFingerprint;
285 }
286
287 public MucOptions getMucOptions() {
288 if (this.mucOptions == null) {
289 this.mucOptions = new MucOptions();
290 }
291 this.mucOptions.setConversation(this);
292 return this.mucOptions;
293 }
294
295 public void resetMucOptions() {
296 this.mucOptions = null;
297 }
298
299 public void setContactJid(String jid) {
300 this.contactJid = jid;
301 }
302}