Example #1
0
/** Scans the \c CHANGES and call the appropriate function for each change.
*
* @param chg : Structure holding all the change info (See CHANGES).
*/
void ApplyChanges(CHANGES *chg)
{
	HANDLE most_online;
	int i;

	// remove removed contacts
	for(i = 0; i < chg->num_deleted; i++) {
		Meta_Delete((WPARAM)chg->hDeletedContacts[i], 0);
		if(chg->hDeletedContacts[i] == chg->hDefaultContact)
			chg->hDefaultContact = 0;
		if(chg->hDeletedContacts[i] == chg->hOfflineContact)
			chg->hOfflineContact = 0;
	}

	// set contact positions
	for(i = 0; i < chg->num_contacts; i++) {
		if(Meta_GetContactNumber(chg->hContact[i]) != i)
			Meta_SwapContacts(chg->hMeta, Meta_GetContactNumber(chg->hContact[i]), i);
	}

	NotifyEventHooks(hSubcontactsChanged, (WPARAM)chg->hMeta, (LPARAM)chg->hDefaultContact);

	// set default
	if(chg->hDefaultContact)
		DBWriteContactSettingDword(chg->hMeta, META_PROTO, "Default", Meta_GetContactNumber(chg->hDefaultContact));
	else
		DBWriteContactSettingDword(chg->hMeta, META_PROTO, "Default", 0);
	NotifyEventHooks(hEventDefaultChanged, (WPARAM)chg->hMeta, (LPARAM)chg->hDefaultContact);

	// set offline
	if(chg->hOfflineContact)
		DBWriteContactSettingDword(chg->hMeta, META_PROTO, "OfflineSend", Meta_GetContactNumber(chg->hOfflineContact));
	else
		DBWriteContactSettingDword(chg->hMeta, META_PROTO, "OfflineSend", (DWORD)-1);

	// fix nick
	most_online = Meta_GetMostOnline(chg->hMeta);
	Meta_CopyContactNick(chg->hMeta, most_online);

	// fix status
	Meta_FixStatus(chg->hMeta);

	// fix avatar
	most_online = Meta_GetMostOnlineSupporting(chg->hMeta, PFLAGNUM_4, PF4_AVATARS);
	if(most_online) {
		PROTO_AVATAR_INFORMATION AI;

		AI.cbSize = sizeof(AI);
		AI.hContact = chg->hMeta;
		AI.format = PA_FORMAT_UNKNOWN;
		strcpy(AI.filename, "X");

		if((int)CallProtoService(META_PROTO, PS_GETAVATARINFO, 0, (LPARAM)&AI) == GAIR_SUCCESS)
	        DBWriteContactSettingString(chg->hMeta, "ContactPhoto", "File",AI.filename);
	}

	if(MetaAPI_GetForceState((WPARAM)chg->hMeta, 0) != chg->force_default)
		MetaAPI_ForceDefault((WPARAM)chg->hMeta, 0);
}
Example #2
0
int Meta_CallMostOnline(WPARAM hContact, LPARAM lParam)
{
	DBCachedContact *cc = CheckMeta(hContact);
	if (cc == NULL)
		return 0;

	Meta_CopyContactNick(cc, db_mc_getSrmmSub(cc->contactID));
	Meta_FixStatus(cc);
	return 0;
}
Example #3
0
/** Call when we want to send a user is typing message
*
* @param wParam HANDLE to the contact that we are typing to
* @param lParam either PROTOTYPE_SELFTYPING_ON or PROTOTYPE_SELFTYPING_OFF
*/
static INT_PTR Meta_UserIsTyping(WPARAM hMeta, LPARAM lParam)
{
	DBCachedContact *cc = CheckMeta(hMeta);
	if (cc == NULL)
		return 0;

	// forward to sending protocol, if supported
	MCONTACT hMostOnline = Meta_GetMostOnline(cc);
	Meta_CopyContactNick(cc, hMostOnline);
	if (!hMostOnline)
		return 0;

	char *proto = GetContactProto(hMostOnline);
	if (proto)
		if (ProtoServiceExists(proto, PSS_USERISTYPING))
			ProtoCallService(proto, PSS_USERISTYPING, hMostOnline, lParam);

	return 0;
}
Example #4
0
INT_PTR Meta_GetInfo(WPARAM wParam, LPARAM lParam)
{
	CCSDATA *ccs = (CCSDATA*)lParam;

	// This is a simple contact
	// (this should normally not happen, since linked contacts do not appear on the list.)
	DBCachedContact *cc = CheckMeta(ccs->hContact);
	if (cc == NULL || cc->nDefault == -1)
		return 0;

	MCONTACT hMostOnline = Meta_GetMostOnlineSupporting(cc, PFLAGNUM_4, PF4_AVATARS);
	if (!hMostOnline)
		return 0;

	char *proto = GetContactProto(hMostOnline);
	if (!proto)
		return 0;

	PROTO_AVATAR_INFORMATIONT AI;
	AI.cbSize = sizeof(AI);
	AI.hContact = ccs->hContact;
	AI.format = PA_FORMAT_UNKNOWN;
	_tcscpy(AI.filename, _T("X"));
	if (CallProtoService(META_PROTO, PS_GETAVATARINFOT, 0, (LPARAM)&AI) == GAIR_SUCCESS)
		db_set_ts(ccs->hContact, "ContactPhoto", "File", AI.filename);

	hMostOnline = Meta_GetMostOnline(cc);
	Meta_CopyContactNick(cc, hMostOnline);

	if (!hMostOnline)
		return 0;

	ccs->hContact = hMostOnline;
	if (!ProtoServiceExists(proto, PSS_GETINFO))
		return 0; // fail

	return CallContactService(ccs->hContact, PSS_GETINFO, ccs->wParam, ccs->lParam);
}
Example #5
0
INT_PTR Meta_SendMessage(WPARAM wParam,LPARAM lParam)
{
	CCSDATA *ccs = (CCSDATA*)lParam;

	DBCachedContact *cc = CheckMeta(ccs->hContact);
	if (cc == NULL || cc->nDefault == -1) {
		// This is a simple contact, let through the stack of protocols
		// (this should normally not happen, since linked contacts do not appear on the list.)
		return CallService(MS_PROTO_CHAINSEND, wParam, lParam);
	}

	MCONTACT hMostOnline = db_mc_getSrmmSub(cc->contactID);
	if (!hMostOnline) {
		// send failure to notify user of reason
		HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

		TFakeAckParams *tfap = (TFakeAckParams *)mir_alloc(sizeof(TFakeAckParams));
		tfap->hContact = ccs->hContact;
		tfap->hEvent = hEvent;
		tfap->id = 10;
		strcpy(tfap->msg, Translate("No online contacts found."));

		DWORD dwThreadId;
		CloseHandle(CreateThread(NULL, 0, sttFakeAckFail, tfap, 0, &dwThreadId));
		SetEvent(hEvent);
		return 10;
	}

	Meta_CopyContactNick(cc, hMostOnline);

	ccs->hContact = hMostOnline;
	char *proto = GetContactProto(hMostOnline);
	Meta_SetNick(proto);	// (no matter what was there before)

	return CallContactService(ccs->hContact, PSS_MESSAGE, ccs->wParam, ccs->lParam);
}
Example #6
0
int Meta_SettingChanged(WPARAM hContact, LPARAM lParam)
{
	DBCONTACTWRITESETTING *dcws = (DBCONTACTWRITESETTING *)lParam;
	char buffer[512];

	// the only global options we're interested in
	if (hContact == 0)
		return 0;

	DBCachedContact *cc = currDb->m_cache->GetCachedContact(hContact);
	if (cc == NULL || !cc->IsSub())
		return 0;

	DBCachedContact *ccMeta = currDb->m_cache->GetCachedContact(cc->parentID);
	if (ccMeta == NULL || !ccMeta->IsMeta())
		return 0;

	// This contact is attached to a MetaContact.
	int contact_number = Meta_GetContactNumber(ccMeta, hContact);
	if (contact_number == -1)
		return 0; // exit - db corruption

	if (!strcmp(dcws->szSetting, "IP")) {
		if (dcws->value.type == DBVT_DWORD)
			db_set_dw(ccMeta->contactID, META_PROTO, "IP", dcws->value.dVal);
		else
			db_unset(ccMeta->contactID, META_PROTO, "IP");
	}
	else if (!strcmp(dcws->szSetting, "RealIP")) {
		if (dcws->value.type == DBVT_DWORD)
			db_set_dw(ccMeta->contactID, META_PROTO, "RealIP", dcws->value.dVal);
		else
			db_unset(ccMeta->contactID, META_PROTO, "RealIP");
	}
	else if (!strcmp(dcws->szSetting, "ListeningTo")) {
		switch (dcws->value.type) {
		case DBVT_ASCIIZ:
			db_set_s(ccMeta->contactID, META_PROTO, "ListeningTo", dcws->value.pszVal);
			break;
		case DBVT_UTF8:
			db_set_utf(ccMeta->contactID, META_PROTO, "ListeningTo", dcws->value.pszVal);
			break;
		case DBVT_WCHAR:
			db_set_ws(ccMeta->contactID, META_PROTO, "ListeningTo", dcws->value.pwszVal);
			break;
		case DBVT_DELETED:
			db_unset(ccMeta->contactID, META_PROTO, "ListeningTo");
			break;
		}
	}
	else if (!strcmp(dcws->szSetting, "Nick") && dcws->value.type != DBVT_DELETED) {
		// subcontact nick has changed - update metacontact
		mir_snprintf(buffer, SIZEOF(buffer), "Nick%d", contact_number);
		db_set(ccMeta->contactID, META_PROTO, buffer, &dcws->value);

		ptrT tszMyhandle(db_get_tsa(hContact, "CList", "MyHandle"));
		if (tszMyhandle == NULL) {
			mir_snprintf(buffer, SIZEOF(buffer), "CListName%d", contact_number);
			db_set(ccMeta->contactID, META_PROTO, buffer, &dcws->value);
		}

		// copy nick to metacontact, if it's the most online
		MCONTACT hMostOnline = Meta_GetMostOnline(ccMeta);
		Meta_CopyContactNick(ccMeta, hMostOnline);
	}
	else if (!strcmp(dcws->szSetting, "IdleTS")) {
		if (dcws->value.type == DBVT_DWORD)
			db_set_dw(ccMeta->contactID, META_PROTO, "IdleTS", dcws->value.dVal);
		else if (dcws->value.type == DBVT_DELETED)
			db_set_dw(ccMeta->contactID, META_PROTO, "IdleTS", 0);
	}
	else if (!strcmp(dcws->szSetting, "LogonTS")) {
		if (dcws->value.type == DBVT_DWORD)
			db_set_dw(ccMeta->contactID, META_PROTO, "LogonTS", dcws->value.dVal);
		else if (dcws->value.type == DBVT_DELETED)
			db_set_dw(ccMeta->contactID, META_PROTO, "LogonTS", 0);
	}
	else if (!strcmp(dcws->szModule, "CList") && !strcmp(dcws->szSetting, "MyHandle")) {
		if (dcws->value.type == DBVT_DELETED) {
			char *proto = GetContactProto(hContact);
			mir_snprintf(buffer, SIZEOF(buffer), "CListName%d", contact_number);

			DBVARIANT dbv;
			if (proto && !db_get_ts(hContact, proto, "Nick", &dbv)) {
				db_set_ts(ccMeta->contactID, META_PROTO, buffer, dbv.ptszVal);
				db_free(&dbv);
			}
			else db_unset(ccMeta->contactID, META_PROTO, buffer);
		}
		else {
			// subcontact clist displayname has changed - update metacontact
			mir_snprintf(buffer, SIZEOF(buffer), "CListName%d", contact_number);
			db_set(ccMeta->contactID, META_PROTO, buffer, &dcws->value);
		}

		// copy nick to metacontact, if it's the most online
		Meta_CopyContactNick(ccMeta, Meta_GetMostOnline(ccMeta));
	}
	// subcontact changing status
	else if (!strcmp(dcws->szSetting, "Status") && dcws->value.type != DBVT_DELETED) {
		// update subcontact status setting
		mir_snprintf(buffer, SIZEOF(buffer), "Status%d", contact_number);
		db_set_w(ccMeta->contactID, META_PROTO, buffer, dcws->value.wVal);
		
		mir_snprintf(buffer, SIZEOF(buffer), "StatusString%d", contact_number);
		db_set_ts(ccMeta->contactID, META_PROTO, buffer, cli.pfnGetStatusModeDescription(dcws->value.wVal, 0));

		// set status to that of most online contact
		MCONTACT hMostOnline = Meta_GetMostOnline(ccMeta);
		if (hMostOnline != db_mc_getDefault(ccMeta->contactID))
			db_mc_notifyDefChange(ccMeta->contactID, hMostOnline);

		Meta_CopyContactNick(ccMeta, hMostOnline);
		Meta_FixStatus(ccMeta);

		// most online contact with avatar support might have changed - update avatar
		hMostOnline = Meta_GetMostOnlineSupporting(ccMeta, PFLAGNUM_4, PF4_AVATARS);
		if (hMostOnline) {
			PROTO_AVATAR_INFORMATIONT AI = { sizeof(AI) };
			AI.hContact = ccMeta->contactID;
			AI.format = PA_FORMAT_UNKNOWN;
			_tcscpy(AI.filename, _T("X"));
			if (CallProtoService(META_PROTO, PS_GETAVATARINFOT, 0, (LPARAM)&AI) == GAIR_SUCCESS)
				db_set_ts(ccMeta->contactID, "ContactPhoto", "File", AI.filename);
		}
	}

	return 0;
}
void Meta_RemoveContactNumber(HANDLE hMeta, int number) {
	int i, num_contacts, default_contact;
	HANDLE hContact;//, handle;

	char buffer[512], buffer2[512];

	num_contacts = DBGetContactSettingDword(hMeta, META_PROTO, "NumContacts", 0);
	default_contact = DBGetContactSettingDword(hMeta, META_PROTO, "Default", -1);
	if(number >= 0 && number < num_contacts) {

		// get the handle
		hContact = Meta_GetContactHandle(hMeta, number);

		// make sure this contact thinks it's part of this metacontact
		if((HANDLE)DBGetContactSettingDword(hContact,META_PROTO,"Handle", 0) == hMeta) {

			// remove link to meta contact
			DBDeleteContactSetting(hContact,META_PROTO,"IsSubcontact");
			DBDeleteContactSetting(hContact,META_PROTO,META_LINK);
			DBDeleteContactSetting(hContact,META_PROTO,"Handle");
			DBDeleteContactSetting(hContact,META_PROTO,"ContactNumber");
			// unhide - must be done after removing link (see meta_services.c:Meta_ChangeStatus)
			Meta_RestoreGroup(hContact);
			DBDeleteContactSetting(hContact,META_PROTO,"OldCListGroup");
			//CallService(MS_PROTO_REMOVEFROMCONTACT,(WPARAM)hContact,(LPARAM)META_PROTO);
			CallService(MS_PROTO_REMOVEFROMCONTACT,(WPARAM)hContact,(LPARAM)META_FILTER);
			// stop ignoring, if we were
			if(options.suppress_status)
				CallService(MS_IGNORE_UNIGNORE, (WPARAM)hContact, (WPARAM)IGNOREEVENT_USERONLINE);
		}

		// remove history from metacontact
		//Meta_RemoveHistory(hMeta, hContact);

		// each contact from 'number' upwards will be moved down one
		// and the last one will be deleted
		for(i = number + 1; i < num_contacts; i++) {
			Meta_SwapContacts(hMeta, i, i-1);
		}

		// remove the last one
		strcpy(buffer, "Protocol");
		strcat(buffer, _itoa((num_contacts - 1), buffer2, 10));
		DBDeleteContactSetting(hMeta, META_PROTO, buffer);
		strcpy(buffer, "Status");
		strcat(buffer, _itoa((num_contacts - 1), buffer2, 10));
		DBDeleteContactSetting(hMeta, META_PROTO, buffer);
		strcpy(buffer, "Handle");
		strcat(buffer, _itoa((num_contacts - 1), buffer2, 10));
		DBDeleteContactSetting(hMeta, META_PROTO, buffer);
		strcpy(buffer, "StatusString");
		strcat(buffer, _itoa((num_contacts - 1), buffer2, 10));
		DBDeleteContactSetting(hMeta, META_PROTO, buffer);
		strcpy(buffer, "Login");
		strcat(buffer, _itoa((num_contacts - 1), buffer2, 10));
		DBDeleteContactSetting(hMeta, META_PROTO, buffer);
		strcpy(buffer, "Nick");
		strcat(buffer, _itoa((num_contacts - 1), buffer2, 10));
		DBDeleteContactSetting(hMeta, META_PROTO, buffer);
		strcpy(buffer, "CListName");
		strcat(buffer, _itoa((num_contacts - 1), buffer2, 10));
		DBDeleteContactSetting(hMeta, META_PROTO, buffer);

		// if the default contact was equal to or greater than 'number', decrement it (and deal with ends)
		if(default_contact >= number) {
			default_contact--;
			if(default_contact < 0) 
				default_contact = 0;

			DBWriteContactSettingDword(hMeta, META_PROTO, "Default", (DWORD)default_contact);
			NotifyEventHooks(hEventDefaultChanged, (WPARAM)hMeta, (LPARAM)Meta_GetContactHandle(hMeta, default_contact));
		}
		num_contacts--;
		DBWriteContactSettingDword(hMeta, META_PROTO, "NumContacts", (DWORD)num_contacts);

		// fix nick
		hContact = Meta_GetMostOnline(hMeta);
		Meta_CopyContactNick(hMeta, hContact);

		// fix status
		Meta_FixStatus(hMeta);

		// fix avatar
		hContact = Meta_GetMostOnlineSupporting(hMeta, PFLAGNUM_4, PF4_AVATARS);
		if(hContact) {
			PROTO_AVATAR_INFORMATION AI;

			AI.cbSize = sizeof(AI);
			AI.hContact = hMeta;
			AI.format = PA_FORMAT_UNKNOWN;
			strcpy(AI.filename, "X");

			if((int)CallProtoService(META_PROTO, PS_GETAVATARINFO, 0, (LPARAM)&AI) == GAIR_SUCCESS)
				DBWriteContactSettingString(hMeta, "ContactPhoto", "File",AI.filename);
		}
	}
}
Example #8
0
void Meta_RemoveContactNumber(DBCachedContact *ccMeta, int number, bool bUpdateInfo)
{
	if (ccMeta == NULL)
		return;

	// make sure this contact thinks it's part of this metacontact
	DBCachedContact *ccSub = currDb->m_cache->GetCachedContact(Meta_GetContactHandle(ccMeta, number));
	if (ccSub != NULL) {
		if (ccSub->parentID == ccMeta->contactID) {
			db_unset(ccSub->contactID, "CList", "Hidden");

			// stop ignoring, if we were
			if (options.bSuppressStatus)
				CallService(MS_IGNORE_UNIGNORE, ccSub->contactID, IGNOREEVENT_USERONLINE);
		}
	}

	// each contact from 'number' upwards will be moved down one
	// and the last one will be deleted
	for (int i = number+1; i < ccMeta->nSubs; i++)
		Meta_SwapContacts(ccMeta, i, i - 1);

	// remove the last one
	int id = ccMeta->nSubs - 1;
	char buffer[512];
	mir_snprintf(buffer, "Handle%d", id);
	db_unset(ccMeta->contactID, META_PROTO, buffer);

	mir_snprintf(buffer, "Protocol%d", id);
	db_unset(ccMeta->contactID, META_PROTO, buffer);

	mir_snprintf(buffer, "Status%d", id);
	db_unset(ccMeta->contactID, META_PROTO, buffer);

	mir_snprintf(buffer, "StatusString%d", id);
	db_unset(ccMeta->contactID, META_PROTO, buffer);

	mir_snprintf(buffer, "Login%d", id);
	db_unset(ccMeta->contactID, META_PROTO, buffer);

	mir_snprintf(buffer, "Nick%d", id);
	db_unset(ccMeta->contactID, META_PROTO, buffer);

	mir_snprintf(buffer, "CListName%d", id);
	db_unset(ccMeta->contactID, META_PROTO, buffer);

	if (ccSub != NULL) {
		ccSub->parentID = 0;
		currDb->MetaDetouchSub(ccMeta, ccMeta->nSubs - 1);

		currDb->MetaSplitHistory(ccMeta, ccSub);
	}

	// if the default contact was equal to or greater than 'number', decrement it (and deal with ends)
	if (ccMeta->nDefault >= number) {
		int iNumber = ccMeta->nDefault-1;
		if (iNumber < 0)
			iNumber = 0;
		db_mc_setDefaultNum(ccMeta->contactID, iNumber, true);
	}
	
	ccMeta->nSubs--;
	db_set_dw(ccMeta->contactID, META_PROTO, "NumContacts", ccMeta->nSubs);

	if (bUpdateInfo) {
		// fix nick
		Meta_CopyContactNick(ccMeta, Meta_GetMostOnline(ccMeta));

		// fix status
		Meta_FixStatus(ccMeta);

		// fix avatar
		MCONTACT hContact = Meta_GetMostOnlineSupporting(ccMeta, PFLAGNUM_4, PF4_AVATARS);
		if (hContact) {
			PROTO_AVATAR_INFORMATION ai = { 0 };
			ai.hContact = ccMeta->contactID;
			ai.format = PA_FORMAT_UNKNOWN;
			_tcsncpy_s(ai.filename, _T("X"), _TRUNCATE);

			if (CallProtoService(META_PROTO, PS_GETAVATARINFO, 0, (LPARAM)&ai) == GAIR_SUCCESS)
				db_set_ts(ccMeta->contactID, "ContactPhoto", "File", ai.filename);
		}
	}
}
Example #9
0
void Meta_RemoveContactNumber(HANDLE hMeta, int number)
{
	int num_contacts = db_get_dw(hMeta, META_PROTO, "NumContacts", 0);
	int default_contact = db_get_dw(hMeta, META_PROTO, "Default", -1);
	if (number < 0 && number >= num_contacts)
		return;

	// get the handle
	HANDLE hContact = Meta_GetContactHandle(hMeta, number);

	// make sure this contact thinks it's part of this metacontact
	if ((HANDLE)db_get_dw(hContact, META_PROTO, "Handle", 0) == hMeta) {
		// remove link to meta contact
		db_unset(hContact, META_PROTO, "IsSubcontact");
		db_unset(hContact, META_PROTO, META_LINK);
		db_unset(hContact, META_PROTO, "Handle");
		db_unset(hContact, META_PROTO, "ContactNumber");
		// unhide - must be done after removing link (see meta_services.c:Meta_ChangeStatus)
		Meta_RestoreGroup(hContact);
		db_unset(hContact, META_PROTO, "OldCListGroup");

		// stop ignoring, if we were
		if (options.suppress_status)
			CallService(MS_IGNORE_UNIGNORE, (WPARAM)hContact, (WPARAM)IGNOREEVENT_USERONLINE);
	}

	// each contact from 'number' upwards will be moved down one
	// and the last one will be deleted
	for (int i = number + 1; i < num_contacts; i++)
		Meta_SwapContacts(hMeta, i, i-1);

	// remove the last one
	char buffer[512], idStr[20];
	_itoa(num_contacts-1, idStr, 10);
	strcpy(buffer, "Protocol"); strcat(buffer, idStr);
	db_unset(hMeta, META_PROTO, buffer);

	strcpy(buffer, "Status"); strcat(buffer, idStr);
	db_unset(hMeta, META_PROTO, buffer);

	strcpy(buffer, "Handle"); strcat(buffer, idStr);
	db_unset(hMeta, META_PROTO, buffer);

	strcpy(buffer, "StatusString"); strcat(buffer, idStr);
	db_unset(hMeta, META_PROTO, buffer);

	strcpy(buffer, "Login"); strcat(buffer, idStr);
	db_unset(hMeta, META_PROTO, buffer);

	strcpy(buffer, "Nick"); strcat(buffer, idStr);
	db_unset(hMeta, META_PROTO, buffer);

	strcpy(buffer, "CListName"); strcat(buffer, idStr);
	db_unset(hMeta, META_PROTO, buffer);

	// if the default contact was equal to or greater than 'number', decrement it (and deal with ends)
	if (default_contact >= number) {
		default_contact--;
		if (default_contact < 0)
			default_contact = 0;

		db_set_dw(hMeta, META_PROTO, "Default", (DWORD)default_contact);
		NotifyEventHooks(hEventDefaultChanged, (WPARAM)hMeta, (LPARAM)Meta_GetContactHandle(hMeta, default_contact));
	}
	num_contacts--;
	db_set_dw(hMeta, META_PROTO, "NumContacts", (DWORD)num_contacts);

	// fix nick
	hContact = Meta_GetMostOnline(hMeta);
	Meta_CopyContactNick(hMeta, hContact);

	// fix status
	Meta_FixStatus(hMeta);

	// fix avatar
	hContact = Meta_GetMostOnlineSupporting(hMeta, PFLAGNUM_4, PF4_AVATARS);
	if (hContact) {
		PROTO_AVATAR_INFORMATIONT AI = { sizeof(AI) };
		AI.hContact = hMeta;
		AI.format = PA_FORMAT_UNKNOWN;
		_tcscpy(AI.filename, _T("X"));

		if ((int)CallProtoService(META_PROTO, PS_GETAVATARINFOT, 0, (LPARAM)&AI) == GAIR_SUCCESS)
			db_set_ts(hMeta, "ContactPhoto", "File",AI.filename);
	}
}