diff options
author | George Hazan <george.hazan@gmail.com> | 2013-08-10 21:34:29 +0000 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2013-08-10 21:34:29 +0000 |
commit | 960336573d3420785094dd46fe4a3edb4cb152a8 (patch) | |
tree | f4e581537a72dad2e1fb07ab0cc8eef91bd56e3f /plugins/AVS/src/services.cpp | |
parent | 84bb8836befd3d31b22562bb02f4ecf22e92c4a9 (diff) |
divide et impera
git-svn-id: http://svn.miranda-ng.org/main/trunk@5639 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/AVS/src/services.cpp')
-rw-r--r-- | plugins/AVS/src/services.cpp | 997 |
1 files changed, 997 insertions, 0 deletions
diff --git a/plugins/AVS/src/services.cpp b/plugins/AVS/src/services.cpp new file mode 100644 index 0000000000..bb1014d70a --- /dev/null +++ b/plugins/AVS/src/services.cpp @@ -0,0 +1,997 @@ +/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2004 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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 "commonheaders.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+INT_PTR GetAvatarBitmap(WPARAM wParam, LPARAM lParam)
+{
+ if (wParam == 0 || g_shutDown || fei == NULL)
+ return 0;
+
+ HANDLE hContact = (HANDLE) wParam;
+ hContact = GetContactThatHaveTheAvatar(hContact);
+
+ // Get the node
+ CacheNode *node = FindAvatarInCache(hContact, TRUE);
+ if (node == NULL || !node->loaded)
+ return (INT_PTR) GetProtoDefaultAvatar(hContact);
+ else
+ return (INT_PTR) &node->ace;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+INT_PTR ProtectAvatar(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ BYTE was_locked = db_get_b(hContact, "ContactPhoto", "Locked", 0);
+
+ if (fei == NULL || was_locked == (BYTE)lParam) // no need for redundant lockings...
+ return 0;
+
+ if (hContact) {
+ if (!was_locked)
+ MakePathRelative(hContact);
+ db_set_b(hContact, "ContactPhoto", "Locked", lParam ? 1 : 0);
+ if (lParam == 0)
+ MakePathRelative(hContact);
+ ChangeAvatar(hContact, TRUE);
+ }
+ return 0;
+}
+
+/*
+ * set an avatar (service function)
+ * if lParam == NULL, a open file dialog will be opened, otherwise, lParam is taken as a FULL
+ * image filename (will be checked for existance, though)
+ */
+
+struct OpenFileSubclassData {
+ BYTE *locking_request;
+ BYTE setView;
+};
+
+BOOL CALLBACK OpenFileSubclass(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ OpenFileSubclassData *data= (OpenFileSubclassData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+
+ switch(msg) {
+ case WM_INITDIALOG:
+ {
+ OPENFILENAME *ofn = (OPENFILENAME *)lParam;
+
+ data = (OpenFileSubclassData *) malloc(sizeof(OpenFileSubclassData));
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)data);
+ data->locking_request = (BYTE *)ofn->lCustData;
+ data->setView = TRUE;
+
+ TranslateDialogDefault(hwnd);
+ CheckDlgButton(hwnd, IDC_PROTECTAVATAR, *(data->locking_request));
+ }
+ break;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_PROTECTAVATAR)
+ *(data->locking_request) = IsDlgButtonChecked(hwnd, IDC_PROTECTAVATAR) ? TRUE : FALSE;
+ break;
+
+ case WM_NOTIFY:
+ if (data->setView) {
+ HWND hwndParent = GetParent(hwnd);
+ HWND hwndLv = FindWindowEx(hwndParent, NULL, _T("SHELLDLL_DefView"), NULL) ;
+ if (hwndLv != NULL) {
+ SendMessage(hwndLv, WM_COMMAND, SHVIEW_THUMBNAIL, 0);
+ data->setView = FALSE;
+ }
+ }
+ break;
+
+ case WM_NCDESTROY:
+ free((OpenFileSubclassData *)data);
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)0);
+ break;
+ }
+
+ return FALSE;
+}
+
+static INT_PTR avSetAvatar(HANDLE hContact, TCHAR *tszPath)
+{
+ BYTE is_locked = 0;
+ TCHAR FileName[MAX_PATH], szBackupName[MAX_PATH];
+ TCHAR *szFinalName = NULL;
+ HANDLE hFile = 0;
+ BYTE locking_request;
+
+ if (hContact == NULL || fei == NULL)
+ return 0;
+
+ is_locked = db_get_b(hContact, "ContactPhoto", "Locked", 0);
+
+ if ( tszPath == NULL ) {
+ OPENFILENAME ofn = {0};
+ TCHAR filter[256];
+
+ filter[0] = '\0';
+ CallService(MS_UTILS_GETBITMAPFILTERSTRINGST, SIZEOF(filter), ( LPARAM )filter);
+
+ if (IsWinVer2000Plus())
+ ofn.lStructSize = sizeof(ofn);
+ else
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+ ofn.hwndOwner = 0;
+ ofn.lpstrFile = FileName;
+ ofn.lpstrFilter = filter;
+ ofn.nMaxFile = MAX_PATH;
+ ofn.nMaxFileTitle = MAX_PATH;
+ ofn.Flags = OFN_FILEMUSTEXIST | OFN_ENABLETEMPLATE | OFN_EXPLORER | OFN_ENABLESIZING | OFN_ENABLEHOOK;
+ ofn.lpstrInitialDir = _T(".");
+ *FileName = '\0';
+ ofn.lpstrDefExt = _T("");
+ ofn.hInstance = g_hInst;
+ ofn.lpTemplateName = MAKEINTRESOURCE(IDD_OPENSUBCLASS);
+ ofn.lpfnHook = (LPOFNHOOKPROC)OpenFileSubclass;
+ locking_request = is_locked;
+ ofn.lCustData = (LPARAM)&locking_request;
+ if (GetOpenFileName(&ofn)) {
+ szFinalName = FileName;
+ is_locked = locking_request ? 1 : is_locked;
+ }
+ else
+ return 0;
+ }
+ else
+ szFinalName = tszPath;
+
+ /*
+ * filename is now set, check it and perform all needed action
+ */
+
+ if ((hFile = CreateFile(szFinalName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
+ return 0;
+
+ // file exists...
+
+ CloseHandle(hFile);
+
+ AVS_pathToRelative(szFinalName, szBackupName);
+ db_set_ts(hContact, "ContactPhoto", "Backup", szBackupName);
+
+ db_set_b(hContact, "ContactPhoto", "Locked", is_locked);
+ db_set_ts(hContact, "ContactPhoto", "File", szFinalName);
+ MakePathRelative(hContact, szFinalName);
+ // Fix cache
+ ChangeAvatar(hContact, TRUE);
+
+ return 0;
+}
+
+INT_PTR SetAvatar(WPARAM wParam, LPARAM lParam)
+{
+ return avSetAvatar((HANDLE)wParam, _A2T((const char*)lParam ));
+}
+
+INT_PTR SetAvatarW(WPARAM wParam, LPARAM lParam)
+{
+ return avSetAvatar((HANDLE)wParam, (TCHAR*)lParam );
+}
+
+/*
+ * see if is possible to set the avatar for the expecified protocol
+ */
+
+static INT_PTR CanSetMyAvatar(WPARAM wParam, LPARAM lParam)
+{
+ char *protocol = (char *) wParam;
+ if (protocol == NULL || fei == NULL)
+ return 0;
+
+ return ProtoServiceExists(protocol, PS_SETMYAVATAR);
+}
+
+/*
+ * set an avatar for a protocol (service function)
+ * if lParam == NULL, a open file dialog will be opened, otherwise, lParam is taken as a FULL
+ * image filename (will be checked for existance, though)
+ */
+
+static int InternalRemoveMyAvatar(char *protocol)
+{
+ SetIgnoreNotify(protocol, TRUE);
+
+ // Remove avatar
+ int ret = 0;
+ if (protocol != NULL)
+ {
+ if ( ProtoServiceExists(protocol, PS_SETMYAVATAR))
+ ret = SaveAvatar(protocol, NULL);
+ else
+ ret = -3;
+
+ if (ret == 0)
+ {
+ // Has global avatar?
+ DBVARIANT dbv = {0};
+ if ( !db_get_ts(NULL, AVS_MODULE, "GlobalUserAvatarFile", &dbv)) {
+ db_free(&dbv);
+ db_set_b(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1);
+ DeleteGlobalUserAvatar();
+ }
+ }
+ }
+ else
+ {
+ PROTOACCOUNT **accs;
+ int i,count;
+
+ ProtoEnumAccounts( &count, &accs );
+ for (i = 0; i < count; i++)
+ {
+ if ( !ProtoServiceExists( accs[i]->szModuleName, PS_SETMYAVATAR))
+ continue;
+
+ if (!Proto_IsAvatarsEnabled( accs[i]->szModuleName ))
+ continue;
+
+ // Found a protocol
+ int retTmp = SaveAvatar( accs[i]->szModuleName, NULL);
+ if (retTmp != 0)
+ ret = retTmp;
+ }
+
+ DeleteGlobalUserAvatar();
+
+ if (ret)
+ db_set_b(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1);
+ else
+ db_set_b(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 0);
+ }
+
+ SetIgnoreNotify(protocol, FALSE);
+
+ ReportMyAvatarChanged(WPARAM((protocol == NULL ) ? "" : protocol), 0);
+ return ret;
+}
+
+static void FilterGetStrings(TCHAR *filter, int bytesLeft, BOOL xml, BOOL swf)
+{
+ TCHAR *pfilter;
+ int wParam = bytesLeft;
+
+ lstrcpyn(filter, TranslateT("All Files"), bytesLeft); bytesLeft-=lstrlen(filter);
+ _tcsncat(filter, _T(" (*.bmp;*.jpg;*.gif;*.png"), bytesLeft);
+ if (swf) _tcscat(filter, _T(";*.swf"));
+ if (xml) _tcscat(filter, _T(";*.xml"));
+ _tcscat(filter, _T(")"));
+ pfilter=filter+lstrlen(filter)+1; bytesLeft=wParam-(pfilter-filter);
+ lstrcpyn(pfilter, _T("*.BMP;*.RLE;*.JPG;*.JPEG;*.GIF;*.PNG"), bytesLeft);
+ if (swf) _tcscat(pfilter, _T(";*.SWF"));
+ if (xml) _tcscat(pfilter, _T(";*.XML"));
+ pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter);
+
+ lstrcpyn(pfilter, TranslateT("Windows Bitmaps"), bytesLeft); bytesLeft-=lstrlen(pfilter);
+ _tcsncat(pfilter, _T(" (*.bmp;*.rle)"), bytesLeft);
+ pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter);
+ lstrcpyn(pfilter, _T("*.BMP;*.RLE"), bytesLeft);
+ pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter);
+
+ lstrcpyn(pfilter,TranslateT("JPEG Bitmaps"),bytesLeft); bytesLeft-=lstrlen(pfilter);
+ _tcsncat(pfilter, _T(" (*.jpg;*.jpeg)"), bytesLeft);
+ pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter);
+ lstrcpyn(pfilter, _T("*.JPG;*.JPEG"), bytesLeft);
+ pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter);
+
+ lstrcpyn(pfilter,TranslateT("GIF Bitmaps"),bytesLeft); bytesLeft-=lstrlen(pfilter);
+ _tcsncat(pfilter, _T(" (*.gif)"), bytesLeft);
+ pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter);
+ lstrcpyn(pfilter, _T("*.GIF"), bytesLeft);
+ pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter);
+
+ lstrcpyn(pfilter,TranslateT("PNG Bitmaps"), bytesLeft); bytesLeft-=lstrlen(pfilter);
+ _tcsncat(pfilter, _T(" (*.png)"), bytesLeft);
+ pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter);
+ lstrcpyn(pfilter, _T("*.PNG"), bytesLeft);
+ pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter);
+
+ if (swf)
+ {
+ lstrcpyn(pfilter,TranslateT("Flash Animations"), bytesLeft); bytesLeft-=lstrlen(pfilter);
+ _tcsncat(pfilter, _T(" (*.swf)"), bytesLeft);
+ pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter);
+ lstrcpyn(pfilter, _T("*.SWF"), bytesLeft);
+ pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter);
+ }
+
+ if (xml)
+ {
+ lstrcpyn(pfilter, TranslateT("XML Files"), bytesLeft); bytesLeft-=lstrlen(pfilter);
+ _tcsncat(pfilter, _T(" (*.xml)"), bytesLeft);
+ pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter);
+ lstrcpyn(pfilter, _T("*.XML"), bytesLeft);
+ pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter);
+ }
+
+ if (bytesLeft) *pfilter='\0';
+}
+
+/*
+ * Callback to set thumbnaill view to open dialog
+ */
+static UINT_PTR CALLBACK SetMyAvatarHookProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_INITDIALOG:
+ {
+ hwndSetMyAvatar = hwnd;
+
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)lParam);
+ OPENFILENAME *ofn = (OPENFILENAME *)lParam;
+ SetMyAvatarHookData *data = (SetMyAvatarHookData *) ofn->lCustData;
+ data->thumbnail = TRUE;
+
+ SetWindowText(GetDlgItem(hwnd, IDC_MAKE_SQUARE), TranslateT("Make the avatar square"));
+ SetWindowText(GetDlgItem(hwnd, IDC_GROW), TranslateT("Grow avatar to fit max allowed protocol size"));
+
+ CheckDlgButton(hwnd, IDC_MAKE_SQUARE, data->square ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwnd, IDC_GROW, data->grow ? BST_CHECKED : BST_UNCHECKED);
+
+ if (data->protocol != NULL && (Proto_AvatarImageProportion(data->protocol) & PIP_SQUARE))
+ EnableWindow(GetDlgItem(hwnd, IDC_MAKE_SQUARE), FALSE);
+ }
+ break;
+
+ case WM_NOTIFY:
+ {
+ OPENFILENAME *ofn = (OPENFILENAME *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ SetMyAvatarHookData *data = (SetMyAvatarHookData *) ofn->lCustData;
+ if (data->thumbnail)
+ {
+ HWND hwndParent = GetParent(hwnd);
+ HWND hwndLv = FindWindowEx(hwndParent, NULL, _T("SHELLDLL_DefView"), NULL) ;
+ if (hwndLv != NULL)
+ {
+ SendMessage(hwndLv, WM_COMMAND, SHVIEW_THUMBNAIL, 0);
+ data->thumbnail = FALSE;
+ }
+ }
+ break;
+ }
+ case WM_DESTROY:
+ {
+ OPENFILENAME *ofn = (OPENFILENAME *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ SetMyAvatarHookData *data = (SetMyAvatarHookData *) ofn->lCustData;
+ data->square = IsDlgButtonChecked(hwnd, IDC_MAKE_SQUARE);
+ data->grow = IsDlgButtonChecked(hwnd, IDC_GROW);
+
+ hwndSetMyAvatar = NULL;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+struct SaveProtocolData {
+ DWORD max_size;
+ TCHAR image_file_name[MAX_PATH];
+ BOOL saved;
+ BOOL need_smaller_size;
+ int width;
+ int height;
+ TCHAR temp_file[MAX_PATH];
+ HBITMAP hBmpProto;
+};
+
+void SaveImage(SaveProtocolData &d, char *protocol, int format)
+{
+ if (Proto_IsAvatarFormatSupported(protocol, format))
+ {
+ mir_sntprintf(d.image_file_name, SIZEOF(d.image_file_name), _T("%s%s"), d.temp_file, GetFormatExtension(format));
+ if (!BmpFilterSaveBitmapT(d.hBmpProto, d.image_file_name, format == PA_FORMAT_JPEG ? JPEG_QUALITYSUPERB : 0))
+ {
+ if (d.max_size != 0 && GetFileSize(d.image_file_name) > d.max_size)
+ {
+ DeleteFile(d.image_file_name);
+
+ if (format == PA_FORMAT_JPEG)
+ {
+ // Try with lower quality
+ if (!BmpFilterSaveBitmapT(d.hBmpProto, d.image_file_name, JPEG_QUALITYGOOD))
+ {
+ if (GetFileSize(d.image_file_name) > d.max_size)
+ {
+ DeleteFile(d.image_file_name);
+ d.need_smaller_size = TRUE;
+ }
+ else
+ d.saved = TRUE;
+ }
+ }
+ else
+ d.need_smaller_size = TRUE;
+ }
+ else
+ d.saved = TRUE;
+ }
+ }
+}
+
+static int SetProtoMyAvatar(char *protocol, HBITMAP hBmp, TCHAR *originalFilename, int originalFormat, BOOL square, BOOL grow)
+{
+ if (!ProtoServiceExists(protocol, PS_SETMYAVATAR))
+ return -1;
+
+ // If is swf or xml, just set it
+
+ if (originalFormat == PA_FORMAT_SWF)
+ {
+ if (!Proto_IsAvatarFormatSupported(protocol, PA_FORMAT_SWF))
+ return -1;
+
+ return SaveAvatar(protocol, originalFilename);
+ }
+
+ if (originalFormat == PA_FORMAT_XML)
+ {
+ if (!Proto_IsAvatarFormatSupported(protocol, PA_FORMAT_XML))
+ return -1;
+
+ return SaveAvatar(protocol, originalFilename);
+ }
+
+ // Get protocol info
+ SaveProtocolData d = {0};
+
+ d.max_size = (DWORD) Proto_GetAvatarMaxFileSize(protocol);
+
+ Proto_GetAvatarMaxSize(protocol, &d.width, &d.height);
+ int orig_width = d.width;
+ int orig_height = d.height;
+
+ if (Proto_AvatarImageProportion(protocol) & PIP_SQUARE)
+ square = TRUE;
+
+ // Try to save until a valid image is found or we give up
+ int num_tries = 0;
+ do {
+ // Lets do it
+ ResizeBitmap rb;
+ rb.size = sizeof(ResizeBitmap);
+ rb.hBmp = hBmp;
+ rb.max_height = d.height;
+ rb.max_width = d.width;
+ rb.fit = (grow ? 0 : RESIZEBITMAP_FLAG_DONT_GROW)
+ | (square ? RESIZEBITMAP_MAKE_SQUARE : RESIZEBITMAP_KEEP_PROPORTIONS);
+
+ d.hBmpProto = (HBITMAP) BmpFilterResizeBitmap((WPARAM)&rb, 0);
+
+ if (d.hBmpProto == NULL)
+ {
+ if (d.temp_file[0] != '\0')
+ DeleteFile(d.temp_file);
+ return -1;
+ }
+
+ // Check if can use original image
+ if (d.hBmpProto == hBmp
+ && Proto_IsAvatarFormatSupported(protocol, originalFormat)
+ && (d.max_size == 0 || GetFileSize(originalFilename) < d.max_size))
+ {
+ if (d.temp_file[0] != '\0')
+ DeleteFile(d.temp_file);
+
+ // Use original image
+ return SaveAvatar(protocol, originalFilename);
+ }
+
+ // Create a temporary file (if was not created already)
+ if (d.temp_file[0] == '\0')
+ {
+ d.temp_file[0] = '\0';
+ if (GetTempPath(MAX_PATH, d.temp_file) == 0
+ || GetTempFileName(d.temp_file, _T("mir_av_"), 0, d.temp_file) == 0)
+ {
+ DeleteObject(d.hBmpProto);
+ return -1;
+ }
+ }
+
+ // Which format?
+
+ // First try to use original format
+ if (originalFormat != PA_FORMAT_BMP)
+ SaveImage(d, protocol, originalFormat);
+
+ if (!d.saved && originalFormat != PA_FORMAT_PNG)
+ SaveImage(d, protocol, PA_FORMAT_PNG);
+
+ if (!d.saved && originalFormat != PA_FORMAT_JPEG)
+ SaveImage(d, protocol, PA_FORMAT_JPEG);
+
+ if (!d.saved && originalFormat != PA_FORMAT_GIF)
+ SaveImage(d, protocol, PA_FORMAT_GIF);
+
+ if (!d.saved)
+ SaveImage(d, protocol, PA_FORMAT_BMP);
+
+ num_tries++;
+ if (!d.saved && d.need_smaller_size && num_tries < 4)
+ {
+ // Cleanup
+ if (d.hBmpProto != hBmp)
+ DeleteObject(d.hBmpProto);
+
+ // use a smaller size
+ d.width = orig_width * (4 - num_tries) / 4;
+ d.height = orig_height * (4 - num_tries) / 4;
+ }
+
+ } while(!d.saved && d.need_smaller_size && num_tries < 4);
+
+ int ret;
+
+ if (d.saved)
+ {
+ // Call proto service
+ ret = SaveAvatar(protocol, d.image_file_name);
+ DeleteFile(d.image_file_name);
+ }
+ else
+ {
+ ret = -1;
+ }
+
+ if (d.temp_file[0] != '\0')
+ DeleteFile(d.temp_file);
+
+ if (d.hBmpProto != hBmp)
+ DeleteObject(d.hBmpProto);
+
+ return ret;
+}
+
+static int InternalSetMyAvatar(char *protocol, TCHAR *szFinalName, SetMyAvatarHookData &data, BOOL allAcceptXML, BOOL allAcceptSWF)
+{
+ HANDLE hFile = 0;
+
+ int format = GetImageFormat(szFinalName);
+ if (format == PA_FORMAT_UNKNOWN || (hFile = CreateFile(szFinalName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
+ return -3;
+
+ CloseHandle(hFile);
+
+ // file exists...
+
+ HBITMAP hBmp = NULL;
+
+ if (format == PA_FORMAT_SWF)
+ {
+ if (!allAcceptSWF)
+ return -4;
+ }
+ else if (format == PA_FORMAT_XML)
+ {
+ if (!allAcceptXML)
+ return -4;
+ }
+ else
+ {
+ // Try to open if is not a flash or XML
+ hBmp = (HBITMAP) CallService(MS_IMG_LOAD, (WPARAM) szFinalName, IMGL_TCHAR);
+ if (hBmp == NULL)
+ return -4;
+ }
+
+ SetIgnoreNotify(protocol, TRUE);
+
+ int ret = 0;
+ if (protocol != NULL)
+ {
+ ret = SetProtoMyAvatar(protocol, hBmp, szFinalName, format, data.square, data.grow);
+
+ if (ret == 0)
+ {
+ DeleteGlobalUserAvatar();
+ db_set_b(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1);
+ }
+ }
+ else
+ {
+ PROTOACCOUNT **accs;
+ int i,count;
+
+ ProtoEnumAccounts( &count, &accs );
+ for (i = 0; i < count; i++)
+ {
+ if ( !ProtoServiceExists( accs[i]->szModuleName, PS_SETMYAVATAR))
+ continue;
+
+ if ( !Proto_IsAvatarsEnabled( accs[i]->szModuleName ))
+ continue;
+
+ int retTmp = SetProtoMyAvatar( accs[i]->szModuleName, hBmp, szFinalName, format, data.square, data.grow);
+ if (retTmp != 0)
+ ret = retTmp;
+ }
+
+ DeleteGlobalUserAvatar();
+
+ if (ret)
+ {
+ db_set_b(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1);
+ }
+ else
+ {
+ // Copy avatar file to store as global one
+ TCHAR globalFile[1024];
+ BOOL saved = TRUE;
+ if (FoldersGetCustomPathT(hGlobalAvatarFolder, globalFile, SIZEOF(globalFile), _T("")))
+ {
+ mir_sntprintf(globalFile, SIZEOF(globalFile), _T("%s\\%s"), g_szDataPath, _T("GlobalAvatar"));
+ CreateDirectory(globalFile, NULL);
+ }
+
+ TCHAR *ext = _tcsrchr(szFinalName, _T('.')); // Can't be NULL here
+ if (format == PA_FORMAT_XML || format == PA_FORMAT_SWF)
+ {
+ mir_sntprintf(globalFile, SIZEOF(globalFile), _T("%s\\my_global_avatar%s"), globalFile, ext);
+ CopyFile(szFinalName, globalFile, FALSE);
+ }
+ else
+ {
+ // Resize (to avoid too big avatars)
+ ResizeBitmap rb = {0};
+ rb.size = sizeof(ResizeBitmap);
+ rb.hBmp = hBmp;
+ rb.max_height = 300;
+ rb.max_width = 300;
+ rb.fit = (data.grow ? 0 : RESIZEBITMAP_FLAG_DONT_GROW)
+ | (data.square ? RESIZEBITMAP_MAKE_SQUARE : RESIZEBITMAP_KEEP_PROPORTIONS);
+
+ HBITMAP hBmpTmp = (HBITMAP) BmpFilterResizeBitmap((WPARAM)&rb, 0);
+
+ // Check if need to resize
+ if (hBmpTmp == hBmp || hBmpTmp == NULL)
+ {
+ // Use original image
+ mir_sntprintf(globalFile, SIZEOF(globalFile), _T("%s\\my_global_avatar%s"), globalFile, ext);
+ CopyFile(szFinalName, globalFile, FALSE);
+ }
+ else
+ {
+ // Save as PNG
+ mir_sntprintf(globalFile, SIZEOF(globalFile), _T("%s\\my_global_avatar.png"), globalFile);
+ if (BmpFilterSaveBitmap((WPARAM) hBmpTmp, (LPARAM) globalFile))
+ saved = FALSE;
+
+ DeleteObject(hBmpTmp);
+ }
+ }
+
+ if (saved)
+ {
+ TCHAR relFile[1024];
+ if (AVS_pathToRelative(globalFile, relFile))
+ db_set_ts(NULL, AVS_MODULE, "GlobalUserAvatarFile", relFile);
+ else
+ db_set_ts(NULL, AVS_MODULE, "GlobalUserAvatarFile", globalFile);
+
+ db_set_b(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 0);
+ }
+ else
+ {
+ db_set_b(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1);
+ }
+ }
+ }
+
+ DeleteObject(hBmp);
+
+ SetIgnoreNotify(protocol, FALSE);
+
+ ReportMyAvatarChanged(WPARAM((protocol == NULL) ? "" : protocol), 0);
+ return ret;
+}
+
+INT_PTR avSetMyAvatar( char* protocol, TCHAR* tszPath )
+{
+ TCHAR FileName[MAX_PATH];
+ TCHAR *szFinalName = NULL;
+ BOOL allAcceptXML;
+ BOOL allAcceptSWF;
+
+ // Protocol allow seting of avatar?
+ if (protocol != NULL && !CanSetMyAvatar((WPARAM)protocol, 0))
+ return -1;
+
+ if (tszPath == NULL && hwndSetMyAvatar != 0) {
+ SetForegroundWindow(hwndSetMyAvatar);
+ SetFocus(hwndSetMyAvatar);
+ ShowWindow(hwndSetMyAvatar, SW_SHOW);
+ return -2;
+ }
+
+ SetMyAvatarHookData data = { 0 };
+
+ // Check for XML and SWF
+ if (protocol == NULL)
+ {
+ allAcceptXML = TRUE;
+ allAcceptSWF = TRUE;
+
+ PROTOACCOUNT **accs;
+ int i,count;
+
+ ProtoEnumAccounts( &count, &accs );
+ for (i = 0; i < count; i++)
+ {
+ if ( !ProtoServiceExists( accs[i]->szModuleName, PS_SETMYAVATAR))
+ continue;
+
+ if ( !Proto_IsAvatarsEnabled( accs[i]->szModuleName ))
+ continue;
+
+ allAcceptXML = allAcceptXML && Proto_IsAvatarFormatSupported( accs[i]->szModuleName, PA_FORMAT_XML);
+ allAcceptSWF = allAcceptSWF && Proto_IsAvatarFormatSupported( accs[i]->szModuleName, PA_FORMAT_SWF);
+ }
+
+ data.square = db_get_b(0, AVS_MODULE, "SetAllwaysMakeSquare", 0);
+ }
+ else
+ {
+ allAcceptXML = Proto_IsAvatarFormatSupported(protocol, PA_FORMAT_XML);
+ allAcceptSWF = Proto_IsAvatarFormatSupported(protocol, PA_FORMAT_SWF);
+
+ data.protocol = protocol;
+ data.square = (Proto_AvatarImageProportion(protocol) & PIP_SQUARE)
+ || db_get_b(0, AVS_MODULE, "SetAllwaysMakeSquare", 0);
+ }
+
+ if (tszPath == NULL) {
+ OPENFILENAME ofn = {0};
+ TCHAR filter[512];
+ TCHAR inipath[1024];
+
+ data.protocol = protocol;
+
+ filter[0] = '\0';
+ FilterGetStrings(filter, SIZEOF(filter), allAcceptXML, allAcceptSWF);
+
+ FoldersGetCustomPathT(hMyAvatarsFolder, inipath, SIZEOF(inipath), _T("."));
+
+ if (IsWinVer2000Plus())
+ ofn.lStructSize = sizeof(ofn);
+ else
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+ ofn.hwndOwner = 0;
+ ofn.lpstrFile = FileName;
+ ofn.lpstrFilter = filter;
+ ofn.nMaxFile = MAX_PATH;
+ ofn.nMaxFileTitle = MAX_PATH;
+ ofn.Flags = OFN_FILEMUSTEXIST | OFN_ENABLETEMPLATE | OFN_EXPLORER | OFN_ENABLESIZING | OFN_ENABLEHOOK;
+ ofn.lpstrInitialDir = inipath;
+ ofn.lpTemplateName = MAKEINTRESOURCE(IDD_SET_OWN_SUBCLASS);
+ ofn.lpfnHook = SetMyAvatarHookProc;
+ ofn.lCustData = (LPARAM) &data;
+
+ *FileName = '\0';
+ ofn.lpstrDefExt = _T("");
+ ofn.hInstance = g_hInst;
+
+ TCHAR title[256];
+ if (protocol == NULL)
+ mir_sntprintf(title, SIZEOF(title), TranslateT("Set My Avatar"));
+ else
+ {
+ TCHAR* prototmp = mir_a2t(protocol);
+ mir_sntprintf(title, SIZEOF(title), TranslateT("Set My Avatar for %s"), prototmp);
+ mir_free(prototmp);
+ }
+ ofn.lpstrTitle = title;
+
+ if (GetOpenFileName(&ofn))
+ szFinalName = FileName;
+ else
+ return 1;
+ }
+ else
+ szFinalName = (TCHAR *)tszPath;
+
+ /*
+ * filename is now set, check it and perform all needed action
+ */
+
+ if (szFinalName[0] == '\0')
+ return InternalRemoveMyAvatar(protocol);
+
+ return InternalSetMyAvatar(protocol, szFinalName, data, allAcceptXML, allAcceptSWF);
+}
+
+static INT_PTR SetMyAvatar( WPARAM wParam, LPARAM lParam )
+{
+ return avSetMyAvatar(( char* )wParam, _A2T(( const char* )lParam ));
+}
+
+static INT_PTR SetMyAvatarW( WPARAM wParam, LPARAM lParam )
+{
+ return avSetMyAvatar(( char* )wParam, ( TCHAR* )lParam );
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+INT_PTR CALLBACK DlgProcAvatarOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+static INT_PTR ContactOptions(WPARAM wParam, LPARAM lParam)
+{
+ if (wParam)
+ CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_AVATAROPTIONS), 0, DlgProcAvatarOptions, (LPARAM)wParam);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+INT_PTR DrawAvatarPicture(WPARAM wParam, LPARAM lParam)
+{
+ AVATARDRAWREQUEST *r = (AVATARDRAWREQUEST *)lParam;
+ AVATARCACHEENTRY *ace = NULL;
+
+ if (fei == NULL || r == NULL || IsBadReadPtr((void *)r, sizeof(AVATARDRAWREQUEST)))
+ return 0;
+
+ if (r->cbSize != sizeof(AVATARDRAWREQUEST))
+ return 0;
+
+ if (r->dwFlags & AVDRQ_PROTOPICT) {
+ if (r->szProto == NULL)
+ return 0;
+
+ for(int i = 0; i < g_ProtoPictures.getCount(); i++) {
+ protoPicCacheEntry& p = g_ProtoPictures[i];
+ if ( !lstrcmpA(p.szProtoname, r->szProto) && lstrlenA(r->szProto) == lstrlenA(p.szProtoname) && p.hbmPic != 0) {
+ ace = (AVATARCACHEENTRY *)&g_ProtoPictures[i];
+ break;
+ }
+ }
+ }
+ else if (r->dwFlags & AVDRQ_OWNPIC) {
+ if (r->szProto == NULL)
+ return 0;
+
+ if (r->szProto[0] == '\0' && db_get_b(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1))
+ return -1;
+
+ ace = (AVATARCACHEENTRY *)GetMyAvatar(0, (LPARAM)r->szProto);
+ }
+ else
+ ace = (AVATARCACHEENTRY *)GetAvatarBitmap((WPARAM)r->hContact, 0);
+
+ if (ace && (!(r->dwFlags & AVDRQ_RESPECTHIDDEN) || !(ace->dwFlags & AVS_HIDEONCLIST))) {
+ ace->t_lastAccess = time(NULL);
+
+ if (ace->bmHeight == 0 || ace->bmWidth == 0 || ace->hbmPic == 0)
+ return 0;
+
+ InternalDrawAvatar(r, ace->hbmPic, ace->bmWidth, ace->bmHeight, ace->dwFlags);
+ return 1;
+ }
+
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+INT_PTR GetMyAvatar(WPARAM wParam, LPARAM lParam)
+{
+ if (wParam || g_shutDown || fei == NULL)
+ return 0;
+
+ char *szProto = (char *)lParam;
+ if (lParam == 0 || IsBadReadPtr(szProto, 4))
+ return 0;
+
+ for(int i = 0; i < g_MyAvatars.getCount(); i++)
+ if (!lstrcmpA(szProto, g_MyAvatars[i].szProtoname) && g_MyAvatars[i].hbmPic != 0)
+ return (INT_PTR)&g_MyAvatars[i];
+
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static void ReloadMyAvatar(LPVOID lpParam)
+{
+ char *szProto = (char *)lpParam;
+
+ mir_sleep(500);
+ for(int i = 0; !g_shutDown && i < g_MyAvatars.getCount(); i++) {
+ char *myAvatarProto = g_MyAvatars[i].szProtoname;
+
+ if (szProto[0] == 0) {
+ // Notify to all possibles
+ if (lstrcmpA(myAvatarProto, szProto)) {
+ if (!ProtoServiceExists( myAvatarProto, PS_SETMYAVATAR))
+ continue;
+ if (!Proto_IsAvatarsEnabled( myAvatarProto ))
+ continue;
+ }
+
+ }
+ else if (lstrcmpA(myAvatarProto, szProto))
+ continue;
+
+ if (g_MyAvatars[i].hbmPic)
+ DeleteObject(g_MyAvatars[i].hbmPic);
+
+ if (CreateAvatarInCache((HANDLE)-1, &g_MyAvatars[i], myAvatarProto) != -1)
+ NotifyEventHooks(hMyAvatarChanged, (WPARAM)myAvatarProto, (LPARAM)&g_MyAvatars[i]);
+ else
+ NotifyEventHooks(hMyAvatarChanged, (WPARAM)myAvatarProto, 0);
+ }
+
+ free(lpParam);
+}
+
+INT_PTR ReportMyAvatarChanged(WPARAM wParam, LPARAM lParam)
+{
+ const char *proto = (const char*)wParam;
+ if (proto == NULL)
+ return -1;
+
+ for(int i = 0; i < g_MyAvatars.getCount(); i++) {
+ if (g_MyAvatars[i].dwFlags & AVS_IGNORENOTIFY)
+ continue;
+
+ if ( !lstrcmpA(g_MyAvatars[i].szProtoname, proto)) {
+ LPVOID lpParam = (void *)malloc(lstrlenA(g_MyAvatars[i].szProtoname) + 2);
+ strcpy((char *)lpParam, g_MyAvatars[i].szProtoname);
+ mir_forkthread(ReloadMyAvatar, lpParam);
+ return 0;
+ }
+ }
+
+ return -2;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void InitServices()
+{
+ CreateServiceFunction(MS_AV_GETAVATARBITMAP, GetAvatarBitmap);
+ CreateServiceFunction(MS_AV_PROTECTAVATAR, ProtectAvatar);
+ CreateServiceFunction(MS_AV_SETAVATAR, SetAvatar);
+ CreateServiceFunction(MS_AV_SETAVATARW, SetAvatarW);
+ CreateServiceFunction(MS_AV_SETMYAVATAR, SetMyAvatar);
+ CreateServiceFunction(MS_AV_SETMYAVATARW, SetMyAvatarW);
+ CreateServiceFunction(MS_AV_CANSETMYAVATAR, CanSetMyAvatar);
+ CreateServiceFunction(MS_AV_CONTACTOPTIONS, ContactOptions);
+ CreateServiceFunction(MS_AV_DRAWAVATAR, DrawAvatarPicture);
+ CreateServiceFunction(MS_AV_GETMYAVATAR, GetMyAvatar);
+ CreateServiceFunction(MS_AV_REPORTMYAVATARCHANGED, ReportMyAvatarChanged);
+
+ CreateServiceFunction(MS_AV_LOADBITMAP32, BmpFilterLoadBitmap32);
+ CreateServiceFunction(MS_AV_SAVEBITMAP, BmpFilterSaveBitmap);
+ CreateServiceFunction(MS_AV_CANSAVEBITMAP, BmpFilterCanSaveBitmap);
+ CreateServiceFunction(MS_AV_RESIZEBITMAP, BmpFilterResizeBitmap);
+}
|