void ICQClientPrivate::snac_lists(unsigned short type, unsigned short seq) { switch (type){ case ICQ_SNACxLISTS_RIGHTS: log(L_DEBUG, "List rights"); break; case ICQ_SNACxLISTS_ROSTER:{ char c; unsigned short list_len; log(L_DEBUG,"Rosters"); sock->readBuffer >> c; if (c){ log(L_WARN, "Bad first roster byte %02X", c); break; } bool bIgnoreTime = false; vector<ICQGroup*>::iterator it_grp; list<ICQUser*>::iterator it_usr; if (!m_bRosters){ m_bRosters = true; client->contacts.Invisible = 0; for (it_grp = client->contacts.groups.begin(); it_grp != client->contacts.groups.end(); it_grp++) (*it_grp)->bChecked = false; for (it_usr = client->contacts.users.begin(); it_usr != client->contacts.users.end(); it_usr++){ if ((*it_usr)->Type != USER_TYPE_ICQ) continue; (*it_usr)->Id = 0; (*it_usr)->GrpId = 0; (*it_usr)->IgnoreId = 0; (*it_usr)->VisibleId = 0; (*it_usr)->InvisibleId = 0; } } sock->readBuffer >> list_len; for (unsigned i = 0; i < list_len; i++){ string str; unsigned short id, grp_id, type, len; sock->readBuffer.unpackStr(str); sock->readBuffer >> grp_id >> id >> type >> len; TlvList *inf = NULL; if (len){ Buffer b(len); b.pack(sock->readBuffer.Data(sock->readBuffer.readPos()), len); sock->readBuffer.incReadPos(len); inf = new TlvList(b); } switch (type){ case 0x0000: /* User */{ unsigned long uin = atol(str.c_str()); if (uin){ Tlv *tlv_name = NULL; if (inf) tlv_name = (*inf)(0x0131); string alias = tlv_name ? (char*)(*tlv_name) : ""; client->fromUTF(alias, client->owner->Encoding.c_str()); bool needAuth = false; if (inf && (*inf)(0x0066)) needAuth = true; ICQUser *user = client->getUser(uin, true); user->Id = id; user->GrpId = grp_id; user->Alias = alias; user->WaitAuth = needAuth; Tlv *tlv_phone = NULL; if (inf) tlv_phone = (*inf)(0x13A); if (tlv_phone){ user->Phones.add(*tlv_phone, "Private cellular", SMS, true, false); user->adjustPhones(); } }else{ bIgnoreTime = true; } break; } case ICQ_GROUPS:{ if (str.size() == 0) break; client->fromUTF(str, client->owner->Encoding.c_str()); ICQGroup *grp = client->getGroup(grp_id, true); if (grp == NULL){ grp = client->createGroup(); client->contacts.groups.push_back(grp); } grp->Id = grp_id; grp->Name = str; grp->bChecked = true; break; } case ICQ_VISIBLE_LIST:{ unsigned long uin = atol(str.c_str()); if (uin) client->getUser(atol(str.c_str()), true)->VisibleId = id; break; } case ICQ_INVISIBLE_LIST:{ unsigned long uin = atol(str.c_str()); if (uin) client->getUser(atol(str.c_str()), true)->InvisibleId = id; break; } case ICQ_IGNORE_LIST:{ unsigned long uin = atol(str.c_str()); if (uin) client->getUser(atol(str.c_str()), true)->IgnoreId = id; break; } case ICQ_INVISIBLE_STATE: client->contacts.Invisible = id; break; case 0x0009: case 0x0011: case 0x0013: break; default: log(L_WARN,"Unknown roster type %04X", type); } if (inf) delete inf; } unsigned long time; sock->readBuffer >> time; if ((time == 0) && list_len && !bIgnoreTime) break; client->contacts.Time = time; for (;;){ bool ok = true; for (it_grp = client->contacts.groups.begin(); it_grp != client->contacts.groups.end(); it_grp++){ if (!(*it_grp)->bChecked){ client->contacts.groups.erase(it_grp); ok = false; break; } } if (ok) break; } for (it_usr = client->contacts.users.begin(); it_usr != client->contacts.users.end(); it_usr++){ unsigned short grpId = (*it_usr)->GrpId; bool ok = false; for (it_grp = client->contacts.groups.begin(); it_grp != client->contacts.groups.end(); it_grp++){ if ((*it_grp)->Id == grpId){ ok = true; break; } } if (!ok) (*it_usr)->GrpId = 0; } ICQEvent e(EVENT_GROUP_CHANGED); client->process_event(&e); m_state = Logged; } case ICQ_SNACxLISTS_ROSTERxOK: // FALLTHROUGH { log(L_DEBUG, "Rosters OK"); snac(ICQ_SNACxFAM_LISTS, ICQ_SNACxLISTS_UNKNOWN); sendPacket(); sendCapability(); sendICMB(); sendLogonStatus(); sendClientReady(); sendMessageRequest(); sendPhoneStatus(); if (client->owner->Nick.size() == 0){ client->addInfoRequest(client->owner->Uin); client->searchByUin(client->owner->Uin); } list<ICQUser*>::iterator it; for (it = client->contacts.users.begin(); it != client->contacts.users.end(); it++){ ICQUser *u = *it; if (u->IgnoreId) continue; if (u->Nick.size() || u->Alias.size()) continue; client->addInfoRequest(u->Uin); } if (client->contacts.groups.size() == 0){ m_state = Logged; client->createGroup("General"); } if (client->contacts.Invisible == 0){ snac(ICQ_SNACxFAM_LISTS, ICQ_SNACxLISTS_EDIT); sendPacket(); snac(ICQ_SNACxFAM_LISTS, ICQ_SNACxLISTS_CREATE, true); sock->writeBuffer << 0x00000000L << 0x00000001L << 0x000400C8L << (unsigned short)0; sendPacket(); snac(ICQ_SNACxFAM_LISTS, ICQ_SNACxLISTS_SAVE); sendPacket(); } break; } case ICQ_SNACxLISTS_ADDED:{ sock->readBuffer.incReadPos(8); unsigned long uin = sock->readBuffer.unpackUin(); ICQAddedToList *m = new ICQAddedToList; m->Uin.push_back(uin); messageReceived(m); break; } case ICQ_SNACxLISTS_AUTHxREQUEST:{ sock->readBuffer.incReadPos(8); unsigned long uin = sock->readBuffer.unpackUin(); ICQUser *u = client->getUser(uin); string message; string charset; unsigned short have_charset; sock->readBuffer.unpackStr(message); sock->readBuffer >> have_charset; if (have_charset){ sock->readBuffer.incReadPos(2); sock->readBuffer.unpackStr(charset); } if (charset.size()){ client->translate(client->localCharset(u), charset.c_str(), message); }else{ client->fromServer(message, u); } log(L_DEBUG, "Auth request %lu", uin); ICQAuthRequest *m = new ICQAuthRequest; m->Uin.push_back(uin); m->Message = message; messageReceived(m); break; } case ICQ_SNACxLISTS_AUTH:{ sock->readBuffer.incReadPos(8); unsigned long uin = sock->readBuffer.unpackUin(); char auth_ok; sock->readBuffer >> auth_ok; string message; string charset; unsigned short have_charset; sock->readBuffer.unpackStr(message); sock->readBuffer >> have_charset; if (have_charset){ sock->readBuffer.incReadPos(2); sock->readBuffer.unpackStr(charset); } ICQUser *u = client->getUser(uin); if (charset.size()){ client->translate(client->localCharset(u), charset.c_str(), message); }else{ client->fromServer(message, u); } log(L_DEBUG, "Auth %u %lu", auth_ok, uin); if (auth_ok){ ICQUser *user = client->getUser(uin); if (user){ user->WaitAuth = false; ICQEvent e(EVENT_INFO_CHANGED, uin); client->process_event(&e); } ICQAuthGranted *m = new ICQAuthGranted(); m->Uin.push_back(uin); messageReceived(m); }else{ ICQAuthRefused *m = new ICQAuthRefused(); m->Uin.push_back(uin); m->Message = message; messageReceived(m); } break; } case ICQ_SNACxLISTS_DONE:{ ICQEvent *e = findListEvent(seq); if (e == NULL) break; sock->readBuffer.incReadPos(8); unsigned short res; sock->readBuffer >> res; e->processAnswer(this, sock->readBuffer, res); delete e; break; } default: log(L_WARN, "Unknown lists family type %04X", type); } }
void ICQClient::snac_lists(unsigned short type, unsigned short seq) { bool bFull = false; switch (type){ case ICQ_SNACxLISTS_RIGHTS: log(L_DEBUG, "List rights"); break; case ICQ_SNACxLISTS_ROSTER:{ char c; unsigned short list_len; log(L_DEBUG,"Rosters"); if (m_bRosters){ log(L_DEBUG, "Rosters part 2"); break; } readBuffer >> c; if (c){ log(L_WARN, "Bad first roster byte %02X", c); break; } vector<ICQGroup*>::iterator it_grp; list<ICQUser*>::iterator it_usr; for (it_grp = contacts.groups.begin(); it_grp != contacts.groups.end(); it_grp++) (*it_grp)->bChecked = false; for (it_usr = contacts.users.begin(); it_usr != contacts.users.end(); it_usr++){ if ((*it_usr)->Type != USER_TYPE_ICQ) continue; (*it_usr)->Id = 0; (*it_usr)->GrpId = 0; (*it_usr)->inIgnore = false; (*it_usr)->inVisible = false; (*it_usr)->inInvisible = false; } readBuffer >> list_len; for (unsigned i = 0; i < list_len; i++){ string str; unsigned short id, grp_id, type, len; readBuffer.unpackStr(str); readBuffer >> grp_id >> id >> type >> len; TlvList *inf = NULL; if (len){ Buffer b(len); b.pack(readBuffer.Data(readBuffer.readPos()), len); readBuffer.incReadPos(len); inf = new TlvList(b); } switch (type){ case 0x0000: /* User */{ unsigned long uin = atol(str.c_str()); if (uin == 0){ log(L_WARN, "Bad uin record %s\n", str.c_str()); break; } Tlv *tlv_name = NULL; if (inf) tlv_name = (*inf)(0x0131); string alias = tlv_name ? (char*)(*tlv_name) : ""; fromUTF(alias); bool needAuth = false; if (inf && (*inf)(0x0066)) needAuth = true; ICQUser *user = getUser(uin, true); user->Id = id; user->GrpId = grp_id; user->Alias = alias; user->WaitAuth = needAuth; break; } case ICQ_GROUPS:{ if (str.size() == 0) break; fromUTF(str); ICQGroup *grp = getGroup(grp_id, true); if (grp == NULL){ grp = new ICQGroup(); contacts.groups.push_back(grp); } grp->Id = grp_id; grp->Name = str; grp->bChecked = true; break; } case ICQ_VISIBLE_LIST:{ unsigned long uin = atol(str.c_str()); if (uin) getUser(atol(str.c_str()), true)->inVisible = true; break; } case ICQ_INVISIBLE_LIST:{ unsigned long uin = atol(str.c_str()); if (uin) getUser(atol(str.c_str()), true)->inInvisible = true; break; } case ICQ_IGNORE_LIST:{ unsigned long uin = atol(str.c_str()); if (uin) getUser(atol(str.c_str()), true)->inIgnore = true; break; } case ICQ_INVISIBLE_STATE: contacts.Invisible = id; break; case 0x0009: break; default: log(L_WARN,"Unknown roster type %04X", type); } if (inf) delete inf; } unsigned long time; readBuffer >> time; contacts.Time = time; for (;;){ bool ok = true; for (it_grp = contacts.groups.begin(); it_grp != contacts.groups.end(); it_grp++){ if (!(*it_grp)->bChecked){ contacts.groups.erase(it_grp); ok = false; break; } } if (ok) break; } for (it_usr = contacts.users.begin(); it_usr != contacts.users.end(); it_usr++){ unsigned short grpId = (*it_usr)->GrpId(); bool ok = false; for (it_grp = contacts.groups.begin(); it_grp != contacts.groups.end(); it_grp++){ if ((*it_grp)->Id() == grpId){ ok = true; break; } } if (!ok) (*it_usr)->GrpId = 0; } ICQEvent e(EVENT_GROUP_CHANGED); process_event(&e); m_state = Logged; bFull = true; } case ICQ_SNACxLISTS_ROSTERxOK: // FALLTHROUGH { m_bRosters = true; log(L_DEBUG, "Rosters OK"); snac(ICQ_SNACxFAM_LISTS, ICQ_SNACxLISTS_UNKNOWN); sendPacket(); sendCapability(); sendICMB(); sendLogonStatus(); sendClientReady(); sendMessageRequest(); sendPhoneInit(); sendPhoneStatus(); if (bFull || (Nick.size() == 0)){ addInfoRequest(Uin); searchByUin(Uin); } list<ICQUser*>::iterator it; for (it = contacts.users.begin(); it != contacts.users.end(); it++){ if ((*it)->inIgnore()) continue; if (!bFull && (*it)->Nick.size()) continue; addInfoRequest((*it)->Uin); } if (contacts.groups.size() == 0){ m_state = Logged; createGroup("General"); } break; } case ICQ_SNACxLISTS_ADDED:{ readBuffer.incReadPos(8); unsigned long uin = readBuffer.unpackUin(); ICQAddedToList *m = new ICQAddedToList; m->Uin.push_back(uin); messageReceived(m); break; } case ICQ_SNACxLISTS_AUTHxREQUEST:{ readBuffer.incReadPos(8); unsigned long uin = readBuffer.unpackUin(); ICQUser *u = getUser(uin); string message; string charset; unsigned short have_charset; readBuffer.unpackStr(message); readBuffer >> have_charset; if (have_charset){ readBuffer.incReadPos(2); readBuffer.unpackStr(charset); } if (charset.size()){ translate(localCharset(u), charset.c_str(), message); }else{ fromServer(message, u); } log(L_DEBUG, "Auth request %lu", uin); ICQAuthRequest *m = new ICQAuthRequest; m->Uin.push_back(uin); m->Message = message; messageReceived(m); break; } case ICQ_SNACxLISTS_AUTH:{ readBuffer.incReadPos(8); unsigned long uin = readBuffer.unpackUin(); char auth_ok; readBuffer >> auth_ok; string message; string charset; unsigned short have_charset; readBuffer.unpackStr(message); readBuffer >> have_charset; if (have_charset){ readBuffer.incReadPos(2); readBuffer.unpackStr(charset); } ICQUser *u = getUser(uin); if (charset.size()){ translate(localCharset(u), charset.c_str(), message); }else{ fromServer(message, u); } log(L_DEBUG, "Auth %u %lu", auth_ok, uin); if (auth_ok){ ICQUser *user = getUser(uin); if (user){ user->WaitAuth = false; ICQEvent e(EVENT_INFO_CHANGED, uin); process_event(&e); } ICQAuthGranted *m = new ICQAuthGranted(); m->Uin.push_back(uin); messageReceived(m); }else{ ICQAuthRefused *m = new ICQAuthRefused(); m->Uin.push_back(uin); m->Message = message; messageReceived(m); } break; } case ICQ_SNACxLISTS_DONE:{ ICQEvent *e = findListEvent(seq); if (e == NULL) break; readBuffer.incReadPos(8); unsigned short res; readBuffer >> res; e->processAnswer(this, readBuffer, res); delete e; break; } default: log(L_WARN, "Unknown lists family type %04X", type); } }