📄 sendimpacket.java
字号:
buf.putLong(0);
buf.putChar((char)0);
buf.put((byte)0);
// 固定字节,0x65
buf.put((byte)0x65);
}
/**
* 初始化IP信息通知包
* @param buf
*/
private void initNotifyFilePortUDP(ByteBuffer buf) {
// 17 - 19. 怀疑也和发送消息包相同,但是在这种情况中,这部分没有使用,为全0,一共11个0字节
buf.putLong(0);
buf.putChar((char)0);
buf.put((byte)0);
// 我们先尝试UDP方式
buf.put((byte)0x65);
buf.put((byte)0x0);
// 四个字节的发送者IP,这是外部IP
buf.put(user.getIp());
// 发送者端口
buf.putChar((char)user.getPort());
// 监听端口,含义未知,为连接服务器的端口,先随便写一个值
buf.putChar(directPort);
// 真实IP和第二个端口
buf.put(localIp);
buf.putChar(localPort);
}
/**
* 初始化拒绝接收文件包的其余部分
* @param buf
*/
private void initSendFileRejectContent(ByteBuffer buf) {
// 17 - 19. 怀疑也和发送消息包相同,但是在这种情况中,这部分没有使用,为全0,一共11个0字节
buf.putLong(0);
buf.putChar((char)0);
buf.put((byte)0);
// 我们先尝试UDP方式
buf.put((byte)0x65);
}
/**
* 初始化同意接收文件包的其余部分
* @param buf
* @throws IOException
*/
private void initSendFileAcceptContent(ByteBuffer buf) {
// 17 - 19. 怀疑也和发送消息包相同,但是在这种情况中,这部分没有使用,为全0,一共11个0字节
buf.putLong(0);
buf.putChar((char)0);
buf.put((byte)0);
// 我们先尝试UDP方式
buf.put((byte)0x65);
buf.put((byte)0x0);
// 四个字节的发送者IP,这是外部IP
buf.put(user.getIp());
// 发送者端口
buf.putChar((char)user.getPort());
// 监听端口,含义未知,为连接服务器的端口,先随便写一个值
buf.putChar(directPort);
// 后面全0
buf.putInt(0);
buf.putChar((char)0);
}
/**
* 初始化请求发送文件包的其余部分
* @param buf
*/
private void initSendFileContent(ByteBuffer buf) {
// 17 - 19. 怀疑也和发送消息包相同,但是在这种情况中,这部分没有使用,为全0,一共11个0字节
buf.putLong(0);
buf.putChar((char)0);
buf.put((byte)0);
// 我们先尝试UDP方式
buf.put((byte)0x65);
buf.put((byte)0x0);
// 四个字节的发送者IP,这是外部IP
buf.put(user.getIp());
// 发送者端口
buf.putChar((char)user.getPort());
// 直接端口
buf.putChar(directPort);
buf.putInt(0);
buf.putChar((char)0);
buf.put((byte)0x20);
buf.put(DELIMIT);
buf.put(fileName.getBytes());
buf.put(DELIMIT);
buf.put(fileSize.getBytes());
}
/**
* 初始化普通消息包的其余部分
* @param buf
*/
private void initTextContent(ByteBuffer buf) {
byte[] b = null;
// 消息方式,是发送的,还是自动回复的,1字节
buf.put(replyType);
// 写入消息正文字节数组
// 以0结束的消息,首先我们要根据用户设置的message,解析出一个网络可发送的格式
// 这一步比较麻烦,暂时想不到好的办法
int j, i = 0;
while((j = message.indexOf((char)QQ.QQ_DEFAULT_FACE_TAG, i)) != -1) {
String sub = message.substring(i, j);
if(!sub.equals("")) {
b = Utils.getBytes(sub, QQ.QQ_CHARSET_DEFAULT);
buf.put(b);
}
buf.put(QQ.QQ_DEFAULT_FACE_TAG);
buf.put((byte)(message.charAt(j + 1) & 0xFF));
i = j + 2;
}
if(i < message.length()) {
String sub = message.substring(i);
b = Utils.getBytes(sub, QQ.QQ_CHARSET_DEFAULT);
buf.put(b);
}
buf.put((byte)0x20); // 空格,不要也没事,但是能尽量和QQ一致就一致
buf.put((byte)0); // 0x0
// 消息尾部,字体修饰属性
buf.put(fontFlag);
// 字体颜色红绿篮
buf.put(red);
buf.put(green);
buf.put(blue);
// 一个未知字节
buf.put((byte)0);
// 消息编码
buf.putChar(encoding);
// 字体
buf.put(fontName.getBytes());
// 最后一个回车符
buf.put((byte)0x0D);
}
/**
* 调试方法,从QQ的抓包中里面解析出内容,看看有没有问题,实际中请勿使用
*/
public byte[] forDebug(byte[] packetBuf) {
// 提取加密内容
byte[] buf = new byte[packetBuf.length - 12];
System.arraycopy(packetBuf, 11, buf, 0, buf.length);
// 解密
buf = crypter.decrypt(buf, user.getSessionKey());
// 创建流
ByteArrayInputStream bais = new ByteArrayInputStream(buf);
DataInputStream dis = new DataInputStream(bais);
try {
log.debug("接收者: " + dis.readInt());
log.debug("发送者: " + dis.readInt());
log.debug("发送者QQ版本: " + Utils.getClientString(dis.readChar()));
log.debug("接收者: " + dis.readInt());
log.debug("发送者: " + dis.readInt());
log.debug("跳过16字节MD5");
dis.skipBytes(16);
log.debug("消息类型: " + Utils.getIMTypeString(dis.readChar()));
log.debug("消息序号: " + (int)dis.readChar());
log.debug("发送时间: " + new Date((long)dis.readInt() * 1000L).toString());
log.debug("跳过1字节");
dis.skipBytes(1);
log.debug("发送者头像: " + (dis.readByte() & 0xFF));
log.debug("跳过8字节");
dis.skipBytes(8);
log.debug("消息回复类型: " + Utils.getIMReplyType(dis.readByte()));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
while(true) {
byte b = dis.readByte();
if(b == 0) break;
dos.writeByte(b);
}
message = new String(baos.toByteArray(), QQ.QQ_CHARSET_DEFAULT);
log.debug("消息正文: " + message);
dos.close();
byte flag = dis.readByte();
log.debug("字体大小: " + (int)(flag & 0x1F));
log.debug("粗体: " + ((flag & 0x20) != 0));
log.debug("斜体: " + ((flag & 0x40) != 0));
log.debug("下划线: " + ((flag & 0x80) != 0));
log.debug("红: " + (dis.readByte() & 0xFF));
log.debug("绿: " + (dis.readByte() & 0xFF));
log.debug("蓝: " + (dis.readByte() & 0xFF));
log.debug("跳过1字节");
dis.skipBytes(1);
log.debug("消息编码: " + Utils.getEncodingString(dis.readChar()));
byte[] f = new byte[dis.available()];
dis.read(f);
log.debug("字体: " + new String(f, QQ.QQ_CHARSET_DEFAULT));
return message.getBytes();
} catch (IOException e) {
log.debug("解析出错");
return null;
}
}
/**
* @return Returns the blue.
*/
public byte getBlue() {
return blue;
}
/**
* @param blue The blue to set.
*/
public void setBlue(byte blue) {
this.blue = blue;
}
/**
* @return Returns the bold.
*/
public boolean isBold() {
return bold;
}
/**
* @param bold The bold to set.
*/
public void setBold(boolean bold) {
this.bold = bold;
fontFlag &= 0xDF;
fontFlag |= bold ? BOLD : NONE;
}
/**
* @return Returns the encoding.
*/
public char getEncoding() {
return encoding;
}
/**
* @param encoding The encoding to set.
*/
public void setEncoding(char encoding) {
this.encoding = encoding;
}
/**
* @return Returns the fontName.
*/
public String getFontName() {
return fontName;
}
/**
* @param fontName The fontName to set.
*/
public void setFontName(String fontName) {
this.fontName = fontName;
}
/**
* @return Returns the green.
*/
public byte getGreen() {
return green;
}
/**
* @param green The green to set.
*/
public void setGreen(byte green) {
this.green = green;
}
/**
* @return Returns the italic.
*/
public boolean isItalic() {
return italic;
}
/**
* @param italic The italic to set.
*/
public void setItalic(boolean italic) {
this.italic = italic;
fontFlag &= 0xBF;
fontFlag |= italic ? ITALIC : NONE;
}
/**
* @return Returns the receiver.
*/
public int getReceiver() {
return receiver;
}
/**
* @param receiver The receiver to set.
*/
public void setReceiver(int receiver) {
this.receiver = receiver;
}
/**
* @return Returns the red.
*/
public byte getRed() {
return red;
}
/**
* @param red The red to set.
*/
public void setRed(byte red) {
this.red = red;
}
/**
* @return Returns the underline.
*/
public boolean isUnderline() {
return underline;
}
/**
* @param underline The underline to set.
*/
public void setUnderline(boolean underline) {
this.underline = underline;
fontFlag &= 0x7F;
fontFlag |= underline ? UNDERLINE : NONE;
}
/**
* @return Returns the message.
*/
public String getMessage() {
return message;
}
/**
* @param message The message to set.
*/
public void setMessage(String message) {
this.message = message;
}
/**
* @return Returns the messageType.
*/
public char getMessageType() {
return messageType;
}
/**
* @param messageType The messageType to set.
*/
public void setMessageType(char messageType) {
this.messageType = messageType;
}
/**
* @return Returns the replyType.
*/
public byte getReplyType() {
return replyType;
}
/**
* @param replyType The replyType to set.
*/
public void setReplyType(byte replyType) {
this.replyType = replyType;
}
/**
* @return Returns the fontSize.
*/
public byte getFontSize() {
return fontSize;
}
/**
* @param fontSize The fontSize to set.
*/
public void setFontSize(byte fontSize) {
this.fontSize = fontSize;
fontSize &= 0x1F;
fontFlag &= 0xE0;
fontFlag |= fontSize;
}
/**
* @param filePath The filePath to set.
*/
public void setFileName(String filePath) {
this.fileName = filePath;
}
/**
* @param fileSize The fileSize to set.
*/
public void setFileSize(int size) {
this.fileSize = String.valueOf(size) + " 字节";
}
/**
* @param port The port to set.
*/
public void setDirectPort(int port) {
this.directPort = (char)port;
}
/**
* @return Returns the requestSequence.
*/
public char getSessionId() {
return sessionId;
}
/**
* @param requestSequence The requestSequence to set.
*/
public void setSessionId(char requestSequence) {
this.sessionId = requestSequence;
}
/**
* @return Returns the localIp.
*/
public byte[] getLocalIp() {
return localIp;
}
/**
* @param localIp The localIp to set.
*/
public void setLocalIp(byte[] localIp) {
this.localIp = localIp;
}
/**
* @return Returns the localPort.
*/
public char getLocalPort() {
return localPort;
}
/**
* @param localPort The localPort to set.
*/
public void setLocalPort(int localPort) {
this.localPort = (char)localPort;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -