From 43f04f0fcb082fb2c7f69617101e6147c81cf0d3 Mon Sep 17 00:00:00 2001 From: Szymon Tokarz Date: Fri, 24 Jan 2014 01:02:07 +0000 Subject: Tlen protocol - Support case when user account is added as contact (show status and status msg on clist) - try to improve fetching avatars and setting own avatar - minor fixes git-svn-id: http://svn.miranda-ng.org/main/trunk@7846 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/Tlen/src/tlen_avatar.cpp | 51 ++++++++++++++++++++++++++++++------ protocols/Tlen/src/tlen_presence.cpp | 45 +++++++++++++++++++++++-------- protocols/Tlen/src/tlen_svc.cpp | 44 ++++++++++++++++++++++--------- protocols/Tlen/src/tlen_thread.cpp | 12 +++++++-- protocols/Tlen/src/tlen_xml.cpp | 5 ++-- 5 files changed, 121 insertions(+), 36 deletions(-) (limited to 'protocols/Tlen') diff --git a/protocols/Tlen/src/tlen_avatar.cpp b/protocols/Tlen/src/tlen_avatar.cpp index f995f7ec2e..fab4adc52b 100644 --- a/protocols/Tlen/src/tlen_avatar.cpp +++ b/protocols/Tlen/src/tlen_avatar.cpp @@ -33,11 +33,21 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. void TlenGetAvatarFileName(TlenProtocol *proto, TLEN_LIST_ITEM *item, TCHAR* ptszDest, int cbLen) { + + int tPathLen = mir_sntprintf(ptszDest, cbLen, TEXT("%s\\%S"), VARST( TEXT("%miranda_avatarcache%")), proto->m_szModuleName); + if (_taccess(ptszDest, 0)) { + int ret = CreateDirectoryTreeT(ptszDest); + if (ret == 0) + proto->debugLog(_T("getAvatarFilename(): Created new directory for avatar cache: %s."), ptszDest); + else { + proto->debugLog(_T("getAvatarFilename(): Can not create directory for avatar cache: %s. errno=%d: %s"), ptszDest, errno, strerror(errno)); + TCHAR buffer[512]; + mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("Cannot create avatars cache directory. ERROR: %d: %s\n%s"), errno, _tcserror(errno), ptszDest); + PUShowMessageT(buffer, SM_WARNING); + } + } + int format = PA_FORMAT_PNG; - int tPathLen = mir_sntprintf(ptszDest, cbLen, TEXT("%s\\Tlen"), VARST( TEXT("%miranda_avatarcache%"))); - DWORD dwAttributes = GetFileAttributes( ptszDest ); - if (dwAttributes == 0xffffffff || ( dwAttributes & FILE_ATTRIBUTE_DIRECTORY ) == 0) - CreateDirectoryTreeT(ptszDest); ptszDest[ tPathLen++ ] = '\\'; if (item != NULL) @@ -92,13 +102,19 @@ static void SetAvatar(TlenProtocol *proto, HANDLE hContact, TLEN_LIST_ITEM *item } TlenGetAvatarFileName(proto, item, filename, sizeof filename ); DeleteFile(filename); - FILE *out = _tfopen( filename, TEXT("wb") ); + FILE *out = _tfopen(filename, TEXT("wb") ); if (out != NULL) { fwrite(data, len, 1, out); fclose(out); db_set_ts(hContact, "ContactPhoto", "File", filename ); db_set_s(hContact, proto->m_szModuleName, "AvatarHash", md5); db_set_dw(hContact, proto->m_szModuleName, "AvatarFormat", format); + } else { + TCHAR buffer[128]; + mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("Can not save new avatar file \"%s\" Error:\n\t%s (Error: %d)"), filename, _tcserror(errno), errno); + PUShowMessageT(buffer, SM_WARNING); + proto->debugLog(buffer); + return; } ProtoBroadcastAck( proto->m_szModuleName, hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL , 0); } @@ -303,7 +319,7 @@ void TlenGetAvatar(TlenProtocol *proto, HANDLE hContact) { typedef struct { TlenProtocol *proto; NETLIBHTTPREQUEST *req; -}TLENREMOVEAVATARTHREADDATA; +} TLENREMOVEAVATARTHREADDATA; static void TlenRemoveAvatarRequestThread(void *ptr) { NETLIBHTTPREQUEST *resp; @@ -327,14 +343,33 @@ typedef struct { NETLIBHTTPREQUEST *req; char *data; int length; -}TLENUPLOADAVATARTHREADDATA; +} TLENUPLOADAVATARTHREADDATA; + +boolean checkUploadAvatarResponse(TlenProtocol *proto, NETLIBHTTPREQUEST *resp){ + if (resp == NULL){ + proto->debugLogA("Error while setting popup on Tlen account (no response)"); + PUShowMessageT(TranslateT("Error while setting popup on Tlen account (no response)"), SM_WARNING); + return false; + } + if (resp->resultCode != 200 || !resp->dataLength || !resp->pData) { + proto->debugLogA("Error while setting popup on Tlen account (invalid response) resultCode=%d, dataLength=%d", resp->resultCode, resp->dataLength); + PUShowMessageT(TranslateT("Error while setting popup on Tlen account (invalid response)"), SM_WARNING); + return false; + } + if (strncmp(resp->pData, "debugLogA("Error while setting popup on Tlen account: %s", resp->pData); + PUShowMessageT(TranslateT("Error while setting popup on Tlen account"), SM_WARNING); + return false; + } + return true; +} static void TlenUploadAvatarRequestThread(void *ptr) { NETLIBHTTPREQUEST *resp; TLENUPLOADAVATARTHREADDATA * data = (TLENUPLOADAVATARTHREADDATA *) ptr; NETLIBHTTPREQUEST *req = data->req; resp = (NETLIBHTTPREQUEST *)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)data->proto->m_hNetlibUser, (LPARAM)req); - if (resp != NULL) { + if (checkUploadAvatarResponse(data->proto, resp)) { CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)resp); SetAvatar(data->proto, NULL, NULL, data->data, data->length, PA_FORMAT_PNG); } diff --git a/protocols/Tlen/src/tlen_presence.cpp b/protocols/Tlen/src/tlen_presence.cpp index 4d20d08f6a..617ec7e2ca 100644 --- a/protocols/Tlen/src/tlen_presence.cpp +++ b/protocols/Tlen/src/tlen_presence.cpp @@ -72,8 +72,10 @@ void TlenProcessPresence(XmlNode *node, TlenProtocol *proto) else p = NULL; TlenListAddResource(proto, LIST_ROSTER, from, status, statusNode?p:NULL); - if (p) { - db_set_s(hContact, "CList", "StatusMsg", p); + if (p != NULL && *p) { + char* statusMsg_utf8 = mir_utf8encode(p); + db_set_utf(hContact, "CList", "StatusMsg", statusMsg_utf8); + mir_free(statusMsg_utf8); mir_free(p); } else { db_unset(hContact, "CList", "StatusMsg"); @@ -121,8 +123,10 @@ void TlenProcessPresence(XmlNode *node, TlenProtocol *proto) p = TlenTextDecode(statusNode->text); TlenListAddResource(proto, LIST_ROSTER, from, status, p); if ((hContact=TlenHContactFromJID(proto, from)) != NULL) { - if (p) { - db_set_s(hContact, "CList", "StatusMsg", p); + if (p != NULL && *p) { + char* statusMsg_utf8 = mir_utf8encode(p); + db_set_utf(hContact, "CList", "StatusMsg", statusMsg_utf8); + mir_free(statusMsg_utf8); } else { db_unset(hContact, "CList", "StatusMsg"); } @@ -170,6 +174,24 @@ void TlenProcessPresence(XmlNode *node, TlenProtocol *proto) } } +/* change status and status msg on own contact on contact list (if present) */ +void setOwnStatusOnCList(TlenProtocol *proto, int status, char *statusMsg) +{ + ptrA ownJid(db_get_sa(NULL, proto->m_szModuleName, "jid")); + HANDLE hContact = TlenHContactFromJID(proto, ownJid); + if(hContact){ + if (db_get_w(hContact, proto->m_szModuleName, "Status", ID_STATUS_OFFLINE) != status) + db_set_w(hContact, proto->m_szModuleName, "Status", (WORD)status); + if (statusMsg != NULL && *statusMsg) { + char* statusMsg_utf8 = mir_utf8encode(statusMsg); + db_set_utf(hContact, "CList", "StatusMsg", statusMsg_utf8); + mir_free(statusMsg_utf8); + } else { + db_unset(hContact, "CList", "StatusMsg"); + } + } +} + static void TlenSendPresenceTo(TlenProtocol *proto, int status, char *to) { char *showBody, *statusMsg, *presenceType; @@ -264,6 +286,7 @@ static void TlenSendPresenceTo(TlenProtocol *proto, int status, char *to) } } } + mir_free(statusMsg); statusMsg = ptr; break; default: @@ -272,19 +295,19 @@ static void TlenSendPresenceTo(TlenProtocol *proto, int status, char *to) } proto->m_iStatus = status; if (presenceType) { - if (statusMsg) - TlenSend(proto, "%s", presenceType, statusMsg); + if (statusMsg != NULL && *statusMsg) + TlenSend(proto, "%s", presenceType, ptrA(TlenTextEncode(statusMsg))); else TlenSend(proto, "", presenceType); } else { - if (statusMsg) - TlenSend(proto, "%s%s", showBody, statusMsg); + if (statusMsg != NULL && *statusMsg) + TlenSend(proto, "%s%s", showBody, ptrA(TlenTextEncode(statusMsg))); else TlenSend(proto, "%s", showBody); } - if (ptr) { - mir_free(ptr); - } + + setOwnStatusOnCList(proto, proto->m_iStatus, statusMsg); + LeaveCriticalSection(&proto->modeMsgMutex); } diff --git a/protocols/Tlen/src/tlen_svc.cpp b/protocols/Tlen/src/tlen_svc.cpp index 4fcd953033..52ab263c8c 100644 --- a/protocols/Tlen/src/tlen_svc.cpp +++ b/protocols/Tlen/src/tlen_svc.cpp @@ -398,14 +398,14 @@ int TlenProtocol::SetStatus(int iNewStatus) } } else if (iNewStatus != m_iStatus) { - if (!isConnected) + if (!isConnected){ TlenConnect(this, iNewStatus); - else { + } else { // change status oldStatus = m_iStatus; // send presence update TlenSendPresence(this, iNewStatus); - ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, m_iStatus); + ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus); } } return 0; @@ -421,9 +421,9 @@ int TlenProtocol::SetAwayMsg(int iStatus, const PROTOCHAR* msg) char **szMsg; char *newModeMsg; - debugLogA("SetAwayMsg called, wParam=%d lParam=%s", iStatus, msg); + newModeMsg = mir_t2a(msg); - newModeMsg = TlenTextEncode(mir_t2a(msg)); //TODO TCHAR + debugLogA("SetAwayMsg called, wParam=%d lParam=%s", iStatus, newModeMsg); EnterCriticalSection(&modeMsgMutex); @@ -567,18 +567,33 @@ static void __cdecl TlenSendMessageFailedThread(void *ptr) static void __cdecl TlenGetAwayMsgThread(void *ptr) { DBVARIANT dbv; - TLEN_LIST_ITEM *item; SENDACKTHREADDATA *data = (SENDACKTHREADDATA *)ptr; + TLEN_LIST_ITEM *item; + + Sleep(50); + if (!db_get(data->hContact, data->proto->m_szModuleName, "jid", &dbv)) { if ((item=TlenListGetItemPtr(data->proto, LIST_ROSTER, dbv.pszVal)) != NULL) { db_free(&dbv); ProtoBroadcastAck(data->proto->m_szModuleName, data->hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, item->statusMessage==NULL ? (LPARAM)NULL : (LPARAM)(TCHAR*)_A2T(item->statusMessage)); - return; + } else { + ptrA ownJid(db_get_sa(NULL, data->proto->m_szModuleName, "jid")); + if (!strcmp(ownJid, dbv.pszVal)){ + DBVARIANT dbv2; + if (!db_get_s(data->hContact, "CList", "StatusMsg", &dbv2, DBVT_TCHAR)){ + data->proto->ProtoBroadcastAck(data->hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, (LPARAM)dbv2.ptszVal); + db_free(&dbv2); + } else { + data->proto->ProtoBroadcastAck(data->hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, (LPARAM)NULL); + } + } + db_free(&dbv); } - else db_free(&dbv); + } else { + data->proto->ProtoBroadcastAck(data->hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, (LPARAM)NULL); } - ProtoBroadcastAck(data->proto->m_szModuleName, data->hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, (LPARAM)(TCHAR*)TEXT("")); + delete data; } @@ -1107,9 +1122,12 @@ static INT_PTR CALLBACK TlenChangeAvatarDlgProc( HWND hwndDlg, UINT msg, WPARAM INT_PTR TlenProtocol::SetMyAvatar(WPARAM wParam, LPARAM lParam) { + if (!isOnline){ + PUShowMessageT(TranslateT("You need to be connected to Tlen account to set avatar."), SM_WARNING); + return 1; + } TCHAR* szFileName = ( TCHAR* )lParam; TCHAR tFileName[ MAX_PATH ]; - if (!isOnline) return 1; if (szFileName != NULL) { int result = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_USER_CHANGEAVATAR), NULL, TlenChangeAvatarDlgProc, (LPARAM) NULL); TlenGetAvatarFileName(this, NULL, tFileName, MAX_PATH); @@ -1127,7 +1145,7 @@ INT_PTR TlenProtocol::SetMyAvatar(WPARAM wParam, LPARAM lParam) TlenUploadAvatar(this, pResult, dwPngSize, (result & 0x10000) != 0); mir_free(pResult); } - } + } else debugLogA("SetMyAvatar open error"); mir_free(tFileName); mir_free(tFileNameA); } @@ -1151,7 +1169,7 @@ INT_PTR TlenProtocol::GetAvatarCaps(WPARAM wParam, LPARAM lParam) case AF_FORMATSUPPORTED: return (lParam == PA_FORMAT_PNG) ? 1 : 0; case AF_ENABLED: - return (tlenOptions.enableAvatars && isOnline) ? 1 : 0; + return tlenOptions.enableAvatars; case AF_DONTNEEDDELAYS: return 1; case AF_MAXFILESIZE: @@ -1214,7 +1232,7 @@ INT_PTR TlenProtocol::AccMgrUI(WPARAM wParam, LPARAM lParam) void TlenInitServicesVTbl(TlenProtocol *proto) { proto->CreateProtoService(PS_GETNAME, &TlenProtocol::GetName); - proto->CreateProtoService(PS_GETAVATARINFO, &TlenProtocol::GetAvatarInfo); + proto->CreateProtoService(PS_GETAVATARINFOT, &TlenProtocol::GetAvatarInfo); proto->CreateProtoService(PS_SEND_NUDGE, &TlenProtocol::SendAlert); proto->CreateProtoService(PS_GETAVATARCAPS, &TlenProtocol::GetAvatarCaps); proto->CreateProtoService(PS_SETMYAVATART, &TlenProtocol::SetMyAvatar); diff --git a/protocols/Tlen/src/tlen_thread.cpp b/protocols/Tlen/src/tlen_thread.cpp index ca7bce7e61..75b65f78ca 100644 --- a/protocols/Tlen/src/tlen_thread.cpp +++ b/protocols/Tlen/src/tlen_thread.cpp @@ -415,6 +415,7 @@ static void TlenSendAuth(TlenProtocol *proto) { mir_free(str); } +/* processing tag sent from server on session opening */ static void TlenProcessStreamOpening(XmlNode *node, ThreadData *info) { char *sid, *s; @@ -470,13 +471,20 @@ static void TlenProcessStreamOpening(XmlNode *node, ThreadData *info) } } +/* processing tag sent from server on session close */ static void TlenProcessStreamClosing(XmlNode *node, ThreadData *info) { Netlib_CloseHandle(info->proto); - if (node->name && !strcmp(node->name, "stream:error") && node->text) - MessageBoxA(NULL, Translate(node->text), Translate("Tlen Connection Error"), MB_OK|MB_ICONERROR|MB_SETFOREGROUND); + if (node->name && !strcmp(node->name, "stream:error") && node->text){ + char buffer[1024]; + mir_snprintf(buffer, SIZEOF(buffer), "%s\n%s", Translate("Tlen Connection Error"), Translate(node->text)); + PUShowMessage(buffer, SM_WARNING); + } else if (!strcmp(node->name, "s")){ + info->proto->debugLogA("Disconnected server message"); + } } +/* processing session tags sent from server */ static void TlenProcessProtocol(XmlNode *node, ThreadData *info) { if (!strcmp(node->name, "message")) diff --git a/protocols/Tlen/src/tlen_xml.cpp b/protocols/Tlen/src/tlen_xml.cpp index 2c86119649..a3e2d892e8 100644 --- a/protocols/Tlen/src/tlen_xml.cpp +++ b/protocols/Tlen/src/tlen_xml.cpp @@ -349,11 +349,12 @@ static BOOL TlenXmlProcessElem(XmlState *xmlState, XmlElemType elemType, char *e case ELEM_CLOSE: if (node->name != NULL && !strcmp(node->name, text)) { node->state = NODE_CLOSE; - if (node->depth == 1 && xmlState->callback1_close != NULL) { + int nodeDepth = node->depth; + if (nodeDepth == 1 && xmlState->callback1_close != NULL) { (*(xmlState->callback1_close))(node, xmlState->userdata1_close); TlenXmlRemoveChild(parentNode, node); } - if (node->depth == 2 && xmlState->callback2_close != NULL) { + if (nodeDepth == 2 && xmlState->callback2_close != NULL) { (*xmlState->callback2_close)(node, xmlState->userdata2_close); TlenXmlRemoveChild(parentNode, node); } -- cgit v1.2.3