1package eu.siacs.conversations.entities;
2
3import java.util.HashSet;
4import java.util.Locale;
5import java.util.Set;
6
7import org.json.JSONArray;
8import org.json.JSONException;
9import org.json.JSONObject;
10
11import eu.siacs.conversations.xml.Element;
12import android.content.ContentValues;
13import android.database.Cursor;
14
15public class Contact implements ListItem {
16 public static final String TABLENAME = "contacts";
17
18 public static final String SYSTEMNAME = "systemname";
19 public static final String SERVERNAME = "servername";
20 public static final String JID = "jid";
21 public static final String OPTIONS = "options";
22 public static final String SYSTEMACCOUNT = "systemaccount";
23 public static final String PHOTOURI = "photouri";
24 public static final String KEYS = "pgpkey";
25 public static final String ACCOUNT = "accountUuid";
26 public static final String AVATAR = "avatar";
27
28 protected String accountUuid;
29 protected String systemName;
30 protected String serverName;
31 protected String presenceName;
32 protected String jid;
33 protected int subscription = 0;
34 protected String systemAccount;
35 protected String photoUri;
36 protected String avatar;
37 protected JSONObject keys = new JSONObject();
38 protected Presences presences = new Presences();
39
40 protected Account account;
41
42 protected boolean inRoster = true;
43
44 public Lastseen lastseen = new Lastseen();
45
46 public Contact(String account, String systemName, String serverName,
47 String jid, int subscription, String photoUri,
48 String systemAccount, String keys, String avatar) {
49 this.accountUuid = account;
50 this.systemName = systemName;
51 this.serverName = serverName;
52 this.jid = jid;
53 this.subscription = subscription;
54 this.photoUri = photoUri;
55 this.systemAccount = systemAccount;
56 if (keys == null) {
57 keys = "";
58 }
59 try {
60 this.keys = new JSONObject(keys);
61 } catch (JSONException e) {
62 this.keys = new JSONObject();
63 }
64 this.avatar = avatar;
65 }
66
67 public Contact(String jid) {
68 this.jid = jid;
69 }
70
71 public String getDisplayName() {
72 if (this.systemName != null) {
73 return this.systemName;
74 } else if (this.serverName != null) {
75 return this.serverName;
76 } else if (this.presenceName != null) {
77 return this.presenceName;
78 } else {
79 return this.jid.split("@")[0];
80 }
81 }
82
83 public String getProfilePhoto() {
84 return this.photoUri;
85 }
86
87 public String getJid() {
88 return this.jid.toLowerCase(Locale.getDefault());
89 }
90
91 public boolean match(String needle) {
92 return needle == null
93 || jid.contains(needle.toLowerCase())
94 || getDisplayName().toLowerCase()
95 .contains(needle.toLowerCase());
96 }
97
98 public ContentValues getContentValues() {
99 ContentValues values = new ContentValues();
100 values.put(ACCOUNT, accountUuid);
101 values.put(SYSTEMNAME, systemName);
102 values.put(SERVERNAME, serverName);
103 values.put(JID, jid);
104 values.put(OPTIONS, subscription);
105 values.put(SYSTEMACCOUNT, systemAccount);
106 values.put(PHOTOURI, photoUri);
107 values.put(KEYS, keys.toString());
108 values.put(AVATAR, avatar);
109 return values;
110 }
111
112 public static Contact fromCursor(Cursor cursor) {
113 return new Contact(cursor.getString(cursor.getColumnIndex(ACCOUNT)),
114 cursor.getString(cursor.getColumnIndex(SYSTEMNAME)),
115 cursor.getString(cursor.getColumnIndex(SERVERNAME)),
116 cursor.getString(cursor.getColumnIndex(JID)),
117 cursor.getInt(cursor.getColumnIndex(OPTIONS)),
118 cursor.getString(cursor.getColumnIndex(PHOTOURI)),
119 cursor.getString(cursor.getColumnIndex(SYSTEMACCOUNT)),
120 cursor.getString(cursor.getColumnIndex(KEYS)),
121 cursor.getString(cursor.getColumnIndex(AVATAR)));
122 }
123
124 public int getSubscription() {
125 return this.subscription;
126 }
127
128 public void setSystemAccount(String account) {
129 this.systemAccount = account;
130 }
131
132 public void setAccount(Account account) {
133 this.account = account;
134 this.accountUuid = account.getUuid();
135 }
136
137 public Account getAccount() {
138 return this.account;
139 }
140
141 public Presences getPresences() {
142 return this.presences;
143 }
144
145 public void updatePresence(String resource, int status) {
146 this.presences.updatePresence(resource, status);
147 }
148
149 public void removePresence(String resource) {
150 this.presences.removePresence(resource);
151 }
152
153 public void clearPresences() {
154 this.presences.clearPresences();
155 this.resetOption(Options.PENDING_SUBSCRIPTION_REQUEST);
156 }
157
158 public int getMostAvailableStatus() {
159 return this.presences.getMostAvailableStatus();
160 }
161
162 public void setPresences(Presences pres) {
163 this.presences = pres;
164 }
165
166 public void setPhotoUri(String uri) {
167 this.photoUri = uri;
168 }
169
170 public void setServerName(String serverName) {
171 this.serverName = serverName;
172 }
173
174 public void setSystemName(String systemName) {
175 this.systemName = systemName;
176 }
177
178 public void setPresenceName(String presenceName) {
179 this.presenceName = presenceName;
180 }
181
182 public String getSystemAccount() {
183 return systemAccount;
184 }
185
186 public Set<String> getOtrFingerprints() {
187 Set<String> set = new HashSet<String>();
188 try {
189 if (this.keys.has("otr_fingerprints")) {
190 JSONArray fingerprints = this.keys
191 .getJSONArray("otr_fingerprints");
192 for (int i = 0; i < fingerprints.length(); ++i) {
193 set.add(fingerprints.getString(i));
194 }
195 }
196 } catch (JSONException e) {
197 // TODO Auto-generated catch block
198 e.printStackTrace();
199 }
200 return set;
201 }
202
203 public void addOtrFingerprint(String print) {
204 try {
205 JSONArray fingerprints;
206 if (!this.keys.has("otr_fingerprints")) {
207 fingerprints = new JSONArray();
208
209 } else {
210 fingerprints = this.keys.getJSONArray("otr_fingerprints");
211 }
212 fingerprints.put(print);
213 this.keys.put("otr_fingerprints", fingerprints);
214 } catch (JSONException e) {
215
216 }
217 }
218
219 public void setPgpKeyId(long keyId) {
220 try {
221 this.keys.put("pgp_keyid", keyId);
222 } catch (JSONException e) {
223
224 }
225 }
226
227 public long getPgpKeyId() {
228 if (this.keys.has("pgp_keyid")) {
229 try {
230 return this.keys.getLong("pgp_keyid");
231 } catch (JSONException e) {
232 return 0;
233 }
234 } else {
235 return 0;
236 }
237 }
238
239 public void setOption(int option) {
240 this.subscription |= 1 << option;
241 }
242
243 public void resetOption(int option) {
244 this.subscription &= ~(1 << option);
245 }
246
247 public boolean getOption(int option) {
248 return ((this.subscription & (1 << option)) != 0);
249 }
250
251 public boolean showInRoster() {
252 return (this.getOption(Contact.Options.IN_ROSTER) && (!this
253 .getOption(Contact.Options.DIRTY_DELETE)))
254 || (this.getOption(Contact.Options.DIRTY_PUSH));
255 }
256
257 public void parseSubscriptionFromElement(Element item) {
258 String ask = item.getAttribute("ask");
259 String subscription = item.getAttribute("subscription");
260
261 if (subscription != null) {
262 if (subscription.equals("to")) {
263 this.resetOption(Contact.Options.FROM);
264 this.setOption(Contact.Options.TO);
265 } else if (subscription.equals("from")) {
266 this.resetOption(Contact.Options.TO);
267 this.setOption(Contact.Options.FROM);
268 this.resetOption(Contact.Options.PREEMPTIVE_GRANT);
269 } else if (subscription.equals("both")) {
270 this.setOption(Contact.Options.TO);
271 this.setOption(Contact.Options.FROM);
272 this.resetOption(Contact.Options.PREEMPTIVE_GRANT);
273 } else if (subscription.equals("none")) {
274 this.resetOption(Contact.Options.FROM);
275 this.resetOption(Contact.Options.TO);
276 }
277 }
278
279 // do NOT override asking if pending push request
280 if (!this.getOption(Contact.Options.DIRTY_PUSH)) {
281 if ((ask != null) && (ask.equals("subscribe"))) {
282 this.setOption(Contact.Options.ASKING);
283 } else {
284 this.resetOption(Contact.Options.ASKING);
285 }
286 }
287 }
288
289 public Element asElement() {
290 Element item = new Element("item");
291 item.setAttribute("jid", this.jid);
292 if (this.serverName != null) {
293 item.setAttribute("name", this.serverName);
294 }
295 return item;
296 }
297
298 public class Options {
299 public static final int TO = 0;
300 public static final int FROM = 1;
301 public static final int ASKING = 2;
302 public static final int PREEMPTIVE_GRANT = 3;
303 public static final int IN_ROSTER = 4;
304 public static final int PENDING_SUBSCRIPTION_REQUEST = 5;
305 public static final int DIRTY_PUSH = 6;
306 public static final int DIRTY_DELETE = 7;
307 }
308
309 public class Lastseen {
310 public long time = 0;
311 public String presence = null;
312 }
313
314 @Override
315 public int compareTo(ListItem another) {
316 return this.getDisplayName().compareToIgnoreCase(
317 another.getDisplayName());
318 }
319
320 public String getServer() {
321 String[] split = getJid().split("@");
322 if (split.length >= 2) {
323 return split[1];
324 } else {
325 return null;
326 }
327 }
328
329 public boolean setAvatar(String filename) {
330 if (this.avatar != null && this.avatar.equals(filename)) {
331 return false;
332 } else {
333 this.avatar = filename;
334 return true;
335 }
336 }
337
338 public String getAvatar() {
339 return this.avatar;
340 }
341
342 public boolean deleteOtrFingerprint(String fingerprint) {
343 boolean success = false;
344 try {
345 if (this.keys.has("otr_fingerprints")) {
346 JSONArray newPrints = new JSONArray();
347 JSONArray oldPrints = this.keys
348 .getJSONArray("otr_fingerprints");
349 for (int i = 0; i < oldPrints.length(); ++i) {
350 if (!oldPrints.getString(i).equals(fingerprint)) {
351 newPrints.put(oldPrints.getString(i));
352 } else {
353 success = true;
354 }
355 }
356 this.keys.put("otr_fingerprints", newPrints);
357 }
358 return success;
359 } catch (JSONException e) {
360 return false;
361 }
362 }
363
364 public boolean trusted() {
365 return getOption(Options.FROM) && getOption(Options.TO);
366 }
367}