Пример #1
0
ICQMessage *ICQClient::parseMessage(unsigned short type, unsigned long uin, string &p, Buffer &packet,
                                    unsigned short cookie1, unsigned short cookie2,
                                    unsigned long timestamp1, unsigned long timestamp2)
{
    log(L_DEBUG, "Parse message [type=%u]", type);
    ICQUser *u = getUser(uin);
    switch (type){
    case ICQ_MSGxMSG:{
            if (uin < 1000){
                log(L_WARN, "Strange UIN %lu in message", uin);
                return NULL;
            }
            if (*(p.c_str()) == 0) return NULL;
            ICQMsg *msg = new ICQMsg;
            msg->Uin.push_back(uin);
            parseMessageText(p.c_str(), msg->Message, u);
            unsigned long forecolor, backcolor;
            packet >> forecolor >> backcolor;
            if (forecolor != backcolor){
                msg->ForeColor = forecolor >> 8;
                msg->BackColor = backcolor >> 8;
            }
            return msg;
        }
    case ICQ_MSGxURL:{
            if (uin < 1000){
                log(L_WARN, "Strange UIN %lu in URL message", uin);
                return NULL;
            }
            vector<string> l;
            if (!parseFE(p.c_str(), l, 2)){
                log(L_WARN, "Parse error URL message");
                return NULL;
            }
            ICQUrl *msg = new ICQUrl;
            msg->Uin.push_back(uin);
            parseMessageText(l[0].c_str(), msg->Message, u);
            msg->URL = l[1];
            return msg;
        }
    case ICQ_MSGxAUTHxREQUEST:{
            if (uin < 1000){
                log(L_WARN, "Strange UIN %lu in auth request message", uin);
                return NULL;
            }
            vector<string> l;
            if (!parseFE(p.c_str(), l, 6)){
                log(L_WARN, "Parse error auth request message");
                return NULL;
            }
            ICQAuthRequest *msg = new ICQAuthRequest;
            msg->Uin.push_back(uin);
            parseMessageText(l[4].c_str(), msg->Message, u);
            return msg;
        }
    case ICQ_MSGxAUTHxGRANTED:{
            if (uin < 1000){
                log(L_WARN, "Strange UIN %lu in auth granted message", uin);
                return NULL;
            }
            ICQAuthGranted *msg = new ICQAuthGranted;
            msg->Uin.push_back(uin);
            return msg;
        }
    case ICQ_MSGxAUTHxREFUSED:{
            if (uin < 1000){
                log(L_WARN, "Strange UIN %lu in auth refused message", uin);
                return NULL;
            }
            ICQAuthRefused *msg = new ICQAuthRefused;
            msg->Uin.push_back(uin);
            parseMessageText(p.c_str(), msg->Message, u);
            return msg;
        }
    case ICQ_MSGxADDEDxTOxLIST:{
            if (uin < 1000){
                log(L_WARN, "Strange UIN %lu in added to list message", uin);
                return NULL;
            }
            ICQAddedToList *msg = new ICQAddedToList;
            msg->Uin.push_back(uin);
            return msg;
        }
    case ICQ_MSGxCONTACTxLIST:{
            if (uin < 1000){
                log(L_WARN, "Strange UIN %lu in contact message", uin);
                return NULL;
            }
            vector<string> l;
            if (!parseFE(p.c_str(), l, 2)){
                log(L_WARN, "Parse error contacts message");
                return NULL;
            }
            unsigned nContacts = atol(l[0].c_str());
            if (nContacts == 0){
                log(L_WARN, "No contacts found");
                return NULL;
            }
            vector<string> c;
            if (!parseFE(l[1].c_str(), c, nContacts*2+1)){
                log(L_WARN, "Parse error contacts message");
                return NULL;
            }
            ICQContacts *msg = new ICQContacts;
            msg->Uin.push_back(uin);
            for (unsigned i = 0; i < nContacts; i++){
                Contact *contact = new Contact;
                contact->Uin = atol(c[i*2].c_str());
                fromServer(c[i*2+1], u);
                contact->Alias = c[i*2+1];
                msg->Contacts.push_back(contact);
            }
            return msg;
        }
    case ICQ_MSGxCHAT:{
            unsigned short port;
            unsigned short junk;
            string name;
            packet
            >> name
            >> port >> junk
            >> junk >> junk;
            fromServer(p, u);
            ICQChat *msg = new ICQChat();
            msg->Uin.push_back(uin);
            msg->Reason = p;
            msg->id1 = port;
            msg->timestamp1 = timestamp1;
            return msg;
        }
    case ICQ_MSGxFILE:{
            unsigned short port;
            unsigned short junk;
            unsigned long fileSize;
            string fileName;
            packet
            >> port
            >> junk
            >> fileName
            >> fileSize
            >> junk >> junk;
            fromServer(p, u);
            fromServer(fileName, u);
            const char *shortName = strrchr(fileName.c_str(), '\\');
            if (shortName){
                shortName++;
            }else{
                shortName = fileName.c_str();
            }
            ICQFile *msg = new ICQFile();
            msg->Uin.push_back(uin);
            msg->Name = shortName;
            msg->Description = p;
            msg->Size = htonl(fileSize);
            msg->id1 = port;
            msg->timestamp1 = timestamp1;
            return msg;
        }
    case ICQ_MSGxSECURExOPEN:{
            ICQSecureOn *msg = new ICQSecureOn;
            msg->Uin.push_back(uin);
            return msg;
        }
    case ICQ_MSGxSECURExCLOSE:{
            ICQSecureOff *msg = new ICQSecureOff;
            msg->Uin.push_back(uin);
            return msg;
        }
    case ICQ_READxAWAYxMSG:
    case ICQ_READxOCCUPIEDxMSG:
    case ICQ_READxNAxMSG:
    case ICQ_READxDNDxMSG:
    case ICQ_READxFFCxMSG:{
            ICQAutoResponse *msg = new ICQAutoResponse;
            msg->setType(type);
            return msg;
        }
    case ICQ_MSGxEXT:{
            string header;
            packet >> header;
            Buffer h(header.size());
            h.pack(header.c_str(), header.size());
            h.incReadPos(16);
            unsigned short msg_type;
            h >> msg_type;
            string msgType;
            h.unpackStr32(msgType);
            string info;
            packet.unpackStr32(info);
            Buffer b(info.size());
            b.pack(info.c_str(), info.size());
            log(L_DEBUG, "Extended message %s [%04X] %u", msgType.c_str(), msg_type, info.size());
            if (strstr(msgType.c_str(), "File")){
                string fileDescr;
                b.unpackStr32(fileDescr);
                unsigned short id1, id2;
                b >> id1 >> id2;
                string fileName;
                b >> fileName;
                unsigned long fileSize;
                b >> fileSize;
                fileSize = htonl(fileSize);
                fromServer(fileDescr, u);
                fromServer(fileName, u);
                ICQFile *msg = new ICQFile();
                msg->isExt = true;
                msg->Uin.push_back(uin);
                msg->Name = fileName;
                msg->Description = fileDescr;
                msg->Size = fileSize;
                msg->id1 = id1;
                msg->id2 = id2;
                msg->cookie1 = cookie1;
                msg->cookie2 = cookie2;
                msg->timestamp1 = timestamp1;
                msg->timestamp2 = timestamp2;
                return msg;
            }
            if (strstr(msgType.c_str(), "Web Page Address (URL)")){
                string info;
                b.unpackStr32(info);
                vector<string> l;
                if (!parseFE(info.c_str(), l, 2)){
                    log(L_DEBUG, "Parse error extended URL message");
                    return NULL;
                }
                ICQUrl *msg = new ICQUrl();
                msg->Uin.push_back(uin);
                parseMessageText(l[0].c_str(), msg->Message, u);
                msg->URL = l[1];
                return msg;
            }
            if (!strcmp(msgType.c_str(), "Request For Contacts")){
                string info;
                b.unpackStr32(info);
                ICQContactRequest *msg = new ICQContactRequest();
                msg->Uin.push_back(uin);
                parseMessageText(info.c_str(), msg->Message, u);
                return msg;
            }
            if (!strcmp(msgType.c_str(), "Send / Start ICQ Chat")){
                string reason;
                b.unpackStr32(reason);
                ICQChat *msg = new ICQChat;
                parseMessageText(reason.c_str(), msg->Reason, u);
                char flag;
                b >> flag;
                if (flag){
                    b.incReadPos(2);
                    b >> msg->id1 >> msg->id2;
                }
                msg->Uin.push_back(uin);
                msg->cookie1 = cookie1;
                msg->cookie2 = cookie2;
                msg->timestamp1 = timestamp1;
                msg->timestamp2 = timestamp2;
                return msg;
            }
Пример #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);
    }
}
Пример #3
0
void ICQClient::snac_message(unsigned short type, unsigned short)
{
    switch (type){
    case ICQ_SNACxMSG_RIGHTSxGRANTED:
        log(L_DEBUG, "Message rights granted");
        break;
    case ICQ_SNACxMSG_ACK:
        log(L_DEBUG, "Ack message");
        break;
    case ICQ_SNACxMSG_AUTOREPLY:{
            unsigned long timestamp1, timestamp2;
            readBuffer >> timestamp1 >> timestamp2;
            readBuffer.incReadPos(2);
            unsigned long uin = readBuffer.unpackUin();
            readBuffer.incReadPos(6);
            unsigned long t1, t2;
            readBuffer >> t1 >> t2;
            unsigned short seq;
            readBuffer.incReadPos(0x0F);
            readBuffer >> seq;
            if ((t1 == 0) && (t2 == 0)){
                readBuffer.incReadPos(0x16);
                string answer;
                readBuffer >> answer;
                fromServer(answer);
                if (timestamp1 || timestamp2){
                    log(L_DEBUG, "Message declined %s", answer.c_str());
                    list<ICQEvent*>::iterator it;
                    for (it = processQueue.begin(); it != processQueue.end(); ++it){
                        ICQEvent *e = *it;
                        if (e->type() != EVENT_MESSAGE_SEND) continue;
                        ICQMessage *msg = e->message();
                        if (msg == NULL) continue;
                        if ((msg->Uin == uin) && (msg->timestamp1 == timestamp1) && (msg->timestamp2 == timestamp2)){
                            msg->DeclineReason = answer;
                            cancelMessage(msg, false);
                            break;
                        }
                    }
                    if (it == processQueue.end())
                        log(L_WARN, "Decline file answer: message not found");
                }else{
                    log(L_DEBUG, "[%X] Autoreply from %u %s", seq, uin, answer.c_str());
                    ICQUser *u = getUser(uin);
                    if (u) u->AutoReply = answer;
                    ICQEvent e(EVENT_STATUS_CHANGED, uin);
                    process_event(&e);
                    processResponseRequestQueue(seq);
                }
            }
            if ((t1 == 0xA0E93F37L) && (t2 == 0x4FE9D311L)){
                ICQUser *u = getUser(uin);
                if (u == NULL){
                    log(L_WARN, "Request info no my user %lu", uin);
                    return;
                }
                if (u->inIgnore()){
                    log(L_WARN, "Request info ignore user %lu", uin);
                    return;
                }

                readBuffer.incReadPos(0x1D);
                unsigned long cookie;
                readBuffer >> cookie;
                readBuffer.incReadPos(4);
                readBuffer.unpack(t1);
                if (t1 == 3){
                    u->PhoneBookTime = (unsigned long)htonl(cookie);
                    u->bPhoneChanged = false;
                    log(L_DEBUG, "[%X] Phone book info %u", seq, uin);
                    PhoneBook::iterator it;
                    PhonePtrList myNumbers;
                    for (it = u->Phones.begin(); it != u->Phones.end(); ++it){
                        PhoneInfo *phone = static_cast<PhoneInfo*>(*it);
                        if (!phone->MyInfo()) continue;
                        PhoneInfo *myPhone = new PhoneInfo;
                        *myPhone = *phone;
                        myNumbers.push_back(myPhone);
                    }
                    u->Phones.clear();
                    unsigned long nPhones;
                    readBuffer.unpack(nPhones);
                    for (unsigned i = 0; i < nPhones; i++){
                        PhoneInfo *phone = new PhoneInfo;
                        u->Phones.push_back(phone);
                        readBuffer.unpackStr32(phone->Name);
                        readBuffer.unpackStr32(phone->AreaCode);
                        readBuffer.unpackStr32(phone->Number);
                        readBuffer.unpackStr32(phone->Extension);
                        readBuffer.unpackStr32(phone->Country);
                        unsigned long type;
                        readBuffer.unpack(type);
                        if (type) phone->Active = true;
                        if (readBuffer.readPos() >= readBuffer.size()) break;
                    }
                    for (it = u->Phones.begin(); it != u->Phones.end(); it++){
                        PhoneInfo *phone = static_cast<PhoneInfo*>(*it);
                        string prop;
                        readBuffer.unpackStr32(prop);
                        Buffer b;
                        b.pack(prop.c_str(), prop.length());
                        b.unpack(phone->Type);
                        b.unpackStr32(phone->Provider);
                        if (readBuffer.readPos() >= readBuffer.size()) break;
                    }
                    for (;;){
                        for (it = u->Phones.begin(); it != u->Phones.end(); it++){
                            PhoneInfo *phone = static_cast<PhoneInfo*>(*it);
                            bool bOK = (phone->getNumber().length() > 0);
                            if (bOK && !*phone->Number.c_str()) bOK = false;
                            if (bOK)
                                for (const char *p = phone->Number.c_str(); *p; p++){
                                    if ((*p >= '0') && (*p <= '9')) continue;
                                    if ((*p == ' ') || (*p == '-')) continue;
                                    bOK = false;
                                    break;
                                }
                            if (bOK) continue;
                            u->Phones.remove(phone);
                            break;
                        }
                        if (it == u->Phones.end()) break;
                    }
                    u->adjustPhones();
                    u->Phones.add(myNumbers);
                    ICQEvent e(EVENT_INFO_CHANGED, uin);
                    process_event(&e);
                    processPhoneRequestQueue(seq);
                }
            }
            break;
        }
Пример #4
0
void ICQClient::fromServer(string &str, ICQUser *u)
{
    fromServer(str, localCharset(u));
}