From cb4a46e7fbe62d788e66ed6121c717a2d22a4d7c Mon Sep 17 00:00:00 2001 From: watcherhd Date: Thu, 21 Apr 2011 14:14:52 +0000 Subject: svn.miranda.im is moving to a new home! git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@7 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- miranda-wine/protocols/Yahoo/avatar.c | 1142 +++++++++++++++++++++++++++++++++ 1 file changed, 1142 insertions(+) create mode 100644 miranda-wine/protocols/Yahoo/avatar.c (limited to 'miranda-wine/protocols/Yahoo/avatar.c') diff --git a/miranda-wine/protocols/Yahoo/avatar.c b/miranda-wine/protocols/Yahoo/avatar.c new file mode 100644 index 0000000..2fc4588 --- /dev/null +++ b/miranda-wine/protocols/Yahoo/avatar.c @@ -0,0 +1,1142 @@ +/* + * $Id: avatar.c 3676 2006-09-01 18:02:28Z gena01 $ + * + * 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 +#include +#include +#include + +#include "yahoo.h" +#include "resource.h" + +#include +#include +#include +#include + +#include "avatar.h" +#include "file_transfer.h" + +static BOOL CALLBACK AvatarDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +extern yahoo_local_account *ylad; + +int OnDetailsInit(WPARAM wParam, LPARAM lParam) +{ + char* szProto; + OPTIONSDIALOGPAGE odp; + char szAvtCaption[MAX_PATH+8]; + + szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, lParam, 0); + if ((lstrcmp(szProto, yahooProtocolName)) && lParam) + return 0; + + if ((lParam == 0) && YAHOO_GetByte( "ShowAvatars", 0 )) + { + // Avatar page only for valid contacts + odp.cbSize = sizeof(odp); + odp.hIcon = NULL; + odp.hInstance = hinstance; + odp.pfnDlgProc = AvatarDlgProc; + odp.position = -1899999997; + odp.pszTemplate = MAKEINTRESOURCE(IDD_INFO_AVATAR); + snprintf(szAvtCaption, sizeof(szAvtCaption), "%s %s", Translate(yahooProtocolName), Translate("Avatar")); + odp.pszTitle = szAvtCaption; + + CallService(MS_USERINFO_ADDPAGE, wParam, (LPARAM)&odp); + } + + return 0; +} + +static char* ChooseAvatarFileName() +{ + char* szDest = (char*)malloc(MAX_PATH+0x10); + char str[MAX_PATH]; + char szFilter[512]; + OPENFILENAME ofn = {0}; + str[0] = 0; + szDest[0]='\0'; + CallService(MS_UTILS_GETBITMAPFILTERSTRINGS,sizeof(szFilter),(LPARAM)szFilter); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.lpstrFilter = szFilter; + //ofn.lpstrFilter = "PNG Bitmaps (*.png)\0*.png\0"; + ofn.lpstrFile = szDest; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; + ofn.nMaxFile = MAX_PATH; + ofn.nMaxFileTitle = MAX_PATH; + ofn.lpstrDefExt = "png"; + if (!GetOpenFileName(&ofn)){ + free(szDest); + return NULL; + } + + return szDest; +} + +/* + *31 bit hash function - this is based on g_string_hash function from glib + */ +int YAHOO_avt_hash(const char *key, long ksize) +{ + const char *p = key; + int h = *p; + long l = 0; + + if (h) + for (p += 1; l < ksize; p++, l++) + h = (h << 5) - h + *p; + + return h; +} + +int calcMD5Hash(char* szFile) +{ + if (szFile) { + HANDLE hFile = NULL, hMap = NULL; + BYTE* ppMap = NULL; + long cbFileSize = 0; + int ck = 0; + + if ((hFile = CreateFile(szFile, 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){ + ck = YAHOO_avt_hash((char *)ppMap, cbFileSize); + } + + if (ppMap != NULL) UnmapViewOfFile(ppMap); + if (hMap != NULL) CloseHandle(hMap); + if (hFile != NULL) CloseHandle(hFile); + + if (ck) return ck; + } + + return 0; +} + +void upload_avt(int id, int fd, int error, void *data); + +/**************** Send Avatar ********************/ + +HBITMAP YAHOO_SetAvatar(const char *szFile) +{ + char szMyFile[MAX_PATH+1]; + HBITMAP avt; + + avt = (HBITMAP)CallService(MS_UTILS_LOADBITMAP, 0, (WPARAM)szFile); + + if (avt == NULL) + return NULL; + + if (( avt = YAHOO_StretchBitmap( avt )) == NULL ) + return NULL; + + GetAvatarFileName(NULL, szMyFile, MAX_PATH, 2); + + if (avt && YAHOO_SaveBitmapAsAvatar( avt, szMyFile) == 0) { + unsigned int hash; + + hash = calcMD5Hash(szMyFile); + if (hash) { + LOG(("[YAHOO_SetAvatar] File: '%s' CK: %d", szMyFile, hash)); + + /* now check and make sure we don't reupload same thing over again */ + if (hash != YAHOO_GetDword("AvatarHash", 0)) { + YAHOO_SetString(NULL, "AvatarFile", szMyFile); + DBWriteContactSettingDword(NULL, yahooProtocolName, "TMPAvatarHash", hash); + + YAHOO_SendAvatar(szMyFile); + } else { + LOG(("[YAHOO_SetAvatar] Same checksum and avatar on YahooFT. Not Reuploading.")); + } + } + } + + return avt; +} + +static BOOL CALLBACK AvatarDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_INITDIALOG: + //MessageBox(NULL, "HALLO AVATARS!!", "AA", MB_OK); + TranslateDialogDefault(hwndDlg); + { + DBVARIANT dbv; + char szAvatar[MAX_PATH]; + + ShowWindow(GetDlgItem(hwndDlg, -1), SW_SHOW); + if (!yahooLoggedIn){ + EnableWindow(GetDlgItem(hwndDlg, IDC_SETAVATAR), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELETEAVATAR), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHARE_AVATAR), FALSE); + } + + SetButtonCheck( hwndDlg, IDC_SHARE_AVATAR, YAHOO_GetByte( "ShareAvatar", 0 ) == 2 ); + + if (!DBGetContactSetting(NULL, yahooProtocolName, "AvatarFile", &dbv)) { + HBITMAP avt; + + lstrcpy(szAvatar, dbv.pszVal); + DBFreeVariant(&dbv); + + avt = (HBITMAP)CallService(MS_UTILS_LOADBITMAP, 0, (WPARAM)szAvatar); + if (avt) { + avt = (HBITMAP)SendDlgItemMessage(hwndDlg, IDC_AVATAR, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)avt); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHARE_AVATAR), TRUE); + if (avt) DeleteObject(avt); // we release old avatar if any + } + } else { + EnableWindow(GetDlgItem(hwndDlg, IDC_DELETEAVATAR), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHARE_AVATAR), FALSE); + } + } + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDC_SETAVATAR: + { + char* szFile; + HBITMAP avt; + + if ((szFile = ChooseAvatarFileName()) != NULL) { + avt = YAHOO_SetAvatar(szFile); + + free(szFile); + + if (avt){ + avt = (HBITMAP)SendDlgItemMessage(hwndDlg, IDC_AVATAR, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)avt); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELETEAVATAR), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHARE_AVATAR), TRUE); + } + if (avt) DeleteObject(avt); // we release old avatar if any + } + + } + break; + case IDC_DELETEAVATAR: + { + HBITMAP avt; + + YAHOO_DebugLog("[Deleting Avatar Info]"); + + avt = (HBITMAP)SendDlgItemMessage(hwndDlg, IDC_AVATAR, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL); + if (avt) DeleteObject(avt); // we release old avatar if any + + /* remove ALL our Avatar Info Keys */ + DBDeleteContactSetting(NULL, yahooProtocolName, "AvatarFile"); + DBDeleteContactSetting(NULL, yahooProtocolName, "AvatarHash"); + DBDeleteContactSetting(NULL, yahooProtocolName, "AvatarURL"); + DBDeleteContactSetting(NULL, yahooProtocolName, "AvatarTS"); + + /* Send a Yahoo packet saying we don't got an avatar anymore */ + YAHOO_set_avatar(0); + + /* clear the avatar window */ + InvalidateRect( hwndDlg, NULL, TRUE ); + + YAHOO_SetByte("ShareAvatar",0); + SetButtonCheck(hwndDlg, IDC_SHARE_AVATAR, 0); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELETEAVATAR), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHARE_AVATAR), FALSE); + } + break; + case IDC_SHARE_AVATAR: + YAHOO_SetByte("ShareAvatar",IsDlgButtonChecked(hwndDlg, IDC_SHARE_AVATAR) ? 2 : 0); + /* Send a Yahoo packet saying we don't got an avatar anymore */ + YAHOO_set_avatar(YAHOO_GetByte( "ShareAvatar", 0 )? 2 : 0); + } + break; + } + + return FALSE; +} + +/* + * YAHOO_StretchBitmap (copied from MSN, Thanks George) + */ +HBITMAP YAHOO_StretchBitmap( HBITMAP hBitmap ) +{ + BITMAPINFO bmStretch; + BITMAP bmp; + UINT* ptPixels; + HDC hDC, hBmpDC; + HBITMAP hOldBitmap1, hOldBitmap2, hStretchedBitmap; + int side, dx, dy; + + ZeroMemory(&bmStretch, sizeof(bmStretch)); + bmStretch.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmStretch.bmiHeader.biWidth = 96; + bmStretch.bmiHeader.biHeight = 96; + bmStretch.bmiHeader.biPlanes = 1; + bmStretch.bmiHeader.biBitCount = 32; + + hStretchedBitmap = CreateDIBSection( NULL, &bmStretch, DIB_RGB_COLORS, ( void* )&ptPixels, NULL, 0); + if ( hStretchedBitmap == NULL ) { + YAHOO_DebugLog( "Bitmap creation failed with error %ld", GetLastError() ); + return NULL; + } + + hDC = CreateCompatibleDC( NULL ); + hOldBitmap1 = ( HBITMAP )SelectObject( hDC, hBitmap ); + GetObject( hBitmap, sizeof( BITMAP ), &bmp ); + + hBmpDC = CreateCompatibleDC( hDC ); + hOldBitmap2 = ( HBITMAP )SelectObject( hBmpDC, hStretchedBitmap ); + + if ( bmp.bmWidth > bmp.bmHeight ) { + side = bmp.bmHeight; + dx = ( bmp.bmWidth - bmp.bmHeight )/2; + dy = 0; + } + else { + side = bmp.bmWidth; + dx = 0; + dy = ( bmp.bmHeight - bmp.bmWidth )/2; + } + + SetStretchBltMode( hBmpDC, HALFTONE ); + StretchBlt( hBmpDC, 0, 0, 96, 96, hDC, dx, dy, side, side, SRCCOPY ); + + SelectObject( hDC, hOldBitmap1 ); + DeleteObject( hBitmap ); + DeleteDC( hDC ); + + SelectObject( hBmpDC, hOldBitmap2 ); + DeleteDC( hBmpDC ); + return hStretchedBitmap; +} + +/* + * YAHOO_SaveBitmapAsAvatar - updates the avatar database settings and file from a bitmap + */ +int YAHOO_SaveBitmapAsAvatar( HBITMAP hBitmap, const char* szFileName ) +{ + BITMAPINFO* bmi; + HDC hdc; + HBITMAP hOldBitmap; + BITMAPINFOHEADER* pDib; + BYTE* pDibBits; + long dwPngSize = 0; + DIB2PNG convertor; + + if ( !ServiceExists(MS_DIB2PNG)) { + MessageBox( NULL, Translate( "Your png2dib.dll is either obsolete or damaged. " ), + Translate( "Error" ), MB_OK | MB_ICONSTOP ); + return 1; + } + + hdc = CreateCompatibleDC( NULL ); + hOldBitmap = ( HBITMAP )SelectObject( hdc, hBitmap ); + + bmi = ( BITMAPINFO* )_alloca( sizeof( BITMAPINFO ) + sizeof( RGBQUAD )*256 ); + memset( bmi, 0, sizeof (BITMAPINFO )); + bmi->bmiHeader.biSize = 0x28; + if ( GetDIBits( hdc, hBitmap, 0, 96, NULL, bmi, DIB_RGB_COLORS ) == 0 ) { + return 2; + } + + pDib = ( BITMAPINFOHEADER* )GlobalAlloc( LPTR, sizeof( BITMAPINFO ) + sizeof( RGBQUAD )*256 + bmi->bmiHeader.biSizeImage ); + if ( pDib == NULL ) + return 3; + + memcpy( pDib, bmi, sizeof( BITMAPINFO ) + sizeof( RGBQUAD )*256 ); + pDibBits = (( BYTE* )pDib ) + sizeof( BITMAPINFO ) + sizeof( RGBQUAD )*256; + + GetDIBits( hdc, hBitmap, 0, pDib->biHeight, pDibBits, ( BITMAPINFO* )pDib, DIB_RGB_COLORS ); + SelectObject( hdc, hOldBitmap ); + DeleteDC( hdc ); + + convertor.pbmi = ( BITMAPINFO* )pDib; + convertor.pDiData = pDibBits; + convertor.pResult = NULL; + convertor.pResultLen = &dwPngSize; + if ( !CallService( MS_DIB2PNG, 0, (LPARAM)&convertor )) { + GlobalFree( pDib ); + return 2; + } + + convertor.pResult = (char *)malloc(dwPngSize); + CallService( MS_DIB2PNG, 0, (LPARAM)&convertor ); + + GlobalFree( pDib ); + { + FILE* out; + + out = fopen( szFileName, "wb" ); + if ( out != NULL ) { + fwrite( convertor.pResult, dwPngSize, 1, out ); + fclose( out ); + } + } + free(convertor.pResult); + + return ERROR_SUCCESS; +} + +void upload_avt(int id, int fd, int error, void *data) +{ + y_filetransfer *sf = (y_filetransfer*) data; + 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 = CreateFile(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->fsize)); + + 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?")); + break; + } + + size += rw; + } + } while (rw >= 0 && size < sf->fsize); + + 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 yahoo_send_avt_thread(void *psf) +{ + y_filetransfer *sf = psf; + + if (sf == NULL) { + YAHOO_DebugLog("[yahoo_send_avt_thread] SF IS NULL!!!"); + return; + } + + YAHOO_SetByte("AvatarUL", 1); + yahoo_send_avatar(ylad->id, sf->filename, sf->fsize, &upload_avt, sf); + + free(sf->filename); + free(sf); + if (YAHOO_GetByte("AvatarUL", 1) == 1) YAHOO_SetByte("AvatarUL", 0); +} + +void YAHOO_SendAvatar(const char *szFile) +{ + y_filetransfer *sf; + struct _stat statbuf; + + if ( _stat( szFile, &statbuf ) != 0 ) { + LOG(("[YAHOO_SendAvatar] Error reading File information?!")); + return; + } + + sf = (y_filetransfer*) malloc(sizeof(y_filetransfer)); + sf->filename = strdup(szFile); + sf->cancel = 0; + sf->fsize = statbuf.st_size; + + YAHOO_DebugLog("[Uploading avatar] filename: %s size: %ld", sf->filename, sf->fsize); + + pthread_create(yahoo_send_avt_thread, sf); +} + +struct avatar_info{ + char *who; + char *pic_url; + int cksum; +}; + +static void __cdecl yahoo_recv_avatarthread(void *pavt) +{ + PROTO_AVATAR_INFORMATION AI; + struct avatar_info *avt = pavt; + int error = 0; + HANDLE hContact = 0; + char buf[4096]; + + if (avt == NULL) { + YAHOO_DebugLog("AVT IS NULL!!!"); + return; + } + + if (!yahooLoggedIn) { + YAHOO_DebugLog("We are not logged in!!!"); + return; + } + +// ProtoBroadcastAck(yahooProtocolName, 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) { + DBWriteContactSettingDword(hContact, yahooProtocolName, "PictCK", avt->cksum); + DBWriteContactSettingDword(hContact, yahooProtocolName, "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)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(ylad->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, yahooProtocolName,"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); + + DBWriteContactSettingString(hContact, "ContactPhoto", "File", buf); + DBWriteContactSettingDword(hContact, yahooProtocolName, "PictLastCheck", 0); + } else { + LOG(("Can not open file for writing: %s", buf)); + error = 1; + } + } + CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT,0,(LPARAM)nlhrReply); + } + } + + if (DBGetContactSettingDword(hContact, yahooProtocolName, "PictCK", 0) != avt->cksum) { + LOG(("WARNING: Checksum updated during download?!")); + error = 1; /* don't use this one? */ + } + + DBWriteContactSettingDword(hContact, yahooProtocolName, "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; + lstrcpy(AI.filename,buf); + + if (error) + DBWriteContactSettingDword(hContact, yahooProtocolName, "PictCK", 0); + + ProtoBroadcastAck(yahooProtocolName, hContact, ACKTYPE_AVATAR, !error ? ACKRESULT_SUCCESS:ACKRESULT_FAILED,(HANDLE) &AI, 0); + +} + +void YAHOO_get_avatar(const char *who, const char *pic_url, long cksum) +{ + struct avatar_info *avt; + + avt = malloc(sizeof(struct avatar_info)); + avt->who = _strdup(who); + avt->pic_url = _strdup(pic_url); + avt->cksum = cksum; + + pthread_create(yahoo_recv_avatarthread, (void *) avt); +} + +void ext_yahoo_got_picture(int id, 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 (!YAHOO_GetByte( "ShowAvatars", 0 )) { + LOG(("[ext_yahoo_got_picture] We are not using/showing avatars!")); + yahoo_send_picture_update(id, who, 0); // no avatar (disabled) + return; + } + + LOG(("[ext_yahoo_got_picture] Getting ready to send info!")); + /* need to read CheckSum */ + cksum = YAHOO_GetDword("AvatarHash", 0); + if (cksum) { + if (!DBGetContactSetting(NULL, yahooProtocolName, "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(id, who, 2, dbv.pszVal, cksum); + DBFreeVariant(&dbv); + } else if (YAHOO_GetByte("AvatarUL", 0) != 1){ + // NO avatar URL?? + if (!DBGetContactSetting(NULL, yahooProtocolName, "AvatarFile", &dbv)) { + DBWriteContactSettingString(NULL, yahooProtocolName, "AvatarInv", who); + YAHOO_SendAvatar(dbv.pszVal); + 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 (!YAHOO_GetByte( "ShowAvatars", 0 )) { + 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 || cksum == -1) { + LOG(("[ext_yahoo_got_picture] Resetting avatar.")); + DBWriteContactSettingDword(hContact, yahooProtocolName, "PictCK", 0); + + yahoo_reset_avatar(hContact); + } else { + char z[1024]; + + if (pic_url == NULL) { + LOG(("[ext_yahoo_got_picture] WARNING: Empty URL for avatar?")); + return; + } + + GetAvatarFileName(hContact, z, 1024, DBGetContactSettingByte(hContact, yahooProtocolName,"AvatarType", 0)); + + if (DBGetContactSettingDword(hContact, yahooProtocolName,"PictCK", 0) != cksum || _access( z, 0 ) != 0 ) { + + YAHOO_DebugLog("[ext_yahoo_got_picture] Checksums don't match or avatar file is missing. Current: %d, New: %d",(int)DBGetContactSettingDword(hContact, yahooProtocolName,"PictCK", 0), cksum); + + YAHOO_get_avatar(who, pic_url, cksum); + } + } + + 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 (!YAHOO_GetByte( "ShowAvatars", 0 )) { + LOG(("[ext_yahoo_got_picture] We are not using/showing avatars!")); + yahoo_send_picture_update(id, who, 0); // no avatar (disabled) + return; + } + + LOG(("[ext_yahoo_got_picture] Getting ready to send info!")); + /* need to read CheckSum */ + mcksum = YAHOO_GetDword("AvatarHash", 0); + if (mcksum == 0) { + /* this should NEVER Happen??? */ + LOG(("[ext_yahoo_got_picture] No personal checksum? and Invalidate?!")); + yahoo_send_picture_update(id, who, 0); // no avatar (disabled) + return; + } + + LOG(("[ext_yahoo_got_picture] My Checksum: %d", mcksum)); + + if (!DBGetContactSetting(NULL, yahooProtocolName, "AvatarURL", &dbv)){ + if (mcksum == cksum && lstrcmpi(pic_url, dbv.pszVal) == 0) { + DBVARIANT dbv2; + + LOG(("[ext_yahoo_got_picture] Buddy: %s told us this is bad??Expired??. Re-uploading", who)); + DBDeleteContactSetting(NULL, yahooProtocolName, "AvatarURL"); + + + if (!DBGetContactSetting(NULL, yahooProtocolName, "AvatarFile", &dbv2)) { + DBWriteContactSettingString(NULL, yahooProtocolName, "AvatarInv", who); + YAHOO_SendAvatar(dbv2.pszVal); + DBFreeVariant(&dbv2); + } else { + LOG(("[ext_yahoo_got_picture] No Local Avatar File??? ")); + } + } else { + LOG(("[ext_yahoo_got_picture] URLs or checksums don't match? Tell them the right thing!!!")); + yahoo_send_picture_info(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 ext_yahoo_got_picture_checksum(int id, 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, yahooProtocolName, "PictCK", 0); + + yahoo_reset_avatar(hContact); + } else { + if (DBGetContactSettingDword(hContact, yahooProtocolName,"PictCK", 0) != cksum) { + char szFile[MAX_PATH]; + + // Now save the new checksum. No rush requesting new avatar yet. + DBWriteContactSettingDword(hContact, yahooProtocolName, "PictCK", cksum); + + // Need to delete the Avatar File!! + GetAvatarFileName(hContact, szFile, sizeof szFile, 0); + DeleteFile(szFile); + + // Reset the avatar and cleanup. + yahoo_reset_avatar(hContact); + } + } + +} + +void ext_yahoo_got_picture_update(int id, const char *me, const char *who, int buddy_icon) +{ + HANDLE hContact = 0; + + LOG(("ext_yahoo_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, yahooProtocolName, "AvatarType", buddy_icon); + + /* Last thing check the checksum and request new one if we need to */ + yahoo_reset_avatar(hContact); +} + +void ext_yahoo_got_avatar_update(int id, const char *me, const char *who, int buddy_icon) +{ + HANDLE hContact = 0; + + LOG(("ext_yahoo_got_avatar_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, yahooProtocolName, "AvatarType", buddy_icon); + + /* Last thing check the checksum and request new one if we need to */ + yahoo_reset_avatar(hContact); +} + +void yahoo_reset_avatar(HANDLE hContact) +{ + LOG(("[YAHOO_RESET_AVATAR]")); + + // STUPID SCRIVER Doesn't listen to ACKTYPE_AVATAR. so remove the file reference! + //DBDeleteContactSetting(hContact, "ContactPhoto", "File"); + + ProtoBroadcastAck(yahooProtocolName, hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL, 0); +} + +void YAHOO_request_avatar(const char* who) +{ + time_t last_chk, cur_time; + HANDLE hContact = 0; + char szFile[MAX_PATH]; + + if (!YAHOO_GetByte( "ShowAvatars", 0 )) { + LOG(("Avatars disabled, but available for: %s", who)); + return; + } + + hContact = getbuddyH(who); + + if (!hContact) + return; + + + GetAvatarFileName(hContact, szFile, sizeof szFile, DBGetContactSettingByte(hContact, yahooProtocolName,"AvatarType", 0)); + DeleteFile(szFile); + + time(&cur_time); + last_chk = DBGetContactSettingDword(hContact, yahooProtocolName, "PictLastCheck", 0); + + /* + * time() - in seconds ( 60*60 = 1 hour) + */ + if (DBGetContactSettingDword(hContact, yahooProtocolName,"PictCK", 0) == 0 || + last_chk == 0 || (cur_time - last_chk) > 60) { + + DBWriteContactSettingDword(hContact, yahooProtocolName, "PictLastCheck", cur_time); + + LOG(("Requesting Avatar for: %s", who)); + yahoo_request_buddy_avatar(ylad->id, who); + } else { + LOG(("Avatar Not Available for: %s Last Check: %ld Current: %ld (Flood Check in Effect)", who, last_chk, cur_time)); + } +} + +void YAHOO_bcast_picture_update(int buddy_icon) +{ + HANDLE hContact; + char *szProto; + + /* need to get online buddies and then send then picture_update packets (ARGH YAHOO!)*/ + for ( hContact = ( HANDLE )YAHOO_CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 ); + hContact != NULL; + hContact = ( HANDLE )YAHOO_CallService( MS_DB_CONTACT_FINDNEXT, ( WPARAM )hContact, 0 )) + { + szProto = ( char* )YAHOO_CallService( MS_PROTO_GETCONTACTBASEPROTO, ( WPARAM )hContact, 0 ); + if ( szProto != NULL && !lstrcmp( szProto, yahooProtocolName )) + { + if (YAHOO_GetWord(hContact, "Status", ID_STATUS_OFFLINE)!=ID_STATUS_OFFLINE) { + DBVARIANT dbv; + + if ( DBGetContactSetting( hContact, yahooProtocolName, YAHOO_LOGINID, &dbv )) + continue; + + yahoo_send_picture_update(ylad->id, dbv.pszVal, buddy_icon); + DBFreeVariant( &dbv ); + } + } + } +} + +void YAHOO_set_avatar(int buddy_icon) +{ + yahoo_send_avatar_update(ylad->id,buddy_icon); + + YAHOO_bcast_picture_update(buddy_icon); +} + +void YAHOO_bcast_picture_checksum(int cksum) +{ + HANDLE hContact; + char *szProto; + + yahoo_send_picture_checksum(ylad->id, NULL, cksum); + + /* need to get online buddies and then send then picture_update packets (ARGH YAHOO!)*/ + for ( hContact = ( HANDLE )YAHOO_CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 ); + hContact != NULL; + hContact = ( HANDLE )YAHOO_CallService( MS_DB_CONTACT_FINDNEXT, ( WPARAM )hContact, 0 )) + { + szProto = ( char* )YAHOO_CallService( MS_PROTO_GETCONTACTBASEPROTO, ( WPARAM )hContact, 0 ); + if ( szProto != NULL && !lstrcmp( szProto, yahooProtocolName )) + { + if (YAHOO_GetWord(hContact, "Status", ID_STATUS_OFFLINE)!=ID_STATUS_OFFLINE) { + DBVARIANT dbv; + + if ( DBGetContactSetting( hContact, yahooProtocolName, YAHOO_LOGINID, &dbv )) + continue; + + yahoo_send_picture_checksum(ylad->id, dbv.pszVal, cksum); + DBFreeVariant( &dbv ); + } + } + } +} + +void GetAvatarFileName(HANDLE hContact, char* pszDest, int cbLen, int type) +{ + int tPathLen; + DBVARIANT dbv; + + CallService(MS_DB_GETPROFILEPATH, cbLen, (LPARAM)pszDest); + + tPathLen = lstrlen(pszDest); + _snprintf(pszDest + tPathLen, MAX_PATH-tPathLen, "\\%s\\", yahooProtocolName); + CreateDirectory(pszDest, NULL); + + if (hContact != NULL && !DBGetContactSetting(hContact, yahooProtocolName, YAHOO_LOGINID, &dbv)) { + lstrcat(pszDest, dbv.pszVal); + DBFreeVariant(&dbv); + }else { + lstrcat(pszDest, "avatar"); + } + + if (type == 1) { + lstrcat(pszDest, ".swf" ); + } else + lstrcat(pszDest, ".png" ); + +} + +int YahooGetAvatarInfo(WPARAM wParam,LPARAM lParam) +{ + PROTO_AVATAR_INFORMATION* AI = ( PROTO_AVATAR_INFORMATION* )lParam; + + DBVARIANT dbv; + int avtType; + + if (!DBGetContactSetting(AI->hContact, yahooProtocolName, YAHOO_LOGINID, &dbv)) { + YAHOO_DebugLog("[YAHOO_GETAVATARINFO] For: %s", dbv.pszVal); + DBFreeVariant(&dbv); + }else { + YAHOO_DebugLog("[YAHOO_GETAVATARINFO]"); + } + + if (!YAHOO_GetByte( "ShowAvatars", 0 ) || !yahooLoggedIn) { + YAHOO_DebugLog("[YAHOO_GETAVATARINFO] %s", yahooLoggedIn ? "We are not using/showing avatars!" : "We are not logged in. Can't load avatars now!"); + + /*if (DBGetContactSettingDword(AI->hContact, yahooProtocolName,"PictCK", 0) != 0) { + YAHOO_DebugLog("[YAHOO_GETAVATARINFO] Removing avatar information!"); + + DBWriteContactSettingDword(AI->hContact, yahooProtocolName, "PictCK", 0); + DBWriteContactSettingDword(AI->hContact, yahooProtocolName, "PictLastCheck", 0); + DBWriteContactSettingDword(AI->hContact, yahooProtocolName, "PictLoading", 0); + //GetAvatarFileName(AI->hContact, AI->filename, sizeof AI->filename); + //DeleteFile(AI->filename); + }*/ + + return GAIR_NOAVATAR; + } + + avtType = DBGetContactSettingByte(AI->hContact, yahooProtocolName,"AvatarType", 0); + YAHOO_DebugLog("[YAHOO_GETAVATARINFO] Avatar Type: %d", avtType); + + if ( avtType != 2) { + if (avtType != 0) + YAHOO_DebugLog("[YAHOO_GETAVATARINFO] Not handling this type yet!"); + + return GAIR_NOAVATAR; + } + + if (DBGetContactSettingDword(AI->hContact, yahooProtocolName,"PictCK", 0) != 0) { + + GetAvatarFileName(AI->hContact, AI->filename, sizeof AI->filename,DBGetContactSettingByte(AI->hContact, yahooProtocolName,"AvatarType", 0)); + //if ( access( AI->filename, 0 ) == 0 ) { + AI->format = PA_FORMAT_PNG; + YAHOO_DebugLog("[YAHOO_GETAVATARINFO] filename: %s", AI->filename); + + if (_access( AI->filename, 0 ) == 0 ) { + return GAIR_SUCCESS; + } else { + /* need to request it again? */ + if (YAHOO_GetWord(AI->hContact, "PictLoading", 0) != 0 && + (time(NULL) - YAHOO_GetWord(AI->hContact, "PictLastCK", 0) < 500)) { + YAHOO_DebugLog("[YAHOO_GETAVATARINFO] Waiting for avatar to load!"); + return GAIR_WAITFOR; + } else if ( yahooLoggedIn ) { + DBVARIANT dbv; + + if (!DBGetContactSetting(AI->hContact, yahooProtocolName, YAHOO_LOGINID, &dbv)) { + YAHOO_DebugLog("[YAHOO_GETAVATARINFO] Requesting avatar!"); + + YAHOO_request_avatar(dbv.pszVal/*who */); + DBFreeVariant(&dbv); + return GAIR_WAITFOR; + } else { + YAHOO_DebugLog("[YAHOO_GETAVATARINFO] Can't retrieve user id?!"); + } + } + } + } + + YAHOO_DebugLog("[YAHOO_GETAVATARINFO] NO AVATAR???"); + return GAIR_NOAVATAR; +} + +/* + * --=[ AVS / LoadAvatars API/Services ]=-- + */ + +/* +Optional. Will pass PNG or BMP if this is not found +wParam = 0 +lParam = PA_FORMAT_* // avatar format +return = 1 (supported) or 0 (not supported) +*/ +int YahooAvatarFormatSupported(WPARAM wParam, LPARAM lParam) +{ + YAHOO_DebugLog("[YahooAvatarFormatSupported]"); + + if (lParam == PA_FORMAT_PNG) + return 1; + else + return 0; +} + +/* +Service: /GetMyAvatarMaxSize +wParam=(int *)max width of avatar +lParam=(int *)max height of avatar +return=0 +*/ +int YahooGetAvatarSize(WPARAM wParam, LPARAM lParam) +{ + YAHOO_DebugLog("[YahooGetAvatarSize]"); + + if (wParam != 0) *((int*) wParam) = 96; + if (lParam != 0) *((int*) lParam) = 96; + + return 0; +} + +/* +Service: /GetMyAvatar +wParam=(char *)Buffer to file name +lParam=(int)Buffer size +return=0 on success, else on error +*/ +int YahooGetMyAvatar(WPARAM wParam, LPARAM lParam) +{ + char *buffer = (char *)wParam; + int size = (int)lParam; + + YAHOO_DebugLog("[YahooGetMyAvatar]"); + + if (buffer == NULL || size <= 0) + return -1; + + + if (!YAHOO_GetByte( "ShowAvatars", 0 )) + return -2; + + { + DBVARIANT dbv; + int ret = -3; + + if (YAHOO_GetDword("AvatarHash", 0)){ + + if (!DBGetContactSetting(NULL, yahooProtocolName, "AvatarFile", &dbv)){ + if (access(dbv.pszVal, 0) == 0){ + strncpy(buffer, dbv.pszVal, 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 YahooSetMyAvatar(WPARAM wParam, LPARAM lParam) +{ + char *szFile = (char *)lParam; + HANDLE avt; + + YAHOO_DebugLog("[YahooSetMyAvatar]"); + + avt = YAHOO_SetAvatar(szFile); + if (avt) { + DeleteObject(avt); // we release old avatar if any + return 0; + } else + return 1; /* error for now */ +} + +/* + * --=[ ]=-- + */ -- cgit v1.2.3