From 94933e21cd08c53a23e5ec6c12bc1dc383b1f3ce Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Fri, 29 Jul 2016 19:52:37 +0200 Subject: changed package id inside manifest and project --- .../conversations/persistance/DatabaseBackend.java | 1196 -------------------- .../conversations/persistance/FileBackend.java | 893 --------------- .../persistance/OnPhoneContactsMerged.java | 5 - 3 files changed, 2094 deletions(-) delete mode 100644 src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java delete mode 100644 src/main/java/eu/siacs/conversations/persistance/FileBackend.java delete mode 100644 src/main/java/eu/siacs/conversations/persistance/OnPhoneContactsMerged.java (limited to 'src/main/java/eu/siacs/conversations/persistance') diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java deleted file mode 100644 index 2c1449122..000000000 --- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java +++ /dev/null @@ -1,1196 +0,0 @@ -package eu.siacs.conversations.persistance; - -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.database.DatabaseUtils; -import android.database.sqlite.SQLiteCantOpenDatabaseException; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.util.Base64; -import android.util.Log; -import android.util.Pair; - -import org.json.JSONException; -import org.whispersystems.libaxolotl.AxolotlAddress; -import org.whispersystems.libaxolotl.IdentityKey; -import org.whispersystems.libaxolotl.IdentityKeyPair; -import org.whispersystems.libaxolotl.InvalidKeyException; -import org.whispersystems.libaxolotl.state.PreKeyRecord; -import org.whispersystems.libaxolotl.state.SessionRecord; -import org.whispersystems.libaxolotl.state.SignedPreKeyRecord; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArrayList; - -import eu.siacs.conversations.Config; -import eu.siacs.conversations.crypto.axolotl.AxolotlService; -import eu.siacs.conversations.crypto.axolotl.SQLiteAxolotlStore; -import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession; -import eu.siacs.conversations.entities.Account; -import eu.siacs.conversations.entities.Contact; -import eu.siacs.conversations.entities.Conversation; -import eu.siacs.conversations.entities.Message; -import eu.siacs.conversations.entities.PresenceTemplate; -import eu.siacs.conversations.entities.Roster; -import eu.siacs.conversations.entities.ServiceDiscoveryResult; -import eu.siacs.conversations.xmpp.jid.InvalidJidException; -import eu.siacs.conversations.xmpp.jid.Jid; - -public class DatabaseBackend extends SQLiteOpenHelper { - - private static DatabaseBackend instance = null; - - public static final String DATABASE_NAME = "history"; - public static final int DATABASE_VERSION = 27; - - private static String CREATE_CONTATCS_STATEMENT = "create table " - + Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, " - + Contact.SERVERNAME + " TEXT, " + Contact.SYSTEMNAME + " TEXT," - + Contact.JID + " TEXT," + Contact.KEYS + " TEXT," - + Contact.PHOTOURI + " TEXT," + Contact.OPTIONS + " NUMBER," - + Contact.SYSTEMACCOUNT + " NUMBER, " + Contact.AVATAR + " TEXT, " - + Contact.LAST_PRESENCE + " TEXT, " + Contact.LAST_TIME + " NUMBER, " - + Contact.GROUPS + " TEXT, FOREIGN KEY(" + Contact.ACCOUNT + ") REFERENCES " - + Account.TABLENAME + "(" + Account.UUID - + ") ON DELETE CASCADE, UNIQUE(" + Contact.ACCOUNT + ", " - + Contact.JID + ") ON CONFLICT REPLACE);"; - - private static String CREATE_DISCOVERY_RESULTS_STATEMENT = "create table " - + ServiceDiscoveryResult.TABLENAME + "(" - + ServiceDiscoveryResult.HASH + " TEXT, " - + ServiceDiscoveryResult.VER + " TEXT, " - + ServiceDiscoveryResult.RESULT + " TEXT, " - + "UNIQUE(" + ServiceDiscoveryResult.HASH + ", " - + ServiceDiscoveryResult.VER + ") ON CONFLICT REPLACE);"; - - private static String CREATE_PRESENCE_TEMPLATES_STATEMENT = "CREATE TABLE " - + PresenceTemplate.TABELNAME + "(" - + PresenceTemplate.UUID + " TEXT, " - + PresenceTemplate.LAST_USED + " NUMBER," - + PresenceTemplate.MESSAGE + " TEXT," - + PresenceTemplate.STATUS + " TEXT," - + "UNIQUE("+PresenceTemplate.MESSAGE + "," +PresenceTemplate.STATUS+") ON CONFLICT REPLACE);"; - - private static String CREATE_PREKEYS_STATEMENT = "CREATE TABLE " - + SQLiteAxolotlStore.PREKEY_TABLENAME + "(" - + SQLiteAxolotlStore.ACCOUNT + " TEXT, " - + SQLiteAxolotlStore.ID + " INTEGER, " - + SQLiteAxolotlStore.KEY + " TEXT, FOREIGN KEY(" - + SQLiteAxolotlStore.ACCOUNT - + ") REFERENCES " + Account.TABLENAME + "(" + Account.UUID + ") ON DELETE CASCADE, " - + "UNIQUE( " + SQLiteAxolotlStore.ACCOUNT + ", " - + SQLiteAxolotlStore.ID - + ") ON CONFLICT REPLACE" - + ");"; - - private static String CREATE_SIGNED_PREKEYS_STATEMENT = "CREATE TABLE " - + SQLiteAxolotlStore.SIGNED_PREKEY_TABLENAME + "(" - + SQLiteAxolotlStore.ACCOUNT + " TEXT, " - + SQLiteAxolotlStore.ID + " INTEGER, " - + SQLiteAxolotlStore.KEY + " TEXT, FOREIGN KEY(" - + SQLiteAxolotlStore.ACCOUNT - + ") REFERENCES " + Account.TABLENAME + "(" + Account.UUID + ") ON DELETE CASCADE, " - + "UNIQUE( " + SQLiteAxolotlStore.ACCOUNT + ", " - + SQLiteAxolotlStore.ID - + ") ON CONFLICT REPLACE" + - ");"; - - private static String CREATE_SESSIONS_STATEMENT = "CREATE TABLE " - + SQLiteAxolotlStore.SESSION_TABLENAME + "(" - + SQLiteAxolotlStore.ACCOUNT + " TEXT, " - + SQLiteAxolotlStore.NAME + " TEXT, " - + SQLiteAxolotlStore.DEVICE_ID + " INTEGER, " - + SQLiteAxolotlStore.KEY + " TEXT, FOREIGN KEY(" - + SQLiteAxolotlStore.ACCOUNT - + ") REFERENCES " + Account.TABLENAME + "(" + Account.UUID + ") ON DELETE CASCADE, " - + "UNIQUE( " + SQLiteAxolotlStore.ACCOUNT + ", " - + SQLiteAxolotlStore.NAME + ", " - + SQLiteAxolotlStore.DEVICE_ID - + ") ON CONFLICT REPLACE" - + ");"; - - private static String CREATE_IDENTITIES_STATEMENT = "CREATE TABLE " - + SQLiteAxolotlStore.IDENTITIES_TABLENAME + "(" - + SQLiteAxolotlStore.ACCOUNT + " TEXT, " - + SQLiteAxolotlStore.NAME + " TEXT, " - + SQLiteAxolotlStore.OWN + " INTEGER, " - + SQLiteAxolotlStore.FINGERPRINT + " TEXT, " - + SQLiteAxolotlStore.CERTIFICATE + " BLOB, " - + SQLiteAxolotlStore.TRUSTED + " INTEGER, " - + SQLiteAxolotlStore.KEY + " TEXT, FOREIGN KEY(" - + SQLiteAxolotlStore.ACCOUNT - + ") REFERENCES " + Account.TABLENAME + "(" + Account.UUID + ") ON DELETE CASCADE, " - + "UNIQUE( " + SQLiteAxolotlStore.ACCOUNT + ", " - + SQLiteAxolotlStore.NAME + ", " - + SQLiteAxolotlStore.FINGERPRINT - + ") ON CONFLICT IGNORE" - + ");"; - - private DatabaseBackend(Context context) { - super(context, DATABASE_NAME, null, DATABASE_VERSION); - } - - @Override - public void onCreate(SQLiteDatabase db) { - db.execSQL("PRAGMA foreign_keys=ON;"); - db.execSQL("create table " + Account.TABLENAME + "(" + Account.UUID+ " TEXT PRIMARY KEY," - + Account.USERNAME + " TEXT," - + Account.SERVER + " TEXT," - + Account.PASSWORD + " TEXT," - + Account.DISPLAY_NAME + " TEXT, " - + Account.STATUS + " TEXT," - + Account.STATUS_MESSAGE + " TEXT," - + Account.ROSTERVERSION + " TEXT," - + Account.OPTIONS + " NUMBER, " - + Account.AVATAR + " TEXT, " - + Account.KEYS + " TEXT, " - + Account.HOSTNAME + " TEXT, " - + Account.PORT + " NUMBER DEFAULT 5222)"); - db.execSQL("create table " + Conversation.TABLENAME + " (" - + Conversation.UUID + " TEXT PRIMARY KEY, " + Conversation.NAME - + " TEXT, " + Conversation.CONTACT + " TEXT, " - + Conversation.ACCOUNT + " TEXT, " + Conversation.CONTACTJID - + " TEXT, " + Conversation.CREATED + " NUMBER, " - + Conversation.STATUS + " NUMBER, " + Conversation.MODE - + " NUMBER, " + Conversation.ATTRIBUTES + " TEXT, FOREIGN KEY(" - + Conversation.ACCOUNT + ") REFERENCES " + Account.TABLENAME - + "(" + Account.UUID + ") ON DELETE CASCADE);"); - db.execSQL("create table " + Message.TABLENAME + "( " + Message.UUID - + " TEXT PRIMARY KEY, " + Message.CONVERSATION + " TEXT, " - + Message.TIME_SENT + " NUMBER, " + Message.COUNTERPART - + " TEXT, " + Message.TRUE_COUNTERPART + " TEXT," - + Message.BODY + " TEXT, " + Message.ENCRYPTION + " NUMBER, " - + Message.STATUS + " NUMBER," + Message.TYPE + " NUMBER, " - + Message.RELATIVE_FILE_PATH + " TEXT, " - + Message.SERVER_MSG_ID + " TEXT, " - + Message.FINGERPRINT + " TEXT, " - + Message.CARBON + " INTEGER, " - + Message.EDITED + " TEXT, " - + Message.READ + " NUMBER DEFAULT 1, " - + Message.OOB + " INTEGER, " - + Message.REMOTE_MSG_ID + " TEXT, FOREIGN KEY(" - + Message.CONVERSATION + ") REFERENCES " - + Conversation.TABLENAME + "(" + Conversation.UUID - + ") ON DELETE CASCADE);"); - - db.execSQL(CREATE_CONTATCS_STATEMENT); - db.execSQL(CREATE_DISCOVERY_RESULTS_STATEMENT); - db.execSQL(CREATE_SESSIONS_STATEMENT); - db.execSQL(CREATE_PREKEYS_STATEMENT); - db.execSQL(CREATE_SIGNED_PREKEYS_STATEMENT); - db.execSQL(CREATE_IDENTITIES_STATEMENT); - db.execSQL(CREATE_PRESENCE_TEMPLATES_STATEMENT); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - if (oldVersion < 2 && newVersion >= 2) { - db.execSQL("update " + Account.TABLENAME + " set " - + Account.OPTIONS + " = " + Account.OPTIONS + " | 8"); - } - if (oldVersion < 3 && newVersion >= 3) { - db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN " - + Message.TYPE + " NUMBER"); - } - if (oldVersion < 5 && newVersion >= 5) { - db.execSQL("DROP TABLE " + Contact.TABLENAME); - db.execSQL(CREATE_CONTATCS_STATEMENT); - db.execSQL("UPDATE " + Account.TABLENAME + " SET " - + Account.ROSTERVERSION + " = NULL"); - } - if (oldVersion < 6 && newVersion >= 6) { - db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN " - + Message.TRUE_COUNTERPART + " TEXT"); - } - if (oldVersion < 7 && newVersion >= 7) { - db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN " - + Message.REMOTE_MSG_ID + " TEXT"); - db.execSQL("ALTER TABLE " + Contact.TABLENAME + " ADD COLUMN " - + Contact.AVATAR + " TEXT"); - db.execSQL("ALTER TABLE " + Account.TABLENAME + " ADD COLUMN " - + Account.AVATAR + " TEXT"); - } - if (oldVersion < 8 && newVersion >= 8) { - db.execSQL("ALTER TABLE " + Conversation.TABLENAME + " ADD COLUMN " - + Conversation.ATTRIBUTES + " TEXT"); - } - if (oldVersion < 9 && newVersion >= 9) { - db.execSQL("ALTER TABLE " + Contact.TABLENAME + " ADD COLUMN " - + Contact.LAST_TIME + " NUMBER"); - db.execSQL("ALTER TABLE " + Contact.TABLENAME + " ADD COLUMN " - + Contact.LAST_PRESENCE + " TEXT"); - } - if (oldVersion < 10 && newVersion >= 10) { - db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN " - + Message.RELATIVE_FILE_PATH + " TEXT"); - } - if (oldVersion < 11 && newVersion >= 11) { - db.execSQL("ALTER TABLE " + Contact.TABLENAME + " ADD COLUMN " - + Contact.GROUPS + " TEXT"); - db.execSQL("delete from " + Contact.TABLENAME); - db.execSQL("update " + Account.TABLENAME + " set " + Account.ROSTERVERSION + " = NULL"); - } - if (oldVersion < 12 && newVersion >= 12) { - db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN " - + Message.SERVER_MSG_ID + " TEXT"); - } - if (oldVersion < 13 && newVersion >= 13) { - db.execSQL("delete from " + Contact.TABLENAME); - db.execSQL("update " + Account.TABLENAME + " set " + Account.ROSTERVERSION + " = NULL"); - } - if (oldVersion < 14 && newVersion >= 14) { - // migrate db to new, canonicalized JID domainpart representation - - // Conversation table - Cursor cursor = db.rawQuery("select * from " + Conversation.TABLENAME, new String[0]); - while (cursor.moveToNext()) { - String newJid; - try { - newJid = Jid.fromString( - cursor.getString(cursor.getColumnIndex(Conversation.CONTACTJID)) - ).toString(); - } catch (InvalidJidException ignored) { - Log.e(Config.LOGTAG, "Failed to migrate Conversation CONTACTJID " - + cursor.getString(cursor.getColumnIndex(Conversation.CONTACTJID)) - + ": " + ignored + ". Skipping..."); - continue; - } - - String updateArgs[] = { - newJid, - cursor.getString(cursor.getColumnIndex(Conversation.UUID)), - }; - db.execSQL("update " + Conversation.TABLENAME - + " set " + Conversation.CONTACTJID + " = ? " - + " where " + Conversation.UUID + " = ?", updateArgs); - } - cursor.close(); - - // Contact table - cursor = db.rawQuery("select * from " + Contact.TABLENAME, new String[0]); - while (cursor.moveToNext()) { - String newJid; - try { - newJid = Jid.fromString( - cursor.getString(cursor.getColumnIndex(Contact.JID)) - ).toString(); - } catch (InvalidJidException ignored) { - Log.e(Config.LOGTAG, "Failed to migrate Contact JID " - + cursor.getString(cursor.getColumnIndex(Contact.JID)) - + ": " + ignored + ". Skipping..."); - continue; - } - - String updateArgs[] = { - newJid, - cursor.getString(cursor.getColumnIndex(Contact.ACCOUNT)), - cursor.getString(cursor.getColumnIndex(Contact.JID)), - }; - db.execSQL("update " + Contact.TABLENAME - + " set " + Contact.JID + " = ? " - + " where " + Contact.ACCOUNT + " = ? " - + " AND " + Contact.JID + " = ?", updateArgs); - } - cursor.close(); - - // Account table - cursor = db.rawQuery("select * from " + Account.TABLENAME, new String[0]); - while (cursor.moveToNext()) { - String newServer; - try { - newServer = Jid.fromParts( - cursor.getString(cursor.getColumnIndex(Account.USERNAME)), - cursor.getString(cursor.getColumnIndex(Account.SERVER)), - "mobile" - ).getDomainpart(); - } catch (InvalidJidException ignored) { - Log.e(Config.LOGTAG, "Failed to migrate Account SERVER " - + cursor.getString(cursor.getColumnIndex(Account.SERVER)) - + ": " + ignored + ". Skipping..."); - continue; - } - - String updateArgs[] = { - newServer, - cursor.getString(cursor.getColumnIndex(Account.UUID)), - }; - db.execSQL("update " + Account.TABLENAME - + " set " + Account.SERVER + " = ? " - + " where " + Account.UUID + " = ?", updateArgs); - } - cursor.close(); - } - if (oldVersion < 15 && newVersion >= 15) { - recreateAxolotlDb(db); - db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN " - + Message.FINGERPRINT + " TEXT"); - } else if (oldVersion < 22 && newVersion >= 22) { - db.execSQL("ALTER TABLE " + SQLiteAxolotlStore.IDENTITIES_TABLENAME + " ADD COLUMN " + SQLiteAxolotlStore.CERTIFICATE); - } - if (oldVersion < 16 && newVersion >= 16) { - db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN " - + Message.CARBON + " INTEGER"); - } - if (oldVersion < 19 && newVersion >= 19) { - db.execSQL("ALTER TABLE " + Account.TABLENAME + " ADD COLUMN " + Account.DISPLAY_NAME + " TEXT"); - } - if (oldVersion < 20 && newVersion >= 20) { - db.execSQL("ALTER TABLE " + Account.TABLENAME + " ADD COLUMN " + Account.HOSTNAME + " TEXT"); - db.execSQL("ALTER TABLE " + Account.TABLENAME + " ADD COLUMN " + Account.PORT + " NUMBER DEFAULT 5222"); - } - if (oldVersion < 26 && newVersion >= 26) { - db.execSQL("ALTER TABLE " + Account.TABLENAME + " ADD COLUMN " + Account.STATUS + " TEXT"); - db.execSQL("ALTER TABLE " + Account.TABLENAME + " ADD COLUMN " + Account.STATUS_MESSAGE + " TEXT"); - } - /* Any migrations that alter the Account table need to happen BEFORE this migration, as it - * depends on account de-serialization. - */ - if (oldVersion < 17 && newVersion >= 17) { - List accounts = getAccounts(db); - for (Account account : accounts) { - String ownDeviceIdString = account.getKey(SQLiteAxolotlStore.JSONKEY_REGISTRATION_ID); - if (ownDeviceIdString == null) { - continue; - } - int ownDeviceId = Integer.valueOf(ownDeviceIdString); - AxolotlAddress ownAddress = new AxolotlAddress(account.getJid().toBareJid().toString(), ownDeviceId); - deleteSession(db, account, ownAddress); - IdentityKeyPair identityKeyPair = loadOwnIdentityKeyPair(db, account); - if (identityKeyPair != null) { - setIdentityKeyTrust(db, account, identityKeyPair.getPublicKey().getFingerprint().replaceAll("\\s", ""), XmppAxolotlSession.Trust.TRUSTED); - } else { - Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not load own identity key pair"); - } - } - } - if (oldVersion < 18 && newVersion >= 18) { - db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN " + Message.READ + " NUMBER DEFAULT 1"); - } - - if (oldVersion < 21 && newVersion >= 21) { - List accounts = getAccounts(db); - for (Account account : accounts) { - account.unsetPgpSignature(); - db.update(Account.TABLENAME, account.getContentValues(), Account.UUID - + "=?", new String[]{account.getUuid()}); - } - } - - if (oldVersion < 23 && newVersion >= 23) { - db.execSQL(CREATE_DISCOVERY_RESULTS_STATEMENT); - } - - if (oldVersion < 24 && newVersion >= 24) { - db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN " + Message.EDITED + " TEXT"); - } - - if (oldVersion < 25 && newVersion >= 25) { - db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN " + Message.OOB + " INTEGER"); - } - - if (oldVersion < 26 && newVersion >= 26) { - db.execSQL(CREATE_PRESENCE_TEMPLATES_STATEMENT); - } - - if (oldVersion < 27 && newVersion >= 27) { - db.execSQL("DELETE FROM "+ServiceDiscoveryResult.TABLENAME); - } - } - - public static synchronized DatabaseBackend getInstance(Context context) { - if (instance == null) { - instance = new DatabaseBackend(context); - } - return instance; - } - - public void createConversation(Conversation conversation) { - SQLiteDatabase db = this.getWritableDatabase(); - db.insert(Conversation.TABLENAME, null, conversation.getContentValues()); - } - - public void createMessage(Message message) { - SQLiteDatabase db = this.getWritableDatabase(); - db.insert(Message.TABLENAME, null, message.getContentValues()); - } - - public void createAccount(Account account) { - SQLiteDatabase db = this.getWritableDatabase(); - db.insert(Account.TABLENAME, null, account.getContentValues()); - } - - public void insertDiscoveryResult(ServiceDiscoveryResult result) { - SQLiteDatabase db = this.getWritableDatabase(); - db.insert(ServiceDiscoveryResult.TABLENAME, null, result.getContentValues()); - } - - public ServiceDiscoveryResult findDiscoveryResult(final String hash, final String ver) { - SQLiteDatabase db = this.getReadableDatabase(); - String[] selectionArgs = {hash, ver}; - Cursor cursor = db.query(ServiceDiscoveryResult.TABLENAME, null, - ServiceDiscoveryResult.HASH + "=? AND " + ServiceDiscoveryResult.VER + "=?", - selectionArgs, null, null, null); - if (cursor.getCount() == 0) { - cursor.close(); - return null; - } - cursor.moveToFirst(); - - ServiceDiscoveryResult result = null; - try { - result = new ServiceDiscoveryResult(cursor); - } catch (JSONException e) { /* result is still null */ } - - cursor.close(); - return result; - } - - public void insertPresenceTemplate(PresenceTemplate template) { - SQLiteDatabase db = this.getWritableDatabase(); - db.insert(PresenceTemplate.TABELNAME, null, template.getContentValues()); - } - - public List getPresenceTemplates() { - ArrayList templates = new ArrayList<>(); - SQLiteDatabase db = this.getReadableDatabase(); - Cursor cursor = db.query(PresenceTemplate.TABELNAME,null,null,null,null,null,PresenceTemplate.LAST_USED+" desc"); - while (cursor.moveToNext()) { - templates.add(PresenceTemplate.fromCursor(cursor)); - } - cursor.close(); - return templates; - } - - public void deletePresenceTemplate(PresenceTemplate template) { - Log.d(Config.LOGTAG,"deleting presence template with uuid "+template.getUuid()); - SQLiteDatabase db = this.getWritableDatabase(); - String where = PresenceTemplate.UUID+"=?"; - String[] whereArgs = {template.getUuid()}; - db.delete(PresenceTemplate.TABELNAME,where,whereArgs); - } - - public CopyOnWriteArrayList getConversations(int status) { - CopyOnWriteArrayList list = new CopyOnWriteArrayList<>(); - SQLiteDatabase db = this.getReadableDatabase(); - String[] selectionArgs = {Integer.toString(status)}; - Cursor cursor = db.rawQuery("select * from " + Conversation.TABLENAME - + " where " + Conversation.STATUS + " = ? order by " - + Conversation.CREATED + " desc", selectionArgs); - while (cursor.moveToNext()) { - list.add(Conversation.fromCursor(cursor)); - } - cursor.close(); - return list; - } - - public ArrayList getMessages(Conversation conversations, int limit) { - return getMessages(conversations, limit, -1); - } - - public ArrayList getMessages(Conversation conversation, int limit, - long timestamp) { - ArrayList list = new ArrayList<>(); - SQLiteDatabase db = this.getReadableDatabase(); - Cursor cursor; - if (timestamp == -1) { - String[] selectionArgs = {conversation.getUuid()}; - cursor = db.query(Message.TABLENAME, null, Message.CONVERSATION - + "=?", selectionArgs, null, null, Message.TIME_SENT - + " DESC", String.valueOf(limit)); - } else { - String[] selectionArgs = {conversation.getUuid(), - Long.toString(timestamp)}; - cursor = db.query(Message.TABLENAME, null, Message.CONVERSATION - + "=? and " + Message.TIME_SENT + " 0) { - cursor.moveToLast(); - do { - Message message = Message.fromCursor(cursor); - message.setConversation(conversation); - list.add(message); - } while (cursor.moveToPrevious()); - } - cursor.close(); - return list; - } - - public Iterable getMessagesIterable(final Conversation conversation) { - return new Iterable() { - @Override - public Iterator iterator() { - class MessageIterator implements Iterator { - SQLiteDatabase db = getReadableDatabase(); - String[] selectionArgs = {conversation.getUuid()}; - Cursor cursor = db.query(Message.TABLENAME, null, Message.CONVERSATION - + "=?", selectionArgs, null, null, Message.TIME_SENT - + " ASC", null); - - public MessageIterator() { - cursor.moveToFirst(); - } - - @Override - public boolean hasNext() { - return !cursor.isAfterLast(); - } - - @Override - public Message next() { - Message message = Message.fromCursor(cursor); - cursor.moveToNext(); - return message; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - return new MessageIterator(); - } - }; - } - - public Conversation findConversation(final Account account, final Jid contactJid) { - SQLiteDatabase db = this.getReadableDatabase(); - String[] selectionArgs = {account.getUuid(), - contactJid.toBareJid().toString() + "/%", - contactJid.toBareJid().toString() - }; - Cursor cursor = db.query(Conversation.TABLENAME, null, - Conversation.ACCOUNT + "=? AND (" + Conversation.CONTACTJID - + " like ? OR " + Conversation.CONTACTJID + "=?)", selectionArgs, null, null, null); - if (cursor.getCount() == 0) { - cursor.close(); - return null; - } - cursor.moveToFirst(); - Conversation conversation = Conversation.fromCursor(cursor); - cursor.close(); - return conversation; - } - - public void updateConversation(final Conversation conversation) { - final SQLiteDatabase db = this.getWritableDatabase(); - final String[] args = {conversation.getUuid()}; - db.update(Conversation.TABLENAME, conversation.getContentValues(), - Conversation.UUID + "=?", args); - } - - public List getAccounts() { - SQLiteDatabase db = this.getReadableDatabase(); - return getAccounts(db); - } - - private List getAccounts(SQLiteDatabase db) { - List list = new ArrayList<>(); - Cursor cursor = db.query(Account.TABLENAME, null, null, null, null, - null, null); - while (cursor.moveToNext()) { - list.add(Account.fromCursor(cursor)); - } - cursor.close(); - return list; - } - - public void updateAccount(Account account) { - SQLiteDatabase db = this.getWritableDatabase(); - String[] args = {account.getUuid()}; - db.update(Account.TABLENAME, account.getContentValues(), Account.UUID - + "=?", args); - } - - public void deleteAccount(Account account) { - SQLiteDatabase db = this.getWritableDatabase(); - String[] args = {account.getUuid()}; - db.delete(Account.TABLENAME, Account.UUID + "=?", args); - } - - public boolean hasEnabledAccounts() { - SQLiteDatabase db = this.getReadableDatabase(); - Cursor cursor = db.rawQuery("select count(" + Account.UUID + ") from " - + Account.TABLENAME + " where not options & (1 <<1)", null); - try { - cursor.moveToFirst(); - int count = cursor.getInt(0); - return (count > 0); - } catch (SQLiteCantOpenDatabaseException e) { - return true; // better safe than sorry - } catch (RuntimeException e) { - return true; // better safe than sorry - } finally { - if (cursor != null) { - cursor.close(); - } - } - } - - @Override - public SQLiteDatabase getWritableDatabase() { - SQLiteDatabase db = super.getWritableDatabase(); - db.execSQL("PRAGMA foreign_keys=ON;"); - return db; - } - - public void updateMessage(Message message) { - SQLiteDatabase db = this.getWritableDatabase(); - String[] args = {message.getUuid()}; - db.update(Message.TABLENAME, message.getContentValues(), Message.UUID - + "=?", args); - } - - public void updateMessage(Message message, String uuid) { - SQLiteDatabase db = this.getWritableDatabase(); - String[] args = {uuid}; - db.update(Message.TABLENAME, message.getContentValues(), Message.UUID - + "=?", args); - } - - public void readRoster(Roster roster) { - SQLiteDatabase db = this.getReadableDatabase(); - Cursor cursor; - String args[] = {roster.getAccount().getUuid()}; - cursor = db.query(Contact.TABLENAME, null, Contact.ACCOUNT + "=?", args, null, null, null); - while (cursor.moveToNext()) { - roster.initContact(Contact.fromCursor(cursor)); - } - cursor.close(); - } - - public void writeRoster(final Roster roster) { - final Account account = roster.getAccount(); - final SQLiteDatabase db = this.getWritableDatabase(); - db.beginTransaction(); - for (Contact contact : roster.getContacts()) { - if (contact.getOption(Contact.Options.IN_ROSTER)) { - db.insert(Contact.TABLENAME, null, contact.getContentValues()); - } else { - String where = Contact.ACCOUNT + "=? AND " + Contact.JID + "=?"; - String[] whereArgs = {account.getUuid(), contact.getJid().toString()}; - db.delete(Contact.TABLENAME, where, whereArgs); - } - } - db.setTransactionSuccessful(); - db.endTransaction(); - account.setRosterVersion(roster.getVersion()); - updateAccount(account); - } - - public void deleteMessagesInConversation(Conversation conversation) { - SQLiteDatabase db = this.getWritableDatabase(); - String[] args = {conversation.getUuid()}; - db.delete(Message.TABLENAME, Message.CONVERSATION + "=?", args); - } - - public Pair getLastMessageReceived(Account account) { - Cursor cursor = null; - try { - SQLiteDatabase db = this.getReadableDatabase(); - String sql = "select messages.timeSent,messages.serverMsgId from accounts join conversations on accounts.uuid=conversations.accountUuid join messages on conversations.uuid=messages.conversationUuid where accounts.uuid=? and (messages.status=0 or messages.carbon=1 or messages.serverMsgId not null) order by messages.timesent desc limit 1"; - String[] args = {account.getUuid()}; - cursor = db.rawQuery(sql, args); - if (cursor.getCount() == 0) { - return null; - } else { - cursor.moveToFirst(); - return new Pair<>(cursor.getLong(0), cursor.getString(1)); - } - } catch (Exception e) { - return null; - } finally { - if (cursor != null) { - cursor.close(); - } - } - } - - private Cursor getCursorForSession(Account account, AxolotlAddress contact) { - final SQLiteDatabase db = this.getReadableDatabase(); - String[] columns = null; - String[] selectionArgs = {account.getUuid(), - contact.getName(), - Integer.toString(contact.getDeviceId())}; - Cursor cursor = db.query(SQLiteAxolotlStore.SESSION_TABLENAME, - columns, - SQLiteAxolotlStore.ACCOUNT + " = ? AND " - + SQLiteAxolotlStore.NAME + " = ? AND " - + SQLiteAxolotlStore.DEVICE_ID + " = ? ", - selectionArgs, - null, null, null); - - return cursor; - } - - public SessionRecord loadSession(Account account, AxolotlAddress contact) { - SessionRecord session = null; - Cursor cursor = getCursorForSession(account, contact); - if (cursor.getCount() != 0) { - cursor.moveToFirst(); - try { - session = new SessionRecord(Base64.decode(cursor.getString(cursor.getColumnIndex(SQLiteAxolotlStore.KEY)), Base64.DEFAULT)); - } catch (IOException e) { - cursor.close(); - throw new AssertionError(e); - } - } - cursor.close(); - return session; - } - - public List getSubDeviceSessions(Account account, AxolotlAddress contact) { - final SQLiteDatabase db = this.getReadableDatabase(); - return getSubDeviceSessions(db, account, contact); - } - - private List getSubDeviceSessions(SQLiteDatabase db, Account account, AxolotlAddress contact) { - List devices = new ArrayList<>(); - String[] columns = {SQLiteAxolotlStore.DEVICE_ID}; - String[] selectionArgs = {account.getUuid(), - contact.getName()}; - Cursor cursor = db.query(SQLiteAxolotlStore.SESSION_TABLENAME, - columns, - SQLiteAxolotlStore.ACCOUNT + " = ? AND " - + SQLiteAxolotlStore.NAME + " = ?", - selectionArgs, - null, null, null); - - while (cursor.moveToNext()) { - devices.add(cursor.getInt( - cursor.getColumnIndex(SQLiteAxolotlStore.DEVICE_ID))); - } - - cursor.close(); - return devices; - } - - public boolean containsSession(Account account, AxolotlAddress contact) { - Cursor cursor = getCursorForSession(account, contact); - int count = cursor.getCount(); - cursor.close(); - return count != 0; - } - - public void storeSession(Account account, AxolotlAddress contact, SessionRecord session) { - SQLiteDatabase db = this.getWritableDatabase(); - ContentValues values = new ContentValues(); - values.put(SQLiteAxolotlStore.NAME, contact.getName()); - values.put(SQLiteAxolotlStore.DEVICE_ID, contact.getDeviceId()); - values.put(SQLiteAxolotlStore.KEY, Base64.encodeToString(session.serialize(), Base64.DEFAULT)); - values.put(SQLiteAxolotlStore.ACCOUNT, account.getUuid()); - db.insert(SQLiteAxolotlStore.SESSION_TABLENAME, null, values); - } - - public void deleteSession(Account account, AxolotlAddress contact) { - SQLiteDatabase db = this.getWritableDatabase(); - deleteSession(db, account, contact); - } - - private void deleteSession(SQLiteDatabase db, Account account, AxolotlAddress contact) { - String[] args = {account.getUuid(), - contact.getName(), - Integer.toString(contact.getDeviceId())}; - db.delete(SQLiteAxolotlStore.SESSION_TABLENAME, - SQLiteAxolotlStore.ACCOUNT + " = ? AND " - + SQLiteAxolotlStore.NAME + " = ? AND " - + SQLiteAxolotlStore.DEVICE_ID + " = ? ", - args); - } - - public void deleteAllSessions(Account account, AxolotlAddress contact) { - SQLiteDatabase db = this.getWritableDatabase(); - String[] args = {account.getUuid(), contact.getName()}; - db.delete(SQLiteAxolotlStore.SESSION_TABLENAME, - SQLiteAxolotlStore.ACCOUNT + "=? AND " - + SQLiteAxolotlStore.NAME + " = ?", - args); - } - - private Cursor getCursorForPreKey(Account account, int preKeyId) { - SQLiteDatabase db = this.getReadableDatabase(); - String[] columns = {SQLiteAxolotlStore.KEY}; - String[] selectionArgs = {account.getUuid(), Integer.toString(preKeyId)}; - Cursor cursor = db.query(SQLiteAxolotlStore.PREKEY_TABLENAME, - columns, - SQLiteAxolotlStore.ACCOUNT + "=? AND " - + SQLiteAxolotlStore.ID + "=?", - selectionArgs, - null, null, null); - - return cursor; - } - - public PreKeyRecord loadPreKey(Account account, int preKeyId) { - PreKeyRecord record = null; - Cursor cursor = getCursorForPreKey(account, preKeyId); - if (cursor.getCount() != 0) { - cursor.moveToFirst(); - try { - record = new PreKeyRecord(Base64.decode(cursor.getString(cursor.getColumnIndex(SQLiteAxolotlStore.KEY)), Base64.DEFAULT)); - } catch (IOException e) { - throw new AssertionError(e); - } - } - cursor.close(); - return record; - } - - public boolean containsPreKey(Account account, int preKeyId) { - Cursor cursor = getCursorForPreKey(account, preKeyId); - int count = cursor.getCount(); - cursor.close(); - return count != 0; - } - - public void storePreKey(Account account, PreKeyRecord record) { - SQLiteDatabase db = this.getWritableDatabase(); - ContentValues values = new ContentValues(); - values.put(SQLiteAxolotlStore.ID, record.getId()); - values.put(SQLiteAxolotlStore.KEY, Base64.encodeToString(record.serialize(), Base64.DEFAULT)); - values.put(SQLiteAxolotlStore.ACCOUNT, account.getUuid()); - db.insert(SQLiteAxolotlStore.PREKEY_TABLENAME, null, values); - } - - public void deletePreKey(Account account, int preKeyId) { - SQLiteDatabase db = this.getWritableDatabase(); - String[] args = {account.getUuid(), Integer.toString(preKeyId)}; - db.delete(SQLiteAxolotlStore.PREKEY_TABLENAME, - SQLiteAxolotlStore.ACCOUNT + "=? AND " - + SQLiteAxolotlStore.ID + "=?", - args); - } - - private Cursor getCursorForSignedPreKey(Account account, int signedPreKeyId) { - SQLiteDatabase db = this.getReadableDatabase(); - String[] columns = {SQLiteAxolotlStore.KEY}; - String[] selectionArgs = {account.getUuid(), Integer.toString(signedPreKeyId)}; - Cursor cursor = db.query(SQLiteAxolotlStore.SIGNED_PREKEY_TABLENAME, - columns, - SQLiteAxolotlStore.ACCOUNT + "=? AND " + SQLiteAxolotlStore.ID + "=?", - selectionArgs, - null, null, null); - - return cursor; - } - - public SignedPreKeyRecord loadSignedPreKey(Account account, int signedPreKeyId) { - SignedPreKeyRecord record = null; - Cursor cursor = getCursorForSignedPreKey(account, signedPreKeyId); - if (cursor.getCount() != 0) { - cursor.moveToFirst(); - try { - record = new SignedPreKeyRecord(Base64.decode(cursor.getString(cursor.getColumnIndex(SQLiteAxolotlStore.KEY)), Base64.DEFAULT)); - } catch (IOException e) { - throw new AssertionError(e); - } - } - cursor.close(); - return record; - } - - public List loadSignedPreKeys(Account account) { - List prekeys = new ArrayList<>(); - SQLiteDatabase db = this.getReadableDatabase(); - String[] columns = {SQLiteAxolotlStore.KEY}; - String[] selectionArgs = {account.getUuid()}; - Cursor cursor = db.query(SQLiteAxolotlStore.SIGNED_PREKEY_TABLENAME, - columns, - SQLiteAxolotlStore.ACCOUNT + "=?", - selectionArgs, - null, null, null); - - while (cursor.moveToNext()) { - try { - prekeys.add(new SignedPreKeyRecord(Base64.decode(cursor.getString(cursor.getColumnIndex(SQLiteAxolotlStore.KEY)), Base64.DEFAULT))); - } catch (IOException ignored) { - } - } - cursor.close(); - return prekeys; - } - - public boolean containsSignedPreKey(Account account, int signedPreKeyId) { - Cursor cursor = getCursorForPreKey(account, signedPreKeyId); - int count = cursor.getCount(); - cursor.close(); - return count != 0; - } - - public void storeSignedPreKey(Account account, SignedPreKeyRecord record) { - SQLiteDatabase db = this.getWritableDatabase(); - ContentValues values = new ContentValues(); - values.put(SQLiteAxolotlStore.ID, record.getId()); - values.put(SQLiteAxolotlStore.KEY, Base64.encodeToString(record.serialize(), Base64.DEFAULT)); - values.put(SQLiteAxolotlStore.ACCOUNT, account.getUuid()); - db.insert(SQLiteAxolotlStore.SIGNED_PREKEY_TABLENAME, null, values); - } - - public void deleteSignedPreKey(Account account, int signedPreKeyId) { - SQLiteDatabase db = this.getWritableDatabase(); - String[] args = {account.getUuid(), Integer.toString(signedPreKeyId)}; - db.delete(SQLiteAxolotlStore.SIGNED_PREKEY_TABLENAME, - SQLiteAxolotlStore.ACCOUNT + "=? AND " - + SQLiteAxolotlStore.ID + "=?", - args); - } - - private Cursor getIdentityKeyCursor(Account account, String name, boolean own) { - final SQLiteDatabase db = this.getReadableDatabase(); - return getIdentityKeyCursor(db, account, name, own); - } - - private Cursor getIdentityKeyCursor(SQLiteDatabase db, Account account, String name, boolean own) { - return getIdentityKeyCursor(db, account, name, own, null); - } - - private Cursor getIdentityKeyCursor(Account account, String fingerprint) { - final SQLiteDatabase db = this.getReadableDatabase(); - return getIdentityKeyCursor(db, account, fingerprint); - } - - private Cursor getIdentityKeyCursor(SQLiteDatabase db, Account account, String fingerprint) { - return getIdentityKeyCursor(db, account, null, null, fingerprint); - } - - private Cursor getIdentityKeyCursor(SQLiteDatabase db, Account account, String name, Boolean own, String fingerprint) { - String[] columns = {SQLiteAxolotlStore.TRUSTED, - SQLiteAxolotlStore.KEY}; - ArrayList selectionArgs = new ArrayList<>(4); - selectionArgs.add(account.getUuid()); - String selectionString = SQLiteAxolotlStore.ACCOUNT + " = ?"; - if (name != null) { - selectionArgs.add(name); - selectionString += " AND " + SQLiteAxolotlStore.NAME + " = ?"; - } - if (fingerprint != null) { - selectionArgs.add(fingerprint); - selectionString += " AND " + SQLiteAxolotlStore.FINGERPRINT + " = ?"; - } - if (own != null) { - selectionArgs.add(own ? "1" : "0"); - selectionString += " AND " + SQLiteAxolotlStore.OWN + " = ?"; - } - Cursor cursor = db.query(SQLiteAxolotlStore.IDENTITIES_TABLENAME, - columns, - selectionString, - selectionArgs.toArray(new String[selectionArgs.size()]), - null, null, null); - - return cursor; - } - - public IdentityKeyPair loadOwnIdentityKeyPair(Account account) { - SQLiteDatabase db = getReadableDatabase(); - return loadOwnIdentityKeyPair(db, account); - } - - private IdentityKeyPair loadOwnIdentityKeyPair(SQLiteDatabase db, Account account) { - String name = account.getJid().toBareJid().toString(); - IdentityKeyPair identityKeyPair = null; - Cursor cursor = getIdentityKeyCursor(db, account, name, true); - if (cursor.getCount() != 0) { - cursor.moveToFirst(); - try { - identityKeyPair = new IdentityKeyPair(Base64.decode(cursor.getString(cursor.getColumnIndex(SQLiteAxolotlStore.KEY)), Base64.DEFAULT)); - } catch (InvalidKeyException e) { - Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Encountered invalid IdentityKey in database for account" + account.getJid().toBareJid() + ", address: " + name); - } - } - cursor.close(); - - return identityKeyPair; - } - - public Set loadIdentityKeys(Account account, String name) { - return loadIdentityKeys(account, name, null); - } - - public Set loadIdentityKeys(Account account, String name, XmppAxolotlSession.Trust trust) { - Set identityKeys = new HashSet<>(); - Cursor cursor = getIdentityKeyCursor(account, name, false); - - while (cursor.moveToNext()) { - if (trust != null && - cursor.getInt(cursor.getColumnIndex(SQLiteAxolotlStore.TRUSTED)) - != trust.getCode()) { - continue; - } - try { - identityKeys.add(new IdentityKey(Base64.decode(cursor.getString(cursor.getColumnIndex(SQLiteAxolotlStore.KEY)), Base64.DEFAULT), 0)); - } catch (InvalidKeyException e) { - Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Encountered invalid IdentityKey in database for account" + account.getJid().toBareJid() + ", address: " + name); - } - } - cursor.close(); - - return identityKeys; - } - - public long numTrustedKeys(Account account, String name) { - SQLiteDatabase db = getReadableDatabase(); - String[] args = { - account.getUuid(), - name, - String.valueOf(XmppAxolotlSession.Trust.TRUSTED.getCode()), - String.valueOf(XmppAxolotlSession.Trust.TRUSTED_X509.getCode()) - }; - return DatabaseUtils.queryNumEntries(db, SQLiteAxolotlStore.IDENTITIES_TABLENAME, - SQLiteAxolotlStore.ACCOUNT + " = ?" - + " AND " + SQLiteAxolotlStore.NAME + " = ?" - + " AND (" + SQLiteAxolotlStore.TRUSTED + " = ? OR " + SQLiteAxolotlStore.TRUSTED + " = ?)", - args - ); - } - - private void storeIdentityKey(Account account, String name, boolean own, String fingerprint, String base64Serialized) { - storeIdentityKey(account, name, own, fingerprint, base64Serialized, XmppAxolotlSession.Trust.UNDECIDED); - } - - private void storeIdentityKey(Account account, String name, boolean own, String fingerprint, String base64Serialized, XmppAxolotlSession.Trust trusted) { - SQLiteDatabase db = this.getWritableDatabase(); - ContentValues values = new ContentValues(); - values.put(SQLiteAxolotlStore.ACCOUNT, account.getUuid()); - values.put(SQLiteAxolotlStore.NAME, name); - values.put(SQLiteAxolotlStore.OWN, own ? 1 : 0); - values.put(SQLiteAxolotlStore.FINGERPRINT, fingerprint); - values.put(SQLiteAxolotlStore.KEY, base64Serialized); - values.put(SQLiteAxolotlStore.TRUSTED, trusted.getCode()); - db.insert(SQLiteAxolotlStore.IDENTITIES_TABLENAME, null, values); - } - - public XmppAxolotlSession.Trust isIdentityKeyTrusted(Account account, String fingerprint) { - Cursor cursor = getIdentityKeyCursor(account, fingerprint); - XmppAxolotlSession.Trust trust = null; - if (cursor.getCount() > 0) { - cursor.moveToFirst(); - int trustValue = cursor.getInt(cursor.getColumnIndex(SQLiteAxolotlStore.TRUSTED)); - trust = XmppAxolotlSession.Trust.fromCode(trustValue); - } - cursor.close(); - return trust; - } - - public boolean setIdentityKeyTrust(Account account, String fingerprint, XmppAxolotlSession.Trust trust) { - SQLiteDatabase db = this.getWritableDatabase(); - return setIdentityKeyTrust(db, account, fingerprint, trust); - } - - private boolean setIdentityKeyTrust(SQLiteDatabase db, Account account, String fingerprint, XmppAxolotlSession.Trust trust) { - String[] selectionArgs = { - account.getUuid(), - fingerprint - }; - ContentValues values = new ContentValues(); - values.put(SQLiteAxolotlStore.TRUSTED, trust.getCode()); - int rows = db.update(SQLiteAxolotlStore.IDENTITIES_TABLENAME, values, - SQLiteAxolotlStore.ACCOUNT + " = ? AND " - + SQLiteAxolotlStore.FINGERPRINT + " = ? ", - selectionArgs); - return rows == 1; - } - - public boolean setIdentityKeyCertificate(Account account, String fingerprint, X509Certificate x509Certificate) { - SQLiteDatabase db = this.getWritableDatabase(); - String[] selectionArgs = { - account.getUuid(), - fingerprint - }; - try { - ContentValues values = new ContentValues(); - values.put(SQLiteAxolotlStore.CERTIFICATE, x509Certificate.getEncoded()); - return db.update(SQLiteAxolotlStore.IDENTITIES_TABLENAME, values, - SQLiteAxolotlStore.ACCOUNT + " = ? AND " - + SQLiteAxolotlStore.FINGERPRINT + " = ? ", - selectionArgs) == 1; - } catch (CertificateEncodingException e) { - Log.d(Config.LOGTAG, "could not encode certificate"); - return false; - } - } - - public X509Certificate getIdentityKeyCertifcate(Account account, String fingerprint) { - SQLiteDatabase db = this.getReadableDatabase(); - String[] selectionArgs = { - account.getUuid(), - fingerprint - }; - String[] colums = {SQLiteAxolotlStore.CERTIFICATE}; - String selection = SQLiteAxolotlStore.ACCOUNT + " = ? AND " + SQLiteAxolotlStore.FINGERPRINT + " = ? "; - Cursor cursor = db.query(SQLiteAxolotlStore.IDENTITIES_TABLENAME, colums, selection, selectionArgs, null, null, null); - if (cursor.getCount() < 1) { - return null; - } else { - cursor.moveToFirst(); - byte[] certificate = cursor.getBlob(cursor.getColumnIndex(SQLiteAxolotlStore.CERTIFICATE)); - cursor.close(); - if (certificate == null || certificate.length == 0) { - return null; - } - try { - CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); - return (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(certificate)); - } catch (CertificateException e) { - Log.d(Config.LOGTAG,"certificate exception "+e.getMessage()); - return null; - } - } - } - - public void storeIdentityKey(Account account, String name, IdentityKey identityKey) { - storeIdentityKey(account, name, false, identityKey.getFingerprint().replaceAll("\\s", ""), Base64.encodeToString(identityKey.serialize(), Base64.DEFAULT)); - } - - public void storeOwnIdentityKeyPair(Account account, IdentityKeyPair identityKeyPair) { - storeIdentityKey(account, account.getJid().toBareJid().toString(), true, identityKeyPair.getPublicKey().getFingerprint().replaceAll("\\s", ""), Base64.encodeToString(identityKeyPair.serialize(), Base64.DEFAULT), XmppAxolotlSession.Trust.TRUSTED); - } - - public void recreateAxolotlDb() { - recreateAxolotlDb(getWritableDatabase()); - } - - public void recreateAxolotlDb(SQLiteDatabase db) { - Log.d(Config.LOGTAG, AxolotlService.LOGPREFIX + " : " + ">>> (RE)CREATING AXOLOTL DATABASE <<<"); - db.execSQL("DROP TABLE IF EXISTS " + SQLiteAxolotlStore.SESSION_TABLENAME); - db.execSQL(CREATE_SESSIONS_STATEMENT); - db.execSQL("DROP TABLE IF EXISTS " + SQLiteAxolotlStore.PREKEY_TABLENAME); - db.execSQL(CREATE_PREKEYS_STATEMENT); - db.execSQL("DROP TABLE IF EXISTS " + SQLiteAxolotlStore.SIGNED_PREKEY_TABLENAME); - db.execSQL(CREATE_SIGNED_PREKEYS_STATEMENT); - db.execSQL("DROP TABLE IF EXISTS " + SQLiteAxolotlStore.IDENTITIES_TABLENAME); - db.execSQL(CREATE_IDENTITIES_STATEMENT); - } - - public void wipeAxolotlDb(Account account) { - String accountName = account.getUuid(); - Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + ">>> WIPING AXOLOTL DATABASE FOR ACCOUNT " + accountName + " <<<"); - SQLiteDatabase db = this.getWritableDatabase(); - String[] deleteArgs = { - accountName - }; - db.delete(SQLiteAxolotlStore.SESSION_TABLENAME, - SQLiteAxolotlStore.ACCOUNT + " = ?", - deleteArgs); - db.delete(SQLiteAxolotlStore.PREKEY_TABLENAME, - SQLiteAxolotlStore.ACCOUNT + " = ?", - deleteArgs); - db.delete(SQLiteAxolotlStore.SIGNED_PREKEY_TABLENAME, - SQLiteAxolotlStore.ACCOUNT + " = ?", - deleteArgs); - db.delete(SQLiteAxolotlStore.IDENTITIES_TABLENAME, - SQLiteAxolotlStore.ACCOUNT + " = ?", - deleteArgs); - } -} diff --git a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java deleted file mode 100644 index 6d4fdba0e..000000000 --- a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java +++ /dev/null @@ -1,893 +0,0 @@ -package eu.siacs.conversations.persistance; - -import android.annotation.TargetApi; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.RectF; -import android.media.MediaMetadataRetriever; -import android.net.Uri; -import android.os.Build; -import android.os.Environment; -import android.os.ParcelFileDescriptor; -import android.provider.MediaStore; -import android.provider.OpenableColumns; -import android.system.Os; -import android.system.StructStat; -import android.util.Base64; -import android.util.Base64OutputStream; -import android.util.Log; -import android.util.LruCache; -import android.webkit.MimeTypeMap; - -import java.io.ByteArrayOutputStream; -import java.io.Closeable; -import java.io.File; -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.Socket; -import java.net.URL; -import java.security.DigestOutputStream; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.List; -import java.util.Locale; - -import eu.siacs.conversations.Config; -import eu.siacs.conversations.R; -import eu.siacs.conversations.entities.DownloadableFile; -import eu.siacs.conversations.entities.Message; -import eu.siacs.conversations.services.XmppConnectionService; -import eu.siacs.conversations.utils.CryptoHelper; -import eu.siacs.conversations.utils.ExifHelper; -import eu.siacs.conversations.utils.FileUtils; -import eu.siacs.conversations.xmpp.pep.Avatar; - -public class FileBackend { - private final SimpleDateFormat fileDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.US); - - private XmppConnectionService mXmppConnectionService; - - public FileBackend(XmppConnectionService service) { - this.mXmppConnectionService = service; - } - - private void createNoMedia() { - final File nomedia_files = new File(getConversationsFileDirectory()+".nomedia"); - final File nomedia_audios = new File(getConversationsAudioDirectory()+".nomedia"); - if (!nomedia_files.exists()) { - try { - nomedia_files.createNewFile(); - } catch (Exception e) { - Log.d(Config.LOGTAG, "could not create nomedia file for files directory"); - } - } - if (!nomedia_audios.exists()) { - try { - nomedia_audios.createNewFile(); - } catch (Exception e) { - Log.d(Config.LOGTAG, "could not create nomedia file for audio directory"); - } - } - } - - public void updateMediaScanner(File file) { - if (file.getAbsolutePath().startsWith(getConversationsImageDirectory()) - || file.getAbsolutePath().startsWith(getConversationsVideoDirectory())) { - Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); - intent.setData(Uri.fromFile(file)); - mXmppConnectionService.sendBroadcast(intent); - } else { - createNoMedia(); - } - } - - public boolean deleteFile(Message message) { - File file = getFile(message); - if (file.delete()) { - updateMediaScanner(file); - return true; - } else { - return false; - } - } - - public DownloadableFile getFile(Message message) { - return getFile(message, true); - } - - public DownloadableFile getFile(Message message, boolean decrypted) { - final boolean encrypted = !decrypted - && (message.getEncryption() == Message.ENCRYPTION_PGP - || message.getEncryption() == Message.ENCRYPTION_DECRYPTED); - final DownloadableFile file; - String path = message.getRelativeFilePath(); - if (path == null) { - String filename = fileDateFormat.format(new Date(message.getTimeSent()))+"_"+message.getUuid().substring(0,4); - path = filename; - } - if (path.startsWith("/")) { - file = new DownloadableFile(path); - } else { - String mime = message.getMimeType(); - if (mime != null && mime.startsWith("image")) { - file = new DownloadableFile(getConversationsImageDirectory() + path); - } else if (mime != null && mime.startsWith("video")) { - file = new DownloadableFile(getConversationsVideoDirectory() + path); - } else if (mime != null && mime.startsWith("audio")) { - file = new DownloadableFile(getConversationsAudioDirectory() + path); - } else { - file = new DownloadableFile(getConversationsFileDirectory() + path); - } - } - if (encrypted) { - return new DownloadableFile(getConversationsFileDirectory() + file.getName() + ".pgp"); - } else { - return file; - } - } - - private static long getFileSize(Context context, Uri uri) { - Cursor cursor = context.getContentResolver().query(uri, null, null, null, null); - if (cursor != null && cursor.moveToFirst()) { - return cursor.getLong(cursor.getColumnIndex(OpenableColumns.SIZE)); - } else { - return -1; - } - } - - public static boolean allFilesUnderSize(Context context, List uris, long max) { - if (max <= 0) { - Log.d(Config.LOGTAG,"server did not report max file size for http upload"); - return true; //exception to be compatible with HTTP Upload < v0.2 - } - for(Uri uri : uris) { - if (FileBackend.getFileSize(context, uri) > max) { - Log.d(Config.LOGTAG,"not all files are under "+max+" bytes. suggesting falling back to jingle"); - return false; - } - } - return true; - } - - public static String getConversationsFileDirectory() { - return Environment.getExternalStorageDirectory().getAbsolutePath()+"/Pix-Art Messenger/files/"; - } - - public static String getConversationsImageDirectory() { - return Environment.getExternalStorageDirectory().getAbsolutePath()+"/Pix-Art Messenger/images/"; - } - - public static String getConversationsVideoDirectory() { - return Environment.getExternalStorageDirectory().getAbsolutePath()+"/Pix-Art Messenger/videos/"; - } - - public static String getConversationsAudioDirectory() { - return Environment.getExternalStorageDirectory().getAbsolutePath()+"/Pix-Art Messenger/audios/"; - } - - public static String getConversationsDirectory() { - return Environment.getExternalStorageDirectory().getAbsolutePath()+"/Pix-Art Messenger/"; - } - - public Bitmap resize(Bitmap originalBitmap, int size) { - int w = originalBitmap.getWidth(); - int h = originalBitmap.getHeight(); - if (Math.max(w, h) > size) { - int scalledW; - int scalledH; - if (w <= h) { - scalledW = (int) (w / ((double) h / size)); - scalledH = size; - } else { - scalledW = size; - scalledH = (int) (h / ((double) w / size)); - } - Bitmap result = Bitmap.createScaledBitmap(originalBitmap, scalledW, scalledH, true); - if (originalBitmap != null && !originalBitmap.isRecycled()) { - originalBitmap.recycle(); - } - return result; - } else { - return originalBitmap; - } - } - - public static Bitmap rotate(Bitmap bitmap, int degree) { - if (degree == 0) { - return bitmap; - } - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - Matrix mtx = new Matrix(); - mtx.postRotate(degree); - Bitmap result = Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true); - if (bitmap != null && !bitmap.isRecycled()) { - bitmap.recycle(); - } - return result; - } - - public boolean useImageAsIs(Uri uri) { - String path = getOriginalPath(uri); - if (path == null) { - return false; - } - File file = new File(path); - long size = file.length(); - if (size == 0 || size >= Config.IMAGE_MAX_SIZE ) { - return false; - } - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - try { - BitmapFactory.decodeStream(mXmppConnectionService.getContentResolver().openInputStream(uri), null, options); - if (options == null || options.outMimeType == null || options.outHeight <= 0 || options.outWidth <= 0) { - return false; - } - return (options.outWidth <= Config.IMAGE_SIZE && options.outHeight <= Config.IMAGE_SIZE && options.outMimeType.contains(Config.IMAGE_FORMAT.name().toLowerCase())); - } catch (FileNotFoundException e) { - return false; - } - } - - public String getOriginalPath(Uri uri) { - return FileUtils.getPath(mXmppConnectionService,uri); - } - - public void copyFileToPrivateStorage(File file, Uri uri) throws FileCopyException { - file.getParentFile().mkdirs(); - OutputStream os = null; - InputStream is = null; - try { - file.createNewFile(); - os = new FileOutputStream(file); - is = mXmppConnectionService.getContentResolver().openInputStream(uri); - byte[] buffer = new byte[1024]; - int length; - while ((length = is.read(buffer)) > 0) { - os.write(buffer, 0, length); - } - os.flush(); - } catch(FileNotFoundException e) { - throw new FileCopyException(R.string.error_file_not_found); - } catch (IOException e) { - e.printStackTrace(); - throw new FileCopyException(R.string.error_io_exception); - } finally { - close(os); - close(is); - } - Log.d(Config.LOGTAG, "output file name " + file.getAbsolutePath()); - } - - public void copyFileToPrivateStorage(Message message, Uri uri) throws FileCopyException { - String mime = mXmppConnectionService.getContentResolver().getType(uri); - Log.d(Config.LOGTAG, "copy " + uri.toString() + " to private storage (mime="+mime+")"); - String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mime); - if (extension == null) { - extension = getExtensionFromUri(uri); - } - String filename = fileDateFormat.format(new Date(message.getTimeSent()))+"_"+message.getUuid().substring(0,4); - message.setRelativeFilePath(filename + "." + extension); - copyFileToPrivateStorage(mXmppConnectionService.getFileBackend().getFile(message), uri); - } - - private String getExtensionFromUri(Uri uri) { - String[] projection = {MediaStore.MediaColumns.DATA}; - String filename = null; - Cursor cursor = mXmppConnectionService.getContentResolver().query(uri, projection, null, null, null); - if (cursor != null) { - try { - if (cursor.moveToFirst()) { - filename = cursor.getString(0); - } - } catch (Exception e) { - filename = null; - } finally { - cursor.close(); - } - } - int pos = filename == null ? -1 : filename.lastIndexOf('.'); - return pos > 0 ? filename.substring(pos+1) : null; - } - - private void copyImageToPrivateStorage(File file, Uri image, int sampleSize) throws FileCopyException { - file.getParentFile().mkdirs(); - InputStream is = null; - OutputStream os = null; - try { - file.createNewFile(); - is = mXmppConnectionService.getContentResolver().openInputStream(image); - Bitmap originalBitmap; - BitmapFactory.Options options = new BitmapFactory.Options(); - int inSampleSize = (int) Math.pow(2, sampleSize); - Log.d(Config.LOGTAG, "reading bitmap with sample size " + inSampleSize); - options.inSampleSize = inSampleSize; - originalBitmap = BitmapFactory.decodeStream(is, null, options); - is.close(); - if (originalBitmap == null) { - throw new FileCopyException(R.string.error_not_an_image_file); - } - Bitmap scaledBitmap = resize(originalBitmap, Config.IMAGE_SIZE); - int rotation = getRotation(image); - scaledBitmap = rotate(scaledBitmap, rotation); - boolean targetSizeReached = false; - int quality = Config.IMAGE_QUALITY; - while(!targetSizeReached) { - os = new FileOutputStream(file); - boolean success = scaledBitmap.compress(Config.IMAGE_FORMAT, quality, os); - if (!success) { - throw new FileCopyException(R.string.error_compressing_image); - } - os.flush(); - targetSizeReached = file.length() <= Config.IMAGE_MAX_SIZE || quality <= 50; - quality -= 5; - } - scaledBitmap.recycle(); - return; - } catch (FileNotFoundException e) { - throw new FileCopyException(R.string.error_file_not_found); - } catch (IOException e) { - e.printStackTrace(); - throw new FileCopyException(R.string.error_io_exception); - } catch (SecurityException e) { - throw new FileCopyException(R.string.error_security_exception_during_image_copy); - } catch (OutOfMemoryError e) { - ++sampleSize; - if (sampleSize <= 3) { - copyImageToPrivateStorage(file, image, sampleSize); - } else { - throw new FileCopyException(R.string.error_out_of_memory); - } - } catch (NullPointerException e) { - throw new FileCopyException(R.string.error_io_exception); - } finally { - close(os); - close(is); - } - } - - public void copyImageToPrivateStorage(File file, Uri image) throws FileCopyException { - copyImageToPrivateStorage(file, image, 0); - } - - public void copyImageToPrivateStorage(Message message, Uri image) throws FileCopyException { - String filename = fileDateFormat.format(new Date(message.getTimeSent()))+"_"+message.getUuid().substring(0,4); - switch(Config.IMAGE_FORMAT) { - case JPEG: - message.setRelativeFilePath(filename+".jpg"); - break; - case PNG: - message.setRelativeFilePath(filename+".png"); - break; - case WEBP: - message.setRelativeFilePath(filename+".webp"); - break; - } - copyImageToPrivateStorage(getFile(message), image); - updateFileParams(message); - } - - private int getRotation(File file) { - return getRotation(Uri.parse("file://"+file.getAbsolutePath())); - } - - private int getRotation(Uri image) { - InputStream is = null; - try { - is = mXmppConnectionService.getContentResolver().openInputStream(image); - return ExifHelper.getOrientation(is); - } catch (FileNotFoundException e) { - return 0; - } finally { - close(is); - } - } - - public Bitmap getThumbnail(Message message, int size, boolean cacheOnly) throws FileNotFoundException { - final String uuid = message.getUuid(); - final LruCache cache = mXmppConnectionService.getBitmapCache(); - Bitmap thumbnail = cache.get(uuid); - if ((thumbnail == null) && (!cacheOnly)) { - synchronized (cache) { - thumbnail = cache.get(uuid); - if (thumbnail != null) { - return thumbnail; - } - DownloadableFile file = getFile(message); - if (file.getMimeType().startsWith("video/")) { - thumbnail = getVideoPreview(file, size); - } else { - Bitmap fullsize = getFullsizeImagePreview(file, size); - if (fullsize == null) { - throw new FileNotFoundException(); - } - thumbnail = resize(fullsize, size); - thumbnail = rotate(thumbnail, getRotation(file)); - } - this.mXmppConnectionService.getBitmapCache().put(uuid, thumbnail); - } - } - return thumbnail; - } - - private Bitmap getFullsizeImagePreview(File file, int size) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inSampleSize = calcSampleSize(file, size); - return BitmapFactory.decodeFile(file.getAbsolutePath(), options); - } - - private Bitmap getVideoPreview(File file, int size) { - MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever(); - Bitmap frame; - try { - metadataRetriever.setDataSource(file.getAbsolutePath()); - frame = metadataRetriever.getFrameAtTime(0); - metadataRetriever.release(); - frame = resize(frame, size); - } catch(IllegalArgumentException e) { - frame = Bitmap.createBitmap(size,size, Bitmap.Config.ARGB_8888); - frame.eraseColor(0xff000000); - } - Canvas canvas = new Canvas(frame); - Bitmap play = BitmapFactory.decodeResource(mXmppConnectionService.getResources(), R.drawable.play_video); - float x = (frame.getWidth() - play.getWidth()) / 2.0f; - float y = (frame.getHeight() - play.getHeight()) / 2.0f; - canvas.drawBitmap(play,x,y,null); - return frame; - } - - public Uri getTakePhotoUri() { - StringBuilder pathBuilder = new StringBuilder(); - pathBuilder.append(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)); - pathBuilder.append('/'); - pathBuilder.append("Camera"); - pathBuilder.append('/'); - pathBuilder.append("IMG_" + this.fileDateFormat.format(new Date()) + ".jpg"); - Uri uri = Uri.parse("file://" + pathBuilder.toString()); - File file = new File(uri.toString()); - file.getParentFile().mkdirs(); - return uri; - } - - public Avatar getPepAvatar(Uri image, int size, Bitmap.CompressFormat format) { - try { - Avatar avatar = new Avatar(); - Bitmap bm = cropCenterSquare(image, size); - if (bm == null) { - return null; - } - ByteArrayOutputStream mByteArrayOutputStream = new ByteArrayOutputStream(); - Base64OutputStream mBase64OutputSttream = new Base64OutputStream( - mByteArrayOutputStream, Base64.DEFAULT); - MessageDigest digest = MessageDigest.getInstance("SHA-1"); - DigestOutputStream mDigestOutputStream = new DigestOutputStream( - mBase64OutputSttream, digest); - if (!bm.compress(format, 75, mDigestOutputStream)) { - return null; - } - mDigestOutputStream.flush(); - mDigestOutputStream.close(); - avatar.sha1sum = CryptoHelper.bytesToHex(digest.digest()); - avatar.image = new String(mByteArrayOutputStream.toByteArray()); - return avatar; - } catch (NoSuchAlgorithmException e) { - return null; - } catch (IOException e) { - return null; - } - } - - public Avatar getStoredPepAvatar(String hash) { - if (hash == null) { - return null; - } - Avatar avatar = new Avatar(); - File file = new File(getAvatarPath(hash)); - FileInputStream is = null; - try { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeFile(file.getAbsolutePath(), options); - is = new FileInputStream(file); - ByteArrayOutputStream mByteArrayOutputStream = new ByteArrayOutputStream(); - Base64OutputStream mBase64OutputStream = new Base64OutputStream(mByteArrayOutputStream, Base64.DEFAULT); - MessageDigest digest = MessageDigest.getInstance("SHA-1"); - DigestOutputStream os = new DigestOutputStream(mBase64OutputStream, digest); - byte[] buffer = new byte[4096]; - int length; - while ((length = is.read(buffer)) > 0) { - os.write(buffer, 0, length); - } - os.flush(); - os.close(); - avatar.sha1sum = CryptoHelper.bytesToHex(digest.digest()); - avatar.image = new String(mByteArrayOutputStream.toByteArray()); - avatar.height = options.outHeight; - avatar.width = options.outWidth; - return avatar; - } catch (IOException e) { - return null; - } catch (NoSuchAlgorithmException e) { - return null; - } finally { - close(is); - } - } - - public boolean isAvatarCached(Avatar avatar) { - File file = new File(getAvatarPath(avatar.getFilename())); - return file.exists(); - } - - public boolean save(Avatar avatar) { - File file; - if (isAvatarCached(avatar)) { - file = new File(getAvatarPath(avatar.getFilename())); - } else { - String filename = getAvatarPath(avatar.getFilename()); - file = new File(filename + ".tmp"); - file.getParentFile().mkdirs(); - OutputStream os = null; - try { - file.createNewFile(); - os = new FileOutputStream(file); - MessageDigest digest = MessageDigest.getInstance("SHA-1"); - digest.reset(); - DigestOutputStream mDigestOutputStream = new DigestOutputStream(os, digest); - mDigestOutputStream.write(avatar.getImageAsBytes()); - mDigestOutputStream.flush(); - mDigestOutputStream.close(); - String sha1sum = CryptoHelper.bytesToHex(digest.digest()); - if (sha1sum.equals(avatar.sha1sum)) { - file.renameTo(new File(filename)); - } else { - Log.d(Config.LOGTAG, "sha1sum mismatch for " + avatar.owner); - file.delete(); - return false; - } - } catch (IllegalArgumentException | IOException | NoSuchAlgorithmException e) { - return false; - } finally { - close(os); - } - } - avatar.size = file.length(); - return true; - } - - public String getAvatarPath(String avatar) { - return mXmppConnectionService.getFilesDir().getAbsolutePath()+ "/avatars/" + avatar; - } - - public Uri getAvatarUri(String avatar) { - return Uri.parse("file:" + getAvatarPath(avatar)); - } - - public Bitmap cropCenterSquare(Uri image, int size) { - if (image == null) { - return null; - } - InputStream is = null; - try { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inSampleSize = calcSampleSize(image, size); - is = mXmppConnectionService.getContentResolver().openInputStream(image); - if (is == null) { - return null; - } - Bitmap input = BitmapFactory.decodeStream(is, null, options); - if (input == null) { - return null; - } else { - input = rotate(input, getRotation(image)); - return cropCenterSquare(input, size); - } - } catch (SecurityException e) { - return null; // happens for example on Android 6.0 if contacts permissions get revoked - } catch (FileNotFoundException e) { - return null; - } finally { - close(is); - } - } - - public Bitmap cropCenter(Uri image, int newHeight, int newWidth) { - if (image == null) { - return null; - } - InputStream is = null; - try { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inSampleSize = calcSampleSize(image, Math.max(newHeight, newWidth)); - is = mXmppConnectionService.getContentResolver().openInputStream(image); - if (is == null) { - return null; - } - Bitmap source = BitmapFactory.decodeStream(is, null, options); - if (source == null) { - return null; - } - int sourceWidth = source.getWidth(); - int sourceHeight = source.getHeight(); - float xScale = (float) newWidth / sourceWidth; - float yScale = (float) newHeight / sourceHeight; - float scale = Math.max(xScale, yScale); - float scaledWidth = scale * sourceWidth; - float scaledHeight = scale * sourceHeight; - float left = (newWidth - scaledWidth) / 2; - float top = (newHeight - scaledHeight) / 2; - - RectF targetRect = new RectF(left, top, left + scaledWidth, top + scaledHeight); - Bitmap dest = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(dest); - canvas.drawBitmap(source, null, targetRect, null); - if (source != null && !source.isRecycled()) { - source.recycle(); - } - return dest; - } catch (SecurityException e) { - return null; //android 6.0 with revoked permissions for example - } catch (FileNotFoundException e) { - return null; - } finally { - close(is); - } - } - - public Bitmap cropCenterSquare(Bitmap input, int size) { - int w = input.getWidth(); - int h = input.getHeight(); - - float scale = Math.max((float) size / h, (float) size / w); - - float outWidth = scale * w; - float outHeight = scale * h; - float left = (size - outWidth) / 2; - float top = (size - outHeight) / 2; - RectF target = new RectF(left, top, left + outWidth, top + outHeight); - - Bitmap output = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(output); - canvas.drawBitmap(input, null, target, null); - if (input != null && !input.isRecycled()) { - input.recycle(); - } - return output; - } - - private int calcSampleSize(Uri image, int size) throws FileNotFoundException, SecurityException { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeStream(mXmppConnectionService.getContentResolver().openInputStream(image), null, options); - return calcSampleSize(options, size); - } - - private static int calcSampleSize(File image, int size) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeFile(image.getAbsolutePath(), options); - return calcSampleSize(options, size); - } - - public static int calcSampleSize(BitmapFactory.Options options, int size) { - int height = options.outHeight; - int width = options.outWidth; - int inSampleSize = 1; - - if (height > size || width > size) { - int halfHeight = height / 2; - int halfWidth = width / 2; - - while ((halfHeight / inSampleSize) > size - && (halfWidth / inSampleSize) > size) { - inSampleSize *= 2; - } - } - return inSampleSize; - } - - public Uri getJingleFileUri(Message message) { - File file = getFile(message); - return Uri.parse("file://" + file.getAbsolutePath()); - } - - public void updateFileParams(Message message) { - updateFileParams(message,null); - } - - public void updateFileParams(Message message, URL url) { - DownloadableFile file = getFile(message); - final String mime = file.getMimeType(); - boolean image = message.getType() == Message.TYPE_IMAGE || (mime != null && mime.startsWith("image/")); - boolean video = mime != null && mime.startsWith("video/"); - if (image || video) { - try { - Dimensions dimensions = image ? getImageDimensions(file) : getVideoDimensions(file); - if (url == null) { - message.setBody(Long.toString(file.getSize()) + '|' + dimensions.width + '|' + dimensions.height); - } else { - message.setBody(url.toString() + "|" + Long.toString(file.getSize()) + '|' + dimensions.width + '|' + dimensions.height); - } - return; - } catch (NotAVideoFile notAVideoFile) { - Log.d(Config.LOGTAG,"file with mime type "+file.getMimeType()+" was not a video file"); - //fall threw - } - } - if (url != null) { - message.setBody(url.toString()+"|"+Long.toString(file.getSize())); - } else { - message.setBody(Long.toString(file.getSize())); - } - - } - - private Dimensions getImageDimensions(File file) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeFile(file.getAbsolutePath(), options); - int rotation = getRotation(file); - boolean rotated = rotation == 90 || rotation == 270; - int imageHeight = rotated ? options.outWidth : options.outHeight; - int imageWidth = rotated ? options.outHeight : options.outWidth; - return new Dimensions(imageHeight, imageWidth); - } - - private Dimensions getVideoDimensions(File file) throws NotAVideoFile { - MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever(); - metadataRetriever.setDataSource(file.getAbsolutePath()); - String hasVideo = metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO); - if (hasVideo == null) { - throw new NotAVideoFile(); - } - int rotation = extractRotationFromMediaRetriever(metadataRetriever); - boolean rotated = rotation == 90 || rotation == 270; - int height; - try { - String h = metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT); - height = Integer.parseInt(h); - } catch (Exception e) { - height = -1; - } - int width; - try { - String w = metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH); - width = Integer.parseInt(w); - } catch (Exception e) { - width = -1; - } - metadataRetriever.release(); - Log.d(Config.LOGTAG,"extracted video dims "+width+"x"+height); - return rotated ? new Dimensions(width, height) : new Dimensions(height, width); - } - - private int extractRotationFromMediaRetriever(MediaMetadataRetriever metadataRetriever) { - int rotation; - if (Build.VERSION.SDK_INT >= 17) { - String r = metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION); - try { - rotation = Integer.parseInt(r); - } catch (Exception e) { - rotation = 0; - } - } else { - rotation = 0; - } - return rotation; - } - - private class Dimensions { - public final int width; - public final int height; - - public Dimensions(int height, int width) { - this.width = width; - this.height = height; - } - } - - private class NotAVideoFile extends Exception { - - } - - public class FileCopyException extends Exception { - private static final long serialVersionUID = -1010013599132881427L; - private int resId; - - public FileCopyException(int resId) { - this.resId = resId; - } - - public int getResId() { - return resId; - } - } - - public Bitmap getAvatar(String avatar, int size) { - if (avatar == null) { - return null; - } - Bitmap bm = cropCenter(getAvatarUri(avatar), size, size); - if (bm == null) { - return null; - } - return bm; - } - - public boolean isFileAvailable(Message message) { - return getFile(message).exists(); - } - - public static void close(Closeable stream) { - if (stream != null) { - try { - stream.close(); - } catch (IOException e) { - } - } - } - - public static void close(Socket socket) { - if (socket != null) { - try { - socket.close(); - } catch (IOException e) { - } - } - } - - - public static boolean weOwnFile(Context context, Uri uri) { - if (uri == null || !ContentResolver.SCHEME_FILE.equals(uri.getScheme())) { - return false; - } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - return fileIsInFilesDir(context, uri); - } else { - return weOwnFileLollipop(uri); - } - } - - - /** - * This is more than hacky but probably way better than doing nothing - * Further 'optimizations' might contain to get the parents of CacheDir and NoBackupDir - * and check against those as well - */ - private static boolean fileIsInFilesDir(Context context, Uri uri) { - try { - final String haystack = context.getFilesDir().getParentFile().getCanonicalPath(); - final String needle = new File(uri.getPath()).getCanonicalPath(); - return needle.startsWith(haystack); - } catch (IOException e) { - return false; - } - } - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - private static boolean weOwnFileLollipop(Uri uri) { - try { - File file = new File(uri.getPath()); - FileDescriptor fd = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY).getFileDescriptor(); - StructStat st = Os.fstat(fd); - return st.st_uid == android.os.Process.myUid(); - } catch (FileNotFoundException e) { - return false; - } catch (Exception e) { - return true; - } - } -} diff --git a/src/main/java/eu/siacs/conversations/persistance/OnPhoneContactsMerged.java b/src/main/java/eu/siacs/conversations/persistance/OnPhoneContactsMerged.java deleted file mode 100644 index 6a457b17f..000000000 --- a/src/main/java/eu/siacs/conversations/persistance/OnPhoneContactsMerged.java +++ /dev/null @@ -1,5 +0,0 @@ -package eu.siacs.conversations.persistance; - -public interface OnPhoneContactsMerged { - public void phoneContactsMerged(); -} -- cgit v1.2.3