示例#1
0
void ICQClient::snac_icmb(unsigned short type, unsigned short seq)
{
    switch (type){
    case ICQ_SNACxMSG_RIGHTSxGRANTED:
        log(L_DEBUG, "Message rights granted");
        break;
    case ICQ_SNACxMSG_MTN:{
            m_socket->readBuffer.incReadPos(10);
            string screen = m_socket->readBuffer.unpackScreen();
            unsigned short type;
            m_socket->readBuffer >> type;
            bool bType = (type > 1);
            Contact *contact;
            ICQUserData *data = findContact(screen.c_str(), NULL, false, contact);
            if (data == NULL)
                break;
            if ((bool)(data->bTyping) == bType)
                break;
            data->bTyping = bType;
            Event e(EventContactStatus, contact);
            e.process();
            break;
        }
    case ICQ_SNACxMSG_ERROR:{
            unsigned short error;
            m_socket->readBuffer >> error;
            const char *err_str = I18N_NOOP("Unknown error");
            if (error == 0x0009){
                err_str = I18N_NOOP("Not supported by client");
                Contact *contact;
                ICQUserData *data = findContact(m_send.screen.c_str(), NULL, false, contact);
                if (data){
                    for (list<SendMsg>::iterator it = sendQueue.begin(); it != sendQueue.end();){
                        if ((*it).screen != m_send.screen){
                            ++it;
                            continue;
                        }
                        if ((*it).msg){
                            (*it).flags = 0;
                            ++it;
                            continue;
                        }
                        sendQueue.erase(it);
                        it = sendQueue.begin();
                    }
                    data->bBadClient = true;
                    if (m_send.msg)
                        sendThruServer(m_send.msg, data);
                    m_send.msg    = NULL;
                    m_send.screen = "";
                    m_sendTimer->stop();
                    send(true);
                    break;
                }
            }else{
                err_str = error_message(error);
            }
            if (m_send.msg){
                if ((m_send.msg->type() == MessageCheckInvisible) && (error == 14)) {
                    Contact *contact;
                    ICQUserData *data = findContact(m_send.screen.c_str(), NULL, false, contact);
                    if (data && (data->bInvisible == 0)) {
                        data->bInvisible = true;
                        Event e(EventContactStatus, contact);
                        e.process();
                    }
                } else {
                    m_send.msg->setError(err_str);
                    Event e(EventMessageSent, m_send.msg);
                    e.process();
                }
                delete m_send.msg;
            }
            m_send.msg    = NULL;
            m_send.screen = "";
            m_sendTimer->stop();
            send(true);
            break;
        }
    case ICQ_SNACxMSG_SRV_MISSED_MSG: {
            unsigned short mFormat; // missed channel
            string screen;			// screen
            unsigned short wrnLevel;// warning level
            unsigned short nTlv;    // number of tlvs
            TlvList  lTlv;          // all tlvs in message
            unsigned short missed;  // number of missed messages
            unsigned short error;   // error reason
            m_socket->readBuffer >> mFormat;
            screen = m_socket->readBuffer.unpackScreen();
            m_socket->readBuffer >> wrnLevel;
            m_socket->readBuffer >> nTlv;
            for(unsigned short i = 0; i < nTlv; i++) {
                unsigned short num;
                unsigned short size;
                const char*    data;
                m_socket->readBuffer >> num >> size;
                data = m_socket->readBuffer.data(m_socket->readBuffer.readPos());
                Tlv* tlv = new Tlv(num,size,data);
                lTlv = lTlv + tlv;
            }
            m_socket->readBuffer >> missed >> error;
            const char *err_str = NULL;
            switch (error) {
            case 0x00:
                err_str = I18N_NOOP("Invalid message");
                break;
            case 0x01:
                err_str = I18N_NOOP("Message was too large");
                break;
            case 0x02:
                err_str = I18N_NOOP("Message rate exceeded");
                break;
            case 0x03:
                err_str = I18N_NOOP("Sender too evil");
                break;
            case 0x04:
                err_str = I18N_NOOP("We are to evil :(");
                break;
            default:
                err_str = I18N_NOOP("Unknown error");
            }
            log(L_DEBUG, "ICMB error %u (%s) - screen(%s)", error, err_str, screen.c_str());
            break;
        }
    case ICQ_SNACxMSG_BLAMExSRVxACK:
        if ((m_send.id.id_l == seq) && m_send.msg){
            unsigned short oldLevel, newLevel;
            m_socket->readBuffer >> oldLevel >> newLevel;
            WarningMessage *msg = static_cast<WarningMessage*>(m_send.msg);
            msg->setOldLevel(newLevel - oldLevel);
            msg->setNewLevel(newLevel);
            ackMessage(m_send);
        }
        break;
    case ICQ_SNACxMSG_ACK:
        {
            log(L_DEBUG, "Ack message");
            MessageId id;
            m_socket->readBuffer >> id.id_l >> id.id_h;
            m_socket->readBuffer.incReadPos(2);
            string screen = m_socket->readBuffer.unpackScreen();
            bool bAck = false;
            if (m_send.id == id){
                const char *p1 = screen.c_str();
                const char *p2 = m_send.screen.c_str();
                for (; *p1 && *p2; p1++, p2++)
                    if (tolower(*p1) != tolower(*p2))
                        break;
                if ((*p1 == 0) && (*p2 == 0))
                    bAck = true;
            }
            if (bAck){
                if (m_send.msg){
                    if (m_send.msg->type() == MessageCheckInvisible){
                        Contact *contact;
                        ICQUserData *data = findContact(m_send.screen.c_str(), NULL, false, contact);
                        if (data && !(bool)(data->bInvisible)) {
                            data->bInvisible = true;
                            Event e(EventContactStatus, contact);
                            e.process();
                        }
                        delete m_send.msg;
                    }else{
                        Contact *contact;
                        ICQUserData *data = findContact(screen.c_str(), NULL, false, contact);
                        if ((data == NULL) || (data->Status == ICQ_STATUS_OFFLINE)){
                            ackMessage(m_send);
                        }else{
                            replyQueue.push_back(m_send);
                        }
                    }
                }else{
                    replyQueue.push_back(m_send);
                }
            }
            m_send.msg    = NULL;
            m_send.screen = "";
            m_sendTimer->stop();
            send(true);
            break;
        }
    case ICQ_SNACxMSG_AUTOREPLY:{
            MessageId id;
            m_socket->readBuffer >> id.id_l >> id.id_h;
            m_socket->readBuffer.incReadPos(2);
            string screen = m_socket->readBuffer.unpackScreen();
            m_socket->readBuffer.incReadPos(2);
            unsigned short len;
            m_socket->readBuffer.unpack(len);
            m_socket->readBuffer.incReadPos(2);
            plugin p;
            m_socket->readBuffer.unpack((char*)p, sizeof(p));
            m_socket->readBuffer.incReadPos(len - sizeof(plugin) + 2);
            m_socket->readBuffer.unpack(len);
            m_socket->readBuffer.incReadPos(len + 12);
            unsigned short ackFlags, msgFlags;
            m_socket->readBuffer.unpack(ackFlags);
            m_socket->readBuffer.unpack(msgFlags);

            list<SendMsg>::iterator it;
            for (it = replyQueue.begin(); it != replyQueue.end(); ++it){
                SendMsg &s = *it;
                if ((s.id == id) && (s.screen == screen))
                    break;
            }
            if (it == replyQueue.end())
                break;

            unsigned plugin_type = (*it).flags;
            if ((*it).msg){
                string answer;
                m_socket->readBuffer >> answer;
                if (ackMessage((*it).msg, ackFlags, answer.c_str())){
                    ackMessage(*it);
                }else{
                    Event e(EventMessageSent, (*it).msg);
                    e.process();
                    delete (*it).msg;
                }
                replyQueue.erase(it);
                break;
            }

            replyQueue.erase(it);
            Contact *contact;
            ICQUserData *data = findContact(screen.c_str(), NULL, false, contact);

            if (memcmp(p, plugins[PLUGIN_NULL], sizeof(plugin))){
                unsigned plugin_index;
                for (plugin_index = 0; plugin_index < PLUGIN_NULL; plugin_index++){
                    if (memcmp(p, plugins[plugin_index], sizeof(plugin)) == 0)
                        break;
                }
                if (plugin_index == PLUGIN_NULL){
                    string plugin_str;
                    unsigned i;
                    for (i = 0; i < sizeof(plugin); i++){
                        char b[4];
                        sprintf(b, "%02X ", p[i]);
                        plugin_str += b;
                    }
                    log(L_DEBUG, "Unknown plugin sign in reply %s", plugin_str.c_str());
                    break;
                }
                if ((data == NULL) && (plugin_index != PLUGIN_RANDOMxCHAT))
                    break;
                parsePluginPacket(m_socket->readBuffer, plugin_type, data, atol(screen.c_str()), false);
                break;
            }

            if (plugin_type == PLUGIN_AR){
                string answer;
                m_socket->readBuffer >> answer;
                log(L_DEBUG, "Autoreply from %s %s", screen.c_str(), answer.c_str());
                Contact *contact;
                ICQUserData *data = findContact(screen.c_str(), NULL, false, contact);
                if (data && set_str(&data->AutoReply, answer.c_str())){
                    Event e(EventContactChanged, contact);
                    e.process();
                }
            }
示例#2
0
void ICQClient::snac_icmb(unsigned short type, unsigned short)
{
    switch (type){
    case ICQ_SNACxMSG_RIGHTSxGRANTED:
        log(L_DEBUG, "Message rights granted");
        break;
    case ICQ_SNACxMSG_MTN:{
            m_socket->readBuffer.incReadPos(10);
            unsigned long uin = m_socket->readBuffer.unpackUin();
            unsigned short type;
            m_socket->readBuffer >> type;
            bool bType = (type > 1);
            Contact *contact;
            ICQUserData *data = findContact(uin, NULL, false, contact);
            if (data == NULL)
                break;
            if ((bool)(data->bTyping) == bType)
                break;
            data->bTyping = bType;
            Event e(EventContactStatus, contact);
            e.process();
            break;
        }
    case ICQ_SNACxMSG_ERROR:{
            unsigned short error;
            m_socket->readBuffer >> error;
            const char *err_str = I18N_NOOP("Unknown error");
            if (error == 0x0009){
                Contact *contact;
                ICQUserData *data = findContact(m_send.uin, NULL, false, contact);
                if (data){
                    for (list<SendMsg>::iterator it = sendQueue.begin(); it != sendQueue.end();){
                        if ((*it).uin != m_send.uin){
                            ++it;
                            continue;
                        }
                        if ((*it).msg){
                            (*it).flags = 0;
                            ++it;
                            continue;
                        }
                        sendQueue.erase(it);
                        it = sendQueue.begin();
                    }
                    data->bBadClient = true;
                    if (m_send.msg)
                        sendThruServer(m_send.msg, data);
                    m_send.msg = NULL;
                    m_send.uin = 0;
                    m_sendTimer->stop();
                    send(true);
                    break;
                }
            }
            switch (error){
            case 0x0004:
                err_str = I18N_NOOP("User is offline");
                break;
            case 0x000E:
                err_str = I18N_NOOP("Packet was malformed");
                break;
            case 0x0015:
                err_str = I18N_NOOP("List overflow");
                break;
            }
            log(L_DEBUG, "ICMB error %u (%s)", error, err_str);
            if (m_send.msg){
				if (m_send.msg->type() == MessageCheckInvisible){
					bool bInvisible = (error == 0x000E);
					Contact *contact;
					ICQUserData *data = findContact(m_send.uin, NULL, false, contact);
					if (data && ((bool)(data->bInvisible) != bInvisible)){
						data->bInvisible = bInvisible;
						Event e(EventContactStatus, contact);
						e.process();
					}
				}
				m_send.msg->setError(err_str);
				Event e(EventMessageSent, m_send.msg);
				e.process();
                delete m_send.msg;
            }
            m_send.msg = NULL;
            m_send.uin = 0;
            m_sendTimer->stop();
            send(true);
            break;
        }
    case ICQ_SNACxMSG_ACK:
        {
            log(L_DEBUG, "Ack message");
            MessageId id;
            m_socket->readBuffer >> id.id_l >> id.id_h;
            m_socket->readBuffer.incReadPos(2);
            unsigned long uin = m_socket->readBuffer.unpackUin();
            if ((m_send.uin != uin) || !(m_send.id == id))
                log(L_WARN, "Bad ack sequence");
            if (m_send.msg){
                ackMessage();
            }else{
                replyQueue.push_back(m_send);
            }
            m_send.msg = NULL;
            m_send.uin = 0;
            m_sendTimer->stop();
            send(true);
            break;
        }
    case ICQ_SNACxMSG_AUTOREPLY:{
            MessageId id;
            m_socket->readBuffer >> id.id_l >> id.id_h;
            m_socket->readBuffer.incReadPos(2);
            unsigned long uin = m_socket->readBuffer.unpackUin();
            m_socket->readBuffer.incReadPos(2);
            unsigned short len;
            m_socket->readBuffer.unpack(len);
            m_socket->readBuffer.incReadPos(2);
            plugin p;
            m_socket->readBuffer.unpack((char*)p, sizeof(p));
            m_socket->readBuffer.incReadPos(len - sizeof(plugin) + 2);
            m_socket->readBuffer.unpack(len);
            m_socket->readBuffer.incReadPos(len + 0x10);

            if (memcmp(p, plugins[PLUGIN_NULL], sizeof(plugin))){
                unsigned plugin_index;
                for (plugin_index = 0; plugin_index < PLUGIN_NULL; plugin_index++){
                    if (memcmp(p, plugins[plugin_index], sizeof(plugin)) == 0)
                        break;
                }
                if (plugin_index == PLUGIN_NULL){
                    string plugin_str;
                    unsigned i;
                    for (i = 0; i < sizeof(plugin); i++){
                        char b[4];
                        sprintf(b, "%02X ", p[i]);
                        plugin_str += b;
                    }
                    log(L_DEBUG, "Unknown plugin sign in reply %s", plugin_str.c_str());
                    break;
                }
                Contact *contact;
                ICQUserData *data = findContact(uin, NULL, false, contact);
                if ((data == NULL) && (plugin_index != PLUGIN_RANDOMxCHAT))
                    break;

                list<SendMsg>::iterator it;
                for (it = replyQueue.begin(); it != replyQueue.end(); ++it){
                    SendMsg &s = *it;
                    if ((s.id == id) && (s.uin == uin))
                        break;
                }
                if (it == replyQueue.end()){
                    log(L_DEBUG, "No found message for plugin answer (%u)", uin);
                    break;
                }
                unsigned plugin_type = (*it).flags;
                replyQueue.erase(it);
                parsePluginPacket(m_socket->readBuffer, plugin_type, data, uin, false);
                break;
            }

            string answer;
            m_socket->readBuffer >> answer;
            log(L_DEBUG, "Autoreply from %u %s", uin, answer.c_str());
            Contact *contact;
            ICQUserData *data = findContact(uin, NULL, false, contact);
            if (data && set_str(&data->AutoReply, answer.c_str())){
                Event e(EventContactChanged, contact);
                e.process();
            }
            break;
        }
    case ICQ_SNACxMSG_SERVERxMESSAGE:{
            unsigned long timestamp1, timestamp2;
            m_socket->readBuffer >> timestamp1 >> timestamp2;
            unsigned short mFormat;
            m_socket->readBuffer >> mFormat;
            unsigned long uin = m_socket->readBuffer.unpackUin();
            log(L_DEBUG, "Message from %u [%04X]", uin, mFormat);
            unsigned short level, nTLV;
            m_socket->readBuffer >> level >> nTLV;
            switch (mFormat){
            case 0x0001:{
                    TlvList tlv(m_socket->readBuffer);
                    if (!tlv(2)){
                        log(L_WARN, "No found generic message tlv");
                        break;
                    }
                    Buffer m(*tlv(2));
                    TlvList tlv_msg(m);
                    Tlv *m_tlv = tlv_msg(0x101);
                    if (m_tlv == NULL){
                        log(L_WARN, "No found generic message tlv 101");
                        break;
                    }
                    if (m_tlv->Size() <= 4)
                        break;
                    char *m_data = (*m_tlv);
                    unsigned short encoding = (m_data[0] << 8) + m_data[1];
                    m_data += 4;
                    if (encoding == 2){
                        QString text;
                        for (int i = 0; i < m_tlv->Size() - 5; i += 2){
                            unsigned char r1 = *(m_data++);
                            unsigned char r2 = *(m_data++);
                            unsigned short c = (r1 << 8) + r2;
                            text += QChar(c);
                        }
                        Message *msg = new Message(MessageGeneric);
                        msg->setText(text);
                        messageReceived(msg, uin);
                        break;
                    }
                    ICQMessage *msg = new ICQMessage;
                    msg->setServerText(m_data);
                    messageReceived(msg, uin);
                    break;
                }
            case 0x0002:{
                    TlvList tlv(m_socket->readBuffer);
                    if (!tlv(5)){
                        log(L_WARN, "No found ICMB message tlv");
                        break;
                    }
                    Buffer msg(*tlv(5));
                    unsigned short type;
                    msg >> type;
                    switch (type){
                    case 0:
                        parseAdvancedMessage(uin, msg, tlv(3) != NULL, timestamp1, timestamp2);
                        break;
                    case 1:
                        log(L_DEBUG, "Cancel");
                        break;
                    case 2:
                        log(L_DEBUG, "File ack");
                        break;
                    default:
                        log(L_WARN, "Unknown type: %u", type);
                    }
                    break;
                }
            case 0x0004:{
                    TlvList tlv(m_socket->readBuffer);
                    if (!tlv(5)){
                        log(L_WARN, "No found advanced message tlv");
                        break;
                    }
                    Buffer msg(*tlv(5));
                    unsigned long msg_uin;
                    msg >> msg_uin;
                    if (msg_uin == 0){
                        parseAdvancedMessage(uin, msg, tlv(6) != NULL, timestamp1, timestamp2);
                        return;
                    }
                    char type, flags;
                    msg >> type;
                    msg >> flags;
                    string msg_str;
                    msg >> msg_str;
                    Message *m = parseMessage(type, uin, msg_str, msg, 0, 0, timestamp1, timestamp2);
                    if (m)
                        messageReceived(m, uin);
                    break;
                }
            default:
                log(L_WARN, "Unknown message format %04X", mFormat);
            }
            break;
        }
    default:
        log(L_WARN, "Unknown message family type %04X", type);
    }
}