/*
* Mrim.java
*
*/
// #sijapp cond.if protocols_MRIM is "true" #
package protocol.mrim;
import java.util.*;
import jimm.*;
import jimm.JimmException;
import jimmui.model.chat.ChatModel;
import jimm.chat.message.*;
import jimm.comm.*;
import jimm.modules.*;
import jimm.search.*;
import jimm.util.*;
import protocol.*;
import protocol.net.*;
import protocol.ui.StatusInfo;
/**
*
* @author vladimir
*/
public final class MrimConnection extends ClientConnection {
private TcpSocket socket;
private Mrim mrim;
private int seqCounter = 0;
private static final int MAX_TYPING_TASK_COUNT = 3;
private TypingTask[] typingTasks = new TypingTask[MAX_TYPING_TASK_COUNT];
private String typingTo = null;
private MrimPacket pingPacket;
private final Vector<MrimPacket> packets = new Vector<MrimPacket>();
private UserInfo singleUserInfo;
private Search search = null;
private MrimContact lastContact = null;
private MrimGroup lastGroup = null;
private static final int MULTICHAT_MESSAGE = 0;
private static final int MULTICHAT_GET_MEMBERS = 1;
private static final int MULTICHAT_MEMBERS = 2;
private static final int MULTICHAT_ADD_MEMBERS = 3;
private static final int MULTICHAT_ATTACHED = 4;
private static final int MULTICHAT_DETACHED = 5;
private static final int MULTICHAT_DESTROYED = 6;
private static final int MULTICHAT_INVITE = 7;
private static final int CONTACT_OPER_SUCCESS = 0x0000;
private static final int GET_CONTACTS_OK = 0x0000;
private static final int GET_CONTACTS_ERROR = 0x0001;
private static final int GET_CONTACTS_INTERR = 0x0002;
private static final int FIRST_CONTACT_ID = 20;
public static final int CONTACT_FLAG_REMOVED = 0x00000001;
public static final int CONTACT_FLAG_SHADOW = 0x00000020;
public static final int CONTACT_FLAG_GROUP = 0x00000002;
public static final int STATUS_FLAG_INVISIBLE = 0x80000000;
public static final int STATUS_OFFLINE = 0x00000000;
public static final int STATUS_ONLINE = 0x00000001;
public static final int STATUS_AWAY = 0x00000002;
public static final int STATUS_UNDETERMINATED = 0x00000003;
public static final int STATUS_CHAT = 0x00000004;
public static final int STATUS_INVISIBLE = STATUS_FLAG_INVISIBLE | STATUS_ONLINE;
public MrimConnection(Mrim protocol) {
this.mrim = protocol;
}
private void setProgress(int progress) {
mrim.setConnectingProgress(progress);
}
protected Protocol getProtocol() {
return mrim;
}
private String getServer() throws JimmException {
StringBuilder buffer = new StringBuilder();
try {
TcpSocket s = new TcpSocket();
s.connectForReadingTo("socket://mrim.mail.ru:2042");
int ch;
while (true) {
ch = s.read();
if (-1 == ch) break;
if(('0' <= ch && ch <= '9') || (ch == '.') || (ch == ':')) {
buffer.append((char)ch);
}
}
} catch (Exception e) {
throw new JimmException(120, 10);
}
return buffer.toString();
}
private int nextSeq() {
return ++seqCounter;
}
private void sendPacket(MrimPacket packet) throws JimmException {
if (0 == packet.getSeq()) {
packet.setSeq(nextSeq());
}
byte[] outpacket = packet.toByteArray();
socket.write(outpacket);
socket.flush();
}
private MrimPacket getPacket() throws JimmException {
byte[] header = new byte[4 * 7 + 16];
socket.readFully(header);
int seq = (int)Util.getDWordLE(header, 8);
int cmd = (int)Util.getDWordLE(header, 12);
int dataSize = (int)Util.getDWordLE(header, 16);
byte[] data = new byte[dataSize];
if (0 < dataSize) {
socket.readFully(data);
}
return new MrimPacket(cmd, seq, data);
}
protected void connect() throws JimmException {
// #sijapp cond.if modules_DEBUGLOG is "true" #
DebugLog.println("go");
// #sijapp cond.end#
String server = getServer();
// #sijapp cond.if modules_DEBUGLOG is "true" #
DebugLog.println("server " + server);
// #sijapp cond.end#
setProgress(20);
socket = new TcpSocket();
socket.connectTo("socket://" + server);
// #sijapp cond.if modules_DEBUGLOG is "true" #
DebugLog.println("send hello");
// #sijapp cond.end#
MrimBuffer hi = new MrimBuffer();
hi.putDWord(getPingInterval());
sendPacket(new MrimPacket(MrimPacket.MRIM_CS_HELLO, hi));
setProgress(40);
MrimPacket packetKeepAlive = getPacket();
int ping = Math.min((int)packetKeepAlive.getData().getDWord(), 120);
setPingInterval(ping);//ping time...
// #sijapp cond.if modules_DEBUGLOG is "true" #
DebugLog.println("recv hello " + getPingInterval());
// #sijapp cond.end#
sendPacket(MrimPacket.getLoginPacket(mrim));
setProgress(60);
MrimPacket loginResult = getPacket();
if (MrimPacket.MRIM_CS_LOGIN_ACK != loginResult.getCommand()) {
// #sijapp cond.if modules_DEBUGLOG is "true" #
DebugLog.println("mrim login resone " + loginResult.getData().getString());
// #sijapp cond.end#
mrim.setPassword(null);
throw new JimmException(111, 0);
}
setProgress(80);
connect = true;
}
private int secondCounter = 0;
private int outTypingCounter = 0;
protected boolean processPacket() throws JimmException {
MrimPacket toPacket = getPacketFromQueue();
if (null != toPacket) {
sendPacket(toPacket);
return true;
}
if (0 < socket.available()) {
MrimPacket packet = getPacket();
try {
processPacket(packet);
} catch (JimmException e) {
throw e;
} catch (Exception e) {
// #sijapp cond.if modules_DEBUGLOG is "true" #
DebugLog.panic("mrim: processPacket", e);
DebugLog.dump("mrim cmd " + packet.getCommand(), packet.toByteArray());
// #sijapp cond.end #
}
return true;
}
secondCounter++;
if (4 == secondCounter) {
inTypingTask(Jimm.getCurrentGmtTime());
if (null != typingTo) {
outTypingCounter++;
if (9 /* 9 sec */ == outTypingCounter) {
outTypingTask();
outTypingCounter = 0;
}
}
secondCounter = 0;
}
return false;
}
private void putPacketIntoQueue(MrimPacket packet) {
synchronized (packets) {
packets.addElement(packet);
}
}
private MrimPacket getPacketFromQueue() {
synchronized (packets) {
if (packets.isEmpty()) {
return null;
}
MrimPacket packet = (MrimPacket) packets.firstElement();
packets.removeElementAt(0);
return packet;
}
}
private void addMessage(String from, String msg, long flags, String date, boolean offline) {
msg = StringUtils.trim(msg);
boolean isAuth = (0 != (MrimPacket.MESSAGE_FLAG_AUTHORIZE & flags));
if (!isAuth && StringUtils.isEmpty(msg)) {
return;
}
try {
if (isAuth && (5 < msg.length())) {
MrimBuffer buffer = new MrimBuffer(Util.base64decode(msg.trim()));
buffer.getDWord();
buffer.getString();
if (0 != (MrimPacket.MESSAGE_FLAG_OLD & flags)) {
msg = buffer.getString();
} else {
msg = buffer.getUcs2String();
}
}
} catch (Exception e) {
msg = "";
}
msg = StringUtils.convert(StringUtils.MRIM2JIMM, msg);
if (-1 == from.indexOf('@')) {
MrimContact contact = mrim.getContactByPhone(from);
String fromEmail = from;
if (null != contact) {
PlainMessage message = new PlainMessage(contact.getUserId(),
mrim, Jimm.getCurrentGmtTime(), msg, false);
message.setName("SMS");
ChatModel chat = mrim.getChatModel(contact);
if (contact instanceof MrimPhoneContact) {
chat.setWritable(false);
}
Jimm.getJimm().getChatUpdater().addMessage(chat, message, false);
if (!(contact instanceof MrimPhoneContact)) {
fromEmail = contact.getUserId();
}
} else {
// #sijapp cond.if target is "MIDP2" #
if (Jimm.getJimm().isPaused()) {
Jimm.getJimm().maximize();
}
// #sijapp cond.end #
Jimm.getJimm().getCL().activateWithMsg(from + " (SMS):\n" + msg);
}
// #sijapp cond.if modules_MAGIC_EYE is "true" #
MagicEye.addAction(mrim, fromEmail, "SMS", msg);
// #sijapp cond.end #
return;
}
if ((MrimPacket.MESSAGE_FLAG_AUTHORIZE & flags) != 0) {
mrim.addMessage(new SystemNotice(mrim,
SystemNotice.TYPE_NOTICE_AUTHREQ,
from, msg));
} else if ((MrimPacket.MESSAGE_FLAG_NOTIFY & flags) == 0) {
if ((MrimPacket.MESSAGE_FLAG_ALARM & flags) != 0) {
msg = PlainMessage.CMD_WAKEUP;
}
mrim.addMessage(new PlainMessage(from, mrim,
(null == date) ? Jimm.getCurrentGmtTime() : Util.createGmtDate(date),
msg, offline));
}
}
public void putMultiChatGetMembers(String to) {
MrimBuffer out = MrimPacket.getMessageBuffer(to, "", 0x00400000);
out.putDWord(4);
out.putDWord(MULTICHAT_GET_MEMBERS);
putPacketIntoQueue(new MrimPacket(MrimPacket.MRIM_CS_MESSAGE, out));
}
private void addMultiChatMessage(MrimBuffer packetData, long flags, String msg, String from) {
long len = packetData.getDWord();
int type = (int)packetData.getDWord(); // maybe rights
String chatName = packetData.getUcs2String();
MrimChatContact chat = (MrimChatContact)mrim.getItemByUID(from);
if (null == chat) {
chat = (MrimChatContact)mrim.createTempContact(from);
mrim.addTempContact(chat);
}
chat.setName(chatName);
String email;
switch (type) {
case MULTICHAT_MESSAGE:
email = packetData.getString();
msg = StringUtils.trim(msg);
if (StringUtils.isEmpty(msg)) {
return;
}
msg = StringUtils.convert(StringUtils.MRIM2JIMM, msg);
if ((MrimPacket.MESSAGE_FLAG_ALARM & flags) != 0) {
msg = PlainMessage.CMD_WAKEUP;
}
PlainMessage message = new PlainMessage(from, mrim,
Jimm.getCurrentGmtTime(), msg, false);
message.setName(email);
mrim.addMessage(message);
return;
case MULTICHAT_MEMBERS:
packetData.getDWord();//len
int count = (int)packetData.getDWord();//count
Vector<String> inChat = new Vector<String>();
for (; 0 < count; --count) {
inChat.addElement(packetData.getString());
}
chat.setMembers(inChat);
return;
case MULTICHAT_INVITE:
email = packetData.getString();
// #sijapp cond.if modules_DEBUGLOG is "true" #
jimm.modules.DebugLog.println("invite from " + email);
// #sijapp cond.end #
return;
case MULTICHAT_ATTACHED:
email = packetData.getString();
chat.getMembers().addElement(email);
return;
case MULTICHAT_DETACHED:
email = packetData.getString();
chat.getMembers().removeElement(email);
return;
}
// #sijapp cond.if modules_DEBUGLOG is "true" #
jimm.modules.DebugLog.dump("type " + type, packetData.toByteArray());
// #sijapp cond.end #
}
private void inTypingTask(long now) {
for (int i = 0; i < typingTasks.length; ++i) {
if ((null != typingTasks[i]) && (typingTasks[i].time <= now)) {
// #sijapp cond.if modules_SOUND is "true" #
mrim.beginTyping(typingTasks[i].email, false);
// #sijapp cond.end #
typingTasks[i] = null;
}
}
}
private void outTypingTask() {
// #sijapp cond.if modules_SOUND is "true" #
String to = typingTo;
if (null != to) {
int flags = MrimPacket.MESSAGE_FLAG_NORECV | MrimPacket.MESSAGE_FLAG_NOTIFY;
MrimPacket packet = MrimPacket.getMessagePacket(to, " ", flags);
packet.setSeq(nextSeq());
putPacketIntoQueue(packet);
}
// #sijapp cond.end #
}
private void beginTyping(MrimContact c, boolean flag) {
// #sijapp cond.if modules_SOUND is "true" #
if (Options.getInt(Options.OPTION_TYPING_MODE) == 0) {
return;
}
long now = Jimm.getCurrentGmtTime();
inTypingTask(now);
for (int i = 0; i < typingTasks.length; ++i) {
if (null == typingTasks[i]) {
typingTasks[i] = new TypingTask(c.getUserId(), now + 11 /* 11 sec */);
mrim.beginTyping(c.getUserId(), true);
return;
}
}
// #sijapp cond.end #
}
private void processPacket(MrimPacket fromPacket) throws JimmException {
int cmd = (int)fromPacket.getCommand();
MrimBuffer packetData = fromPacket.getData();
if (MrimPacket.MRIM_CS_MESSAGE_ACK == cmd) {
long msgId = packetData.getDWord();
long flags = packetData.getDWord();
String from = packetData.getString();
String msg;
if ((0 != (MrimPacket.MESSAGE_FLAG_OLD & flags))
|| (0 != (MrimPacket.MESSAGE_FLAG_AUTHORIZE & flags))) {
msg = packetData.getString();
} else {
msg = packetData.getUcs2String();
}
// #sijapp cond.if modules_DEBUGLOG is "true" #
//DebugLog.dump("message " + flags, packetData.toByteArray());
// #sijapp cond.end#
if (from.endsWith("@chat.agent")) {
packetData.getString();// rtf-message
addMultiChatMessage(packetData, flags, msg, from);
return;
}
MrimContact c = (MrimContact)mrim.getItemByUID(from);
if (null != c) {
beginTyping(c, (MrimPacket.MESSAGE_FLAG_NOTIFY & flags) != 0);
}
if ((MrimPacket.MESSAGE_FLAG_NORECV & flags) == 0) {
putPacketIntoQueue(MrimPacket.getMessageRecvPacket(from, msgId));
}
addMessage(from, msg, flags, null, false);
} else if (MrimPacket.MRIM_CS_OFFLINE_MESSAGE_ACK == cmd) {
byte[] uidl = packetData.getUidl();
String offmsg = packetData.getString();
// #sijapp cond.if modules_DEBUGLOG is "true" #
//DebugLog.println("Offline message\n" + offmsg);
// #sijapp cond.end#
String[] mail = explodeMail(offmsg);
String date = getMailValue(mail[0], "Date");
String from = getMailValue(mail[0], "From");
String msg = getMailMessage(mail);
long flags = 0;
try {
flags = Integer.parseInt(getMailValue(mail[0], "X-MRIM-Flags"), 16);
} catch (Exception ignored) {
}
addMessage(from, msg, flags, date, true);
putPacketIntoQueue(MrimPacket.getDeleteOfflineMessagePacket(uidl));
} else if (MrimPacket.MRIM_CS_MESSAGE_STATUS == cmd) {
long status = packetData.getDWord();
// #sijapp cond.if modules_DEBUGLOG is "true" #
DebugLog.println("message status " + status);
// #sijapp cond.end#
setMessageSended(fromPacket.getSeq(), status);
} else if (MrimPacket.MRIM_CS_AUTHORIZE_ACK == cmd) {
String uin = packetData.getString();
mrim.setAuthResult(uin, true);
} else if (MrimPacket.MRIM_CS_LOGOUT == cmd) {
int resone = (int)packetData.getDWord();
// #sijapp cond.if modules_DEBUGLOG is "true" #
DebugLog.println("disconnect reason " + resone);
// #sijapp cond.end#
throw new JimmException(110, resone);
} else if (MrimPacket.MRIM_CS_USER_STATUS == cmd) {
long status = packetData.getDWord();
String xstatus = packetData.getString();
String title = packetData.getUcs2String();
String desc = packetData.getUcs2String();
String user = packetData.getString();
int clientCaps = (int)packetData.getDWord();
String client = packetData.getString();
//System.out.println("***xstatus " + xstatus + " " + status + " 0x" + Integer.toHexString(clientCaps));
MrimContact contact = (MrimContact)mrim.getItemByUID(user);
if ((null != contact) && !(contact instanceof MrimPhoneContact)) {
final int oldStatusIndex = contact.getStatusIndex();
mrim.setContactStatus(contact, MrimConnection.getStatusIndexBy(status, xstatus), null);
final int newStatusIndex = contact.getStatusIndex();
contact.setMood(xstatus, title, desc);
// #sijapp cond.if modules_CLIENTS is "true" #
if (StatusInfo.STATUS_OFFLINE != newStatusIndex) {
contact.setClient(client);
}
// #sijapp cond.end#
// Update contact list
mrim.ui_changeContactStatus(contact);
if ((contact instanceof MrimChatContact) && contact.isOnline()) {
putMultiChatGetMembers(contact.getUserId());
}
// #sijapp cond.if modules_MAGIC_EYE is "true" #
if ((StatusInfo.STATUS_OFFLINE == newStatusIndex)
&& (StatusInfo.STATUS_OFFLINE == oldStatusIndex)) {
MagicEye.addAction(mrim, contact.getUserId(), "hiding_from_you");
}
// #sijapp cond.end#
}
} else if (MrimPacket.MRIM_CS_ANKETA_INFO == cmd) {
long searchStatus = packetData.getDWord();
if (MrimPacket.MRIM_ANKETA_INFO_STATUS_OK == searchStatus) {
int fieldNum = (int)packetData.getDWord();
long maxResults = packetData.getDWord();
long serverTime = packetData.getDWord();
String[] fieldNames = new String[fieldNum];
for (int i = 0; i < fieldNum; ++i) {
fieldNames[i] = packetData.getString().toLowerCase();
}
while (!packetData.isEOF()) {
UserInfo userInfo = (null == singleUserInfo)
? new UserInfo(mrim, "")
: singleUserInfo;
setUserInfo(userInfo, fieldNames, packetData);
if (null != search) {
search.addResult(userInfo);
}
if (null != lastContact) {
if (StringUtils.isEmpty(lastContact.getPhones())) {
// do nothing
} else if (StringUtils.isEmpty(userInfo.homePhones)) {
userInfo.homePhones = lastContact.getPhones();
} else {
userInfo.homePhones += ", " + lastContact.getPhones();
}
lastContact = null;
}
if (null != singleUserInfo) {
singleUserInfo.setOptimalName();
singleUserInfo.updateProfileView();
singleUserInfo = null;
}
}
if (null != search) {
search.finished();
search = null;
}
} else {
if (null != search) {
search.finished();
}
}
} else if (MrimPacket.MRIM_CS_ADD_CONTACT_ACK == cmd) {
final long result = packetData.getDWord();
// #sijapp cond.if modules_DEBUGLOG is "true" #
DebugLog.println("add result " + result);
// #sijapp cond.end#
if (CONTACT_OPER_SUCCESS == result) {
int id = (int)packetData.getDWord();
if (0 <= id) {
if (null != lastGroup) {
lastGroup.setGroupId(id);
} else {
lastContact.setContactId(id);
if (!(lastContact instanceof MrimPhoneContact)) {
lastContact.setBooleanValue(Contact.CONTACT_NO_AUTH, true);
}
lastContact.setTempFlag(false);
mrim.ui_updateContact(lastContact);
}
}
}
lastContact = null;
} else if (MrimPacket.MRIM_CS_MODIFY_CONTACT_ACK == cmd) {
// #sijapp cond.if modules_DEBUGLOG is "true" #
DebugLog.println("contact update status " + packetData.getDWord());
// #sijapp cond.end#
} else if (MrimPacket.MRIM_CS_CONTACT_LIST2 == cmd) {
getContactList(packetData);
} else if (MrimPacket.MRIM_MICROBLOG_RECORD == cmd) {
long type = packetData.getDWord();
String from = packetData.getString();
String postid = packetData.getQWordAsString();
long time = packetData.getDWord();
String text = packetData.getUcs2String();
String nick = packetData.getUcs2String();
boolean reply = ((MRIM_BLOG_STATUS_REPLY & type) != 0);
if (reply) {
String alert = packetData.getUtf8String();
}
// #sijapp cond.if modules_MAGIC_EYE is "true" #
if (isConnected()) {
mrim.getMicroBlog().addPost(from, nick, text, postid, reply, time);
}
// #sijapp cond.end #
} else {
// #sijapp cond.if modules_DEBUGLOG is "true" #
if (MrimPacket.MRIM_CS_NEW_EMAIL == cmd) {
packetData.getDWord();
String from = packetData.getUcs2String();
String subject = packetData.getUcs2String();
DebugLog.println("new message from " + from + "\n\n" + subject);
} else if (0x1015 == cmd) {
DebugLog.println("enviroment");
while (!packetData.isEOF()) {
DebugLog.println("mrim: " + packetData.getString() + "="+packetData.getUcs2String());
}
} else {
DebugLog.println("mrim cmd 0x" + Integer.toHexString((int)cmd));
}
// #sijapp cond.end#
}
}
private static final int MRIM_BLOG_STATUS_UPDATE = 0x00000001;
private static final int MRIM_BLOG_STATUS_MUSIC = 0x00000002;
private static final int MRIM_BLOG_STATUS_REPLY = 0x00000004;
private static final int MRIM_BLOG_STATUS_NOTIFY = 0x00000010;
private void setUserInfo(UserInfo userInfo, String[] fields, MrimBuffer in) {
String username = null;
String domain = null;
for (String field : fields) {
if (field.equals("n" + "ickname")) {
userInfo.nick = in.getUcs2String();
} else if (field.equals("f" + "irstname")) {
userInfo.firstName = in.getUcs2String();
} else if (field.equals("l" + "astname")) {
userInfo.lastName = in.getUcs2String();
} else if (field.equals("l" + "ocation")) {
userInfo.homeAddress = in.getUcs2String();
} else if (field.equals("d" + "omain")) {
domain = in.getUtf8String();
} else if (field.equals("u" + "sername")) {
username = in.getUtf8String();
} else if (field.equals("b" + "irthday")) {
userInfo.birthDay = in.getBirthdayString();
} else if (field.equals("s" + "e" + "x")) {
byte[] gender = {0, 2, 1};
userInfo.gender = gender[Util.strToIntDef(in.getUtf8String(), 0) % 3];
} else {
in.getString();
}
}
userInfo.auth = true;
userInfo.uin = username + "@" + domain;
}
private String getMailValue(String header, String key) {
int pos = header.indexOf(key);
if (-1 == pos) {
return "";
}
int end = header.indexOf('\n', pos);
return header.substring(pos + key.length() + 1, end).trim();
}
private String[] explodeMail(String mail) {
int delemiter = mail.indexOf("\n\n");
String[] m = new String[2];
m[0] = mail.substring(0, delemiter + 1);
m[1] = mail.substring(delemiter + 2);
return m;
}
private String getMailMessage(String[] mail) {
String body = mail[1];
if (-1 != getMailValue(mail[0], "Content-Type").indexOf("multipart/")) {
String boundary = getMailValue(mail[0], "Boundary");
int start = body.indexOf("--" + boundary) + 2 + boundary.length();
int end = body.indexOf("--" + boundary, start);
mail = explodeMail(body.substring(start, end));
body = mail[1];
}
if (-1 != getMailValue(mail[0], "Content-Transfer-Encoding").indexOf("base64")) {
byte[] data = Util.base64decode(body);
MrimBuffer buffer = new MrimBuffer(data);
body = buffer.getUcs2StringZ(data.length);
}
return body;
}
protected void closeSocket() {
socket.close();
}
protected void ping() throws JimmException {
if (isConnected()) {
if (null == pingPacket) {
pingPacket = new MrimPacket(MrimPacket.MRIM_CS_PING);
}
sendPacket(pingPacket);
}
}
private void getContactList(MrimBuffer packetData) {
long resultState = packetData.getDWord();
if (GET_CONTACTS_OK != resultState) {
return;
}
TemporaryRoster roster = new TemporaryRoster(mrim);
mrim.setContactListStub();
int groupCount = (int)packetData.getDWord();
String groupMask = packetData.getString();
String contactMask = packetData.getString();
// #sijapp cond.if modules_DEBUGLOG is "true" #
DebugLog.println("group mask " + groupMask);
DebugLog.println("contact mask " + contactMask);
// #sijapp cond.end#
for (int groupId = 0; groupId < groupCount; ++groupId) {
int flags = (int)packetData.getDWord();
String name = packetData.getUcs2String();
packetData.skipFormattedRecord(groupMask, 2);
if ((CONTACT_FLAG_REMOVED & flags) != 0) continue;
MrimGroup g = (MrimGroup) roster.getGroupById(groupId);
if (null == g) {
g = (MrimGroup) roster.makeGroup(name);
g.setGroupId(groupId);
}
g.setFlags(flags);
g.setName(name);
roster.addGroup(g);
}
boolean hasPhones = false;
for (int cotactId = FIRST_CONTACT_ID; !packetData.isEOF(); ++cotactId) {
int flags = (int)packetData.getDWord();
int groupId = (int)packetData.getDWord();
String userid = packetData.getString();
String name = packetData.getUcs2String();
int serverFlags = (int)packetData.getDWord();
int status = (int)packetData.getDWord();
String phone = packetData.getString();
String xstatus = packetData.getString();
String title = packetData.getUcs2String();
String desc = packetData.getUcs2String();
long unkVal = packetData.getDWord();
String client = packetData.getString();
String id = packetData.getQWordAsString();
long time = packetData.getDWord(); // microblog timestamp
String blogPost = packetData.getUcs2String(); // micro blog
// DebugLog.println("s1 " + packetData.getUcs2String());
// DebugLog.println("s2 " + packetData.getUcs2String());
// DebugLog.println("s3 " + packetData.getUcs2String());
// DebugLog.println("s4 " + packetData.getUcs2String());
packetData.skipFormattedRecord(contactMask, 7 + 5 + 4);
if ((CONTACT_FLAG_REMOVED & flags) != 0) continue;
MrimContact contact;
if (MrimPhoneContact.PHONE_UIN.equals(userid)) {
if (StringUtils.isEmpty(phone)) continue;
contact = new MrimPhoneContact(phone);
groupId = MrimGroup.PHONE_CONTACTS_GROUP;
} else {
contact = (MrimContact)roster.makeContact(userid);
}
contact.init(cotactId, name, phone, groupId, serverFlags, flags);
mrim.setContactStatus(contact, MrimConnection.getStatusIndexBy(status, xstatus), null);
contact.setMood(xstatus, title, desc);
hasPhones |= (MrimGroup.PHONE_CONTACTS_GROUP == contact.getGroupId());
// #sijapp cond.if modules_MAGIC_EYE is "true" #
mrim.getMicroBlog().addPost(userid, name, blogPost, id, false, time);
// #sijapp cond.end#
// #sijapp cond.if modules_CLIENTS is "true" #
contact.setClient(client);
// #sijapp cond.end#
roster.addContact(contact);
if ((contact instanceof MrimChatContact) && contact.isOnline()) {
putMultiChatGetMembers(contact.getUserId());
}
}
if (hasPhones) {
MrimGroup phoneGroup = (MrimGroup)roster.makeGroup(JLocale.getString("phone_contacts"));
phoneGroup.setName(JLocale.getString("phone_contacts"));
phoneGroup.setFlags(0);
phoneGroup.setGroupId(MrimGroup.PHONE_CONTACTS_GROUP);
roster.addGroup(phoneGroup);
}
if (isConnected()) {
mrim.setContactList(roster.getGroups(), roster.mergeContacts());
setProgress(100);
}
}
public void disconnect() {
connect = false;
mrim = null;
}
void sendMessage(PlainMessage message) {
boolean notify = true;
typingTo = null;
String text = message.getText();
String to = message.getRcvrUin();
text = StringUtils.convert(StringUtils.JIMM2MRIM, text);
int flags = 0;
if (text.startsWith(PlainMessage.CMD_WAKEUP)) {
notify = false;
flags = MrimPacket.MESSAGE_FLAG_ALARM;
text = "/wakeup Wake up and be free!\n" +
"Please, update your client on http://jimm.net.ru/";
}
MrimPacket packet = MrimPacket.getMessagePacket(to, text, flags);
packet.setSeq(nextSeq());
message.setMessageId(packet.getSeq());
putPacketIntoQueue(packet);
if (notify) {
addMessage(message);
}
}
void sendTypingNotify(String to, boolean isTyping) {
if (isTyping) {
typingTo = to;
outTypingTask();
} else {
typingTo = null;
}
}
void requestAuth(String to, String myUin/*, String msg*/) {
MrimBuffer data = new MrimBuffer();
data.putDWord(2);
data.putString(myUin);
data.putUcs2String("Hi!");
putPacketIntoQueue(MrimPacket.getMessagePacket(to, Util.base64encode(data.toByteArray()),
MrimPacket.MESSAGE_FLAG_AUTHORIZE + MrimPacket.MESSAGE_FLAG_NORECV));
}
void sendSms(String to, String msg) {
String phone = (to.charAt(0) == '+') ? to
: ('+' + ((to.charAt(0) == '8') ? '7' + to.substring(1) : to));
MrimBuffer out = new MrimBuffer();
out.putDWord(0);
out.putString(phone);
out.putUcs2String(msg);
putPacketIntoQueue(new MrimPacket(MrimPacket.MRIM_CS_SMS, out));
}
void addGroup(MrimGroup group) {
lastGroup = group;
String name = group.getName();
putPacketIntoQueue(MrimPacket.getAddContactPacket(CONTACT_FLAG_GROUP, 0, "", name, "", ""));
}
void addContact(MrimContact contact) {
lastContact = contact;
putPacketIntoQueue(MrimPacket.getAddContactPacket(contact.getFlags(),
contact.getGroupId(),
contact.getUserId(), contact.getName(), contact.getPhones(), ""));
}
void removeContact(MrimContact contact) {
int flags = contact.getFlags() | CONTACT_FLAG_REMOVED;
putPacketIntoQueue(MrimPacket.getModifyContactPacket(
contact.getContactId(), flags, 0,//contact.getGroupId(),
contact.getUserId(), contact.getName(), contact.getPhones()));
}
void removeGroup(MrimGroup group) {
int flags = CONTACT_FLAG_GROUP | CONTACT_FLAG_REMOVED;
putPacketIntoQueue(MrimPacket.getModifyContactPacket(
group.getId(), flags, 0,
group.getName(), group.getName(), ""));
}
void updateContact(MrimContact contact) {
putPacketIntoQueue(MrimPacket.getModifyContactPacket(
contact.getContactId(), contact.getFlags(), contact.getGroupId(),
contact.getUserId(), contact.getName(), contact.getPhones()));
}
void renameGroup(MrimGroup group) {
int flags = group.getFlags() | CONTACT_FLAG_GROUP;
putPacketIntoQueue(MrimPacket.getModifyContactPacket(
group.getId(), flags, 0,
group.getName(), group.getName(), ""));
}
void setStatus() {
putPacketIntoQueue(MrimPacket.getSetStatusPacket(mrim));
}
void grandAuth(String uin) {
putPacketIntoQueue(MrimPacket.getAutorizePacket(uin));
}
public void postToMicroBlog(String text, String reply) {
MrimBuffer out = new MrimBuffer();
if (StringUtils.isEmpty(reply)) {
out.putDWord(0x01);
out.putUcs2String(text);
} else {
out.putDWord(0x14);
out.putUcs2String(text);
out.putStringAsQWord(reply);
}
putPacketIntoQueue(new MrimPacket(MrimPacket.MRIM_MICROBLOG_ADD_RECORD, out));
}
void searchUsers(Search cont) {
this.search = cont;
putPacketIntoQueue(MrimPacket.getUserSearchRequestPacket(cont.getSearchParams()));
}
UserInfo getUserInfo(MrimContact contact) {
lastContact = contact;
String[] userInfo = new String[Search.LAST_INDEX];
userInfo[Search.UIN] = contact.getUserId();
singleUserInfo = new UserInfo(mrim);
putPacketIntoQueue(MrimPacket.getUserSearchRequestPacket(userInfo));
return singleUserInfo;
}
private void setMessageSended(long msgId, long status) {
if (MrimPacket.MESSAGE_DELIVERED == status) {
markMessageSent(msgId, PlainMessage.NOTIFY_FROM_CLIENT);
}
}
/////////////////////////////////////////////////////////////
private static final int[] statusCodes = {
STATUS_OFFLINE,
STATUS_ONLINE,
STATUS_AWAY,
STATUS_CHAT,
-1,
-1,
-1,
-1,
-1,
-1,
STATUS_AWAY, //STATUS_UNDETERMINATED,
-1,
STATUS_INVISIBLE
-1};
private static final String[] xstatusCodes = {
"",
"",
"STATUS_AWAY",
"sta" + "tus_chat",
"",
"",
"",
"",
"",
"",
"sta" + "tus_dnd",
"",
""};
private static byte getStatusIndexBy(long status, String xstatus) {
for (byte i = 0; i < xstatusCodes.length; ++i) {
if (StringUtils.isEmpty(xstatusCodes[i])) {
continue;
}
if (xstatusCodes[i].equals(xstatus)) {
return i;
}
}
for (byte i = 0; i < statusCodes.length; ++i) {
if (statusCodes[i] == status) {
return i;
}
}
if (STATUS_UNDETERMINATED == status) {
return StatusInfo.STATUS_UNDETERMINATED;
}
return StatusInfo.STATUS_ONLINE;
}
static String getNativeXStatus(byte statusIndex) {
return xstatusCodes[statusIndex];
}
static int getNativeStatus(byte statusIndex) {
return statusCodes[statusIndex];
}
}
// #sijapp cond.end #