diff options
Diffstat (limited to 'protocols/Sametime/src/userlist.cpp')
| -rw-r--r-- | protocols/Sametime/src/userlist.cpp | 836 | 
1 files changed, 836 insertions, 0 deletions
diff --git a/protocols/Sametime/src/userlist.cpp b/protocols/Sametime/src/userlist.cpp new file mode 100644 index 0000000000..89e11a0a81 --- /dev/null +++ b/protocols/Sametime/src/userlist.cpp @@ -0,0 +1,836 @@ +#include "StdAfx.h"
 +#include "sametime.h"
 +
 +MCONTACT CSametimeProto::FindContactByUserId(const char* id)
 +{
 +	DBVARIANT dbv;
 +	for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) {
 +		if (!db_get_utf(hContact, m_szModuleName, "stid", &dbv)) {
 +			if (dbv.pszVal && strcmp(id, dbv.pszVal) == 0) {
 +				db_free(&dbv);
 +				return hContact;
 +			}
 +			db_free(&dbv);
 +		}
 +	}
 +	return 0;
 +}
 +
 +bool CSametimeProto::GetAwareIdFromContact(MCONTACT hContact, mwAwareIdBlock* id_block)
 +{
 +	char* proto = (char*)CallService( MS_PROTO_GETCONTACTBASEPROTO, ( WPARAM )hContact,0 );
 +	DBVARIANT dbv;
 +	if ( proto && !strcmp(m_szModuleName, proto)) {
 +		if (!db_get_utf(hContact, m_szModuleName, "stid", &dbv)) {
 +			if (dbv.pszVal) {
 +				id_block->type = mwAware_USER;
 +				id_block->user = _strdup(dbv.pszVal);
 +				id_block->community = 0;
 +				db_free(&dbv);
 +				return true;
 +			}
 +			db_free(&dbv);
 +		}
 +	}
 +	return false;
 +}
 +
 +void CSametimeProto::SetContactGroup(MCONTACT hContact, const char* name)
 +{
 +	db_set_utf(hContact, "CList", "Group", name);
 +}
 +
 +void CSametimeProto::AddGroup(const char* name, bool expanded)
 +{
 +	if (name && strcmp(name, "MetaContacts Hidden Group") == 0)
 +		return;
 +
 +	if (name && strcmp(name, Translate("None")) == 0)
 +		return;
 +
 +	ptrT ptszGroup(mir_utf8decodeT(name));
 +	HANDLE hGroup = Clist_GroupExists(ptszGroup);
 +	if (hGroup == NULL) {
 +		hGroup = Clist_CreateGroup(NULL, ptszGroup);
 +		if (hGroup) {
 +			CallService(MS_CLUI_GROUPADDED, (WPARAM)hGroup, 0);
 +			CallService(MS_CLIST_GROUPSETEXPANDED, (WPARAM)hGroup, expanded ? 1 : 0);
 +		}
 +	}
 +}
 +
 +MCONTACT CSametimeProto::AddContact(mwSametimeUser* user, bool temporary) 
 +{
 +
 +	debugLog(_T("CSametimeProto::AddContact() start"));
 +	const char* id = mwSametimeUser_getUser(user);
 +	const char* name = mwSametimeUser_getShortName(user);
 +	const char* nick = mwSametimeUser_getAlias(user);
 +	//const char* nick = mwSametimeUser_getShortName(user);
 +	mwSametimeUserType type = mwSametimeUser_getType(user);
 +
 +	MCONTACT hContact = FindContactByUserId(id);
 +	bool new_contact = false;
 +	if (!hContact) {
 +		hContact = (MCONTACT)CallService(MS_DB_CONTACT_ADD, 0, 0);
 +		if (!hContact) {
 +			debugLog(_T("AddContact(): Failed to create Sametime contact"));
 +			return NULL; ///TODO error handling
 +		}
 +		if (CallService(MS_PROTO_ADDTOCONTACT, (WPARAM) hContact, (LPARAM) m_szModuleName) != 0) {
 +			CallService(MS_DB_CONTACT_DELETE, (WPARAM) hContact, 0);
 +			debugLog(_T("AddContact(): Failed to register Sametime contact"));
 +			return NULL; ///TODO error handling
 +		}
 +		new_contact = true;
 +	} else if (!temporary) {
 +		db_unset(hContact, "CList", "NotOnList");
 +		db_unset(hContact, "CList", "Hidden");
 +	}
 +
 +
 +	// add to miranda
 +	if (new_contact) db_set_utf(hContact, m_szModuleName, "stid", id);
 +
 +	if (name && strlen(name))
 +		db_set_utf(hContact, m_szModuleName, "Name", name);
 +
 +	if (nick && strlen(nick)) {
 +		db_set_utf(hContact, m_szModuleName, "Nick", nick);
 +	} else if (name && strlen(name)) {
 +		db_set_utf(hContact, m_szModuleName, "Nick", name);
 +	} else {
 +		db_set_utf(hContact, m_szModuleName, "Nick", id);
 +	}
 +
 +	db_set_b(hContact, m_szModuleName, "type", (BYTE)type);
 +
 +	if (new_contact) {
 +		//add to our awareness list
 +		mwAwareIdBlock id_block;
 +		if (GetAwareIdFromContact(hContact, &id_block)) {
 +			GList* gl = g_list_prepend(NULL, &id_block);
 +			mwAwareList_addAware(aware_list, gl);
 +			g_list_free(gl);  
 +			free(id_block.user);
 +		}
 +	}
 +
 +	if (temporary) {
 +		db_set_b(hContact, "CList", "NotOnList", 1);
 +		db_set_b(hContact, "CList", "Hidden", 1);
 +	} else {
 +		db_unset(hContact, "CList", "NotOnList");
 +		db_unset(hContact, "CList", "Hidden");
 +	}
 +
 +	return hContact;
 +}
 +
 +void CSametimeProto::ImportContactsFromList(mwSametimeList* user_list, bool temporary)
 +{
 +	debugLog(_T("CSametimeProto::ImportContactsFromList() start"));
 +	// add contacts
 +	mwSametimeGroup* stgroup;
 +	mwSametimeUser* stuser;
 +	GList *gl, *gtl, *ul, *utl;
 +	const char* group_name;
 +	const char* group_alias;
 +	mwSametimeGroupType group_type;
 +	bool group_open;
 +
 +	gl = gtl = mwSametimeList_getGroups(user_list);
 +	for (; gl; gl = gl->next) {
 +		char buff[256];
 +		stgroup = (mwSametimeGroup*)gl->data;
 +
 +		group_name = mwSametimeGroup_getName(stgroup);
 +		group_alias = mwSametimeGroup_getAlias(stgroup);
 +		if (!group_alias) group_alias = group_name;
 +
 +		group_type = mwSametimeGroup_getType(stgroup);
 +		group_open = (mwSametimeGroup_isOpen(stgroup) != 0);
 +
 +		mir_snprintf(buff, SIZEOF(buff), "GN_%s", group_alias);
 +		db_set_utf(0, szProtoGroups, buff, group_name);
 +		mir_snprintf(buff, SIZEOF(buff), "GT_%s", group_alias);
 +		db_set_b(0, szProtoGroups, buff, (BYTE)group_type);
 +		mir_snprintf(buff, SIZEOF(buff), "GO_%s", group_alias);
 +		db_set_b(0, szProtoGroups, buff, (BYTE)(group_open ? 1 : 0));
 +
 +		// inverse mapping
 +		mir_snprintf(buff, SIZEOF(buff), "GA_%s", group_name);
 +		db_set_utf(0, szProtoGroups, buff, group_alias);
 +
 +		AddGroup(group_alias, group_open);
 +
 +		if (group_type == mwSametimeGroup_DYNAMIC) {
 +			mwAwareIdBlock id_block;
 +			id_block.type = mwAware_GROUP;
 +			id_block.user = (char*)group_name;
 +			id_block.community = 0;
 +
 +			GList* gl = g_list_prepend(NULL, &id_block);
 +			mwAwareList_addAware(aware_list, gl);
 +			g_list_free(gl);  
 +		}
 +
 +		ul = utl = mwSametimeGroup_getUsers(stgroup);
 +		for (; ul; ul = ul->next) {
 +			stuser = (mwSametimeUser*)ul->data;
 +			MCONTACT hContact = AddContact(stuser, temporary);
 +			if (hContact && group_alias && strcmp(group_alias, Translate("None")) != 0 && strcmp(group_alias, "MetaContacts Hidden Group") != 0) {
 +				SetContactGroup(hContact, group_alias);
 +				// mark contact as belonging to dynamic group
 +			}
 +		}
 +		g_list_free(utl);
 +	}
 +	g_list_free(gtl);
 +}
 +
 +void CSametimeProto::ExportContactsToList(mwSametimeList* user_list)
 +{
 +	debugLog(_T("CSametimeProto::ExportContactsToList() start"));
 +	mwSametimeGroup* stgroup = 0;
 +	char* group_name;
 +	char* group_alias;
 +	mwSametimeGroupType group_type;
 +	bool group_open;
 +
 +	mwSametimeUser* stuser;
 +	char* user_alias;
 +	char* user_shortName;
 +	mwSametimeUserType user_type;
 +	DBVARIANT dbv, dbv2;
 +	char buff[256];
 +	mwAwareIdBlock id_block;
 +	mwIdBlock uid;
 +
 +	GList* gl = 0;
 +	for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) {
 +		if (!db_get_utf(hContact, m_szModuleName, "stid", &dbv)) {
 +			if (dbv.pszVal) {
 +				if (GetAwareIdFromContact(hContact, &id_block)) {
 +					if (!db_get_utf(hContact, "CList", "Group", &dbv2)) {
 +						group_alias = _strdup(dbv2.pszVal);
 +						db_free(&dbv2);
 +					} else
 +						group_alias = _strdup(Translate("None"));
 +
 +					if (group_alias) {
 +						mir_snprintf(buff, SIZEOF(buff), "GT_%s", group_alias);
 +						group_type = (mwSametimeGroupType)db_get_b(0, szProtoGroups, buff, (BYTE)mwSametimeGroup_NORMAL);
 +						// apparently we don't want to upload contacts in dynamic groups - see gaim sametime plugin comments
 +						if (group_type == mwSametimeGroup_DYNAMIC) {
 +							db_free(&dbv);
 +							free(id_block.user);
 +							free(group_alias);
 +							hContact = db_find_next(hContact, m_szModuleName);
 +							continue;
 +						}
 +
 +						mir_snprintf(buff, SIZEOF(buff), "GN_%s", group_alias);
 +						if (!db_get_utf(0, szProtoGroups, buff, &dbv2)) {
 +							group_name = _strdup(dbv2.pszVal);
 +							db_free(&dbv2);
 +						} else
 +							group_name = _strdup(group_alias);
 +						
 +						//group_open = (db_get_b(0, szProtoGroups, buff, 0) == 1);
 +
 +						ptrT ptszGroup(mir_utf8decodeT(group_alias));
 +						HANDLE hGroup = Clist_GroupExists(ptszGroup);
 +						if (hGroup) {
 +							int expanded;
 +							CallService(MS_CLIST_GROUPGETNAME, (WPARAM)hGroup, (LPARAM)&expanded);
 +							group_open = (expanded != 0);
 +						} else {
 +							mir_snprintf(buff, SIZEOF(buff), "GO_%s", group_alias);
 +							group_open = (db_get_b(0, szProtoGroups, buff, 0) == 1);
 +						}
 +
 +						stgroup = 0;
 +						stgroup = mwSametimeList_findGroup(user_list, group_name);
 +						if (!stgroup) {
 +							if (group_name) stgroup = mwSametimeGroup_new(user_list, group_type, group_name);
 +							mwSametimeGroup_setAlias(stgroup, group_alias);
 +							mwSametimeGroup_setOpen(stgroup, group_open);
 +						}
 +
 +						free(group_name);
 +						free(group_alias);
 +
 +						if (!db_get_utf(hContact, m_szModuleName, "Name", &dbv2)) {
 +							user_shortName = _strdup(dbv2.pszVal);
 +							db_free(&dbv2);
 +						} else
 +							user_shortName = 0;
 +
 +						if (!db_get_utf(hContact, "CList", "MyHandle", &dbv2)) {
 +							user_alias = _strdup(dbv2.pszVal);
 +							db_free(&dbv2);
 +						} else
 +							user_alias = 0;
 +
 +						user_type = (mwSametimeUserType)db_get_b(hContact, m_szModuleName, "type", (BYTE)mwSametimeUser_NORMAL);
 +
 +						uid.user = id_block.user;
 +						uid.community = id_block.community;
 +
 +						stuser = mwSametimeUser_new(stgroup, user_type, &uid);
 +						if (user_shortName) {
 +							mwSametimeUser_setShortName(stuser, user_shortName);
 +							free(user_shortName);
 +						}
 +						if (user_alias) {
 +							mwSametimeUser_setAlias(stuser, user_alias);
 +							free(user_alias);
 +						}
 +					}
 +
 +					free(id_block.user);
 +				}
 +			}
 +			db_free(&dbv);
 +		}
 +	}
 +}
 +
 +void CSametimeProto::ImportContactsFromFile(TCHAR* filename)
 +{
 +	debugLog(_T("CSametimeProto::ImportContactsFromFile() start"));
 +	std::ifstream in(filename);
 +	std::string text;
 +	std::string line;
 +	if (in.is_open()) {
 +		while(!in.eof()) {
 +			std::getline(in, line);
 +			text += line;
 +			text += "\r\n";
 +		}
 +		in.close();
 +
 +		mwSametimeList* new_list = mwSametimeList_load(text.c_str());
 +		ImportContactsFromList(new_list, false);
 +		mwSametimeList_free(new_list);
 +
 +	}
 +}
 +
 +void CSametimeProto::ExportContactsToServer()
 +{
 +	mwSametimeList* user_list;
 +	mwStorageUnit* unit;
 +	mwPutBuffer* buff;
 +	mwOpaque* op;
 +
 +	debugLog(_T("CSametimeProto::ExportContactsToServer() start"));
 +	if (MW_SERVICE_IS_DEAD(service_storage)) {
 +		debugLog(_T("CSametimeProto::ExportContactsToServer() Failed"));
 +		showPopup(TranslateT("Failed to upload contacts - Storage service unavailable."), SAMETIME_POPUP_ERROR);
 +		return;
 +	}
 +
 +	user_list = mwSametimeList_new();
 +	ExportContactsToList(user_list);
 +
 +	buff = mwPutBuffer_new();
 +	mwSametimeList_put(buff, user_list);
 +	mwSametimeList_free(user_list);
 +
 +	/* put the buffer contents into a storage unit */
 +	unit = mwStorageUnit_new(mwStore_AWARE_LIST);
 +	op = mwStorageUnit_asOpaque(unit);
 +	mwPutBuffer_finalize(op, buff);
 +
 +	/* save the storage unit to the service */
 +	mwServiceStorage_save(service_storage, unit, NULL, NULL, NULL);
 +}
 +
 +
 +CSametimeProto* getProtoFromMwServiceStorage(mwServiceStorage* srvcStorage)
 +{
 +	mwService* service = mwServiceStorage_getService(srvcStorage);
 +	mwSession* session = mwService_getSession(service);
 +	return (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
 +}
 +
 +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);
 +		}
 +	}
 +}
 +
 +void CSametimeProto::UserListAddStored()
 +{
 +	mwStorageUnit* unit;
 +	unit = mwStorageUnit_new(mwStore_AWARE_LIST);
 +	mwServiceStorage_load(service_storage, unit, &load_users_callback, (gpointer)this, 0);
 +}
 +
 +int CSametimeProto::ContactDeleted(MCONTACT hContact)
 +{
 +	mwAwareIdBlock id_block;
 +	
 +	if (db_get_b(hContact, m_szModuleName, "ChatRoom", 0))
 +		return 0;
 +
 +	debugLog(_T("CSametimeProto::ContactDeleted()"));
 +
 +	if (GetAwareIdFromContact(hContact, &id_block)) {
 +		GList* gl = g_list_prepend(NULL, &id_block);
 +		mwAwareList_removeAware(aware_list, gl);
 +		g_list_free(gl);
 +		free(id_block.user);
 +	}
 +
 +	return 0;
 +}
 +
 +CSametimeProto* getProtoFromMwServiceResolve(mwServiceResolve* srvcResolve)
 +{
 +	mwService* service = mwServiceResolve_getService(srvcResolve);
 +	mwSession* session = mwService_getSession(service);
 +	return (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
 +}
 +
 +
 +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 && strcmp(group_alias, Translate("None")) && strcmp(group_alias, "MetaContacts Hidden Group")) {
 +					proto->SetContactGroup(hContact, group_alias);
 +				}
 +			}
 +		}
 +	}
 +
 +	if (stgroup)
 +		mwSametimeList_free(mwSametimeGroup_getList(stgroup));
 +}
 +
 +
 +CSametimeProto* getProtoFromMwAwareList(mwAwareList* list)
 +{
 +	mwServiceAware* servAwere = mwAwareList_getServiceAware(list);
 +	mwService* service = mwServiceAware_getService(servAwere);
 +	mwSession* session = mwService_getSession(service);
 +	return (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
 +}
 +
 +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) && 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;
 +		}
 +		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 || 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, SIZEOF(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, (void*)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;
 +			}
 +		} 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);
 +}
 +
 +
 +void mwAwareList_on_attrib(mwAwareList* list, mwAwareIdBlock* id, mwAwareAttribute* attrib)
 +{
 +}
 +
 +
 +void mwAwareList_clear(mwAwareList* list)
 +{
 +}
 +
 +
 +mwAwareListHandler mwAwareList_handler = {
 +	&mwAwareList_on_aware,
 +	&mwAwareList_on_attrib,
 +	&mwAwareList_clear
 +};
 +
 +
 +void CSametimeProto::UserListCreate()
 +{
 +	debugLog(_T("CSametimeProto::UserListCreate() start"));
 +	mwServiceAware_unsetAttribute(service_aware, mwAttribute_SPEAKERS);
 +	mwServiceAware_unsetAttribute(service_aware, mwAttribute_MICROPHONE);
 +	mwServiceAware_unsetAttribute(service_aware, mwAttribute_VIDEO_CAMERA);
 +	mwServiceAware_setAttributeBoolean(service_aware, mwAttribute_AV_PREFS_SET, TRUE);
 +	mwServiceAware_setAttributeBoolean(service_aware, mwAttribute_FILE_TRANSFER, TRUE);
 +
 +	aware_list = mwAwareList_new(service_aware, &mwAwareList_handler);
 +
 +	// add all contacts
 +
 +	DBVARIANT dbv;
 +	mwAwareIdBlock id_block;
 +	GList *gl = 0;
 +
 +	for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) {
 +		if (db_get_b(hContact, m_szModuleName, "ChatRoom", 0) == 0 /*&&  proto && !strcmp( PROTO, proto)*/) {
 +			if (!db_get_utf(hContact, m_szModuleName, "stid", &dbv)) {
 +				if (dbv.pszVal) {
 +					if (GetAwareIdFromContact(hContact, &id_block)) {
 +						// add user to aware list
 +						gl = g_list_prepend(0, &id_block);
 +						mwAwareList_addAware(aware_list, gl);
 +						free(id_block.user);
 +						g_list_free(gl);
 +					}
 +				}
 +				db_free(&dbv);
 +			}
 +		}
 +	}
 +
 +	// add self - might be necessary for some servers
 +	if (!db_get_utf(0, m_szModuleName, "stid", &dbv)) {
 +		id_block.type = mwAware_USER;
 +		id_block.user = dbv.pszVal;
 +		id_block.community = 0;
 +
 +		gl = g_list_prepend(0, &id_block);
 +		mwAwareList_addAware(aware_list, gl);
 +		g_list_free(gl);
 +
 +		db_free(&dbv);
 +	}
 +}
 +
 +void CSametimeProto::UserListDestroy()
 +{
 +	mwAwareList_free(aware_list);
 +	aware_list = 0;
 +}
 +
 +void CSametimeProto::UserRecvAwayMessage(MCONTACT hContact)
 +{
 +	debugLog(_T("CSametimeProto::UserRecvAwayMessage() start hContact=[%x]"), hContact);
 +	DBVARIANT dbv;
 +	if (!db_get_s((MCONTACT)hContact, "CList", "StatusMsg", &dbv, DBVT_TCHAR)) {
 +		ProtoBroadcastAck((MCONTACT)hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, (LPARAM)dbv.ptszVal);
 +		db_free(&dbv);
 +	} else {
 +		ProtoBroadcastAck((MCONTACT)hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, (LPARAM)NULL);
 +	}
 +}
 +
 +void mwResolve_handler_callback(mwServiceResolve* srvc, guint32 id, guint32 code, GList* results, gpointer data)
 +{
 +	CSametimeProto* proto = getProtoFromMwServiceResolve(srvc);
 +	BOOL advanced = (BOOL)data;
 +
 +	MYCUSTOMSEARCHRESULTS mcsr = {0};
 +	mcsr.nSize = sizeof(MYCUSTOMSEARCHRESULTS);
 +	//MYPROTOSEARCHRESULT mpsr = {0};
 +	//mpsr.cbSize = sizeof(MYPROTOSEARCHRESULT);
 +	mcsr.psr.nick = mcsr.psr.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) {
 +		GList *ri = results, *mri;
 +		for (;ri;ri = ri->next) {
 +			mri = ((mwResolveResult *)ri->data)->matches;
 +			for (;mri;mri = mri->next) {
 +				strncpy(mcsr.psr.stid, ((mwResolveMatch *)mri->data)->id, 256);
 +				mcsr.psr.stid[255] = 0;
 +				MultiByteToWideChar(CP_UTF8, 0, mcsr.psr.stid, -1, mcsr.pszFields[0], 512);
 +
 +				strncpy(mcsr.psr.name, ((mwResolveMatch *)mri->data)->name, 256);
 +				mcsr.psr.name[255] = 0;
 +				MultiByteToWideChar(CP_UTF8, 0, mcsr.psr.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.psr.group = (((mwResolveMatch *)mri->data)->type == mwResolveMatch_GROUP);
 +				//MultiByteToWideChar(CP_UTF8, 0, mcsr.psr.name, -1, mcsr.pszFields[1], 512);
 +				_tcsncpy(mcsr.pszFields[3], mcsr.psr.group ? TranslateT("True") : TranslateT("False"), 512);
 +
 +				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);
 +	}
 +}
 +
 +
 +void mwResolve_handler_details_callback(mwServiceResolve* srvc, guint32 id, guint32 code, GList* results, gpointer data)
 +{
 +	CSametimeProto* proto = getProtoFromMwServiceResolve(srvc);
 +
 +	MYPROTOSEARCHRESULT mpsr = {0};
 +	mpsr.cbSize = sizeof(mpsr);
 +	mpsr.nick = 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 && 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);
 +					}
 +				}
 +			}
 +		}
 +	}
 +}
 +
 +
 +int CSametimeProto::SearchForUser(const char* name, BOOLEAN advanced)
 +{
 +	if (m_iStatus != ID_STATUS_OFFLINE && service_resolve) {
 +		GList *query = g_list_prepend(0, (void*)name);
 +		guint32 id = mwServiceResolve_resolve(service_resolve, query, (mwResolveFlag)(mwResolveFlag_USERS | mwResolveFlag_GROUPS), &mwResolve_handler_callback, (gpointer)advanced, 0);
 +		g_list_free(query);
 +		return id; // search handle
 +	}
 +	return 0; // fail
 +}
 +
 +
 +int CSametimeProto::GetMoreDetails(const char* name)
 +{
 +	if (m_iStatus != ID_STATUS_OFFLINE && service_resolve) {
 +		GList *query = g_list_prepend(0, (void *)name);
 +		guint32 id = mwServiceResolve_resolve(service_resolve, query, (mwResolveFlag)(mwResolveFlag_USERS | mwResolveFlag_UNIQUE), &mwResolve_handler_details_callback, NULL, 0);
 +		g_list_free(query);
 +		return id; // search handle
 +	}
 +	return 0; // fail
 +}
 +
 +
 +INT_PTR CALLBACK CALLBACK SearchDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
 +{
 +	switch (msg) {
 +	case WM_INITDIALOG: 
 +		{
 +			TranslateDialogDefault(hwndDlg);
 +			return TRUE;
 +		}
 +	}
 +	return FALSE;
 +}
 +
 +
 +MCONTACT CSametimeProto::AddSearchedUser(MYPROTOSEARCHRESULT* mpsr, bool temporary)
 +{
 +	MCONTACT hContact = 0;
 +	debugLog(_T("CSametimeProto::AddSearchedUser() start"));
 +	mwSametimeList* user_list = mwSametimeList_new();
 +	mwSametimeGroup* stgroup = 0;
 +	if (mpsr->group) {
 +		 stgroup = mwSametimeGroup_new(user_list, mwSametimeGroup_DYNAMIC, mpsr->stid);
 +		 mwSametimeGroup_setAlias(stgroup, mpsr->name);
 +		 ImportContactsFromList(user_list, temporary);
 +	} else {
 +		stgroup = mwSametimeGroup_new(user_list, mwSametimeGroup_NORMAL, Translate("None"));
 +
 +		mwIdBlock uid;
 +		uid.user = mpsr->stid;
 +		uid.community = 0;
 +		mwSametimeUser *stuser = mwSametimeUser_new(stgroup, mwSametimeUser_NORMAL, &uid);
 +		mwSametimeUser_setShortName(stuser, mpsr->name);
 +
 +		hContact = AddContact(stuser, temporary);
 +		mwSametimeList_free(mwSametimeGroup_getList(stgroup));
 +	}	
 +
 +	return hContact;
 +}
 +
 +
 +void mwServiceAware_on_attrib_callback(mwServiceAware* srvc, mwAwareAttribute* attrib)
 +{
 +}
 +
 +void mwServiceAware_clear_callback(mwServiceAware* srvc)
 +{
 +}
 +
 +
 +void CSametimeProto::InitUserList()
 +{
 +	debugLog(_T("CSametimeProto::InitUserList()"));
 +
 +	mwSession_addService(session, (mwService*)(service_storage = mwServiceStorage_new(session)));
 +	mwSession_addService(session, (mwService*)(service_resolve = mwServiceResolve_new(session)));
 +	
 +	mwAwareHandler mwAware_handler = {
 +		&mwServiceAware_on_attrib_callback,
 +		&mwServiceAware_clear_callback
 +	};
 +	mwSession_addService(session, (mwService*)(service_aware = mwServiceAware_new(session, &mwAware_handler)));
 +
 +}
 +
 +void CSametimeProto::DeinitUserList()
 +{
 +	debugLog(_T("CSametimeProto::DeinitUserList()"));
 +
 +	mwSession_removeService(session, mwService_AWARE);
 +	mwService_free((mwService*)service_aware);
 +	service_aware = 0;
 +
 +	mwSession_removeService(session, mwService_RESOLVE);
 +	mwService_free((mwService*)service_resolve);
 +	service_resolve = 0;
 +
 +	mwSession_removeService(session, mwService_STORAGE);
 +	mwService_free((mwService*)service_storage);
 +	service_storage = 0;
 +}
 +
  | 
