示例#1
0
void ICQClient::snac_buddy(unsigned short type, unsigned short)
{
    switch (type){
    case ICQ_SNACxBDY_RIGHTSxGRANTED:
        log(L_DEBUG, "Buddy rights granted");
        break;
    case ICQ_SNACxBDY_USEROFFLINE:{
            unsigned long uin = readBuffer.unpackUin();
            ICQUser *user = getUser(uin);
            if (user && (user->uStatus != ICQ_STATUS_OFFLINE)){
                log(L_DEBUG, "User %lu [%s] offline", uin, user->Alias.c_str());
                user->setOffline();
                ICQEvent e(EVENT_STATUS_CHANGED, uin);
                process_event(&e);
            }
            break;
        }
    case ICQ_SNACxBDY_USERONLINE:{
            unsigned long uin = readBuffer.unpackUin();
            if (uin == Uin()) break;
            ICQUser *user = getUser(uin);
            if (user){
                time_t now;
                time(&now);
                bool changed = false;

                unsigned long cookie1, cookie2, cookie3;
                cookie1 = cookie2 = cookie3 = 0;
                unsigned short level, len;
                readBuffer >> level >> len;
                TlvList tlv(readBuffer);

                // Status TLV
                Tlv *tlvStatus = tlv(0x0006);
                if (tlvStatus){
                    unsigned long status = *tlvStatus;
                    log(L_DEBUG, "User %lu [%s] online [%08lX]", uin, user->Alias.c_str(), status);
                    if (status != user->uStatus){
                        user->prevStatus = user->uStatus;
                        user->uStatus = status;
                        if (status & 0xFF){
                            addResponseRequest(uin);
                        }else{
                            user->AutoReply = "";
                        }
                        user->StatusTime = (unsigned long)now;
                        changed = true;
                    }
                }

                // Online time TLV
                Tlv *tlvOnlineTime = tlv(0x0003);
                if (tlvOnlineTime){
                    user->OnlineTime = (unsigned long)(*tlvOnlineTime);
                    changed = true;
                }
                Tlv *tlvNATime = tlv(0x0004);
                if (tlvNATime){
                    user->StatusTime = (unsigned long)now - (unsigned short)(*tlvNATime) * 60L;
                    changed = true;
                }
                // IP TLV
                Tlv *tlvIP = tlv(0x000A);
                if (tlvIP){
                    unsigned long ip = htonl((unsigned long)(*tlvIP));
                    if (user->IP() != ip) user->HostName = "";
                    user->IP = ip;
                    changed = true;
                }

                // Direct connection info
                Tlv *tlvDirect = tlv(0x000C);
                if (tlvDirect){
                    user->ClientType = 0;
                    Buffer info(*tlvDirect);
                    unsigned long  realIP;
                    unsigned short port;
                    char mode, version, junk;
                    info >> realIP;
                    info.incReadPos(2);
                    info >> port;
                    realIP = htonl(realIP);
                    if (user->RealIP != realIP) user->RealHostName ="";
                    user->RealIP = realIP;
                    user->Port = port;
                    info >> mode >> junk >> version >> user->DCcookie;
                    info.incReadPos(8);
                    info
                    >> cookie1
                    >> cookie2
                    >> cookie3;
                    if (cookie3 != user->PhoneBookTime()){
                        user->bPhoneChanged = true;
                        user->PhoneBookTime = cookie3;
                    }
                    user->PhoneStatusTime = cookie2;
                    user->TimeStamp       = cookie1;
                    if (mode == MODE_DENIED) mode = MODE_INDIRECT;
                    if ((mode != MODE_DIRECT) && (mode != MODE_INDIRECT))
                        mode = MODE_INDIRECT;
                    user->Mode = (unsigned short)mode;
                    user->Version = (unsigned short)version;
                    changed = true;
                    if (user->DCcookie == 0)
                        user->ClientType = 4;
                    if ((user->DCcookie == cookie1) && (cookie1 == cookie2))
                        user->ClientType = 5;
                    if (cookie1 == 0x279c6996)
                        user->ClientType = 3;
                }

                Tlv *tlvCapability = tlv(0x000D);
                if (tlvCapability){
                    user->GetRTF = false;
                    Buffer info(*tlvCapability);
                    for (; info.readPos() < info.size(); ){
                        capability cap;
                        info.unpack((char*)cap, sizeof(capability));
                        if (!memcmp(cap, capabilities[1], sizeof(capability))){
                            user->GetRTF = true;
                            if (!user->CanPlugin){
                                if (user->bPhoneChanged) addPhoneRequest(uin);
                                user->CanPlugin = true;
                            }
                        }
                        if (!memcmp(cap, capabilities[3], sizeof(capability)))
                            user->CanResponse = true;
                        if (!memcmp(cap, capabilities[5], sizeof(capability)))
                            user->ClientType = 2;
                        if (!memcmp(cap, capabilities[4], sizeof(capability)))
                            user->ClientType = 1;
                        if (!memcmp(cap, capabilities[4], sizeof(capability)-1) &&
                                (cap[sizeof(capability)-1] > (1 << 6)) &&
                                (cap[sizeof(capability)-1] != 0x92))
                            user->ClientType = (char)(cap[sizeof(capability)-1]);
                    }
                }

                Tlv *tlvPlugin = tlv(0x0011);
                if (tlvPlugin){
                    Buffer info(*tlvPlugin);
                    char reqType;
                    info >> reqType;
                    info.incReadPos(10);
                    capability cap;
                    info.unpack((char*)cap, sizeof(capability));
                    if (user->CanPlugin && !memcmp(cap, PHONEBOOK_SIGN, sizeof(capability))){
                        if (reqType == 3){
                            info.incReadPos(3);
                            info >> user->PhoneState;
                            if (user->bPhoneChanged) addPhoneRequest(uin);
                        }else if (reqType == 2)
                            if (user->bPhoneChanged) addPhoneRequest(uin);
                    }
                    addInfoRequest(uin);
                    changed = true;
                }

                if (changed){
                    ICQEvent e(EVENT_STATUS_CHANGED, uin);
                    process_event(&e);
                    user->prevStatus = user->uStatus;
                }
            }
            break;
        }
示例#2
0
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);
    }
}