📄 clusterim.java
字号:
/*
* LumaQQ - Java QQ Client
*
* Copyright (C) 2004 luma <stubma@163.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.tsinghua.lumaqq.qq.beans;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import edu.tsinghua.lumaqq.qq.QQ;
import edu.tsinghua.lumaqq.qq.Util;
/**
* <pre>
* 群消息的信息封装bean,具体内容可以参见ReceiveIMPacket
*
* 关于自定义表情的格式,参见NormalIM注释
* </pre>
*
* @see edu.tsinghua.lumaqq.qq.beans.NormalIM
* @author 马若劼
*/
public class ClusterIM {
public char source;
// 这个字段在收到临时群消息时表示父群ID,在固定群消息时表示群外部ID
public int externalId;
public byte type;
public int sender;
public char unknown1;
public char sequence;
public long sendTime;
public int versionId;
public char contentType;
public int fragmentSequence;
public int totalFragments;
public char messageId;
// 下面这些都是消息的属性,比如字体啦颜色啦,都是在fontAttribute里面的
public boolean hasFontAttribute;
public String encoding;
public int red, green, blue;
public int fontSize;
public String fontName;
public boolean bold, italic, underline;
// 临时群内部ID,仅用于临时群消息时
public int clusterId;
// 消息内容,在解析的时候只用byte[],正式要显示到界面上时才会转为String,上层程序
// 要负责这个事,这个类只负责把内容读入byte[]
public byte[] messageBytes;
public String message;
// true表示这个消息中的自定义表情已经全部得到
public boolean faceResolved;
public ClusterIM(char source) {
this.source = source;
faceResolved = false;
}
/**
* 给定一个输入流,解析ClusterIM结构
* @param buf
*/
public void readBean(ByteBuffer buf) {
// 群外部ID或者父群ID
externalId = buf.getInt();
// 群类型,1字节
type = buf.get();
// 临时群内部ID
if(source == QQ.QQ_RECV_IM_TEMP_CLUSTER_IM)
clusterId = buf.getInt();
// 发送者
sender = buf.getInt();
// 未知1
unknown1 = buf.getChar();
// 消息序号
sequence = buf.getChar();
// 发送时间,记得乘1000才对
sendTime = buf.getInt() * 1000L;
// Member Version ID
versionId = buf.getInt();
// 后面的内容长度
buf.getChar();
// 一些扩展信息
if(source != QQ.QQ_RECV_IM_UNKNOWN_CLUSTER_IM) {
// content type
contentType = buf.getChar();
// 分片数
totalFragments = buf.get() & 0xFF;
// 分片序号
fragmentSequence = buf.get() & 0xFF;
// 2字节未知
messageId = buf.getChar();
// 4字节未知
buf.getInt();
}
// 消息正文,0是分隔符
// 先不停的读,直到找到0x0为止
// 要注意只有最后一个分片是0结尾且有字体信息的
if(!buf.hasRemaining())
messageBytes = new byte[0];
else {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while(buf.hasRemaining()) {
byte b = buf.get();
if(b == 0)
break;
else /* if(b == QQ.QQ_CUSTOM_FACE_TAG) { // 现在不过滤了
baos.write(QQ.QQ_CUSTOM_FACE_TAG);
baos.write(0x30);
byte existence = buf.get();
String lenStr = Util.getString(buf, 3).trim();
int len = Util.getInt(lenStr, 0);
buf.position(buf.position() + len - 5);
} else */
baos.write(b);
}
messageBytes = baos.toByteArray();
}
// 如果后面还有字节,则说明还有字体属性
hasFontAttribute = buf.hasRemaining();
// 这后面都是字体属性,这个和SendIMPacket里面的是一样的,我想大概服务器就是直接拷贝那一块
if(hasFontAttribute) {
byte fontStyle = buf.get();
// 分析字体属性到具体的变量
// 字体大小
fontSize = fontStyle & 0x1F;
// 组体,斜体,下画线
bold = (fontStyle & 0x20) != 0;
italic = (fontStyle & 0x40) != 0;
underline = (fontStyle & 0x80) != 0;
// 字体颜色rgb
red = buf.get() & 0xFF;
green = buf.get() & 0xFF;
blue = buf.get() & 0xFF;
// 1个未知字节
buf.get();
// 消息编码,这个据Gaim QQ的注释,这个字段用处不大,说是如果在一个英文windows
// 里面输入了中文,那么编码是英文的,按照这个encoding来解码就不行了
// 不过我们还是得到这个字段吧,后面我们采用先缺省GBK解码,不行就这个encoding
// 解码,再不行就ISO-8859-1的方式
encoding = Util.getEncodingString(buf.getChar());
// 字体名称,字体名称也有中文的也有英文的,所以。。先来试试缺省的
fontName = Util.getString(buf, buf.remaining() - 1);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -