Skip to content

Commit

Permalink
fixed bug: consider charset of response when decoding strings
Browse files Browse the repository at this point in the history
  • Loading branch information
gmuth committed Mar 23, 2020
1 parent de0ee81 commit 27cb503
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 58 deletions.
4 changes: 3 additions & 1 deletion src/main/kotlin/ipp/printJobByteArrayVersion.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ package ipp
import java.io.*
import java.net.HttpURLConnection
import java.net.URI
import java.nio.charset.Charset

fun main(args: Array<String>) {
val (printerURI, documentInputStream) = getArgsOrThrowUsage(args)
printJobByteArrayVersion(printerURI, documentInputStream)
}

fun printJobByteArrayVersion(uri: URI, documentInputStream: InputStream) {
val charset = Charsets.UTF_8
var charset = Charsets.US_ASCII

// encode Print-Job operation
val byteArrayOutputStream = ByteArrayOutputStream()
Expand Down Expand Up @@ -91,6 +92,7 @@ fun printJobByteArrayVersion(uri: URI, documentInputStream: InputStream) {
}
}
println(String.format(" %s (%02X) = %s", name, tag, value))
if (name == "attributes-charset") charset = Charset.forName(value as String)
} while (tag != 0x03.toByte())
}
}
115 changes: 58 additions & 57 deletions src/main/kotlin/ipp/printJobStreamingVersion.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,83 +11,84 @@ import java.io.IOException
import java.io.InputStream
import java.net.HttpURLConnection
import java.net.URI
import java.nio.charset.Charset

fun main(args: Array<String>) {
val (printerURI, documentInputStream) = getArgsOrThrowUsage(args)
printJobStreamingVersion(printerURI, documentInputStream)
}

fun printJobStreamingVersion(uri: URI, documentInputStream: InputStream) {
val charset = Charsets.UTF_8
var charset = Charsets.US_ASCII
val ippContentType = "application/ipp"

println("send ipp request to $uri")
with(uri.toURL().openConnection() as HttpURLConnection) {
val ippContentType = "application/ipp"
val httpURLConnection = uri.toURL().openConnection() as HttpURLConnection
with(httpURLConnection) {
setConnectTimeout(3000)
setDoOutput(true)
setRequestProperty("Content-Type", ippContentType)

// encode ipp request 'Print-Job operation'
with(DataOutputStream(outputStream)) {
fun writeAttribute(tag: Int, name: String, value: String) {
writeByte(tag)
writeShort(name.length)
write(name.toByteArray(charset))
writeShort(value.length)
write(value.toByteArray(charset))
}
writeShort(0x0101) // ipp version
writeShort(0x0002) // print job operation
writeInt(0x002A) // request id
writeByte(0x01) // operation group tag
writeAttribute(0x47, "attributes-charset", charset.name().toLowerCase())
writeAttribute(0x48, "attributes-natural-language", "en")
writeAttribute(0x45, "printer-uri", "$uri")
writeByte(0x03) // end tag
// append document
documentInputStream.copyTo(outputStream)
close()
outputStream.close()
}
// encode ipp request 'Print-Job operation'
with(DataOutputStream(httpURLConnection.outputStream)) {
fun writeAttribute(tag: Int, name: String, value: String) {
writeByte(tag)
writeShort(name.length)
write(name.toByteArray(charset))
writeShort(value.length)
write(value.toByteArray(charset))
}

// check http response
writeShort(0x0101) // ipp version
writeShort(0x0002) // print job operation
writeInt(0x002A) // request id
writeByte(0x01) // operation group tag
writeAttribute(0x47, "attributes-charset", charset.name().toLowerCase())
writeAttribute(0x48, "attributes-natural-language", "en")
writeAttribute(0x45, "printer-uri", "$uri")
writeByte(0x03) // end tag
// append document
documentInputStream.copyTo(httpURLConnection.outputStream)
close()
}
// check http response
with(httpURLConnection) {
if (getHeaderField("Content-Type") != ippContentType) {
throw IOException("response from $uri is not '$ippContentType'")
}
if (responseCode != 200) {
throw IOException("post to $uri failed with http status $responseCode")
}

// decode ipp response
with(DataInputStream(inputStream)) {
fun readValue(): ByteArray = readNBytes(readShort().toInt())
println(String.format("ipp version %d.%s", readByte(), readByte()))
println(String.format("ipp status %04X", readShort()))
readInt() // ignore request id
var tag: Byte
do {
tag = readByte()
if (tag < 0x10) {
println(String.format("group %02X", tag))
continue
}
// decode ipp response
with(DataInputStream(httpURLConnection.inputStream)) {
fun readValue(): ByteArray = readNBytes(readShort().toInt())
println(String.format("ipp version %d.%s", readByte(), readByte()))
println(String.format("ipp status %04X", readShort()))
readInt() // ignore request id
var tag: Byte
do {
tag = readByte()
if (tag < 0x10) {
println(String.format("group %02X", tag))
continue
}
// attribute tag
val name = String(readValue(), charset)
val value: Any = when (tag.toInt()) {
0x21, 0x23 -> {
readShort()
readInt()
}
// attribute tag
val name = String(readValue(), charset)
val value: Any = when (tag.toInt()) {
0x21, 0x23 -> {
readShort()
readInt()
}
0x41, 0x44, 0x45, 0x47, 0x48 -> {
String(readValue(), charset)
}
else -> {
readValue()
String.format("<decoding-tag-%02X-not-implemented>", tag)
}
0x41, 0x44, 0x45, 0x47, 0x48 -> {
String(readValue(), charset)
}
println(String.format(" %s (%02X) = %s", name, tag, value))
} while (tag != 0x03.toByte())
}
else -> {
readValue()
String.format("<decoding-tag-%02X-not-implemented>", tag)
}
}
println(String.format(" %s (%02X) = %s", name, tag, value))
if (name == "attributes-charset") charset = Charset.forName(value as String)
} while (tag != 0x03.toByte())
}
}

0 comments on commit 27cb503

Please sign in to comment.