예제 #1
0
void ICQClient::idle()
{
    time_t now;
    time(&now);
    if (m_state == Logged){
        processInfoRequestQueue();
        processPhoneRequestQueue(0);
        processResponseRequestQueue(0);
        if (now <= m_lastTime + PING_TIMEOUT) return;
        flap(ICQ_CHNxPING);
        sendPacket();
        return;
    }
    if (m_state == Reconnect){
        if (now <= m_reconnectTime) return;
        setStatus(m_nLogonStatus);
    }
}
예제 #2
0
void ICQClient::packet_ready()
{
    time(&m_lastTime);
    if (m_bHeader){
        char c;
        readBuffer >> c;
        if (c != 0x2A){
            log(L_ERROR, "Server send bad packet start code: %02X", c);
            error(ErrorProtocol);
            return;
        }
        readBuffer >> m_nChannel;
        unsigned short sequence, size;
        readBuffer >> sequence >> size;
        if (size){
            readBuffer.add(size);
            m_bHeader = false;
            return;
        }
    }
    dumpPacket(readBuffer, 0,"Read");
    switch (m_nChannel){
    case ICQ_CHNxNEW:
        chn_login();
        break;
    case ICQ_CHNxCLOSE:
        chn_close();
        break;
    case ICQ_CHNxDATA:{
            unsigned short fam, type;
            unsigned short flags, seq, cmd;
            readBuffer >> fam >> type >> flags >> seq >> cmd;
            switch (fam){
            case ICQ_SNACxFAM_SERVICE:
                snac_service(type, seq);
                break;
            case ICQ_SNACxFAM_LOCATION:
                snac_location(type, seq);
                break;
            case ICQ_SNACxFAM_BUDDY:
                snac_buddy(type, seq);
                break;
            case ICQ_SNACxFAM_MESSAGE:
                snac_message(type, seq);
                break;
            case ICQ_SNACxFAM_BOS:
                snac_bos(type, seq);
                break;
            case ICQ_SNACxFAM_PING:
                snac_ping(type, seq);
                break;
            case ICQ_SNACxFAM_LISTS:
                snac_lists(type, seq);
                break;
            case ICQ_SNACxFAM_VARIOUS:
                snac_various(type, seq);
                break;
            case ICQ_SNACxFAM_LOGIN:
                snac_login(type, seq);
                break;
            default:
                log(L_WARN, "Unknown family %02X", fam);
            }
            break;
        }
    default:
        log(L_ERROR, "Unknown channel %u", m_nChannel & 0xFF);
    }
    processInfoRequestQueue();
    processPhoneRequestQueue(0);
    processResponseRequestQueue(0);
    readBuffer.init(6);
    m_bHeader = true;
}
예제 #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;
        }