summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSzymon Tokarz <wsx22@o2.pl>2014-01-24 01:02:07 +0000
committerSzymon Tokarz <wsx22@o2.pl>2014-01-24 01:02:07 +0000
commit43f04f0fcb082fb2c7f69617101e6147c81cf0d3 (patch)
tree6ef3bfb716719e3fe7a0640dbad9f859619c9e7a
parent259bd5726faf89964ff6ee7ec0858d39ff6ac170 (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
-rw-r--r--protocols/Tlen/src/tlen_avatar.cpp51
-rw-r--r--protocols/Tlen/src/tlen_presence.cpp45
-rw-r--r--protocols/Tlen/src/tlen_svc.cpp44
-rw-r--r--protocols/Tlen/src/tlen_thread.cpp12
-rw-r--r--protocols/Tlen/src/tlen_xml.cpp5
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);
}