Beispiel #1
0
/** triggered when someone says something */
void mwServiceConf_on_text(mwConference* conf, mwLoginInfo* user, const char* what)
{
	CSametimeProto* proto = getProtoFromMwConference(conf);
	proto->debugLog(_T("mwServiceConf_on_text() start"));

	TCHAR* tszConfId = mir_utf8decodeT(mwConference_getName(conf));

	GCDEST gcd = { proto->m_szModuleName };
	gcd.ptszID = tszConfId;
	gcd.iType = GC_EVENT_MESSAGE;

	GCEVENT gce = { sizeof(gce), &gcd };
	gce.dwFlags = GCEF_ADDTOLOG;

	TCHAR* textT = mir_utf8decodeT(what);
	TCHAR* tszUserName = mir_utf8decodeT(user->user_name);
	TCHAR* tszUserId = mir_utf8decodeT(user->login_id);
	gce.ptszText = textT;
	gce.ptszNick = tszUserName;
	gce.ptszUID = tszUserId;
	gce.time = (DWORD)time(0);

	CallService(MS_GC_EVENT, 0, (LPARAM)(GCEVENT *) &gce);

	mir_free(textT);
	mir_free(tszUserName);
	mir_free(tszUserId);
	mir_free(tszConfId);
}
Beispiel #2
0
/** received an ack for a sent chunk on an outbound file transfer.
  this indicates that a previous call to mwFileTransfer_send has
  reached the target and that the target has responded. */
void mwFileTransfer_handle_ack(mwFileTransfer* ft)
{
	// see SendThread above - not all clients send us acks
	CSametimeProto* proto = getProtoFromMwFileTransfer(ft);
	//FileTransferClientData* ftcd = (FileTransferClientData*)mwFileTransfer_getClientData(ft);
	proto->debugLog(_T("mwFileTransfer_handle_ack()"));
}
Beispiel #3
0
void __cdecl SessionClose(mwSession* session)
{
	CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
	proto->debugLog(_T("SessionClose()  server_connection=[%d]"), proto->server_connection);
	Netlib_CloseHandle(proto->server_connection);
	proto->server_connection = 0;
}
Beispiel #4
0
void __cdecl KeepAliveThread(LPVOID param)
{
	CSametimeProto* proto = (CSametimeProto*)param;
	int i = 120;
	proto->debugLog(_T("KeepAliveThread() start"));

	while (1) {

		if (i <= 0) {
			i = 120;
			// send keepalive every 120 * 250 = 30000[ms]
			if (mwSession_isStarted(proto->session) && proto->session) {
				mwSession_sendKeepalive(proto->session);
			}
		}

		i--;

		SleepEx(250, TRUE);

		EnterCriticalSection(&(proto->session_cs));
		if (Miranda_Terminated() || !proto->session) {
			LeaveCriticalSection(&(proto->session_cs));
			proto->debugLog(_T("KeepAliveThread() end"));
			break;
		}
		LeaveCriticalSection(&(proto->session_cs));
	}

	return;
}
Beispiel #5
0
void mwServiceConf_on_invited(mwConference* conf, mwLoginInfo* inviter, const char* invite)
{
	GList *members, *mem;
	CSametimeProto* proto = getProtoFromMwConference(conf);
	proto->debugLog(_T("mwServiceConf_on_invited() start"));

	members = mem = mwConference_getMembers(conf);
	for (;mem;mem=mem->next) {
		if (proto->my_login_info && strcmp(proto->my_login_info->login_id, ((mwLoginInfo*)mem->data)->login_id) == 0) {
			proto->debugLog(_T("mwServiceConf_on_invited() already present"));
			char* utfs = mir_utf8encodeT(TranslateT("Invitation rejected - already present."));
			mwConference_reject(conf, 0, utfs);
			mir_free(utfs);
			return;
		}
	}
	g_list_free(members);

	wchar_t ws_username[128];
	MultiByteToWideChar(CP_UTF8, 0, (const char*)inviter->user_name, -1, ws_username, 128);

	wchar_t ws_invite[512];
	MultiByteToWideChar(CP_UTF8, 0, (const char*)invite, -1, ws_invite, 128);

	if (MessageBoxW(0, ws_invite, ws_username, MB_OKCANCEL) == IDOK) {
		proto->debugLog(_T("mwServiceConf_on_invited() mwConference_accept"));
		mwConference_accept(conf);
	}
	else {
		proto->debugLog(_T("mwServiceConf_on_invited() mwConference_reject"));
		char* temp = mir_utf8encodeT(TranslateT("Your invitation has been rejected."));
		mwConference_reject(conf, 0, temp);
		mir_free(temp);
	}
}
Beispiel #6
0
void mwResolve_handler_details_callback(mwServiceResolve* srvc, guint32 id, guint32 code, GList* results, gpointer data)
{
	CSametimeProto* proto = getProtoFromMwServiceResolve(srvc);

	MYPROTOSEARCHRESULT mpsr;
	memset(&mpsr, 0, sizeof(mpsr));
	mpsr.cbSize = sizeof(mpsr);
	mpsr.nick.a = mpsr.name;

	if (code == mwResolveCode_SUCCESS) {
		GList *ri = results, *mri;
		for (; ri; ri = ri->next) {
			mri = ((mwResolveResult *)ri->data)->matches;
			for (; mri; mri = mri->next) {

				MCONTACT hContact = proto->FindContactByUserId(((mwResolveMatch*)mri->data)->id);
				if (hContact) {
					char* name = ((mwResolveMatch*)mri->data)->name;
					if (name && mir_strlen(name)) {
						db_set_utf(hContact, proto->m_szModuleName, "Name", name);
						db_set_utf(hContact, proto->m_szModuleName, "Nick", name);
						db_set_utf(hContact, "CList", "MyHandle", name);
					}
				}
			}
		}
	}
}
Beispiel #7
0
void __cdecl SessionAdmin(struct mwSession* session, const char* text)
{
	CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
	proto->debugLog(_T("SessionAdmin()"));
	TCHAR* tt = mir_utf8decodeT(text);
	MessageBox(0, tt, TranslateT("Sametime administrator message"), MB_OK);
	mir_free(tt);
}
Beispiel #8
0
void mwResolve_handler_callback(mwServiceResolve* srvc, guint32 id, guint32 code, GList* results, gpointer data)
{
	CSametimeProto* proto = getProtoFromMwServiceResolve(srvc);
	BOOL advanced = (INT_PTR)data;

	MYCUSTOMSEARCHRESULTS mcsr;
	memset(&mcsr, 0, sizeof(mcsr));
	mcsr.nSize = sizeof(MYCUSTOMSEARCHRESULTS);
	mcsr.psr.nick.a = mcsr.name;

	mcsr.nFieldCount = 4;
	TCHAR fields[4][512];
	TCHAR *fields_addr[4];
	mcsr.pszFields = fields_addr;
	mcsr.pszFields[0] = fields[0];
	mcsr.pszFields[1] = fields[1];
	mcsr.pszFields[2] = fields[2];
	mcsr.pszFields[3] = fields[3];

	if (advanced == TRUE) {
		// send column names
		mcsr.psr.cbSize = 0;
		_tcsncpy(mcsr.pszFields[0], TranslateT("ID"), 512);
		_tcsncpy(mcsr.pszFields[1], TranslateT("Name"), 512);
		_tcsncpy(mcsr.pszFields[2], TranslateT("Description"), 512);
		_tcsncpy(mcsr.pszFields[3], TranslateT("Group?"), 512);
		proto->ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SEARCHRESULT, (HANDLE)id, (LPARAM)&mcsr);
	}

	mcsr.psr.cbSize = sizeof(MYPROTOSEARCHRESULT);

	if (code == mwResolveCode_SUCCESS) {
		for (GList *ri = results; ri; ri = ri->next) {
			for (GList *mri = ((mwResolveResult *)ri->data)->matches; mri; mri = mri->next) {
				strncpy_s(mcsr.stid, ((mwResolveMatch *)mri->data)->id, _TRUNCATE);
				MultiByteToWideChar(CP_UTF8, 0, mcsr.stid, -1, mcsr.pszFields[0], 512);

				strncpy_s(mcsr.name, ((mwResolveMatch *)mri->data)->name, _TRUNCATE);
				MultiByteToWideChar(CP_UTF8, 0, mcsr.name, -1, mcsr.pszFields[1], 512);

				if (((mwResolveMatch *)mri->data)->desc)
					MultiByteToWideChar(CP_UTF8, 0, ((mwResolveMatch *)mri->data)->desc, -1, mcsr.pszFields[2], 512);
				else
					mcsr.pszFields[2][0] = 0;

				mcsr.group = (((mwResolveMatch *)mri->data)->type == mwResolveMatch_GROUP);
				_tcsncpy_s(mcsr.pszFields[3], 512, mcsr.group ? TranslateT("True") : TranslateT("False"), _TRUNCATE);

				if (advanced == TRUE)
					proto->ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SEARCHRESULT, (HANDLE)id, (LPARAM)&mcsr);
				else
					proto->ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)id, (LPARAM)&mcsr.psr);
			}
		}
		proto->ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)id, 0);
	}
}
Beispiel #9
0
int __cdecl SessionWrite(mwSession* session, const unsigned char* buf, gsize len)
{
	CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
	proto->debugLog(_T("SessionWrite()  server_connection=[%d], len=[%d]"), proto->server_connection, len);
	if (!proto->server_connection) return 1;
	if (Netlib_Send(proto->server_connection, (const char*)buf, len, 0) == SOCKET_ERROR)
		return 1;
	return 0;
}
Beispiel #10
0
void __cdecl sttRecvAwayThread(void *param)
{
	TFakeAckParams* tParam = (TFakeAckParams*)param;
	CSametimeProto* proto = tParam->proto;
	proto->debugLog(_T("sttRecvAwayThread() start"));

	Sleep(100);
	proto->UserRecvAwayMessage(tParam->hContact);

	proto->debugLog(_T("sttRecvAwayThread() end"));
	free(tParam);
}
Beispiel #11
0
void __cdecl sttFakeAckMessageSuccessThread(void *param)
{
	TFakeAckParams* tParam = (TFakeAckParams*)param;
	CSametimeProto* proto = tParam->proto;
	proto->debugLog(_T("sttFakeAckMessageSuccessThread() start"));

	Sleep(100);
	proto->ProtoBroadcastAck(tParam->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE)tParam->lParam, 0);

	proto->debugLog(_T("sttFakeAckMessageSuccessThread() end"));
	mir_free(tParam);
}
Beispiel #12
0
void __cdecl sttFakeAckMessageFailedThread(void *param)
{
	TFakeAckParams* tParam = (TFakeAckParams*)param;
	CSametimeProto* proto = tParam->proto;
	proto->debugLog(_T("sttFakeAckMessageFailedThread() start"));

	Sleep(100);
	proto->ProtoBroadcastAck(tParam->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, NULL, tParam->lParam); ///TODO tParam->lParam: add error message

	proto->debugLog(_T("sttFakeAckMessageFailedThread() end"));
	mir_free(tParam);
}
Beispiel #13
0
/** a file transfer has been fully initiated */
void mwFileTransfer_opened(mwFileTransfer* ft)
{
	CSametimeProto* proto = getProtoFromMwFileTransfer(ft);
	FileTransferClientData* ftcd = (FileTransferClientData*)mwFileTransfer_getClientData(ft);

	proto->debugLog(_T("Sametime mwFileTransfer_opened start"));

	if (ftcd->sending) {
		// create a thread to send chunks - since it seems not all clients send acks for each of our chunks!
		mir_forkthread(SendThread, ft);
	}
}
Beispiel #14
0
void __cdecl SessionAnnounce(struct mwSession* session, struct mwLoginInfo* from, gboolean may_reply, const char* text)
{
	CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
	proto->debugLog(_T("SessionAnnounce()"));
	TCHAR* stzFrom;
	TCHAR* stzText;
	TCHAR stzFromBuff[256];
	stzFrom = mir_utf8decodeT(from->user_name);
	stzText = mir_utf8decodeT(text);
	mir_sntprintf(stzFromBuff, SIZEOF(stzFromBuff), TranslateT("Session announcement - from '%s'"), stzFrom);
	MessageBox(0, TranslateTS(stzText), stzFromBuff, MB_OK);
	mir_free(stzText);
	mir_free(stzFrom);
}
Beispiel #15
0
void load_users_callback(mwServiceStorage* srvc, guint32 result, mwStorageUnit *item, gpointer data)
{
	CSametimeProto* proto = getProtoFromMwServiceStorage(srvc);

	if (mwStorageUnit_getKey(item) == mwStore_AWARE_LIST) {
		mwGetBuffer *buff = mwGetBuffer_wrap(mwStorageUnit_asOpaque(item));
		if (mwGetBuffer_remaining(buff)) {
			mwSametimeList* user_list = mwSametimeList_new();
			mwSametimeList_get(buff, user_list);
			proto->ImportContactsFromList(user_list, false);
			mwSametimeList_free(user_list);
		}
	}
}
Beispiel #16
0
VOID CALLBACK IdleTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
	CSametimeProto* proto = (CSametimeProto*)idEvent;

	KillTimer(0, proto->idle_timerid);
	proto->idle_timerid = 0;

	if (proto->idle_status) {
		struct mwUserStatus us;
		us.time = (DWORD)time(0);
		us.status = mwStatus_IDLE;
		us.desc = 0;
		mwSession_setUserStatus(proto->session, &us);
	}
	else proto->SetSessionStatus(proto->m_iStatus);
}
Beispiel #17
0
void __cdecl SendThread(LPVOID param) {

	mwFileTransfer* ft = (mwFileTransfer*)param;
	if (!ft) return;
	CSametimeProto* proto = getProtoFromMwFileTransfer(ft);
	FileTransferClientData* ftcd = (FileTransferClientData*)mwFileTransfer_getClientData(ft);

	proto->debugLog(_T("SendThread() start"));

	PROTOFILETRANSFERSTATUS pfts = {0};

	pfts.cbSize = sizeof(pfts);
	pfts.flags = PFTS_UTF;
	pfts.hContact = ftcd->hContact;
	if (ftcd->sending == 1)
		pfts.flags |= PFTS_SENDING;

	pfts.pszFiles = NULL;
	pfts.totalFiles = ftcd->first->ft_count;
	pfts.totalBytes = ftcd->first->totalSize;

	while(SendFileChunk(proto, ft, ftcd) && !Miranda_Terminated()) {
		pfts.currentFileNumber = ftcd->ft_number;
		pfts.totalProgress = ftcd->sizeToHere + mwFileTransfer_getSent(ft);
		pfts.szWorkingDir = ftcd->save_path;
		pfts.szCurrentFile = (char*)mwFileTransfer_getFileName(ft);
		pfts.currentFileSize = mwFileTransfer_getFileSize(ft);
		pfts.currentFileProgress = mwFileTransfer_getSent(ft);
		pfts.currentFileTime = 0; //?

		proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_DATA, ftcd->hFt, (LPARAM)&pfts);

		SleepEx(500,TRUE);
	}

	proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ftcd->hFt, 0);

	mwFileTransfer_removeClientData(ft);
	if (ftcd->save_path) free(ftcd->save_path);
	if (ftcd->buffer) delete[] ftcd->buffer;
	delete ftcd;
	
	proto->debugLog(_T("SendThread() end"));
	return;
}
Beispiel #18
0
/** triggered when a conference is closed. This is typically when
  we've left it */
void mwServiceConf_conf_closed(mwConference* conf, guint32 reason)
{
	CSametimeProto* proto = getProtoFromMwConference(conf);
	proto->debugLog(_T("mwServiceConf_conf_closed() start"));

	TCHAR* tszConfId = mir_utf8decodeT(mwConference_getName(conf));

	GCDEST gcd = { proto->m_szModuleName };
	gcd.ptszID = tszConfId;
	gcd.iType = GC_EVENT_CONTROL;

	GCEVENT gce = { sizeof(gce), &gcd };
	gce.dwFlags = GCEF_ADDTOLOG;

	CallService(MS_GC_EVENT, SESSION_OFFLINE, (LPARAM)&gce);
	CallService(MS_GC_EVENT, SESSION_TERMINATE, (LPARAM)&gce);
	mir_free(tszConfId);
}
Beispiel #19
0
/** triggered when someone joins the conference */
void mwServiceConf_on_peer_joined(mwConference* conf, mwLoginInfo *user)
{
	CSametimeProto* proto = getProtoFromMwConference(conf);
	proto->debugLog(_T("mwServiceConf_on_peer_joined() start"));

	MCONTACT hContact = proto->FindContactByUserId(user->user_id);
	if (!hContact) {
		mwIdBlock idb;
		idb.user = ((mwLoginInfo *)user)->user_id;
		idb.community = 0;

		mwSametimeList* user_list = mwSametimeList_new();
		char* utfs = mir_utf8encodeT(TranslateT("None"));
		mwSametimeGroup* stgroup = mwSametimeGroup_new(user_list, mwSametimeGroup_NORMAL, utfs);
		mwSametimeUser* stuser = mwSametimeUser_new(stgroup, mwSametimeUser_NORMAL, &idb);

		hContact = proto->AddContact(stuser, (proto->options.add_contacts ? false : true));

		mwSametimeList_free(user_list);
		mir_free(utfs);
	}

	ptrT tszConfId(mir_utf8decodeT(mwConference_getName(conf)));
	ptrT tszUserName(mir_utf8decodeT(user->user_name));
	ptrT tszUserId(mir_utf8decodeT(user->login_id));

	// add user
	GCDEST gcd = { proto->m_szModuleName };
	gcd.ptszID = tszConfId;
	gcd.iType = GC_EVENT_JOIN;

	GCEVENT gce = { sizeof(gce), &gcd };
	gce.dwFlags = GCEF_ADDTOLOG;
	gce.ptszNick = tszUserName;
	gce.ptszUID = tszUserId;
	gce.ptszStatus = _T("Normal");
	gce.time = (DWORD)time(0);

	CallServiceSync(MS_GC_EVENT, 0, (LPARAM) &gce);

	mir_free(tszUserName);
	mir_free(tszUserId);
	mir_free(tszConfId);
}
Beispiel #20
0
void __cdecl SessionStateChange(mwSession* session, mwSessionState state, gpointer info)
{
	CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
	proto->debugLog(_T("SessionStateChange()  state=[%d]"), state);

	switch (state) {
	case mwSession_STARTING:
		break;

	case mwSession_HANDSHAKE:
		break;

	case mwSession_HANDSHAKE_ACK:
		break;

	case mwSession_STARTED:
		proto->SessionStarted();
		break;

	case mwSession_STOPPING:
		if ((int)info) {// & ERR_FAILURE) {
			char *msg = mwError((int)info);
			TCHAR *msgT = mir_utf8decodeT(msg);
			proto->showPopup(TranslateTS(msgT), SAMETIME_POPUP_ERROR);
			mir_free(msgT);
			g_free(msg);
		}
		proto->SessionStopping();
		break;

	case mwSession_STOPPED:
		break;

	case mwSession_LOGIN_REDIR:
		proto->debugLog(_T("SessionStateChange()  mwSession_LOGIN_REDIR  info=[%s]"), _A2T((char*)info));
		//options.server_name = str((char*)info);
		strcpy(proto->options.server_name, (char*)info);
		proto->LogOut();
		proto->LogIn(proto->login_status, proto->m_hNetlibUser);
		break;

	case mwSession_LOGIN_CONT:
		break;

	case mwSession_LOGIN:
		break;

	case mwSession_LOGIN_ACK:
		break;

	case mwSession_UNKNOWN:
		break;
	}
}
Beispiel #21
0
/** triggered when someone leaves the conference */
void mwServiceConf_on_peer_parted(mwConference* conf, mwLoginInfo* user)
{
	CSametimeProto* proto = getProtoFromMwConference(conf);
	proto->debugLog(_T("mwServiceConf_on_peer_parted() start"));

	ptrT tszConfId(mir_utf8decodeT(mwConference_getName(conf)));
	ptrT tszUserName(mir_utf8decodeT(user->user_name));
	ptrT tszUserId(mir_utf8decodeT(user->login_id));

	// remove user
	GCDEST gcd = { proto->m_szModuleName };
	gcd.ptszID = tszConfId;
	gcd.iType = GC_EVENT_PART;

	GCEVENT gce = { sizeof(gce), &gcd };
	gce.dwFlags = GCEF_ADDTOLOG;
	gce.ptszNick = tszUserName;
	gce.ptszUID = tszUserId;
	gce.ptszStatus = _T("Normal");
	gce.time = (DWORD)time(0);
	CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce);
}
Beispiel #22
0
/** receive a chunk of a file from an inbound file transfer. */
void mwFileTransfer_recv(mwFileTransfer* ft, struct mwOpaque* data)
{
	CSametimeProto* proto = getProtoFromMwFileTransfer(ft);
	FileTransferClientData* ftcd = (FileTransferClientData*)mwFileTransfer_getClientData(ft);
	proto->debugLog(_T("mwFileTransfer_recv() start"));

	DWORD bytes_written;
	if (!WriteFile(ftcd->hFile, data->data, data->len, &bytes_written, 0)) {
		proto->debugLog(_T("mwFileTransfer_recv() !WriteFile"));
		mwFileTransfer_cancel(ft);
		proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ftcd->hFt, 0);
		proto->debugLog(_T("mwFileTransfer_recv() ACKRESULT_FAILED"));
	}
	else {
		mwFileTransfer_ack(ft); // acknowledge chunk

		PROTOFILETRANSFERSTATUS pfts = { 0 };
		pfts.cbSize = sizeof(pfts);
		pfts.flags = PFTS_UTF;
		pfts.hContact = ftcd->hContact;
		if (ftcd->sending == 1) {
			pfts.flags |= PFTS_SENDING;
		}
		pfts.pszFiles = NULL;
		pfts.totalFiles = 1;
		pfts.currentFileNumber = 0;
		pfts.totalBytes = mwFileTransfer_getFileSize(ft);
		pfts.totalProgress = mwFileTransfer_getSent(ft);
		pfts.szWorkingDir = ftcd->save_path;
		pfts.szCurrentFile = (char*)mwFileTransfer_getFileName(ft);
		pfts.currentFileSize = mwFileTransfer_getFileSize(ft);
		pfts.currentFileProgress = mwFileTransfer_getSent(ft);
		pfts.currentFileTime = 0; //?

		proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_DATA, ftcd->hFt, (LPARAM)&pfts);
		proto->debugLog(_T("mwFileTransfer_recv() ACKRESULT_DATA"));

		if (mwFileTransfer_isDone(ft)) {
			proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ftcd->hFt, 0);
			proto->debugLog(_T("mwFileTransfer_recv() ACKRESULT_SUCCESS"));
		}
	}
}
Beispiel #23
0
void mwResolve_handler_dyngroup_callback(mwServiceResolve* srvc, guint32 id, guint32 code, GList *results, gpointer data)
{
	CSametimeProto* proto = getProtoFromMwServiceResolve(srvc);
	mwSametimeGroup* stgroup = (mwSametimeGroup*)data;

	mwResolveResult* result;
	mwResolveMatch* match;
	g_return_if_fail(results != NULL);

	if (results) {
		result = (mwResolveResult*)results->data;
		if (result && result->matches) {

			match = (mwResolveMatch*)result->matches->data;
			if (match) {
				mwIdBlock uid;
				uid.user = match->id;
				uid.community = 0;
				mwSametimeUser *stuser = mwSametimeUser_new(stgroup, mwSametimeUser_NORMAL, &uid);
				mwSametimeUser_setShortName(stuser, match->name);

				MCONTACT hContact = proto->AddContact(stuser, false);

				const char* group_name = mwSametimeGroup_getName(stgroup);
				const char* group_alias = mwSametimeGroup_getAlias(stgroup);
				if (!group_alias) group_alias = group_name;
				if (hContact && group_alias && mir_strcmp(group_alias, Translate("None")) && mir_strcmp(group_alias, "MetaContacts Hidden Group")) {
					proto->SetContactGroup(hContact, group_alias);
				}
			}
		}
	}

	if (stgroup)
		mwSametimeList_free(mwSametimeGroup_getList(stgroup));
}
Beispiel #24
0
/** an incoming file transfer has been offered */
void mwFileTransfer_offered(mwFileTransfer* ft)
{
	CSametimeProto* proto = getProtoFromMwFileTransfer(ft);
	proto->debugLog(_T("mwFileTransfer_offered() start"));

	const mwIdBlock* idb = mwFileTransfer_getUser(ft);
	MCONTACT hContact = proto->FindContactByUserId(idb->user);
	proto->debugLog(_T("Sametime mwFileTransfer_offered hContact=[%x]"), hContact);

	if (!hContact) {
		mwSametimeList* user_list = mwSametimeList_new();
		mwSametimeGroup* stgroup = mwSametimeGroup_new(user_list, mwSametimeGroup_NORMAL, Translate("None"));
		mwSametimeUser* stuser = mwSametimeUser_new(stgroup, mwSametimeUser_NORMAL, (mwIdBlock*)idb);
		hContact = proto->AddContact(stuser, (proto->options.add_contacts ? false : true));
	}

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

	TCHAR* filenameT = mir_utf8decodeT(mwFileTransfer_getFileName(ft));
	const char* message = mwFileTransfer_getMessage(ft);
	TCHAR descriptionT[512];
	if (message) {
		TCHAR* messageT = mir_utf8decodeT(message);
		mir_sntprintf(descriptionT, _T("%s - %s"), filenameT, messageT);
		mir_free(messageT);
	} else
		_tcsncpy_s(descriptionT, filenameT, _TRUNCATE);

	PROTORECVFILET pre = {0};
	pre.dwFlags = PRFF_TCHAR;
	pre.fileCount = 1;
	pre.timestamp = time(NULL);
	pre.descr.t = descriptionT;
	pre.files.t = &filenameT;
	pre.lParam = (LPARAM)ft;

	ProtoChainRecvFile(hContact, &pre);
	
	mir_free(filenameT);
}
Beispiel #25
0
void __cdecl SessionSetPrivacyInfo(struct mwSession* session)
{
	CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
	proto->debugLog(_T("SessionSetPrivacyInfo()"));
}
Beispiel #26
0
void mwAwareList_on_aware(mwAwareList* list, mwAwareSnapshot* aware)
{
	CSametimeProto* proto = getProtoFromMwAwareList(list);;

	MCONTACT hContact = proto->FindContactByUserId(aware->id.user);
	char* group = 0;
	DBVARIANT dbv;

	// update self - necessary for some servers
	if (aware->online && !db_get_utf(0, proto->m_szModuleName, "stid", &dbv) && mir_strcmp(aware->id.user, dbv.pszVal) == 0) {
		int new_status = ID_STATUS_OFFLINE;

		switch (aware->status.status) {
		case mwStatus_ACTIVE:
			new_status = ID_STATUS_ONLINE;
			break;
		case mwStatus_AWAY:
			new_status = ID_STATUS_AWAY;
			break;
		case mwStatus_IDLE:
			new_status = ID_STATUS_IDLE;
			break;
		case mwStatus_BUSY:
			new_status = ID_STATUS_DND;
			break;
		case mwStatus_IN_MEETING:				// link 'in meeting' Sametime status
			new_status = ID_STATUS_OCCUPIED;	// with 'Occupied' MIR_NG status
			break;
		}
		if (new_status != ID_STATUS_IDLE) //SetSessionStatus(new_status);
			proto->UpdateSelfStatus();

		db_free(&dbv);
	}

	if (hContact && !db_get_utf(hContact, "CList", "Group", &dbv)) {
		group = _strdup(dbv.pszVal);
		db_free(&dbv);
	}

	if (aware->group && (!group || mir_strcmp(aware->group, group) || !hContact)) {
		// dynamic group member we're not already aware of
		// resolve server alias to user id via resolver
		mwSametimeList* user_list = mwSametimeList_new();
		mwSametimeGroup* stgroup = mwSametimeGroup_new(user_list, mwSametimeGroup_DYNAMIC, aware->group);
		char buff[256];
		mir_snprintf(buff, "GA_%s", aware->group);
		if (!db_get_utf(0, proto->szProtoGroups, buff, &dbv)) {
			mwSametimeGroup_setAlias(stgroup, dbv.pszVal);
			db_free(&dbv);
		}

		GList* query = g_list_prepend(0, aware->id.user);
		mwServiceResolve_resolve(proto->service_resolve, query, mwResolveFlag_USERS, mwResolve_handler_dyngroup_callback, (gpointer)stgroup, 0);
		g_list_free(query);

	}
	else if (hContact) {

		if (aware->online) {
			int new_status = ID_STATUS_OFFLINE;

			switch (aware->status.status) {
			case mwStatus_ACTIVE:
				new_status = ID_STATUS_ONLINE;
				db_set_dw(hContact, proto->m_szModuleName, "IdleTS", 0);
				db_set_w(hContact, proto->m_szModuleName, "Status", new_status);
				break;
			case mwStatus_AWAY:
				new_status = ID_STATUS_AWAY;
				db_set_dw(hContact, proto->m_szModuleName, "IdleTS", 0);
				db_set_w(hContact, proto->m_szModuleName, "Status", new_status);
				break;
			case mwStatus_IDLE:
				if (proto->options.idle_as_away) {
					new_status = ID_STATUS_AWAY;
					db_set_w(hContact, proto->m_szModuleName, "Status", new_status);
				}
				db_set_dw(hContact, proto->m_szModuleName, "IdleTS", (DWORD)time(0));
				break;
			case mwStatus_BUSY:
				new_status = ID_STATUS_DND;
				db_set_w(hContact, proto->m_szModuleName, "Status", new_status);
				db_set_dw(hContact, proto->m_szModuleName, "IdleTS", 0);
				break;
			case mwStatus_IN_MEETING:
				// link 'in meeting' Sametime status to 'Occipied' MIR_NG status
				new_status = ID_STATUS_OCCUPIED;
				db_set_w(hContact, proto->m_szModuleName, "Status", new_status);
				db_set_dw(hContact, proto->m_szModuleName, "IdleTS", 0);
				break;
			}
		}
		else
			db_set_w(hContact, proto->m_szModuleName, "Status", ID_STATUS_OFFLINE);

		if (proto->service_aware) {
			const char* desc = mwServiceAware_getText(proto->service_aware, &aware->id);
			if (desc)
				//db_set_utf(hContact, m_szModuleName, "StatusMsg", desc);
				db_set_utf(hContact, "CList", "StatusMsg", desc);
			else
				//db_set_utf(hContact, m_szModuleName, "StatusMsg", "");
				//db_unset(hContact, m_szModuleName, "StatusMsg");
				db_unset(hContact, "CList", "StatusMsg");
		}
	}

	if (group) free(group);
}
Beispiel #27
0
void __cdecl SessionThread(LPVOID param)
{
	CSametimeProto* proto = (CSametimeProto*)param;
	HANDLE hNetlibUser = proto->m_hNetlibUser;
	proto->debugLog(_T("SessionThread() start"));

	continue_connect = true;

	//setup
	NETLIBOPENCONNECTION conn_data = { 0 };
	conn_data.cbSize = sizeof(NETLIBOPENCONNECTION);
	conn_data.flags = NLOCF_V2;
	conn_data.szHost = proto->options.server_name;
	conn_data.wPort = proto->options.port;
	conn_data.timeout = 20;
	conn_data.waitcallback = waitcallback;

	proto->BroadcastNewStatus(ID_STATUS_CONNECTING);

	proto->server_connection = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)hNetlibUser, (LPARAM)&conn_data);

	if (!proto->server_connection) {

		proto->BroadcastNewStatus(ID_STATUS_OFFLINE);

		if (continue_connect) {
			// real timeout - not user cancelled
			proto->showPopup(TranslateT("No server connection!"), SAMETIME_POPUP_ERROR);
		}

		proto->debugLog(_T("SessionThread() end, no server_connection, continue_connect=[%d]"), continue_connect);
		return;
	}

	mwSessionHandler handler = { 0 };
	handler.clear = SessionClear;
	handler.io_write = SessionWrite;
	handler.io_close = SessionClose;
	handler.on_stateChange = SessionStateChange;
	handler.on_admin = SessionAdmin;
	handler.on_announce = SessionAnnounce;
	handler.on_setPrivacyInfo = SessionSetPrivacyInfo;
	handler.on_setUserStatus = SessionSetUserStatus;

	EnterCriticalSection(&proto->session_cs);
	proto->session = mwSession_new(&handler);

	proto->InitMeanwhileServices();

	mwSession_start(proto->session);
	LeaveCriticalSection(&proto->session_cs);

	mir_forkthread(KeepAliveThread, (void*)proto);

	unsigned char* recv_buffer = (unsigned char*)mir_alloc(1024 * 32);
	int bytes;
	//while(session && server_connection && mwSession_getState(session) != mwSession_STOPPED) {
	while (proto->server_connection) {// && session) {// && !mwSession_isStopped(session)) { // break on error
		bytes = Netlib_Recv(proto->server_connection, (char *)recv_buffer, 1024 * 32, 0);
		proto->debugLog(_T("SessionThread() Netlib_Recv'ed bytes=[%d]"), bytes);

		if (bytes == 0) {
			break;
		}
		else if (bytes == SOCKET_ERROR) {
			// this is normal - e.g. socket closed due to log off, during blocking read above
			break;
		}
		else {
			EnterCriticalSection(&proto->session_cs);
			mwSession_recv(proto->session, recv_buffer, bytes);
			LeaveCriticalSection(&proto->session_cs);
		}
	}
	mir_free(recv_buffer);

	EnterCriticalSection(&proto->session_cs);
	proto->DeinitMeanwhileServices();
	mwSession* old_session = proto->session;
	proto->session = 0; // kills keepalive thread, if awake
	mwSession_free(old_session);
	LeaveCriticalSection(&proto->session_cs);

	proto->BroadcastNewStatus(ID_STATUS_OFFLINE);
	proto->SetAllOffline();
	proto->first_online = true;

	proto->debugLog(_T("SessionThread() end"));
	return;
}
Beispiel #28
0
static INT_PTR CALLBACK DlgProcOptNet(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	CSametimeProto* proto = (CSametimeProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);

	switch (msg) {
	case WM_INITDIALOG: {
		TranslateDialogDefault(hwndDlg);

		SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
		proto = (CSametimeProto*)lParam;

		WORD client_ver = proto->GetClientVersion();
		if (client_ver) {
			TCHAR verbuf[100];
			mir_sntprintf(verbuf, _countof(verbuf), TranslateT("Client protocol version: %03d.%03d"), (client_ver & 0xFF00) >> 8, client_ver & 0xFF);
			SetDlgItemText(hwndDlg, IDC_ST_CLIENTVER, verbuf);
		}

		WORD server_ver = proto->GetServerVersion();
		if (server_ver) {
			TCHAR verbuf[100];
			mir_sntprintf(verbuf, _countof(verbuf), TranslateT("Server protocol version: %03d.%03d"), (server_ver & 0xFF00) >> 8, server_ver & 0xFF);
			SetDlgItemText(hwndDlg, IDC_ST_SERVERVER, verbuf);
		}

		TCHAR *s = mir_utf8decodeT(proto->options.server_name); SetDlgItemText(hwndDlg, IDC_ED_SNAME, s); mir_free(s);
		s = mir_utf8decodeT(proto->options.id); SetDlgItemText(hwndDlg, IDC_ED_NAME, s); mir_free(s);
		s = mir_utf8decodeT(proto->options.pword); SetDlgItemText(hwndDlg, IDC_ED_PWORD, s); mir_free(s);

		SetDlgItemInt(hwndDlg, IDC_ED_PORT, proto->options.port, FALSE);
		CheckDlgButton(hwndDlg, IDC_CHK_GETSERVERCONTACTS, proto->options.get_server_contacts ? BST_CHECKED : BST_UNCHECKED);
		CheckDlgButton(hwndDlg, IDC_CHK_ADDCONTACTS, proto->options.add_contacts ? BST_CHECKED : BST_UNCHECKED);
		CheckDlgButton(hwndDlg, IDC_CHK_IDLEAWAY, proto->options.idle_as_away ? BST_CHECKED : BST_UNCHECKED);

		SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENT, CB_RESETCONTENT, 0, 0);
		int pos = 0;
		bool found = false;

		for (int i = 0; i < NUM_IDS; i++) {
			pos = SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENT, CB_ADDSTRING, -1, (LPARAM)client_names[i]);
			SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENT, CB_SETITEMDATA, pos, client_ids[i]);
			if (client_ids[i] == proto->options.client_id) {
				found = true;
				SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENT, CB_SETCURSEL, pos, 0);
				SetDlgItemInt(hwndDlg, IDC_ED_CLIENTID, client_ids[i], FALSE);
				if (i != sizeof(client_ids) / sizeof(int)-1) {
					HWND hw = GetDlgItem(hwndDlg, IDC_ED_CLIENTID);
					EnableWindow(hw, false);
				}
			}
		}

		if (!found) {
			SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENT, CB_SETCURSEL, pos, 0); // pos is last item, i.e. custom
			SetDlgItemInt(hwndDlg, IDC_ED_CLIENTID, proto->options.client_id, FALSE);
		}


		SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENTVN, CB_RESETCONTENT, 0, 0);
		pos = 0;

		for (int i = 0; i < NUM_CVS; i++) {
			pos = SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENTVN, CB_ADDSTRING, -1, (LPARAM)CV_names[i]);
			SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENTVN, CB_SETITEMDATA, pos, i);
			if (CV_major[i] == proto->options.client_versionMajor && CV_minor[i] == proto->options.client_versionMinor) {
				found = true;
				SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENTVN, CB_SETCURSEL, pos, 0);
			}
		}


		if (!ServiceExists(MS_POPUP_ADDPOPUPT)) {
			HWND hw = GetDlgItem(hwndDlg, IDC_RAD_ERRPOP);
			EnableWindow(hw, FALSE);
		}

		if (!ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) {
			HWND hw = GetDlgItem(hwndDlg, IDC_RAD_ERRBAL);
			EnableWindow(hw, FALSE);
		}

		switch (proto->options.err_method) {
			case ED_POP: CheckDlgButton(hwndDlg, IDC_RAD_ERRPOP, BST_CHECKED); break;
			case ED_MB: CheckDlgButton(hwndDlg, IDC_RAD_ERRMB, BST_CHECKED); break;
			case ED_BAL: CheckDlgButton(hwndDlg, IDC_RAD_ERRBAL, BST_CHECKED); break;
		}

		if (proto->options.encrypt_session)
			CheckDlgButton(hwndDlg, IDC_RAD_ENC, BST_CHECKED);
		else
			CheckDlgButton(hwndDlg, IDC_RAD_NOENC, BST_CHECKED);

		return FALSE;
	}

	case WM_COMMAND:
		if (HIWORD(wParam) == EN_CHANGE && (HWND)lParam == GetFocus())
			SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);

		if (HIWORD(wParam) == CBN_SELCHANGE) {
			switch (LOWORD(wParam)) {
			case IDC_CMB_CLIENT:
			{
				int sel = SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENT, CB_GETCURSEL, 0, 0);
				int id = SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENT, CB_GETITEMDATA, sel, 0);
				bool custom = (id == client_ids[sizeof(client_ids) / sizeof(int)-1]);

				if (!custom)
				   SetDlgItemInt(hwndDlg, IDC_ED_CLIENTID, id, FALSE);
				else
				   SetDlgItemInt(hwndDlg, IDC_ED_CLIENTID, DEFAULT_ID, FALSE);

				HWND hw = GetDlgItem(hwndDlg, IDC_ED_CLIENTID);
				EnableWindow(hw, custom);

				SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
				return TRUE;
			}
			case IDC_CMB_CLIENTVN:
			{
				SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
				return TRUE;
			}
			}
		}

		if (HIWORD(wParam) == BN_CLICKED) {
			switch (LOWORD(wParam)) {
			case IDC_BTN_UPLOADCONTACTS:
				{
					EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_UPLOADCONTACTS), FALSE);
					EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_IMPORTCONTACTS), FALSE);

					proto->ExportContactsToServer();

					SendMessage(hwndDlg, WMU_STORECOMPLETE, 0, 0);
				}
				return TRUE;

			case IDC_BTN_IMPORTCONTACTS:
				{
					TCHAR import_filename[MAX_PATH]; import_filename[0] = 0;

					OPENFILENAME ofn = { 0 };
					ofn.lStructSize = sizeof(ofn);
					ofn.lpstrFile = import_filename;
					ofn.hwndOwner = hwndDlg;
					ofn.Flags = CC_FULLOPEN;
					ofn.nMaxFile = MAX_PATH;
					ofn.lpstrFilter = _T("All\0*.*\0");
					ofn.nFilterIndex = 1;
					ofn.lpstrFileTitle = NULL;
					ofn.nMaxFileTitle = 0;
					ofn.lpstrInitialDir = NULL;
					ofn.Flags = OFN_PATHMUSTEXIST;

					if (GetOpenFileName(&ofn) == TRUE) {
						HWND hBut = GetDlgItem(hwndDlg, IDC_BTN_UPLOADCONTACTS);
						EnableWindow(hBut, FALSE);
						hBut = GetDlgItem(hwndDlg, IDC_BTN_IMPORTCONTACTS);
						EnableWindow(hBut, FALSE);

						proto->ImportContactsFromFile(ofn.lpstrFile);

						SendMessage(hwndDlg, WMU_STORECOMPLETE, 0, 0);
					}
				}
				return TRUE;

			case IDC_CHK_GETSERVERCONTACTS:
			case IDC_CHK_ENCMESSAGES:
			case IDC_RAD_ERRMB:
			case IDC_RAD_ERRBAL:
			case IDC_RAD_ERRPOP:
			case IDC_CHK_USERCP:
			case IDC_CHK_ADDCONTACTS:
			case IDC_CHK_IDLEAWAY:
			case IDC_RAD_ENC:
			case IDC_RAD_NOENC:
				SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
				return TRUE;
			case IDC_RAD_ANSI:
			case IDC_RAD_UTF8:
			case IDC_RAD_OEM:
			case IDC_RAD_UTF7:
			case IDC_RAD_USERCP:
				HWND hw = GetDlgItem(hwndDlg, IDC_CHK_USERCP);
				EnableWindow(hw, BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_RAD_USERCP));

				SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
				return TRUE;
			}
		}
		break;

	case WMU_STORECOMPLETE:
		EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_UPLOADCONTACTS), TRUE);
		EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_IMPORTCONTACTS), TRUE);
		return TRUE;

	case WM_NOTIFY:
		if (((LPNMHDR)lParam)->code == PSN_APPLY) {
			TCHAR ws[2048];

			GetDlgItemText(hwndDlg, IDC_ED_SNAME, ws, LSTRINGLEN);
			mir_strcpy(proto->options.server_name, T2Utf(ws));
			GetDlgItemText(hwndDlg, IDC_ED_NAME, ws, LSTRINGLEN);
			mir_strcpy(proto->options.id, T2Utf(ws));
			GetDlgItemText(hwndDlg, IDC_ED_PWORD, ws, LSTRINGLEN);
			mir_strcpy(proto->options.pword, T2Utf(ws));

			BOOL translated;
			int port = GetDlgItemInt(hwndDlg, IDC_ED_PORT, &translated, FALSE);
			if (translated)
				proto->options.port = port;

			proto->options.get_server_contacts = (IsDlgButtonChecked(hwndDlg, IDC_CHK_GETSERVERCONTACTS) != FALSE);

			int sel = SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENT, CB_GETCURSEL, 0, 0);
			int id = SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENT, CB_GETITEMDATA, sel, 0);

			if (id == client_ids[sizeof(client_ids) / sizeof(int)-1]) {
				BOOL trans;
				id = GetDlgItemInt(hwndDlg, IDC_ED_CLIENTID, &trans, FALSE);
				if (trans)
					proto->options.client_id = id;
			}
			else proto->options.client_id = id;

			sel = SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENTVN, CB_GETCURSEL, 0, 0);
			int CVpos = SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENTVN, CB_GETITEMDATA, sel, 0);
			proto->options.client_versionMajor = CV_major[CVpos];
			proto->options.client_versionMinor = CV_minor[CVpos];

			if (IsDlgButtonChecked(hwndDlg, IDC_RAD_ERRMB)) proto->options.err_method = ED_MB;
			else if (IsDlgButtonChecked(hwndDlg, IDC_RAD_ERRBAL)) proto->options.err_method = ED_BAL;
			else if (IsDlgButtonChecked(hwndDlg, IDC_RAD_ERRPOP)) proto->options.err_method = ED_POP;

			proto->options.add_contacts = (IsDlgButtonChecked(hwndDlg, IDC_CHK_ADDCONTACTS) != FALSE);
			proto->options.encrypt_session = (IsDlgButtonChecked(hwndDlg, IDC_RAD_ENC) != FALSE);
			proto->options.idle_as_away = (IsDlgButtonChecked(hwndDlg, IDC_CHK_IDLEAWAY) != FALSE);

			proto->SaveOptions();

			return TRUE;
		}
		break;

	case WM_DESTROY:
		break;
	}

	return FALSE;
}
Beispiel #29
0
void __cdecl SessionClear(mwSession* session)
{
	CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
	proto->debugLog(_T("SessionClear()"));
}
Beispiel #30
0
void __cdecl SessionSetUserStatus(struct mwSession* session)
{
	CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");

	int new_status;
	struct mwUserStatus us;
	mwUserStatus_clone(&us, mwSession_getUserStatus(session));

	proto->debugLog(_T("SessionSetUserStatus()  us.status=[%d]"), us.status);

	switch (us.status) {
	case mwStatus_ACTIVE:
		new_status = ID_STATUS_ONLINE;
		break;

	case mwStatus_AWAY:
		new_status = ID_STATUS_AWAY;
		if (proto->idle_status) {
			// ignore setting to away by idle module, after we've set ourselves idle
			// most standard clients represent idle and away the same way anyway,
			// but this allows miranda users to make use of the idle timestamp
			// but show our status in clist as away
			proto->BroadcastNewStatus(new_status);
			mwUserStatus_clear(&us);
			return;
		}
		break;

	case mwStatus_BUSY:
		new_status = ID_STATUS_DND;
		break;

	case mwStatus_IDLE:
		new_status = ID_STATUS_AWAY;
		if (!proto->first_online && !proto->options.idle_as_away) { // show our status in clist as away if idle when going online or treating idle as away
			mwUserStatus_clear(&us);
			return;
		}
		break;

	case mwStatus_IN_MEETING: // new 'in meeting' status
		new_status = ID_STATUS_OCCUPIED;
		break;

	default:
		TCHAR buff[512];
		mir_sntprintf(buff, SIZEOF(buff), TranslateT("Unknown user status: %d"), us.status);
		proto->showPopup(buff, SAMETIME_POPUP_ERROR);
		proto->debugLog(buff);

		mwUserStatus_clear(&us);
		// just go online...to prevent us getting stuck 'connecting'
		new_status = ID_STATUS_ONLINE;
		break;
	}

	proto->m_iDesiredStatus = new_status;

	if (proto->first_online) {
		proto->first_online = false;
		//proto->showPopup(TranslateT("Setting login status"), SAMETIME_POPUP_INFO);
		proto->debugLog(_T("Setting login status"));
		proto->SetSessionStatus(proto->login_status);
	}
	else proto->BroadcastNewStatus(new_status);

	mwUserStatus_clear(&us);
}