summaryrefslogtreecommitdiff
path: root/src/main/kotlin/RFC822Parser.kt
diff options
context:
space:
mode:
authornea <romangraef@gmail.com>2022-09-13 00:25:28 +0200
committernea <romangraef@gmail.com>2022-09-13 00:25:28 +0200
commitb7793a83b1f39ff94bfbaeef8ac4c387839a94de (patch)
tree2d89200e800de8230cf91aa4741d9958edd76d0a /src/main/kotlin/RFC822Parser.kt
parent24b3430c42614bc2f9076a8a04d79720c05bb67b (diff)
downloadjavamailserver-b7793a83b1f39ff94bfbaeef8ac4c387839a94de.tar.gz
javamailserver-b7793a83b1f39ff94bfbaeef8ac4c387839a94de.tar.bz2
javamailserver-b7793a83b1f39ff94bfbaeef8ac4c387839a94de.zip
Diffstat (limited to 'src/main/kotlin/RFC822Parser.kt')
-rw-r--r--src/main/kotlin/RFC822Parser.kt58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/main/kotlin/RFC822Parser.kt b/src/main/kotlin/RFC822Parser.kt
new file mode 100644
index 0000000..4a6ce74
--- /dev/null
+++ b/src/main/kotlin/RFC822Parser.kt
@@ -0,0 +1,58 @@
+import kotlinx.coroutines.MainScope
+import java.io.ByteArrayOutputStream
+import java.io.File
+
+suspend fun main() {
+ val io = Protocol.IO.FromStreams(File("samplemail.txt").inputStream(), ByteArrayOutputStream())
+ val rfc = RFC822Parser()
+ rfc.executeAsync(MainScope(), io).join()
+ println(rfc.headers)
+ println("Content: ${rfc.content.decodeToString()}")
+}
+
+class RFC822Parser() : Protocol() {
+
+ class Header(val field: String, val value: ByteArray)
+
+ private val _headers = mutableListOf<Header>()
+ val headers: List<Header> get() = _headers
+ lateinit var content: ByteArray
+ private set
+
+ override suspend fun IO.execute() {
+ while (parseField()) Unit
+ content = readAll()
+ }
+
+ private suspend fun IO.parseField(): Boolean {
+ val read = readUntil(CRLF)
+ if (read.contentEquals(CRLF)) {
+ return false
+ }
+ val indexOfColon = read.indexOf(':'.code.toByte())
+ if (indexOfColon == -1) {
+ throw IllegalStateException("Expected : in MIME header")
+ }
+ val headerField = read.sliceArray(0 until indexOfColon).decodeToString().trim()
+ var data = read.sliceArray(indexOfColon + 1 until read.size)
+ while (true) {
+ val nextLine = readUntil(CRLF)
+ if (nextLine.isNotEmpty() && isWhitespaceCharacter(nextLine[0])) {
+ val oldSize = data.size
+ data = data.copyOf(oldSize + nextLine.size)
+ nextLine.copyInto(data, oldSize)
+ } else {
+ pushBack(CRLF)
+ pushBack(nextLine)
+ break
+ }
+ }
+ _headers.add(Header(headerField, data))
+ return true
+ }
+
+ fun isWhitespaceCharacter(char: Byte): Boolean {
+ val char = char.toInt().toChar()
+ return char == ' ' || char == '\t'
+ }
+}