Commit d19216a6 authored by Him188moe's avatar Him188moe

Updated

parent e3c23b35
...@@ -2,7 +2,7 @@ package net.mamoe.mirai.message.defaults ...@@ -2,7 +2,7 @@ package net.mamoe.mirai.message.defaults
import net.mamoe.mirai.message.Message import net.mamoe.mirai.message.Message
import net.mamoe.mirai.message.MessageId import net.mamoe.mirai.message.MessageId
import net.mamoe.mirai.utils.lazyOutput import net.mamoe.mirai.utils.lazyEncode
import org.intellij.lang.annotations.MagicConstant import org.intellij.lang.annotations.MagicConstant
import java.util.* import java.util.*
import java.util.stream.Collectors import java.util.stream.Collectors
...@@ -71,7 +71,7 @@ class MessageChain : Message { ...@@ -71,7 +71,7 @@ class MessageChain : Message {
return this return this
} }
override fun toByteArray(): ByteArray = lazyOutput { override fun toByteArray(): ByteArray = lazyEncode {
stream().forEach { message -> stream().forEach { message ->
it.write(message.toByteArray()) it.write(message.toByteArray())
} }
......
...@@ -2,7 +2,9 @@ package net.mamoe.mirai.message.defaults ...@@ -2,7 +2,9 @@ package net.mamoe.mirai.message.defaults
import net.mamoe.mirai.message.Message import net.mamoe.mirai.message.Message
import net.mamoe.mirai.message.MessageId import net.mamoe.mirai.message.MessageId
import net.mamoe.mirai.utils.lazyOutput import net.mamoe.mirai.network.packet.writeLVByteArray
import net.mamoe.mirai.network.packet.writeLVString
import net.mamoe.mirai.utils.lazyEncode
/** /**
* @author Him188moe * @author Him188moe
...@@ -14,12 +16,12 @@ class PlainText(private val text: String) : Message() { ...@@ -14,12 +16,12 @@ class PlainText(private val text: String) : Message() {
return text return text
} }
override fun toByteArray(): ByteArray = lazyOutput { section -> override fun toByteArray(): ByteArray = lazyEncode { section ->
section.writeByte(this.type) section.writeByte(this.type)
section.writeVarByteArray(lazyOutput { child -> section.writeLVByteArray(lazyEncode { child ->
child.writeByte(0x01) child.writeByte(0x01)
child.writeVarString(this.text) child.writeLVString(this.text)
}) })
} }
......
...@@ -18,9 +18,13 @@ import net.mamoe.mirai.message.defaults.MessageChain ...@@ -18,9 +18,13 @@ import net.mamoe.mirai.message.defaults.MessageChain
import net.mamoe.mirai.network.BotNetworkHandler.* import net.mamoe.mirai.network.BotNetworkHandler.*
import net.mamoe.mirai.network.packet.* import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.network.packet.action.* import net.mamoe.mirai.network.packet.action.*
import net.mamoe.mirai.network.packet.image.ServerTryUploadGroupImageFailedPacket
import net.mamoe.mirai.network.packet.image.ServerTryUploadGroupImageResponsePacket
import net.mamoe.mirai.network.packet.image.ServerTryUploadGroupImageSuccessPacket
import net.mamoe.mirai.network.packet.login.* import net.mamoe.mirai.network.packet.login.*
import net.mamoe.mirai.task.MiraiThreadPool import net.mamoe.mirai.task.MiraiThreadPool
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.*
import java.awt.image.BufferedImage
import java.io.Closeable import java.io.Closeable
import java.net.DatagramPacket import java.net.DatagramPacket
import java.net.DatagramSocket import java.net.DatagramSocket
...@@ -301,7 +305,7 @@ class BotNetworkHandler(private val bot: Bot) : Closeable { ...@@ -301,7 +305,7 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
private lateinit var loginIP: String private lateinit var loginIP: String
private var tgtgtKey: ByteArray = getRandomByteArray(16) private var tgtgtKey: ByteArray = getRandomByteArray(16)
private var tlv0105: ByteArray = lazyOutput { private var tlv0105: ByteArray = lazyEncode {
it.writeHex("01 05 00 30") it.writeHex("01 05 00 30")
it.writeHex("00 01 01 02 00 14 01 01 00 10") it.writeHex("00 01 01 02 00 14 01 01 00 10")
it.writeRandom(16) it.writeRandom(16)
...@@ -560,14 +564,24 @@ class BotNetworkHandler(private val bot: Bot) : Closeable { ...@@ -560,14 +564,24 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
internal var gtk: Int = 0 internal var gtk: Int = 0
private val addFriendSessions = Collections.synchronizedCollection(mutableListOf<AddFriendSession>()) private val addFriendSessions = Collections.synchronizedCollection(mutableListOf<AddFriendSession>())
private val uploadImageSessions = Collections.synchronizedCollection(mutableListOf<UploadImageSession>())
override fun onPacketReceived(packet: ServerPacket) { override fun onPacketReceived(packet: ServerPacket) {
when (packet) { when (packet) {
is ServerCanAddFriendResponsePacket -> { is ServerCanAddFriendResponsePacket -> {
this.addFriendSessions.forEach { this.uploadImageSessions.forEach {
it.onPacketReceived(packet) it.onPacketReceived(packet)
} }
} }
is ServerTryUploadGroupImageSuccessPacket -> {
ImageNetworkUtils.postImage(packet.uKey.toUHexString(), )
}
is ServerTryUploadGroupImageFailedPacket -> {
}
is ServerTryUploadGroupImageResponsePacket.Encrypted -> distributePacket(packet.decrypt(sessionKey))
else -> { else -> {
} }
} }
...@@ -581,7 +595,7 @@ class BotNetworkHandler(private val bot: Bot) : Closeable { ...@@ -581,7 +595,7 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
fun addFriend(qqNumber: Long, message: Lazy<String> = lazyOf("")): CompletableFuture<AddFriendResult> { fun addFriend(qqNumber: Long, message: Lazy<String> = lazyOf("")): CompletableFuture<AddFriendResult> {
val future = CompletableFuture<AddFriendResult>() val future = CompletableFuture<AddFriendResult>()
val session = AddFriendSession(qqNumber, future, message) val session = AddFriendSession(qqNumber, future, message)
addFriendSessions.add(session) uploadImageSessions.add(session)
session.sendAddRequest(); session.sendAddRequest();
return future return future
} }
...@@ -590,6 +604,58 @@ class BotNetworkHandler(private val bot: Bot) : Closeable { ...@@ -590,6 +604,58 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
} }
private inner class UploadImageSession(
private val group: Long,
private val future: CompletableFuture<AddFriendResult>,
private val image: BufferedImage
) : Closeable {
lateinit var id: ByteArray
fun onPacketReceived(packet: ServerPacket) {
if (!::id.isInitialized) {
return
}
when (packet) {
is ServerCanAddFriendResponsePacket -> {
if (!(packet.idByteArray[2] == id[0] && packet.idByteArray[3] == id[1])) {
return
}
when (packet.state) {
ServerCanAddFriendResponsePacket.State.FAILED -> {
future.complete(AddFriendResult.FAILED)
close()
}
ServerCanAddFriendResponsePacket.State.ALREADY_ADDED -> {
future.complete(AddFriendResult.ALREADY_ADDED)
close()
}
ServerCanAddFriendResponsePacket.State.REQUIRE_VERIFICATION -> {
sendPacket(ClientAddFriendPacket(bot.account.qqNumber, qq, sessionKey))
}
ServerCanAddFriendResponsePacket.State.NOT_REQUIRE_VERIFICATION -> {
}
}
}
}
}
override fun sendRequest() {
}
override fun close() {
uploadImageSessions.remove(this)
}
}
private inner class AddFriendSession( private inner class AddFriendSession(
private val qq: Long, private val qq: Long,
private val future: CompletableFuture<AddFriendResult>, private val future: CompletableFuture<AddFriendResult>,
...@@ -638,7 +704,7 @@ class BotNetworkHandler(private val bot: Bot) : Closeable { ...@@ -638,7 +704,7 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
} }
override fun close() { override fun close() {
addFriendSessions.remove(this) uploadImageSessions.remove(this)
} }
} }
} }
......
package net.mamoe.mirai.network.handler
import net.mamoe.mirai.Bot
import net.mamoe.mirai.network.BotNetworkHandler
/**
* @author Him188moe
*/
data class BotSession(
val bot: Bot,
val sessionKey: ByteArray,
val networkHandler: BotNetworkHandler
) {
}
\ No newline at end of file
...@@ -113,7 +113,7 @@ fun DataOutputStream.encryptAndWrite(byteArray: ByteArray, key: ByteArray) { ...@@ -113,7 +113,7 @@ fun DataOutputStream.encryptAndWrite(byteArray: ByteArray, key: ByteArray) {
} }
fun DataOutputStream.encryptAndWrite(key: ByteArray, encoder: (ByteArrayDataOutputStream) -> Unit) { fun DataOutputStream.encryptAndWrite(key: ByteArray, encoder: (ByteArrayDataOutputStream) -> Unit) {
this.write(TEA.encrypt(ByteArrayDataOutputStream().let { encoder(it); it.toByteArray() }, key)) this.write(TEA.encrypt(ByteArrayDataOutputStream().also(encoder).toByteArray(), key))
} }
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
...@@ -204,7 +204,7 @@ fun Int.toLByteArray(): ByteArray = byteArrayOf( ...@@ -204,7 +204,7 @@ fun Int.toLByteArray(): ByteArray = byteArrayOf(
) )
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
fun Int.toUHexString(separator: String = " "): String = this.toByteArray().toUByteArray().toUHexString(separator) fun Int.toUHexString(separator: String = " "): String = this.toByteArray().toUHexString(separator)
internal fun md5(str: String): ByteArray = MessageDigest.getInstance("MD5").digest(str.toByteArray()) internal fun md5(str: String): ByteArray = MessageDigest.getInstance("MD5").digest(str.toByteArray())
...@@ -237,21 +237,11 @@ fun DataOutputStream.writeGroup(groupIdOrGroupNumber: Long) { ...@@ -237,21 +237,11 @@ fun DataOutputStream.writeGroup(groupIdOrGroupNumber: Long) {
this.write(groupIdOrGroupNumber.toUInt().toByteArray()) this.write(groupIdOrGroupNumber.toUInt().toByteArray())
} }
fun DataOutputStream.writeVarByteArray(byteArray: ByteArray) { fun DataOutputStream.writeLVByteArray(byteArray: ByteArray) {
this.writeShort(byteArray.size) this.writeShort(byteArray.size)
this.write(byteArray) this.write(byteArray)
} }
fun DataOutputStream.writeVarString(str: String) { fun DataOutputStream.writeLVString(str: String) {
this.writeVarByteArray(str.toByteArray()) this.writeLVByteArray(str.toByteArray())
}
fun DataOutputStream.writeVarShort(short: Int) {
this.writeByte(0x02)
this.writeShort(short)
}
fun DataOutputStream.writeVarInt(int: Int) {
this.writeByte(0x04)
this.writeInt(int)
} }
\ No newline at end of file
...@@ -19,7 +19,7 @@ import java.util.zip.GZIPInputStream ...@@ -19,7 +19,7 @@ import java.util.zip.GZIPInputStream
* *
* @author Him188moe * @author Him188moe
*/ */
open class ServerEventPacket(input: DataInputStream, val packetId: ByteArray, val eventIdentity: ByteArray) : ServerPacket(input) { abstract class ServerEventPacket(input: DataInputStream, val packetId: ByteArray, val eventIdentity: ByteArray) : ServerPacket(input) {
@PacketId("00 17") @PacketId("00 17")
class Raw(input: DataInputStream, private val packetId: ByteArray) : ServerPacket(input) { class Raw(input: DataInputStream, private val packetId: ByteArray) : ServerPacket(input) {
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
......
...@@ -7,6 +7,7 @@ import net.mamoe.mirai.network.packet.action.ServerSendGroupMessageResponsePacke ...@@ -7,6 +7,7 @@ import net.mamoe.mirai.network.packet.action.ServerSendGroupMessageResponsePacke
import net.mamoe.mirai.network.packet.login.* import net.mamoe.mirai.network.packet.login.*
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.*
import java.io.DataInputStream import java.io.DataInputStream
import java.io.EOFException
/** /**
* @author Him188moe * @author Him188moe
...@@ -169,7 +170,7 @@ abstract class ServerPacket(val input: DataInputStream) : Packet { ...@@ -169,7 +170,7 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
return this.decryptBy(keyHex1.hexToBytes(), keyHex2.hexToBytes()) return this.decryptBy(keyHex1.hexToBytes(), keyHex2.hexToBytes())
} }
private fun decryptAsByteArray(key: ByteArray): ByteArray { fun decryptAsByteArray(key: ByteArray): ByteArray {
input.goto(14) input.goto(14)
return TEA.decrypt(input.readAllBytes().cutTail(1), key) return TEA.decrypt(input.readAllBytes().cutTail(1), key)
} }
...@@ -257,4 +258,47 @@ fun <N : Number> DataInputStream.readShortAt(position: N): Short { ...@@ -257,4 +258,47 @@ fun <N : Number> DataInputStream.readShortAt(position: N): Short {
return this.readShort(); return this.readShort();
} }
@ExperimentalUnsignedTypes
@JvmSynthetic
fun DataInputStream.gotoWhere(matcher: UByteArray): DataInputStream {
return this.gotoWhere(matcher.toByteArray())
}
/**
* 去往下一个含这些连续字节的位置
*/
@Throws(EOFException::class)
fun DataInputStream.gotoWhere(matcher: ByteArray): DataInputStream {
require(matcher.isNotEmpty())
loop@
do {
val byte = this.readByte()
if (byte == matcher[0]) {
//todo mark here
for (i in 1 until matcher.size) {
val b = this.readByte()
if (b != matcher[i]) {
continue@loop //todo goto mark
}
return this
}
}
} while (true)
}
/*
@Throws(EOFException::class)
fun DataInputStream.gotoWhere(matcher: ByteArray) {
require(matcher.isNotEmpty())
do {
val byte = this.readByte()
if (byte == matcher[0]) {
for (i in 1 until matcher.size){
}
}
} while (true)
}*/
fun ByteArray.cutTail(length: Int): ByteArray = this.copyOfRange(0, this.size - length) fun ByteArray.cutTail(length: Int): ByteArray = this.copyOfRange(0, this.size - length)
\ No newline at end of file
...@@ -4,7 +4,7 @@ import net.mamoe.mirai.network.Protocol ...@@ -4,7 +4,7 @@ import net.mamoe.mirai.network.Protocol
import net.mamoe.mirai.utils.ByteArrayDataOutputStream import net.mamoe.mirai.utils.ByteArrayDataOutputStream
import net.mamoe.mirai.utils.TEA import net.mamoe.mirai.utils.TEA
import net.mamoe.mirai.utils.getRandomByteArray import net.mamoe.mirai.utils.getRandomByteArray
import net.mamoe.mirai.utils.lazyOutput import net.mamoe.mirai.utils.lazyEncode
import java.io.DataInputStream import java.io.DataInputStream
import java.net.InetAddress import java.net.InetAddress
...@@ -85,7 +85,7 @@ class ServerSessionKeyResponsePacket(inputStream: DataInputStream, private val d ...@@ -85,7 +85,7 @@ class ServerSessionKeyResponsePacket(inputStream: DataInputStream, private val d
527 -> { 527 -> {
input.goto(63) input.goto(63)
sessionKey = input.readNBytes(16) sessionKey = input.readNBytes(16)
tlv0105 = lazyOutput { tlv0105 = lazyEncode {
it.writeHex("01 05 00 88 00 01 01 02 00 40 02 01 03 3C 01 03 00 00") it.writeHex("01 05 00 88 00 01 01 02 00 40 02 01 03 3C 01 03 00 00")
input.goto(dataLength - 122) input.goto(dataLength - 122)
it.write(input.readNBytes(56)) it.write(input.readNBytes(56))
......
...@@ -163,7 +163,7 @@ class ServerVerificationCodeWrongPacket(input: DataInputStream, dataSize: Int, p ...@@ -163,7 +163,7 @@ class ServerVerificationCodeWrongPacket(input: DataInputStream, dataSize: Int, p
* @author Him188moe * @author Him188moe
*/ */
@PacketId("00 BA 31") @PacketId("00 BA 31")
open class ServerVerificationCodeTransmissionPacket(input: DataInputStream, private val dataSize: Int, private val packetId: ByteArray) : ServerVerificationCodePacket(input) { abstract class ServerVerificationCodeTransmissionPacket(input: DataInputStream, private val dataSize: Int, private val packetId: ByteArray) : ServerVerificationCodePacket(input) {
lateinit var captchaSectionN: ByteArray lateinit var captchaSectionN: ByteArray
lateinit var verificationToken: ByteArray//56bytes lateinit var verificationToken: ByteArray//56bytes
......
...@@ -111,7 +111,7 @@ class ServerAddGroupResponsePacket(input: DataInputStream) : ServerAddContactRes ...@@ -111,7 +111,7 @@ class ServerAddGroupResponsePacket(input: DataInputStream) : ServerAddContactRes
/** /**
* 添加好友/群的回复 * 添加好友/群的回复
*/ */
open class ServerAddContactResponsePacket(input: DataInputStream) : ServerPacket(input) { abstract class ServerAddContactResponsePacket(input: DataInputStream) : ServerPacket(input) {
class Raw(input: DataInputStream) : ServerPacket(input) { class Raw(input: DataInputStream) : ServerPacket(input) {
......
...@@ -3,7 +3,7 @@ package net.mamoe.mirai.network.packet.action ...@@ -3,7 +3,7 @@ package net.mamoe.mirai.network.packet.action
import net.mamoe.mirai.message.defaults.MessageChain import net.mamoe.mirai.message.defaults.MessageChain
import net.mamoe.mirai.network.Protocol import net.mamoe.mirai.network.Protocol
import net.mamoe.mirai.network.packet.* import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.utils.lazyOutput import net.mamoe.mirai.utils.lazyEncode
import java.io.DataInputStream import java.io.DataInputStream
/** /**
...@@ -29,7 +29,7 @@ class ClientSendFriendMessagePacket( ...@@ -29,7 +29,7 @@ class ClientSendFriendMessagePacket(
it.writeHex("37 0F") it.writeHex("37 0F")
it.writeQQ(botQQ) it.writeQQ(botQQ)
it.writeQQ(targetQQ) it.writeQQ(targetQQ)
it.write(md5(lazyOutput { md5Key -> md5Key.writeQQ(targetQQ); md5Key.write(sessionKey) })) it.write(md5(lazyEncode { md5Key -> md5Key.writeQQ(targetQQ); md5Key.write(sessionKey) }))
it.writeHex("00 0B") it.writeHex("00 0B")
it.writeRandom(2) it.writeRandom(2)
it.writeTime() it.writeTime()
......
...@@ -4,16 +4,19 @@ import net.mamoe.mirai.network.packet.* ...@@ -4,16 +4,19 @@ import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.utils.toByteArray import net.mamoe.mirai.utils.toByteArray
import net.mamoe.mirai.utils.writeUVarInt import net.mamoe.mirai.utils.writeUVarInt
import java.awt.image.BufferedImage import java.awt.image.BufferedImage
import java.io.DataInputStream
/** /**
* 查询群消息的 image id. * 请求上传图片. 将发送图片的 md5, size.
* That is, 查询服务器上是否有这个图片, 有就返回 id, 没有就需要上传 * 服务器返回以下之一:
* - 服务器已经存有这个图片 [ServerTryUploadGroupImageFailedPacket]
* - 服务器未存有, 返回一个 key 用于客户端上传 [ServerTryUploadGroupImageSuccessPacket]
* *
* @author Him188moe * @author Him188moe
*/ */
@PacketId("03 88") @PacketId("03 88")
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
class ClientGetGroupImageIDPacket( class ClientTryGetGroupImageIDPacket(
private val bot: Long, private val bot: Long,
private val sessionKey: ByteArray, private val sessionKey: ByteArray,
private val group: Long, private val group: Long,
...@@ -85,6 +88,41 @@ class ClientGetGroupImageIDPacket( ...@@ -85,6 +88,41 @@ class ClientGetGroupImageIDPacket(
} }
} }
abstract class ServerTryUploadGroupImageResponsePacket(input: DataInputStream) : ServerPacket(input) {
class Encrypted(input: DataInputStream) : ServerPacket(input) {
fun decrypt(sessionKey: ByteArray): ServerTryUploadGroupImageResponsePacket {
val data = this.decryptAsByteArray(sessionKey)
if (data.size == 239) {
return ServerTryUploadGroupImageSuccessPacket(data.dataInputStream()).setId(this.idHex)
}
return ServerTryUploadGroupImageFailedPacket(data.dataInputStream())
}
}
}
/**
* 服务器未存有图片, 返回一个 key 用于客户端上传
*/
class ServerTryUploadGroupImageSuccessPacket(input: DataInputStream) : ServerTryUploadGroupImageResponsePacket(input) {
lateinit var uKey: ByteArray
@ExperimentalUnsignedTypes
override fun decode() {
uKey = this.input.gotoWhere(ubyteArrayOf(0x42u, 0x80u, 0x01u)).readNBytes(128)
}
}
/**
* 服务器已经存有这个图片
*/
class ServerTryUploadGroupImageFailedPacket(input: DataInputStream) : ServerTryUploadGroupImageResponsePacket(input) {
override fun decode() {
}
}
fun main() { fun main() {
println(0xff) println(0xff)
......
package net.mamoe.mirai.utils; package net.mamoe.mirai.utils;
import org.apache.commons.httpclient.util.HttpURLConnection; import org.apache.commons.httpclient.util.HttpURLConnection;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.net.URL; import java.net.URL;
/**
* @author NaturalHG
*/
public class ImageNetworkUtils { public class ImageNetworkUtils {
public static void postImage(String ukey, int fileSize, String g_uin,String groupCode, byte[] img){ public static void postImage(String uKeyHex, int fileSize, String qqNumber, String groupCode, byte[] img) throws IOException {
//http://htdata2.qq.com/cgi-bin/httpconn?htcmd=0x6ff0071&ver=5515&term=pc&ukey=” + 删全部空 (ukey) + “&filesize=” + 到文本 (fileSize) + “&range=0&uin=” + g_uin + “&groupcode=” + Group //http://htdata2.qq.com/cgi-bin/httpconn?htcmd=0x6ff0071&ver=5515&term=pc&ukey=” + 删全部空 (ukey) + “&filesize=” + 到文本 (fileSize) + “&range=0&uin=” + g_uin + “&groupcode=” + Group
StringBuilder builder = new StringBuilder("http://htdata2.qq.com/cgi-bin/httpconn?htcmd=0x6ff0071&ver=5515&term=pc"); StringBuilder builder = new StringBuilder("http://htdata2.qq.com/cgi-bin/httpconn?htcmd=0x6ff0071&ver=5515&term=pc");
builder.append("&ukey=") builder.append("&ukey=")
.append(ukey.trim()) .append(uKeyHex.trim())
.append("&filezise=").append(fileSize) .append("&filezise=").append(fileSize)
.append("&range=").append("0") .append("&range=").append("0")
.append("&uin=").append(g_uin) .append("&uin=").append(qqNumber)
.append("&groupcode=").append(groupCode); .append("&groupcode=").append(groupCode);
try { HttpURLConnection conn = (HttpURLConnection) new URL(builder.toString()).openConnection();
HttpURLConnection conn = (HttpURLConnection) new URL(builder.toString()).openConnection(); conn.setRequestProperty("User-agent", "QQClient");
conn.setRequestProperty("User-agent","QQClient"); conn.setRequestProperty("Content-length", "" + fileSize);
conn.setRequestProperty("Content-length","" + fileSize); conn.setRequestMethod("POST");
conn.setRequestMethod("POST"); conn.getOutputStream().write(img);
conn.getOutputStream().write(img);
conn.connect(); conn.connect();
System.out.println(conn.getResponseCode()); System.out.println(conn.getResponseCode());
System.out.println(conn.getResponseMessage());
} catch (IOException e) {
e.printStackTrace();
}
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment