diff options
author | George Hazan <george.hazan@gmail.com> | 2013-10-07 20:33:20 +0000 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2013-10-07 20:33:20 +0000 |
commit | d91b68566522230f4daff25c8c2376fbd99ca640 (patch) | |
tree | 8c773a1a44d32ca06f9f0b2c8c7c7d00e57ab5bd | |
parent | eeb8b2901b9a58285929071cac255d8bb565a2f7 (diff) |
VK: avatars
git-svn-id: http://svn.miranda-ng.org/main/trunk@6401 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
-rw-r--r-- | protocols/VKontakte/src/misc.cpp | 5 | ||||
-rw-r--r-- | protocols/VKontakte/src/stdafx.h | 2 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_avatars.cpp | 99 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_proto.cpp | 3 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_proto.h | 22 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_queue.cpp | 7 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_thread.cpp | 29 | ||||
-rw-r--r-- | protocols/VKontakte/vk_10.vcxproj | 1 | ||||
-rw-r--r-- | protocols/VKontakte/vk_10.vcxproj.filters | 3 | ||||
-rw-r--r-- | protocols/VKontakte/vk_11.vcxproj | 1 | ||||
-rw-r--r-- | protocols/VKontakte/vk_11.vcxproj.filters | 3 |
11 files changed, 154 insertions, 21 deletions
diff --git a/protocols/VKontakte/src/misc.cpp b/protocols/VKontakte/src/misc.cpp index 6470a303ad..edb7739e6e 100644 --- a/protocols/VKontakte/src/misc.cpp +++ b/protocols/VKontakte/src/misc.cpp @@ -59,11 +59,6 @@ HANDLE CVkProto::FindUser(LPCSTR pUserid, bool bCreate) return hNewContact;
}
-int CVkProto::SetServerStatus(int iStatus)
-{
- return 0;
-}
-
LPCSTR findHeader(NETLIBHTTPREQUEST *pReq, LPCSTR szField)
{
for (int i=0; i < pReq->headersCount; i++)
diff --git a/protocols/VKontakte/src/stdafx.h b/protocols/VKontakte/src/stdafx.h index 94469d2b79..5788e340a5 100644 --- a/protocols/VKontakte/src/stdafx.h +++ b/protocols/VKontakte/src/stdafx.h @@ -24,7 +24,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include <Windows.h>
#include <Shlwapi.h>
#include <Wincrypt.h>
+
#include <stdio.h>
+#include <malloc.h>
#include <tchar.h>
#include <time.h>
diff --git a/protocols/VKontakte/src/vk_avatars.cpp b/protocols/VKontakte/src/vk_avatars.cpp new file mode 100644 index 0000000000..6325516509 --- /dev/null +++ b/protocols/VKontakte/src/vk_avatars.cpp @@ -0,0 +1,99 @@ +/*
+Copyright (C) 2013 Miranda NG Project (http://miranda-ng.org)
+
+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 version 2
+of the License.
+
+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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "stdafx.h"
+
+void CVkProto::OnReceiveAvatar(NETLIBHTTPREQUEST *reply, void* hContact)
+{
+ if (reply->resultCode != 200)
+ return;
+
+ PROTO_AVATAR_INFORMATIONT AI = { sizeof(AI) };
+ GetAvatarFileName(hContact, AI.filename, SIZEOF(AI.filename));
+ AI.format = ProtoGetBufferFormat(reply->pData);
+
+ FILE *out = _tfopen(AI.filename, _T("wb"));
+ if (out == NULL) {
+ ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_FAILED, &AI, 0);
+ return;
+ }
+
+ fwrite(reply->pData, 1, reply->dataLength, out);
+ fclose(out);
+ ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, &AI, 0);
+}
+
+INT_PTR CVkProto::SvcGetAvatarInfo(WPARAM wParam, LPARAM lParam)
+{
+ PROTO_AVATAR_INFORMATIONT* AI = (PROTO_AVATAR_INFORMATIONT*)lParam;
+
+ ptrA szUrl( getStringA(AI->hContact, "AvatarUrl"));
+ if (szUrl == NULL)
+ return GAIR_NOAVATAR;
+
+ TCHAR tszFileName[MAX_PATH];
+ GetAvatarFileName(AI->hContact, tszFileName, SIZEOF(tszFileName));
+ _tcsncpy(AI->filename, tszFileName, SIZEOF(AI->filename));
+
+ AI->format = ProtoGetAvatarFormat(AI->filename);
+
+ if (::_taccess(AI->filename, 0) == 0)
+ return GAIR_SUCCESS;
+
+ if ( IsOnline()) {
+ AsyncHttpRequest *pReq = new AsyncHttpRequest();
+ pReq->szUrl = mir_strdup(szUrl);
+ pReq->pUserInfo = (char*)AI->hContact;
+ pReq->m_pFunc = &CVkProto::OnReceiveAvatar;
+ pReq->requestType = REQUEST_GET;
+ PushAsyncHttpRequest(pReq);
+
+ Netlib_Logf(m_hNetlibUser, "Requested to read an avatar from '%s'", szUrl);
+ return GAIR_WAITFOR;
+ }
+
+ Netlib_Logf(m_hNetlibUser, "No avatar");
+ return GAIR_NOAVATAR;
+}
+
+void CVkProto::GetAvatarFileName(HANDLE hContact, TCHAR* pszDest, size_t cbLen)
+{
+ size_t tPathLen;
+ TCHAR *path = (TCHAR*)_alloca(cbLen * sizeof(TCHAR));
+
+ if (m_hAvatarFolder == NULL || FoldersGetCustomPathT(m_hAvatarFolder, path, (int)cbLen, _T("")))
+ tPathLen = mir_sntprintf(pszDest, cbLen, _T("%s\\%S"), (TCHAR*)VARST(_T("%miranda_avatarcache%")), m_szModuleName);
+ else
+ tPathLen = mir_sntprintf(pszDest, cbLen, _T("%s"), path);
+
+ DWORD dwAttributes = GetFileAttributes(pszDest);
+ if (dwAttributes == 0xffffffff || (dwAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
+ CreateDirectoryTreeT(pszDest);
+
+ pszDest[ tPathLen++ ] = '\\';
+
+ const TCHAR* szFileType = _T(".jpg");
+ ptrT szUrl( getTStringA(hContact, "AvatarUrl"));
+ if (szUrl) {
+ TCHAR *p = _tcsrchr(szUrl, '.');
+ if (p != NULL)
+ szFileType = p;
+ }
+
+ ptrA id( getStringA(hContact, "ID"));
+ mir_sntprintf(pszDest + tPathLen, MAX_PATH - tPathLen, _T("%S%s"), id, szFileType);
+}
diff --git a/protocols/VKontakte/src/vk_proto.cpp b/protocols/VKontakte/src/vk_proto.cpp index a93c84d647..0b10090237 100644 --- a/protocols/VKontakte/src/vk_proto.cpp +++ b/protocols/VKontakte/src/vk_proto.cpp @@ -24,6 +24,7 @@ CVkProto::CVkProto(const char *szModuleName, const TCHAR *ptszUserName) : InitQueue();
CreateProtoService(PS_CREATEACCMGRUI, &CVkProto::SvcCreateAccMgrUI);
+ CreateProtoService(PS_GETAVATARINFOT, &CVkProto::SvcGetAvatarInfo);
TCHAR descr[512];
mir_sntprintf(descr, SIZEOF(descr), TranslateT("%s server connection"), m_tszUserName);
@@ -36,7 +37,7 @@ CVkProto::CVkProto(const char *szModuleName, const TCHAR *ptszUserName) : m_hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
mir_sntprintf(descr, SIZEOF(descr), _T("%%miranda_avatarcache%%\\%s"), m_tszUserName);
- hAvatarFolder = FoldersRegisterCustomPathT(LPGEN("Avatars"), m_szModuleName, descr, m_tszUserName);
+ m_hAvatarFolder = FoldersRegisterCustomPathT(LPGEN("Avatars"), m_szModuleName, descr, m_tszUserName);
m_defaultGroup = getTStringA("ProtoGroup");
if (m_defaultGroup == NULL)
diff --git a/protocols/VKontakte/src/vk_proto.h b/protocols/VKontakte/src/vk_proto.h index 71a9eecf1c..1f1db4c38b 100644 --- a/protocols/VKontakte/src/vk_proto.h +++ b/protocols/VKontakte/src/vk_proto.h @@ -16,7 +16,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */
struct CVkProto;
-typedef void (CVkProto::*VK_REQUEST_HANDLER)(NETLIBHTTPREQUEST*);
+typedef void (CVkProto::*VK_REQUEST_HANDLER)(NETLIBHTTPREQUEST*, void*);
struct CVkProto : public PROTO<CVkProto>
{
@@ -78,22 +78,26 @@ struct CVkProto : public PROTO<CVkProto> int __cdecl OnOptionsInit(WPARAM, LPARAM);
int __cdecl OnPreShutdown(WPARAM, LPARAM);
- void OnOAuthAuthorize(NETLIBHTTPREQUEST*);
- void OnReceiveMyInfo(NETLIBHTTPREQUEST*);
+ void OnOAuthAuthorize(NETLIBHTTPREQUEST*, void*);
+ void OnReceiveMyInfo(NETLIBHTTPREQUEST*, void*);
+ void OnReceiveAvatar(NETLIBHTTPREQUEST*, void*);
//==== Services ======================================================================
INT_PTR __cdecl SvcCreateAccMgrUI(WPARAM, LPARAM);
+ INT_PTR __cdecl SvcGetAvatarInfo(WPARAM, LPARAM);
//==== Misc ==========================================================================
TCHAR* GetUserStoredPassword(void);
void RetrieveUserInfo(LPCSTR szUserId);
- void OnReceiveUserInfo(NETLIBHTTPREQUEST*);
+ void OnReceiveUserInfo(NETLIBHTTPREQUEST*, void*);
void RetrieveFriends();
- void OnReceiveFriends(NETLIBHTTPREQUEST*);
+ void OnReceiveFriends(NETLIBHTTPREQUEST*, void*);
+
+ int SetServerStatus(int);
__forceinline bool IsOnline() const { return m_bOnline; }
@@ -107,7 +111,7 @@ private: void Redirect(NETLIBHTTPREQUEST*);
VK_REQUEST_HANDLER m_pFunc;
- time_t m_expireTime;
+ void *pUserInfo;
};
LIST<AsyncHttpRequest> m_arRequestsQueue;
CRITICAL_SECTION m_csRequestsQueue;
@@ -131,15 +135,17 @@ private: void OnLoggedOut();
void ShutdownSession();
+ void GetAvatarFileName(HANDLE hContact, TCHAR* pszDest, size_t cbLen);
+
HANDLE FindUser(LPCSTR userid, bool bCreate = false);
void SetAllContactStatuses(int status);
- int SetServerStatus(int);
bool m_bOnline;
HANDLE m_hNetlibUser, m_hNetlibConn;
- HANDLE hAvatarFolder;
+ HANDLE m_hAvatarFolder;
ptrA m_szAccessToken, m_myUserId;
ptrT m_defaultGroup;
+ UINT_PTR m_timer;
};
diff --git a/protocols/VKontakte/src/vk_queue.cpp b/protocols/VKontakte/src/vk_queue.cpp index 47a146ffa9..e81bc61b0c 100644 --- a/protocols/VKontakte/src/vk_queue.cpp +++ b/protocols/VKontakte/src/vk_queue.cpp @@ -52,7 +52,8 @@ void CVkProto::ExecuteRequest(AsyncHttpRequest *pReq) {
NETLIBHTTPREQUEST *reply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)m_hNetlibUser, (LPARAM)pReq);
if (reply != NULL) {
- (this->*(pReq->m_pFunc))(reply);
+ if (pReq->m_pFunc != NULL)
+ (this->*(pReq->m_pFunc))(reply, pReq->pUserInfo);
CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)reply);
}
delete pReq;
@@ -80,6 +81,7 @@ bool CVkProto::PushAsyncHttpRequest(int iRequestType, LPCSTR szUrl, bool bSecure url.AppendChar('=');
url += ptrA( mir_urlEncode(pParams[i].szValue));
}
+ pReq->nlc = m_hNetlibConn;
}
else {
url = szUrl;
@@ -94,8 +96,7 @@ bool CVkProto::PushAsyncHttpRequest(int iRequestType, LPCSTR szUrl, bool bSecure bool CVkProto::PushAsyncHttpRequest(AsyncHttpRequest *pReq, int iTimeout)
{
- pReq->nlc = m_hNetlibConn;
- pReq->m_expireTime = time(0) + iTimeout;
+ pReq->timeout = iTimeout;
{
mir_cslock lck(m_csRequestsQueue);
m_arRequestsQueue.insert(pReq);
diff --git a/protocols/VKontakte/src/vk_thread.cpp b/protocols/VKontakte/src/vk_thread.cpp index 92b0f4ce76..4ef6be5c89 100644 --- a/protocols/VKontakte/src/vk_thread.cpp +++ b/protocols/VKontakte/src/vk_thread.cpp @@ -36,6 +36,12 @@ void CVkProto::ConnectionFailed(int iReason) ShutdownSession();
}
+static VOID CALLBACK TimerProc(HWND, UINT, UINT_PTR pObject, DWORD)
+{
+ CVkProto *ppro = (CVkProto*)pObject;
+ ppro->SetServerStatus(ppro->m_iStatus);
+}
+
void CVkProto::OnLoggedIn()
{
m_bOnline = true;
@@ -43,6 +49,10 @@ void CVkProto::OnLoggedIn() ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)m_iStatus, m_iDesiredStatus);
m_iStatus = m_iDesiredStatus;
+ // initialize online timer
+ SetServerStatus(m_iStatus);
+ m_timer = SetTimer(NULL, (UINT_PTR)this, 870000, TimerProc);
+
HttpParam param = { "access_token", m_szAccessToken };
PushAsyncHttpRequest(REQUEST_GET, "/method/getUserInfoEx.json", true, &CVkProto::OnReceiveMyInfo, 1, ¶m);
@@ -56,6 +66,17 @@ void CVkProto::OnLoggedOut() ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)m_iStatus, ID_STATUS_OFFLINE);
m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE;
+
+ KillTimer(NULL, m_timer);
+}
+
+int CVkProto::SetServerStatus(int iStatus)
+{
+ if (iStatus != ID_STATUS_OFFLINE && iStatus != ID_STATUS_INVISIBLE) {
+ HttpParam param = { "access_token", m_szAccessToken };
+ PushAsyncHttpRequest(REQUEST_GET, "/method/account.setOnline.json", true, NULL, 1, ¶m);
+ }
+ return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -64,7 +85,7 @@ extern CMStringA loginCookie; static char VK_TOKEN_BEG[] = "access_token=";
-void CVkProto::OnOAuthAuthorize(NETLIBHTTPREQUEST *reply)
+void CVkProto::OnOAuthAuthorize(NETLIBHTTPREQUEST *reply, void*)
{
if (reply->resultCode == 302) { // manual redirect
LPCSTR pszLocation = findHeader(reply, "Location");
@@ -143,7 +164,7 @@ LBL_NoForm: /////////////////////////////////////////////////////////////////////////////////////////
-void CVkProto::OnReceiveMyInfo(NETLIBHTTPREQUEST *reply)
+void CVkProto::OnReceiveMyInfo(NETLIBHTTPREQUEST *reply, void*)
{
Netlib_Logf(m_hNetlibUser, "CVkProto::OnReceiveMyInfo %d", reply->resultCode);
if (reply->resultCode != 200) {
@@ -200,7 +221,7 @@ void CVkProto::RetrieveUserInfo(LPCSTR szUserId) PushAsyncHttpRequest(REQUEST_GET, "/method/getProfiles.json", true, &CVkProto::OnReceiveUserInfo, SIZEOF(params), params);
}
-void CVkProto::OnReceiveUserInfo(NETLIBHTTPREQUEST *reply)
+void CVkProto::OnReceiveUserInfo(NETLIBHTTPREQUEST *reply, void*)
{
Netlib_Logf(m_hNetlibUser, "CVkProto::OnReceiveUserInfo %d", reply->resultCode);
if (reply->resultCode != 200)
@@ -257,7 +278,7 @@ void CVkProto::RetrieveFriends() PushAsyncHttpRequest(REQUEST_GET, "/method/friends.get.json", true, &CVkProto::OnReceiveFriends, SIZEOF(params), params);
}
-void CVkProto::OnReceiveFriends(NETLIBHTTPREQUEST *reply)
+void CVkProto::OnReceiveFriends(NETLIBHTTPREQUEST *reply, void*)
{
Netlib_Logf(m_hNetlibUser, "CVkProto::OnReceiveFriends %d", reply->resultCode);
if (reply->resultCode != 200)
diff --git a/protocols/VKontakte/vk_10.vcxproj b/protocols/VKontakte/vk_10.vcxproj index 6d68d67a49..140b1141f1 100644 --- a/protocols/VKontakte/vk_10.vcxproj +++ b/protocols/VKontakte/vk_10.vcxproj @@ -180,6 +180,7 @@ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
+ <ClCompile Include="src\vk_avatars.cpp" />
<ClCompile Include="src\vk_options.cpp" />
<ClCompile Include="src\vk_proto.cpp" />
<ClCompile Include="src\vk_queue.cpp" />
diff --git a/protocols/VKontakte/vk_10.vcxproj.filters b/protocols/VKontakte/vk_10.vcxproj.filters index 60d0e438ca..e7ac9a423b 100644 --- a/protocols/VKontakte/vk_10.vcxproj.filters +++ b/protocols/VKontakte/vk_10.vcxproj.filters @@ -36,6 +36,9 @@ <ClCompile Include="src\vk_queue.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="src\vk_avatars.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\resource.h">
diff --git a/protocols/VKontakte/vk_11.vcxproj b/protocols/VKontakte/vk_11.vcxproj index 1770c97512..3e30504c57 100644 --- a/protocols/VKontakte/vk_11.vcxproj +++ b/protocols/VKontakte/vk_11.vcxproj @@ -183,6 +183,7 @@ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
+ <ClCompile Include="src\vk_avatars.cpp" />
<ClCompile Include="src\vk_options.cpp" />
<ClCompile Include="src\vk_proto.cpp" />
<ClCompile Include="src\vk_queue.cpp" />
diff --git a/protocols/VKontakte/vk_11.vcxproj.filters b/protocols/VKontakte/vk_11.vcxproj.filters index 408fc79322..6a23ec20c2 100644 --- a/protocols/VKontakte/vk_11.vcxproj.filters +++ b/protocols/VKontakte/vk_11.vcxproj.filters @@ -36,6 +36,9 @@ <ClCompile Include="src\vk_queue.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="src\vk_avatars.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\version.h">
|