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(); } }
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); } }