diff options
author | Szymon Tokarz <wsx22@o2.pl> | 2014-01-24 01:02:07 +0000 |
---|---|---|
committer | Szymon Tokarz <wsx22@o2.pl> | 2014-01-24 01:02:07 +0000 |
commit | 43f04f0fcb082fb2c7f69617101e6147c81cf0d3 (patch) | |
tree | 6ef3bfb716719e3fe7a0640dbad9f859619c9e7a /protocols | |
parent | 259bd5726faf89964ff6ee7ec0858d39ff6ac170 (diff) |
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
Diffstat (limited to 'protocols')
-rw-r--r-- | protocols/Tlen/src/tlen_avatar.cpp | 51 | ||||
-rw-r--r-- | protocols/Tlen/src/tlen_presence.cpp | 45 | ||||
-rw-r--r-- | protocols/Tlen/src/tlen_svc.cpp | 44 | ||||
-rw-r--r-- | protocols/Tlen/src/tlen_thread.cpp | 12 | ||||
-rw-r--r-- | protocols/Tlen/src/tlen_xml.cpp | 5 |
5 files changed, 121 insertions, 36 deletions
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, "<ok", 3)){
+ proto->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, "<presence type='%s'><status>%s</status></presence>", presenceType, statusMsg); + if (statusMsg != NULL && *statusMsg) + TlenSend(proto, "<presence type='%s'><status>%s</status></presence>", presenceType, ptrA(TlenTextEncode(statusMsg))); else TlenSend(proto, "<presence type='%s'></presence>", presenceType); } else { - if (statusMsg) - TlenSend(proto, "<presence><show>%s</show><status>%s</status></presence>", showBody, statusMsg); + if (statusMsg != NULL && *statusMsg) + TlenSend(proto, "<presence><show>%s</show><status>%s</status></presence>", showBody, ptrA(TlenTextEncode(statusMsg))); else TlenSend(proto, "<presence><show>%s</show></presence>", 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 <s ... > 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 </s> 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);
}
|