Last active
June 8, 2019 08:05
-
-
Save Skhmt/b5d1b4145b5d316ca74dee652b669e94 to your computer and use it in GitHub Desktop.
png mixed content
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import io.javalin.Javalin | |
import java.util.zip.CRC32 | |
import java.util.zip.Deflater | |
/* | |
main requires: | |
io.javalin:javalin:2.7.0 | |
org.slf4j:slf4j-simple:1.7.25 | |
test at: | |
https://skhmt.github.io/https.html | |
*/ | |
fun main(args: Array<String>) { | |
val port = 80 | |
val app = Javalin.create() | |
app.enableCorsForAllOrigins() | |
app.start(port) | |
println("running on port $port") | |
app.get("/get.png") { ctx -> | |
val msg = ctx.queryParam("msg") | |
println("${ctx.ip()}: msg=$msg") | |
val png = makePNG(msg!!) | |
ctx.result(png.inputStream()) | |
} | |
} | |
fun makePNG(data: String): ByteArray { | |
val dataAsByteArray = data.toByteArray(Charsets.UTF_8) // string (utf8) as a byte array | |
return (pngSignature() + | |
pngIHDR(dataAsByteArray.size,1) + | |
pngIDAT(dataAsByteArray) + | |
pngIEND()) | |
} | |
// PNG Signature - https://www.w3.org/TR/PNG/#5PNG-file-signature | |
fun pngSignature(): ByteArray { | |
return byteArrayOf(-119,80,78,71,13,10,26,10) | |
} | |
// PNG IHDR chunk - https://www.w3.org/TR/PNG/#11IHDR | |
fun pngIHDR(width: Int, height: Int): ByteArray { | |
val ihdrLength = byteArrayOf(0,0,0,13) | |
val ihdrType = byteArrayOf(73,72,68,82) | |
val ihdrData = byteArrayOf( | |
*intToBA(width), // width | |
*intToBA(height), // height | |
8, // bitdepth - 8 so each pixel is a byte | |
0, // color type - 0 is greyscale | |
0,0,0 // compression, filter, and interlace methods - must be 0 | |
) | |
val ihdrCRC = getCRC(ihdrType, ihdrData) | |
return (ihdrLength + | |
ihdrType + | |
ihdrData + | |
ihdrCRC) | |
} | |
// PNG IDAT chunk - https://www.w3.org/TR/PNG/#11IDAT | |
fun pngIDAT(data: ByteArray): ByteArray { | |
val idatType = byteArrayOf(73,68,65,84) | |
val idatData = deflate(byteArrayOf(0, *data)) // filter type 0 (no filter) | |
val idatCRC = getCRC(idatType, idatData) | |
val idatLength = intToBA(idatData.size) // compressed data length | |
return (idatLength + | |
idatType + | |
idatData + | |
idatCRC) | |
} | |
// PNG IEND chunk - https://www.w3.org/TR/PNG/#11IEND | |
fun pngIEND(): ByteArray { | |
return byteArrayOf(0,0,0,0,73,69,78,68,-82,66,96,-126) | |
} | |
// convenience function to use Java's built-in CRC32 library | |
private fun getCRC(ba1: ByteArray, ba2: ByteArray): ByteArray { | |
val ba = ba1 + ba2 | |
val crc = CRC32() | |
crc.update(ba) | |
return intToBA(crc.value.toInt()) | |
} | |
// this is faster than using a for-loop and faster than ByteBuffer by 15-20x | |
private fun intToBA(num: Int): ByteArray { | |
val ba = ByteArray(4) | |
ba[3] = (num and 0xff).toByte() | |
ba[2] = ((num shr 8) and 0xff).toByte() | |
ba[1] = ((num shr 16) and 0xff).toByte() | |
ba[0] = ((num shr 24) and 0xff).toByte() | |
return ba | |
} | |
// convenience function to use Java's built-in Deflater library | |
// the buffer can be modified if necessary; it should probably be 32767 | |
private fun deflate(ba: ByteArray): ByteArray { | |
val buffer = ByteArray(1048576) // 2^20 = 1024*1024 = 1MB max | |
val deflater = Deflater() | |
deflater.setInput(ba) | |
deflater.finish() | |
val length = deflater.deflate(buffer) | |
return buffer.sliceArray(0 until length) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment