diff --git a/app/src/main/java/ch/dissem/apps/abit/repository/AndroidAddressRepository.kt b/app/src/main/java/ch/dissem/apps/abit/repository/AndroidAddressRepository.kt index fb8be4d..60623f2 100644 --- a/app/src/main/java/ch/dissem/apps/abit/repository/AndroidAddressRepository.kt +++ b/app/src/main/java/ch/dissem/apps/abit/repository/AndroidAddressRepository.kt @@ -86,8 +86,7 @@ class AndroidAddressRepository(private val sql: SqlHelper) : AddressRepository { // you will actually use after this query. val projection = arrayOf(COLUMN_ADDRESS) - val db = sql.readableDatabase - db.query( + sql.readableDatabase.query( TABLE_NAME, projection, where, null, null, null, orderBy @@ -106,8 +105,7 @@ class AndroidAddressRepository(private val sql: SqlHelper) : AddressRepository { // you will actually use after this query. val projection = arrayOf(COLUMN_ADDRESS, COLUMN_ALIAS, COLUMN_PUBLIC_KEY, COLUMN_PRIVATE_KEY, COLUMN_SUBSCRIBED, COLUMN_CHAN) - val db = sql.readableDatabase - db.query( + sql.readableDatabase.query( TABLE_NAME, projection, where, null, null, null, null ).use { c -> @@ -154,8 +152,7 @@ class AndroidAddressRepository(private val sql: SqlHelper) : AddressRepository { } private fun exists(address: BitmessageAddress): Boolean { - val db = sql.readableDatabase - db.rawQuery( + sql.readableDatabase.rawQuery( "SELECT COUNT(*) FROM Address WHERE address=?", arrayOf(address.address) ).use { cursor -> @@ -165,49 +162,45 @@ class AndroidAddressRepository(private val sql: SqlHelper) : AddressRepository { } private fun update(address: BitmessageAddress) { - val db = sql.writableDatabase // Create a new map of values, where column names are the keys val values = getContentValues(address) - val update = db.update(TABLE_NAME, values, "address=?", arrayOf(address.address)) + val update = sql.writableDatabase.update(TABLE_NAME, values, "address=?", arrayOf(address.address)) if (update < 0) { LOG.error("Could not update address {}", address) } } private fun insert(address: BitmessageAddress) { - val db = sql.writableDatabase // Create a new map of values, where column names are the keys - val values = getContentValues(address) - values.put(COLUMN_ADDRESS, address.address) - values.put(COLUMN_VERSION, address.version) - values.put(COLUMN_CHAN, address.isChan) + val values = getContentValues(address).apply { + put(COLUMN_ADDRESS, address.address) + put(COLUMN_VERSION, address.version) + put(COLUMN_CHAN, address.isChan) + } - val insert = db.insert(TABLE_NAME, null, values) + val insert = sql.writableDatabase.insert(TABLE_NAME, null, values) if (insert < 0) { LOG.error("Could not insert address {}", address) } } - private fun getContentValues(address: BitmessageAddress): ContentValues { - val values = ContentValues() - address.alias?.let { values.put(COLUMN_ALIAS, it) } + private fun getContentValues(address: BitmessageAddress) = ContentValues().apply { + address.alias?.let { put(COLUMN_ALIAS, it) } address.pubkey?.let { pubkey -> val out = ByteArrayOutputStream() pubkey.writer().writeUnencrypted(out) - values.put(COLUMN_PUBLIC_KEY, out.toByteArray()) + put(COLUMN_PUBLIC_KEY, out.toByteArray()) } - address.privateKey?.let { values.put(COLUMN_PRIVATE_KEY, Encode.bytes(it)) } + address.privateKey?.let { put(COLUMN_PRIVATE_KEY, Encode.bytes(it)) } if (address.isChan) { - values.put(COLUMN_CHAN, true) + put(COLUMN_CHAN, true) } - values.put(COLUMN_SUBSCRIBED, address.isSubscribed) - return values + put(COLUMN_SUBSCRIBED, address.isSubscribed) } override fun remove(address: BitmessageAddress) { - val db = sql.writableDatabase - db.delete(TABLE_NAME, "address = ?", arrayOf(address.address)) + sql.writableDatabase.delete(TABLE_NAME, "address = ?", arrayOf(address.address)) } override fun getAddress(address: String) = find("address = '$address'").firstOrNull() diff --git a/app/src/main/java/ch/dissem/apps/abit/repository/AndroidInventory.kt b/app/src/main/java/ch/dissem/apps/abit/repository/AndroidInventory.kt index 8ab4e39..b381654 100644 --- a/app/src/main/java/ch/dissem/apps/abit/repository/AndroidInventory.kt +++ b/app/src/main/java/ch/dissem/apps/abit/repository/AndroidInventory.kt @@ -57,10 +57,10 @@ class AndroidInventory(private val sql: SqlHelper) : Inventory { cache.put(stream, result) val projection = arrayOf(COLUMN_HASH, COLUMN_EXPIRES) - val db = sql.readableDatabase - db.query( - TABLE_NAME, projection, - "stream = $stream", null, null, null, null + + sql.readableDatabase.query( + TABLE_NAME, projection, + "stream = $stream", null, null, null, null ).use { c -> while (c.moveToNext()) { val blob = c.getBlob(c.getColumnIndex(COLUMN_HASH)) @@ -84,10 +84,9 @@ class AndroidInventory(private val sql: SqlHelper) : Inventory { // you will actually use after this query. val projection = arrayOf(COLUMN_VERSION, COLUMN_DATA) - val db = sql.readableDatabase - db.query( - TABLE_NAME, projection, - "hash = X'$vector'", null, null, null, null + sql.readableDatabase.query( + TABLE_NAME, projection, + "hash = X'$vector'", null, null, null, null ).use { c -> if (!c.moveToFirst()) { LOG.info("Object requested that we don't have. IV: {}", vector) @@ -115,11 +114,10 @@ class AndroidInventory(private val sql: SqlHelper) : Inventory { where.append(" AND type IN (").append(types.joinToString(separator = "', '", prefix = "'", postfix = "'", transform = { it.number.toString() })).append(")") } - val db = sql.readableDatabase val result = LinkedList() - db.query( - TABLE_NAME, projection, - where.toString(), null, null, null, null + sql.readableDatabase.query( + TABLE_NAME, projection, + where.toString(), null, null, null, null ).use { c -> while (c.moveToNext()) { val objectVersion = c.getInt(c.getColumnIndex(COLUMN_VERSION)) @@ -139,31 +137,29 @@ class AndroidInventory(private val sql: SqlHelper) : Inventory { LOG.trace("Storing object {}", iv) try { - val db = sql.writableDatabase // Create a new map of values, where column names are the keys - val values = ContentValues() - values.put(COLUMN_HASH, objectMessage.inventoryVector.hash) - values.put(COLUMN_STREAM, objectMessage.stream) - values.put(COLUMN_EXPIRES, objectMessage.expiresTime) - values.put(COLUMN_DATA, Encode.bytes(objectMessage)) - values.put(COLUMN_TYPE, objectMessage.type) - values.put(COLUMN_VERSION, objectMessage.version) + val values = ContentValues().apply { + put(COLUMN_HASH, objectMessage.inventoryVector.hash) + put(COLUMN_STREAM, objectMessage.stream) + put(COLUMN_EXPIRES, objectMessage.expiresTime) + put(COLUMN_DATA, Encode.bytes(objectMessage)) + put(COLUMN_TYPE, objectMessage.type) + put(COLUMN_VERSION, objectMessage.version) + } - db.insertOrThrow(TABLE_NAME, null, values) + sql.writableDatabase.insertOrThrow(TABLE_NAME, null, values) getCache(objectMessage.stream).put(iv, objectMessage.expiresTime) } catch (e: SQLiteConstraintException) { LOG.trace(e.message, e) } - } override fun contains(objectMessage: ObjectMessage) = getCache(objectMessage.stream).keys.contains(objectMessage.inventoryVector) override fun cleanup() { val fiveMinutesAgo = now - 5 * MINUTE - val db = sql.writableDatabase - db.delete(TABLE_NAME, "expires < ?", arrayOf(fiveMinutesAgo.toString())) + sql.writableDatabase.delete(TABLE_NAME, "expires < ?", arrayOf(fiveMinutesAgo.toString())) cache.values.map { it.entries }.forEach { entries -> entries.removeAll { it.value < fiveMinutesAgo } } } diff --git a/app/src/main/java/ch/dissem/apps/abit/repository/AndroidMessageRepository.kt b/app/src/main/java/ch/dissem/apps/abit/repository/AndroidMessageRepository.kt index 66167f7..5dc8697 100644 --- a/app/src/main/java/ch/dissem/apps/abit/repository/AndroidMessageRepository.kt +++ b/app/src/main/java/ch/dissem/apps/abit/repository/AndroidMessageRepository.kt @@ -19,7 +19,6 @@ package ch.dissem.apps.abit.repository import android.content.ContentValues import android.database.Cursor import android.database.DatabaseUtils -import android.database.sqlite.SQLiteConstraintException import android.database.sqlite.SQLiteDatabase import ch.dissem.apps.abit.repository.AndroidLabelRepository.Companion.LABEL_ARCHIVE import ch.dissem.apps.abit.util.UuidUtils @@ -29,7 +28,6 @@ import ch.dissem.bitmessage.entity.Plaintext import ch.dissem.bitmessage.entity.valueobject.InventoryVector import ch.dissem.bitmessage.entity.valueobject.Label import ch.dissem.bitmessage.ports.AbstractMessageRepository -import ch.dissem.bitmessage.ports.AlreadyStoredException import ch.dissem.bitmessage.ports.MessageRepository import ch.dissem.bitmessage.utils.Encode import ch.dissem.bitmessage.utils.Strings.hex @@ -137,8 +135,7 @@ class AndroidMessageRepository(private val sql: SqlHelper) : AbstractMessageRepo // you will actually use after this query. val projection = arrayOf(COLUMN_ID, COLUMN_IV, COLUMN_TYPE, COLUMN_SENDER, COLUMN_RECIPIENT, COLUMN_DATA, COLUMN_ACK_DATA, COLUMN_SENT, COLUMN_RECEIVED, COLUMN_STATUS, COLUMN_TTL, COLUMN_RETRIES, COLUMN_NEXT_TRY, COLUMN_CONVERSATION) - val db = sql.readableDatabase - db.query( + sql.readableDatabase.query( TABLE_NAME, projection, where, null, null, null, "$COLUMN_RECEIVED DESC, $COLUMN_SENT DESC", @@ -206,23 +203,21 @@ class AndroidMessageRepository(private val sql: SqlHelper) : AbstractMessageRepo } } - private fun getValues(message: Plaintext): ContentValues { - val values = ContentValues() - values.put(COLUMN_IV, message.inventoryVector?.hash) - values.put(COLUMN_TYPE, message.type.name) - values.put(COLUMN_SENDER, message.from.address) - values.put(COLUMN_RECIPIENT, message.to?.address) - values.put(COLUMN_DATA, Encode.bytes(message)) - values.put(COLUMN_ACK_DATA, message.ackData) - values.put(COLUMN_SENT, message.sent) - values.put(COLUMN_RECEIVED, message.received) - values.put(COLUMN_STATUS, message.status.name) - values.put(COLUMN_INITIAL_HASH, message.initialHash) - values.put(COLUMN_TTL, message.ttl) - values.put(COLUMN_RETRIES, message.retries) - values.put(COLUMN_NEXT_TRY, message.nextTry) - values.put(COLUMN_CONVERSATION, UuidUtils.asBytes(message.conversationId)) - return values + private fun getValues(message: Plaintext) = ContentValues(14).apply { + put(COLUMN_IV, message.inventoryVector?.hash) + put(COLUMN_TYPE, message.type.name) + put(COLUMN_SENDER, message.from.address) + put(COLUMN_RECIPIENT, message.to?.address) + put(COLUMN_DATA, Encode.bytes(message)) + put(COLUMN_ACK_DATA, message.ackData) + put(COLUMN_SENT, message.sent) + put(COLUMN_RECEIVED, message.received) + put(COLUMN_STATUS, message.status.name) + put(COLUMN_INITIAL_HASH, message.initialHash) + put(COLUMN_TTL, message.ttl) + put(COLUMN_RETRIES, message.retries) + put(COLUMN_NEXT_TRY, message.nextTry) + put(COLUMN_CONVERSATION, UuidUtils.asBytes(message.conversationId)) } private fun insert(db: SQLiteDatabase, message: Plaintext) { @@ -235,8 +230,7 @@ class AndroidMessageRepository(private val sql: SqlHelper) : AbstractMessageRepo } override fun remove(message: Plaintext) { - val db = sql.writableDatabase - db.delete(TABLE_NAME, "id = ?", arrayOf(message.id.toString())) + sql.writableDatabase.delete(TABLE_NAME, "id = ?", arrayOf(message.id.toString())) } companion object { diff --git a/app/src/main/java/ch/dissem/apps/abit/repository/AndroidNodeRegistry.kt b/app/src/main/java/ch/dissem/apps/abit/repository/AndroidNodeRegistry.kt index 5e4a68f..60975de 100644 --- a/app/src/main/java/ch/dissem/apps/abit/repository/AndroidNodeRegistry.kt +++ b/app/src/main/java/ch/dissem/apps/abit/repository/AndroidNodeRegistry.kt @@ -5,7 +5,6 @@ import android.database.sqlite.SQLiteConstraintException import android.database.sqlite.SQLiteDoneException import android.database.sqlite.SQLiteStatement import ch.dissem.bitmessage.entity.valueobject.NetworkAddress -import ch.dissem.bitmessage.exception.ApplicationException import ch.dissem.bitmessage.ports.NodeRegistry import ch.dissem.bitmessage.ports.NodeRegistryHelper.loadStableNodes import ch.dissem.bitmessage.utils.Collections @@ -120,19 +119,20 @@ class AndroidNodeRegistry(private val sql: SqlHelper) : NodeRegistry { private fun insert(node: NetworkAddress) { try { // Create a new map of values, where column names are the keys - val values = ContentValues() - values.put(COLUMN_STREAM, node.stream) - values.put(COLUMN_ADDRESS, node.IPv6) - values.put(COLUMN_PORT, node.port) - values.put(COLUMN_SERVICES, node.services) - values.put(COLUMN_TIME, - if (node.time > UnixTime.now) { - // This might be an attack, let's not use those nodes with priority - UnixTime.now - 7 * UnixTime.DAY - } else { - node.time - } - ) + val values = ContentValues().apply { + put(COLUMN_STREAM, node.stream) + put(COLUMN_ADDRESS, node.IPv6) + put(COLUMN_PORT, node.port) + put(COLUMN_SERVICES, node.services) + put(COLUMN_TIME, + if (node.time > UnixTime.now) { + // This might be an attack, let's not use those nodes with priority + UnixTime.now - 7 * UnixTime.DAY + } else { + node.time + } + ) + } sql.writableDatabase.insertOrThrow(TABLE_NAME, null, values) } catch (e: SQLiteConstraintException) { @@ -150,9 +150,10 @@ class AndroidNodeRegistry(private val sql: SqlHelper) : NodeRegistry { } // Create a new map of values, where column names are the keys - val values = ContentValues() - values.put(COLUMN_SERVICES, node.services) - values.put(COLUMN_TIME, max(node.time, time)) + val values = ContentValues().apply { + put(COLUMN_SERVICES, node.services) + put(COLUMN_TIME, max(node.time, time)) + } sql.writableDatabase.update( TABLE_NAME, diff --git a/app/src/main/java/ch/dissem/apps/abit/repository/AndroidProofOfWorkRepository.kt b/app/src/main/java/ch/dissem/apps/abit/repository/AndroidProofOfWorkRepository.kt index 45a387f..f7510c2 100644 --- a/app/src/main/java/ch/dissem/apps/abit/repository/AndroidProofOfWorkRepository.kt +++ b/app/src/main/java/ch/dissem/apps/abit/repository/AndroidProofOfWorkRepository.kt @@ -48,28 +48,27 @@ class AndroidProofOfWorkRepository(private val sql: SqlHelper) : ProofOfWorkRepo // you will actually use after this query. val projection = arrayOf(COLUMN_DATA, COLUMN_VERSION, COLUMN_NONCE_TRIALS_PER_BYTE, COLUMN_EXTRA_BYTES, COLUMN_EXPIRATION_TIME, COLUMN_MESSAGE_ID) - val db = sql.readableDatabase - db.query( - TABLE_NAME, projection, - "initial_hash=X'${hex(initialHash)}'", - null, null, null, null + sql.readableDatabase.query( + TABLE_NAME, projection, + "initial_hash=X'${hex(initialHash)}'", + null, null, null, null ).use { c -> if (c.moveToFirst()) { val version = c.getInt(c.getColumnIndex(COLUMN_VERSION)) val blob = c.getBlob(c.getColumnIndex(COLUMN_DATA)) return if (c.isNull(c.getColumnIndex(COLUMN_MESSAGE_ID))) { ProofOfWorkRepository.Item( - Factory.getObjectMessage(version, ByteArrayInputStream(blob), blob.size) ?: throw RuntimeException("Invalid object in repository"), - c.getLong(c.getColumnIndex(COLUMN_NONCE_TRIALS_PER_BYTE)), - c.getLong(c.getColumnIndex(COLUMN_EXTRA_BYTES)) + Factory.getObjectMessage(version, ByteArrayInputStream(blob), blob.size) ?: throw RuntimeException("Invalid object in repository"), + c.getLong(c.getColumnIndex(COLUMN_NONCE_TRIALS_PER_BYTE)), + c.getLong(c.getColumnIndex(COLUMN_EXTRA_BYTES)) ) } else { ProofOfWorkRepository.Item( - Factory.getObjectMessage(version, ByteArrayInputStream(blob), blob.size) ?: throw RuntimeException("Invalid object in repository"), - c.getLong(c.getColumnIndex(COLUMN_NONCE_TRIALS_PER_BYTE)), - c.getLong(c.getColumnIndex(COLUMN_EXTRA_BYTES)), - c.getLong(c.getColumnIndex(COLUMN_EXPIRATION_TIME)), - bmc.messageRepository.getMessage(c.getLong(c.getColumnIndex(COLUMN_MESSAGE_ID))) + Factory.getObjectMessage(version, ByteArrayInputStream(blob), blob.size) ?: throw RuntimeException("Invalid object in repository"), + c.getLong(c.getColumnIndex(COLUMN_NONCE_TRIALS_PER_BYTE)), + c.getLong(c.getColumnIndex(COLUMN_EXTRA_BYTES)), + c.getLong(c.getColumnIndex(COLUMN_EXPIRATION_TIME)), + bmc.messageRepository.getMessage(c.getLong(c.getColumnIndex(COLUMN_MESSAGE_ID))) ) } } @@ -82,10 +81,9 @@ class AndroidProofOfWorkRepository(private val sql: SqlHelper) : ProofOfWorkRepo // you will actually use after this query. val projection = arrayOf(COLUMN_INITIAL_HASH) - val db = sql.readableDatabase val result = LinkedList() - db.query( - TABLE_NAME, projection, null, null, null, null, null + sql.readableDatabase.query( + TABLE_NAME, projection, null, null, null, null, null ).use { c -> while (c.moveToNext()) { val initialHash = c.getBlob(c.getColumnIndex(COLUMN_INITIAL_HASH)) @@ -97,20 +95,20 @@ class AndroidProofOfWorkRepository(private val sql: SqlHelper) : ProofOfWorkRepo override fun putObject(item: ProofOfWorkRepository.Item) { try { - val db = sql.writableDatabase // Create a new map of values, where column names are the keys - val values = ContentValues() - values.put(COLUMN_INITIAL_HASH, cryptography().getInitialHash(item.objectMessage)) - values.put(COLUMN_DATA, Encode.bytes(item.objectMessage)) - values.put(COLUMN_VERSION, item.objectMessage.version) - values.put(COLUMN_NONCE_TRIALS_PER_BYTE, item.nonceTrialsPerByte) - values.put(COLUMN_EXTRA_BYTES, item.extraBytes) - item.message?.let { message -> - values.put(COLUMN_EXPIRATION_TIME, item.expirationTime) - values.put(COLUMN_MESSAGE_ID, message.id as Long?) + val values = ContentValues().apply { + put(COLUMN_INITIAL_HASH, cryptography().getInitialHash(item.objectMessage)) + put(COLUMN_DATA, Encode.bytes(item.objectMessage)) + put(COLUMN_VERSION, item.objectMessage.version) + put(COLUMN_NONCE_TRIALS_PER_BYTE, item.nonceTrialsPerByte) + put(COLUMN_EXTRA_BYTES, item.extraBytes) + item.message?.let { message -> + put(COLUMN_EXPIRATION_TIME, item.expirationTime) + put(COLUMN_MESSAGE_ID, message.id as Long?) + } } - db.insertOrThrow(TABLE_NAME, null, values) + sql.writableDatabase.insertOrThrow(TABLE_NAME, null, values) } catch (e: SQLiteConstraintException) { LOG.trace(e.message, e) } @@ -121,8 +119,7 @@ class AndroidProofOfWorkRepository(private val sql: SqlHelper) : ProofOfWorkRepo putObject(ProofOfWorkRepository.Item(objectMessage, nonceTrialsPerByte, extraBytes)) override fun removeObject(initialHash: ByteArray) { - val db = sql.writableDatabase - db.delete(TABLE_NAME, "initial_hash=X'${hex(initialHash)}'", null) + sql.writableDatabase.delete(TABLE_NAME, "initial_hash=X'${hex(initialHash)}'", null) } companion object { diff --git a/app/src/main/java/ch/dissem/apps/abit/repository/SqlHelper.kt b/app/src/main/java/ch/dissem/apps/abit/repository/SqlHelper.kt index 833039e..588b117 100644 --- a/app/src/main/java/ch/dissem/apps/abit/repository/SqlHelper.kt +++ b/app/src/main/java/ch/dissem/apps/abit/repository/SqlHelper.kt @@ -32,42 +32,42 @@ class SqlHelper(private val ctx: Context) : SQLiteOpenHelper(ctx, DATABASE_NAME, override fun onCreate(db: SQLiteDatabase) = onUpgrade(db, 0, DATABASE_VERSION) override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) = mapOf( - 0 to { - executeMigration(db, "V1.0__Create_table_inventory") - executeMigration(db, "V1.1__Create_table_address") - executeMigration(db, "V1.2__Create_table_message") - }, - 1 to { - // executeMigration(db, "V2.0__Update_table_message"); - executeMigration(db, "V2.1__Create_table_POW") - }, - 2 to { - executeMigration(db, "V3.0__Update_table_address") - }, - 3 to { - executeMigration(db, "V3.1__Update_table_POW") - executeMigration(db, "V3.2__Update_table_message") - }, - 4 to { - executeMigration(db, "V3.3__Create_table_node") - }, - 5 to { - executeMigration(db, "V3.4__Add_label_outbox") - }, - 6 to { - executeMigration(db, "V4.0__Create_table_message_parent") - }, - 7 to { - setMissingConversationIds(db) - } + 0 to { + executeMigration(db, "V1.0__Create_table_inventory") + executeMigration(db, "V1.1__Create_table_address") + executeMigration(db, "V1.2__Create_table_message") + }, + 1 to { + // executeMigration(db, "V2.0__Update_table_message"); + executeMigration(db, "V2.1__Create_table_POW") + }, + 2 to { + executeMigration(db, "V3.0__Update_table_address") + }, + 3 to { + executeMigration(db, "V3.1__Update_table_POW") + executeMigration(db, "V3.2__Update_table_message") + }, + 4 to { + executeMigration(db, "V3.3__Create_table_node") + }, + 5 to { + executeMigration(db, "V3.4__Add_label_outbox") + }, + 6 to { + executeMigration(db, "V4.0__Create_table_message_parent") + }, + 7 to { + setMissingConversationIds(db) + } ).filterKeys { it in oldVersion until newVersion }.forEach { (_, v) -> v.invoke() } /** * Set UUIDs for all messages that have no conversation ID */ private fun setMissingConversationIds(db: SQLiteDatabase) = db.query( - "Message", arrayOf("id"), - "conversation IS NULL", null, null, null, null + "Message", arrayOf("id"), + "conversation IS NULL", null, null, null, null ).use { c -> while (c.moveToNext()) { val id = c.getLong(0) @@ -76,8 +76,9 @@ class SqlHelper(private val ctx: Context) : SQLiteOpenHelper(ctx, DATABASE_NAME, } private fun setMissingConversationId(id: Long, db: SQLiteDatabase) { - val values = ContentValues(1) - values.put("conversation", UuidUtils.asBytes(UUID.randomUUID())) + val values = ContentValues(1).apply { + put("conversation", UuidUtils.asBytes(UUID.randomUUID())) + } db.update("Message", values, "id=?", arrayOf(id.toString())) }