bool PKCS15DODF::parseData(ByteArray data) { bool result = false; SimpleTLV tlv(data); while (tlv.decodeTLV()) { switch (tlv.getTag()) { case (unsigned int)0xA1 : /* CHOICE 1 : OidDO */ { PKCS15OID oid(tlv.getValue()); SCARD_DEBUG("OID DataObject"); pair<ByteArray, PKCS15OID> newPair(oid.getOID(), oid); mapOID.insert(newPair); } break; default : SCARD_DEBUG("Unknown tlv : t [%X], l [%d], v %s", tlv.getTag(), tlv.getLength(), tlv.getValue().toString()); break; } } SCARD_DEBUG("dataList.size() = %d", mapOID.size()); return result; }
void SecurityBlock::TLVList::set(SecurityBlock::TLV_TYPES type, std::string value) { SecurityBlock::TLV tlv(type, value); erase(tlv); insert(tlv); }
TlvChain& TlvChain::operator=(const Buffer& buffer) { Buffer tmpBuffer = buffer; while ( tmpBuffer.bytesAvailable() > 0 ) { Word type = tmpBuffer.getWord(); Word length = tmpBuffer.getWord(); Tlv tlv( type, tmpBuffer.read(length) ); m_tlvList.insert(type, tlv); } return *this; }
// CliMetaReqOfflineDelete SNAC CliMetaReqOfflineDeleteSNAC::CliMetaReqOfflineDeleteSNAC(DWord uin) : SNAC_ICQ(ICQ_CLI_METAREQ, true) { UnformattedTLV tlv(TLV_TYPE_UIN); tlv.data().setLittleEndian(); tlv.data() << (Word) 0x0008; tlv.data() << uin; tlv.data() << DELETE_OFFLINE_MESSAGES; tlv.data() << (Word) 0x0002; // FIXME: request sequence m_data << tlv.pack(); }
void MetaInfoManager::sendMetaRequest(Word type, Buffer& metadata) { Tlv tlv(0x01); // ENCAPSULATED_METADATA tlv.addLEWord( metadata.size() + 8 ); // data chunk size (tlv size - 2 ) tlv.addLEDWord( d->uin.toUInt() ); // own UIN tlv.addLEWord(type); tlv.addLEWord( ++(d->metaSequence) ); // request sequence number tlv.addData(metadata); SnacBuffer snac(0x15, 0x02); snac.addTlv(tlv); d->socket->write(snac); }
void TLVChain::parseLen(Buffer& b) { Word len; UnformattedTLV* tlv(TLV_TYPE_GENERIC); b >> len; while (len){ tlv = new UnformattedTLV(TLV_TYPE_GENERIC); b.removeFromBegin(); tlv->parse(b); this->addTLV(tlv); len -= (tlv->data().len() + 4); } b.removeFromBegin(); }
string pad256(string& str) { string out = str; int pad = out.length() % 32; if( pad ) { // надо выровнять на 256 бит if( pad>3 ) { out += tlv(0,padding.substr(0,32-3-pad)); } else { if( pad==3 ) out += string("\0\0\0"); else if( pad==2 ) out += string("\0\0"); else out += string("\0"); } } return out; }
void ICQClient::snac_service(unsigned short type, unsigned short) { switch (type){ case ICQ_SNACxSRV_PAUSE: log(L_DEBUG, "Server pause"); m_bNoSend = true; snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_PAUSExACK); m_socket->writeBuffer << ICQ_SNACxFAM_SERVICE << ICQ_SNACxFAM_LOCATION << ICQ_SNACxFAM_BUDDY << ICQ_SNACxFAM_MESSAGE << ICQ_SNACxFAM_BOS << ICQ_SNACxFAM_PING << ICQ_SNACxFAM_LISTS << ICQ_SNACxFAM_VARIOUS << ICQ_SNACxFAM_LOGIN; sendPacket(true); break; case ICQ_SNACxSRV_RESUME: log(L_DEBUG, "Server resume"); m_bNoSend = false; processSendQueue(); break; case ICQ_SNACxSRV_MIGRATE:{ log(L_DEBUG, "Server migrate"); m_bNoSend = true; int i; unsigned short cnt; unsigned short fam[0x17]; m_socket->readBuffer >> cnt; for (i = 0; i < cnt; i++) { m_socket->readBuffer >> fam[i]; } TlvList tlv(m_socket->readBuffer); Tlv *tlv_adr = tlv(0x05); Tlv *tlv_cookie = tlv(0x06); for (; i >= 0; i--) { setServiceSocket(tlv_adr,tlv_cookie,fam[i]); } break; } case ICQ_SNACxSRV_RATExINFO: case ICQ_SNACxSRV_RATExCHANGE:{ const char *msg_text = NULL; unsigned short msg_code; unsigned short class_id; unsigned long window_size; unsigned long clear_level; unsigned long alert_level; unsigned long limit_level; unsigned long discon_level; unsigned long current_level; unsigned long max_level; unsigned long last_level; char current_state; m_socket->readBuffer >> msg_code >> class_id >> window_size >> clear_level >> alert_level >> limit_level >> discon_level >> current_level >> max_level >> last_level >> current_state; if (type == ICQ_SNACxSRV_RATExCHANGE){ switch (msg_code) { case 0x0001: msg_text = "Rate limits parameters changed"; break; case 0x0002: msg_text = "Rate limits warning"; break; case 0x0003: msg_text = "Rate limit hit"; break; case 0x0004: msg_text = "Rate limit clear"; break; default: msg_text = "Unknown"; } log(L_DEBUG, msg_text); } log(L_DEBUG, "ws: %04X, cl %04X, al %04X, ll %04X, dl: %04X, cur %04X, ml %04X", window_size,clear_level,alert_level,limit_level,discon_level, current_level,max_level); m_winSize = window_size; m_maxLevel = max_level; m_minLevel = alert_level; m_curLevel = current_level; m_lastSend = QDateTime::currentDateTime(); processSendQueue(); } if (type != ICQ_SNACxSRV_RATExINFO) break; snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_RATExACK); m_socket->writeBuffer << 0x00010002L << 0x00030004L << 0x0005; sendPacket(true); snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_GETxUSERxINFO); sendPacket(true); listsRequest(); locationRequest(); buddyRequest(); icmbRequest(); bosRequest(); break; case ICQ_SNACxSRV_MOTD: break; case ICQ_SNACxSRV_ACKxIMxICQ: snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_REQxRATExINFO); sendPacket(true); break; case ICQ_SNACxSRV_NAMExINFO:{ string screen = m_socket->readBuffer.unpackScreen(); if (screen.length() == 0){ char n; m_socket->readBuffer >> n; m_socket->readBuffer.incReadPos(n); screen = m_socket->readBuffer.unpackScreen(); } if ((unsigned)atol(screen.c_str()) != data.owner.Uin.value){ log(L_WARN, "No my name info (%s)", screen.c_str()); break; } m_socket->readBuffer.incReadPos(4); TlvList tlv(m_socket->readBuffer); Tlv *tlvIP = tlv(0x000A); if (tlvIP) set_ip(&data.owner.IP, htonl((unsigned long)(*tlvIP))); log(L_DEBUG, "Name info"); break; } case ICQ_SNACxSRV_SERVICExRESP:{ TlvList tlv(m_socket->readBuffer); Tlv *tlv_id = tlv(0x0D); if (!tlv_id){ log(L_WARN, "No service id in response"); break; } Tlv *tlv_adr = tlv(0x05); Tlv *tlv_cookie = tlv(0x06); setServiceSocket(tlv_adr,tlv_cookie,(unsigned short)(*tlv_id)); break; } case ICQ_SNACxSRV_READYxSERVER: log(L_DEBUG, "Server ready"); snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_IMxICQ); if (m_bAIM){ m_socket->writeBuffer << 0x00010003L << 0x00130003L << 0x00020001L << 0x00030001L << 0x00040001L << 0x00060001L << 0x00080001L << 0x00090001L << 0x000A0001L << 0x000B0001L; }else{ m_socket->writeBuffer << 0x00010004L << 0x00130004L << 0x00020001L << 0x00030001L << 0x00150001L << 0x00040001L << 0x00060001L << 0x00090001L << 0x000A0001L << 0x000B0001L; } sendPacket(true); break; case ICQ_SNACxSRV_ERROR: break; case ICQ_SNACxSRV_EVIL:{ unsigned short level; m_socket->readBuffer.unpack(level); string from = m_socket->readBuffer.unpackScreen(); data.owner.WarningLevel.value = level; QString f; f = from.c_str(); if (f.isEmpty()) f = i18n("anonymous"); clientErrorData d; d.client = this; d.code = 0; d.err_str = I18N_NOOP("You've been warned by %1"); d.args = strdup(f.utf8()); d.flags = ERR_INFO; d.options = NULL; d.id = CmdShowWarning; Event e(EventClientError, &d); e.process(); free(d.args); break; } default: log(L_WARN, "Unknown service family type %04X", type); }
void ICQClient::chn_close() { unsigned errorCode = 0; TlvList tlv(m_socket->readBuffer); Tlv *tlv_error = tlv(8); if (tlv_error){ unsigned short err = *tlv_error; string errString; switch (err){ case ICQ_LOGIN_ERRxIP_RATE_LIMIT: case ICQ_LOGIN_ERRxIP_RATE_LIMIT1: errString = I18N_NOOP("Too many clients from same IP"); m_reconnect = NO_RECONNECT; break; case ICQ_LOGIN_ERRxRATE_LIMIT: errString = I18N_NOOP("Rate limit"); m_reconnect = NO_RECONNECT; break; case ICQ_LOGIN_ERRxBAD_PASSWD: case ICQ_LOGIN_ERRxBAD_PASSWD1: errString = I18N_NOOP("Invalid UIN and password combination"); m_reconnect = NO_RECONNECT; errorCode = AuthError; break; case ICQ_LOGIN_ERRxNOT_EXISTS: case ICQ_LOGIN_ERRxNOT_EXISTS1: errString = I18N_NOOP("Non-existant UIN"); m_reconnect = NO_RECONNECT; errorCode = AuthError; break; case 0: break; default: errString = "Unknown error "; errString += number(err); } if (err){ log(L_ERROR, "%s", errString.c_str()); m_socket->error_state(errString.c_str(), errorCode); return; } } tlv_error = tlv(9); if (tlv_error){ string errString; unsigned short err = *tlv_error; switch (err){ case 0x1:{ errString = I18N_NOOP("Youur UIN is being used from another location"); m_reconnect = NO_RECONNECT; break; } case 0: break; default: errString = "Unknown run-time error "; errString += number(err); } if (err){ log(L_ERROR, "%s", errString.c_str()); m_socket->error_state(errString.c_str()); return; } } Tlv *tlv_host = tlv(5); Tlv *tlv_cookie = tlv(6); if ((tlv_host == NULL) || (tlv_cookie == NULL)){ m_socket->error_state(I18N_NOOP("Close packet from server")); return; } char *host = *tlv_host; char *port = strchr(host, ':'); if (port == NULL){ log(L_ERROR, "Bad host address %s", host); m_socket->error_state(I18N_NOOP("Bad host address")); return; } *port = 0; port++; m_socket->close(); m_socket->connect(host, (unsigned short)atol(port), this); m_cookie.init(0); m_cookie.pack(*tlv_cookie, tlv_cookie->Size()); }
void ICQClient::snac_service(unsigned short type, unsigned short) { switch (type){ case ICQ_SNACxSRV_RATExCHANGE: log(L_DEBUG, "Rate change"); if (m_nSendTimeout < 200){ m_nSendTimeout = m_nSendTimeout + 2; if (m_sendTimer->isActive()){ m_sendTimer->stop(); m_sendTimer->start(m_nSendTimeout * 500); } } break; case ICQ_SNACxSRV_RATExINFO: log(L_DEBUG, "Rate info"); snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_RATExACK); m_socket->writeBuffer << 0x00010002L << 0x00030004L << 0x0005; sendPacket(); snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_GETxUSERxINFO); sendPacket(); listsRequest(); locationRequest(); buddyRequest(); icmbRequest(); bosRequest(); break; case ICQ_SNACxSRV_MOTD: log(L_DEBUG, "Motd"); snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_REQxRATExINFO); sendPacket(); break; case ICQ_SNACxSRV_ACKxIMxICQ: log(L_DEBUG, "Ack im icq"); break; case ICQ_SNACxSRV_NAMExINFO:{ string screen = m_socket->readBuffer.unpackScreen(); if (screen.length() == 0){ char n; m_socket->readBuffer >> n; m_socket->readBuffer.incReadPos(n); screen = m_socket->readBuffer.unpackScreen(); } if (atol(screen.c_str()) != data.owner.Uin){ log(L_WARN, "No my name info (%s)", screen.c_str()); break; } m_socket->readBuffer.incReadPos(4); TlvList tlv(m_socket->readBuffer); Tlv *tlvIP = tlv(0x000A); if (tlvIP) set_ip(&data.owner.IP, htonl((unsigned long)(*tlvIP))); log(L_DEBUG, "Name info"); break; } case ICQ_SNACxSRV_READYxSERVER: log(L_DEBUG, "Server ready"); snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_IMxICQ); m_socket->writeBuffer << 0x00010003L << 0x00130002L << 0x00020001L << 0x00030001L << 0x00150001L << 0x00040001L << 0x00060001L << 0x00090001L << 0x000a0001L << 0x000b0001L; sendPacket(); break; case ICQ_SNACxSRV_ERROR: break; default: log(L_WARN, "Unknown service family type %04X", type); }
void FrustumCullingTask::FrustrumCull(CCamera* cam, BaseState* state) { Renderer* renderer = Renderer::getInstance(); // Points of the AABB in world space std::vector<Vector3> verts(8); Vector3 origin, scaledHalfVec, rotatedX, rotatedY, rotatedZ; Quaternion rot; std::vector<CRenderer*>* deferredQueue; std::vector<CRenderer*>* forwardQueue; std::vector<CRenderer*>* diffuseQueue; std::vector<CRenderer*>* fontQueue; std::vector<CLight*>* lightQueue; //the only thread sensitive area should be here { ThreadUtils::ThreadLockVisitor tlv(4); deferredQueue = &renderer->mMapDeferredQueues[cam]; forwardQueue = &renderer->mMapForwardQueues[cam]; diffuseQueue = &renderer->mMapDiffuseQueues[cam]; fontQueue = &renderer->mMapFontQueues[cam]; lightQueue = &renderer->mMapLightQueues[cam]; } const std::list<CRenderer*>* listRenderers = state->GetListOfComponentsOfType<CRenderer>(); if (listRenderers) { // Get vertices in world space for (auto& iter : *listRenderers) { if (!iter->isEnabled() || !iter->mMesh.Valid()) continue; origin = iter->GetMesh()->GetOrigin(); rot = iter->gameObject->transform->GetRotationQuaternion(); scaledHalfVec = iter->GetMesh()->GetAABB().maxPoint - origin; scaledHalfVec *= iter->gameObject->transform->scale; origin *= iter->gameObject->transform->scale; rotatedX = rot.RotatedVector(Vector3::cXAxis * scaledHalfVec.x); rotatedY = rot.RotatedVector(Vector3::cYAxis * scaledHalfVec.y); rotatedZ = rot.RotatedVector(Vector3::cZAxis * scaledHalfVec.z); rot.RotateVector(&origin); origin += iter->gameObject->transform->GetGlobalPosition(); // + + + verts[0] = origin + rotatedX + rotatedY + rotatedZ; // + + - verts[1] = origin + rotatedX + rotatedY - rotatedZ; // + - + verts[2] = origin + rotatedX - rotatedY + rotatedZ; // - + + verts[3] = origin - rotatedX + rotatedY + rotatedZ; // - - + verts[4] = origin - rotatedX - rotatedY + rotatedZ; // - + - verts[5] = origin - rotatedX + rotatedY - rotatedZ; // + - - verts[6] = origin + rotatedX - rotatedY - rotatedZ; // - - - verts[7] = origin - rotatedX - rotatedY - rotatedZ; // AABB cull check if (cam->CullAABB(verts)) { if (iter->mymeta() == CMeshRenderer::getmeta() || iter->mymeta() == CSkinMeshRenderer::getmeta()) deferredQueue->push_back(iter); else if (iter->mymeta() == CForwardRenderer::getmeta()) forwardQueue->push_back(iter); else if (iter->mymeta() == CDiffuseRenderer::getmeta()) diffuseQueue->push_back(iter); else if (iter->mymeta() == CFontRenderer::getmeta()) fontQueue->push_back(iter); } } } const std::list<CLight*>* listLight = state->GetListOfComponentsOfType<CLight>(); if (listLight) { // Iterate through all Lights for (auto& light : *listLight) { if (!light->isEnabled()) continue; if (light->mLightType == CLight::DIRECTIONAL) { lightQueue->push_back(light); continue; } Vector3 lightPos = light->gameObject->transform->GetGlobalPosition(); if (cam->CullSphere(lightPos, light->GetRange())) lightQueue->push_back(light); } } }
void ICQClient::snac_service(unsigned short type, unsigned short) { switch (type){ case ICQ_SNACxSRV_PAUSE: log(L_DEBUG, "Server pause"); /* we now shouldn't send any packets to the server ... but I don't know how to solve this. Valdimir do you have an idea? */ /* m_bDontSendPakets = true; */ snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_PAUSExACK); m_socket->writeBuffer << ICQ_SNACxFAM_SERVICE << ICQ_SNACxFAM_LOCATION << ICQ_SNACxFAM_BUDDY << ICQ_SNACxFAM_MESSAGE << ICQ_SNACxFAM_BOS << ICQ_SNACxFAM_PING << ICQ_SNACxFAM_LISTS << ICQ_SNACxFAM_VARIOUS << ICQ_SNACxFAM_LOGIN; sendPacket(); break; case ICQ_SNACxSRV_RESUME: /* m_bDontSendPakets = true; emit canSendPakets(); */ break; case ICQ_SNACxSRV_MIGRATE:{ int i; unsigned short cnt; unsigned short fam[0x17]; m_socket->readBuffer >> cnt; for (i = 0; i < cnt; i++) { m_socket->readBuffer >> fam[i]; } TlvList tlv(m_socket->readBuffer); Tlv *tlv_adr = tlv(0x05); Tlv *tlv_cookie = tlv(0x06); for (; i >= 0; i--) { setServiceSocket(tlv_adr,tlv_cookie,fam[i]); } /* m_bDontSendPakets = true; emit canSendPakets(); */ break; } case ICQ_SNACxSRV_RATExCHANGE: log(L_DEBUG, "Rate change"); if (m_nSendTimeout < 200){ m_nSendTimeout = m_nSendTimeout + 2; if (m_sendTimer->isActive()){ m_sendTimer->stop(); m_sendTimer->start(m_nSendTimeout * 500); } } break; case ICQ_SNACxSRV_RATExINFO: snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_RATExACK); m_socket->writeBuffer << 0x00010002L << 0x00030004L << 0x0005; sendPacket(); snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_GETxUSERxINFO); sendPacket(); listsRequest(); locationRequest(); buddyRequest(); icmbRequest(); bosRequest(); break; case ICQ_SNACxSRV_MOTD: break; case ICQ_SNACxSRV_ACKxIMxICQ: snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_REQxRATExINFO); sendPacket(); break; case ICQ_SNACxSRV_NAMExINFO:{ string screen = m_socket->readBuffer.unpackScreen(); if (screen.length() == 0){ char n; m_socket->readBuffer >> n; m_socket->readBuffer.incReadPos(n); screen = m_socket->readBuffer.unpackScreen(); } if ((unsigned)atol(screen.c_str()) != data.owner.Uin.value){ log(L_WARN, "No my name info (%s)", screen.c_str()); break; } m_socket->readBuffer.incReadPos(4); TlvList tlv(m_socket->readBuffer); Tlv *tlvIP = tlv(0x000A); if (tlvIP) set_ip(&data.owner.IP, htonl((unsigned long)(*tlvIP))); log(L_DEBUG, "Name info"); break; } case ICQ_SNACxSRV_SERVICExRESP:{ TlvList tlv(m_socket->readBuffer); Tlv *tlv_id = tlv(0x0D); if (!tlv_id){ log(L_WARN, "No service id in response"); break; } Tlv *tlv_adr = tlv(0x05); Tlv *tlv_cookie = tlv(0x06); setServiceSocket(tlv_adr,tlv_cookie,(unsigned short)(*tlv_id)); break; } case ICQ_SNACxSRV_READYxSERVER: log(L_DEBUG, "Server ready"); snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_IMxICQ); if (m_bAIM){ m_socket->writeBuffer << 0x00010003L << 0x00130003L << 0x00020001L << 0x00030001L << 0x00040001L << 0x00060001L << 0x00080001L << 0x00090001L << 0x000A0001L << 0x000B0001L; }else{ m_socket->writeBuffer << 0x00010004L << 0x00130004L << 0x00020001L << 0x00030001L << 0x00150001L << 0x00040001L << 0x00060001L << 0x00090001L << 0x000A0001L << 0x000B0001L; } sendPacket(); break; case ICQ_SNACxSRV_ERROR: break; case ICQ_SNACxSRV_EVIL:{ unsigned short level; m_socket->readBuffer.unpack(level); string from = m_socket->readBuffer.unpackScreen(); data.owner.WarningLevel.value = level; QString f; f = from.c_str(); if (f.isEmpty()) f = i18n("anonymous"); clientErrorData d; d.client = this; d.code = 0; d.err_str = I18N_NOOP("You've been warned by %1"); d.args = strdup(f.utf8()); Event e(EventClientError, &d); e.process(); free(d.args); break; } default: log(L_WARN, "Unknown service family type %04X", type); }
void ICQClient::snac_service(unsigned short type, unsigned short) { switch (type){ case ICQ_SNACxSRV_RATExCHANGE: log(L_DEBUG, "Rate change"); if (m_nSendTimeout < 200){ m_nSendTimeout = m_nSendTimeout + 2; if (m_sendTimer->isActive()){ m_sendTimer->stop(); m_sendTimer->start(m_nSendTimeout * 500); } } break; case ICQ_SNACxSRV_RATExINFO: snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_RATExACK); m_socket->writeBuffer << 0x00010002L << 0x00030004L << 0x0005; sendPacket(); snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_GETxUSERxINFO); sendPacket(); listsRequest(); locationRequest(); buddyRequest(); icmbRequest(); bosRequest(); break; case ICQ_SNACxSRV_MOTD: break; case ICQ_SNACxSRV_ACKxIMxICQ: snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_REQxRATExINFO); sendPacket(); break; case ICQ_SNACxSRV_NAMExINFO:{ string screen = m_socket->readBuffer.unpackScreen(); if (screen.length() == 0){ char n; m_socket->readBuffer >> n; m_socket->readBuffer.incReadPos(n); screen = m_socket->readBuffer.unpackScreen(); } if ((unsigned)atol(screen.c_str()) != data.owner.Uin){ log(L_WARN, "No my name info (%s)", screen.c_str()); break; } m_socket->readBuffer.incReadPos(4); TlvList tlv(m_socket->readBuffer); Tlv *tlvIP = tlv(0x000A); if (tlvIP) set_ip(&data.owner.IP, htonl((unsigned long)(*tlvIP))); log(L_DEBUG, "Name info"); break; } case ICQ_SNACxSRV_SERVICExRESP:{ TlvList tlv(m_socket->readBuffer); Tlv *tlv_id = tlv(0x0D); if (tlv_id == NULL){ log(L_WARN, "No service id in response"); break; } ServiceSocket *s = NULL; for (list<ServiceSocket*>::iterator it = m_services.begin(); it != m_services.end(); ++it){ if ((*it)->id() == (unsigned short)(*tlv_id)){ s = *it; break; } } if (s == NULL){ log(L_WARN, "Service not found"); break; } Tlv *tlv_addr = tlv(0x05); if (tlv_addr == NULL){ s->error_state("No address for service", 0); break; } Tlv *tlv_cookie = tlv(0x06); if (tlv_cookie == NULL){ s->error_state("No cookie for service", 0); break; } unsigned short port = getPort(); string addr; addr = (const char*)(*tlv_addr); char *p = (char*)strchr(addr.c_str(), ':'); if (p){ *p = 0; port = (unsigned short)atol(p + 1); } s->connect(addr.c_str(), port, *tlv_cookie, tlv_cookie->Size()); break; } case ICQ_SNACxSRV_READYxSERVER: log(L_DEBUG, "Server ready"); snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_IMxICQ); if (m_bAIM){ m_socket->writeBuffer << 0x00010003L << 0x00130003L << 0x00020001L << 0x00030001L << 0x00040001L << 0x00060001L << 0x00080001L << 0x00090001L << 0x000A0001L << 0x000B0001L; }else{ m_socket->writeBuffer << 0x00010004L << 0x00130004L << 0x00020001L << 0x00030001L << 0x00150001L << 0x00040001L << 0x00060001L << 0x00090001L << 0x000A0001L << 0x000B0001L; } sendPacket(); break; case ICQ_SNACxSRV_ERROR: break; case ICQ_SNACxSRV_EVIL:{ unsigned short level; m_socket->readBuffer.unpack(level); string from = m_socket->readBuffer.unpackScreen(); data.owner.WarningLevel = level; QString f; f = from.c_str(); if (f.isEmpty()) f = i18n("anonymous"); clientErrorData d; d.client = this; d.code = 0; d.err_str = I18N_NOOP("You've been warned by %1"); d.args = strdup(f.utf8()); Event e(EventClientError, &d); e.process(); free(d.args); break; } default: log(L_WARN, "Unknown service family type %04X", type); }
void ICQClient::chn_close() { unsigned errorCode = 0; TlvList tlv(m_socket->readBuffer); Tlv *tlv_error = tlv(8); if (tlv_error){ unsigned short err = *tlv_error; string errString; switch (err){ case ICQ_LOGIN_ERRxOLDCLIENT1: case ICQ_LOGIN_ERRxOLDCLIENT2: errString = I18N_NOOP("This client is outdated"); m_reconnect = NO_RECONNECT; break; case ICQ_LOGIN_ERRxIP_RATE_LIMIT1: case ICQ_LOGIN_ERRxIP_RATE_LIMIT2: errString = I18N_NOOP("Too many clients from same IP"); m_reconnect = NO_RECONNECT; break; case ICQ_LOGIN_ERRxRATE_LIMIT1: case ICQ_LOGIN_ERRxRATE_LIMIT2: errString = I18N_NOOP("Rate limit"); m_reconnect = NO_RECONNECT; break; case ICQ_LOGIN_ERRxBAD_PASSWD1: case ICQ_LOGIN_ERRxBAD_PASSWD2: case ICQ_LOGIN_ERRxBAD_PASSWD3: errString = I18N_NOOP("Invalid UIN and password combination"); m_reconnect = NO_RECONNECT; errorCode = AuthError; break; case ICQ_LOGIN_ERRxNOT_EXISTS1: case ICQ_LOGIN_ERRxNOT_EXISTS2: errString = I18N_NOOP("Non-existant UIN"); m_reconnect = NO_RECONNECT; errorCode = AuthError; break; case ICQ_LOGIN_ERRxBAD_LOGIN: errString = I18N_NOOP("Bad login procedure"); m_reconnect = NO_RECONNECT; break; case ICQ_LOGIN_ERRxUNAVAILABLE1: case ICQ_LOGIN_ERRxUNAVAILABLE2: case ICQ_LOGIN_ERRxUNAVAILABLE3: case ICQ_LOGIN_ERRxUNAVAILABLE4: case ICQ_LOGIN_ERRxUNAVAILABLE5: case ICQ_LOGIN_ERRxUNAVAILABLE6: case ICQ_LOGIN_ERRxUNAVAILABLE7: case ICQ_LOGIN_ERRxUNAVAILABLE8: errString = I18N_NOOP("Service temporarly unavailable"); m_reconnect = NO_RECONNECT; break; case ICQ_LOGIN_ERRxINVALID_ID: errString = I18N_NOOP("Invalid SecureID"); m_reconnect = NO_RECONNECT; break; case ICQ_LOGIN_ERRxTOO_YOUNG: errString = I18N_NOOP("Too young!"); m_reconnect = NO_RECONNECT; break; case ICQ_LOGIN_ERRxSUSPENDED1: errString = I18N_NOOP("UIN was suspended"); m_reconnect = NO_RECONNECT; break; case ICQ_LOGIN_ERRxCANT_REGISTER: errString = I18N_NOOP("Can't login to ICQ network - Please try again later"); m_reconnect = NO_RECONNECT; break; case 0: break; default: errString = "Unknown error "; errString += number(err); } if (err){ log(L_ERROR, "%s", errString.c_str()); m_socket->error_state(errString.c_str(), errorCode); return; } } tlv_error = tlv(9); if (tlv_error){ string errString; unsigned short err = *tlv_error; switch (err){ case 0x1:{ errString = I18N_NOOP("Youur UIN is being used from another location"); m_reconnect = NO_RECONNECT; break; } case 0: break; default: errString = "Unknown run-time error "; errString += number(err); } if (err){ log(L_ERROR, "%s", errString.c_str()); m_socket->error_state(errString.c_str()); return; } } Tlv *tlv_host = tlv(5); Tlv *tlv_cookie = tlv(6); if ((tlv_host == NULL) || (tlv_cookie == NULL)){ m_socket->error_state(I18N_NOOP("Close packet from server")); return; } char *host = *tlv_host; char *port = strchr(host, ':'); if (port == NULL){ log(L_ERROR, "Bad host address %s", host); m_socket->error_state(I18N_NOOP("Bad host address")); return; } *port = 0; port++; m_socket->close(); m_socket->connect(host, (unsigned short)atol(port), this); m_cookie.init(0); m_cookie.pack(*tlv_cookie, tlv_cookie->Size()); }
void ICQClient::snac_login(unsigned short type, unsigned short) { unsigned long newUin; switch (type){ case ICQ_SNACxLOGIN_ERROR: if (data.owner.Uin.value){ m_reconnect = NO_RECONNECT; m_socket->error_state(I18N_NOOP("Login error"), AuthError); break; } // in the process of registering; // it seems that we need to request bot protection picture; // reconnecting to send the request. log(L_DEBUG, "Verification required, reconnecting"); m_bVerifying = true; m_socket->close(); m_socket->connect(getServer(), getPort(), this); break; case ICQ_SNACxLOGIN_REGISTER: if (data.owner.Uin.value){ m_socket->error_state(I18N_NOOP("Registered in no register state")); break; } m_socket->readBuffer.incReadPos(0x2E); m_socket->readBuffer.unpack(newUin); log(L_DEBUG, "Register %lu %08lX", newUin, newUin); setUin(newUin); setState(Connecting); m_socket->connect(getServer(), getPort(), this); break; case ICQ_SNACxLOGIN_AUTHxKEYxRESPONSE: log(L_DEBUG, "Sending MD5 key"); if (data.owner.Screen.ptr || data.owner.Uin.value){ string md5_key; m_socket->readBuffer.unpackStr(md5_key); snac(ICQ_SNACxFAM_LOGIN, ICQ_SNACxLOGIN_MD5xLOGIN, false, false); if (data.owner.Uin.value){ char uin[20]; sprintf(uin, "%lu", data.owner.Uin.value); m_socket->writeBuffer.tlv(0x0001, uin); }else{ m_socket->writeBuffer.tlv(0x0001, data.owner.Screen.ptr); } string md = md5_key; md += getContacts()->fromUnicode(NULL, getPassword()); md += "AOL Instant Messenger (SM)"; md = md5(md.c_str()); m_socket->writeBuffer.tlv(0x0025, md.c_str(), md.length()); if (data.owner.Uin.value){ m_socket->writeBuffer.tlv(0x0003, "ICQ Inc. - Product of ICQ (TM).2003b.5.56.1.3916.85"); m_socket->writeBuffer.tlv(0x0016, 0x010A); m_socket->writeBuffer.tlv(0x0017, 0x0002); m_socket->writeBuffer.tlv(0x0018, 0x0038); m_socket->writeBuffer.tlv(0x0019, 0x0001); m_socket->writeBuffer.tlv(0x001A, 0x0F4C); m_socket->writeBuffer.tlv(0x0014, 0x00000055L); m_socket->writeBuffer.tlv(0x000f, "en"); m_socket->writeBuffer.tlv(0x000e, "us"); }else{ m_socket->writeBuffer.tlv(0x0003, "AOL Instant Messenger, version 5.1.3036/WIN32"); m_socket->writeBuffer.tlv(0x0016, (unsigned short)0x0109); m_socket->writeBuffer.tlv(0x0017, (unsigned short)0x0005); m_socket->writeBuffer.tlv(0x0018, (unsigned short)0x0001); m_socket->writeBuffer.tlv(0x0019, (unsigned short)0x0000); m_socket->writeBuffer.tlv(0x001A, (unsigned short)0x0BDC); m_socket->writeBuffer.tlv(0x0014, 0x000000D2L); m_socket->writeBuffer.tlv(0x000F, "en"); m_socket->writeBuffer.tlv(0x000E, "us"); m_socket->writeBuffer.tlv(0x004A, "\x01"); } sendPacket(true); } break; case ICQ_SNACxLOGIN_LOGINxREPLY: chn_close(); break; case ICQ_SNACxLOGIN_REGISTERxSEND_IMG: { m_bVerifying = false; TlvList tlv(m_socket->readBuffer); // currently there are 2 TLVs in SNAC(17,0D): // type = 1: the value contains the mime type of the image (image/jpeg); ignored // type = 2: the value contains the image itself in the binary form Tlv* tlvImage = tlv(2); if (!tlvImage) break; log(L_DEBUG, "Image length: %d bytes", tlvImage->Size()); uchar* buf = new uchar[tlvImage->Size()]; memcpy(buf, *tlvImage, tlvImage->Size()); QPixmap pict; if (!pict.loadFromData(buf, tlvImage->Size())) { delete[] buf; break; } delete[] buf; log(L_DEBUG, "Received verification image"); VerifyDlg verdlg(qApp->activeWindow(), pict); if (verdlg.exec() == QDialog::Accepted) // what to do if the user has cancelled the dialog? { QString verifyStr = verdlg.getVerifyString(); log(L_DEBUG, "User input: %s", verifyStr.latin1()); snac(ICQ_SNACxFAM_LOGIN, ICQ_SNACxLOGIN_REGISTERxREQ); Buffer msg; msg << 0x00000000L << 0x28000300L << 0x00000000L << 0x00000000L << 0x94680000L << 0x94680000L << 0x00000000L << 0x00000000L << 0x00000000L << 0x00000000L; string pswd = getContacts()->fromUnicode(NULL, getPassword()); unsigned short len = (unsigned short)(pswd.length() + 1); msg.pack(len); msg.pack(pswd.c_str(), len); msg << 0x94680000L << 0x00000602L; m_socket->writeBuffer.tlv(0x0001, msg); m_socket->writeBuffer.tlv(0x0009, verifyStr.latin1(), verifyStr.length()); sendPacket(true); } break; } default: log(L_WARN, "Unknown login family type %04X", type); } }
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); } }
void ICQClient::snac_various(unsigned short type, unsigned short) { switch (type){ case ICQ_SNACxVAR_DATA:{ TlvList tlv(readBuffer); if (tlv(0x0001) == NULL){ log(L_WARN, "Bad server response"); break; } Buffer msg(*tlv(1)); unsigned short len, nType, nId; unsigned long own_uin; msg >> len >> own_uin >> nType >> nId; switch (nType){ case ICQ_SRVxEND_OFFLINE_MSG: log(L_DEBUG, "End offline messages"); serverRequest(ICQ_SRVxREQ_ACK_OFFLINE_MSG); sendServerRequest(); break; case ICQ_SRVxOFFLINE_MSG:{ log(L_DEBUG, "Offline message"); unsigned long uin; char type, flag; struct tm sendTM; memset(&sendTM, 0, sizeof(sendTM)); string message; unsigned short year; char month, day, hours, min; msg >> uin >> year >> month >> day >> hours >> min >> type >> flag; msg >> message; uin = htonl(uin); year = htons(year); sendTM.tm_year = year-1900; sendTM.tm_mon = month-1; sendTM.tm_mday = day; sendTM.tm_hour = hours; sendTM.tm_min = min; sendTM.tm_sec = 0; time_t send_time = mktime(&sendTM); log(L_DEBUG, "Offline message %u [%08lX] %02X %02X %s", uin, uin, type & 0xFF, flag & 0xFF, message.c_str()); ICQMessage *m = parseMessage(type, uin, message, msg, 0, 0, 0, 0); if (m){ m->Time = (unsigned long)send_time; messageReceived(m); } break; } case ICQ_SRVxANSWER_MORE:{ unsigned short nSubtype; char nResult; msg >> nSubtype >> nResult; log(L_DEBUG, "Server answer %02X %04X", nResult & 0xFF, nSubtype); if ((nResult == 0x32) || (nResult == 0x14) || (nResult == 0x1E)){ ICQEvent *e = findVarEvent(htons(nId)); if (e == NULL){ log(L_WARN, "Various event ID %04X not found (%X)", nId, nResult); break; } e->failAnswer(this); varEvents.remove(e); delete e; break; } ICQEvent *e = findVarEvent(htons(nId)); if (e == NULL){ log(L_WARN, "Various event ID %04X not found (%X)", nId, nResult); break; } bool nDelete = e->processAnswer(this, msg, nSubtype); if (nDelete){ log(L_DEBUG, "Delete event"); varEvents.remove(e); delete e; } break; } default: log(L_WARN, "Unknown SNAC(15,03) response type %04X", nType); } break; } default: log(L_WARN, "Unknown various family type %04X", type); } }
string tlv(int t, int v) { string s; u_int l=(v<=0xFF)?1:((v<=0xFFFF)?2:((v<=0xFFFFFF)?3:4)); s.assign((char*)&v,l); return tlv(t,s); }
string tlv(int t, const char* v) { return tlv(t, string(v)); }
void ICQClient::snac_service(unsigned short type, unsigned short) { switch (type){ case ICQ_SNACxSRV_RATExCHANGE: break; case ICQ_SNACxSRV_RATExINFO: log(L_DEBUG, "Rate info"); snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_RATExACK); writeBuffer << 0x00010002L << 0x00030004L << 0x0005; sendPacket(); snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_GETxUSERxINFO); sendPacket(); listsRequest(); locationRequest(); buddyRequest(); messageRequest(); bosRequest(); break; case ICQ_SNACxSRV_MOTD: log(L_DEBUG, "Motd"); snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_REQxRATExINFO); sendPacket(); break; case ICQ_SNACxSRV_ACKxIMxICQ: log(L_DEBUG, "Ack im icq"); break; case ICQ_SNACxSRV_NAMExINFO:{ unsigned long uin = readBuffer.unpackUin(); if (uin == 0){ char n; readBuffer >> n; readBuffer.incReadPos(n); uin = readBuffer.unpackUin(); } if (uin != Uin()){ log(L_WARN, "No my name info (%lu)", uin); break; } readBuffer.incReadPos(4); TlvList tlv(readBuffer); Tlv *tlvIP = tlv(0x000A); if (tlvIP) RealIP = htonl((unsigned long)(*tlvIP)); log(L_DEBUG, "Name info"); bool bSend = true; if (needPhonebookUpdate){ sendInfoUpdate(); needPhonebookUpdate = false; bSend = false; } if (needPhoneStatusUpdate){ sendPhoneStatus(); needPhoneStatusUpdate = false; bSend = false; } break; } case ICQ_SNACxSRV_READYxSERVER: log(L_DEBUG, "Server ready"); snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_IMxICQ); writeBuffer << 0x00010003L; writeBuffer << 0x00130002L; writeBuffer << 0x00020001L; writeBuffer << 0x00030001L; writeBuffer << 0x00150001L; writeBuffer << 0x00040001L; writeBuffer << 0x00060001L; writeBuffer << 0x00090001L; writeBuffer << 0x000a0001L; writeBuffer << 0x000b0001L; sendPacket(); break; default: log(L_WARN, "Unknown service family type %04X", type); }
void ICQClient::snac_service(unsigned short type, unsigned short) { switch (type){ case ICQ_SNACxSRV_RATExCHANGE: log(L_DEBUG, "Rate change"); if (m_nSendTimeout < 200){ m_nSendTimeout = m_nSendTimeout + 2; if (m_sendTimer->isActive()){ m_sendTimer->stop(); m_sendTimer->start(m_nSendTimeout * 500); } } break; case ICQ_SNACxSRV_RATExINFO: snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_RATExACK); m_socket->writeBuffer << 0x00010002L << 0x00030004L << 0x0005; sendPacket(); snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_GETxUSERxINFO); sendPacket(); listsRequest(); locationRequest(); buddyRequest(); icmbRequest(); bosRequest(); break; case ICQ_SNACxSRV_MOTD: break; case ICQ_SNACxSRV_ACKxIMxICQ: snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_REQxRATExINFO); sendPacket(); break; case ICQ_SNACxSRV_NAMExINFO:{ string screen = m_socket->readBuffer.unpackScreen(); if (screen.length() == 0){ char n; m_socket->readBuffer >> n; m_socket->readBuffer.incReadPos(n); screen = m_socket->readBuffer.unpackScreen(); } if ((unsigned)atol(screen.c_str()) != data.owner.Uin){ log(L_WARN, "No my name info (%s)", screen.c_str()); break; } m_socket->readBuffer.incReadPos(4); TlvList tlv(m_socket->readBuffer); Tlv *tlvIP = tlv(0x000A); if (tlvIP) set_ip(&data.owner.IP, htonl((unsigned long)(*tlvIP))); log(L_DEBUG, "Name info"); break; } case ICQ_SNACxSRV_READYxSERVER: log(L_DEBUG, "Server ready"); snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_IMxICQ); if (m_bAIM){ m_socket->writeBuffer << 0x00010003L << 0x00130003L << 0x00020001L << 0x00030001L << 0x00040001L << 0x00060001L << 0x00080001L << 0x00090001L << 0x000A0001L << 0x000B0001L; }else{ m_socket->writeBuffer << 0x00010004L << 0x00130004L << 0x00020001L << 0x00030001L << 0x00150001L << 0x00040001L << 0x00060001L << 0x00090001L << 0x000A0001L << 0x000B0001L; } sendPacket(); break; case ICQ_SNACxSRV_ERROR: break; case ICQ_SNACxSRV_EVIL:{ unsigned short level; m_socket->readBuffer.unpack(level); string from = m_socket->readBuffer.unpackScreen(); data.owner.WarningLevel = level; QString f; f = from.c_str(); if (f.isEmpty()) f = i18n("anonymous"); clientErrorData d; d.client = this; d.code = 0; d.err_str = I18N_NOOP("You've been warned by %1"); d.args = strdup(f.utf8()); Event e(EventClientError, &d); e.process(); free(d.args); break; } default: log(L_WARN, "Unknown service family type %04X", type); }
void ICQClient::snac_buddy(unsigned short type, unsigned short) { string screen; Contact *contact; ICQUserData *data; switch (type){ case ICQ_SNACxBDY_RIGHTSxGRANTED: log(L_DEBUG, "Buddy rights granted"); break; case ICQ_SNACxBDY_USEROFFLINE: screen = m_socket->readBuffer.unpackScreen(); data = findContact(screen.c_str(), NULL, false, contact); if (data && (data->Status.value != ICQ_STATUS_OFFLINE)){ setOffline(data); StatusMessage m; m.setContact(contact->id()); m.setClient(dataName(data).c_str()); m.setStatus(STATUS_OFFLINE); m.setFlags(MESSAGE_RECEIVED); Event e(EventMessageReceived, &m); e.process(); } break; case ICQ_SNACxBDY_USERONLINE: screen = m_socket->readBuffer.unpackScreen(); data = findContact(screen.c_str(), NULL, false, contact); if (data){ time_t now; time(&now); bool bChanged = false; bool bAwayChanged = false; unsigned long prevStatus = data->Status.value; unsigned short level, len; m_socket->readBuffer >> level >> len; data->WarningLevel.value = level; TlvList tlv(m_socket->readBuffer); Tlv *tlvClass = tlv(0x0001); if (tlvClass){ unsigned short userClass = *tlvClass; if (userClass != data->Class.value){ if ((userClass & CLASS_AWAY) != (data->Class.value & CLASS_AWAY)){ data->StatusTime.value = (unsigned long)now; bAwayChanged = true; } data->Class.value = userClass; bChanged = true; } if (data->Uin.value == 0){ if (userClass & CLASS_AWAY){ fetchAwayMessage(data); }else{ set_str(&data->AutoReply.ptr, NULL); } } } // Status TLV Tlv *tlvStatus = tlv(0x0006); if (tlvStatus){ unsigned long status = *tlvStatus; if (status != data->Status.value){ data->Status.value = status; if ((status & 0xFF) == 0) set_str(&data->AutoReply.ptr, NULL); data->StatusTime.value = (unsigned long)now; } }else if (data->Status.value == ICQ_STATUS_OFFLINE){ data->Status.value = ICQ_STATUS_ONLINE; data->StatusTime.value = (unsigned long)now; } // Online time TLV Tlv *tlvOnlineTime = tlv(0x0003); if (tlvOnlineTime){ unsigned long OnlineTime = *tlvOnlineTime; if (OnlineTime != data->OnlineTime.value){ data->OnlineTime.value = OnlineTime; bChanged = true; } } Tlv *tlvNATime = tlv(0x0004); if (tlvNATime){ unsigned short na_time = *tlvNATime; unsigned long StatusTime = (unsigned long)now - na_time * 60; if (StatusTime != data->StatusTime.value){ data->StatusTime.value = StatusTime; bChanged = true; } } // IP TLV Tlv *tlvIP = tlv(0x000A); if (tlvIP) bChanged |= set_ip(&data->IP, htonl((unsigned long)(*tlvIP))); Tlv *tlvCapability = tlv(0x000D); if (tlvCapability){ data->Caps.value = 0; Buffer info(*tlvCapability); for (; info.readPos() < info.size(); ){ capability cap; info.unpack((char*)cap, sizeof(capability)); for (unsigned i = 0;; i++){ if (*capabilities[i] == 0) break; unsigned size = sizeof(capability); if (i == CAP_SIMOLD) size--; if ((i == CAP_MICQ) || (i == CAP_LICQ) || (i == CAP_SIM)) size -= 4; if (!memcmp(cap, capabilities[i], size)){ if (i == CAP_SIMOLD){ unsigned char build = cap[sizeof(capability)-1]; if (build && ((build == 0x92) || (build < (1 << 6)))) continue; data->Build.value = build; } if ((i == CAP_MICQ) || (i == CAP_LICQ) || (i == CAP_SIM)){ unsigned char *p = (unsigned char*)cap; p += 12; data->Build.value = (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3]; } data->Caps.value |= (1 << i); break; } } } } unsigned long infoUpdateTime = 0; unsigned long pluginInfoTime = 0; unsigned long pluginStatusTime = 0; // Direct connection info Tlv *tlvDirect = tlv(0x000C); if (tlvDirect){ Buffer info(*tlvDirect); unsigned long realIP; unsigned short port; char mode, version, junk; info >> realIP; info.incReadPos(2); info >> port; if (realIP == 0x7F000001) realIP = 0; bChanged |= set_ip(&data->RealIP, htonl(realIP)); data->Port.value = port; unsigned long DCcookie; info >> mode >> junk >> version >> DCcookie; data->DCcookie.value = DCcookie; info.incReadPos(8); info >> infoUpdateTime >> pluginInfoTime >> pluginStatusTime; if (mode == MODE_DENIED) mode = MODE_INDIRECT; if ((mode != MODE_DIRECT) && (mode != MODE_INDIRECT)) mode = MODE_INDIRECT; data->Mode.value = mode; data->Version.value = version; } Tlv *tlvPlugin = tlv(0x0011); if (tlvPlugin && data->Uin.value){ Buffer info(*tlvPlugin); char type; unsigned long time; info >> type; info.unpack(time); plugin p; unsigned plugin_index; unsigned long plugin_status; switch (type){ case 1: addFullInfoRequest(data->Uin.value); break; case 2: info.incReadPos(6); info.unpack((char*)p, sizeof(p)); data->PluginInfoTime.value = time; for (plugin_index = 0; plugin_index < PLUGIN_NULL; plugin_index++) if (!memcmp(p, plugins[plugin_index], sizeof(p))) break; switch (plugin_index){ case PLUGIN_PHONEBOOK: log(L_DEBUG, "Updated phonebook"); addPluginInfoRequest(data->Uin.value, plugin_index); break; case PLUGIN_PICTURE: log(L_DEBUG, "Updated picture"); addPluginInfoRequest(data->Uin.value, plugin_index); break; case PLUGIN_QUERYxINFO: log(L_DEBUG, "Updated info plugin list"); addPluginInfoRequest(data->Uin.value, plugin_index); break; default: if (plugin_index >= PLUGIN_NULL) log(L_WARN, "Unknown plugin sign"); } break; case 3: info.incReadPos(6); info.unpack((char*)p, sizeof(p)); info.incReadPos(1); info.unpack(plugin_status); data->PluginStatusTime.value = time; for (plugin_index = 0; plugin_index < PLUGIN_NULL; plugin_index++) if (!memcmp(p, plugins[plugin_index], sizeof(p))) break; switch (plugin_index){ case PLUGIN_FOLLOWME: if (data->FollowMe.value == plugin_status) break; data->FollowMe.value = plugin_status; bChanged = true; break; case PLUGIN_FILESERVER: if ((data->SharedFiles.value != 0) == (plugin_status != 0)) break; data->SharedFiles.value = (plugin_status != 0); bChanged = true; break; case PLUGIN_ICQPHONE: if (data->ICQPhone.value == plugin_status) break; data->ICQPhone.value = plugin_status; bChanged = true; break; default: if (plugin_index >= PLUGIN_NULL) log(L_WARN, "Unknown plugin sign"); } break; } }else{ data->InfoUpdateTime.value = infoUpdateTime; data->PluginInfoTime.value = pluginInfoTime; data->PluginStatusTime.value = pluginStatusTime; if (getAutoUpdate()){ if (infoUpdateTime == 0) infoUpdateTime = 1; if (infoUpdateTime != data->InfoFetchTime.value) addFullInfoRequest(data->Uin.value); if ((data->PluginInfoTime.value != data->PluginInfoFetchTime.value)){ if (data->PluginInfoTime.value) addPluginInfoRequest(data->Uin.value, PLUGIN_QUERYxINFO); } if ((data->PluginInfoTime.value != data->PluginInfoFetchTime.value) || (data->PluginStatusTime.value != data->PluginStatusFetchTime.value)){ if (data->SharedFiles.bValue){ data->SharedFiles.bValue = false; bChanged = true; } if (data->FollowMe.value){ data->FollowMe.value = 0; bChanged = true; } if (data->ICQPhone.bValue){ data->ICQPhone.bValue = false; bChanged = true; } if (data->PluginStatusTime.value) addPluginInfoRequest(data->Uin.value, PLUGIN_QUERYxSTATUS); } } } if (data->bInvisible.bValue){ data->bInvisible.bValue = false; bChanged = true; } if (bChanged){ Event e(EventContactChanged, contact); e.process(); } if ((data->Status.value != prevStatus) || bAwayChanged){ unsigned status = STATUS_OFFLINE; if ((data->Status.value & 0xFFFF) != ICQ_STATUS_OFFLINE){ status = STATUS_ONLINE; if (data->Status.value & ICQ_STATUS_DND){ status = STATUS_DND; }else if (data->Status.value & ICQ_STATUS_OCCUPIED){ status = STATUS_OCCUPIED; }else if (data->Status.value & ICQ_STATUS_NA){ status = STATUS_NA; }else if (data->Status.value & ICQ_STATUS_AWAY){ status = STATUS_AWAY; }else if (data->Status.value & ICQ_STATUS_FFC){ status = STATUS_FFC; } } if ((status == STATUS_ONLINE) && (data->Class.value & CLASS_AWAY)) status = STATUS_AWAY; StatusMessage m; m.setContact(contact->id()); m.setClient(dataName(data).c_str()); m.setStatus(status); m.setFlags(MESSAGE_RECEIVED); Event e(EventMessageReceived, &m); e.process(); if (!contact->getIgnore() && ((data->Class.value & CLASS_AWAY) == 0) && (((data->Status.value & 0xFF) == ICQ_STATUS_ONLINE) && (((prevStatus & 0xFF) != ICQ_STATUS_ONLINE)) || bAwayChanged) && (((prevStatus & 0xFFFF) != ICQ_STATUS_OFFLINE) || (data->OnlineTime.value > this->data.owner.OnlineTime.value))){ Event e(EventContactOnline, contact); e.process(); } if (getAutoReplyUpdate() && ((data->Status.value & 0xFF) != ICQ_STATUS_ONLINE)){ if ((getInvisible() && data->VisibleId.value) || (!getInvisible() && (data->InvisibleId.value == 0))) addPluginInfoRequest(data->Uin.value, PLUGIN_AR); } } }
void ICQClient::snac_buddy(unsigned short type, unsigned short) { switch (type){ case ICQ_SNACxBDY_RIGHTSxGRANTED: log(L_DEBUG, "Buddy rights granted"); break; case ICQ_SNACxBDY_USEROFFLINE:{ unsigned long uin = readBuffer.unpackUin(); ICQUser *user = getUser(uin); if (user && (user->uStatus != ICQ_STATUS_OFFLINE)){ log(L_DEBUG, "User %lu [%s] offline", uin, user->Alias.c_str()); user->setOffline(); ICQEvent e(EVENT_STATUS_CHANGED, uin); process_event(&e); } break; } case ICQ_SNACxBDY_USERONLINE:{ unsigned long uin = readBuffer.unpackUin(); if (uin == Uin()) break; ICQUser *user = getUser(uin); if (user){ time_t now; time(&now); bool changed = false; unsigned long cookie1, cookie2, cookie3; cookie1 = cookie2 = cookie3 = 0; unsigned short level, len; readBuffer >> level >> len; TlvList tlv(readBuffer); // Status TLV Tlv *tlvStatus = tlv(0x0006); if (tlvStatus){ unsigned long status = *tlvStatus; log(L_DEBUG, "User %lu [%s] online [%08lX]", uin, user->Alias.c_str(), status); if (status != user->uStatus){ user->prevStatus = user->uStatus; user->uStatus = status; if (status & 0xFF){ addResponseRequest(uin); }else{ user->AutoReply = ""; } user->StatusTime = (unsigned long)now; changed = true; } } // Online time TLV Tlv *tlvOnlineTime = tlv(0x0003); if (tlvOnlineTime){ user->OnlineTime = (unsigned long)(*tlvOnlineTime); changed = true; } Tlv *tlvNATime = tlv(0x0004); if (tlvNATime){ user->StatusTime = (unsigned long)now - (unsigned short)(*tlvNATime) * 60L; changed = true; } // IP TLV Tlv *tlvIP = tlv(0x000A); if (tlvIP){ unsigned long ip = htonl((unsigned long)(*tlvIP)); if (user->IP() != ip) user->HostName = ""; user->IP = ip; changed = true; } // Direct connection info Tlv *tlvDirect = tlv(0x000C); if (tlvDirect){ user->ClientType = 0; Buffer info(*tlvDirect); unsigned long realIP; unsigned short port; char mode, version, junk; info >> realIP; info.incReadPos(2); info >> port; realIP = htonl(realIP); if (user->RealIP != realIP) user->RealHostName =""; user->RealIP = realIP; user->Port = port; info >> mode >> junk >> version >> user->DCcookie; info.incReadPos(8); info >> cookie1 >> cookie2 >> cookie3; if (cookie3 != user->PhoneBookTime()){ user->bPhoneChanged = true; user->PhoneBookTime = cookie3; } user->PhoneStatusTime = cookie2; user->TimeStamp = cookie1; if (mode == MODE_DENIED) mode = MODE_INDIRECT; if ((mode != MODE_DIRECT) && (mode != MODE_INDIRECT)) mode = MODE_INDIRECT; user->Mode = (unsigned short)mode; user->Version = (unsigned short)version; changed = true; if (user->DCcookie == 0) user->ClientType = 4; if ((user->DCcookie == cookie1) && (cookie1 == cookie2)) user->ClientType = 5; if (cookie1 == 0x279c6996) user->ClientType = 3; } Tlv *tlvCapability = tlv(0x000D); if (tlvCapability){ user->GetRTF = false; Buffer info(*tlvCapability); for (; info.readPos() < info.size(); ){ capability cap; info.unpack((char*)cap, sizeof(capability)); if (!memcmp(cap, capabilities[1], sizeof(capability))){ user->GetRTF = true; if (!user->CanPlugin){ if (user->bPhoneChanged) addPhoneRequest(uin); user->CanPlugin = true; } } if (!memcmp(cap, capabilities[3], sizeof(capability))) user->CanResponse = true; if (!memcmp(cap, capabilities[5], sizeof(capability))) user->ClientType = 2; if (!memcmp(cap, capabilities[4], sizeof(capability))) user->ClientType = 1; if (!memcmp(cap, capabilities[4], sizeof(capability)-1) && (cap[sizeof(capability)-1] > (1 << 6)) && (cap[sizeof(capability)-1] != 0x92)) user->ClientType = (char)(cap[sizeof(capability)-1]); } } Tlv *tlvPlugin = tlv(0x0011); if (tlvPlugin){ Buffer info(*tlvPlugin); char reqType; info >> reqType; info.incReadPos(10); capability cap; info.unpack((char*)cap, sizeof(capability)); if (user->CanPlugin && !memcmp(cap, PHONEBOOK_SIGN, sizeof(capability))){ if (reqType == 3){ info.incReadPos(3); info >> user->PhoneState; if (user->bPhoneChanged) addPhoneRequest(uin); }else if (reqType == 2) if (user->bPhoneChanged) addPhoneRequest(uin); } addInfoRequest(uin); changed = true; } if (changed){ ICQEvent e(EVENT_STATUS_CHANGED, uin); process_event(&e); user->prevStatus = user->uStatus; } } break; }
void ICQClient::snac_service(unsigned short type, unsigned short) { switch (type){ case ICQ_SNACxSRV_PAUSE: log(L_DEBUG, "Server pause"); m_bNoSend = true; snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_PAUSExACK); m_socket->writeBuffer << ICQ_SNACxFAM_SERVICE << ICQ_SNACxFAM_LOCATION << ICQ_SNACxFAM_BUDDY << ICQ_SNACxFAM_MESSAGE << ICQ_SNACxFAM_BOS << ICQ_SNACxFAM_PING << ICQ_SNACxFAM_LISTS << ICQ_SNACxFAM_VARIOUS << ICQ_SNACxFAM_LOGIN; sendPacket(true); break; case ICQ_SNACxSRV_RESUME: log(L_DEBUG, "Server resume"); m_bNoSend = false; processSendQueue(); break; case ICQ_SNACxSRV_MIGRATE:{ log(L_DEBUG, "Server migrate"); m_bNoSend = true; int i; unsigned short cnt; unsigned short fam[0x17]; m_socket->readBuffer >> cnt; for (i = 0; i < cnt; i++) { m_socket->readBuffer >> fam[i]; } TlvList tlv(m_socket->readBuffer); Tlv *tlv_adr = tlv(0x05); Tlv *tlv_cookie = tlv(0x06); for (; i >= 0; i--) { setServiceSocket(tlv_adr,tlv_cookie,fam[i]); } break; } case ICQ_SNACxSRV_RATExCHANGE:{ const char *msg_text = NULL; unsigned short msg_code; unsigned short class_id; unsigned long window_size; unsigned long clear_level; unsigned long alert_level; unsigned long limit_level; unsigned long discon_level; unsigned long current_level; unsigned long max_level; unsigned long last_send; char current_state; m_socket->readBuffer >> msg_code >> class_id >> window_size >> clear_level >> alert_level >> limit_level >> discon_level >> current_level >> max_level >> last_send >> current_state; if (type == ICQ_SNACxSRV_RATExCHANGE){ switch (msg_code) { case 0x0001: msg_text = "Rate limits parameters changed"; break; case 0x0002: msg_text = "Rate limits warning"; break; case 0x0003: msg_text = "Rate limit hit"; break; case 0x0004: msg_text = "Rate limit clear"; break; default: msg_text = "Unknown"; } log(L_DEBUG, "%s", msg_text); } log(L_DEBUG, "grp: %02X, ws: %04lX, cl %04lX, al %04lX, ll %04lX, dl: %04lX, cur %04lX, ml %04lX", class_id,window_size,clear_level,alert_level,limit_level,discon_level, current_level,max_level); if (--class_id < m_rates.size()){ RateInfo &r = m_rates[class_id]; r.m_winSize = window_size; r.m_maxLevel = max_level; r.m_minLevel = alert_level; r.m_curLevel = current_level; r.m_lastSend = QDateTime::currentDateTime(); processSendQueue(); } break; } case ICQ_SNACxSRV_RATExINFO: if (m_rates.size() == 0){ unsigned short n_rates; m_socket->readBuffer >> n_rates; unsigned n; for (n = 0; n < n_rates; n++){ unsigned short class_id; unsigned long window_size; unsigned long clear_level; unsigned long alert_level; unsigned long limit_level; unsigned long discon_level; unsigned long current_level; unsigned long max_level; unsigned long last_send; char current_state; m_socket->readBuffer >> class_id >> window_size >> clear_level >> alert_level >> limit_level >> discon_level >> current_level >> max_level >> last_send >> current_state; log(L_DEBUG, "grp: %02X, ws: %04lX, cl %04lX, al %04lX, ll %04lX, dl: %04lX, cur %04lX, ml %04lX", class_id,window_size,clear_level,alert_level,limit_level,discon_level, current_level,max_level); RateInfo r; r.m_winSize = window_size; r.m_minLevel = alert_level; r.m_maxLevel = max_level; r.m_curLevel = current_level; r.m_lastSend = QDateTime::currentDateTime(); m_rates.push_back(r); } for (n = 0; n < n_rates; n++){ unsigned short class_id; unsigned short pairs; m_socket->readBuffer >> class_id >> pairs; class_id--; for (unsigned i = 0; i < pairs; i++){ unsigned long snac; m_socket->readBuffer >> snac; if (class_id >= m_rates.size()) continue; RATE_MAP::iterator it = m_rate_grp.find(snac); if (it != m_rate_grp.end()) continue; m_rate_grp.insert(RATE_MAP::value_type(snac, class_id)); } } snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_RATExACK); m_socket->writeBuffer << 0x00010002L << 0x00030004L << 0x0005; sendPacket(true); snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_GETxUSERxINFO); sendPacket(true); listsRequest(); locationRequest(); buddyRequest(); icmbRequest(); bosRequest(); } break; case ICQ_SNACxSRV_MOTD: break; case ICQ_SNACxSRV_ACKxIMxICQ: snac(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_REQxRATExINFO); sendPacket(true); break; case ICQ_SNACxSRV_NAMExINFO:{ string screen = m_socket->readBuffer.unpackScreen(); if (screen.length() == 0){ char n; m_socket->readBuffer >> n; m_socket->readBuffer.incReadPos(n); screen = m_socket->readBuffer.unpackScreen(); } if ((unsigned)atol(screen.c_str()) != data.owner.Uin.value){ log(L_WARN, "No my name info (%s)", screen.c_str()); break; } m_socket->readBuffer.incReadPos(4); TlvList tlv(m_socket->readBuffer); Tlv *tlvIP = tlv(0x000A); if (tlvIP) set_ip(&data.owner.IP, htonl((unsigned long)(*tlvIP))); break; }
void ICQClientPrivate::snac_buddy(unsigned short type, unsigned short) { switch (type){ case ICQ_SNACxBDY_RIGHTSxGRANTED: log(L_DEBUG, "Buddy rights granted"); break; case ICQ_SNACxBDY_USEROFFLINE:{ unsigned long uin = sock->readBuffer.unpackUin(); ICQUser *user = client->getUser(uin); if (user && (user->uStatus != ICQ_STATUS_OFFLINE)){ log(L_DEBUG, "User %lu [%s] offline", uin, user->Alias.c_str()); user->setOffline(); ICQEvent e(EVENT_STATUS_CHANGED, uin); client->process_event(&e); } break; } case ICQ_SNACxBDY_USERONLINE:{ unsigned long uin = sock->readBuffer.unpackUin(); if (uin == client->owner->Uin) break; ICQUser *user = client->getUser(uin); if (user){ time_t now; time(&now); bool changed = false; if (user->uStatus == ICQ_STATUS_OFFLINE) user->Caps = 0; unsigned long cookie1, cookie2, cookie3; cookie1 = cookie2 = cookie3 = 0; unsigned short level, len; sock->readBuffer >> level >> len; TlvList tlv(sock->readBuffer); // Status TLV Tlv *tlvStatus = tlv(0x0006); if (tlvStatus){ unsigned long status = *tlvStatus; log(L_DEBUG, "User %lu [%s] online [%08lX]", uin, user->Alias.c_str(), status); if (status != user->uStatus){ user->prevStatus = user->uStatus; user->uStatus = status; if (status & 0xFF){ client->addResponseRequest(uin); }else{ user->AutoReply = ""; } user->StatusTime = (unsigned long)now; changed = true; } }else if (user->uStatus == ICQ_STATUS_OFFLINE){ user->uStatus = ICQ_STATUS_ONLINE; } // Online time TLV Tlv *tlvOnlineTime = tlv(0x0003); if (tlvOnlineTime){ user->OnlineTime = (unsigned long)(*tlvOnlineTime); changed = true; } Tlv *tlvNATime = tlv(0x0004); if (tlvNATime){ user->StatusTime = (unsigned long)now - (unsigned short)(*tlvNATime) * 60L; changed = true; } // IP TLV Tlv *tlvIP = tlv(0x000A); if (tlvIP){ unsigned long ip = htonl((unsigned long)(*tlvIP)); if (user->IP != ip) user->HostName = ""; user->IP = ip; log(L_DEBUG, "IP %s %lu", user->Alias.c_str(), user->IP); changed = true; } // Direct connection info Tlv *tlvDirect = tlv(0x000C); if (tlvDirect){ Buffer info(*tlvDirect); unsigned long realIP; unsigned short port; char mode, version, junk; info >> realIP; info.incReadPos(2); info >> port; realIP = htonl(realIP); if (user->RealIP != realIP) user->RealHostName =""; user->RealIP = realIP; user->Port = port; info >> mode >> junk >> version >> user->DCcookie; info.incReadPos(8); info >> cookie1 >> cookie2 >> cookie3; if (cookie3 != user->PhoneBookTime){ user->bPhoneChanged = true; user->PhoneBookTime = cookie3; } user->PhoneStatusTime = cookie2; user->InfoUpdateTime = cookie1; if (mode == MODE_DENIED) mode = MODE_INDIRECT; if ((mode != MODE_DIRECT) && (mode != MODE_INDIRECT)) mode = MODE_INDIRECT; user->Mode = (unsigned short)mode; user->Version = (unsigned short)version; changed = true; } Tlv *tlvCapability = tlv(0x000D); if (tlvCapability){ Buffer info(*tlvCapability); for (; info.readPos() < info.size(); ){ capability cap; info.unpack((char*)cap, sizeof(capability)); for (unsigned i = 0;; i++){ if (*capabilities[i] == 0) break; unsigned size = sizeof(capability); if (i == CAP_SIM) size--; if (i == CAP_MICQ) size -= 4; if (!memcmp(cap, capabilities[i], size)){ if (i == CAP_SIM){ unsigned char build = cap[sizeof(capability)-1]; log(L_DEBUG, "Build: %X %u", build, build); if (build && ((build == 0x92) || (build < (1 << 6)))) continue; user->Build = build; } if (i == CAP_MICQ){ unsigned char *p = (unsigned char*)cap; p += 12; user->Build = (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3]; } user->Caps |= (1 << i); } } } if (user->hasCap(CAP_RTF) && !user->CanPlugin){ user->CanPlugin = true; if (user->bPhoneChanged) client->addPhoneRequest(uin); } } Tlv *tlvPlugin = tlv(0x0011); if (tlvPlugin){ Buffer info(*tlvPlugin); char reqType; info >> reqType; info.incReadPos(10); capability cap; info.unpack((char*)cap, sizeof(capability)); if (user->CanPlugin && !memcmp(cap, PHONEBOOK_SIGN, sizeof(capability))){ if (reqType == 3){ info.incReadPos(3); info >> user->PhoneState; if (user->bPhoneChanged) client->addPhoneRequest(uin); }else if (reqType == 2) if (user->bPhoneChanged) client->addPhoneRequest(uin); } client->addInfoRequest(uin); changed = true; } if (changed){ ICQEvent e(EVENT_STATUS_CHANGED, uin); client->process_event(&e); user->prevStatus = user->uStatus; } } break; }