Ejemplo n.º 1
0
void CIcqProto::ReleaseLookupCookie(DWORD dwCookie, cookie_search *pCookie)
{
	FreeCookie(dwCookie);
	SAFE_FREE(&pCookie->szObject);

	if (pCookie->dwMainId && !pCookie->dwStatus)
	{ // we need to wait for main search
		pCookie->dwStatus = 1;
	}
	else
	{ // finish everything
		if (pCookie->dwMainId)
			BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)pCookie->dwMainId, 0);
		else // we are single
			BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)dwCookie, 0);

		SAFE_FREE((void**)&pCookie);
	}
}
Ejemplo n.º 2
0
void CIcqProto::handleLookupEmailReply(BYTE* buf, WORD wLen, DWORD dwCookie)
{
	ICQSEARCHRESULT sr = {0};
	oscar_tlv_chain *pChain;
	cookie_search *pCookie;

	if (!FindCookie(dwCookie, NULL, (void**)&pCookie))
	{
		NetLog_Server("Error: Received unexpected lookup reply");
		return;
	}
	
	NetLog_Server("SNAC(0x0A,0x3): Lookup reply");

	sr.hdr.cbSize = sizeof(sr);
  sr.hdr.flags = PSR_TCHAR;
	sr.hdr.email = ansi_to_tchar(pCookie->szObject);

	// Syntax check, read chain
	if (wLen >= 4 && (pChain = readIntoTLVChain(&buf, wLen, 0)))
	{
		for (WORD i = 1; TRUE; i++)
		{ // collect the results
			char *szUid = pChain->getString(0x01, i);
			if (!szUid) break;
      sr.hdr.id = ansi_to_tchar(szUid);
			sr.hdr.nick = sr.hdr.id;
			// broadcast the result
			if (pCookie->dwMainId)
				BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)pCookie->dwMainId, (LPARAM)&sr);
			else
				BroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)dwCookie, (LPARAM)&sr);
			SAFE_FREE(&sr.hdr.id);
      SAFE_FREE(&szUid);
		}
		disposeChain(&pChain);
	}
  SAFE_FREE(&sr.hdr.email);

	ReleaseLookupCookie(dwCookie, pCookie);
}
Ejemplo n.º 3
0
void CIcqProto::icq_sendFileResume(filetransfer *ft, int action, const char *szFilename)
{
	if (ft->hConnection == NULL)
		return;

	directconnect *dc = FindFileTransferDC(ft);
	if (!dc) return; // something is broken...

	int openFlags;

	switch (action)
	{
	case FILERESUME_RESUME:
		openFlags = _O_BINARY | _O_WRONLY;
		break;

	case FILERESUME_OVERWRITE:
		openFlags = _O_BINARY | _O_CREAT | _O_TRUNC | _O_WRONLY;
		ft->dwFileBytesDone = 0;
		break;

	case FILERESUME_SKIP:
		openFlags = _O_BINARY | _O_WRONLY;
		ft->dwFileBytesDone = ft->dwThisFileSize;
		break;

	case FILERESUME_RENAME:
		openFlags = _O_BINARY | _O_CREAT | _O_TRUNC | _O_WRONLY;
		SAFE_FREE(&ft->szThisFile);
		ft->szThisFile = null_strdup(szFilename);
		ft->dwFileBytesDone = 0;
		break;
	}

	ft->fileId = OpenFileUtf(ft->szThisFile, openFlags, _S_IREAD | _S_IWRITE);
	if (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."));
		NetLib_CloseConnection(&ft->hConnection, FALSE);
		return;
	}

	if (action == FILERESUME_RESUME)
		ft->dwFileBytesDone = _lseek(ft->fileId, 0, SEEK_END);
	else
		_lseek(ft->fileId, ft->dwFileBytesDone, SEEK_SET);

	ft->dwBytesDone += ft->dwFileBytesDone;

	file_sendResume(this, dc);

	BroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ft, 0);
}
Ejemplo n.º 4
0
void CIcqProto::handleRuntimeError(WORD wError)
{
    switch (wError)
    {

    case 0x01:
    {
        BroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_OTHERLOCATION);
        icq_LogMessage(LOG_FATAL, LPGEN("You have been disconnected from the ICQ network because you logged on from another location using the same ICQ number."));
        break;
    }

    default:
        icq_LogFatalParam(LPGEN("Unknown runtime error: 0x%02x"), wError);
        break;
    }
}
Ejemplo n.º 5
0
void CIcqProto::handleLocationFam(BYTE *pBuffer, WORD wBufferLength, snac_header *pSnacHeader)
{
	switch (pSnacHeader->wSubtype) {

	case ICQ_LOCATION_RIGHTS_REPLY: // Reply to CLI_REQLOCATION
		NetLog_Server("Server sent SNAC(x02,x03) - SRV_LOCATION_RIGHTS_REPLY");
		break;

	case ICQ_LOCATION_USR_INFO_REPLY: // AIM user info reply
		handleLocationUserInfoReply(pBuffer, wBufferLength, pSnacHeader->dwRef);
		break;

	case ICQ_ERROR:
		{ 
			WORD wError;
			HANDLE hCookieContact;
			cookie_fam15_data *pCookieData;


			if (wBufferLength >= 2)
				unpackWord(&pBuffer, &wError);
			else 
				wError = 0;

			if (wError == 4)
			{
				if (FindCookie(pSnacHeader->dwRef, &hCookieContact, (void**)&pCookieData) && !getContactUin(hCookieContact) && pCookieData->bRequestType == REQUESTTYPE_PROFILE)
				{
					BroadcastAck(hCookieContact, ACKTYPE_GETINFO, ACKRESULT_FAILED, (HANDLE)1 ,0);

					ReleaseCookie(pSnacHeader->dwRef);
				}
			}

			LogFamilyError(ICQ_LOCATION_FAMILY, wError);
			break;
		}

	default:
		NetLog_Server("Warning: Ignoring SNAC(x%02x,x%02x) - Unknown SNAC (Flags: %u, Ref: %u)", ICQ_LOCATION_FAMILY, pSnacHeader->wSubtype, pSnacHeader->wFlags, pSnacHeader->dwRef);
		break;
	}
}
Ejemplo n.º 6
0
void CIcqProto::handleLocationUserInfoReply(BYTE* buf, WORD wLen, DWORD dwCookie)
{
	HANDLE hContact;
	DWORD dwUIN;
	uid_str szUID;
	WORD wTLVCount;
	WORD wWarningLevel;
	HANDLE hCookieContact;
	WORD status;
	cookie_message_data *pCookieData;

	// Unpack the sender's user ID
	if (!unpackUID(&buf, &wLen, &dwUIN, &szUID)) return;

	// Syntax check
	if (wLen < 4)
		return;

	// Warning level?
	unpackWord(&buf, &wWarningLevel);
	wLen -= 2;

	// TLV count
	unpackWord(&buf, &wTLVCount);
	wLen -= 2;

	// Determine contact
	hContact = HContactFromUID(dwUIN, szUID, NULL);

	// Ignore away status if the user is not already on our list
	if (hContact == INVALID_HANDLE_VALUE)
	{
#ifdef _DEBUG
		NetLog_Server("Ignoring away reply (%s)", strUID(dwUIN, szUID));
#endif
		return;
	}

	if (!FindCookie(dwCookie, &hCookieContact, (void**)&pCookieData))
	{
		NetLog_Server("Error: Received unexpected away reply from %s", strUID(dwUIN, szUID));
		return;
	}

	if (hContact != hCookieContact)
	{
		NetLog_Server("Error: Away reply Contact does not match Cookie Contact(0x%x != 0x%x)", hContact, hCookieContact);

		ReleaseCookie(dwCookie); // This could be a bad idea, but I think it is safe
		return;
	}

	switch (GetCookieType(dwCookie))
	{
	case CKT_FAMILYSPECIAL:
		{
			ReleaseCookie(dwCookie);

			// Read user info TLVs
			{
				oscar_tlv_chain* pChain;
				BYTE *tmp;
				char *szMsg = NULL;

				// Syntax check
				if (wLen < 4)
					return;

				tmp = buf;
				// Get general chain
				if (!(pChain = readIntoTLVChain(&buf, wLen, wTLVCount)))
					return;

				disposeChain(&pChain);

				wLen -= (buf - tmp);

				// Get extra chain
				if (pChain = readIntoTLVChain(&buf, wLen, 2))
				{
					oscar_tlv *pTLV;
					char *szEncoding = NULL;

					// Get Profile encoding TLV
					pTLV = pChain->getTLV(0x01, 1);
					if (pTLV && (pTLV->wLen >= 1))
					{
						szEncoding = (char*)_alloca(pTLV->wLen + 1);
						memcpy(szEncoding, pTLV->pData, pTLV->wLen);
						szEncoding[pTLV->wLen] = '\0';
					}
					// Get Profile info TLV
					pTLV = pChain->getTLV(0x02, 1);
					if (pTLV && (pTLV->wLen >= 1))
					{
						szMsg = (char*)SAFE_MALLOC(pTLV->wLen + 2);
						memcpy(szMsg, pTLV->pData, pTLV->wLen);
						szMsg[pTLV->wLen] = '\0';
						szMsg[pTLV->wLen + 1] = '\0';
						szMsg = AimApplyEncoding(szMsg, szEncoding);
						szMsg = EliminateHtml(szMsg, pTLV->wLen);
					}
					// Free TLV chain
					disposeChain(&pChain);
				}

				setSettingString(hContact, "About", szMsg);
				BroadcastAck(hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE)1 ,0);

				SAFE_FREE((void**)&szMsg);
			}
			break;
		}

	default: // away message
		{
			status = AwayMsgTypeToStatus(pCookieData->nAckType);
			if (status == ID_STATUS_OFFLINE)
			{
				NetLog_Server("SNAC(2.6) Ignoring unknown status message from %s", strUID(dwUIN, szUID));

				ReleaseCookie(dwCookie);
				return;
			}

			ReleaseCookie(dwCookie);

			// Read user info TLVs
			{
				oscar_tlv_chain* pChain;
				oscar_tlv* pTLV;
				BYTE *tmp;
				char *szMsg = NULL;
				CCSDATA ccs;
				PROTORECVEVENT pre;

				// Syntax check
				if (wLen < 4)
					return;

				tmp = buf;
				// Get general chain
				if (!(pChain = readIntoTLVChain(&buf, wLen, wTLVCount)))
					return;

				disposeChain(&pChain);

				wLen -= (buf - tmp);

				// Get extra chain
				if (pChain = readIntoTLVChain(&buf, wLen, 2))
				{
					char* szEncoding = NULL;

					// Get Away encoding TLV
					pTLV = pChain->getTLV(0x03, 1);
					if (pTLV && (pTLV->wLen >= 1))
					{
						szEncoding = (char*)_alloca(pTLV->wLen + 1);
						memcpy(szEncoding, pTLV->pData, pTLV->wLen);
						szEncoding[pTLV->wLen] = '\0';
					}
					// Get Away info TLV
					pTLV = pChain->getTLV(0x04, 1);
					if (pTLV && (pTLV->wLen >= 1))
					{
						szMsg = (char*)SAFE_MALLOC(pTLV->wLen + 2);
						memcpy(szMsg, pTLV->pData, pTLV->wLen);
						szMsg[pTLV->wLen] = '\0';
						szMsg[pTLV->wLen + 1] = '\0';
						szMsg = AimApplyEncoding(szMsg, szEncoding);
						szMsg = EliminateHtml(szMsg, pTLV->wLen);
					}
					// Free TLV chain
					disposeChain(&pChain);
				}

				ccs.szProtoService = PSR_AWAYMSG;
				ccs.hContact = hContact;
				ccs.wParam = status;
				ccs.lParam = (LPARAM)&pre;
				pre.flags = 0;
				pre.szMessage = szMsg?szMsg:(char *)"";
				pre.timestamp = time(NULL);
				pre.lParam = dwCookie;

				CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs);

				SAFE_FREE((void**)&szMsg);
			}
			break;
		}
	}
}
Ejemplo n.º 7
0
void CIcqProto::handleSignonError(WORD wError)
{
    switch (wError) {

    case 0x01: // Unregistered uin
    case 0x04: // Incorrect uin or password
    case 0x05: // Mismatch uin or password
    case 0x06: // Internal Client error (bad input to authorizer)
    case 0x07: // Invalid account
        BroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_WRONGPASSWORD);
        ZeroMemory(m_szPassword, sizeof(m_szPassword));
        icq_LogFatalParam(LPGEN("Connection failed.\nYour ICQ number or password was rejected (%d)."), wError);
        break;

    case 0x02: // Service temporarily unavailable
    case 0x0D: // Bad database status
    case 0x10: // Service temporarily offline
    case 0x12: // Database send error
    case 0x14: // Reservation map error
    case 0x15: // Reservation link error
    case 0x1A: // Reservation timeout
        BroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_NOSERVER);
        icq_LogFatalParam(LPGEN("Connection failed.\nThe server is temporarily unavailable (%d)."), wError);
        break;

    case 0x16: // The users num connected from this IP has reached the maximum
    case 0x17: // The users num connected from this IP has reached the maximum (reserved)
        icq_LogFatalParam(LPGEN("Connection failed.\nServer has too many connections from your IP (%d)."), wError);
        break;

    case 0x18: // Reservation rate limit exceeded
    case 0x1D: // Rate limit exceeded
        BroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_NOSERVER);
        icq_LogFatalParam(LPGEN("Connection failed.\nYou have connected too quickly,\nplease wait and retry 10 to 20 minutes later (%d)."), wError);
        break;

    case 0x1B: // You are using an older version of ICQ. Upgrade required
        BroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_WRONGPROTOCOL);
        icq_LogMessage(LOG_FATAL, LPGEN("Connection failed.\nThe server did not accept this client version."));
        break;

    case 0x1C: // You are using an older version of ICQ. Upgrade recommended
        icq_LogMessage(LOG_WARNING, LPGEN("The server sent warning, this version is getting old.\nTry to look for a new one."));
        break;

    case 0x1E: // Can't register on the ICQ network
        icq_LogMessage(LOG_FATAL, LPGEN("Connection failed.\nYou were rejected by the server for an unknown reason.\nThis can happen if the UIN is already connected."));
        break;

    case 0x0C: // Invalid database fields, MD5 login not supported
        icq_LogMessage(LOG_FATAL, LPGEN("Connection failed.\nSecure (MD5) login is not supported on this account."));
        break;

    case 0:    // No error
        break;

    case 0x08: // Deleted account
    case 0x09: // Expired account
    case 0x0A: // No access to database
    case 0x0B: // No access to resolver
    case 0x0E: // Bad resolver status
    case 0x0F: // Internal error
    case 0x11: // Suspended account
    case 0x13: // Database link error
    case 0x19: // User too heavily warned
    case 0x1F: // Token server timeout
    case 0x20: // Invalid SecureID number
    case 0x21: // MC error
    case 0x22: // Age restriction
    case 0x23: // RequireRevalidation
    case 0x24: // Link rule rejected
    case 0x25: // Missing information or bad SNAC format
    case 0x26: // Link broken
    case 0x27: // Invalid client IP
    case 0x28: // Partner rejected
    case 0x29: // SecureID missing
    case 0x2A: // Blocked account | Bump user

    default:
        icq_LogFatalParam(LPGEN("Connection failed.\nUnknown error during sign on: 0x%02x"), wError);
        break;
    }
}
Ejemplo n.º 8
0
void CIcqProto::handleDirectMessage(directconnect* dc, PBYTE buf, WORD wLen)
{
	WORD wCommand;
	WORD wCookie;
	BYTE bMsgType,bMsgFlags;
	WORD wStatus;
	WORD wFlags;
	WORD wTextLen;
	char* pszText = NULL;


	// The first part of the packet should always be at least 31 bytes
	if (wLen < 31)
	{
		NetLog_Direct("Error during parsing of DC packet 2 PEER_MSG (too short)");
		return;
	}

	// Skip packet checksum
	buf += 4;
	wLen -= 4;

	// Command:
	//   0x07d0 = 2000 - cancel given message.
	//   0x07da = 2010 - acknowledge message.
	//   0x07ee = 2030 - normal message/request.
	unpackLEWord(&buf, &wCommand);
	wLen -= 2;

	// Unknown, always 0xe (14)
	buf += 2;
	wLen -= 2;

	// Sequence number
	unpackLEWord(&buf, &wCookie);
	wLen -=2;

	// Unknown, always zeroes
	buf += 12;
	wLen -= 12;

	// Peer message type
	unpackByte(&buf, &bMsgType);
	// Peer message flags
	unpackByte(&buf, &bMsgFlags);
	wLen -= 2;

	// The current status of the user, or whether the message was accepted or not.
	//   0x00 - user is online, or message was receipt, or file transfer accepted
	//   0x01 - refused
	//   0x04 - auto-refused, because of away
	//   0x09 - auto-refused, because of occupied
	//   0x0a - auto-refused, because of dnd
	//   0x0e - auto-refused, because of na
	unpackLEWord(&buf, &wStatus);
	wLen -= 2;

	// Flags, or priority
	// Seen: 1 - Chat request
	//       0 - File auto accept (type 3)
	//       33 - priority ?
	unpackLEWord(&buf, &wFlags);
	wLen -= 2;

	// Messagetext. This is either the status message or the actual message
	// when this is a PEER_MSG_MSG packet
	unpackLEWord(&buf, &wTextLen);
	if (wTextLen > 0)
	{
		pszText = (char*)_malloca(wTextLen+1);
		unpackString(&buf, pszText, wTextLen);
		pszText[wTextLen] = '\0';
	}
	wLen = (wLen - 2) - wTextLen;

#ifdef _DEBUG
	NetLog_Direct("Handling PEER_MSG '%s', command %u, cookie %u, messagetype %u, messageflags %u, status %u, flags %u", pszText, wCommand, wCookie, bMsgType, bMsgFlags, wStatus, wFlags);
#else
	NetLog_Direct("Message through direct - UID: %u", dc->dwRemoteUin);
#endif

	// The remaining actual message is handled either as a status message request,
	// a greeting message, a acknowledge or a normal (text, url, file) message
	if (wCommand == DIRECT_MESSAGE)
		switch (bMsgType)
	{
		case MTYPE_FILEREQ: // File inits
			handleFileRequest(buf, wLen, dc->dwRemoteUin, wCookie, 0, 0, pszText, 7, TRUE);
			break;

		case MTYPE_AUTOAWAY:
		case MTYPE_AUTOBUSY:
		case MTYPE_AUTONA:
		case MTYPE_AUTODND:
		case MTYPE_AUTOFFC:
			{
				char **szMsg = MirandaStatusToAwayMsg(AwayMsgTypeToStatus(bMsgType));
				if (szMsg)
					icq_sendAwayMsgReplyDirect(dc, wCookie, bMsgType, ( const char** )szMsg);
			}
			break;

		case MTYPE_PLUGIN: // Greeting
			handleDirectGreetingMessage(dc, buf, wLen, wCommand, wCookie, bMsgType, bMsgFlags, wStatus, wFlags, pszText);
			break;

		default: 
			{
				message_ack_params pMsgAck = {0};
		uid_str szUID;

				buf -= wTextLen;
				wLen += wTextLen;

				pMsgAck.bType = MAT_DIRECT;
				pMsgAck.pDC = dc;
				pMsgAck.wCookie = wCookie;
				pMsgAck.msgType = bMsgType;
				pMsgAck.bFlags = bMsgFlags;
				handleMessageTypes(dc->dwRemoteUin, szUID, time(NULL), 0, 0, wCookie, dc->wVersion, (int)bMsgType, (int)bMsgFlags, 0, (DWORD)wLen, wTextLen, (char*)buf, MTF_DIRECT, &pMsgAck);
				break;
			}
	}
	else if (wCommand == DIRECT_ACK)
	{
		if (bMsgFlags == 3)
		{ // this is status reply
	  uid_str szUID;

			buf -= wTextLen;
			wLen += wTextLen;

			handleMessageTypes(dc->dwRemoteUin, szUID, time(NULL), 0, 0, wCookie, dc->wVersion, (int)bMsgType, (int)bMsgFlags, 2, (DWORD)wLen, wTextLen, (char*)buf, MTF_DIRECT, NULL);
		}
		else
		{
			HANDLE hCookieContact;
			cookie_message_data *pCookieData = NULL;

			if (!FindCookie(wCookie, &hCookieContact, (void**)&pCookieData))
			{
				NetLog_Direct("Received an unexpected direct ack");
			}
			else if (hCookieContact != dc->hContact)
			{
				NetLog_Direct("Direct Contact does not match Cookie Contact(0x%x != 0x%x)", dc->hContact, hCookieContact);
				ReleaseCookie(wCookie); // This could be a bad idea, but I think it is safe
			}
			else
			{ // the ack is correct
				int ackType = -1;

				switch (bMsgType)
				{ 
				case MTYPE_PLAIN:
					ackType = ACKTYPE_MESSAGE;
					break;
				case MTYPE_URL:
					ackType = ACKTYPE_URL;
					break;
				case MTYPE_CONTACTS:
					ackType = ACKTYPE_CONTACTS;
					break;

				case MTYPE_FILEREQ: // File acks
					handleFileAck(buf, wLen, dc->dwRemoteUin, wCookie, wStatus, pszText);
					break;

				case MTYPE_PLUGIN: // Greeting
					handleDirectGreetingMessage(dc, buf, wLen, wCommand, wCookie, bMsgType, bMsgFlags, wStatus, wFlags, pszText);
					break;

				default: 
					NetLog_Direct("Skipped packet from direct connection");
					break;
				}
				if (ackType != -1)
				{ // was a good ack to broadcast ?
					BroadcastAck(dc->hContact, ackType, ACKRESULT_SUCCESS, (HANDLE)wCookie, 0);
					ReleaseCookie(wCookie);
				}
			}
		}
	}
	else if (wCommand == DIRECT_CANCEL)
	{
		NetLog_Direct("Cannot handle abort messages yet... :(");
	}
	else
		NetLog_Direct("Unknown wCommand, packet skipped");
}
Ejemplo n.º 9
0
void CIcqProto::handleDirectGreetingMessage(directconnect* dc, PBYTE buf, WORD wLen, WORD wCommand, WORD wCookie, BYTE bMsgType, BYTE bMsgFlags, WORD wStatus, WORD wFlags, char* pszText)
{
	DWORD dwLengthToEnd;
	DWORD dwDataLength;
	char* pszFileName = NULL;
	int typeId;
	WORD qt;

#ifdef _DEBUG
	NetLog_Direct("Handling PEER_MSG_GREETING, command %u, cookie %u, messagetype %u, messageflags %u, status %u, flags %u", wCommand, wCookie, bMsgType, bMsgFlags, wStatus, wFlags);
#endif

	NetLog_Direct("Parsing Greeting message through direct");

	if (!unpackPluginTypeId(&buf, &wLen, &typeId, &qt, TRUE)) return;

	// Length of remaining data
	unpackLEDWord(&buf, &dwLengthToEnd);
	if (dwLengthToEnd < 4 || dwLengthToEnd > wLen)
	{
		NetLog_Direct("Error: Sanity checking failed (%d) in handleDirectGreetingMessage, datalen %u wLen %u", 2, dwLengthToEnd, wLen);
		return;
	}

	// Length of message/reason
	unpackLEDWord(&buf, &dwDataLength);
	wLen -= 4;
	if (dwDataLength > wLen)
	{
		NetLog_Direct("Error: Sanity checking failed (%d) in handleDirectGreetingMessage, datalen %u wLen %u", 3, dwDataLength, wLen);
		return;
	}

	if (typeId == MTYPE_FILEREQ && wCommand == DIRECT_MESSAGE)
	{
		char* szMsg;

		NetLog_Direct("This is file request");
		szMsg = (char*)_malloca(dwDataLength+1);
		unpackString(&buf, szMsg, (WORD)dwDataLength);
		szMsg[dwDataLength] = '\0';
		wLen = wLen - (WORD)dwDataLength;

		handleFileRequest(buf, wLen, dc->dwRemoteUin, wCookie, 0, 0, szMsg, 8, TRUE);
	}
	else if (typeId == MTYPE_FILEREQ && wCommand == DIRECT_ACK)
	{
		char* szMsg;

		NetLog_Direct("This is file ack");
		szMsg = (char*)_malloca(dwDataLength+1);
		unpackString(&buf, szMsg, (WORD)dwDataLength);
		szMsg[dwDataLength] = '\0';
		wLen = wLen - (WORD)dwDataLength;

		// 50 - file request granted/refused
		handleFileAck(buf, wLen, dc->dwRemoteUin, wCookie, wStatus, szMsg);
	}
	else if (typeId && wCommand == DIRECT_MESSAGE)
	{
	uid_str szUID;
		message_ack_params pMsgAck = {0};

		pMsgAck.bType = MAT_DIRECT;
		pMsgAck.pDC = dc;
		pMsgAck.wCookie = wCookie;
		pMsgAck.msgType = typeId;
		handleMessageTypes(dc->dwRemoteUin, szUID, time(NULL), 0, 0, wCookie, dc->wVersion, typeId, 0, 0, dwLengthToEnd, (WORD)dwDataLength, (char*)buf, MTF_PLUGIN | MTF_DIRECT, &pMsgAck);
	}
	else if (typeId == MTYPE_STATUSMSGEXT && wCommand == DIRECT_ACK)
	{ // especially for icq2003b
		NetLog_Direct("This is extended status reply");

		char *szMsg = (char*)_malloca(dwDataLength+1);
	uid_str szUID;
		unpackString(&buf, szMsg, (WORD)dwDataLength);
		szMsg[dwDataLength] = '\0';

		handleMessageTypes(dc->dwRemoteUin, szUID, time(NULL), 0, 0, wCookie, dc->wVersion, (int)(qt + 0xE7), 3, 2, (DWORD)wLen, (WORD)dwDataLength, szMsg, MTF_PLUGIN | MTF_DIRECT, NULL);
	}
	else if (typeId && wCommand == DIRECT_ACK)
	{
		HANDLE hCookieContact;
		cookie_message_data *pCookieData = NULL;

		if (!FindCookie(wCookie, &hCookieContact, (void**)&pCookieData))
		{
			NetLog_Direct("Received an unexpected direct ack");
		}
		else if (hCookieContact != dc->hContact)
		{
			NetLog_Direct("Direct Contact does not match Cookie Contact(0x%x != 0x%x)", dc->hContact, hCookieContact);
			ReleaseCookie(wCookie); // This could be a bad idea, but I think it is safe
		}
		else
		{
			int ackType = -1;

			switch (typeId)
			{
			case MTYPE_MESSAGE:
				ackType = ACKTYPE_MESSAGE;
				break;
			case MTYPE_URL:
				ackType = ACKTYPE_URL;
				break;
			case MTYPE_CONTACTS:
				ackType = ACKTYPE_CONTACTS;
				break;
			case MTYPE_SCRIPT_NOTIFY:
				{
					char *szMsg;

					szMsg = (char*)_malloca(dwDataLength + 1);
					if (dwDataLength > 0)
						memcpy(szMsg, buf, dwDataLength);
					szMsg[dwDataLength] = '\0';

					handleXtrazNotifyResponse(dc->dwRemoteUin, dc->hContact, wCookie, szMsg, dwDataLength);
				}
				break;

			default:
				NetLog_Direct("Skipped packet from direct connection");
				break;
			}

			if (ackType != -1)
			{ // was a good ack to broadcast ?
				BroadcastAck(dc->hContact, ackType, ACKRESULT_SUCCESS, (HANDLE)wCookie, 0);
			}
			// Release cookie
			ReleaseCookie(wCookie);
		}
	}
	else
		NetLog_Direct("Unsupported plugin message type %s", typeId);
}
Ejemplo n.º 10
0
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;
	}
}