Account.java

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