Beispiel #1
0
static void ReportSslError(SECURITY_STATUS scRet, int line, bool = false)
{
	TCHAR szMsgBuf[256];
	switch (scRet) {
	case 0:
	case ERROR_NOT_READY:
		return;

	case SEC_E_INVALID_TOKEN:
		_tcsncpy_s(szMsgBuf, TranslateT("Client cannot decode host message. Possible causes: host does not support SSL or requires not existing security package"), _TRUNCATE);
		break;

	case CERT_E_CN_NO_MATCH:
	case SEC_E_WRONG_PRINCIPAL:
		_tcsncpy_s(szMsgBuf, TranslateT("Host we are connecting to is not the one certificate was issued for"), _TRUNCATE);
		break;

	default:
		FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, scRet, LANG_USER_DEFAULT, szMsgBuf, _countof(szMsgBuf), NULL);
	}

	TCHAR szMsgBuf2[512];
	mir_sntprintf(szMsgBuf2, _T("SSL connection failure (%x %u): %s"), scRet, line, szMsgBuf);

	char* szMsg = Utf8EncodeT(szMsgBuf2);
	SslLog(szMsg);
	mir_free(szMsg);

	SetLastError(scRet);
	PUShowMessageT(szMsgBuf2, SM_WARNING);
}
Beispiel #2
0
int StartServer()
{
	int failure = 1;
	if (sdCmdLine)
	{
		if (sdCmdLine->instances == 0)
		{
			HANDLE server = mir_forkthread(ServerWorkerThread);
			if (server)
			{
				wchar_t path[MIMFOLDER_SIZE];
				GetModuleFileNameW(GetModuleHandle(nullptr), path, _countof(path));
				wchar_t *p = wcsrchr(path, '\\');
				if (p) *p = 0;
				wcsncpy_s(sdCmdLine->mimFolder, path, _TRUNCATE);
				sdCmdLine->instances++;

				failure = 0;
			}
			else PUShowMessageT(TranslateT("Could not create CommandLine listening server!"), SM_WARNING);
		}
		else MessageBox(nullptr, TranslateT("You can only run one instance of CmdLine plugin."), TranslateT("Error"), MB_ICONERROR | MB_OK);
	}

	return failure;
}
void TlenGetAvatarFileName(TlenProtocol *proto, TLEN_LIST_ITEM *item, TCHAR* ptszDest, int cbLen)
{
	
	int tPathLen = mir_sntprintf(ptszDest, cbLen, TEXT("%s\\%S"), VARST( TEXT("%miranda_avatarcache%")), proto->m_szModuleName);
	if (_taccess(ptszDest, 0)) {
		int ret = CreateDirectoryTreeT(ptszDest);
		if (ret == 0)
			proto->debugLog(_T("getAvatarFilename(): Created new directory for avatar cache: %s."), ptszDest);
		else {
			proto->debugLog(_T("getAvatarFilename(): Can not create directory for avatar cache: %s. errno=%d: %s"), ptszDest, errno, strerror(errno));
			TCHAR buffer[512];
			mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("Cannot create avatars cache directory. ERROR: %d: %s\n%s"), errno, _tcserror(errno), ptszDest);
			PUShowMessageT(buffer, SM_WARNING);
		}
	}

	int format = PA_FORMAT_PNG;

	ptszDest[ tPathLen++ ] = '\\';
	if (item != NULL)
		format = item->avatarFormat;
	else if (proto->threadData != NULL)
		format = proto->threadData->avatarFormat;
	else
		format = db_get_dw(NULL, proto->m_szModuleName, "AvatarFormat", PA_FORMAT_UNKNOWN);

	const TCHAR *tszFileType = ProtoGetAvatarExtension(format);
	if ( item != NULL )
		mir_sntprintf(ptszDest + tPathLen, MAX_PATH - tPathLen, TEXT("%S%s"), ptrA( TlenSha1(item->jid)), tszFileType);
	else
		mir_sntprintf(ptszDest + tPathLen, MAX_PATH - tPathLen, TEXT("%S_avatar%s"), proto->m_szModuleName, tszFileType);
}
Beispiel #4
0
void ShowError(wchar_t *msg) {
	wchar_t buffer[512];
	ErrorDisplay disp = options.err_method;
	// funny logic :) ... try to avoid message boxes
	// if want popups but no popups, try baloons
	if(disp == ED_POP && !options.bHavePopups)
		disp = ED_BAL;

	mir_snwprintf(buffer, L"%s Error", _A2W(MODULENAME));

	wchar_t *message;
	switch (disp) {
	case ED_POP:
		{
			int size = int(mir_wstrlen(msg) + 515);
			message = new wchar_t[size]; // newline and null terminator
			mir_snwprintf(message, size, L"%s\r\n%s", buffer, msg);
			PUShowMessageT(message, SM_WARNING);
			delete[] message;
		}
		break;
	case ED_MB:
		MessageBox(nullptr, msg, buffer, MB_OK | MB_ICONERROR);
		break;
	case ED_BAL:
		Clist_TrayNotifyW(MODULENAME, buffer, msg, NIIF_ERROR, 10000);
		break;
	}
}
boolean checkUploadAvatarResponse(TlenProtocol *proto, NETLIBHTTPREQUEST *resp){
	if (resp == NULL){
		proto->debugLogA("Error while setting avatar on Tlen account (no response)");
		PUShowMessageT(TranslateT("Error while setting avatar on Tlen account (no response)"), SM_WARNING);
		return false;
	}
	if (resp->resultCode != 200 || !resp->dataLength || !resp->pData) {
		proto->debugLogA("Error while setting avatar on Tlen account (invalid response) resultCode=%d, dataLength=%d", resp->resultCode, resp->dataLength);
		PUShowMessageT(TranslateT("Error while setting avatar on Tlen account (invalid response)"), SM_WARNING);
		return false;
	}
	if (strncmp(resp->pData, "<ok", 3)){
		proto->debugLogA("Error while setting avatar on Tlen account: %s", resp->pData);
		PUShowMessageT(TranslateT("Error while setting avatar on Tlen account"), SM_WARNING);
		return false;
	}
	return true;
}
Beispiel #6
0
void PopupPreview()
{
	TCHAR *lptzTitle1Eng = TranslateT("The Jabberwocky");
	TCHAR *lptzText1Eng = TranslateT("`Twas brillig, and the slithy toves\r\nDid gyre and gimble in the wabe:\r\nAll mimsy were the borogoves,\r\nAnd the mome raths outgrabe.\r\n\t[b][i]Lewis Carroll, 1855[/i][/b]");

	TCHAR *lptzTitle2 = TranslateT("Test preview for the popup plugin settings. This is supposed to be long enough not to fit in one line...");
	TCHAR *lptzText2 = TranslateTS(
		LPGENT("This is a special test preview for the popup plugin settings. The text and title are quite long so you can tweak your skin and plugin settings to best fit your needs :)")
		);

	POPUPDATA2 ppd = { 0 };

	memset(&ppd, 0, sizeof(ppd));
	ppd.cbSize = sizeof(ppd);
	ppd.flags = PU2_TCHAR;

	ppd.lptzTitle = lptzTitle1Eng;
	ppd.lptzText = lptzText1Eng;
	ppd.lchIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE);
	CallService(MS_POPUP_ADDPOPUP2, (WPARAM)&ppd, APF_NO_HISTORY);
	if (PopupOptions.UseAnimations || PopupOptions.UseEffect) Sleep((ANIM_TIME * 2) / 3); // Pause

	memset(&ppd, 0, sizeof(ppd));
	ppd.cbSize = sizeof(ppd);
	ppd.flags = PU2_TCHAR;
	ppd.lptzTitle = lptzTitle2;
	ppd.lptzText = lptzText2;
	ppd.lchIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
	ppd.hbmAvatar = hbmNoAvatar;

	CallService(MS_POPUP_ADDPOPUP2, (WPARAM)&ppd, APF_NO_HISTORY);
	if (PopupOptions.UseAnimations || PopupOptions.UseEffect) Sleep((ANIM_TIME * 2) / 3); // Pause

	PUShowMessageT(TranslateT("This is a notification message"), (DWORD)SM_NOTIFY | 0x80000000);
	if (PopupOptions.UseAnimations || PopupOptions.UseEffect) Sleep((ANIM_TIME * 2) / 3); // Pause

	PUShowMessageT(TranslateT("This is a warning message"), (DWORD)SM_WARNING | 0x80000000);
	if (PopupOptions.UseAnimations || PopupOptions.UseEffect) Sleep((ANIM_TIME * 2) / 3); // Pause

	PUShowMessageT(TranslateT("This is an error message"), (DWORD)SM_ERROR | 0x80000000);
}
Beispiel #7
0
int MyPUShowMessage(TCHAR *lpzText, BYTE kind)
{
	if (ServiceExists(MS_POPUP_SHOWMESSAGE))
	{
		return PUShowMessageT(lpzText, kind);
	}
	else{
		TCHAR *title = (kind == SM_NOTIFY) ? TranslateT("Notify") : TranslateT("Warning");
		
		return MessageBox(NULL, lpzText, title, MB_OK | (kind == SM_NOTIFY) ? MB_ICONINFORMATION : MB_ICONEXCLAMATION);
	}
}
Beispiel #8
0
int WeatherError(WPARAM wParam, LPARAM lParam) 
{
	if ( !opt.UsePopup)
		return 0;

	TCHAR* tszMsg = ( TCHAR* )wParam;

	if ((DWORD)lParam == SM_WARNING)
		PUShowMessageT( tszMsg, SM_WARNING );
	else if ((DWORD)lParam == SM_NOTIFY)
		PUShowMessageT( tszMsg, SM_NOTIFY);
	else if ((DWORD)lParam == SM_WEATHERALERT) 
	{
		POPUPDATAT ppd = {0};
		TCHAR *chop, str1[512], str2[512];

		// get the 2 strings
		_tcscpy(str1, tszMsg);
		_tcscpy(str2, tszMsg);
		chop = _tcschr(str1, 255);
		if (chop != NULL)	*chop = '\0';
		else				str1[0] = 0;
		chop = _tcschr(str2, 255);
		if (chop != NULL)	_tcscpy(str2, chop+1);
		else				str2[0] = 0;

		// setup the popup
		ppd.lchIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(OIC_BANG), IMAGE_ICON, 
			GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
		_tcscpy(ppd.lptzContactName, str1);
		_tcscpy(ppd.lptzText, str2);
		ppd.colorBack = (opt.UseWinColors)?GetSysColor(COLOR_BTNFACE):opt.BGColour;
		ppd.colorText = (opt.UseWinColors)?GetSysColor(COLOR_WINDOWTEXT):opt.TextColour;
		ppd.iSeconds = opt.pDelay;
		PUAddPopupT( &ppd );
	}
	return 0;
}
Beispiel #9
0
void ShowError(TCHAR *msg) {
	TCHAR buffer[512];
	ErrorDisplay disp = options.err_method;
	// funny logic :) ... try to avoid message boxes
	// if want baloons but no balloons, try popups
	// if want popups but no popups, try baloons
	// if, after that, you want balloons but no balloons, revert to message boxes
	if(disp == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) disp = ED_POP;
	if(disp == ED_POP && !options.bHavePopups) disp = ED_BAL;
	if(disp == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) disp = ED_MB;

	mir_sntprintf(buffer, SIZEOF(buffer), _T("%s Error"), _T(MODULENAME));


	TCHAR *message;
	switch(disp) {
		case ED_POP:
			{
				int size = int(_tcslen(msg) + 515);
				message = new TCHAR[size]; // newline and null terminator
				mir_sntprintf(message, size, _T("%s\r\n%s"), buffer, msg);
				PUShowMessageT(message, SM_WARNING);
				delete message;
			}
			break;
		case ED_MB:
			MessageBox(0, msg, buffer, MB_OK | MB_ICONERROR);
			break;
		case ED_BAL:
			{
				MIRANDASYSTRAYNOTIFY sn = {0};
				sn.cbSize = sizeof(sn);
				sn.szProto = MODULENAME;
				sn.tszInfoTitle = buffer;
				sn.tszInfo = msg;

				sn.dwInfoFlags = NIIF_ERROR | NIIF_INTERN_UNICODE;

				sn.uTimeout = 10;

				CallService(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM)&sn);
			}

			break;
	}
}
static void SetAvatar(TlenProtocol *proto, HANDLE hContact, TLEN_LIST_ITEM *item, char *data, int len, DWORD format) {
	TCHAR filename[MAX_PATH];
	char md5[33];
	mir_md5_state_t ctx;
	DWORD digest[4];

	if (format == PA_FORMAT_UNKNOWN && len > 4)
		format = ProtoGetBufferFormat(data);

	mir_md5_init( &ctx );
	mir_md5_append( &ctx, ( BYTE* )data, len);
	mir_md5_finish( &ctx, ( BYTE* )digest );

	sprintf( md5, "%08x%08x%08x%08x", (int)htonl(digest[0]), (int)htonl(digest[1]), (int)htonl(digest[2]), (int)htonl(digest[3])); //!!!!!!!!!!!!!!
	if (item != NULL) {
		char *hash = item->avatarHash;
		item->avatarFormat = format;
		item->avatarHash = mir_strdup(md5);
		mir_free(hash);
	} else {
		proto->threadData->avatarFormat = format;
		strcpy(proto->threadData->avatarHash, md5);
	}
	TlenGetAvatarFileName(proto, item, filename, sizeof filename );
	DeleteFile(filename);
	FILE *out = _tfopen(filename, TEXT("wb") );
	if (out != NULL) {
		fwrite(data, len, 1, out);
		fclose(out);
		db_set_ts(hContact, "ContactPhoto", "File", filename );
		db_set_s(hContact, proto->m_szModuleName, "AvatarHash",  md5);
		db_set_dw(hContact, proto->m_szModuleName, "AvatarFormat",  format);
	} else {
		TCHAR buffer[128];
		mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("Can not save new avatar file \"%s\" Error:\n\t%s (Error: %d)"), filename, _tcserror(errno), errno);
		PUShowMessageT(buffer, SM_WARNING);
		proto->debugLog(buffer);
		return;
	}
	ProtoBroadcastAck( proto->m_szModuleName, hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL , 0);
}
void MirandaUtils::setStatusOnAccount(ActionThreadArgStruct* args)
{

	logger->log(L"MirandaUtils::setStatusOnAccount: start");
	int status = CallProtoService(args->accountSzModuleName, PS_GETSTATUS, 0, 0);
	logger->log_p(L"SSOA: on account: [%S]  targetHandle = [" SCNuPTR L"]   at status = [%d]", args->accountSzModuleName, args->targetHandle, status);

	int result = -1;

	if (!(CallProtoService(args->accountSzModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_INDIVMODEMSG)){
		result = CallProtoService(args->accountSzModuleName, PS_SETAWAYMSGW, (WPARAM)status, (LPARAM)args->userActionSelection);
		if (result == CALLSERVICE_NOTFOUND){
			char *szMsg = mir_u2a(args->userActionSelection);
			result = CallProtoService(args->accountSzModuleName, PS_SETAWAYMSG, (WPARAM)status, (LPARAM)szMsg);
			mir_free(szMsg);
		}
	}

	MirandaAccount* mirandaAccount = args->mirfoxDataPtr->getMirandaAccountPtrBySzModuleName(args->accountSzModuleName);
	TCHAR* tszAccountName = NULL;
	if (mirandaAccount){
		tszAccountName = mirandaAccount->tszAccountName;
	}

	wchar_t* buffer = new wchar_t[1024 * sizeof(wchar_t)];
	if(result == 0){

		if (tszAccountName != NULL){
			logger->log_p(L"SSOA: Status message set on [%s]", tszAccountName);
			mir_sntprintf(buffer, 1024, TranslateT("Status message set on %s"), tszAccountName);
		} else {
			logger->log(L"SSOA: Status message set");
			buffer = mir_wstrdup(TranslateT("Status message set"));
		}

		if(ServiceExists(MS_POPUP_ADDPOPUPCLASS)) {
			ShowClassPopupT("MirFox_Notify", TranslateT("MirFox"), buffer);
		} else {
			PUShowMessageT(buffer, SM_NOTIFY);
		}

	} else {

		if (tszAccountName != NULL){
			logger->log_p(L"SSOA: ERROR - Cannot set status message 2 on [%s] - result = [%d] ", tszAccountName, result);
			mir_sntprintf(buffer, 1024, TranslateT("Cannot set status message on %s"), tszAccountName);
		} else {
			logger->log_p(L"SSOA: ERROR - Cannot set status message 2 - result = [%d] ", result);
			buffer = mir_wstrdup(TranslateT("Cannot set status message"));
		}

		if(ServiceExists(MS_POPUP_ADDPOPUPCLASS)) {
			ShowClassPopupT("MirFox_Error", TranslateT("MirFox error"), buffer);
		} else {
			PUShowMessageT(buffer, SM_WARNING);
		}

	}
	delete buffer;

}
void MirandaUtils::sendMessage(ActionThreadArgStruct* args, MFENUM_SEND_MESSAGE_MODE mode)
{

	logger->log_p(L"MirandaUtils::sendMessage: mode = [%d]  to = [" SCNuPTR L"]  msg = [%s]", mode, args->targetHandle, args->userActionSelection );

	if (mode == MFENUM_SMM_ONLY_SEND || mode == MFENUM_SMM_SEND_AND_SHOW_MW){

		//TODO - metacontacts support - C:\MIRANDA\SOURCES\PLUGINS\popup_trunk\src\popup_wnd2.cpp : 1083
		//	//check for MetaContact and get szProto from subcontact
		//	if(strcmp(targetHandleSzProto, gszMetaProto)==0) {
		//		HANDLE hSubContact = (HANDLE)CallService(MS_MC_GETDEFAULTCONTACT, (WPARAM)hContact, 0);
		//		if(!hSubContact) return FALSE;
		//		targetHandleSzProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hSubContact, 0);
		//	}

		char* targetHandleSzProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)args->targetHandle, 0); //targetHandleSzProto doesnt need mir_free or delete
		if (targetHandleSzProto == NULL){
			logger->log(L"MirandaUtils::sendMessageToContact: ERROR targetHandleSzProto == NULL");
			return;
		}

		int mirandaSendModeFlag = getMirandaSendModeFlag(targetHandleSzProto);

		char* msgBuffer = NULL;
		std::size_t bufSize = 0;

		if (mirandaSendModeFlag == PREF_UTF){

			msgBuffer = mir_utf8encodeW(args->userActionSelection);
			bufSize = strlen(msgBuffer) + 1;

		} else if (mirandaSendModeFlag == PREF_UNICODE){

			msgBuffer = mir_t2a(args->userActionSelection);
			bufSize = strlen(msgBuffer) + 1;
			size_t bufSizeT = (wcslen(args->userActionSelection) + 1) * sizeof(wchar_t);
			msgBuffer = (char*)mir_realloc(msgBuffer, bufSizeT + bufSize);
			memcpy((wchar_t*)&msgBuffer[bufSize], args->userActionSelection, bufSizeT);
			bufSize += bufSizeT;

		}

		logger->log_p(L"SMTC: mirandaSendModeFlag = [%d]  bufSize = [%d]", mirandaSendModeFlag, bufSize);
		HANDLE hProcess = sendMessageMiranda(args->targetHandle, mirandaSendModeFlag, msgBuffer);
		logger->log_p(L"SMTC: hProcess = [" SCNuPTR L"]", hProcess);

		MIRFOXACKDATA* myMfAck = NULL;

		if (hProcess != NULL){
			//if hProcess of sending process is null there will not be any ack

			EnterCriticalSection(&ackMapCs);
			ackMap[hProcess] = (MIRFOXACKDATA*)NULL;
			LeaveCriticalSection(&ackMapCs);

			int counter = 0;
			const int ACK_WAIT_TIME = 250;			//[ms]
			const int MAX_ACK_WAIT_COUNTER = 40;	//40 * 250ms = 10s

			do {
				SleepEx(ACK_WAIT_TIME, TRUE);
				counter++;
				EnterCriticalSection(&ackMapCs);
				myMfAck = ackMap[hProcess];
				LeaveCriticalSection(&ackMapCs);
				if(Miranda_Terminated() || args->mirfoxDataPtr->Plugin_Terminated){
					logger->log_p(L"SMTC: ACK break by Plugin_Terminated (=%d) or Miranda_Terminated()", args->mirfoxDataPtr->Plugin_Terminated);
					break;
				}
			} while (myMfAck == NULL && counter <= MAX_ACK_WAIT_COUNTER); //TODO or Plugin_Terminated or Miranda_Terminated()

			logger->log_p(L"SMTC: ACK found  counter = [%d]   myMfAck = [" SCNuPTR L"]", counter, myMfAck);

		}


		MirandaContact* mirandaContact = args->mirfoxDataPtr->getMirandaContactPtrByHandle(args->targetHandle);
		const wchar_t* contactNameW = NULL;
		TCHAR* tszAccountName = NULL;
		if (mirandaContact){
			contactNameW = mirandaContact->contactNameW.c_str();
			MirandaAccount* mirandaAccount = mirandaContact->mirandaAccountPtr;
			if (mirandaAccount){
				tszAccountName = mirandaAccount->tszAccountName;
			}
		}

		if(myMfAck != NULL && myMfAck->result == ACKRESULT_SUCCESS){

			addMessageToDB(args->targetHandle, mirandaSendModeFlag, msgBuffer, bufSize, targetHandleSzProto);

			if (mode == MFENUM_SMM_ONLY_SEND){

				//show notyfication popup (only in SMM_ONLY_SEND mode)
				wchar_t* buffer = new wchar_t[1024 * sizeof(wchar_t)];
				if (contactNameW != NULL && tszAccountName != NULL){
					mir_sntprintf(buffer, 1024, TranslateT("Message sent to %s (%s)"), contactNameW, tszAccountName);
				} else {
					buffer = mir_wstrdup(TranslateT("Message sent"));
				}

				if(ServiceExists(MS_POPUP_ADDPOPUPCLASS)) {
					ShowClassPopupT("MirFox_Notify", TranslateT("MirFox"), buffer);
				} else {
					PUShowMessageT(buffer, SM_NOTIFY);
				}

				delete buffer;

			} else if (mode == MFENUM_SMM_SEND_AND_SHOW_MW){

				//notify hook to open window
				if (args->mirfoxDataPtr != NULL && args->mirfoxDataPtr->hhook_EventOpenMW != NULL){

					OnHookOpenMvStruct* onHookOpenMv = new(OnHookOpenMvStruct);
					onHookOpenMv->targetHandle = args->targetHandle;
					onHookOpenMv->msgBuffer = NULL;
					NotifyEventHooks(args->mirfoxDataPtr->hhook_EventOpenMW, (WPARAM)onHookOpenMv, (LPARAM)NULL);

				} else {

					logger->log(L"SMTC: ERROR1 args->mirfoxDataPtr == NULL || args->mirfoxDataPtr->hhook_EventOpenMW == NULL");

				}

			}

		} else {

			//error - show error popup
			wchar_t* buffer = new wchar_t[1024 * sizeof(wchar_t)];
			if (myMfAck != NULL){
				logger->log_p(L"SMTC: ERROR - Cannot send message - result = [%d] ", myMfAck->result);
				if (myMfAck->errorDesc != NULL){
					if (contactNameW != NULL && tszAccountName != NULL){
						mir_sntprintf(buffer, 1024, TranslateT("Cannot send message to %s (%s) - %S"), contactNameW, tszAccountName, myMfAck->errorDesc);
					} else {
						mir_sntprintf(buffer, 1024, TranslateT("Cannot send message - %S"), myMfAck->errorDesc);
					}
				} else {
					if (contactNameW != NULL && tszAccountName != NULL){
						mir_sntprintf(buffer, 1024, TranslateT("Cannot send message to %s (%s)"), contactNameW, tszAccountName);
					} else {
						buffer = mir_wstrdup(TranslateT("Cannot send message - %S"));
					}
				}

			} else {
				logger->log(L"SMTC: ERROR - Cannot send message 2");
				if (contactNameW != NULL && tszAccountName != NULL){
					mir_sntprintf(buffer, 1024, TranslateT("Cannot send message to %s (%s)"), contactNameW, tszAccountName);
				} else {
					buffer = mir_wstrdup(TranslateT("Cannot send message"));
				}
			}

			if(ServiceExists(MS_POPUP_ADDPOPUPCLASS)) {
				ShowClassPopupT("MirFox_Error", TranslateT("MirFox error"), buffer);
			} else {
				PUShowMessageT(buffer, SM_WARNING);
			}

			delete buffer;

		}

		if (myMfAck != NULL){ //when we found ack, not when we exceed MAX_ACK_WAIT_COUNTER
			if (myMfAck->errorDesc != NULL) delete myMfAck->errorDesc;
			delete myMfAck->szModule;
			delete myMfAck;
		}
		EnterCriticalSection(&ackMapCs);
		ackMap.erase(hProcess);
		LeaveCriticalSection(&ackMapCs);

		mir_free(msgBuffer);

	} else if (mode == MFENUM_SMM_ONLY_SHOW_MW){

		//notify hook to open window
		if (args->mirfoxDataPtr != NULL && args->mirfoxDataPtr->hhook_EventOpenMW != NULL){

			OnHookOpenMvStruct* onHookOpenMv = new(OnHookOpenMvStruct);
			onHookOpenMv->targetHandle = args->targetHandle;
			//adding newline to message in Message Window, only in this mode
			std::wstring* msgBuffer = new std::wstring(); //deleted at on_hook_OpenMW
			msgBuffer->append(args->userActionSelection);
			msgBuffer->append(L"\r\n");
			onHookOpenMv->msgBuffer = msgBuffer;
			NotifyEventHooks(args->mirfoxDataPtr->hhook_EventOpenMW, (WPARAM)onHookOpenMv, (LPARAM)NULL);

		} else {
			logger->log(L"SMTC: ERROR1 args->mirfoxDataPtr == NULL || args->mirfoxDataPtr->hhook_EventOpenMW == NULL");
		}

	}

}
bool UpdateXMLData(const Category cat, const char *redirect_url /*= 0*/, int recurse_count /*=0*/) {
	
	if(recurse_count > MAX_REDIRECT_RECURSE) {
		PUShowMessageT(TranslateT("Updater: Error getting data - too many redirects"), SM_WARNING);
		return false;
	}

	NETLIBHTTPREQUEST req = {0};
	NETLIBHTTPHEADER etag_hdr = {0};

	if(OldXMLDataExists(cat)) {
		// ensure backend not checked more than once every MIN_XMLDATA_AGE hours
		long age = OldXMLDataAge(cat);
		if(age >= 0 && age < MIN_XMLDATA_AGE)	{	// get it only if our file is at least 8 hours old
#ifdef DEBUG_HTTP_POPUPS
			char buff[512];
			sprintf(buff, "XML Data is recent (%d hours old) - not downloading, using local copy", age);
			PUShowMessage(buff, SM_NOTIFY);
#endif

			return LoadOldXMLData(cat, false);
		}

		// add ETag header for conditional get
		DBCONTACTGETSETTING cgs;
		DBVARIANT dbv;
		cgs.szModule = MODULE;
		char buff[256];
		strcpy(buff, "DataETag_");
		strcat(buff, category_files[cat]);
		cgs.szSetting = buff;
		cgs.pValue = &dbv;
		if(!CallService(MS_DB_CONTACT_GETSETTING, 0, (LPARAM)&cgs)) {
			req.headersCount = 1;
			req.headers = &etag_hdr;
			etag_hdr.szName = "If-None-Match";
			etag_hdr.szValue = _strdup(dbv.pszVal);
			DBFreeVariant(&dbv);
		}
	}

	req.cbSize = sizeof(req);
	req.requestType = REQUEST_GET;
	char URL[MAX_PATH];
	if(!redirect_url) {
		strcpy(URL, MIM_BACKEND_URL_PREFIX);
		strcat(URL, category_files[cat]);
		strcat(URL, ".bz2");
	} else {
		strcpy(URL, redirect_url);
	}
	req.szUrl = URL;
	req.flags = NLHRF_HTTP11;
	req.nlc = hNetlibHttp;

	if (CallService(MS_SYSTEM_GETVERSION, 0, 0) >= PLUGIN_MAKE_VERSION(0,9,0,5))
		req.flags |= NLHRF_PERSISTENT | NLHRF_REDIRECT;

	NETLIBHTTPREQUEST *resp = (NETLIBHTTPREQUEST *)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hNetlibUser, (LPARAM)&req);
	free(etag_hdr.szValue);

	if (!resp) 
	{
		hNetlibHttp = NULL;
		if (!Miranda_Terminated())
		{
			int err = GetLastError();
			if (err) 
			{
				TCHAR buff[512];
				int len = mir_sntprintf(buff, SIZEOF(buff), TranslateT("Failed to download XML data: "));
				FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, err, 0, buff + len, 512 - len, 0);
				ShowError(buff);
				//MessageBox(0, buff + len, TranslateT("Updater: Error Downloading XML Data"), MB_OK | MB_ICONWARNING);
			} 
			else 
			{
				ShowError(TranslateT("Failed to download XML data - Response is NULL"));
				//MessageBox(0, TranslateT("Error downloading XML data...\nResponse is NULL"), TranslateT("Updater Error"), MB_OK | MB_ICONWARNING);
				NLog("Failed to download XML data - Response is NULL");
			}
		}
		return LoadOldXMLData(cat, false);
	} 
	else if (resp->resultCode == 304) { // 'Not Modified' response
		hNetlibHttp = resp->nlc;
		CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)resp);
		resp = 0;
#ifdef DEBUG_HTTP_POPUPS
		PUShowMessage("XML Data unchanged - using local copy", SM_NOTIFY);
#endif

		// mark data as current
		return LoadOldXMLData(cat, true);
	} else if(resp->resultCode >= 300 && resp->resultCode < 400) { // redirect response
		hNetlibHttp = resp->nlc;
		// get new location
		bool ret = false;
		for(int i = 0; i < resp->headersCount; i++) {
			//MessageBox(0, resp->headers[i].szValue, resp->headers[i].szName, MB_OK);
			if(strcmp(resp->headers[i].szName, "Location") == 0) {
				ret = UpdateXMLData(cat, resp->headers[i].szValue, recurse_count + 1);
				break;
			}
		}
		CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)resp);
		resp = 0;
		if(!ret) return LoadOldXMLData(cat, false);

		return ret;

	} else if(resp->resultCode != 200) {
		hNetlibHttp = resp->nlc;
		TCHAR buff[512];
		mir_sntprintf(buff, SIZEOF(buff), TranslateT("Failed to download XML data - Invalid response, code %d"), resp->resultCode);
		ShowError(buff);
		NLog(buff);
		CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)resp);
		resp = 0;
		return LoadOldXMLData(cat, false);
	}
		
	// resp->resultCode == 200
	hNetlibHttp = resp->nlc;

	if(!bz2_decompress_xml(resp->pData, resp->dataLength, &pData[cat], &dataLength[cat])) {
		ShowError(TranslateT("Failed to decompress XML data"));
		CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)resp);
		resp = 0;
		return LoadOldXMLData(cat, false);
	}

	// store date header and data for response 'Not Modified' (304) above
	for(int i = 0; i < resp->headersCount; i++) {
		//MessageBox(0, resp->headers[i].szValue, resp->headers[i].szName, MB_OK);
		if(strcmp(resp->headers[i].szName, "ETag") == 0) {
			//MessageBox(0, resp->headers[i].szValue, "Storing ETag", MB_OK);
			char buff[256];
			strcpy(buff, "DataETag_");
			strcat(buff, category_files[cat]);
			DBWriteContactSettingString(0, MODULE, buff, resp->headers[i].szValue);
		}
	}

	CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)resp);
	resp = 0;

	SaveXMLData(cat);

	doc[cat] = ezxml_parse_str((char*)pData[cat], strlen((char*)pData[cat]));
	if (!doc[cat]) return false;

	return true;
}