From 7df19254e64619d6b077a7c69b456a39d4a810cb Mon Sep 17 00:00:00 2001
From: George Hazan <george.hazan@gmail.com>
Date: Fri, 30 Jan 2015 23:30:48 +0000
Subject: - avatar support functions moved to the separate module; - added
 support for setting our own avatar

git-svn-id: http://svn.miranda-ng.org/main/trunk@11963 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
---
 protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp |  12 +-
 protocols/WhatsApp/src/WhatsAPI++/WAConnection.h   |   2 +-
 protocols/WhatsApp/src/avatars.cpp                 | 123 +++++++++++++++++++++
 protocols/WhatsApp/src/common.h                    |   1 +
 protocols/WhatsApp/src/proto.cpp                   |  63 +----------
 protocols/WhatsApp/src/proto.h                     |   2 +
 protocols/WhatsApp/src/version.h                   |   2 +-
 7 files changed, 138 insertions(+), 67 deletions(-)
 create mode 100644 protocols/WhatsApp/src/avatars.cpp

(limited to 'protocols/WhatsApp/src')

diff --git a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp
index 34b0f2a899..c08066426e 100644
--- a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp
+++ b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp
@@ -835,14 +835,18 @@ void WAConnection::sendQueryLastOnline(const std::string &jid) throw (WAExceptio
 		<< XATTR("id", id) << XATTR("type", "get") << XATTR("to", jid));
 }
 
-void WAConnection::sendSetPicture(const std::string &jid, std::vector<unsigned char>* data) throw (WAException)
+void WAConnection::sendSetPicture(const std::string &jid, std::vector<unsigned char>* data, std::vector<unsigned char>* preview) throw (WAException)
 {
 	std::string id = this->makeId("set_photo_");
 	this->pending_server_requests[id] = new IqResultSetPhotoHandler(this, jid);
 
-	ProtocolTreeNode *listNode = new ProtocolTreeNode("picture", data, NULL) << XATTR("xmlns", "w:profile:picture");
-	out.write(ProtocolTreeNode("iq", listNode)
-		<< XATTR("id", id) << XATTR("type", "set") << XATTR("to", jid));
+	std::vector<ProtocolTreeNode*>* messageChildren = new std::vector<ProtocolTreeNode*>();
+	if (preview)
+		messageChildren->push_back(new ProtocolTreeNode("picture", preview, NULL) << XATTR("type", "preview"));
+	if (data)
+		messageChildren->push_back(new ProtocolTreeNode("picture", data, NULL) << XATTR("type", "image"));
+	out.write(ProtocolTreeNode("iq", NULL, messageChildren)
+		<< XATTR("id", id) << XATTR("type", "set") << XATTR("to", jid) << XATTR("xmlns", "w:profile:picture"));
 }
 
 void WAConnection::sendStatusUpdate(std::string& status) throw (WAException)
diff --git a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h
index 6ed955caa7..6f4fb2b4f2 100644
--- a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h
+++ b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h
@@ -412,7 +412,7 @@ public:
 	void sendSetNewSubject(const std::string& gjid, const std::string& subject) throw (WAException);
 	void sendStatusUpdate(std::string& status) throw (WAException);
 	void sendGetPicture(const std::string& jid, const std::string& type) throw (WAException);
-	void sendSetPicture(const std::string& jid, std::vector<unsigned char>* data) throw (WAException);
+	void sendSetPicture(const std::string& jid, std::vector<unsigned char>* data, std::vector<unsigned char>* preview) throw (WAException);
 	void sendNotificationReceived(const std::string& from, const std::string& id) throw(WAException);
 	void sendDeleteAccount() throw(WAException);
 };
diff --git a/protocols/WhatsApp/src/avatars.cpp b/protocols/WhatsApp/src/avatars.cpp
new file mode 100644
index 0000000000..8bdfe9212b
--- /dev/null
+++ b/protocols/WhatsApp/src/avatars.cpp
@@ -0,0 +1,123 @@
+#include "common.h"
+
+INT_PTR WhatsAppProto::GetAvatarInfo(WPARAM wParam, LPARAM lParam)
+{
+	PROTO_AVATAR_INFORMATIONT* AI = (PROTO_AVATAR_INFORMATIONT*)lParam;
+
+	ptrA id(getStringA(AI->hContact, WHATSAPP_KEY_ID));
+	if (id == NULL)
+		return GAIR_NOAVATAR;
+
+	std::tstring tszFileName = GetAvatarFileName(AI->hContact);
+	_tcsncpy_s(AI->filename, tszFileName.c_str(), _TRUNCATE);
+	AI->format = PA_FORMAT_JPEG;
+
+	ptrA szAvatarId(getStringA(AI->hContact, WHATSAPP_KEY_AVATAR_ID));
+	if (szAvatarId == NULL || (wParam & GAIF_FORCE) != 0)
+	if (AI->hContact != NULL && m_pConnection != NULL) {
+		m_pConnection->sendGetPicture((const char*)id, "image");
+		return GAIR_WAITFOR;
+	}
+
+	debugLogA("No avatar");
+	return GAIR_NOAVATAR;
+}
+
+INT_PTR WhatsAppProto::GetAvatarCaps(WPARAM wParam, LPARAM lParam)
+{
+	switch (wParam) {
+	case AF_PROPORTION:
+		return PIP_SQUARE;
+
+	case AF_FORMATSUPPORTED: // Jabber supports avatars of virtually all formats
+		return PA_FORMAT_JPEG;
+
+	case AF_ENABLED:
+		return TRUE;
+
+	case AF_MAXSIZE:
+		POINT *size = (POINT*)lParam;
+		if (size)
+			size->x = size->y = 640;
+		return 0;
+	}
+	return -1;
+}
+
+std::tstring WhatsAppProto::GetAvatarFileName(MCONTACT hContact)
+{
+	std::tstring result = m_tszAvatarFolder + _T("\\");
+
+	std::string jid;
+	if (hContact != NULL) {
+		ptrA szId(getStringA(hContact, "ID"));
+		if (szId == NULL)
+			return _T("");
+
+		jid = szId;
+	}
+	else jid = m_szJid;
+
+	return result + std::tstring(_A2T(jid.c_str())) + _T(".jpg");
+}
+
+INT_PTR WhatsAppProto::GetMyAvatar(WPARAM wParam, LPARAM lParam)
+{
+	std::tstring tszOwnAvatar(m_tszAvatarFolder + _T("\\myavatar.jpg"));
+	_tcsncpy_s((TCHAR*)wParam, lParam, tszOwnAvatar.c_str(), _TRUNCATE);
+	return 0;
+}
+
+static std::vector<unsigned char>* sttFileToMem(const TCHAR *ptszFileName)
+{
+	HANDLE hFile = CreateFile(ptszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+	if (hFile == INVALID_HANDLE_VALUE)
+		return NULL;
+
+	DWORD upperSize, lowerSize = GetFileSize(hFile, &upperSize);
+	std::vector<unsigned char> *result = new std::vector<unsigned char>(lowerSize);
+	ReadFile(hFile, (void*)result->data(), lowerSize, &upperSize, NULL);
+	CloseHandle(hFile);
+	return result;
+}
+
+INT_PTR WhatsAppProto::SetMyAvatar(WPARAM wParam, LPARAM lParam)
+{
+	if (!isOnline())
+		return 1;
+
+	const TCHAR *ptszFileName = (const TCHAR*)lParam;
+	if (_taccess(ptszFileName, 4) != 0)
+		return errno;
+
+	ResizeBitmap resize = { 0 };
+	if ((resize.hBmp = (HBITMAP)CallService(MS_UTILS_LOADBITMAPT, 0, (LPARAM)ptszFileName)) == NULL)
+		return 2;
+	resize.size = sizeof(resize);
+	resize.fit = RESIZEBITMAP_KEEP_PROPORTIONS;
+	resize.max_height = resize.max_width = 96;
+	
+	HBITMAP hbmpPreview = (HBITMAP)CallService(MS_IMG_RESIZE, (LPARAM)&resize, 0);
+	if (hbmpPreview == NULL)
+		return 3;
+
+	TCHAR tszTempFile[MAX_PATH], tszMyFile[MAX_PATH];
+	mir_sntprintf(tszMyFile, SIZEOF(tszMyFile), _T("%s\\myavatar.jpg"), m_tszAvatarFolder.c_str());
+	mir_sntprintf(tszTempFile, SIZEOF(tszTempFile), _T("%s\\myavatar.preview.jpg"), m_tszAvatarFolder.c_str());
+
+	IMGSRVC_INFO saveInfo = { sizeof(saveInfo), 0 };
+	saveInfo.hbm = hbmpPreview;
+	saveInfo.tszName = tszTempFile;
+	saveInfo.dwMask = IMGI_HBITMAP;
+	saveInfo.fif = FIF_JPEG;
+	CallService(MS_IMG_SAVE, (WPARAM)&saveInfo, IMGL_TCHAR);
+
+	if (hbmpPreview != resize.hBmp)
+		DeleteObject(hbmpPreview);
+	DeleteObject(resize.hBmp);
+
+	CopyFile(ptszFileName, tszMyFile, FALSE);
+
+	m_pConnection->sendSetPicture(m_szJid, sttFileToMem(ptszFileName), sttFileToMem(tszTempFile));
+	return 0;
+}
diff --git a/protocols/WhatsApp/src/common.h b/protocols/WhatsApp/src/common.h
index e6bff0462a..41a9dc1866 100644
--- a/protocols/WhatsApp/src/common.h
+++ b/protocols/WhatsApp/src/common.h
@@ -47,6 +47,7 @@ Copyright 
 #include <m_database.h>
 #include <m_history.h>
 #include <m_idle.h>
+#include <m_imgsrvc.h>
 #include <m_ignore.h>
 #include <m_langpack.h>
 #include <m_message.h>
diff --git a/protocols/WhatsApp/src/proto.cpp b/protocols/WhatsApp/src/proto.cpp
index 0d7285bb60..42ec1990eb 100644
--- a/protocols/WhatsApp/src/proto.cpp
+++ b/protocols/WhatsApp/src/proto.cpp
@@ -23,6 +23,8 @@ WhatsAppProto::WhatsAppProto(const char* proto_name, const TCHAR* username) :
 
 	CreateProtoService(PS_GETAVATARINFOT, &WhatsAppProto::GetAvatarInfo);
 	CreateProtoService(PS_GETAVATARCAPS, &WhatsAppProto::GetAvatarCaps);
+	CreateProtoService(PS_GETMYAVATART, &WhatsAppProto::GetMyAvatar);
+	CreateProtoService(PS_SETMYAVATART, &WhatsAppProto::SetMyAvatar);
 
 	HookProtoEvent(ME_OPT_INITIALISE, &WhatsAppProto::OnOptionsInit);
 	HookProtoEvent(ME_SYSTEM_MODULESLOADED, &WhatsAppProto::OnModulesLoaded);
@@ -354,67 +356,6 @@ void WhatsAppProto::RequestFriendship(MCONTACT hContact)
 	}
 }
 
-INT_PTR WhatsAppProto::GetAvatarInfo(WPARAM wParam, LPARAM lParam)
-{
-	PROTO_AVATAR_INFORMATIONT* AI = (PROTO_AVATAR_INFORMATIONT*)lParam;
-
-	ptrA id(getStringA(AI->hContact, WHATSAPP_KEY_ID));
-	if (id == NULL)
-		return GAIR_NOAVATAR;
-
-	std::tstring tszFileName = GetAvatarFileName(AI->hContact);
-	_tcsncpy_s(AI->filename, tszFileName.c_str(), _TRUNCATE);
-	AI->format = PA_FORMAT_JPEG;
-
-	ptrA szAvatarId(getStringA(AI->hContact, WHATSAPP_KEY_AVATAR_ID));
-	if (szAvatarId == NULL || (wParam & GAIF_FORCE) != 0)
-	if (AI->hContact != NULL && m_pConnection != NULL) {
-		m_pConnection->sendGetPicture((const char*)id, "image");
-		return GAIR_WAITFOR;
-	}
-
-	debugLogA("No avatar");
-	return GAIR_NOAVATAR;
-}
-
-INT_PTR WhatsAppProto::GetAvatarCaps(WPARAM wParam, LPARAM lParam)
-{
-	switch (wParam) {
-	case AF_PROPORTION:
-		return PIP_SQUARE;
-
-	case AF_FORMATSUPPORTED: // Jabber supports avatars of virtually all formats
-		return PA_FORMAT_JPEG;
-
-	case AF_ENABLED:
-		return TRUE;
-
-	case AF_MAXSIZE:
-		POINT *size = (POINT*)lParam;
-		if (size)
-			size->x = size->y = 96;
-		return 0;
-	}
-	return -1;
-}
-
-std::tstring WhatsAppProto::GetAvatarFileName(MCONTACT hContact)
-{
-	std::tstring result = m_tszAvatarFolder + _T("\\");
-
-	std::string jid;
-	if (hContact != NULL) {
-		ptrA szId(getStringA(hContact, "ID"));
-		if (szId == NULL)
-			return _T("");
-
-		jid = szId;
-	}
-	else jid = m_szJid;
-	
-	return result + std::tstring(_A2T(jid.c_str())) + _T(".jpg");
-}
-
 LRESULT CALLBACK PopupDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
 	switch (message) {
diff --git a/protocols/WhatsApp/src/proto.h b/protocols/WhatsApp/src/proto.h
index cff4d14f65..b0c5c8a6bf 100644
--- a/protocols/WhatsApp/src/proto.h
+++ b/protocols/WhatsApp/src/proto.h
@@ -151,6 +151,8 @@ private:
 
 	INT_PTR __cdecl GetAvatarInfo(WPARAM, LPARAM);
 	INT_PTR __cdecl GetAvatarCaps(WPARAM, LPARAM);
+	INT_PTR __cdecl GetMyAvatar(WPARAM, LPARAM);
+	INT_PTR __cdecl SetMyAvatar(WPARAM, LPARAM);
 
 	//////////////////////////////////////////////////////////////////////////////////////
 	// Handles, Locks
diff --git a/protocols/WhatsApp/src/version.h b/protocols/WhatsApp/src/version.h
index f762aa15d7..5d83753125 100644
--- a/protocols/WhatsApp/src/version.h
+++ b/protocols/WhatsApp/src/version.h
@@ -1,7 +1,7 @@
 #define __MAJOR_VERSION          0
 #define __MINOR_VERSION          1
 #define __RELEASE_NUM            2
-#define __BUILD_NUM              5
+#define __BUILD_NUM              6
 
 #include <stdver.h>
 
-- 
cgit v1.2.3