summaryrefslogtreecommitdiff
path: root/protocols/Yahoo/avatar.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Yahoo/avatar.cpp')
-rw-r--r--protocols/Yahoo/avatar.cpp920
1 files changed, 920 insertions, 0 deletions
diff --git a/protocols/Yahoo/avatar.cpp b/protocols/Yahoo/avatar.cpp
new file mode 100644
index 0000000000..4ad7233cb9
--- /dev/null
+++ b/protocols/Yahoo/avatar.cpp
@@ -0,0 +1,920 @@
+/*
+ * $Id: avatar.cpp 14178 2012-03-11 15:02:54Z borkra $
+ *
+ * myYahoo Miranda Plugin
+ *
+ * Authors: Gennady Feldman (aka Gena01)
+ * Laurent Marechal (aka Peorth)
+ *
+ * This code is under GPL and is based on AIM, MSN and Miranda source code.
+ * I want to thank Robert Rainwater and George Hazan for their code and support
+ * and for answering some of my questions during development of this plugin.
+ */
+
+#include "yahoo.h"
+
+#include <sys/stat.h>
+
+#include <m_langpack.h>
+#include "m_folders.h"
+#include "avatar.h"
+#include "resource.h"
+
+/*
+ *31 bit hash function - this is based on g_string_hash function from glib
+ */
+
+int YAHOO_avt_hash(const char *key, DWORD len)
+{
+ /*
+ Thank you Pidgin and Kopete devs. It seems that both clients are using this code now.
+
+ */
+
+ const unsigned char *p = (const unsigned char *)key;
+ int checksum = 0, g, i = len;
+
+ while(i--) {
+ checksum = (checksum << 4) + *p++;
+
+ if((g = (checksum & 0xf0000000)) != 0)
+ checksum ^= g >> 23;
+
+ checksum &= ~g;
+ }
+
+ return checksum;
+}
+
+/**************** Send Avatar ********************/
+
+void upload_avt(int id, int fd, int error, void *data)
+{
+ struct yahoo_file_info *sf = (struct yahoo_file_info*) data;
+ unsigned long size = 0;
+ char buf[1024];
+ int rw; /* */
+ DWORD dw; /* needed for ReadFile */
+ HANDLE myhFile;
+
+ if (fd < 1 || error) {
+ LOG(("[get_fd] Connect Failed!"));
+ return;
+ }
+
+ myhFile = CreateFileA(sf->filename,
+ GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
+ 0);
+
+ if (myhFile == INVALID_HANDLE_VALUE) {
+ LOG(("[get_fd] Can't open file for reading?!"));
+ return;
+ }
+
+ LOG(("Sending file: %s size: %ld", sf->filename, sf->filesize));
+
+ do {
+ rw = ReadFile(myhFile, buf, sizeof(buf), &dw, NULL);
+
+ if (rw != 0) {
+ rw = Netlib_Send((HANDLE)fd, buf, dw, MSG_NODUMP);
+
+ if (rw < 1) {
+ LOG(("Upload Failed. Send error?"));
+ //ShowError(Translate("Yahoo Error"), Translate("Avatar upload failed!?!"));
+ break;
+ }
+
+ size += rw;
+ }
+ } while (rw >= 0 && size < sf->filesize);
+
+ CloseHandle(myhFile);
+
+ do {
+ rw = Netlib_Recv((HANDLE)fd, buf, sizeof(buf), 0);
+ LOG(("Got: %d bytes", rw));
+ } while (rw > 0);
+
+ LOG(("File send complete!"));
+}
+
+void __cdecl CYahooProto::send_avt_thread(void *psf)
+{
+ struct yahoo_file_info *sf = ( yahoo_file_info* )psf;
+ if (sf == NULL) {
+ DebugLog("[yahoo_send_avt_thread] SF IS NULL!!!");
+ return;
+ }
+
+ SetByte("AvatarUL", 1);
+ yahoo_send_avatar(m_id, sf->filename, sf->filesize, &upload_avt, sf);
+
+ free(sf->filename);
+ free(sf);
+
+ if (GetByte("AvatarUL", 1) == 1)
+ SetByte("AvatarUL", 0);
+}
+
+void CYahooProto::SendAvatar(const TCHAR *szFile)
+{
+ struct _stat statbuf;
+ if (_tstat( szFile, &statbuf ) != 0) {
+ LOG(("[YAHOO_SendAvatar] Error reading File information?!"));
+ return;
+ }
+
+ yahoo_file_info *sf = y_new(struct yahoo_file_info, 1);
+ sf->filesize = statbuf.st_size;
+
+#ifdef _UNICODE
+ wchar_t tszFilename[MAX_PATH];
+ wcscpy(tszFilename, szFile);
+ GetShortPathNameW(szFile, tszFilename, SIZEOF(tszFilename));
+ char szFilename[MAX_PATH];
+ WideCharToMultiByte(CP_ACP, 0, tszFilename, -1, szFilename, MAX_PATH, 0, 0);
+ sf->filename = strdup(szFilename);
+#else
+ sf->filename = strdup(szFile);
+#endif
+
+ DebugLog("[Uploading avatar] filename: %s size: %ld", sf->filename, sf->filesize);
+
+ YForkThread(&CYahooProto::send_avt_thread, sf);
+}
+
+struct avatar_info{
+ char *who;
+ char *pic_url;
+ int cksum;
+};
+
+void __cdecl CYahooProto::recv_avatarthread(void *pavt)
+{
+ PROTO_AVATAR_INFORMATION AI;
+ struct avatar_info *avt = ( avatar_info* )pavt;
+ int error = 0;
+ HANDLE hContact = 0;
+ TCHAR buf[4096];
+
+ if (avt == NULL) {
+ DebugLog("AVT IS NULL!!!");
+ return;
+ }
+
+ if (!m_bLoggedIn) {
+ DebugLog("We are not logged in!!!");
+ return;
+ }
+
+ // ProtoBroadcastAck(m_szModuleName, 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));
+
+ 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 {
+ HANDLE myhFile;
+
+ GetAvatarFileName(hContact, buf, 1024, DBGetContactSettingByte(hContact, m_szModuleName,"AvatarType", 0));
+ DeleteFile(buf);
+
+ LOG(("Saving file: %s size: %u", buf, nlhrReply->dataLength));
+ 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);
+
+ AI.cbSize = sizeof AI;
+ AI.format = PA_FORMAT_PNG;
+ AI.hContact = hContact;
+ #if defined( _UNICODE )
+ WideCharToMultiByte( CP_ACP, 0, buf, -1, AI.filename, sizeof AI.filename, 0, 0 );
+ #else
+ lstrcpyA( AI.filename, buf );
+ #endif
+
+ if (error)
+ SetDword(hContact, "PictCK", 0);
+
+ ProtoBroadcastAck(m_szModuleName, hContact, ACKTYPE_AVATAR, !error ? ACKRESULT_SUCCESS:ACKRESULT_FAILED,(HANDLE) &AI, 0);
+}
+
+void CYahooProto::ext_got_picture(const char *me, const char *who, const char *pic_url, int cksum, int type)
+{
+ HANDLE 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 (!DBGetContactSettingString(NULL, m_szModuleName, "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);
+ DBFreeVariant(&dbv);
+ break;
+ } else
+ LOG(("No AvatarURL???"));
+
+ /*
+ * Try to re-upload the avatar
+ */
+ if (GetByte("AvatarUL", 0) != 1){
+ // NO avatar URL??
+ if (!DBGetContactSettingTString(NULL, m_szModuleName, "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 {
+ DBWriteContactSettingString(NULL, m_szModuleName, "AvatarInv", who);
+ SendAvatar(dbv.ptszVal);
+ }
+
+ DBFreeVariant(&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."));
+ DBWriteContactSettingDword(hContact, m_szModuleName, "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, DBGetContactSettingByte(hContact, m_szModuleName,"AvatarType", 0));
+
+ if (DBGetContactSettingDword(hContact, m_szModuleName,"PictCK", 0) != cksum || _taccess( z, 0 ) != 0 ) {
+
+ DebugLog("[ext_yahoo_got_picture] Checksums don't match or avatar file is missing. Current: %d, New: %d",(int)DBGetContactSettingDword(hContact, m_szModuleName,"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;
+
+ YForkThread(&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 (!DBGetContactSettingString(NULL, m_szModuleName, "AvatarURL", &dbv)){
+ if (lstrcmpiA(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
+ DBFreeVariant(&dbv);
+
+ break;
+ }*/
+
+ LOG(("[ext_yahoo_got_picture] Buddy: %s told us this is bad??Expired??. Re-uploading", who));
+ DBDeleteContactSetting(NULL, m_szModuleName, "AvatarURL");
+
+ if (!DBGetContactSettingTString(NULL, m_szModuleName, "AvatarFile", &dbv2)) {
+ DBWriteContactSettingString(NULL, m_szModuleName, "AvatarInv", who);
+ SendAvatar(dbv2.ptszVal);
+ DBFreeVariant(&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
+ DBFreeVariant(&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 CYahooProto::ext_got_picture_checksum(const char *me, const char *who, int cksum)
+{
+ HANDLE hContact = 0;
+
+ LOG(("ext_yahoo_got_picture_checksum for %s checksum: %d", who, cksum));
+
+ 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) {
+ DBWriteContactSettingDword(hContact, m_szModuleName, "PictCK", 0);
+
+ reset_avatar(hContact);
+ }
+ else {
+ if (DBGetContactSettingDword(hContact, m_szModuleName,"PictCK", 0) != cksum) {
+ // Now save the new checksum. No rush requesting new avatar yet.
+ DBWriteContactSettingDword(hContact, m_szModuleName, "PictCK", cksum);
+
+ // Need to delete the Avatar File!!
+ TCHAR szFile[MAX_PATH];
+ GetAvatarFileName(hContact, szFile, sizeof szFile, 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 CYahooProto::ext_got_picture_update(const char *me, const char *who, int buddy_icon)
+{
+ HANDLE hContact = 0;
+
+ LOG(("ext_got_picture_update for %s buddy_icon: %d", who, buddy_icon));
+
+ hContact = getbuddyH(who);
+ if (hContact == NULL) {
+ LOG(("Buddy Not Found. Skipping avatar update"));
+ return;
+ }
+
+ DBWriteContactSettingByte(hContact, m_szModuleName, "AvatarType", buddy_icon);
+
+ /* Last thing check the checksum and request new one if we need to */
+ reset_avatar(hContact);
+}
+
+void CYahooProto::ext_got_picture_status(const char *me, const char *who, int buddy_icon)
+{
+ HANDLE hContact = 0;
+
+ LOG(("ext_yahoo_got_picture_status for %s buddy_icon: %d", who, buddy_icon));
+
+ hContact = getbuddyH(who);
+ if (hContact == NULL) {
+ LOG(("Buddy Not Found. Skipping avatar update"));
+ return;
+ }
+
+ DBWriteContactSettingByte(hContact, m_szModuleName, "AvatarType", buddy_icon);
+
+ /* Last thing check the checksum and request new one if we need to */
+ reset_avatar(hContact);
+}
+
+void CYahooProto::ext_got_picture_upload(const char *me, const char *url,unsigned int ts)
+{
+ int cksum = 0;
+ DBVARIANT dbv;
+
+ LOG(("[ext_yahoo_got_picture_upload] url: %s timestamp: %d", url, ts));
+
+ if (!url) {
+ LOG(("[ext_yahoo_got_picture_upload] Problem with upload?"));
+ return;
+ }
+
+
+ cksum = GetDword("TMPAvatarHash", 0);
+ if (cksum != 0) {
+ LOG(("[ext_yahoo_got_picture_upload] Updating Checksum to: %d", cksum));
+ SetDword("AvatarHash", cksum);
+ DBDeleteContactSetting(NULL, m_szModuleName, "TMPAvatarHash");
+
+ // This is only meant for message sessions, but we don't got those in miranda yet
+ //YAHOO_bcast_picture_checksum(cksum);
+ yahoo_send_picture_checksum(m_id, NULL, cksum);
+
+ // need to tell the stupid Yahoo that our icon updated
+ //YAHOO_bcast_picture_update(2);
+ }else
+ cksum = GetDword("AvatarHash", 0);
+
+ SetString(NULL, "AvatarURL", url);
+ //YAHOO_SetDword("AvatarExpires", ts);
+
+ if (!DBGetContactSettingString(NULL, m_szModuleName, "AvatarInv", &dbv) ){
+ LOG(("[ext_yahoo_got_picture_upload] Buddy: %s told us this is bad??", dbv.pszVal));
+
+ LOG(("[ext_yahoo_got_picture] Sending url: %s checksum: %d to '%s'!", url, cksum, dbv.pszVal));
+ //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, dbv.pszVal, 2, url, cksum);
+
+ DBDeleteContactSetting(NULL, m_szModuleName, "AvatarInv");
+ DBFreeVariant(&dbv);
+ }
+}
+
+void CYahooProto::ext_got_avatar_share(int buddy_icon)
+{
+ LOG(("[ext_yahoo_got_avatar_share] buddy icon: %d", buddy_icon));
+
+ SetByte( "ShareAvatar", buddy_icon );
+}
+
+void CYahooProto::reset_avatar(HANDLE hContact)
+{
+ LOG(("[YAHOO_RESET_AVATAR]"));
+
+ ProtoBroadcastAck(m_szModuleName, hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL, 0);
+}
+
+void CYahooProto::request_avatar(const char* who)
+{
+ time_t last_chk, cur_time;
+ HANDLE hContact = 0;
+ //char szFile[MAX_PATH];
+
+ if (!GetByte( "ShowAvatars", 1 )) {
+ LOG(("Avatars disabled, but available for: %s", who));
+ return;
+ }
+
+ hContact = getbuddyH(who);
+
+ if (!hContact)
+ return;
+
+ /*GetAvatarFileName(hContact, szFile, sizeof szFile, DBGetContactSettingByte(hContact, m_szModuleName,"AvatarType", 0));
+ DeleteFile(szFile);*/
+
+ time(&cur_time);
+ last_chk = DBGetContactSettingDword(hContact, m_szModuleName, "PictLastCheck", 0);
+
+ /*
+ * time() - in seconds ( 60*60 = 1 hour)
+ */
+ if (DBGetContactSettingDword(hContact, m_szModuleName,"PictCK", 0) == 0 ||
+ last_chk == 0 || (cur_time - last_chk) > 60) {
+
+ DBWriteContactSettingDword(hContact, m_szModuleName, "PictLastCheck", (DWORD)cur_time);
+
+ LOG(("Requesting Avatar for: %s", who));
+ yahoo_request_buddy_avatar(m_id, who);
+ } else {
+ LOG(("Avatar Not Available for: %s Last Check: %ld Current: %ld (Flood Check in Effect)", who, last_chk, cur_time));
+ }
+}
+
+void CYahooProto::InitCustomFolders(void)
+{
+ if ( InitCstFldRan ) return;
+
+ InitCstFldRan = true;
+ if ( ServiceExists( MS_FOLDERS_REGISTER_PATH ))
+ {
+ TCHAR AvatarsFolder[MAX_PATH];
+ TCHAR *tmpPath = Utils_ReplaceVarsT( _T("%miranda_avatarcache%"));
+ mir_sntprintf(AvatarsFolder, MAX_PATH, _T("%s\\") _T(TCHAR_STR_PARAM), tmpPath, m_szModuleName);
+ hYahooAvatarsFolder = FoldersRegisterCustomPathT(m_szModuleName, "Avatars", AvatarsFolder);
+ mir_free(tmpPath);
+ }
+}
+
+void CYahooProto::GetAvatarFileName(HANDLE hContact, TCHAR* pszDest, int cbLen, int type)
+{
+ size_t tPathLen;
+
+ InitCustomFolders();
+
+ TCHAR* path = ( TCHAR* )alloca( sizeof(TCHAR)*( cbLen+1 ));
+ if ( hYahooAvatarsFolder != NULL && !FoldersGetCustomPathT( hYahooAvatarsFolder, path, (int)cbLen, _T("")))
+ {
+ _tcscpy( pszDest, path );
+ tPathLen = _tcslen( pszDest );
+ } else {
+ TCHAR *tmpPath = Utils_ReplaceVarsT( _T("%miranda_avatarcache%"));
+ tPathLen = mir_sntprintf(pszDest, cbLen, _T("%s\\") _T(TCHAR_STR_PARAM), tmpPath, m_szModuleName);
+ mir_free(tmpPath);
+ }
+
+ if ( _taccess(pszDest, 0))
+ YAHOO_CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)pszDest);
+
+ if (hContact != NULL) {
+ int ck_sum = DBGetContactSettingDword(hContact, m_szModuleName,"PictCK", 0);
+ tPathLen += mir_sntprintf(pszDest + tPathLen, cbLen - tPathLen, _T("\\%lX"), ck_sum);
+ } else {
+ tPathLen += mir_sntprintf(pszDest + tPathLen, cbLen - tPathLen, _T("\\") _T(TCHAR_STR_PARAM) _T(" avatar"), m_szModuleName);
+ }
+
+ mir_sntprintf(pszDest + tPathLen, cbLen - tPathLen, _T("%s"), type == 1 ? _T(".swf") : _T(".png"));
+}
+
+INT_PTR __cdecl CYahooProto::GetAvatarInfo(WPARAM wParam,LPARAM lParam)
+{
+ PROTO_AVATAR_INFORMATIONT* AI = ( PROTO_AVATAR_INFORMATIONT* )lParam;
+ DBVARIANT dbv;
+ int avtType;
+
+ if (!DBGetContactSettingString(AI->hContact, m_szModuleName, YAHOO_LOGINID, &dbv)) {
+ DebugLog("[YAHOO_GETAVATARINFO] For: %s", dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }else {
+ DebugLog("[YAHOO_GETAVATARINFO]");
+ }
+
+ if (!GetByte( "ShowAvatars", 1 ) || !m_bLoggedIn) {
+ DebugLog("[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 = DBGetContactSettingByte(AI->hContact, m_szModuleName,"AvatarType", 0);
+ DebugLog("[YAHOO_GETAVATARINFO] Avatar Type: %d", avtType);
+
+ if ( avtType != 2) {
+ if (avtType != 0)
+ DebugLog("[YAHOO_GETAVATARINFO] Not handling this type yet!");
+
+ return GAIR_NOAVATAR;
+ }
+
+ if (DBGetContactSettingDword(AI->hContact, m_szModuleName,"PictCK", 0) == 0)
+ return GAIR_NOAVATAR;
+
+ GetAvatarFileName(AI->hContact, AI->filename, SIZEOF(AI->filename), DBGetContactSettingByte(AI->hContact, m_szModuleName,"AvatarType", 0));
+ AI->format = PA_FORMAT_PNG;
+ DebugLog("[YAHOO_GETAVATARINFO] filename: %s", AI->filename);
+
+ if (_taccess( AI->filename, 0 ) == 0 )
+ return GAIR_SUCCESS;
+
+ if (( wParam & GAIF_FORCE ) != 0 && AI->hContact != NULL ) {
+ /* need to request it again? */
+ if (GetDword(AI->hContact, "PictLoading", 0) != 0 &&
+ (time(NULL) - GetDword(AI->hContact, "PictLastCheck", 0) < 500)) {
+ DebugLog("[YAHOO_GETAVATARINFO] Waiting for avatar to load!");
+ return GAIR_WAITFOR;
+ } else if ( m_bLoggedIn ) {
+ DBVARIANT dbv;
+
+ if (!DBGetContactSettingString(AI->hContact, m_szModuleName, YAHOO_LOGINID, &dbv)) {
+ DebugLog("[YAHOO_GETAVATARINFO] Requesting avatar!");
+
+ request_avatar(dbv.pszVal);
+ DBFreeVariant(&dbv);
+
+ return GAIR_WAITFOR;
+ } else {
+ DebugLog("[YAHOO_GETAVATARINFO] Can't retrieve user id?!");
+ }
+ }
+ }
+
+ DebugLog("[YAHOO_GETAVATARINFO] NO AVATAR???");
+ return GAIR_NOAVATAR;
+}
+
+/*
+ * --=[ AVS / LoadAvatars API/Services ]=--
+ */
+INT_PTR __cdecl CYahooProto::GetAvatarCaps(WPARAM wParam, LPARAM lParam)
+{
+ int res = 0;
+
+ switch (wParam) {
+ case AF_MAXSIZE:
+ LOG(("[YahooGetAvatarCaps] AF_MAXSIZE"));
+
+ ((POINT*)lParam)->x = 96;
+ ((POINT*)lParam)->y = 96;
+
+ break;
+
+ case AF_PROPORTION:
+ LOG(("[YahooGetAvatarCaps] AF_PROPORTION"));
+
+ res = PIP_NONE;
+ break;
+
+ case AF_FORMATSUPPORTED:
+ LOG(("[YahooGetAvatarCaps] AF_FORMATSUPPORTED"));
+ res = lParam == PA_FORMAT_PNG;
+ break;
+
+ case AF_ENABLED:
+ LOG(("[YahooGetAvatarCaps] AF_ENABLED"));
+
+ res = (GetByte( "ShowAvatars", 1 )) ? 1 : 0;
+ break;
+
+ case AF_DONTNEEDDELAYS:
+ res = 1; /* don't need to delay avatar loading */
+ break;
+
+ case AF_MAXFILESIZE:
+ res = 0; /* no max filesize for now */
+ break;
+
+ case AF_DELAYAFTERFAIL:
+ res = 15 * 60 * 1000; /* 15 mins */
+ break;
+
+ default:
+ LOG(("[YahooGetAvatarCaps] Unknown: %d", wParam));
+ }
+
+ return res;
+}
+
+/*
+Service: /GetMyAvatar
+wParam=(char *)Buffer to file name
+lParam=(int)Buffer size
+return=0 on success, else on error
+*/
+INT_PTR __cdecl CYahooProto::GetMyAvatar(WPARAM wParam, LPARAM lParam)
+{
+ TCHAR *buffer = ( TCHAR* )wParam;
+ int size = (int)lParam;
+
+ DebugLog("[YahooGetMyAvatar]");
+
+ if (buffer == NULL || size <= 0)
+ return -1;
+
+ if (!GetByte( "ShowAvatars", 1 ))
+ return -2;
+
+ DBVARIANT dbv;
+ int ret = -3;
+
+ if (GetDword("AvatarHash", 0)){
+ if (!DBGetContactSettingTString(NULL, m_szModuleName, "AvatarFile", &dbv)){
+ if (_taccess(dbv.ptszVal, 0) == 0){
+ lstrcpyn(buffer, dbv.ptszVal, size-1);
+ buffer[size-1] = '\0';
+
+ ret = 0;
+ }
+ DBFreeVariant(&dbv);
+ }
+ }
+
+ return ret;
+}
+
+/*
+#define PS_SETMYAVATAR "/SetMyAvatar"
+wParam=0
+lParam=(const char *)Avatar file name
+return=0 for sucess
+*/
+
+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) {
+ DebugLog("[Deleting Avatar Info]");
+
+ /* remove ALL our Avatar Info Keys */
+ DBDeleteContactSetting(NULL, m_szModuleName, "AvatarFile");
+ DBDeleteContactSetting(NULL, m_szModuleName, "AvatarHash");
+ DBDeleteContactSetting(NULL, m_szModuleName, "AvatarURL");
+ DBDeleteContactSetting(NULL, m_szModuleName, "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 {
+ DWORD dwPngSize, dw;
+ BYTE* pResult;
+ unsigned int hash;
+ HANDLE hFile;
+
+ 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;
+
+ dwPngSize = GetFileSize( hFile, NULL );
+ if (( pResult = ( BYTE* )malloc( dwPngSize )) == NULL )
+ return 2;
+
+ 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 );
+
+ 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)) {
+ SetStringT(NULL, "AvatarFile", tszMyFile);
+ DBWriteContactSettingDword(NULL, m_szModuleName, "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;
+}
+
+/*
+ * --=[ ]=--
+ */