1package eu.siacs.conversations.entities;
2
3import java.security.interfaces.DSAPublicKey;
4import java.util.List;
5import java.util.Locale;
6import java.util.concurrent.CopyOnWriteArrayList;
7
8import net.java.otr4j.crypto.OtrCryptoEngineImpl;
9import net.java.otr4j.crypto.OtrCryptoException;
10
11import org.json.JSONException;
12import org.json.JSONObject;
13
14import eu.siacs.conversations.R;
15import eu.siacs.conversations.crypto.OtrEngine;
16import eu.siacs.conversations.persistance.FileBackend;
17import eu.siacs.conversations.utils.UIHelper;
18import eu.siacs.conversations.xmpp.XmppConnection;
19import android.content.ContentValues;
20import android.content.Context;
21import android.database.Cursor;
22import android.graphics.Bitmap;
23
24public class Account extends AbstractEntity {
25
26 public static final String TABLENAME = "accounts";
27
28 public static final String USERNAME = "username";
29 public static final String SERVER = "server";
30 public static final String PASSWORD = "password";
31 public static final String OPTIONS = "options";
32 public static final String ROSTERVERSION = "rosterversion";
33 public static final String KEYS = "keys";
34 public static final String AVATAR = "avatar";
35
36 public static final int OPTION_USETLS = 0;
37 public static final int OPTION_DISABLED = 1;
38 public static final int OPTION_REGISTER = 2;
39 public static final int OPTION_USECOMPRESSION = 3;
40
41 public static final int STATUS_CONNECTING = 0;
42 public static final int STATUS_DISABLED = -2;
43 public static final int STATUS_OFFLINE = -1;
44 public static final int STATUS_ONLINE = 1;
45 public static final int STATUS_NO_INTERNET = 2;
46 public static final int STATUS_UNAUTHORIZED = 3;
47 public static final int STATUS_SERVER_NOT_FOUND = 5;
48
49 public static final int STATUS_REGISTRATION_FAILED = 7;
50 public static final int STATUS_REGISTRATION_CONFLICT = 8;
51 public static final int STATUS_REGISTRATION_SUCCESSFULL = 9;
52 public static final int STATUS_REGISTRATION_NOT_SUPPORTED = 10;
53
54 protected String username;
55 protected String server;
56 protected String password;
57 protected int options = 0;
58 protected String rosterVersion;
59 protected String resource = "mobile";
60 protected int status = -1;
61 protected JSONObject keys = new JSONObject();
62 protected String avatar;
63
64 protected boolean online = false;
65
66 transient OtrEngine otrEngine = null;
67 transient XmppConnection xmppConnection = null;
68 transient protected Presences presences = new Presences();
69
70 private String otrFingerprint;
71
72 private Roster roster = null;
73
74 private List<Bookmark> bookmarks = new CopyOnWriteArrayList<Bookmark>();
75
76 public List<Conversation> pendingConferenceJoins = new CopyOnWriteArrayList<Conversation>();
77 public List<Conversation> pendingConferenceLeaves = new CopyOnWriteArrayList<Conversation>();
78
79 public Account() {
80 this.uuid = "0";
81 }
82
83 public Account(String username, String server, String password) {
84 this(java.util.UUID.randomUUID().toString(), username, server,
85 password, 0, null, "",null);
86 }
87
88 public Account(String uuid, String username, String server,
89 String password, int options, String rosterVersion, String keys, String avatar) {
90 this.uuid = uuid;
91 this.username = username;
92 this.server = server;
93 this.password = password;
94 this.options = options;
95 this.rosterVersion = rosterVersion;
96 try {
97 this.keys = new JSONObject(keys);
98 } catch (JSONException e) {
99
100 }
101 this.avatar = avatar;
102 }
103
104 public boolean isOptionSet(int option) {
105 return ((options & (1 << option)) != 0);
106 }
107
108 public void setOption(int option, boolean value) {
109 if (value) {
110 this.options |= 1 << option;
111 } else {
112 this.options &= ~(1 << option);
113 }
114 }
115
116 public String getUsername() {
117 return username;
118 }
119
120 public void setUsername(String username) {
121 this.username = username;
122 }
123
124 public String getServer() {
125 return server;
126 }
127
128 public void setServer(String server) {
129 this.server = server;
130 }
131
132 public String getPassword() {
133 return password;
134 }
135
136 public void setPassword(String password) {
137 this.password = password;
138 }
139
140 public void setStatus(int status) {
141 this.status = status;
142 }
143
144 public int getStatus() {
145 if (isOptionSet(OPTION_DISABLED)) {
146 return STATUS_DISABLED;
147 } else {
148 return this.status;
149 }
150 }
151
152 public boolean errorStatus() {
153 int s = getStatus();
154 return (s == STATUS_REGISTRATION_FAILED || s == STATUS_REGISTRATION_CONFLICT || s == STATUS_REGISTRATION_NOT_SUPPORTED || s == STATUS_SERVER_NOT_FOUND || s == STATUS_UNAUTHORIZED);
155 }
156
157 public boolean hasErrorStatus() {
158 return getStatus() > STATUS_NO_INTERNET
159 && (getXmppConnection().getAttempt() >= 2);
160 }
161
162 public void setResource(String resource) {
163 this.resource = resource;
164 }
165
166 public String getResource() {
167 return this.resource;
168 }
169
170 public String getJid() {
171 return username.toLowerCase(Locale.getDefault()) + "@"
172 + server.toLowerCase(Locale.getDefault());
173 }
174
175 public JSONObject getKeys() {
176 return keys;
177 }
178
179 public String getSSLFingerprint() {
180 if (keys.has("ssl_cert")) {
181 try {
182 return keys.getString("ssl_cert");
183 } catch (JSONException e) {
184 return null;
185 }
186 } else {
187 return null;
188 }
189 }
190
191 public void setSSLCertFingerprint(String fingerprint) {
192 this.setKey("ssl_cert", fingerprint);
193 }
194
195 public boolean setKey(String keyName, String keyValue) {
196 try {
197 this.keys.put(keyName, keyValue);
198 return true;
199 } catch (JSONException e) {
200 return false;
201 }
202 }
203
204 @Override
205 public ContentValues getContentValues() {
206 ContentValues values = new ContentValues();
207 values.put(UUID, uuid);
208 values.put(USERNAME, username);
209 values.put(SERVER, server);
210 values.put(PASSWORD, password);
211 values.put(OPTIONS, options);
212 values.put(KEYS, this.keys.toString());
213 values.put(ROSTERVERSION, rosterVersion);
214 values.put(AVATAR, avatar);
215 return values;
216 }
217
218 public static Account fromCursor(Cursor cursor) {
219 return new Account(cursor.getString(cursor.getColumnIndex(UUID)),
220 cursor.getString(cursor.getColumnIndex(USERNAME)),
221 cursor.getString(cursor.getColumnIndex(SERVER)),
222 cursor.getString(cursor.getColumnIndex(PASSWORD)),
223 cursor.getInt(cursor.getColumnIndex(OPTIONS)),
224 cursor.getString(cursor.getColumnIndex(ROSTERVERSION)),
225 cursor.getString(cursor.getColumnIndex(KEYS)),
226 cursor.getString(cursor.getColumnIndex(AVATAR)));
227 }
228
229 public OtrEngine getOtrEngine(Context context) {
230 if (otrEngine == null) {
231 otrEngine = new OtrEngine(context, this);
232 }
233 return this.otrEngine;
234 }
235
236 public XmppConnection getXmppConnection() {
237 return this.xmppConnection;
238 }
239
240 public void setXmppConnection(XmppConnection connection) {
241 this.xmppConnection = connection;
242 }
243
244 public String getFullJid() {
245 return this.getJid() + "/" + this.resource;
246 }
247
248 public String getOtrFingerprint() {
249 if (this.otrFingerprint == null) {
250 try {
251 DSAPublicKey pubkey = (DSAPublicKey) this.otrEngine
252 .getPublicKey();
253 if (pubkey == null) {
254 return null;
255 }
256 StringBuilder builder = new StringBuilder(
257 new OtrCryptoEngineImpl().getFingerprint(pubkey));
258 builder.insert(8, " ");
259 builder.insert(17, " ");
260 builder.insert(26, " ");
261 builder.insert(35, " ");
262 this.otrFingerprint = builder.toString();
263 } catch (OtrCryptoException e) {
264
265 }
266 }
267 return this.otrFingerprint;
268 }
269
270 public String getRosterVersion() {
271 if (this.rosterVersion == null) {
272 return "";
273 } else {
274 return this.rosterVersion;
275 }
276 }
277
278 public void setRosterVersion(String version) {
279 this.rosterVersion = version;
280 }
281
282 public String getOtrFingerprint(Context applicationContext) {
283 this.getOtrEngine(applicationContext);
284 return this.getOtrFingerprint();
285 }
286
287 public void updatePresence(String resource, int status) {
288 this.presences.updatePresence(resource, status);
289 }
290
291 public void removePresence(String resource) {
292 this.presences.removePresence(resource);
293 }
294
295 public void clearPresences() {
296 this.presences = new Presences();
297 }
298
299 public int countPresences() {
300 return this.presences.size();
301 }
302
303 public String getPgpSignature() {
304 if (keys.has("pgp_signature")) {
305 try {
306 return keys.getString("pgp_signature");
307 } catch (JSONException e) {
308 return null;
309 }
310 } else {
311 return null;
312 }
313 }
314
315 public Roster getRoster() {
316 if (this.roster == null) {
317 this.roster = new Roster(this);
318 }
319 return this.roster;
320 }
321
322 public void setBookmarks(List<Bookmark> bookmarks) {
323 this.bookmarks = bookmarks;
324 }
325
326 public List<Bookmark> getBookmarks() {
327 return this.bookmarks;
328 }
329
330 public boolean hasBookmarkFor(String conferenceJid) {
331 for (Bookmark bmark : this.bookmarks) {
332 if (bmark.getJid().equals(conferenceJid)) {
333 return true;
334 }
335 }
336 return false;
337 }
338
339 public Bitmap getImage(Context context, int size) {
340 if (this.avatar != null) {
341 Bitmap bm = FileBackend.getAvatar(this.avatar, size, context);
342 if (bm == null) {
343 return UIHelper.getContactPicture(getJid(), size, context,
344 false);
345 } else {
346 return bm;
347 }
348 } else {
349 return UIHelper.getContactPicture(getJid(), size, context, false);
350 }
351 }
352
353 public boolean setAvatar(String filename) {
354 if (this.avatar != null && this.avatar.equals(filename)) {
355 return false;
356 } else {
357 this.avatar = filename;
358 return true;
359 }
360 }
361
362 public String getAvatar() {
363 return this.avatar;
364 }
365
366 public int getReadableStatusId() {
367 switch (getStatus()) {
368
369 case Account.STATUS_DISABLED:
370 return R.string.account_status_disabled;
371 case Account.STATUS_ONLINE:
372 return R.string.account_status_online;
373 case Account.STATUS_CONNECTING:
374 return R.string.account_status_connecting;
375 case Account.STATUS_OFFLINE:
376 return R.string.account_status_offline;
377 case Account.STATUS_UNAUTHORIZED:
378 return R.string.account_status_unauthorized;
379 case Account.STATUS_SERVER_NOT_FOUND:
380 return R.string.account_status_not_found;
381 case Account.STATUS_NO_INTERNET:
382 return R.string.account_status_no_internet;
383 case Account.STATUS_REGISTRATION_FAILED:
384 return R.string.account_status_regis_fail;
385 case Account.STATUS_REGISTRATION_CONFLICT:
386 return R.string.account_status_regis_conflict;
387 case Account.STATUS_REGISTRATION_SUCCESSFULL:
388 return R.string.account_status_regis_success;
389 case Account.STATUS_REGISTRATION_NOT_SUPPORTED:
390 return R.string.account_status_regis_not_sup;
391 default:
392 return R.string.account_status_unknown;
393 }
394 }
395}