/* 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. */ #include "stdafx.h" namespace NServices { namespace NAvatar { static HANDLE ghChangedHook = nullptr; static int GetContactAvatarFileName(LPCWSTR zodiac, LPWSTR szFileName, int cchFileName) { if (!Profile_GetPathW(cchFileName, szFileName)) { size_t len = mir_wstrlen(szFileName); mir_snwprintf(szFileName + len, cchFileName - len, L"\\avatars\\%s.png", zodiac); return !PathFileExistsW(szFileName); } return 1; } static void SetZodiacAvatar(MCONTACT hContact) { MAnnivDate mtb; // try to load birthday for contact if (!mtb.DBGetBirthDate(hContact)) { MZodiac zodiac; //ICONINFO iinfo; WCHAR szFileName[MAX_PATH]; // get zodiac for birthday zodiac = mtb.Zodiac(); if (!GetContactAvatarFileName(zodiac.pszName, szFileName, _countof(szFileName))) { // extract the bitmap from the icon //GetIconInfo(zodiac.hIcon, &iinfo); // save the bitmap to a file used as avatar later if (!CallService(MS_AV_SETAVATARW, hContact, (LPARAM)szFileName)) db_set_b(hContact, "ContactPhoto", "IsZodiac", 1); } } } void DeleteAvatar(MCONTACT hContact) { if (hContact && db_get_b(hContact, "ContactPhoto", "IsZodiac", FALSE)) { db_unset(hContact, "ContactPhoto", "File"); db_unset(hContact, "ContactPhoto", "RFile"); db_unset(hContact, "ContactPhoto", "Backup"); db_unset(hContact, "ContactPhoto", "ImageHash"); db_set_b(hContact, "ContactPhoto", "IsZodiac", 0); } } static int OnAvatarChanged(MCONTACT hContact, AVATARCACHEENTRY *ace) { if (hContact) { // check valid parameters if (ace) { // set zodiac as avatar either if the desired avatar is invalid or a general protocol picture if (((ace->dwFlags & AVS_PROTOPIC) || !(ace->dwFlags & AVS_BITMAP_VALID))) { if (!db_get_b(hContact, "ContactPhoto", "IsZodiac", 0)) SetZodiacAvatar(hContact); } else db_set_b(hContact, "ContactPhoto", "IsZodiac", 0); } // avatar was deleted, so we can set up a zodiac avatar else SetZodiacAvatar(hContact); } return 0; } void Enable(BYTE bEnable) { DBVARIANT dbv; if (bEnable && !ghChangedHook) { // walk through all the contacts stored in the DB for (auto &hContact : Contacts()) { // don't set if avatar is locked! if (!db_get_b(hContact, "ContactPhoto", "Locked", 0)) { BYTE 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 (!PathToAbsolute(dbv.pszVal, absolute)) { FILE *f = fopen(absolute, "rb"); if (f) { bInvalidAvatar = FALSE; fclose(f); } } db_free(&dbv); } // the absolute file is valid if (bInvalidAvatar && !db_get(hContact, "ContactPhoto", "File", &dbv)) { FILE *f = fopen(dbv.pszVal, "rb"); if (f) { bInvalidAvatar = FALSE; fclose(f); } db_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 = nullptr; // walk through all the contacts stored in the DB for (auto &hContact : Contacts()) DeleteAvatar(hContact); } } /** * name: OnModulesLoaded * desc: initialize stuff, which require all standard modules to bee loaded * params: none * return: 0 **/ void OnModulesLoaded() { Enable(g_plugin.getByte(SET_ZODIAC_AVATARS, FALSE)); } } /* namespace NAvatar */ } /* namespace NServices */