Ejemplo n.º 1
0
INT_PTR CVkProto::SvcGetAvatarInfo(WPARAM, LPARAM lParam)
{
	PROTO_AVATAR_INFORMATION* pai = (PROTO_AVATAR_INFORMATION*)lParam;

	ptrA szUrl(getStringA(pai->hContact, "AvatarUrl"));
	if (szUrl == NULL)
		return GAIR_NOAVATAR;

	TCHAR tszFileName[MAX_PATH];
	GetAvatarFileName(pai->hContact, tszFileName, _countof(tszFileName));
	_tcsncpy(pai->filename, tszFileName, _countof(pai->filename));

	pai->format = ProtoGetAvatarFormat(pai->filename);

	if (::_taccess(pai->filename, 0) == 0 && !getBool(pai->hContact, "NeedNewAvatar"))
		return GAIR_SUCCESS;

	if (IsOnline()) {
		AsyncHttpRequest *pReq = new AsyncHttpRequest();
		pReq->flags = NLHRF_NODUMP | NLHRF_REDIRECT;
		pReq->m_szUrl = szUrl;
		pReq->pUserInfo = new CVkSendMsgParam(pai->hContact);
		pReq->m_pFunc = &CVkProto::OnReceiveAvatar;
		pReq->requestType = REQUEST_GET;
		pReq->m_bApiReq = false;
		Push(pReq);

		debugLogA("Requested to read an avatar from '%s'", szUrl);
		return GAIR_WAITFOR;
	}

	debugLogA("No avatar");
	return GAIR_NOAVATAR;
}
Ejemplo n.º 2
0
INT_PTR CVkProto::SvcGetAvatarInfo(WPARAM wParam, LPARAM lParam)
{
	PROTO_AVATAR_INFORMATIONT* AI = (PROTO_AVATAR_INFORMATIONT*)lParam;

	ptrA szUrl( getStringA(AI->hContact, "AvatarUrl"));
	if (szUrl == NULL)
		return GAIR_NOAVATAR;

	TCHAR tszFileName[MAX_PATH];
	GetAvatarFileName(AI->hContact, tszFileName, SIZEOF(tszFileName));
	_tcsncpy(AI->filename, tszFileName, SIZEOF(AI->filename));

	AI->format = ProtoGetAvatarFormat(AI->filename);

	if (::_taccess(AI->filename, 0) == 0)
		return GAIR_SUCCESS;

	if ( IsOnline()) {
		AsyncHttpRequest *pReq = new AsyncHttpRequest();
		pReq->flags = NLHRF_NODUMP | NLHRF_REDIRECT;
		pReq->m_szUrl = szUrl;
		pReq->pUserInfo = (char*)AI->hContact;
		pReq->m_pFunc = &CVkProto::OnReceiveAvatar;
		pReq->requestType = REQUEST_GET;
		Push(pReq);

		debugLogA("Requested to read an avatar from '%s'", szUrl);
		return GAIR_WAITFOR;
	}

	debugLogA("No avatar");
	return GAIR_NOAVATAR;
}
Ejemplo n.º 3
0
void CYahooProto::ext_got_picture_checksum(const char *me, const char *who, int cksum)
{
	LOG(("ext_yahoo_got_picture_checksum for %s checksum: %d", who, cksum));

	MCONTACT hContact = getbuddyH(who);
	if (hContact == NULL) {
		LOG(("Buddy Not Found. Skipping avatar update"));
		return;
	}

	/* Last thing check the checksum and request new one if we need to */
	if (!cksum || cksum == -1) {
		setDword(hContact, "PictCK", 0);
		reset_avatar(hContact);
	}
	else {
		if (getDword(hContact, "PictCK", 0) != cksum) {
			// Now save the new checksum. No rush requesting new avatar yet.
			setDword(hContact, "PictCK", cksum);

			// Need to delete the Avatar File!!
			TCHAR szFile[MAX_PATH];
			GetAvatarFileName(hContact, szFile, _countof(szFile) - 1, 0);
			DeleteFile(szFile);

			// Reset the avatar and cleanup.
			reset_avatar(hContact);

			// Request new avatar here... (might also want to check the sharing status?)

			if (getByte("ShareAvatar", 0) == 2)
				request_avatar(who);
		}
	}
}
Ejemplo n.º 4
0
void CVkProto::OnReceiveAvatar(NETLIBHTTPREQUEST *reply, AsyncHttpRequest* pReq)
{
	if (reply->resultCode != 200 || !pReq->pUserInfo)
		return;

	PROTO_AVATAR_INFORMATION ai = { 0 };
	CVkSendMsgParam * param = (CVkSendMsgParam *)pReq->pUserInfo;
	GetAvatarFileName(param->hContact, ai.filename, _countof(ai.filename));
	ai.format = ProtoGetBufferFormat(reply->pData);

	FILE *out = _tfopen(ai.filename, _T("wb"));
	if (out == NULL) {
		ProtoBroadcastAck(param->hContact, ACKTYPE_AVATAR, ACKRESULT_FAILED, &ai);
		delete param;
		pReq->pUserInfo = NULL;
		return;
	}

	fwrite(reply->pData, 1, reply->dataLength, out);
	fclose(out);
	setByte(param->hContact, "NeedNewAvatar", 0);
	ProtoBroadcastAck(param->hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, &ai);
	delete param;
	pReq->pUserInfo = NULL;
}
Ejemplo n.º 5
0
INT_PTR __cdecl CJabberProto::JabberGetAvatarInfo(WPARAM wParam, LPARAM lParam)
{
	if (!m_options.EnableAvatars)
		return GAIR_NOAVATAR;

	PROTO_AVATAR_INFORMATIONT* AI = (PROTO_AVATAR_INFORMATIONT*)lParam;

	ptrA szHashValue( getStringA(AI->hContact, "AvatarHash"));
	if (szHashValue == NULL) {
		debugLogA("No avatar");
		return GAIR_NOAVATAR;
	}

	TCHAR tszFileName[MAX_PATH];
	GetAvatarFileName(AI->hContact, tszFileName, SIZEOF(tszFileName));
	_tcsncpy(AI->filename, tszFileName, SIZEOF(AI->filename));

	AI->format = (AI->hContact == NULL) ? PA_FORMAT_PNG : getByte(AI->hContact, "AvatarType", 0);

	if (::_taccess(AI->filename, 0) == 0) {
		ptrA szSavedHash( getStringA(AI->hContact, "AvatarSaved"));
		if (szSavedHash != NULL && !strcmp(szSavedHash, szHashValue)) {
			debugLogA("Avatar is Ok: %s == %s", szSavedHash, szHashValue);
			return GAIR_SUCCESS;
		}
	}

	if ((wParam & GAIF_FORCE) != 0 && AI->hContact != NULL && m_bJabberOnline) {
		ptrT tszJid( getTStringA(AI->hContact, "jid"));
		if (tszJid != NULL) {
			JABBER_LIST_ITEM *item = ListGetItemPtr(LIST_ROSTER, tszJid);
			if (item != NULL) {
				BOOL isXVcard = getByte(AI->hContact, "AvatarXVcard", 0);

				TCHAR szJid[JABBER_MAX_JID_LEN]; szJid[0] = 0;
				if (item->arResources.getCount() != NULL && !isXVcard)
					if (TCHAR *bestResName = ListGetBestClientResourceNamePtr(tszJid))
						mir_sntprintf(szJid, SIZEOF(szJid), _T("%s/%s"), tszJid, bestResName);

				if (szJid[0] == 0)
					_tcsncpy_s(szJid, SIZEOF(szJid), tszJid, _TRUNCATE);

				debugLogA("Rereading %s for %S", isXVcard ? JABBER_FEAT_VCARD_TEMP : JABBER_FEAT_AVATAR, szJid);

				m_ThreadInfo->send((isXVcard) ?
					XmlNodeIq( AddIQ(&CJabberProto::OnIqResultGetVCardAvatar, JABBER_IQ_TYPE_GET, szJid)) << XCHILDNS(_T("vCard"), JABBER_FEAT_VCARD_TEMP) :
					XmlNodeIq( AddIQ(&CJabberProto::OnIqResultGetClientAvatar, JABBER_IQ_TYPE_GET, szJid)) << XQUERY(JABBER_FEAT_AVATAR));
				return GAIR_WAITFOR;
			}
		}
	}

	debugLogA("No avatar");
	return GAIR_NOAVATAR;
}
Ejemplo n.º 6
0
int				
PokerData::SetUserAvatar(int nUserId, _String &sAvatarFileName, int nAvatarId /*= -1*/, bool bIsPrivateAvatar /*= true*/){
	if( nUserId <= 0 ) return 0;
	SetUserAvatarProc proc;
	proc.m_nAvatarId		= nAvatarId;
	proc.m_nUserId			= nUserId;
	proc.m_bIsPrivateAvatar	= bIsPrivateAvatar;

	int nRet = 0;
	if( m_pDataMan->ExecuteProc(&proc) && proc.m_nSuccess == 0 ){
		int nAvatarIdNew	= proc.m_nAvatarIdNew;
		nRet				= nAvatarIdNew;
		if( nAvatarId != nAvatarIdNew ){
			sAvatarFileName = GetAvatarFileName(nAvatarIdNew);

			// Update new avatars file name. {{
			PokerAvatar avatarNew;
			avatarNew.m_nId				= nAvatarIdNew;
			avatarNew.m_sAvatarFileName = sAvatarFileName;
			CStringVector arrDirtyFields;
			arrDirtyFields.push_back(_T("AVATAR_FILE_NAME"));
			if( m_pDataMan->SaveRecord(&avatarNew, &arrDirtyFields) ){
				/*
				PokerAvatar* pAvatarInfoNew			= new PokerAvatar();
				pAvatarInfoNew->m_nId				= proc.m_nAvatarIdNew;
				pAvatarInfoNew->m_nPrivateUserId	= nUserId;
				pAvatarInfoNew->m_sAvatarFileName	= sAvatarFileName;
				pAvatarInfoNew->m_recStatus			= 0;
				m_listAvatars.Add(pAvatarInfoNew);
				*/
				}
			// }}
			}
		else
			sAvatarFileName = GetAvatarFileName(nAvatarId);
		nAvatarIdNew = proc.m_nAvatarIdNew;
		}
	return nRet;
	}
Ejemplo n.º 7
0
INT_PTR __cdecl CJabberProto::JabberGetAvatar(WPARAM wParam, LPARAM lParam)
{
	TCHAR *buf = (TCHAR*)wParam;
	int size = (int)lParam;

	if (buf == NULL || size <= 0)
		return -1;

	if (!m_options.EnableAvatars)
		return -2;

	GetAvatarFileName(NULL, buf, size);
	return 0;
}
Ejemplo n.º 8
0
void CVkProto::OnReceiveAvatar(NETLIBHTTPREQUEST *reply, AsyncHttpRequest* pReq)
{
	if (reply->resultCode != 200)
		return;

	PROTO_AVATAR_INFORMATIONT AI = { sizeof(AI) };
	GetAvatarFileName((MCONTACT)pReq->pUserInfo, AI.filename, SIZEOF(AI.filename));
	AI.format = ProtoGetBufferFormat(reply->pData);

	FILE *out = _tfopen(AI.filename, _T("wb"));
	if (out == NULL) {
		ProtoBroadcastAck((MCONTACT)pReq->pUserInfo, ACKTYPE_AVATAR, ACKRESULT_FAILED, &AI, 0);
		return;
	}

	fwrite(reply->pData, 1, reply->dataLength, out);
	fclose(out);
	ProtoBroadcastAck((MCONTACT)pReq->pUserInfo, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, &AI, 0);
}
Ejemplo n.º 9
0
void CVkProto::SetAvatarUrl(MCONTACT hContact, LPCTSTR ptszUrl)
{
	ptrT oldUrl( getTStringA(hContact, "AvatarUrl"));
	if (!lstrcmp(ptszUrl, oldUrl))
		return;

	if (ptszUrl == NULL) {
		delSetting(hContact, "AvatarUrl");
		ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, NULL, 0);
	}
	else {
		setTString(hContact, "AvatarUrl", ptszUrl);

		PROTO_AVATAR_INFORMATIONT AI = { sizeof(AI) };
		AI.hContact = hContact;
		GetAvatarFileName(AI.hContact, AI.filename, SIZEOF(AI.filename));
		AI.format = ProtoGetAvatarFormat(AI.filename);
		ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, (HANDLE)&AI, 0);
	}
}
Ejemplo n.º 10
0
bool
PokerData::LoadAvatarData(int nAvatarId, GrowableMemory* pImageData){
	ASSERT(pImageData && nAvatarId > 0);
	_String sAvatarImageFile;
	sAvatarImageFile.Format(_T("%s\\%s"), m_sAvatarsFolder.GetBuffer(), GetAvatarFileName(nAvatarId).GetBuffer());
	Path::BuildFullPath(sAvatarImageFile);

	int		nSize = 0;
	BYTE*	lpContent = NULL;
	if( !Path::ReadFileContent(sAvatarImageFile, lpContent, nSize) )
		return NULL;

	pImageData->SetBufferSize(nSize);
	pImageData->SetUsedBufferSize(0);
	pImageData->AddBytes(lpContent, nSize);
	pImageData->SetUsedBufferSize(0);
	
	delete [] lpContent;
	return true;
	}
Ejemplo n.º 11
0
PokerAvatar*
PokerData::LoadAvatarInfo(int nAvatarId){
	_String sAvatarImageFile;
	sAvatarImageFile.Format(_T("%s\\%s"), m_sAvatarsFolder.GetBuffer(), GetAvatarFileName(nAvatarId).GetBuffer());
	Path::BuildFullPath(sAvatarImageFile);

	int		nSize = 0;
	BYTE*	lpContent = NULL;
	if( !Path::ReadFileContent(sAvatarImageFile, lpContent, nSize) )
		return NULL;

	PokerAvatar* pAvatarNew			= new PokerAvatar();
	pAvatarNew->m_nId				= nAvatarId;
	pAvatarNew->m_nPrivateUserId	= 0;
	pAvatarNew->m_recStatus			= 0;
	pAvatarNew->m_binImage.SetBinarySize(nSize, lpContent);

	delete [] lpContent;
	return pAvatarNew;
	}
Ejemplo n.º 12
0
void CVkProto::SetAvatarUrl(MCONTACT hContact, CMString &tszUrl)
{
	CMString oldUrl(getTStringA(hContact, "AvatarUrl"));

	if (tszUrl == oldUrl)
		return;

	if (tszUrl.IsEmpty()) {
		delSetting(hContact, "AvatarUrl");
		ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, NULL);
	}
	else {
		setTString(hContact, "AvatarUrl", tszUrl);
		setByte(hContact,"NeedNewAvatar", 1);
		PROTO_AVATAR_INFORMATION ai = { 0 };
		ai.hContact = hContact;
		GetAvatarFileName(ai.hContact, ai.filename, _countof(ai.filename));
		ai.format = ProtoGetAvatarFormat(ai.filename);
		ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, (HANDLE)&ai);
	}
}
Ejemplo n.º 13
0
BOOL CJabberProto::OnIqRequestAvatar(HXML, CJabberIqInfo *pInfo)
{
	if (!m_options.EnableAvatars)
		return TRUE;

	int pictureType = m_options.AvatarType;
	if (pictureType == PA_FORMAT_UNKNOWN)
		return TRUE;

	TCHAR *szMimeType;
	switch (pictureType) {
	case PA_FORMAT_JPEG:	 szMimeType = _T("image/jpeg");   break;
	case PA_FORMAT_GIF:	 szMimeType = _T("image/gif");    break;
	case PA_FORMAT_PNG:	 szMimeType = _T("image/png");    break;
	case PA_FORMAT_BMP:	 szMimeType = _T("image/bmp");    break;
	default:	return TRUE;
	}

	TCHAR szFileName[MAX_PATH];
	GetAvatarFileName(NULL, szFileName, _countof(szFileName));

	FILE* in = _tfopen(szFileName, _T("rb"));
	if (in == NULL)
		return TRUE;

	long bytes = _filelength(_fileno(in));
	ptrA buffer((char*)mir_alloc(bytes * 4 / 3 + bytes + 1000));
	if (buffer == NULL) {
		fclose(in);
		return TRUE;
	}

	fread(buffer, bytes, 1, in);
	fclose(in);

	ptrA str(mir_base64_encode((PBYTE)(char*)buffer, bytes));
	m_ThreadInfo->send(XmlNodeIq(_T("result"), pInfo) << XQUERY(JABBER_FEAT_AVATAR) << XCHILD(_T("query"), _A2T(str)) << XATTR(_T("mimetype"), szMimeType));
	return TRUE;
}
Ejemplo n.º 14
0
void __cdecl CYahooProto::recv_avatarthread(void *pavt)
{
	struct avatar_info *avt = (avatar_info*)pavt;
	int 	error = 0;
	TCHAR  buf[4096];

	if (avt == NULL) {
		debugLogA("AVT IS NULL!!!");
		return;
	}

	if (!m_bLoggedIn) {
		debugLogA("We are not logged in!!!");
		return;
	}

	//    ProtoBroadcastAck(hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE) 1, 0);

	LOG(("yahoo_recv_avatarthread who:%s url:%s checksum: %d", avt->who, avt->pic_url, avt->cksum));

	MCONTACT hContact = getbuddyH(avt->who);

	if (!hContact) {
		LOG(("ERROR: Can't find buddy: %s", avt->who));
		error = 1;
	}
	else if (!error) {
		setDword(hContact, "PictCK", avt->cksum);
		setDword(hContact, "PictLoading", 1);
	}

	if (!error) {

		NETLIBHTTPREQUEST nlhr = { 0 }, *nlhrReply;

		nlhr.cbSize = sizeof(nlhr);
		nlhr.requestType = REQUEST_GET;
		nlhr.flags = NLHRF_NODUMP | NLHRF_GENERATEHOST | NLHRF_SMARTAUTHHEADER;
		nlhr.szUrl = avt->pic_url;

		nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)m_hNetlibUser, (LPARAM)&nlhr);

		if (nlhrReply) {

			if (nlhrReply->resultCode != 200) {
				LOG(("Update server returned '%d' instead of 200. It also sent the following: %s", nlhrReply->resultCode, nlhrReply->szResultDescr));
				// make sure it's a real problem and not a problem w/ our connection
				yahoo_send_picture_info(m_id, avt->who, 3, avt->pic_url, avt->cksum);
				error = 1;
			}
			else if (nlhrReply->dataLength < 1 || nlhrReply->pData == NULL) {
				LOG(("No data??? Got %d bytes.", nlhrReply->dataLength));
				error = 1;
			}
			else {
				GetAvatarFileName(hContact, buf, 1024, getByte(hContact, "AvatarType", 0));
				DeleteFile(buf);

				LOG(("Saving file: %s size: %u", buf, nlhrReply->dataLength));
				HANDLE myhFile = CreateFile(buf,
					GENERIC_WRITE,
					FILE_SHARE_WRITE,
					NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);

				if (myhFile != INVALID_HANDLE_VALUE) {
					DWORD c;

					WriteFile(myhFile, nlhrReply->pData, nlhrReply->dataLength, &c, NULL);
					CloseHandle(myhFile);

					setDword(hContact, "PictLastCheck", 0);
				}
				else {
					LOG(("Can not open file for writing: %s", buf));
					error = 1;
				}
			}
			CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply);
		}
	}

	if (getDword(hContact, "PictCK", 0) != avt->cksum) {
		LOG(("WARNING: Checksum updated during download?!"));
		error = 1; /* don't use this one? */
	}

	setDword(hContact, "PictLoading", 0);
	LOG(("File download complete!?"));

	if (error)
		buf[0] = '\0';

	free(avt->who);
	free(avt->pic_url);
	free(avt);

	PROTO_AVATAR_INFORMATION ai;
	ai.format = PA_FORMAT_PNG;
	ai.hContact = hContact;
	_tcsncpy_s(ai.filename, buf, _TRUNCATE);

	if (error)
		setDword(hContact, "PictCK", 0);

	ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, !error ? ACKRESULT_SUCCESS : ACKRESULT_FAILED, (HANDLE)&ai, 0);
}
Ejemplo n.º 15
0
INT_PTR __cdecl CJabberProto::JabberSetAvatar(WPARAM, LPARAM lParam)
{
	TCHAR *tszFileName = (TCHAR*)lParam;

	if (m_bJabberOnline) {
		SetServerVcard(TRUE, tszFileName);
		SendPresence(m_iDesiredStatus, false);
	}
	else if (tszFileName == NULL || tszFileName[0] == 0) {
		// Remove avatar
		TCHAR tFileName[ MAX_PATH ];
		GetAvatarFileName(NULL, tFileName, MAX_PATH);
		DeleteFile(tFileName);

		delSetting("AvatarSaved");
		delSetting("AvatarHash");
	}
	else {
		int fileIn = _topen(tszFileName, O_RDWR | O_BINARY, S_IREAD | S_IWRITE);
		if (fileIn == -1) {
			mir_free(tszFileName);
			return 1;
		}

		long dwPngSize = _filelength(fileIn);
		char *pResult = new char[ dwPngSize ];
		if (pResult == NULL) {
			_close(fileIn);
			mir_free(tszFileName);
			return 2;
		}

		_read(fileIn, pResult, dwPngSize);
		_close(fileIn);

		BYTE digest[MIR_SHA1_HASH_SIZE];
		mir_sha1_ctx sha1ctx;
		mir_sha1_init(&sha1ctx);
		mir_sha1_append(&sha1ctx, (BYTE*)pResult, dwPngSize);
		mir_sha1_finish(&sha1ctx, digest);

		TCHAR tFileName[MAX_PATH];
		GetAvatarFileName(NULL, tFileName, MAX_PATH);
		DeleteFile(tFileName);

		char buf[MIR_SHA1_HASH_SIZE*2+1];
		bin2hex(digest, sizeof(digest), buf);

		m_options.AvatarType = ProtoGetBufferFormat(pResult);

		GetAvatarFileName(NULL, tFileName, MAX_PATH);
		FILE *out = _tfopen(tFileName, _T("wb"));
		if (out != NULL) {
			fwrite(pResult, dwPngSize, 1, out);
			fclose(out);
		}
		delete[] pResult;

		setString("AvatarSaved", buf);
	}

	return 0;
}
Ejemplo n.º 16
0
INT_PTR __cdecl CYahooProto::GetAvatarInfo(WPARAM wParam, LPARAM lParam)
{
	PROTO_AVATAR_INFORMATION* pai = (PROTO_AVATAR_INFORMATION*)lParam;
	DBVARIANT dbv;
	int avtType;

	if (!getString(pai->hContact, YAHOO_LOGINID, &dbv)) {
		debugLogA("[YAHOO_GETAVATARINFO] For: %s", dbv.pszVal);
		db_free(&dbv);
	}
	else {
		debugLogA("[YAHOO_GETAVATARINFO]");
	}

	if (!getByte("ShowAvatars", 1) || !m_bLoggedIn) {
		debugLogA("[YAHOO_GETAVATARINFO] %s", m_bLoggedIn ? "We are not using/showing avatars!" : "We are not logged in. Can't load avatars now!");

		return GAIR_NOAVATAR;
	}

	avtType = getByte(pai->hContact, "AvatarType", 0);
	debugLogA("[YAHOO_GETAVATARINFO] Avatar Type: %d", avtType);

	if (avtType != 2) {
		if (avtType != 0)
			debugLogA("[YAHOO_GETAVATARINFO] Not handling this type yet!");

		return GAIR_NOAVATAR;
	}

	if (getDword(pai->hContact, "PictCK", 0) == 0)
		return GAIR_NOAVATAR;

	GetAvatarFileName(pai->hContact, pai->filename, _countof(pai->filename), getByte(pai->hContact, "AvatarType", 0));
	pai->format = PA_FORMAT_PNG;
	debugLogA("[YAHOO_GETAVATARINFO] filename: %s", pai->filename);

	if (_taccess(pai->filename, 0) == 0)
		return GAIR_SUCCESS;

	if ((wParam & GAIF_FORCE) != 0 && pai->hContact != NULL) {
		/* need to request it again? */
		if (getDword(pai->hContact, "PictLoading", 0) != 0 &&
			(time(NULL) - getDword(pai->hContact, "PictLastCheck", 0) < 500)) {
			debugLogA("[YAHOO_GETAVATARINFO] Waiting for avatar to load!");
			return GAIR_WAITFOR;
		}
		else if (m_bLoggedIn) {
			DBVARIANT dbv;

			if (!getString(pai->hContact, YAHOO_LOGINID, &dbv)) {
				debugLogA("[YAHOO_GETAVATARINFO] Requesting avatar!");

				request_avatar(dbv.pszVal);
				db_free(&dbv);

				return GAIR_WAITFOR;
			}
			else {
				debugLogA("[YAHOO_GETAVATARINFO] Can't retrieve user id?!");
			}
		}
	}

	debugLogA("[YAHOO_GETAVATARINFO] NO AVATAR???");
	return GAIR_NOAVATAR;
}
Ejemplo n.º 17
0
void CIcqProto::GetFullAvatarFileName(int dwUin, const char *szUid, int dwFormat, TCHAR *pszDest, size_t cbLen)
{
	GetAvatarFileName(dwUin, szUid, pszDest, cbLen);
	AddAvatarExt(dwFormat, pszDest);
}
Ejemplo n.º 18
0
// handle Contact's avatar hash
void CIcqProto::handleAvatarContactHash(DWORD dwUIN, char *szUID, MCONTACT hContact, BYTE *pHash, size_t nHashLen)
{
	int bJob = FALSE;
	BOOL avatarInfoPresent = FALSE;
	int avatarType = -1;
	BYTE *pAvatarHash = NULL;
	size_t cbAvatarHash = 0;
	BYTE emptyItem[0x10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

	if (!m_bAvatarsEnabled || nHashLen < 4)
		return; // only if enabled

	while (nHashLen >= 4) { // parse online message items one by one
		WORD itemType = pHash[0] << 8 | pHash[1];
		size_t itemLen = pHash[3];

		// just some validity check
		if (itemLen + 4 > nHashLen)
			itemLen = nHashLen - 4;

		if (itemLen && memcmp(pHash + 4, emptyItem, itemLen > 0x10 ? 0x10 : itemLen)) {
			// Item types
			// 0000: AIM mini avatar
			// 0001: AIM/ICQ avatar ID/hash (len 5 or 16 bytes)
			// 0002: iChat online message
			// 0008: ICQ Flash avatar hash (16 bytes)
			// 0009: iTunes music store link
			// 000C: ICQ contact photo (16 bytes)
			// 000D: Last update time of online message
			// 000E: Status mood
			if (itemType == AVATAR_HASH_MINI && itemLen == 0x05 && avatarType == -1) { // mini avatar
				pAvatarHash = pHash;
				cbAvatarHash = itemLen + 4;
				avatarType = itemType;
			}
			else if (itemType == AVATAR_HASH_STATIC && (itemLen == 0x05 || itemLen == 0x10) && (avatarType == -1 || avatarType == AVATAR_HASH_MINI)) { // normal avatar
				pAvatarHash = pHash;
				cbAvatarHash = itemLen + 4;
				avatarType = itemType;
			}
			else if (itemType == AVATAR_HASH_FLASH && itemLen == 0x10 && (avatarType == -1 || avatarType == AVATAR_HASH_MINI || avatarType == AVATAR_HASH_STATIC)) { // flash avatar
				pAvatarHash = pHash;
				cbAvatarHash = itemLen + 4;
				avatarType = itemType;
			}
			else if (itemType == AVATAR_HASH_PHOTO && itemLen == 0x10) { // big avatar (ICQ 6+)
				pAvatarHash = pHash;
				cbAvatarHash = itemLen + 4;
				avatarType = itemType;
			}
		}
		else if ((itemLen == 0) && (itemType == AVATAR_HASH_MINI || itemType == AVATAR_HASH_STATIC || itemType == AVATAR_HASH_FLASH || itemType == AVATAR_HASH_PHOTO))
			// empty item - indicating that avatar of that type was removed
			avatarInfoPresent = TRUE;

		pHash += itemLen + 4;
		nHashLen -= itemLen + 4;
	}

	if (avatarType != -1) { // check settings, should we request avatar immediatelly?
		DBVARIANT dbv = { DBVT_DELETED };
		TCHAR tszAvatar[MAX_PATH * 2 + 4];
		BYTE bAutoLoad = getByte("AvatarsAutoLoad", DEFAULT_LOAD_AVATARS);

		if ((avatarType == AVATAR_HASH_STATIC || avatarType == AVATAR_HASH_MINI) && cbAvatarHash == 0x09 && !memcmp(pAvatarHash + 4, hashEmptyAvatar + 4, 0x05)) { // empty avatar - unlink image, clear hash
			if (!getSetting(hContact, "AvatarHash", &dbv)) { // contact had avatar, clear hash, notify UI
				db_free(&dbv);
				debugLogA("%s has removed Avatar.", strUID(dwUIN, szUID));

				delSetting(hContact, "AvatarHash");
				ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL, 0);
			}
			else debugLogA("%s has empty Avatar.", strUID(dwUIN, szUID));
			return;
		}

		if (getSetting(hContact, "AvatarHash", &dbv)) { // we did not find old avatar hash, i.e. get new avatar
			int avatarState = IsAvatarChanged(hContact, pAvatarHash, cbAvatarHash);

			// check saved hash and file, if equal only store hash
			if (!avatarState) { // hashes are the same
				int dwPaFormat = getByte(hContact, "AvatarType", PA_FORMAT_UNKNOWN);

				GetFullAvatarFileName(dwUIN, szUID, dwPaFormat, tszAvatar, MAX_PATH * 2);
				if (_taccess(tszAvatar, 0) == 0) { // the file is there, link to contactphoto, save hash
					debugLogA("%s has published Avatar. Image was found in the cache.", strUID(dwUIN, szUID));

					setSettingBlob(hContact, "AvatarHash", pAvatarHash, cbAvatarHash);
					ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL, 0);
				}
				else { // the file was lost, request avatar again
					debugLogA("%s has published Avatar.", strUID(dwUIN, szUID));
					bJob = TRUE;
				}
			}
			else { // the hash is not the one we want, request avatar
				debugLogA("%s has published a new Avatar.", strUID(dwUIN, szUID));
				bJob = TRUE;
			}
		}
		else { // we found hash check if it changed or not
			if ((dbv.cpbVal != cbAvatarHash) || memcmp(dbv.pbVal, pAvatarHash, cbAvatarHash)) { // the hash is different, request new avatar
				debugLogA("%s has changed Avatar.", strUID(dwUIN, szUID));
				bJob = TRUE;
			}
			else { // the hash was not changed, check if we have the correct file
				int avatarState = IsAvatarChanged(hContact, pAvatarHash, cbAvatarHash);

				// we should have file, check if the file really exists
				if (!avatarState) {
					int dwPaFormat = getByte(hContact, "AvatarType", PA_FORMAT_UNKNOWN);
					if (dwPaFormat == PA_FORMAT_UNKNOWN) { // we do not know the format, get avatar again
						debugLogA("%s has Avatar. Image is missing.", strUID(dwUIN, szUID));
						bJob = 2;
					}
					else {
						GetFullAvatarFileName(dwUIN, szUID, dwPaFormat, tszAvatar, MAX_PATH * 2);
						if (_taccess(tszAvatar, 0) != 0) { // the file was lost, get it again
							debugLogA("%s has Avatar. Image is missing.", strUID(dwUIN, szUID));
							bJob = 2;
						}
						else debugLogA("%s has Avatar. Image was found in the cache.", strUID(dwUIN, szUID));
					}
				}
				else { // the hash is not the one we want, request avatar
					debugLogA("%s has Avatar. Image was not retrieved yet.", strUID(dwUIN, szUID));
					bJob = 2;
				}
			}
			db_free(&dbv);
		}

		if (bJob) {
			if (bJob == TRUE) { // Remove possible block - hash changed, try again.
				mir_cslock l(m_avatarsMutex);

				for (int i = 0; i < m_arAvatars.getCount(); i++) {
					avatars_request *ar = m_arAvatars[i];
					if (ar->hContact == hContact && ar->type == ART_BLOCK) { // found one, remove
						m_arAvatars.remove(i);
						delete ar;
						break;
					}
				}
			}

			setSettingBlob(hContact, "AvatarHash", pAvatarHash, cbAvatarHash);

			ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL, 0);

			if (bAutoLoad) { // auto-load is on, so request the avatar now, otherwise we are done
				GetAvatarFileName(dwUIN, szUID, tszAvatar, MAX_PATH * 2);
				GetAvatarData(hContact, dwUIN, szUID, pAvatarHash, cbAvatarHash, tszAvatar);
			} // avatar request sent or added to queue
		}
	}
	else if (avatarInfoPresent) { // hash was not found, clear the hash
		DBVARIANT dbv = { DBVT_DELETED };
		if (!getSetting(hContact, "AvatarHash", &dbv)) { // contact had avatar, clear hash, notify UI
			db_free(&dbv);
			debugLogA("%s has removed Avatar.", strUID(dwUIN, szUID));

			delSetting(hContact, "AvatarHash");
			ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL, 0);
		}
		else debugLogA("%s has no Avatar.", strUID(dwUIN, szUID));
	}
}
Ejemplo n.º 19
0
// handle Owner's avatar hash changes
void CIcqProto::handleAvatarOwnerHash(BYTE bFlags, BYTE *pData, size_t nDataLen)
{
	if (nDataLen < 0x14 || !m_bAvatarsEnabled)
		return;

	switch (bFlags) {
	case 1: // our avatar is on the server
		setSettingBlob(NULL, "AvatarHash", pData, 0x14); /// TODO: properly handle multiple avatar items (more formats)
		setUserInfo();
		{
			// here we need to find a file, check its hash, if invalid get avatar from server
			TCHAR *file = GetOwnAvatarFileName();
			if (!file) { // we have no avatar file, download from server
				debugLogA("We have no avatar, requesting from server.");

				TCHAR szFile[MAX_PATH * 2 + 4];
				GetAvatarFileName(0, NULL, szFile, MAX_PATH * 2);
				GetAvatarData(NULL, m_dwLocalUIN, NULL, pData, 0x14, szFile);
			}
			else { // we know avatar filename
				BYTE *hash = calcMD5HashOfFile(file);

				if (!hash) { // hash could not be calculated - probably missing file, get avatar from server
					debugLogA("We have no avatar, requesting from server.");

					TCHAR szFile[MAX_PATH * 2 + 4];
					GetAvatarFileName(0, NULL, szFile, MAX_PATH * 2);
					GetAvatarData(NULL, m_dwLocalUIN, NULL, pData, 0x14, szFile);
				}
				// check if we had set any avatar if yes set our, if not download from server
				else if (memcmp(hash, pData + 4, 0x10)) { // we have different avatar, sync that
					if (m_bSsiEnabled && getByte("ForceOurAvatar", 1)) { // we want our avatar, update hash
						DWORD dwPaFormat = ::ProtoGetAvatarFileFormat(file);
						BYTE pHash[0x14];

						debugLogA("Our avatar is different, setting our new hash.");

						pHash[0] = 0;
						pHash[1] = dwPaFormat == PA_FORMAT_XML ? AVATAR_HASH_FLASH : AVATAR_HASH_STATIC;
						pHash[2] = 1; // state of the hash
						pHash[3] = 0x10; // len of the hash
						memcpy((pHash + 4), hash, 0x10);
						updateServAvatarHash(pHash, 0x14);
					}
					else { // get avatar from server
						debugLogA("We have different avatar, requesting new from server.");

						TCHAR tszFile[MAX_PATH * 2 + 4];
						GetAvatarFileName(0, NULL, tszFile, MAX_PATH * 2);
						GetAvatarData(NULL, m_dwLocalUIN, NULL, pData, 0x14, tszFile);
					}
				}
				SAFE_FREE((void**)&hash);
				SAFE_FREE(&file);
			}
		}
		break;

	case 0x41: // request to upload avatar data
	case 0x81:
		// request to re-upload avatar data
		if (m_bSsiEnabled) { // we could not change serv-list if it is disabled...
			TCHAR *file = GetOwnAvatarFileName();
			if (!file) { // we have no file to upload, remove hash from server
				debugLogA("We do not have avatar, removing hash.");
				SetMyAvatar(0, 0);
				break;
			}

			DWORD dwPaFormat = ::ProtoGetAvatarFileFormat(file);
			BYTE *hash = calcMD5HashOfFile(file);
			if (!hash) { // the hash could not be calculated, remove from server
				debugLogA("We could not obtain hash, removing hash.");
				SetMyAvatar(0, 0);
			}
			else if (!memcmp(hash, pData + 4, 0x10)) { // we have the right file
				HANDLE hFile = NULL, hMap = NULL;
				BYTE *ppMap = NULL;
				long cbFileSize = 0;

				debugLogA("Uploading our avatar data.");

				if ((hFile = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE)
					if ((hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL)
						if ((ppMap = (BYTE*)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL)
							cbFileSize = GetFileSize(hFile, NULL);

				if (cbFileSize != 0)
					SetAvatarData(NULL, (WORD)(dwPaFormat == PA_FORMAT_XML ? AVATAR_HASH_FLASH : AVATAR_HASH_STATIC), ppMap, cbFileSize);

				if (ppMap != NULL) UnmapViewOfFile(ppMap);
				if (hMap != NULL)  CloseHandle(hMap);
				if (hFile != NULL) CloseHandle(hFile);
				SAFE_FREE((void**)&hash);
			}
			else {
				BYTE pHash[0x14];

				debugLogA("Our file is different, set our new hash.");

				pHash[0] = 0;
				pHash[1] = dwPaFormat == PA_FORMAT_XML ? AVATAR_HASH_FLASH : AVATAR_HASH_STATIC;
				pHash[2] = 1; // state of the hash
				pHash[3] = 0x10; // len of the hash
				memcpy((pHash + 4), hash, 0x10);
				updateServAvatarHash(pHash, 0x14);

				SAFE_FREE((void**)&hash);
			}

			SAFE_FREE(&file);
		}
		break;

	default:
		debugLogA("Received UNKNOWN Avatar Status.");
	}
}
Ejemplo n.º 20
0
INT_PTR __cdecl CYahooProto::SetMyAvatar(WPARAM wParam, LPARAM lParam)
{
	TCHAR* tszFile = (TCHAR*)lParam;
	TCHAR  tszMyFile[MAX_PATH + 1];

	GetAvatarFileName(NULL, tszMyFile, MAX_PATH, 2);

	if (tszFile == NULL) {
		debugLogA("[Deleting Avatar Info]");

		/* remove ALL our Avatar Info Keys */
		delSetting("AvatarFile");
		delSetting("AvatarHash");
		delSetting("AvatarURL");
		delSetting("AvatarTS");

		/* Send a Yahoo packet saying we don't got an avatar anymore */
		yahoo_send_picture_status(m_id, 0);

		setByte("ShareAvatar", 0);

		DeleteFile(tszMyFile);
	}
	else {
		HANDLE hFile = CreateFile(tszFile,
			GENERIC_READ,
			FILE_SHARE_READ | FILE_SHARE_WRITE,
			NULL,
			OPEN_EXISTING,
			FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
			0);

		if (hFile == INVALID_HANDLE_VALUE)
			return 1;

		DWORD dwPngSize = GetFileSize(hFile, NULL);
		BYTE *pResult = (BYTE*)malloc(dwPngSize);
		if (pResult == NULL) {
			CloseHandle(hFile);
			return 2;
		}

		DWORD dw;
		ReadFile(hFile, pResult, dwPngSize, &dw, NULL);
		CloseHandle(hFile);

		hFile = CreateFile(tszMyFile,
			GENERIC_WRITE,
			FILE_SHARE_WRITE,
			NULL,
			OPEN_ALWAYS,
			FILE_ATTRIBUTE_NORMAL, 0);
		if (hFile == INVALID_HANDLE_VALUE)
			return 1;

		WriteFile(hFile, pResult, dwPngSize, &dw, NULL);
		SetEndOfFile(hFile);
		CloseHandle(hFile);

		unsigned int hash = YAHOO_avt_hash((const char*)pResult, dwPngSize);
		free(pResult);

		if (hash) {
			LOG(("[YAHOO_SetAvatar] File: '%s' CK: %d", tszMyFile, hash));

			/* now check and make sure we don't reupload same thing over again */
			if (hash != getDword("AvatarHash", 0)) {
				setTString("AvatarFile", tszMyFile);
				setDword("TMPAvatarHash", hash);

				/*	Set Sharing to ON if it's OFF */
				if (getByte("ShareAvatar", 0) != 2) {
					setByte("ShareAvatar", 2);
					yahoo_send_picture_status(m_id, 2);
				}

				SendAvatar(tszMyFile);
			}
			else LOG(("[YAHOO_SetAvatar] Same checksum and avatar on YahooFT. Not Reuploading."));
		}
	}

	return 0;
}
Ejemplo n.º 21
0
void CYahooProto::ext_got_picture(const char *me, const char *who, const char *pic_url, int cksum, int type)
{
	MCONTACT hContact = 0;

	LOG(("[ext_yahoo_got_picture] for %s with url %s (checksum: %d) type: %d", who, pic_url, cksum, type));

	/*
	  Type:

	  1 - Send Avatar Info
	  2 - Got Avatar Info
	  3 - YIM6 didn't like my avatar? Expired? We need to invalidate and re-load
	  */
	switch (type) {
	case 1:
		{
			int cksum = 0;
			DBVARIANT dbv;

			/* need to send avatar info */
			if (!getByte("ShowAvatars", 1)) {
				LOG(("[ext_yahoo_got_picture] We are not using/showing avatars!"));
				yahoo_send_picture_update(m_id, who, 0); // no avatar (disabled)
				return;
			}

			LOG(("[ext_yahoo_got_picture] Getting ready to send info!"));
			/* need to read CheckSum */
			cksum = getDword("AvatarHash", 0);
			if (cksum) {
				if (!getString("AvatarURL", &dbv)) {
					LOG(("[ext_yahoo_got_picture] Sending url: %s checksum: %d to '%s'!", dbv.pszVal, cksum, who));
					//void yahoo_send_picture_info(int id, const char *me, const char *who, const char *pic_url, int cksum)
					yahoo_send_picture_info(m_id, who, 2, dbv.pszVal, cksum);
					db_free(&dbv);
					break;
				}
				else
					LOG(("No AvatarURL???"));

				/*
				 * Try to re-upload the avatar
				 */
				if (getByte("AvatarUL", 0) != 1) {
					// NO avatar URL??
					if (!getTString("AvatarFile", &dbv)) {
						struct _stat statbuf;

						if (_tstat(dbv.ptszVal, &statbuf) != 0) {
							LOG(("[ext_yahoo_got_picture] Avatar File Missing? Can't find file: %s", dbv.ptszVal));
						}
						else {
							setString("AvatarInv", who);
							SendAvatar(dbv.ptszVal);
						}

						db_free(&dbv);
					}
					else {
						LOG(("[ext_yahoo_got_picture] No Local Avatar File??? "));
					}
				}
				else
					LOG(("[ext_yahoo_got_picture] Another avatar upload in progress?"));
			}
		}
		break;
	case 2: /*
			  * We got Avatar Info for our buddy.
			  */
		if (!getByte("ShowAvatars", 1)) {
			LOG(("[ext_yahoo_got_picture] We are not using/showing avatars!"));
			return;
		}

		/* got avatar info, so set miranda up */
		hContact = getbuddyH(who);
		if (!hContact) {
			LOG(("[ext_yahoo_got_picture] Buddy not on my buddy list?."));
			return;
		}

		if (!cksum && pic_url) {
			const char *chk = strstr(pic_url, "chksum=");
			if (chk)
				cksum = strtol(chk + 7, NULL, 10);
		}

		if (!cksum || cksum == -1) {
			LOG(("[ext_yahoo_got_picture] Resetting avatar."));
			setDword(hContact, "PictCK", 0);
			reset_avatar(hContact);
		}
		else {
			if (pic_url == NULL) {
				LOG(("[ext_yahoo_got_picture] WARNING: Empty URL for avatar?"));
				return;
			}

			TCHAR z[1024];
			GetAvatarFileName(hContact, z, 1024, getByte(hContact, "AvatarType", 0));

			if (getDword(hContact, "PictCK", 0) != cksum || _taccess(z, 0) != 0) {

				debugLogA("[ext_yahoo_got_picture] Checksums don't match or avatar file is missing. Current: %d, New: %d",
					getDword(hContact, "PictCK", 0), cksum);

				struct avatar_info *avt = (avatar_info*)malloc(sizeof(struct avatar_info));
				avt->who = strdup(who);
				avt->pic_url = strdup(pic_url);
				avt->cksum = cksum;

				ForkThread(&CYahooProto::recv_avatarthread, avt);
			}
		}

		break;
	case 3:
		// Our Avatar is not good anymore? Need to re-upload??
		/* who, pic_url, cksum */
		{
			int mcksum = 0;
			DBVARIANT dbv;

			/* need to send avatar info */
			if (!getByte("ShowAvatars", 1)) {
				LOG(("[ext_yahoo_got_picture] We are not using/showing avatars!"));
				yahoo_send_picture_update(m_id, who, 0); // no avatar (disabled)
				return;
			}

			LOG(("[ext_yahoo_got_picture] Getting ready to send info!"));
			/* need to read CheckSum */
			mcksum = getDword("AvatarHash", 0);
			if (mcksum == 0) {
				/* this should NEVER Happen??? */
				LOG(("[ext_yahoo_got_picture] No personal checksum? and Invalidate?!"));
				yahoo_send_picture_update(m_id, who, 0); // no avatar (disabled)
				return;
			}

			LOG(("[ext_yahoo_got_picture] My Checksum: %d", mcksum));

			if (!getString("AvatarURL", &dbv)) {
				if (mir_strcmpi(pic_url, dbv.pszVal) == 0) {
					DBVARIANT dbv2;
					/*time_t  ts;
					DWORD	ae;*/

					if (mcksum != cksum)
						LOG(("[ext_yahoo_got_picture] WARNING: Checksums don't match!"));

					/*time(&ts);
					ae = getDword("AvatarExpires", 0);

					if (ae != 0 && ae > (ts - 300)) {
					LOG(("[ext_yahoo_got_picture] Current Time: %lu Expires: %lu ", ts, ae));
					LOG(("[ext_yahoo_got_picture] We just reuploaded! Stop screwing with Yahoo FT. "));

					// don't leak stuff
					db_free(&dbv);

					break;
					}*/

					LOG(("[ext_yahoo_got_picture] Buddy: %s told us this is bad??Expired??. Re-uploading", who));
					delSetting("AvatarURL");

					if (!getTString("AvatarFile", &dbv2)) {
						setString("AvatarInv", who);
						SendAvatar(dbv2.ptszVal);
						db_free(&dbv2);
					}
					else {
						LOG(("[ext_yahoo_got_picture] No Local Avatar File??? "));
					}
				}
				else {
					LOG(("[ext_yahoo_got_picture] URL doesn't match? Tell them the right thing!!!"));
					yahoo_send_picture_info(m_id, who, 2, dbv.pszVal, mcksum);
				}
				// don't leak stuff
				db_free(&dbv);
			}
			else {
				LOG(("[ext_yahoo_got_picture] no AvatarURL?"));
			}
		}
		break;
	default:
		LOG(("[ext_yahoo_got_picture] Unknown request/packet type exiting!"));
	}

	LOG(("ext_yahoo_got_picture exiting"));
}
Ejemplo n.º 22
0
void CJabberProto::SetServerVcard(BOOL bPhotoChanged, TCHAR* szPhotoFileName)
{
	if (!m_bJabberOnline) return;

	int  i;
	char idstr[33];

	XmlNodeIq iq(AddIQ(&CJabberProto::OnIqResultSetVcard, JABBER_IQ_TYPE_SET));
	HXML v = iq << XCHILDNS(_T("vCard"), JABBER_FEAT_VCARD_TEMP);

	AppendVcardFromDB(v, "FN", "FullName");

	HXML n = v << XCHILD(_T("N"));
	AppendVcardFromDB(n, "GIVEN", "FirstName");
	AppendVcardFromDB(n, "MIDDLE", "MiddleName");
	AppendVcardFromDB(n, "FAMILY", "LastName");

	AppendVcardFromDB(v, "NICKNAME", "Nick");
	AppendVcardFromDB(v, "BDAY", "BirthDate");
	AppendVcardFromDB(v, "GENDER", "GenderString");

	for (i = 0;; i++) {
		mir_snprintf(idstr, "e-mail%d", i);
		ptrT email(getTStringA(idstr));
		if (email == NULL)
			break;

		HXML e = v << XCHILD(_T("EMAIL"), email);
		AppendVcardFromDB(e, "USERID", idstr);

		mir_snprintf(idstr, "e-mailFlag%d", i);
		WORD nFlag = getWord(idstr, 0);
		if (nFlag & JABBER_VCEMAIL_HOME)     e << XCHILD(_T("HOME"));
		if (nFlag & JABBER_VCEMAIL_WORK)     e << XCHILD(_T("WORK"));
		if (nFlag & JABBER_VCEMAIL_INTERNET) e << XCHILD(_T("INTERNET"));
		if (nFlag & JABBER_VCEMAIL_X400)     e << XCHILD(_T("X400"));
	}

	n = v << XCHILD(_T("ADR"));
	n << XCHILD(_T("HOME"));
	AppendVcardFromDB(n, "STREET", "Street");
	AppendVcardFromDB(n, "EXTADR", "Street2");
	AppendVcardFromDB(n, "EXTADD", "Street2");	// for compatibility with client using old vcard format
	AppendVcardFromDB(n, "LOCALITY", "City");
	AppendVcardFromDB(n, "REGION", "State");
	AppendVcardFromDB(n, "PCODE", "ZIP");
	AppendVcardFromDB(n, "CTRY", "Country");
	AppendVcardFromDB(n, "COUNTRY", "Country");	// for compatibility with client using old vcard format

	n = v << XCHILD(_T("ADR"));
	n << XCHILD(_T("WORK"));
	AppendVcardFromDB(n, "STREET", "CompanyStreet");
	AppendVcardFromDB(n, "EXTADR", "CompanyStreet2");
	AppendVcardFromDB(n, "EXTADD", "CompanyStreet2");	// for compatibility with client using old vcard format
	AppendVcardFromDB(n, "LOCALITY", "CompanyCity");
	AppendVcardFromDB(n, "REGION", "CompanyState");
	AppendVcardFromDB(n, "PCODE", "CompanyZIP");
	AppendVcardFromDB(n, "CTRY", "CompanyCountry");
	AppendVcardFromDB(n, "COUNTRY", "CompanyCountry");	// for compatibility with client using old vcard format

	n = v << XCHILD(_T("ORG"));
	AppendVcardFromDB(n, "ORGNAME", "Company");
	AppendVcardFromDB(n, "ORGUNIT", "CompanyDepartment");

	AppendVcardFromDB(v, "TITLE", "CompanyPosition");
	AppendVcardFromDB(v, "ROLE", "Role");
	AppendVcardFromDB(v, "URL", "Homepage");
	AppendVcardFromDB(v, "DESC", "About");

	for (i = 0;; i++) {
		mir_snprintf(idstr, "Phone%d", i);
		ptrT phone(getTStringA(idstr));
		if (phone == NULL)
			break;

		n = v << XCHILD(_T("TEL"));
		AppendVcardFromDB(n, "NUMBER", idstr);

		mir_snprintf(idstr, "PhoneFlag%d", i);
		WORD nFlag = getWord(idstr, 0);
		if (nFlag & JABBER_VCTEL_HOME)  n << XCHILD(_T("HOME"));
		if (nFlag & JABBER_VCTEL_WORK)  n << XCHILD(_T("WORK"));
		if (nFlag & JABBER_VCTEL_VOICE) n << XCHILD(_T("VOICE"));
		if (nFlag & JABBER_VCTEL_FAX)   n << XCHILD(_T("FAX"));
		if (nFlag & JABBER_VCTEL_PAGER) n << XCHILD(_T("PAGER"));
		if (nFlag & JABBER_VCTEL_MSG)   n << XCHILD(_T("MSG"));
		if (nFlag & JABBER_VCTEL_CELL)  n << XCHILD(_T("CELL"));
		if (nFlag & JABBER_VCTEL_VIDEO) n << XCHILD(_T("VIDEO"));
		if (nFlag & JABBER_VCTEL_BBS)   n << XCHILD(_T("BBS"));
		if (nFlag & JABBER_VCTEL_MODEM) n << XCHILD(_T("MODEM"));
		if (nFlag & JABBER_VCTEL_ISDN)  n << XCHILD(_T("ISDN"));
		if (nFlag & JABBER_VCTEL_PCS)   n << XCHILD(_T("PCS"));
	}

	TCHAR szAvatarName[MAX_PATH], *szFileName;
	GetAvatarFileName(NULL, szAvatarName, _countof(szAvatarName));
	if (bPhotoChanged)
		szFileName = szPhotoFileName;
	else
		szFileName = szAvatarName;

	// Set photo element, also update the global jabberVcardPhotoFileName to reflect the update
	debugLog(_T("Before update, file name = %s"), szFileName);
	if (szFileName == NULL || szFileName[0] == 0) {
		v << XCHILD(_T("PHOTO"));
		DeleteFile(szAvatarName);
		delSetting("AvatarSaved");
		delSetting("AvatarHash");
	}
	else {
		debugLog(_T("Saving picture from %s"), szFileName);

		struct _stat st;
		if (_tstat(szFileName, &st) >= 0) {
			// Note the FILE_SHARE_READ attribute so that the CopyFile can succeed
			HANDLE hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
			if (hFile != INVALID_HANDLE_VALUE) {
				ptrA buffer((char*)mir_alloc(st.st_size));
				if (buffer != NULL) {
					DWORD nRead;
					if (ReadFile(hFile, buffer, st.st_size, &nRead, NULL)) {
						ptrA str(mir_base64_encode((PBYTE)(LPSTR)buffer, nRead));
						if (str != NULL) {
							n = v << XCHILD(_T("PHOTO"));
							TCHAR *szFileType;
							switch (ProtoGetBufferFormat(buffer)) {
								case PA_FORMAT_PNG:  szFileType = _T("image/png");   break;
								case PA_FORMAT_GIF:  szFileType = _T("image/gif");   break;
								case PA_FORMAT_BMP:  szFileType = _T("image/bmp");   break;
								default:             szFileType = _T("image/jpeg");  break;
							}
							n << XCHILD(_T("TYPE"), szFileType);
							n << XCHILD(_T("BINVAL"), _A2T(str));

							// NEED TO UPDATE OUR AVATAR HASH:
							BYTE digest[MIR_SHA1_HASH_SIZE];
							mir_sha1_ctx sha1ctx;
							mir_sha1_init(&sha1ctx);
							mir_sha1_append(&sha1ctx, (BYTE*)(LPSTR)buffer, nRead);
							mir_sha1_finish(&sha1ctx, digest);

							char buf[MIR_SHA1_HASH_SIZE * 2 + 1];
							bin2hex(digest, sizeof(digest), buf);

							m_options.AvatarType = ProtoGetBufferFormat(buffer);

							if (bPhotoChanged) {
								DeleteFile(szAvatarName);

								GetAvatarFileName(NULL, szAvatarName, _countof(szAvatarName));
								CopyFile(szFileName, szAvatarName, FALSE);
							}

							setString("AvatarHash", buf);
							setString("AvatarSaved", buf);
						}
					}
				}
				CloseHandle(hFile);
			}
		}
	}

	m_ThreadInfo->send(iq);
}