/*******************************************************************************
Jimm - Mobile Messaging - J2ME ICQ clone
Copyright (C) 2003-05 Jimm Project
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.
********************************************************************************
File: src/jimm/comm/ConnectAction.java
Version: ###VERSION### Date: ###DATE###
Author(s): Manuel Linsmayer, Andreas Rossbacher
*******************************************************************************/
// #sijapp cond.if protocols_ICQ is "true" #
package protocol.icq.action;
import java.util.*;
import jimm.*;
import jimm.comm.*;
import protocol.*;
import protocol.icq.*;
import protocol.icq.packet.*;
import jimm.modules.*;
public class ConnectAction extends IcqAction {
// Action states
public static final int STATE_ERROR = -1;
public static final int STATE_INIT = 0;
public static final int STATE_INIT_DONE = 1;
public static final int STATE_AUTHKEY_REQUESTED = 2;
public static final int STATE_CLI_IDENT_SENT = 3;
public static final int STATE_CLI_DISCONNECT_SENT = 4;
public static final int STATE_CLI_COOKIE_SENT = 5;
public static final int STATE_CLI_WANT_CAPS_SENT = 6;
public static final int STATE_CLI_WANT_CAPS_SENT2 = 7;
public static final int STATE_CLI_CHECKROSTER_SENT = 8;
public static final int STATE_CLI_STATUS_INFO_SENT = 9;
public static final int STATE_CLI_REQOFFLINEMSGS_SENT = 10;
public static final int STATE_CLI_ACKOFFLINEMSGS_SENT = 11;
private static final short[] FAMILIES_AND_VER_LIST = {
0x0022, 0x0001,
0x0001, 0x0004,
0x0013, 0x0004,
0x0002, 0x0001,
0x0025, 0x0001,
0x0003, 0x0001,
0x0015, 0x0001,
0x0004, 0x0001,
0x0006, 0x0001,
0x0009, 0x0001,
0x000a, 0x0001,
0x000b, 0x0001};
// #sijapp cond.if modules_SERVERLISTS is "true" #
private Vector<PrivacyItem> ignoreList = new Vector<PrivacyItem>();
private Vector<PrivacyItem> invisibleList = new Vector<PrivacyItem>();
private Vector<PrivacyItem> visibleList = new Vector<PrivacyItem>();
// #sijapp cond.end #
private int timestamp;
private int count;
private TemporaryRoster roster;
// CLI_READY packet data
private static final byte[] CLI_READY_DATA = {
/*
(byte)0x00, (byte)0x22, (byte)0x00, (byte)0x01, (byte)0x01, (byte)0x10, (byte)0x16, (byte)0x4f,
(byte)0x00, (byte)0x01, (byte)0x00, (byte)0x04, (byte)0x01, (byte)0x10, (byte)0x16, (byte)0x4f,
(byte)0x00, (byte)0x13, (byte)0x00, (byte)0x04, (byte)0x01, (byte)0x10, (byte)0x16, (byte)0x4f,
(byte)0x00, (byte)0x02, (byte)0x00, (byte)0x01, (byte)0x01, (byte)0x10, (byte)0x16, (byte)0x4f,
(byte)0x00, (byte)0x03, (byte)0x00, (byte)0x01, (byte)0x01, (byte)0x10, (byte)0x16, (byte)0x4f,
(byte)0x00, (byte)0x15, (byte)0x00, (byte)0x01, (byte)0x01, (byte)0x10, (byte)0x16, (byte)0x4f,
(byte)0x00, (byte)0x04, (byte)0x00, (byte)0x01, (byte)0x01, (byte)0x10, (byte)0x16, (byte)0x4f,
(byte)0x00, (byte)0x06, (byte)0x00, (byte)0x01, (byte)0x01, (byte)0x10, (byte)0x16, (byte)0x4f,
(byte)0x00, (byte)0x09, (byte)0x00, (byte)0x01, (byte)0x01, (byte)0x10, (byte)0x16, (byte)0x4f,
(byte)0x00, (byte)0x0a, (byte)0x00, (byte)0x01, (byte)0x01, (byte)0x10, (byte)0x16, (byte)0x4f,
(byte)0x00, (byte)0x0b, (byte)0x00, (byte)0x01, (byte)0x01, (byte)0x10, (byte)0x16, (byte)0x4f
*/
(byte) 0x00, (byte) 0x22, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x10, (byte) 0x17, (byte) 0xf2,
(byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x04, (byte) 0x01, (byte) 0x10, (byte) 0x17, (byte) 0xf2,
(byte) 0x00, (byte) 0x13, (byte) 0x00, (byte) 0x04, (byte) 0x01, (byte) 0x10, (byte) 0x17, (byte) 0xf2,
(byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x10, (byte) 0x17, (byte) 0xf2,
(byte) 0x00, (byte) 0x25, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x10, (byte) 0x17, (byte) 0xf2,
(byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x10, (byte) 0x17, (byte) 0xf2,
(byte) 0x00, (byte) 0x15, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x10, (byte) 0x17, (byte) 0xf2,
(byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x10, (byte) 0x17, (byte) 0xf2,
(byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x10, (byte) 0x17, (byte) 0xf2,
(byte) 0x00, (byte) 0x09, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x10, (byte) 0x17, (byte) 0xf2,
(byte) 0x00, (byte) 0x0a, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x10, (byte) 0x17, (byte) 0xf2,
(byte) 0x00, (byte) 0x0b, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x10, (byte) 0x17, (byte) 0xf2
};
// Timeout
private static final int TIMEOUT = 20; // seconds
private static final byte[] AIM_MD5_STRING = new byte[]{'A', 'O', 'L', ' ', 'I', 'n', 's', 't', 'a', 'n', 't', ' ',
'M', 'e', 's', 's', 'e', 'n', 'g', 'e', 'r', ' ', '(', 'S', 'M', ')'};
/** *********************************************************************** */
// UIN
private String uin;
// Password
private String password;
// Action state
private int state;
private volatile boolean active;
private String server;
private byte[] cookie;
private String getServerHostAndPort() {
return "login.icq.com:5190";
}
// Constructor
private boolean md5login;
public ConnectAction(Icq icq) {
super();
this.uin = icq.getUserId();
this.password = icq.getPassword();
this.server = getServerHostAndPort();
active();
if (8 < password.length()) {
this.password = password.substring(0, 8);
}
md5login = (-1 == uin.indexOf('@'));
}
private void setProgress(int progress) {
getIcq().setConnectingProgress(progress);
}
public void init() throws JimmException {
this.active = true;
this.state = ConnectAction.STATE_INIT;
active();
// Open connection
getConnection().connectTo(server);
state = ConnectAction.STATE_INIT_DONE;
this.active = false;
// Init activity timestamp
active();
}
// Forwards received packet, returns true if packet has been consumed
public boolean forward(Packet packet) throws JimmException {
if (null == getIcq()) {
return false;
}
// Set activity flag
this.active = true;
active();
// Catch JimmExceptions
try {
// Flag indicates whether packet has been consumed or not
boolean consumed = false;
// Watch out for STATE_INIT_DONE
if (ConnectAction.STATE_INIT_DONE == this.state) {
// Watch out for SRV_CLI_HELLO packet
if (packet instanceof ConnectPacket) {
ConnectPacket connectPacket = (ConnectPacket) packet;
if (ConnectPacket.SRV_CLI_HELLO == connectPacket.getType()) {
if (md5login) {
sendPacket(new ConnectPacket());
OutStream stream = new OutStream();
stream.writeWordBE(0x0001);
stream.writeLenAndUtf8String(uin);
stream.writeTLV(0x4b, new byte[0]);
sendPacket(new SnacPacket(0x0017, 0x0006, -1, stream.toByteArray()));
state = STATE_AUTHKEY_REQUESTED;
} else {
// Send a CLI_IDENT packet as reply
sendPacket(new ConnectPacket(uin, password));
state = ConnectAction.STATE_CLI_IDENT_SENT;
}
// Packet has been consumed
consumed = true;
}
}
} else if (STATE_AUTHKEY_REQUESTED == state) {
if (packet instanceof SnacPacket) {
SnacPacket snacPacket = (SnacPacket) packet;
if ((0x0017 == snacPacket.getFamily())
&& (0x0007 == snacPacket.getCommand())) {
OutStream stream = new OutStream();
stream.writeTLV(0x0001, uin.getBytes());
ArrayReader rbuf = snacPacket.getReader();
byte[] authkey = rbuf.getArray(rbuf.getWordBE());
byte[] passwordRaw = StringUtils.stringToByteArray(password);
byte[] passkey = new MD5().calculate(passwordRaw);
// Old style
//passkey = passwordRaw;
byte[] md5buf = new byte[authkey.length + passkey.length + AIM_MD5_STRING.length];
int md5marker = 0;
System.arraycopy(authkey, 0, md5buf, md5marker, authkey.length);
md5marker += authkey.length;
System.arraycopy(passkey, 0, md5buf, md5marker, passkey.length);
md5marker += passkey.length;
System.arraycopy(AIM_MD5_STRING, 0, md5buf, md5marker, AIM_MD5_STRING.length);
stream.writeTLV(0x0025, new MD5().calculate(md5buf));
ConnectPacket.putVersion(stream, true);
sendPacket(new SnacPacket(0x0017, 0x0002, -1, stream.toByteArray()));
state = STATE_CLI_IDENT_SENT;
} else {
// #sijapp cond.if modules_DEBUGLOG is "true"#
DebugLog.println("connect: family = 0x" + Integer.toHexString(snacPacket.getFamily())
+ " command = 0x" + Integer.toHexString(snacPacket.getCommand()));
// #sijapp cond.end#
throw new JimmException(100, 0);
}
}
consumed = true;
// Watch out for STATE_CLI_IDENT_SENT
} else if (STATE_CLI_IDENT_SENT == state) {
int errcode = -1;
if (md5login) {
if (packet instanceof SnacPacket) {
SnacPacket snacPacket = (SnacPacket) packet;
if ((0x0017 == snacPacket.getFamily())
&& (0x0003 == snacPacket.getCommand())) {
ArrayReader marker = snacPacket.getReader();
while (marker.isNotEnd()) {
int tlvType = marker.getTlvType();
byte[] tlvData = marker.getTlv();
switch (tlvType) {
case 0x0001:
getIcq().setRealUin(StringUtils.byteArrayToAsciiString(tlvData));
this.uin = getIcq().getUserId();
break;
case 0x0008:
errcode = Util.getWordBE(tlvData, 0);
break;
case 0x0005:
this.server = StringUtils.byteArrayToAsciiString(tlvData);
break;
case 0x0006:
this.cookie = tlvData;
break;
}
}
}
} else if (packet instanceof DisconnectPacket) {
consumed = true;
}
} else {
// watch out for channel 4 packet
if (packet instanceof DisconnectPacket) {
DisconnectPacket disconnectPacket = (DisconnectPacket) packet;
// Watch out for SRV_COOKIE packet
if (DisconnectPacket.TYPE_SRV_COOKIE == disconnectPacket.getType()) {
// Save cookie
getIcq().setRealUin(disconnectPacket.getUin());
this.uin = getIcq().getUserId();
this.cookie = disconnectPacket.getCookie();
this.server = disconnectPacket.getServer();
// Watch out for SRV_GOODBYE packet
} else if (DisconnectPacket.TYPE_SRV_GOODBYE == disconnectPacket.getType()) {
errcode = disconnectPacket.getError();
}
consumed = true;
}
}
if (-1 != errcode) {
int toThrow = 100;
switch (errcode) {
// Multiple logins
case 0x0001:
toThrow = 110;
break;
// Bad password
case 0x0004:
case 0x0005:
toThrow = 111;
break;
// Non-existant UIN
case 0x0007:
case 0x0008:
toThrow = 112;
break;
// Too many clients from same IP
case 0x0015:
case 0x0016:
toThrow = 113;
break;
// Rate exceeded
case 0x0018:
case 0x001d:
toThrow = 114;
break;
}
if (111 == toThrow) {
getIcq().setPassword(null);
}
throw new JimmException(toThrow, errcode);
}
if (consumed & (null != this.server) & (null != this.cookie)) {
// Open connection
getConnection().connectTo(server);
// Move to next state
this.state = ConnectAction.STATE_CLI_DISCONNECT_SENT;
}
// Watch out for STATE_CLI_DISCONNECT_SENT
} else if (STATE_CLI_DISCONNECT_SENT == state) {
// Watch out for SRV_HELLO packet
if (packet instanceof ConnectPacket) {
ConnectPacket connectPacket = (ConnectPacket) packet;
if (connectPacket.getType() == ConnectPacket.SRV_CLI_HELLO) {
// #sijapp cond.if modules_DEBUGLOG is "true" #
DebugLog.println("connect say 'hello'");
// #sijapp cond.end #
// Send a CLI_COOKIE packet as reply
ConnectPacket reply = new ConnectPacket(this.cookie);
sendPacket(reply);
// Move to next state
this.state = ConnectAction.STATE_CLI_COOKIE_SENT;
// this.state = ConnectAction.STATE_CLI_WANT_CAPS_SENT;
// Packet has been consumed
consumed = true;
}
}
// Watch out for STATE_CLI_COOKIE_SENT
} else if (STATE_CLI_COOKIE_SENT == state) {
OutStream stream = new OutStream();
for (short familyOrVersion : FAMILIES_AND_VER_LIST) {
stream.writeWordBE(familyOrVersion);
}
sendPacket(new SnacPacket(SnacPacket.SERVICE_FAMILY, SnacPacket.CLI_FAMILIES_COMMAND, SnacPacket.CLI_FAMILIES_COMMAND, stream.toByteArray()));
this.state = ConnectAction.STATE_CLI_WANT_CAPS_SENT;
} else if (STATE_CLI_WANT_CAPS_SENT == state) {
if (packet instanceof SnacPacket) {
SnacPacket s = (SnacPacket) packet;
if ((SnacPacket.SERVICE_FAMILY == s.getFamily())
&& (SnacPacket.SRV_MOTD_COMMAND == s.getCommand())) {
sendPacket(new SnacPacket(SnacPacket.SERVICE_FAMILY,
SnacPacket.CLI_RATESREQUEST_COMMAND));
this.state = ConnectAction.STATE_CLI_WANT_CAPS_SENT2;
}
}
} else if (STATE_CLI_WANT_CAPS_SENT2 == state) {
OutStream udata;
udata = new OutStream();
udata.writeWordBE(0x0001);
udata.writeWordBE(0x0002);
udata.writeWordBE(0x0003);
udata.writeWordBE(0x0004);
udata.writeWordBE(0x0005);
sendPacket(new SnacPacket(SnacPacket.SERVICE_FAMILY, SnacPacket.CLI_ACKRATES_COMMAND, 0x6F4E0000, udata.toByteArray()));
// Request own status
sendPacket(new SnacPacket(SnacPacket.SERVICE_FAMILY, SnacPacket.CLI_REQINFO_COMMAND, 0x2BDD0000));
udata = new OutStream();
udata.writeTLVWord(0x000B, 0x00FF);
sendPacket(new SnacPacket(SnacPacket.SSI_FAMILY, SnacPacket.CLI_REQLISTS_COMMAND, SnacPacket.CLI_REQLISTS_COMMAND, udata.toByteArray()));
SnacPacket reply2;
timestamp = getIcq().getSsiListLastChangeTime();
count = getIcq().getSsiNumberOfItems();
if ((-1 == timestamp) || (0 == count) || (0 == getIcq().getContactItems().size())) {
reply2 = new SnacPacket(SnacPacket.SSI_FAMILY, SnacPacket.CLI_REQROSTER_COMMAND, 0x07630000);
} else {
OutStream data = new OutStream();
data.writeDWordBE(timestamp);
data.writeWordBE(count);
reply2 = new SnacPacket(SnacPacket.SSI_FAMILY, SnacPacket.CLI_CHECKROSTER_COMMAND, data.toByteArray());
}
sendPacket(reply2);
roster = new TemporaryRoster(getIcq());
getIcq().setContactListInfo(-1, 0);
getIcq().setContactListStub();
// Request limits
//sendPacket(new SnacPacket(SnacPacket.LOCATION_FAMILY, SnacPacket.CLI_REQLOCATION_COMMAND, SnacPacket.CLI_REQLOCATION_COMMAND));
// Request roster limits
//udata = new OutStream();
//udata.writeTLVWord(0x0005, 0x000B);
//sendPacket(new SnacPacket(SnacPacket.CONTACT_FAMILY, SnacPacket.CLI_REQBUDDY_COMMAND, SnacPacket.CLI_REQBUDDY_COMMAND, udata.toByteArray()));
// request ICBM
//sendPacket(new SnacPacket(SnacPacket.CLI_ICBM_FAMILY, SnacPacket.CLI_REQICBM_COMMAND, SnacPacket.CLI_REQICBM_COMMAND));
// Request private lists limits
//sendPacket(new SnacPacket(SnacPacket.BOS_FAMILY, SnacPacket.CLI_REQBOS_COMMAND, SnacPacket.CLI_REQBOS_COMMAND));
// Move to next state
this.state = ConnectAction.STATE_CLI_CHECKROSTER_SENT;
// Watch out for STATE_CLI_CHECKROSTER_SENT
} else if (STATE_CLI_CHECKROSTER_SENT == state) {
if (packet instanceof SnacPacket) {
consumed = loadContactList((SnacPacket) packet);
}
} else if (STATE_CLI_STATUS_INFO_SENT == state) {
// Send a CLI_TOICQSRV/CLI_REQOFFLINEMSGS packet
sendPacket(new ToIcqSrvPacket(0x00000000, this.uin, ToIcqSrvPacket.CLI_REQOFFLINEMSGS_SUBCMD, new byte[0], new byte[0]));
getConnection().initPing();
getConnection().setIcqConnected();
// Move to next state
this.state = ConnectAction.STATE_CLI_REQOFFLINEMSGS_SENT;
}
// Update activity timestamp and reset activity flag
active();
this.active = false;
updateProgress();
// Return consumption flag
return consumed;
// Catch JimmExceptions
} catch (JimmException e) {
// Update activity timestamp and reset activity flag
this.active = false;
// Set error state if exception is critical
this.state = ConnectAction.STATE_ERROR;
// Forward exception
throw e;
}
}
private void requestOtherContacts() throws JimmException {
OutStream stream = new OutStream();
stream.writeTLVByte(0x08, 1);
sendPacket(new SnacPacket(SnacPacket.CONTACT_FAMILY, SnacPacket.CLI_REQBUDDY_COMMAND, stream.toByteArray()));
}
private void processOtherContacts(SnacPacket snacPacket) throws JimmException {
}
private void sendStatusData() throws JimmException {
byte pstatus = getIcq().getIcqPrivateStatus();
sendPacket(getIcq().getPrivateStatusPacket(pstatus));
// #sijapp cond.if modules_XSTATUSES is "true" #
int x = getIcq().getProfile().xstatusIndex;
String title = getIcq().getProfile().xstatusTitle;
String desc = getIcq().getProfile().xstatusDescription;
//sendPacket(OtherAction.getNew2XStatus(getIcq(), title, desc));
title = StringUtils.notNull(title);
desc = StringUtils.notNull(desc);
String text = (title + " " + desc).trim();
sendPacket(getIcq().getNewXStatusPacket(x, text));
// #sijapp cond.end#
sendPacket(getIcq().getStatusPacket());
// Send to server sequence of unuthoruzed oldContacts to see their statuses
////////////////////////////////////
// Set version information to this packet in our capability
sendPacket(getIcq().getCapsPacket());
sendPacket(getIcbmPacket());
}
private boolean loadContactList(SnacPacket snacPacket) throws JimmException {
boolean consumed = false;
if (SnacPacket.SSI_FAMILY != snacPacket.getFamily()) {
return false;
}
boolean srvReplyRosterRcvd = false;
boolean newRosterLoaded = false;
// Watch out for
// SRV_REPLYROSTEROK
if (SnacPacket.SRV_REPLYROSTEROK_COMMAND == snacPacket.getCommand()) {
srvReplyRosterRcvd = true;
newRosterLoaded = false;
// Packet has been consumed
consumed = true;
roster.useOld();
// Update contact list
getIcq().setContactList(roster.getGroups(), roster.mergeContacts());
getIcq().setContactListInfo(timestamp, count);
// watch out for SRV_REPLYROSTER
// packet
} else if (SnacPacket.SRV_REPLYROSTER_COMMAND == snacPacket.getCommand()) {
if (1 != snacPacket.getFlags()) {
srvReplyRosterRcvd = true;
newRosterLoaded = true;
}
// Get data
ArrayReader marker = snacPacket.getReader();
// SRV_REPLYROSTER.UNKNOWN
marker.skip(1);
// Iterate through all
// items
count = marker.getWordBE();
for (int i = 0; i < count; ++i) {
// Get userId length
int nameLen = marker.getWordBE();
// Get userId
String userId = StringUtils.utf8beByteArrayToString(
marker.getArray(nameLen), 0, nameLen);
// Get groupId, id and type
int groupId = marker.getWordBE();
int id = marker.getWordBE();
int type = marker.getWordBE();
// Get length of the following TLVs
int len = marker.getWordBE();
// Normal contact
if (0x0000 == type) {
// Get nick
String nick = userId;
boolean noAuth = false;
int end = marker.getOffset() + len;
while (marker.getOffset() < end) {
int tlvType = marker.getTlvType();
if (0x0131 == tlvType) {
byte[] tlvData = marker.getTlv();
nick = StringUtils.utf8beByteArrayToString(tlvData, 0, tlvData.length);
} else {
if (0x0066 == tlvType) {
noAuth = true;
}
marker.skipTlv();
}
//else if (tlvType == 0x006D) /* Server-side additional data */
//{
// Util.writeWord(serverData, tlvType, true);
// Util.writeWord(serverData, tlvData.length, true);
// Util.writeByteArray(serverData, tlvData);
//
// Util.showBytes(serverData.toByteArray());
//}
}
// Add this contact item to the vector
try {
//DebugLog.println("c " + userId + " " + nick);
//// only icq-contact (ignore aim contacts)
//Integer.parseInt(uin);
IcqContact item = (IcqContact) roster.makeContact(userId);
if (nick.equals(userId) && !StringUtils.isEmpty(item.getName())) {
nick = item.getName();
}
item.init(id, groupId, nick, noAuth);
roster.addContact(item);
} catch (Exception e) {
// Contact with wrong uin was received
}
// Group of oldContacts
} else if (0x0001 == type) {
marker.skip(len);
// Add this groupId item to the vector
if (0x0000 != groupId) {
Group grp = roster.getGroupById(groupId);
if (null == grp) {
grp = roster.makeGroup(userId);
grp.setGroupId(groupId);
} else {
grp.setName(userId);
}
if ("Not In List".equals(userId)) {
grp.setMode(Group.MODE_REMOVABLE | Group.MODE_BOTTOM);
} else {
grp.setMode(Group.MODE_FULL_ACCESS);
}
roster.addGroup(grp);
}
// #sijapp cond.if modules_SERVERLISTS is "true" #
// Permit record ("Allow" list in AIM, and "Visible" list in ICQ)
} else if (0x0002 == type) {
marker.skip(len);
visibleList.addElement(new PrivacyItem(userId, id));
// Deny record ("Block" list in AIM, and "Invisible" list in ICQ)
} else if (0x0003 == type) {
marker.skip(len);
invisibleList.addElement(new PrivacyItem(userId, id));
// Ignore list record.
} else if (0x000E == type) {
marker.skip(len);
ignoreList.addElement(new PrivacyItem(userId, id));
// #sijapp cond.end #
// Permit/deny settings or/and bitmask of the AIM classes
} else if (0x0004 == type) {
int end = marker.getOffset() + len;
while (marker.getOffset() < end) {
int tlvType = marker.getTlvType();
marker.skipTlv();
if (0x00CA == tlvType) {
getIcq().privateStatusId = id;
}
}
// All other item types
} else {
// Skip TLVs
marker.skip(len);
}
}
// Get timestamp
timestamp = (int) marker.getDWordBE();
// Packet has been consumed
consumed = true;
}
// Check if all required packets have been received
if (newRosterLoaded) {
Vector<Contact> contactItems = roster.mergeContacts();
active();
// #sijapp cond.if modules_SERVERLISTS is "true" #
for (int i = 0; i < contactItems.size(); ++i) {
IcqContact contact = (IcqContact) contactItems.elementAt(i);
String userId = contact.getUserId();
contact.setBooleanValue(Contact.SL_IGNORE, inList(ignoreList, userId));
contact.setBooleanValue(Contact.SL_VISIBLE, inList(visibleList, userId));
contact.setBooleanValue(Contact.SL_INVISIBLE, inList(invisibleList, userId));
}
getIcq().setPrivacyLists(ignoreList, invisibleList, visibleList);
// #sijapp cond.end #
// Update contact list
getIcq().setContactList(roster.getGroups(), contactItems);
getIcq().setContactListInfo(timestamp, count);
}
if (srvReplyRosterRcvd) {
// #sijapp cond.if modules_DEBUGLOG is "true" #
DebugLog.memoryUsage("Connect memory usage");
// #sijapp cond.end #
sendStatusData();
// Send a CLI_ROSTERACK packet
sendPacket(new SnacPacket(SnacPacket.SSI_FAMILY, SnacPacket.CLI_ROSTERACK_COMMAND));
// Send a CLI_READY packet
sendPacket(new SnacPacket(SnacPacket.SERVICE_FAMILY, SnacPacket.CLI_READY_COMMAND, ConnectAction.CLI_READY_DATA));
//// avatars
//sendPacket(new SnacPacket(SnacPacket.SERVICE_FAMILY, 0x04, 0x6B1B0000, new byte[]{(byte)0x00, (byte)0x18}));
// Move to next state
this.state = ConnectAction.STATE_CLI_STATUS_INFO_SENT;
}
return consumed;
}
private SnacPacket getIcbmPacket() {
// Calculate client flags
// 0x0008 - typing notification
// 0x1000 - turn off status message
long flags = 0x0003;
if (0 != Options.getInt(Options.OPTION_TYPING_MODE)) {
flags |= 0x0B;
}
// ICQ6
// flags = 0x3FDB
OutStream icbm = new OutStream();
icbm.writeWordBE(0x0000);
icbm.writeDWordBE(flags); // message flags
icbm.writeWordBE(8000); // Maximum message size
icbm.writeWordBE(0x03E7);
icbm.writeWordBE(0x03E7);
icbm.writeWordBE(0x0000); // Minimum message interval
icbm.writeWordBE(0x0000);
return new SnacPacket(SnacPacket.CLI_ICBM_FAMILY, SnacPacket.CLI_SETICBM_COMMAND, icbm.toByteArray());
}
private boolean inList(Vector list, String uin) {
PrivacyItem item;
for (int i = list.size() - 1; 0 <= i; --i) {
item = (PrivacyItem) list.elementAt(i);
if (uin.equals(item.userId)) {
item.userId = uin;
return true;
}
}
return false;
}
// Returns true if the action is completed
public boolean isCompleted() {
return (null == getIcq()) || getIcq().isConnected();
}
// Returns true if an error has occured
public boolean isError() {
if (isCompleted()) {
return false;
}
if (state == ConnectAction.STATE_ERROR) {
return true;
}
if (!active && isNotActive(TIMEOUT)) {
state = ConnectAction.STATE_ERROR;
getConnection().processIcqException(new JimmException(118, 0));
}
return state == ConnectAction.STATE_ERROR;
}
private void updateProgress() {
setProgress(getProgress());
}
// Returns a number between 0 and 100 (inclusive) which indicates the current progress
private int getProgress() {
switch (this.state) {
case STATE_INIT:
return 1;
case STATE_INIT_DONE:
return 12;
case STATE_AUTHKEY_REQUESTED:
return 25;
case STATE_CLI_IDENT_SENT:
return 37;
case STATE_CLI_DISCONNECT_SENT:
return 50;
case STATE_CLI_COOKIE_SENT:
return 62;
case STATE_CLI_WANT_CAPS_SENT:
return 68;
case STATE_CLI_WANT_CAPS_SENT2:
return 69;
case STATE_CLI_CHECKROSTER_SENT:
return 75;
case STATE_CLI_STATUS_INFO_SENT:
return 90;
case STATE_CLI_REQOFFLINEMSGS_SENT:
return 100;
}
return 2;
}
}
// #sijapp cond.end #