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; }
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; }
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); } } }
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; }
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; }
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; }
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; }
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); }
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); } }
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; }
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; }
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); } }
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; }
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); }
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; }
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; }
void CIcqProto::GetFullAvatarFileName(int dwUin, const char *szUid, int dwFormat, TCHAR *pszDest, size_t cbLen) { GetAvatarFileName(dwUin, szUid, pszDest, cbLen); AddAvatarExt(dwFormat, pszDest); }
// 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)); } }
// 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."); } }
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; }
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")); }
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); }