Allow missing recipient for drafts
This commit is contained in:
parent
fab1c06135
commit
681ea148db
@ -87,10 +87,10 @@ class Plaintext private constructor(
|
|||||||
if (to == null) {
|
if (to == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (this.to != null) {
|
this.to?.let {
|
||||||
if (this.to!!.version != 0L)
|
if (it.version != 0L)
|
||||||
throw IllegalStateException("Correct address already set")
|
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")
|
throw IllegalArgumentException("RIPEs don't match")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -187,7 +187,8 @@ class Plaintext private constructor(
|
|||||||
Factory.getObjectMessage(
|
Factory.getObjectMessage(
|
||||||
3,
|
3,
|
||||||
ByteArrayInputStream(ackMessage),
|
ByteArrayInputStream(ackMessage),
|
||||||
ackMessage.size)
|
ackMessage.size
|
||||||
|
)
|
||||||
} else null
|
} else null
|
||||||
},
|
},
|
||||||
conversationId = conversationId,
|
conversationId = conversationId,
|
||||||
@ -243,7 +244,8 @@ class Plaintext private constructor(
|
|||||||
Factory.getObjectMessage(
|
Factory.getObjectMessage(
|
||||||
3,
|
3,
|
||||||
ByteArrayInputStream(ackMsg),
|
ByteArrayInputStream(ackMsg),
|
||||||
ackMsg.size)
|
ackMsg.size
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
Factory.createAck(builder.from!!, builder.ackData, builder.ttl)
|
Factory.createAck(builder.from!!, builder.ackData, builder.ttl)
|
||||||
}
|
}
|
||||||
@ -462,7 +464,12 @@ class Plaintext private constructor(
|
|||||||
}
|
}
|
||||||
}.invoke()
|
}.invoke()
|
||||||
if (item.type == MSG) {
|
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.encodingCode, out)
|
||||||
Encode.varInt(item.message.size, out)
|
Encode.varInt(item.message.size, out)
|
||||||
@ -508,7 +515,12 @@ class Plaintext private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (item.type == MSG) {
|
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.varInt(item.encodingCode, buffer)
|
||||||
Encode.varBytes(item.message, buffer)
|
Encode.varBytes(item.message, buffer)
|
||||||
@ -727,7 +739,8 @@ class Plaintext private constructor(
|
|||||||
|
|
||||||
internal fun prepare(): Builder {
|
internal fun prepare(): Builder {
|
||||||
if (from == null) {
|
if (from == null) {
|
||||||
from = BitmessageAddress(Factory.createPubkey(
|
from = BitmessageAddress(
|
||||||
|
Factory.createPubkey(
|
||||||
addressVersion,
|
addressVersion,
|
||||||
stream,
|
stream,
|
||||||
publicSigningKey!!,
|
publicSigningKey!!,
|
||||||
@ -735,7 +748,8 @@ class Plaintext private constructor(
|
|||||||
nonceTrialsPerByte,
|
nonceTrialsPerByte,
|
||||||
extraBytes,
|
extraBytes,
|
||||||
behaviorBitfield
|
behaviorBitfield
|
||||||
))
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (to == null && type != Type.BROADCAST && destinationRipe != null) {
|
if (to == null && type != Type.BROADCAST && destinationRipe != null) {
|
||||||
to = BitmessageAddress(0, 0, destinationRipe!!)
|
to = BitmessageAddress(0, 0, destinationRipe!!)
|
||||||
@ -743,7 +757,7 @@ class Plaintext private constructor(
|
|||||||
if (preventAck) {
|
if (preventAck) {
|
||||||
ackData = null
|
ackData = null
|
||||||
ackMessage = 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)
|
ackData = cryptography().randomBytes(Msg.ACK_LENGTH)
|
||||||
}
|
}
|
||||||
if (ttl <= 0) {
|
if (ttl <= 0) {
|
||||||
@ -784,7 +798,9 @@ class Plaintext private constructor(
|
|||||||
.publicEncryptionKey(Decode.bytes(input, 64))
|
.publicEncryptionKey(Decode.bytes(input, 64))
|
||||||
.nonceTrialsPerByte(if (version >= 3) Decode.varInt(input) else 0)
|
.nonceTrialsPerByte(if (version >= 3) Decode.varInt(input) else 0)
|
||||||
.extraBytes(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))
|
.encoding(Decode.varInt(input))
|
||||||
.message(Decode.varBytes(input))
|
.message(Decode.varBytes(input))
|
||||||
.ackMessage(if (type == MSG) Decode.varBytes(input) else null)
|
.ackMessage(if (type == MSG) Decode.varBytes(input) else null)
|
||||||
|
@ -123,6 +123,31 @@ class SerializationTest : TestBase() {
|
|||||||
assertEquals(expected, actual)
|
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
|
@Test
|
||||||
fun `ensure plaintext with ack message is serialized and deserialized correctly`() {
|
fun `ensure plaintext with ack message is serialized and deserialized correctly`() {
|
||||||
val expected = Plaintext.Builder(MSG)
|
val expected = Plaintext.Builder(MSG)
|
||||||
|
Loading…
Reference in New Issue
Block a user