void __fastcall write_flap(icq_packet *pPacket, BYTE byFlapChannel) { init_generic_packet(pPacket, 6); pPacket->nChannel = byFlapChannel; packByte(pPacket, FLAP_MARKER); packByte(pPacket, byFlapChannel); packWord(pPacket, 0); // This is the sequence ID, it is filled in during the actual sending packWord(pPacket, (WORD)(pPacket->wLen - 6)); // This counter should not include the flap header (thus the -6) }
static void file_sendTransferSpeed(CIcqProto* ppro, directconnect* dc) { icq_packet packet; directPacketInit(&packet, 5); packByte(&packet, PEER_FILE_SPEED); /* Ident */ packLEDWord(&packet, dc->ft->dwTransferSpeed); ppro->sendDirectPacket(dc, &packet); }
static void file_sendResume(CIcqProto* ppro, directconnect* dc) { icq_packet packet; directPacketInit(&packet, 17); packByte(&packet, PEER_FILE_RESUME); /* Ident */ packLEDWord(&packet, dc->ft->dwFileBytesDone); /* file resume */ packLEDWord(&packet, 0); /* unknown */ packLEDWord(&packet, dc->ft->dwTransferSpeed); packLEDWord(&packet, dc->ft->iCurrentFile + 1); /* file number */ ppro->sendDirectPacket(dc, &packet); }
static void file_sendData(CIcqProto* ppro, directconnect* dc) { BYTE buf[2048]; int bytesRead = 0; if (!dc->ft->currentIsDir) { icq_packet packet; if (dc->ft->fileId == -1) return; bytesRead = _read(dc->ft->fileId, buf, sizeof(buf)); if (bytesRead == -1) return; directPacketInit(&packet, (WORD)(1 + bytesRead)); packByte(&packet, PEER_FILE_DATA); /* Ident */ packBuffer(&packet, buf, (WORD)bytesRead); ppro->sendDirectPacket(dc, &packet); } dc->ft->dwBytesDone += bytesRead; dc->ft->dwFileBytesDone += bytesRead; if (GetTickCount() > dc->ft->dwLastNotify + 500 || bytesRead == 0) { PROTOFILETRANSFERSTATUS pfts; file_buildProtoFileTransferStatus(dc->ft, &pfts); ppro->BroadcastAck(dc->ft->hContact, ACKTYPE_FILE, ACKRESULT_DATA, dc->ft, (LPARAM)&pfts); dc->ft->dwLastNotify = GetTickCount(); } if (bytesRead == 0) { if (!dc->ft->currentIsDir) _close(dc->ft->fileId); dc->ft->fileId = -1; dc->wantIdleTime = 0; dc->ft->iCurrentFile++; file_sendNextFile(ppro, dc); /* this will close the socket if no more files */ } }
void __fastcall serverCookieInit(icq_packet *pPacket, BYTE *pCookie, WORD wCookieSize) { pPacket->wLen = (WORD)(wCookieSize + 8 + sizeof(CLIENT_ID_STRING) + 66); write_flap(pPacket, ICQ_LOGIN_CHAN); packDWord(pPacket, 0x00000001); packTLV(pPacket, 0x06, wCookieSize, pCookie); // Pack client identification details. packTLV(pPacket, 0x0003, (WORD)sizeof(CLIENT_ID_STRING)-1, (LPBYTE)CLIENT_ID_STRING); packTLVWord(pPacket, 0x0017, CLIENT_VERSION_MAJOR); packTLVWord(pPacket, 0x0018, CLIENT_VERSION_MINOR); packTLVWord(pPacket, 0x0019, CLIENT_VERSION_LESSER); packTLVWord(pPacket, 0x001a, CLIENT_VERSION_BUILD); packTLVWord(pPacket, 0x0016, CLIENT_ID_CODE); packTLVDWord(pPacket, 0x0014, CLIENT_DISTRIBUTION); packTLV(pPacket, 0x000f, 0x0002, (LPBYTE)CLIENT_LANGUAGE); packTLV(pPacket, 0x000e, 0x0002, (LPBYTE)CLIENT_COUNTRY); packDWord(pPacket, 0x00940001); // reconnect flag packByte(pPacket, 0); packTLVDWord(pPacket, 0x8003, 0x00100000); // Unknown }
static void file_sendNick(CIcqProto* ppro, directconnect* dc) { icq_packet packet; char* szNick; WORD wNickLen; DBVARIANT dbv = {DBVT_DELETED}; if (ppro->getSettingString(NULL, "Nick", &dbv)) szNick = ""; else szNick = dbv.pszVal; wNickLen = strlennull(szNick); directPacketInit(&packet, (WORD)(8 + wNickLen)); packByte(&packet, PEER_FILE_INIT_ACK); /* Ident */ packLEDWord(&packet, dc->ft->dwTransferSpeed); packLEWord(&packet, (WORD)(wNickLen + 1)); packBuffer(&packet, (LPBYTE)szNick, (WORD)(wNickLen + 1)); ppro->sendDirectPacket(dc, &packet); ICQFreeVariant(&dbv); }
DWORD avatars_server_connection::sendGetAvatarRequest(MCONTACT hContact, DWORD dwUin, char *szUid, const BYTE *hash, size_t hashlen, const TCHAR *file) { int i; DWORD dwNow = GetTickCount(); mir_cslockfull alck(ppro->m_avatarsMutex); for (i = 0; i < runCount;) { // look for timeouted requests if (runTime[i] < dwNow) { // found outdated, remove runContact[i] = runContact[runCount - 1]; runTime[i] = runTime[runCount - 1]; runCount--; } else i++; } for (i = 0; i < runCount; i++) { if (runContact[i] == hContact) { ppro->debugLogA("Ignoring duplicate get %s image request.", strUID(dwUin, szUid)); return -1; // Success: request ignored } } if (runCount < 4) { // 4 concurent requests at most int bSendNow = TRUE; { // rate management mir_cslock l(m_ratesMutex); WORD wGroup = m_rates->getGroupFromSNAC(ICQ_AVATAR_FAMILY, ICQ_AVATAR_GET_REQUEST); if (m_rates->getNextRateLevel(wGroup) < m_rates->getLimitLevel(wGroup, RML_ALERT)) { // we will be over quota if we send the request now, add to queue instead bSendNow = FALSE; ppro->debugLogA("Rates: Delay avatar request."); } } if (bSendNow) { runContact[runCount] = hContact; runTime[runCount] = GetTickCount() + 30000; // 30sec to complete request runCount++; alck.unlock(); int nUinLen = getUIDLen(dwUin, szUid); cookie_avatar *ack = (cookie_avatar*)SAFE_MALLOC(sizeof(cookie_avatar)); if (!ack) return 0; // Failure: out of memory ack->dwUin = 1; //dwUin; // I should be damned for this - only to identify get request ack->hContact = hContact; ack->hash = (BYTE*)SAFE_MALLOC(hashlen); memcpy(ack->hash, hash, hashlen); // copy the data ack->hashlen = hashlen; ack->szFile = null_strdup(file); // duplicate the string DWORD dwCookie = ppro->AllocateCookie(CKT_AVATAR, ICQ_AVATAR_GET_REQUEST, hContact, ack); icq_packet packet; serverPacketInit(&packet, 12 + nUinLen + hashlen); packFNACHeader(&packet, ICQ_AVATAR_FAMILY, ICQ_AVATAR_GET_REQUEST, 0, dwCookie); packUID(&packet, dwUin, szUid); packByte(&packet, 1); // unknown, probably type of request: 1 = get icon :) packBuffer(&packet, hash, hashlen); if (sendServerPacket(&packet)) { ppro->debugLogA("Request to get %s image sent.", strUID(dwUin, szUid)); return dwCookie; } ppro->FreeCookie(dwCookie); // sending failed, free resources SAFE_FREE(&ack->szFile); SAFE_FREE((void**)&ack->hash); SAFE_FREE((void**)&ack); } } return 0; // Failure }
void CIcqProto::handleServUINSettings(int nPort, serverthread_info *info) { setUserInfo(); /* SNAC 3,4: Tell server who's on our list (deprecated) */ /* SNAC 3,15: Try to add unauthorised contacts to temporary list */ sendEntireListServ(ICQ_BUDDY_FAMILY, ICQ_USER_ADDTOTEMPLIST, BUL_ALLCONTACTS); if (m_iDesiredStatus == ID_STATUS_INVISIBLE) { /* Tell server who's on our visible list (deprecated) */ if (!m_bSsiEnabled) sendEntireListServ(ICQ_BOS_FAMILY, ICQ_CLI_ADDVISIBLE, BUL_VISIBLE); else updateServVisibilityCode(3); } if (m_iDesiredStatus != ID_STATUS_INVISIBLE) { /* Tell server who's on our invisible list (deprecated) */ if (!m_bSsiEnabled) sendEntireListServ(ICQ_BOS_FAMILY, ICQ_CLI_ADDINVISIBLE, BUL_INVISIBLE); else updateServVisibilityCode(4); } // SNAC 1,1E: Set status icq_packet packet; { DWORD dwDirectCookie = rand() ^ (rand() << 16); // Get status WORD wStatus = MirandaStatusToIcq(m_iDesiredStatus); // Get status note & mood char *szStatusNote = PrepareStatusNote(m_iDesiredStatus); BYTE bXStatus = getContactXStatus(NULL); char szMoodData[32]; // prepare mood id if (m_bMoodsEnabled && bXStatus && moodXStatus[bXStatus - 1] != -1) mir_snprintf(szMoodData, "icqmood%d", moodXStatus[bXStatus - 1]); else szMoodData[0] = '\0'; //! Tricky code, this ensures that the status note will be saved to the directory SetStatusNote(szStatusNote, m_bGatewayMode ? 5000 : 2500, TRUE); size_t wStatusNoteLen = mir_strlen(szStatusNote); size_t wStatusMoodLen = mir_strlen(szMoodData); size_t wSessionDataLen = (wStatusNoteLen ? wStatusNoteLen + 4 : 0) + 4 + wStatusMoodLen + 4; serverPacketInit(&packet, 71 + (wSessionDataLen ? wSessionDataLen + 4 : 0)); packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_SET_STATUS); packDWord(&packet, 0x00060004); // TLV 6: Status mode and security flags packWord(&packet, GetMyStatusFlags()); // Status flags packWord(&packet, wStatus); // Status packTLVWord(&packet, 0x0008, 0x0A06); // TLV 8: Independent Status Messages packDWord(&packet, 0x000c0025); // TLV C: Direct connection info packDWord(&packet, getDword("RealIP", 0)); packDWord(&packet, nPort); packByte(&packet, DC_TYPE); // TCP/FLAG firewall settings packWord(&packet, ICQ_VERSION); packDWord(&packet, dwDirectCookie); // DC Cookie packDWord(&packet, WEBFRONTPORT); // Web front port packDWord(&packet, CLIENTFEATURES); // Client features packDWord(&packet, 0x7fffffff); // Abused timestamp packDWord(&packet, ICQ_PLUG_VERSION); // Abused timestamp if (ServiceExists("SecureIM/IsContactSecured")) packDWord(&packet, 0x5AFEC0DE); // SecureIM Abuse else packDWord(&packet, 0x00000000); // Timestamp packWord(&packet, 0x0000); // Unknown packTLVWord(&packet, 0x001F, 0x0000); if (wSessionDataLen) { // Pack session data packWord(&packet, 0x1D); // TLV 1D packWord(&packet, WORD(wSessionDataLen)); // TLV length packWord(&packet, 0x02); // Item Type if (wStatusNoteLen) { packWord(&packet, 0x400 | WORD(wStatusNoteLen + 4)); // Flags + Item Length packWord(&packet, WORD(wStatusNoteLen)); // Text Length packBuffer(&packet, (LPBYTE)szStatusNote, wStatusNoteLen); packWord(&packet, 0); // Encoding not specified (utf-8 is default) } else packWord(&packet, 0); // Flags + Item Length packWord(&packet, 0x0E); // Item Type packWord(&packet, WORD(wStatusMoodLen)); // Flags + Item Length if (wStatusMoodLen) packBuffer(&packet, (LPBYTE)szMoodData, wStatusMoodLen); // Mood // Save current status note & mood db_set_utf(NULL, m_szModuleName, DBSETTING_STATUS_NOTE, szStatusNote); setString(DBSETTING_STATUS_MOOD, szMoodData); } // Release memory SAFE_FREE(&szStatusNote); sendServPacket(&packet); } /* SNAC 1,11 */ serverPacketInit(&packet, 14); packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_SET_IDLE); packDWord(&packet, 0x00000000); sendServPacket(&packet); m_bIdleAllow = 0; // Change status SetCurrentStatus(m_iDesiredStatus); // Finish Login sequence serverPacketInit(&packet, 98); packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_READY); packDWord(&packet, 0x00220001); // imitate ICQ 6 behaviour packDWord(&packet, 0x0110164f); packDWord(&packet, 0x00010004); packDWord(&packet, 0x0110164f); packDWord(&packet, 0x00130004); packDWord(&packet, 0x0110164f); packDWord(&packet, 0x00020001); packDWord(&packet, 0x0110164f); packDWord(&packet, 0x00030001); packDWord(&packet, 0x0110164f); packDWord(&packet, 0x00150001); packDWord(&packet, 0x0110164f); packDWord(&packet, 0x00040001); packDWord(&packet, 0x0110164f); packDWord(&packet, 0x00060001); packDWord(&packet, 0x0110164f); packDWord(&packet, 0x00090001); packDWord(&packet, 0x0110164f); packDWord(&packet, 0x000A0001); packDWord(&packet, 0x0110164f); packDWord(&packet, 0x000B0001); packDWord(&packet, 0x0110164f); sendServPacket(&packet); debugLogA(" *** Yeehah, login sequence complete"); // login sequence is complete enter logged-in mode info->bLoggedIn = true; m_bConnectionLost = false; // enable auto info-update routine icq_EnableUserLookup(true); if (!info->isMigrating) { // Get Offline Messages Reqeust cookie_offline_messages *ack = (cookie_offline_messages*)SAFE_MALLOC(sizeof(cookie_offline_messages)); if (ack) { DWORD dwCookie = AllocateCookie(CKT_OFFLINEMESSAGE, ICQ_MSG_CLI_REQ_OFFLINE, 0, ack); serverPacketInit(&packet, 10); packFNACHeader(&packet, ICQ_MSG_FAMILY, ICQ_MSG_CLI_REQ_OFFLINE, 0, dwCookie); sendServPacket(&packet); } else icq_LogMessage(LOG_WARNING, LPGEN("Failed to request offline messages. They may be received next time you log in.")); // Update our information from the server sendOwnerInfoRequest(); // Request info updates on all contacts icq_RescanInfoUpdate(); // Start sending Keep-Alive packets StartKeepAlive(info); if (m_bAvatarsEnabled) { // Send SNAC 1,4 - request avatar family 0x10 connection icq_requestnewfamily(ICQ_AVATAR_FAMILY, &CIcqProto::StartAvatarThread); m_avatarsConnectionPending = TRUE; debugLogA("Requesting Avatar family entry point."); } // Set last xstatus updateServerCustomStatus(TRUE); } info->isMigrating = false; if (m_bAimEnabled) { char **szAwayMsg = NULL; mir_cslock l(m_modeMsgsMutex); szAwayMsg = MirandaStatusToAwayMsg(m_iStatus); if (szAwayMsg) icq_sendSetAimAwayMsgServ(*szAwayMsg); } }
static void file_sendNextFile(CIcqProto* ppro, directconnect* dc) { icq_packet packet; struct _stati64 statbuf; char szThisSubDir[MAX_PATH]; if (dc->ft->iCurrentFile >= (int)dc->ft->dwFileCount) { ppro->BroadcastAck(dc->ft->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, dc->ft, 0); ppro->CloseDirectConnection(dc); dc->ft->hConnection = NULL; return; } dc->ft->szThisFile = dc->ft->pszFiles[dc->ft->iCurrentFile]; if (FileStatUtf(dc->ft->szThisFile, &statbuf)) { ppro->icq_LogMessage(LOG_ERROR, LPGEN("Your file transfer has been aborted because one of the files that you selected to send is no longer readable from the disk. You may have deleted or moved it.")); ppro->CloseDirectConnection(dc); dc->ft->hConnection = NULL; return; } char *pszThisFileName = FindFilePathContainer((LPCSTR*)dc->ft->pszFiles, dc->ft->iCurrentFile, szThisSubDir); if (statbuf.st_mode&_S_IFDIR) { dc->ft->currentIsDir = 1; } else { dc->ft->currentIsDir = 0; dc->ft->fileId = OpenFileUtf(dc->ft->szThisFile, _O_BINARY | _O_RDONLY, _S_IREAD); if (dc->ft->fileId == -1) { ppro->icq_LogMessage(LOG_ERROR, LPGEN("Your file transfer has been aborted because one of the files that you selected to send is no longer readable from the disk. You may have deleted or moved it.")); ppro->CloseDirectConnection(dc); dc->ft->hConnection = NULL; return; } } dc->ft->dwThisFileSize = statbuf.st_size; dc->ft->dwThisFileDate = statbuf.st_mtime; dc->ft->dwFileBytesDone = 0; char *szThisFileNameAnsi = NULL, *szThisSubDirAnsi = NULL; if (!utf8_decode(pszThisFileName, &szThisFileNameAnsi)) szThisFileNameAnsi = NULL; if (!utf8_decode(szThisSubDir, &szThisSubDirAnsi)) szThisSubDirAnsi = NULL; WORD wThisFileNameLen = strlennull(szThisFileNameAnsi); WORD wThisSubDirLen = strlennull(szThisSubDirAnsi); directPacketInit(&packet, (WORD)(20 + wThisFileNameLen + wThisSubDirLen)); packByte(&packet, PEER_FILE_NEXTFILE); /* Ident */ packByte(&packet, (BYTE)((statbuf.st_mode & _S_IFDIR) != 0)); // Is subdir packLEWord(&packet, (WORD)(wThisFileNameLen + 1)); packBuffer(&packet, (LPBYTE)szThisFileNameAnsi, (WORD)(wThisFileNameLen + 1)); packLEWord(&packet, (WORD)(wThisSubDirLen + 1)); packBuffer(&packet, (LPBYTE)szThisSubDirAnsi, (WORD)(wThisSubDirLen + 1)); packLEDWord(&packet, dc->ft->dwThisFileSize); packLEDWord(&packet, statbuf.st_mtime); packLEDWord(&packet, dc->ft->dwTransferSpeed); SAFE_FREE(&szThisFileNameAnsi); SAFE_FREE(&szThisSubDirAnsi); ppro->sendDirectPacket(dc, &packet); ppro->BroadcastAck(dc->ft->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, dc->ft, 0); }