示例#1
0
void CIcqProto::handleXtrazData(DWORD dwUin, DWORD dwMID, DWORD dwMID2, WORD wCookie, char* szMsg, int nMsgLen, BOOL bThruDC)
{
	MCONTACT hContact;
	char* szPluginID;

	hContact = HContactFromUIN(dwUin, NULL);
	if (hContact) // user sent us xtraz, he supports it
		SetContactCapabilities(hContact, CAPF_XTRAZ);

	szPluginID = getXmlPidItem(szMsg, nMsgLen);
	if (!strcmpnull(szPluginID, "viewCard")) { // it is a greeting card
		char *szWork, *szEnd, *szUrl, *szNum;

		szWork = strstrnull(szMsg, "<InD>");
		szEnd = strstrnull(szMsg, "</InD>");
		if (szWork && szEnd) {
			int nDataLen = szEnd - szWork;

			szUrl = (char*)_alloca(nDataLen);
			memcpy(szUrl, szWork + 5, nDataLen);
			szUrl[nDataLen - 5] = '\0';

			if (!_strnicmp(szUrl, "view_", 5)) {
				szNum = szUrl + 5;
				szWork = strstrnull(szUrl, ".html");
				if (szWork) {
					strcpy(szWork, ".php");
					strcat(szWork, szWork + 5);
				}
				while (szWork = strstrnull(szUrl, "&amp;"))  // unescape &amp; code
					strcpy(szWork + 1, szWork + 5);

				szWork = (char*)SAFE_MALLOC(nDataLen + MAX_PATH);
				ICQTranslateUtfStatic(LPGEN("Greeting card:"), szWork, MAX_PATH);
				strcat(szWork, "\r\nhttp://www.icq.com/friendship/pages/view_page_");
				strcat(szWork, szNum);

				// Create message to notify user
				PROTORECVEVENT pre = { 0 };
				pre.timestamp = time(NULL);
				pre.szMessage = szWork;
				pre.flags = PREF_UTF;

				int bAdded;
				ProtoChainRecvMsg(HContactFromUIN(dwUin, &bAdded), &pre);

				SAFE_FREE(&szWork);
			}
			else NetLog_Uni(bThruDC, "Error: Non-standard greeting card message");
		}
		else NetLog_Uni(bThruDC, "Error: Malformed greeting card message");
	}
	else NetLog_Uni(bThruDC, "Error: Unknown plugin \"%s\" in Xtraz message", szPluginID);

	SAFE_FREE(&szPluginID);
}
示例#2
0
static void MessageIcqUser(ICQFILEINFO *info)
{
	MCONTACT hContact;
	if (ServiceExists(MS_MSG_SENDMESSAGE)) {
		hContact = HContactFromUIN(atoi(info->uin), NULL); /* adds the contact if needed */
		if (hContact != NULL)
			CallService(MS_MSG_SENDMESSAGE, hContact, 0);
	}
}
示例#3
0
void CIcqProto::handleXtrazInvitation(DWORD dwUin, DWORD dwMID, DWORD dwMID2, WORD wCookie, char* szMsg, int nMsgLen, BOOL bThruDC)
{
	MCONTACT hContact = HContactFromUIN(dwUin, NULL);
	if (hContact) // user sent us xtraz, he supports it
		SetContactCapabilities(hContact, CAPF_XTRAZ);

	char *szPluginID = getXmlPidItem(szMsg, nMsgLen);
	if (!strcmpnull(szPluginID, "ICQChatRecv"))  // it is a invitation to multi-user chat
		;
	else 
		NetLog_Uni(bThruDC, "Error: Unknown plugin \"%s\" in Xtraz message", szPluginID);

	SAFE_FREE(&szPluginID);
}
示例#4
0
void CIcqProto::SendXtrazNotifyResponse(DWORD dwUin, DWORD dwMID, DWORD dwMID2, WORD wCookie, char* szResponse, int nResponseLen, BOOL bThruDC)
{
	char *szResBody = MangleXml(szResponse, nResponseLen);
	int nBodyLen = strlennull(szResBody) + 21;
	char *szBody = (char*)_alloca(nBodyLen);
	MCONTACT hContact = HContactFromUIN(dwUin, NULL);

	if (hContact != INVALID_CONTACT_ID && !CheckContactCapabilities(hContact, CAPF_XTRAZ)) {
		SAFE_FREE(&szResBody);
		return; // Contact does not support xtraz, do not send anything
	}

	nBodyLen = mir_snprintf(szBody, nBodyLen, "<NR><RES>%s</RES></NR>", szResBody);
	SAFE_FREE(&szResBody);

	// Was request received thru DC and have we a open DC, send through that
	if (bThruDC && IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD, 0))
		icq_sendXtrazResponseDirect(hContact, wCookie, szBody, nBodyLen, MTYPE_SCRIPT_NOTIFY);
	else
		icq_sendXtrazResponseServ(dwUin, dwMID, dwMID2, wCookie, szBody, nBodyLen, MTYPE_SCRIPT_NOTIFY);
}
示例#5
0
void CIcqProto::handleXtrazNotify(DWORD dwUin, DWORD dwMID, DWORD dwMID2, WORD wCookie, char* szMsg, int nMsgLen, BOOL bThruDC)
{
	char *szNotify = strstrnull(szMsg, "<NOTIFY>");
	char *szQuery = strstrnull(szMsg, "<QUERY>");

	MCONTACT hContact = HContactFromUIN(dwUin, NULL);
	if (hContact) // user sent us xtraz, he supports it
		SetContactCapabilities(hContact, CAPF_XTRAZ);

	if (szNotify && szQuery) { // valid request
		char *szWork, *szEnd;
		int nNotifyLen, nQueryLen;

		szNotify += 8;
		szQuery += 7;
		szEnd = strstrnull(szMsg, "</NOTIFY>");
		if (!szEnd) szEnd = szMsg + nMsgLen;
		nNotifyLen = (szEnd - szNotify);
		szEnd = strstrnull(szMsg, "</QUERY>");
		if (!szEnd) szEnd = szNotify;
		szNotify = DemangleXml(szNotify, nNotifyLen);
		nQueryLen = (szEnd - szQuery);
		szQuery = DemangleXml(szQuery, nQueryLen);
		szWork = strstrnull(szQuery, "<PluginID>");
		szEnd = strstrnull(szQuery, "</PluginID>");
#ifdef _DEBUG
		debugLogA("Query: %s", szQuery);
		debugLogA("Notify: %s", szNotify);
#endif
		if (szWork && szEnd) { // this is our plugin
			szWork += 10;
			*szEnd = '\0';

			if (!stricmpnull(szWork, "srvMng") && strstrnull(szNotify, "AwayStat")) {
				char *szSender = strstrnull(szNotify, "<senderId>");
				char *szEndSend = strstrnull(szNotify, "</senderId>");

				if (szSender && szEndSend) {
					szSender += 10;
					*szEndSend = '\0';

					if ((DWORD)atoi(szSender) == dwUin) {
						BYTE dwXId = m_bXStatusEnabled ? getContactXStatus(NULL) : 0;

						if (dwXId && validateStatusMessageRequest(hContact, MTYPE_SCRIPT_NOTIFY)) { // apply privacy rules
							NotifyEventHooks(m_modeMsgsEvent, (WPARAM)MTYPE_SCRIPT_NOTIFY, (LPARAM)dwUin);

							char *tmp = getSettingStringUtf(NULL, DBSETTING_XSTATUS_NAME, "");
							char *szXName = MangleXml(tmp, strlennull(tmp));
							SAFE_FREE(&tmp);

							tmp = getSettingStringUtf(NULL, DBSETTING_XSTATUS_MSG, "");
							char *szXMsg = MangleXml(tmp, strlennull(tmp));
							SAFE_FREE(&tmp);

							int nResponseLen = 212 + strlennull(szXName) + strlennull(szXMsg) + UINMAXLEN + 2;
							char *szResponse = (char*)_alloca(nResponseLen + 1);
							// send response
							mir_snprintf(szResponse, nResponseLen,
								"<ret event=\"OnRemoteNotification\">"
								"<srv><id>cAwaySrv</id>"
								"<val srv_id=\"cAwaySrv\"><Root>"
								"<CASXtraSetAwayMessage></CASXtraSetAwayMessage>"
								"<uin>%d</uin>"
								"<index>%d</index>"
								"<title>%s</title>"
								"<desc>%s</desc></Root></val></srv></ret>",
								m_dwLocalUIN, dwXId, szXName, szXMsg);

							SAFE_FREE(&szXName);
							SAFE_FREE(&szXMsg);

							struct rates_xstatus_response : public rates_queue_item {
							protected:
								virtual rates_queue_item* copyItem(rates_queue_item *aDest = NULL)
								{
									rates_xstatus_response *pDest = (rates_xstatus_response*)aDest;
									if (!pDest)
										pDest = new rates_xstatus_response(ppro, wGroup);

									pDest->bThruDC = bThruDC;
									pDest->dwMsgID1 = dwMsgID1;
									pDest->dwMsgID2 = dwMsgID2;
									pDest->wCookie = wCookie;
									pDest->szResponse = null_strdup(szResponse);

									return rates_queue_item::copyItem(pDest);
								};
							public:
								rates_xstatus_response(CIcqProto *ppro, WORD wGroup) : rates_queue_item(ppro, wGroup), szResponse(NULL) {};
								virtual ~rates_xstatus_response() { if (bCreated) SAFE_FREE(&szResponse); };

								virtual void execute()
								{
									ppro->SendXtrazNotifyResponse(dwUin, dwMsgID1, dwMsgID2, wCookie, szResponse, strlennull(szResponse), bThruDC);
								};

								BOOL bThruDC;
								DWORD dwMsgID1;
								DWORD dwMsgID2;
								WORD wCookie;
								char *szResponse;
							};

							m_ratesMutex->Enter();
							WORD wGroup = m_rates->getGroupFromSNAC(ICQ_MSG_FAMILY, ICQ_MSG_RESPONSE);
							m_ratesMutex->Leave();

							rates_xstatus_response rr(this, wGroup);
							rr.hContact = hContact;
							rr.dwUin = dwUin;
							rr.bThruDC = bThruDC;
							rr.dwMsgID1 = dwMID;
							rr.dwMsgID2 = dwMID2;
							rr.wCookie = wCookie;
							rr.szResponse = szResponse;

							handleRateItem(&rr, RQT_RESPONSE, 0, !bThruDC);
						}
						else if (dwXId)
							debugLogA("Privacy: Ignoring XStatus request");
						else
							debugLogA("Error: We are not in XStatus, skipping");
					}
					else
						debugLogA("Error: Invalid sender information");
				}
				else
					debugLogA("Error: Missing sender information");
			}
			else
				debugLogA("Error: Unknown plugin \"%s\" in Xtraz message", szWork);
		}
		else
			debugLogA("Error: Missing PluginID in Xtraz message");

		SAFE_FREE(&szNotify);
		SAFE_FREE(&szQuery);
	}
	else
		debugLogA("Error: Invalid Xtraz Notify message");
}
void CIcqProto::handleFileAck(PBYTE buf, WORD wLen, DWORD dwUin, DWORD dwCookie, WORD wStatus, char* pszText)
{
	char* pszFileName = NULL;
	DWORD dwFileSize;
	HANDLE hCookieContact;
	WORD wPort;
	WORD wFilenameLength;
	filetransfer* ft;


	// Find the filetransfer that belongs to this response
	if (!FindCookie(dwCookie, &hCookieContact, (void**)&ft))
	{
		NetLog_Direct("Error: Received unexpected file transfer request response");
		return;
	}

	FreeCookie(dwCookie);

	if (hCookieContact != HContactFromUIN(dwUin, NULL))
	{
		NetLog_Direct("Error: UINs do not match in file transfer request response");
		return;
	}

	// If status != 0, a request has been denied
	if (wStatus != 0)
	{
		NetLog_Direct("File transfer denied by %u.", dwUin);
		ProtoBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_DENIED, (HANDLE)ft, 0);

		FreeCookie(dwCookie);

		return;
	}

	if (wLen < 6) 
	{ // sanity check
		NetLog_Direct("Ignoring malformed file transfer request response");
		return;
	}

	// Port to connect to
	unpackWord(&buf, &wPort);
	ft->dwRemotePort = wPort;
	wLen -= 2;

	// Unknown
	buf += 2;
	wLen -= 2;

	// Filename
	unpackLEWord(&buf, &wFilenameLength);
	if (wFilenameLength > 0)
	{
		if (wFilenameLength > wLen - 2)
			wFilenameLength = wLen - 2;
		pszFileName = (char*)_alloca(wFilenameLength+1);
		unpackString(&buf, pszFileName, wFilenameLength);
		pszFileName[wFilenameLength] = '\0';
	}
	wLen = wLen - 2 - wFilenameLength;

	if (wLen >= 4)
	{ // Total filesize
		unpackLEDWord(&buf, &dwFileSize);
		wLen -= 4;
	}
	else
		dwFileSize = 0;

	NetLog_Direct("File transfer ack from %u, port %u, name %s, size %u", dwUin, ft->dwRemotePort, pszFileName, dwFileSize);

	ProtoBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, (HANDLE)ft, 0);

	OpenDirectConnection(ft->hContact, DIRECTCONN_FILE, ft);
}
// pszDescription points to a string with the reason
// buf points to the first data after the string
void CIcqProto::handleFileRequest(PBYTE buf, WORD wLen, DWORD dwUin, DWORD dwCookie, DWORD dwID1, DWORD dwID2, char* pszDescription, int nVersion, BOOL bDC)
{
	BOOL bEmptyDesc = FALSE;
	if (strlennull(pszDescription) == 0) {
		pszDescription = Translate("No description given");
		bEmptyDesc = TRUE;
	}

	// Empty port+pad
	buf += 4;
	wLen -= 4;

	// Filename
	WORD wFilenameLength;
	unpackLEWord(&buf, &wFilenameLength);
	if (!wFilenameLength) {
		NetLog_Direct("Ignoring malformed file send request");
		return;
	}
	
	char *pszFileName = (char*)_alloca(wFilenameLength + 1);
	unpackString(&buf, pszFileName, wFilenameLength);
	pszFileName[wFilenameLength] = '\0';

	wLen = wLen - 2 - wFilenameLength;

	// Total filesize
	DWORD dwFileSize;
	unpackLEDWord(&buf, &dwFileSize);
	wLen -= 4;

	int bAdded;
	HANDLE hContact = HContactFromUIN(dwUin, &bAdded);

	// Initialize a filetransfer struct
	filetransfer *ft = CreateFileTransfer(hContact, dwUin, nVersion);
	ft->dwCookie = dwCookie;
	ft->szFilename = mir_strdup(pszFileName);
	ft->szDescription = 0;
	ft->fileId = -1;
	ft->dwTotalSize = dwFileSize;
	ft->pMessage.dwMsgID1 = dwID1;
	ft->pMessage.dwMsgID2 = dwID2;
	ft->bDC = bDC;
	ft->bEmptyDesc = bEmptyDesc;

	// Send chain event
	TCHAR* ptszFileName = mir_utf8decodeT(pszFileName);

	PROTORECVFILET pre = {0};
	pre.flags = PREF_TCHAR;
	pre.fileCount = 1;
	pre.timestamp = time(NULL);
	pre.tszDescription = mir_utf8decodeT(pszDescription);
	pre.ptszFiles = &ptszFileName;
	pre.lParam = (LPARAM)ft;
	ProtoChainRecvFile(hContact, &pre);

	mir_free(pre.tszDescription);
	mir_free(ptszFileName);
}
void CIcqProto::handleFileTransferPacket(directconnect* dc, PBYTE buf, WORD wLen)
{
	if (wLen < 1)
		return;

	NetLog_Direct("Handling file packet");

	switch (buf[0])
	{
	case PEER_FILE_INIT:   /* first packet of a file transfer */
		if (dc->initialised)
			return;
		if (wLen < 19)
			return;
		buf += 5;  /* id, and unknown 0 */
		dc->type = DIRECTCONN_FILE;
		{
			DWORD dwFileCount;
			DWORD dwTotalSize;
			DWORD dwTransferSpeed;
			WORD wNickLength;
			int bAdded;

			unpackLEDWord(&buf, &dwFileCount);
			unpackLEDWord(&buf, &dwTotalSize);
			unpackLEDWord(&buf, &dwTransferSpeed);
			unpackLEWord(&buf, &wNickLength);

			dc->ft = FindExpectedFileRecv(dc->dwRemoteUin, dwTotalSize);
			if (dc->ft == NULL)
			{
				NetLog_Direct("Unexpected file receive");
				CloseDirectConnection(dc);
				return;
			}
			dc->ft->dwFileCount = dwFileCount;
			dc->ft->dwTransferSpeed = dwTransferSpeed;
			dc->ft->hContact = HContactFromUIN(dc->ft->dwUin, &bAdded);
			dc->ft->dwBytesDone = 0;
			dc->ft->iCurrentFile = -1;
			dc->ft->fileId = -1;        
			dc->ft->hConnection = dc->hConnection;
			dc->ft->dwLastNotify = GetTickCount();

			dc->initialised = 1;

			file_sendTransferSpeed(this, dc);
			file_sendNick(this, dc);
		}
		BroadcastAck(dc->ft->hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, dc->ft, 0);
		break;

	case PEER_FILE_INIT_ACK:
		if (wLen < 8)
			return;
		buf++;
		unpackLEDWord(&buf, &dc->ft->dwTransferSpeed);
		/* followed by nick */
		file_sendNextFile(this, dc);
		break;

	case PEER_FILE_NEXTFILE:
		if (wLen < 20)
			return;
		buf++;  /* id */
		{
	  char *szAnsi;
			WORD wThisFilenameLen, wSubdirLen;
			BYTE isDirectory;

			unpackByte(&buf, &isDirectory);
			unpackLEWord(&buf, &wThisFilenameLen);
			if (wLen < 19 + wThisFilenameLen)
				return;
			SAFE_FREE(&dc->ft->szThisFile);
	  szAnsi = (char *)_malloca(wThisFilenameLen + 1);
			memcpy(szAnsi, buf, wThisFilenameLen);
			szAnsi[wThisFilenameLen] = '\0';
	  dc->ft->szThisFile = ansi_to_utf8(szAnsi);
			buf += wThisFilenameLen;

			unpackLEWord(&buf, &wSubdirLen);
			if (wLen < 18 + wThisFilenameLen + wSubdirLen)
				return;
			SAFE_FREE(&dc->ft->szThisSubdir);
	  szAnsi = (char *)_malloca(wSubdirLen + 1);
			memcpy(szAnsi, buf, wSubdirLen);
			szAnsi[wSubdirLen] = '\0';
			dc->ft->szThisSubdir = ansi_to_utf8(szAnsi);
			buf += wSubdirLen;

			unpackLEDWord(&buf, &dc->ft->dwThisFileSize);
			unpackLEDWord(&buf,  &dc->ft->dwThisFileDate);
			unpackLEDWord(&buf,  &dc->ft->dwTransferSpeed);

			/* no cheating with paths */
			if (!IsValidRelativePath(dc->ft->szThisFile) || !IsValidRelativePath(dc->ft->szThisSubdir))
			{
				NetLog_Direct("Invalid path information");
				break;
			}

			char *szFullPath = (char*)SAFE_MALLOC(strlennull(dc->ft->szSavePath)+strlennull(dc->ft->szThisSubdir)+strlennull(dc->ft->szThisFile)+3);
			strcpy(szFullPath, dc->ft->szSavePath);
			NormalizeBackslash(szFullPath);
			strcat(szFullPath, dc->ft->szThisSubdir);
			NormalizeBackslash(szFullPath);
//			_chdir(szFullPath); // set current dir - not very useful
			strcat(szFullPath, dc->ft->szThisFile);
			// we joined the full path to dest file
			SAFE_FREE(&dc->ft->szThisFile);
			dc->ft->szThisFile = szFullPath;

			dc->ft->dwFileBytesDone = 0;
			dc->ft->iCurrentFile++;

			if (isDirectory)
			{
				MakeDirUtf(dc->ft->szThisFile);
				dc->ft->fileId = -1;
			}
			else
			{
				/* file resume */
				PROTOFILETRANSFERSTATUS pfts = {0};

				file_buildProtoFileTransferStatus(dc->ft, &pfts);
				if (BroadcastAck(dc->ft->hContact, ACKTYPE_FILE, ACKRESULT_FILERESUME, dc->ft, (LPARAM)&pfts))
					break;   /* UI supports resume: it will call PS_FILERESUME */

				dc->ft->fileId = OpenFileUtf(dc->ft->szThisFile, _O_BINARY | _O_CREAT | _O_TRUNC | _O_WRONLY, _S_IREAD | _S_IWRITE);
				if (dc->ft->fileId == -1)
				{
					icq_LogMessage(LOG_ERROR, LPGEN("Your file receive has been aborted because Miranda could not open the destination file in order to write to it. You may be trying to save to a read-only folder."));
					CloseDirectConnection(dc);
					dc->ft->hConnection = NULL;
					break;
				}
			}
		}
		file_sendResume(this, dc);
		BroadcastAck(dc->ft->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, dc->ft, 0);
		break;

	case PEER_FILE_RESUME:
		if (dc->ft->fileId == -1 && !dc->ft->currentIsDir)
			return;
		if (wLen < 13)
			return;
		if (wLen < 17)
			NetLog_Direct("Warning: Received short PEER_FILE_RESUME");
		buf++;
		{
			DWORD dwRestartFrom;

			unpackLEDWord(&buf, &dwRestartFrom);
			if (dwRestartFrom > dc->ft->dwThisFileSize)
				return;
			buf += 4;  /* unknown. 0 */
			unpackLEDWord(&buf, &dc->ft->dwTransferSpeed);
			buf += 4;  /* unknown. 1 */
			if (!dc->ft->currentIsDir)
				_lseek(dc->ft->fileId, dwRestartFrom, 0);
			dc->wantIdleTime = 1;
			dc->ft->dwBytesDone += dwRestartFrom;
			dc->ft->dwFileBytesDone += dwRestartFrom;
		}
		break;

	case PEER_FILE_SPEED:
		if (wLen < 5)
			return;
		buf++;
		unpackLEDWord(&buf, &dc->ft->dwTransferSpeed);
		dc->ft->dwLastNotify = GetTickCount();
		break;

	case PEER_FILE_DATA:
		if (!dc->ft->currentIsDir)
		{
			if (dc->ft->fileId == -1)
				break;
			buf++; wLen--;
			_write(dc->ft->fileId, buf, wLen);
		}
		else
			wLen = 0;
		dc->ft->dwBytesDone += wLen;
		dc->ft->dwFileBytesDone += wLen;
		if (GetTickCount() > dc->ft->dwLastNotify + 500 || wLen < 2048) 
		{
			PROTOFILETRANSFERSTATUS pfts;

			file_buildProtoFileTransferStatus(dc->ft, &pfts);
			BroadcastAck(dc->ft->hContact, ACKTYPE_FILE, ACKRESULT_DATA, dc->ft, (LPARAM)&pfts);
			dc->ft->dwLastNotify = GetTickCount();
		}
		if (wLen < 2048)
		{
			/* EOF */
			if (!dc->ft->currentIsDir)
				_close(dc->ft->fileId);
			dc->ft->fileId = -1;
			if ((DWORD)dc->ft->iCurrentFile == dc->ft->dwFileCount - 1)
			{
				dc->type = DIRECTCONN_CLOSING;     /* this guarantees that we won't accept any more data but that the sender is still free to closesocket() neatly */
				BroadcastAck(dc->ft->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, dc->ft, 0);
			}
		}
		break;

	default:
		NetLog_Direct("Unknown file transfer packet ignored.");
		break;
	}
}