/* Avatar History Plugin --------- This plugin uses the event provided by Avatar Service to automatically back up contacts' avatars when they change. Copyright (C) 2006 Matthew Wild - Email: mwild1@gmail.com 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "stdafx.h" bool ProtocolEnabled(const char *proto) { if (proto == NULL) return FALSE; char setting[256]; mir_snprintf(setting, "%sEnabled", proto); return 0 != db_get_b(NULL, MODULE_NAME, setting, true); } bool ContactEnabled(MCONTACT hContact, char *setting, int def) { if (hContact == NULL) return false; char *proto = GetContactProto(hContact); if (!ProtocolEnabled(proto)) return false; BYTE globpref = db_get_b(NULL, MODULE_NAME, setting, def); BYTE userpref = db_get_b(hContact, MODULE_NAME, setting, BST_INDETERMINATE); return (globpref && userpref == BST_INDETERMINATE) || userpref == BST_CHECKED; } // Returns true if the unicode buffer only contains 7-bit characters. BOOL IsUnicodeAscii(const WCHAR * pBuffer, int nSize) { for (int nIndex = 0; nIndex < nSize; nIndex++) if (pBuffer[nIndex] > 0x7F) return FALSE; return TRUE; } void ConvertToFilename(wchar_t *str, size_t size) { for(size_t i = 0; i < size && str[i] != '\0'; i++) { switch(str[i]) { case '/': case '\\': case ':': case '*': case '?': case '"': case '<': case '>': case '|': str[i] = '_'; } } } wchar_t* GetExtension(wchar_t *file) { if (file == NULL) return L""; wchar_t *ext = wcsrchr(file, '.'); if (ext != NULL) ext++; else ext = L""; return ext; } wchar_t* GetHistoryFolder(wchar_t *fn) { if (fn == NULL) return NULL; FoldersGetCustomPathT(hFolder, fn, MAX_PATH, basedir); CreateDirectoryTreeT(fn); return fn; } wchar_t* GetProtocolFolder(wchar_t *fn, char *proto) { GetHistoryFolder(fn); if (proto == NULL) proto = Translate("Unknown Protocol"); mir_sntprintf(fn, MAX_PATH, L"%s\\%S", fn, proto); CreateDirectoryTreeT(fn); return fn; } wchar_t* GetContactFolder(wchar_t *fn, MCONTACT hContact) { char *proto = GetContactProto(hContact); GetProtocolFolder(fn, proto); wchar_t uin[MAX_PATH]; ptrT id(Contact_GetInfo(CNF_UNIQUEID, hContact, proto)); wcsncpy_s(uin, (id == NULL) ? TranslateT("Unknown UIN") : id, _TRUNCATE); ConvertToFilename(uin, MAX_PATH); //added so that weather id's like "yw/CI0000" work mir_sntprintf(fn, MAX_PATH, L"%s\\%s", fn, uin); CreateDirectoryTreeT(fn); #ifdef DBGPOPUPS wchar_t log[1024]; mir_sntprintf(log, L"Path: %s\nProto: %S\nUIN: %s", fn, proto, uin); ShowPopup(hContact, L"AVH Debug: GetContactFolder", log); #endif return fn; } wchar_t* GetOldStyleAvatarName(wchar_t *fn, MCONTACT hContact) { GetContactFolder(fn, hContact); SYSTEMTIME curtime; GetLocalTime(&curtime); mir_sntprintf(fn, MAX_PATH, L"%s\\%04d-%02d-%02d %02dh%02dm%02ds", fn, curtime.wYear, curtime.wMonth, curtime.wDay, curtime.wHour, curtime.wMinute, curtime.wSecond); ShowDebugPopup(hContact,TranslateT("AVH Debug: GetOldStyleAvatarName"),fn); return fn; } void CreateOldStyleShortcut(MCONTACT hContact, wchar_t *history_filename) { wchar_t shortcut[MAX_PATH] = L""; GetOldStyleAvatarName(shortcut, hContact); mir_sntprintf(shortcut, L"%s.%s.lnk", shortcut, GetExtension(history_filename)); if (!CreateShortcut(history_filename, shortcut)) { ShowPopup(hContact, TranslateT("Avatar History: Unable to create shortcut"), shortcut); } else { ShowDebugPopup(hContact, TranslateT("AVH Debug: Shortcut created successfully"), shortcut); } } BOOL CopyImageFile(wchar_t *old_file, wchar_t *new_file) { wchar_t *ext = GetExtension(old_file); mir_sntprintf(new_file, MAX_PATH, L"%s.%s", new_file, ext); return !CopyFile(old_file, new_file, TRUE); } wchar_t * GetCachedAvatar(char *proto, wchar_t *hash) { wchar_t *ret = NULL; wchar_t file[1024] = L""; wchar_t search[1024] = L""; if (opts.log_keep_same_folder) GetHistoryFolder(file); else GetProtocolFolder(file, proto); mir_sntprintf(search, L"%s\\%s.*", file, hash); WIN32_FIND_DATA finddata; HANDLE hFind = FindFirstFile(search, &finddata); if (hFind == INVALID_HANDLE_VALUE) return NULL; do { size_t len = mir_tstrlen(finddata.cFileName); if (len > 4 && (!mir_tstrcmpi(&finddata.cFileName[len-4], L".png") || !mir_tstrcmpi(&finddata.cFileName[len-4], L".bmp") || !mir_tstrcmpi(&finddata.cFileName[len-4], L".gif") || !mir_tstrcmpi(&finddata.cFileName[len-4], L".jpg") || !mir_tstrcmpi(&finddata.cFileName[len-5], L".jpeg"))) { mir_sntprintf(file, L"%s\\%s", file, finddata.cFileName); ret = mir_tstrdup(file); break; } } while(FindNextFile(hFind, &finddata)); FindClose(hFind); return ret; } BOOL CreateShortcut(wchar_t *file, wchar_t *shortcut) { IShellLink *psl = NULL; HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **) &psl); if (SUCCEEDED(hr)) { psl->SetPath(file); IPersistFile *ppf = NULL; hr = psl->QueryInterface(IID_IPersistFile, (void **) &ppf); if (SUCCEEDED(hr)) { hr = ppf->Save(shortcut, TRUE); ppf->Release(); } psl->Release(); } return SUCCEEDED(hr); } BOOL ResolveShortcut(wchar_t *shortcut, wchar_t *file) { IShellLink* psl = NULL; HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **) &psl); if (SUCCEEDED(hr)) { IPersistFile* ppf = NULL; hr = psl->QueryInterface(IID_IPersistFile, (void **) &ppf); if (SUCCEEDED(hr)) { hr = ppf->Load(shortcut, STGM_READ); if (SUCCEEDED(hr)) { hr = psl->Resolve(NULL, SLR_UPDATE); if (SUCCEEDED(hr)) { WIN32_FIND_DATA wfd; hr = psl->GetPath(file, MAX_PATH, &wfd, SLGP_RAWPATH); } } ppf->Release(); } psl->Release(); } return SUCCEEDED(hr); }