Allow missing recipient for drafts

This commit is contained in:
Christian Basler 2018-02-16 17:04:24 +01:00
parent fab1c06135
commit 681ea148db
2 changed files with 59 additions and 18 deletions

View File

@ -87,10 +87,10 @@ class Plaintext private constructor(
if (to == null) {
return
}
if (this.to != null) {
if (this.to!!.version != 0L)
this.to?.let {
if (it.version != 0L)
throw IllegalStateException("Correct address already set")
if (!Arrays.equals(this.to!!.ripe, to.ripe)) {
if (!Arrays.equals(it.ripe, to.ripe)) {
throw IllegalArgumentException("RIPEs don't match")
}
}
@ -187,7 +187,8 @@ class Plaintext private constructor(
Factory.getObjectMessage(
3,
ByteArrayInputStream(ackMessage),
ackMessage.size)
ackMessage.size
)
} else null
},
conversationId = conversationId,
@ -243,7 +244,8 @@ class Plaintext private constructor(
Factory.getObjectMessage(
3,
ByteArrayInputStream(ackMsg),
ackMsg.size)
ackMsg.size
)
} else {
Factory.createAck(builder.from!!, builder.ackData, builder.ttl)
}
@ -462,7 +464,12 @@ class Plaintext private constructor(
}
}.invoke()
if (item.type == MSG) {
out.write(item.to?.ripe ?: throw IllegalStateException("No recipient set for message"))
// A draft without recipient is allowed, therefore this workaround.
item.to?.let { out.write(it.ripe) } ?: if (item.status == Status.DRAFT) {
out.write(ByteArray(20))
} else {
throw IllegalStateException("No recipient set for message")
}
}
Encode.varInt(item.encodingCode, out)
Encode.varInt(item.message.size, out)
@ -508,7 +515,12 @@ class Plaintext private constructor(
}
}
if (item.type == MSG) {
buffer.put(item.to!!.ripe)
// A draft without recipient is allowed, therefore this workaround.
item.to?.let { buffer.put(it.ripe) } ?: if (item.status == Status.DRAFT) {
buffer.put(ByteArray(20))
} else {
throw IllegalStateException("No recipient set for message")
}
}
Encode.varInt(item.encodingCode, buffer)
Encode.varBytes(item.message, buffer)
@ -727,15 +739,17 @@ class Plaintext private constructor(
internal fun prepare(): Builder {
if (from == null) {
from = BitmessageAddress(Factory.createPubkey(
addressVersion,
stream,
publicSigningKey!!,
publicEncryptionKey!!,
nonceTrialsPerByte,
extraBytes,
behaviorBitfield
))
from = BitmessageAddress(
Factory.createPubkey(
addressVersion,
stream,
publicSigningKey!!,
publicEncryptionKey!!,
nonceTrialsPerByte,
extraBytes,
behaviorBitfield
)
)
}
if (to == null && type != Type.BROADCAST && destinationRipe != null) {
to = BitmessageAddress(0, 0, destinationRipe!!)
@ -743,7 +757,7 @@ class Plaintext private constructor(
if (preventAck) {
ackData = null
ackMessage = null
} else if (type == MSG && ackMessage == null && ackData == null) {
} else if (type == MSG && ackMessage == null && ackData == null && to?.has(Feature.DOES_ACK) == true) {
ackData = cryptography().randomBytes(Msg.ACK_LENGTH)
}
if (ttl <= 0) {
@ -784,7 +798,9 @@ class Plaintext private constructor(
.publicEncryptionKey(Decode.bytes(input, 64))
.nonceTrialsPerByte(if (version >= 3) Decode.varInt(input) else 0)
.extraBytes(if (version >= 3) Decode.varInt(input) else 0)
.destinationRipe(if (type == MSG) Decode.bytes(input, 20) else null)
.destinationRipe(if (type == MSG) Decode.bytes(input, 20).let {
if (it.any { x -> x != 0.toByte() }) it else null
} else null)
.encoding(Decode.varInt(input))
.message(Decode.varBytes(input))
.ackMessage(if (type == MSG) Decode.varBytes(input) else null)

View File

@ -123,6 +123,31 @@ class SerializationTest : TestBase() {
assertEquals(expected, actual)
}
@Test
fun `ensure plaintext without recipient can be serialized (needed for saving drafts)`() {
val expected = Plaintext.Builder(MSG)
.from(TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8"))
.message(Message.Builder()
.subject("Subject")
.body("Message")
.build())
.signature(ByteArray(0))
.status(Plaintext.Status.DRAFT)
.build()
val out = ByteArrayOutputStream()
expected.writer().write(out)
val input = ByteArrayInputStream(out.toByteArray())
val actual = Plaintext.read(MSG, input)
actual.status = Plaintext.Status.DRAFT // status isn't serialized, that's OK
// Received is automatically set on deserialization, so we'll need to set it to null
val received = Plaintext::class.java.getDeclaredField("received")
received.isAccessible = true
received.set(actual, null)
assertEquals(expected, actual)
}
@Test
fun `ensure plaintext with ack message is serialized and deserialized correctly`() {
val expected = Plaintext.Builder(MSG)