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