/* UserinfoEx plugin for Miranda IM Copyright: ฉ 2006-2010 DeathAxe, Yasnovidyashii, Merlin, K. Romanov, Kreol This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. =============================================================================== File name : $HeadURL: https://userinfoex.googlecode.com/svn/trunk/svc_avatar.cpp $ Revision : $Revision: 187 $ Last change on : $Date: 2010-09-08 16:05:54 +0400 (ะกั€, 08 ัะตะฝ 2010) $ Last change by : $Author: ing.u.horn $ =============================================================================== */ #include "commonheaders.h" #include "m_protocols.h" #include "m_png.h" #include "m_avatars.h" namespace NServices { namespace NAvatar { static HANDLE ghChangedHook = NULL; /* int SaveBitmapAsAvatar(HBITMAP hBitmap, LPCSTR szFileName) { BITMAPINFO* bmi; HDC hdc; HBITMAP hOldBitmap; BITMAPINFOHEADER* pDib; BYTE* pDibBits; long dwPngSize = 0; DIB2PNG convertor; FILE* out; // file exists? out = fopen(szFileName, "rb"); if (out != NULL) { fclose(out); return ERROR_SUCCESS; } if (!ServiceExists(MS_DIB2PNG)) { MsgErr(NULL, TranslateT("Your png2dib.dll is either obsolete or damaged.")); 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 = (PBYTE)mir_alloc(dwPngSize); CallService(MS_DIB2PNG, 0, (LPARAM)&convertor); GlobalFree(pDib); out = fopen(szFileName, "wb"); if (out != NULL) { fwrite(convertor.pResult, dwPngSize, 1, out); fclose(out); } mir_free(convertor.pResult); return ERROR_SUCCESS; } */ static INT GetContactAvatarFileName(LPCTSTR zodiac, LPSTR szFileName, INT cchFileName) { if (!CallService(MS_DB_GETPROFILEPATH, (WPARAM)cchFileName, (LPARAM)szFileName)) { size_t len = mir_strlen(szFileName); CHAR tmp[64]; if (WideCharToMultiByte(CP_ACP, 0, zodiac, 64, tmp, SIZEOF(tmp),0,0) > 0) { mir_snprintf(szFileName + len, cchFileName - len, "\\avatars\\%s.png", tmp); } return !PathFileExistsA(szFileName); } return 1; } /** * * **/ static VOID SetZodiacAvatar(HANDLE hContact) { MAnnivDate mtb; // try to load birthday for contact if (!mtb.DBGetBirthDate(hContact)) { MZodiac zodiac; //ICONINFO iinfo; CHAR szFileName[MAX_PATH]; // get zodiac for birthday zodiac = mtb.Zodiac(); if (!GetContactAvatarFileName(zodiac.pszName, szFileName, SIZEOF(szFileName))) { // extract the bitmap from the icon //GetIconInfo(zodiac.hIcon, &iinfo); // save the bitmap to a file used as avatar later //if (!SaveBitmapAsAvatar(iinfo.hbmColor, szFileName)) { if (!CallService(MS_AV_SETAVATAR, (WPARAM)hContact, (LPARAM)szFileName)) { DB::Setting::WriteByte(hContact, "ContactPhoto", "IsZodiac", 1); } } } } } VOID DeleteAvatar(HANDLE hContact) { if (hContact && DB::Setting::GetByte(hContact, "ContactPhoto", "IsZodiac", FALSE)) { //AVATARCACHEENTRY *ace; LPSTR szProto = DB::Contact::Proto(hContact); DB::Setting::Delete(hContact, "ContactPhoto", "File"); DB::Setting::Delete(hContact, "ContactPhoto", "RFile"); DB::Setting::Delete(hContact, "ContactPhoto", "Backup"); DB::Setting::Delete(hContact, "ContactPhoto", "ImageHash"); DB::Setting::WriteByte(hContact, "ContactPhoto", "IsZodiac", 0); /* ace = (AVATARCACHEENTRY *)CallService(MS_AV_GETMYAVATAR, NULL, (LPARAM)szProto); if (ace) { if (!CallService(MS_AV_SETAVATAR, (WPARAM)hContact, (LPARAM)ace->szFilename)) { DB::Setting::WriteByte(hContact, "ContactPhoto", "IsZodiac", 0); } } */ } } /** * * **/ static INT OnAvatarChanged(HANDLE hContact, AVATARCACHEENTRY *ace) { if (hContact) { // check valid parameters if (ace) { if (// check for correct structure ace->cbSize == sizeof(AVATARCACHEENTRY) && // set zodiac as avatar either if the desired avatar is invalid or a general protocol picture ((ace->dwFlags & AVS_PROTOPIC) || !(ace->dwFlags & AVS_BITMAP_VALID))) { if (!DB::Setting::GetByte(hContact, "ContactPhoto", "IsZodiac", 0)) { SetZodiacAvatar(hContact); } } else { DB::Setting::WriteByte(hContact, "ContactPhoto", "IsZodiac", 0); } } // avatar was deleted, so we can set up a zodiac avatar else { SetZodiacAvatar(hContact); } } return 0; } /** * * **/ VOID Enable(BOOLEAN bEnable) { HANDLE hContact; DBVARIANT dbv; if (bEnable && !ghChangedHook) { //walk through all the contacts stored in the DB for (hContact = DB::Contact::FindFirst(); hContact != NULL; hContact = DB::Contact::FindNext(hContact)) { // don't set if avatar is locked! if (!DB::Setting::GetByte(hContact, "ContactPhoto", "Locked", 0)) { BOOLEAN bInvalidAvatar = TRUE; // the relative file is valid if (!DB::Setting::GetAString(hContact, "ContactPhoto", "RFile", &dbv)) { CHAR absolute[MAX_PATH]; absolute[0] = '\0'; // check if file exists if (!CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)dbv.pszVal, (LPARAM)absolute)) { FILE *f = fopen(absolute, "rb"); if (f) { bInvalidAvatar = FALSE; fclose(f); } } DB::Variant::Free(&dbv); } // the absolute file is valid if (bInvalidAvatar && !DBGetContactSetting(hContact, "ContactPhoto", "File", &dbv)) { FILE *f = fopen(dbv.pszVal, "rb"); if (f) { bInvalidAvatar = FALSE; fclose(f); } DB::Variant::Free(&dbv); } // set the zodiac as avatar if (bInvalidAvatar) { SetZodiacAvatar(hContact); } } } ghChangedHook = HookEvent(ME_AV_AVATARCHANGED, (MIRANDAHOOK) OnAvatarChanged); } else if (!bEnable && ghChangedHook) { UnhookEvent(ghChangedHook); ghChangedHook = NULL; //walk through all the contacts stored in the DB for (hContact = DB::Contact::FindFirst(); hContact != NULL; hContact = DB::Contact::FindNext(hContact)) { DeleteAvatar(hContact); } } } /** * name: OnModulesLoaded * desc: initialize stuff, which require all standard modules to bee loaded * params: none * return: 0 **/ VOID OnModulesLoaded() { Enable(DB::Setting::GetByte(SET_ZODIAC_AVATARS, FALSE)); } } /* namespace NAvatar */ } /* namespace NServices */