summaryrefslogtreecommitdiff
path: root/protocols
diff options
context:
space:
mode:
Diffstat (limited to 'protocols')
-rw-r--r--protocols/SkypeWeb/src/requests/chatrooms.h13
-rw-r--r--protocols/SkypeWeb/src/requests/contacts.h12
-rw-r--r--protocols/SkypeWeb/src/requests/files.h2
-rw-r--r--protocols/SkypeWeb/src/requests/history.h4
-rw-r--r--protocols/SkypeWeb/src/requests/login.h8
-rw-r--r--protocols/SkypeWeb/src/requests/messages.h6
-rw-r--r--protocols/SkypeWeb/src/requests/oauth.h3
-rw-r--r--protocols/SkypeWeb/src/requests/subscriptions.h2
-rw-r--r--protocols/SkypeWeb/src/skype_chatrooms.cpp240
-rw-r--r--protocols/SkypeWeb/src/skype_contacts.cpp36
-rw-r--r--protocols/SkypeWeb/src/skype_db.cpp17
-rw-r--r--protocols/SkypeWeb/src/skype_db.h6
-rw-r--r--protocols/SkypeWeb/src/skype_history_sync.cpp43
-rw-r--r--protocols/SkypeWeb/src/skype_login.cpp6
-rw-r--r--protocols/SkypeWeb/src/skype_messages.cpp39
-rw-r--r--protocols/SkypeWeb/src/skype_polling.cpp11
-rw-r--r--protocols/SkypeWeb/src/skype_proto.cpp21
-rw-r--r--protocols/SkypeWeb/src/skype_proto.h37
-rw-r--r--protocols/SkypeWeb/src/skype_trouter.cpp4
-rw-r--r--protocols/SkypeWeb/src/skype_utils.cpp143
-rw-r--r--protocols/SkypeWeb/src/skype_utils.h13
-rw-r--r--protocols/SkypeWeb/src/stdafx.h1
-rw-r--r--protocols/SkypeWeb/src/version.h4
23 files changed, 391 insertions, 280 deletions
diff --git a/protocols/SkypeWeb/src/requests/chatrooms.h b/protocols/SkypeWeb/src/requests/chatrooms.h
index aa39995f01..921f6b2519 100644
--- a/protocols/SkypeWeb/src/requests/chatrooms.h
+++ b/protocols/SkypeWeb/src/requests/chatrooms.h
@@ -68,8 +68,7 @@ struct CreateChatroomRequest : public AsyncHttpRequest
for (auto &it : skypenames) {
JSONNode member;
- member << CHAR_PARAM("id", CMStringA(::FORMAT, "8:%s", it).GetBuffer())
- << CHAR_PARAM("role", !mir_strcmpi(it, ppro->m_szSkypename) ? "Admin" : "User");
+ member << CHAR_PARAM("id", it) << CHAR_PARAM("role", !mir_strcmpi(it, ppro->m_szSkypename) ? "Admin" : "User");
members << member;
}
node << members;
@@ -79,10 +78,10 @@ struct CreateChatroomRequest : public AsyncHttpRequest
struct GetChatInfoRequest : public AsyncHttpRequest
{
- GetChatInfoRequest(const char *chatId, const CMStringW topic) :
+ GetChatInfoRequest(const char *chatId, const CMStringW &topic) :
AsyncHttpRequest(REQUEST_GET, HOST_DEFAULT, 0, &CSkypeProto::OnGetChatInfo)
{
- m_szUrl.AppendFormat("/threads/%s%s", strstr(chatId, "19:") == chatId ? "" : "19:", chatId);
+ m_szUrl.AppendFormat("/threads/%s", chatId);
pUserInfo = topic.Detach();
this << CHAR_PARAM("view", "msnp24Equivalent");
@@ -94,7 +93,7 @@ struct InviteUserToChatRequest : public AsyncHttpRequest
InviteUserToChatRequest(const char *chatId, const char *skypename, const char *role) :
AsyncHttpRequest(REQUEST_PUT, HOST_DEFAULT)
{
- m_szUrl.AppendFormat("/threads/19:%s/members/8:%s", chatId, skypename);
+ m_szUrl.AppendFormat("/threads/%s/members/%s", chatId, skypename);
JSONNode node;
node << CHAR_PARAM("role", role);
@@ -107,7 +106,7 @@ struct KickUserRequest : public AsyncHttpRequest
KickUserRequest(const char *chatId, const char *skypename) :
AsyncHttpRequest(REQUEST_DELETE, HOST_DEFAULT)
{
- m_szUrl.AppendFormat("/threads/19:%s/members/8:%s", chatId, skypename);
+ m_szUrl.AppendFormat("/threads/%s/members/%s", chatId, skypename);
}
};
@@ -116,7 +115,7 @@ struct SetChatPropertiesRequest : public AsyncHttpRequest
SetChatPropertiesRequest(const char *chatId, const char *propname, const char *value) :
AsyncHttpRequest(REQUEST_PUT, HOST_DEFAULT)
{
- m_szUrl.AppendFormat("/threads/19:%s/properties?name=%s", chatId, propname);
+ m_szUrl.AppendFormat("/threads/%s/properties?name=%s", chatId, propname);
JSONNode node;
node << CHAR_PARAM(propname, value);
diff --git a/protocols/SkypeWeb/src/requests/contacts.h b/protocols/SkypeWeb/src/requests/contacts.h
index 5791d96517..d66eb1476d 100644
--- a/protocols/SkypeWeb/src/requests/contacts.h
+++ b/protocols/SkypeWeb/src/requests/contacts.h
@@ -48,7 +48,7 @@ struct AddContactRequest : public AsyncHttpRequest
AddHeader("Accept", "application/json");
JSONNode node;
- node << CHAR_PARAM("mri", CMStringA(::FORMAT, "8:%s", who)) << CHAR_PARAM("greeting", greeting);
+ node << CHAR_PARAM("mri", who) << CHAR_PARAM("greeting", greeting);
m_szParam = node.write().c_str();
}
};
@@ -56,7 +56,7 @@ struct AddContactRequest : public AsyncHttpRequest
struct DeleteContactRequest : public AsyncHttpRequest
{
DeleteContactRequest(const char *who) :
- AsyncHttpRequest(REQUEST_DELETE, HOST_CONTACTS, "/contacts/v2/users/SELF/contacts/8:" + mir_urlEncode(who))
+ AsyncHttpRequest(REQUEST_DELETE, HOST_CONTACTS, "/contacts/v2/users/SELF/contacts/" + mir_urlEncode(who))
{
AddHeader("Accept", "application/json");
}
@@ -67,7 +67,7 @@ struct AuthAcceptRequest : public AsyncHttpRequest
AuthAcceptRequest(const char *who) :
AsyncHttpRequest(REQUEST_PUT, HOST_CONTACTS)
{
- m_szUrl.AppendFormat("/contacts/v2/users/SELF/invites/8:%s/accept", who);
+ m_szUrl.AppendFormat("/contacts/v2/users/SELF/invites/%s/accept", who);
AddHeader("Accept", "application/json");
}
@@ -78,7 +78,7 @@ struct AuthDeclineRequest : public AsyncHttpRequest
AuthDeclineRequest(const char *who) :
AsyncHttpRequest(REQUEST_PUT, HOST_CONTACTS)
{
- m_szUrl.AppendFormat("/contacts/v2/users/SELF/invites/8:%s/decline", who);
+ m_szUrl.AppendFormat("/contacts/v2/users/SELF/invites/%s/decline", who);
AddHeader("Accept", "application/json");
}
@@ -89,7 +89,7 @@ struct BlockContactRequest : public AsyncHttpRequest
BlockContactRequest(CSkypeProto *ppro, MCONTACT hContact) :
AsyncHttpRequest(REQUEST_PUT, HOST_CONTACTS, 0, &CSkypeProto::OnBlockContact)
{
- m_szUrl.AppendFormat("/contacts/v2/users/SELF/contacts/blocklist/8:%s", ppro->getId(hContact).c_str());
+ m_szUrl.AppendFormat("/contacts/v2/users/SELF/contacts/blocklist/%s", ppro->getId(hContact).c_str());
m_szParam = "{\"report_abuse\":\"false\",\"ui_version\":\"skype.com\"}";
pUserInfo = (void *)hContact;
@@ -102,7 +102,7 @@ struct UnblockContactRequest : public AsyncHttpRequest
UnblockContactRequest(CSkypeProto *ppro, MCONTACT hContact) :
AsyncHttpRequest(REQUEST_DELETE, HOST_CONTACTS, 0, &CSkypeProto::OnUnblockContact)
{
- m_szUrl.AppendFormat("/contacts/v2/users/SELF/contacts/blocklist/8:%s", ppro->getId(hContact).c_str());
+ m_szUrl.AppendFormat("/contacts/v2/users/SELF/contacts/blocklist/%s", ppro->getId(hContact).c_str());
pUserInfo = (void *)hContact;
AddHeader("Accept", "application/json");
diff --git a/protocols/SkypeWeb/src/requests/files.h b/protocols/SkypeWeb/src/requests/files.h
index 6afd64d7f5..0b46644c7f 100644
--- a/protocols/SkypeWeb/src/requests/files.h
+++ b/protocols/SkypeWeb/src/requests/files.h
@@ -12,7 +12,7 @@ struct ASMObjectCreateRequest : public AsyncHttpRequest
AddHeader("Content-Type", "text/json");
AddHeader("X-Client-Version", "0/0.0.0.0");
- CMStringA szContact(FORMAT, "%d:%s", ppro->isChatRoom(fup->hContact) ? 19 : 8, ppro->getId(fup->hContact).c_str());
+ CMStringA szContact(ppro->getId(fup->hContact));
T2Utf uszFileName(fup->tszFileName);
const char *szFileName = strrchr(uszFileName.get() + 1, '\\');
diff --git a/protocols/SkypeWeb/src/requests/history.h b/protocols/SkypeWeb/src/requests/history.h
index 4c2394ed0c..6be005ae57 100644
--- a/protocols/SkypeWeb/src/requests/history.h
+++ b/protocols/SkypeWeb/src/requests/history.h
@@ -35,10 +35,10 @@ struct SyncHistoryFirstRequest : public AsyncHttpRequest
struct GetHistoryRequest : public AsyncHttpRequest
{
- GetHistoryRequest(const char *username, int pageSize, bool isChat, LONGLONG timestamp) :
+ GetHistoryRequest(const char *username, int pageSize, LONGLONG timestamp) :
AsyncHttpRequest(REQUEST_GET, HOST_DEFAULT, 0, &CSkypeProto::OnGetServerHistory)
{
- m_szUrl.AppendFormat("/users/ME/conversations/%d:%s/messages", isChat ? 19 : 8, mir_urlEncode(username).c_str());
+ m_szUrl.AppendFormat("/users/ME/conversations/%s/messages", mir_urlEncode(username).c_str());
this << INT_PARAM("startTime", timestamp) << INT_PARAM("pageSize", pageSize)
<< CHAR_PARAM("view", "msnp24Equivalent") << CHAR_PARAM("targetType", "Passport|Skype|Lync|Thread");
diff --git a/protocols/SkypeWeb/src/requests/login.h b/protocols/SkypeWeb/src/requests/login.h
index da293572e5..fa3a9148c6 100644
--- a/protocols/SkypeWeb/src/requests/login.h
+++ b/protocols/SkypeWeb/src/requests/login.h
@@ -24,14 +24,18 @@ struct LoginOAuthRequest : public AsyncHttpRequest
AsyncHttpRequest(REQUEST_POST, HOST_API, "/login/skypetoken", &CSkypeProto::OnLoginOAuth)
{
username.MakeLower();
- CMStringA hashStr(::FORMAT, "%s\nskyper\n%s", username.c_str(), password);
+ const char *pszLogin = username;
+ if (int iOffset = username.Find(':'))
+ pszLogin += iOffset + 1;
+
+ CMStringA hashStr(::FORMAT, "%s\nskyper\n%s", pszLogin, password);
BYTE digest[16];
mir_md5_hash((const BYTE*)hashStr.GetString(), hashStr.GetLength(), digest);
this << CHAR_PARAM("scopes", "client")
<< CHAR_PARAM("clientVersion", mir_urlEncode("0/7.4.85.102/259/").c_str())
- << CHAR_PARAM("username", mir_urlEncode(username).c_str())
+ << CHAR_PARAM("username", mir_urlEncode(pszLogin).c_str())
<< CHAR_PARAM("passwordHash", mir_urlEncode(ptrA(mir_base64_encode(digest, sizeof(digest)))).c_str());
}
};
diff --git a/protocols/SkypeWeb/src/requests/messages.h b/protocols/SkypeWeb/src/requests/messages.h
index da5c37662e..e523b184c3 100644
--- a/protocols/SkypeWeb/src/requests/messages.h
+++ b/protocols/SkypeWeb/src/requests/messages.h
@@ -29,7 +29,7 @@ struct SendMessageRequest : public AsyncHttpRequest
SendMessageRequest(const char *username, time_t timestamp, const char *message, const char *MessageType = nullptr) :
AsyncHttpRequest(REQUEST_POST, HOST_DEFAULT, 0, &CSkypeProto::OnMessageSent)
{
- m_szUrl.AppendFormat("/users/ME/conversations/8:%s/messages", username);
+ m_szUrl.AppendFormat("/users/ME/conversations/%s/messages", username);
JSONNode node;
node << INT64_PARAM("clientmessageid", timestamp) << CHAR_PARAM("messagetype", MessageType ? MessageType : "Text")
@@ -43,7 +43,7 @@ struct SendActionRequest : public AsyncHttpRequest
SendActionRequest(const char *username, time_t timestamp, const char *message, CSkypeProto *ppro) :
AsyncHttpRequest(REQUEST_POST, HOST_DEFAULT, 0, &CSkypeProto::OnMessageSent)
{
- m_szUrl.AppendFormat("/users/ME/conversations/8:%s/messages", username);
+ m_szUrl.AppendFormat("/users/ME/conversations/%s/messages", username);
CMStringA content;
content.AppendFormat("%s %s", ppro->m_szSkypename.c_str(), message);
@@ -58,7 +58,7 @@ struct SendActionRequest : public AsyncHttpRequest
struct SendTypingRequest : public AsyncHttpRequest
{
SendTypingRequest(const char *username, int iState) :
- AsyncHttpRequest(REQUEST_POST, HOST_DEFAULT, "/users/ME/conversations/8:" + mir_urlEncode(username) + "/messages")
+ AsyncHttpRequest(REQUEST_POST, HOST_DEFAULT, "/users/ME/conversations/" + mir_urlEncode(username) + "/messages")
{
const char *state = (iState == PROTOTYPE_SELFTYPING_ON) ? "Control/Typing" : "Control/ClearTyping";
diff --git a/protocols/SkypeWeb/src/requests/oauth.h b/protocols/SkypeWeb/src/requests/oauth.h
index 32cee1ec76..ccd9a9d2fc 100644
--- a/protocols/SkypeWeb/src/requests/oauth.h
+++ b/protocols/SkypeWeb/src/requests/oauth.h
@@ -41,6 +41,9 @@ struct OAuthRequest : public AsyncHttpRequest
AddHeader("Cookie", cookies);
+ if (auto *delim = strchr(login, ':'))
+ login = delim + 1;
+
this << CHAR_PARAM("login", login) << CHAR_PARAM("passwd", password) << CHAR_PARAM("PPFT", ppft);
}
diff --git a/protocols/SkypeWeb/src/requests/subscriptions.h b/protocols/SkypeWeb/src/requests/subscriptions.h
index 1f8717e91d..19b8deb355 100644
--- a/protocols/SkypeWeb/src/requests/subscriptions.h
+++ b/protocols/SkypeWeb/src/requests/subscriptions.h
@@ -43,7 +43,7 @@ struct CreateContactsSubscriptionRequest : public AsyncHttpRequest
JSONNode contacts(JSON_ARRAY); contacts.set_name("contacts");
for (auto &it : skypenames) {
JSONNode contact;
- contact << CHAR_PARAM("id", CMStringA(::FORMAT, "8:%s", it));
+ contact << CHAR_PARAM("id", it);
contacts << contact;
}
diff --git a/protocols/SkypeWeb/src/skype_chatrooms.cpp b/protocols/SkypeWeb/src/skype_chatrooms.cpp
index 0a86517a7a..71193390a0 100644
--- a/protocols/SkypeWeb/src/skype_chatrooms.cpp
+++ b/protocols/SkypeWeb/src/skype_chatrooms.cpp
@@ -32,18 +32,12 @@ void CSkypeProto::InitGroupChatModule()
CreateProtoService(PS_LEAVECHAT, &CSkypeProto::OnLeaveChatRoom);
}
-MCONTACT CSkypeProto::FindChatRoom(const char *chatname)
-{
- SESSION_INFO *si = g_chatApi.SM_FindSession(_A2T(chatname), m_szModuleName);
- return si ? si->hContact : 0;
-}
-
-void CSkypeProto::StartChatRoom(const wchar_t *tid, const wchar_t *tname)
+SESSION_INFO* CSkypeProto::StartChatRoom(const wchar_t *tid, const wchar_t *tname)
{
// Create the group chat session
SESSION_INFO *si = Chat_NewSession(GCW_CHATROOM, m_szModuleName, tid, tname);
if (!si)
- return;
+ return nullptr;
// Create a user statuses
Chat_AddGroup(si, TranslateT("Admin"));
@@ -52,6 +46,7 @@ void CSkypeProto::StartChatRoom(const wchar_t *tid, const wchar_t *tname)
// Finish initialization
Chat_Control(m_szModuleName, tid, (getBool("HideChats", 1) ? WINDOW_HIDDEN : SESSION_INITDONE));
Chat_Control(m_szModuleName, tid, SESSION_ONLINE);
+ return si;
}
void CSkypeProto::OnLoadChats(NETLIBHTTPREQUEST *response, AsyncHttpRequest*)
@@ -117,14 +112,15 @@ int CSkypeProto::OnGroupChatEventHook(WPARAM, LPARAM lParam)
if (!gch)
return 0;
- if (mir_strcmp(gch->si->pszModule, m_szModuleName) != 0)
+ auto *si = gch->si;
+ if (mir_strcmp(si->pszModule, m_szModuleName) != 0)
return 0;
- T2Utf chat_id(gch->si->ptszID), user_id(gch->ptszUID);
+ T2Utf user_id(gch->ptszUID);
switch (gch->iType) {
case GC_USER_MESSAGE:
- OnSendChatMessage(chat_id, gch->ptszText);
+ OnSendChatMessage(si->hContact, gch->ptszText);
break;
case GC_USER_PRIVMESS:
@@ -147,18 +143,18 @@ int CSkypeProto::OnGroupChatEventHook(WPARAM, LPARAM lParam)
CSkypeInviteDlg dlg(this);
if (dlg.DoModal())
if (dlg.m_hContact != NULL)
- PushRequest(new InviteUserToChatRequest(chat_id, getId(dlg.m_hContact), "User"));
+ PushRequest(new InviteUserToChatRequest(getId(si->hContact), getId(dlg.m_hContact), "User"));
}
break;
case 20:
- OnLeaveChatRoom(FindChatRoom(chat_id), NULL);
+ OnLeaveChatRoom(si->hContact, NULL);
break;
case 30:
CMStringW newTopic = ChangeTopicForm();
if (!newTopic.IsEmpty())
- PushRequest(new SetChatPropertiesRequest(chat_id, "topic", T2Utf(newTopic.GetBuffer())));
+ PushRequest(new SetChatPropertiesRequest(getId(si->hContact), "topic", T2Utf(newTopic.GetBuffer())));
break;
}
break;
@@ -166,16 +162,16 @@ int CSkypeProto::OnGroupChatEventHook(WPARAM, LPARAM lParam)
case GC_USER_NICKLISTMENU:
switch (gch->dwData) {
case 10:
- PushRequest(new KickUserRequest(chat_id, user_id));
+ PushRequest(new KickUserRequest(getId(si->hContact), user_id));
break;
case 30:
- PushRequest(new InviteUserToChatRequest(chat_id, user_id, "Admin"));
+ PushRequest(new InviteUserToChatRequest(getId(si->hContact), user_id, "Admin"));
break;
case 40:
- PushRequest(new InviteUserToChatRequest(chat_id, user_id, "User"));
+ PushRequest(new InviteUserToChatRequest(getId(si->hContact), user_id, "User"));
break;
case 50:
- ptrA tnick_old(GetChatContactNick(chat_id, user_id, T2Utf(gch->ptszText)));
+ ptrW tnick_old(GetChatContactNick(si->hContact, gch->ptszUID, gch->ptszText));
ENTER_STRING pForm = {};
pForm.type = ESF_COMBO;
@@ -184,32 +180,33 @@ int CSkypeProto::OnGroupChatEventHook(WPARAM, LPARAM lParam)
pForm.szDataPrefix = "renamenick_";
if (EnterString(&pForm)) {
- MCONTACT hChatContact = FindChatRoom(chat_id);
+ MCONTACT hChatContact = si->hContact;
if (hChatContact == NULL)
break; // This probably shouldn't happen, but if chat is NULL for some reason, do nothing
- ptrA tnick_new(mir_utf8encodeW(pForm.ptszResult));
- bool reset = mir_strlen(tnick_new) == 0;
+ ptrW tnick_new(pForm.ptszResult);
+ bool reset = mir_wstrlen(tnick_new) == 0;
if (reset) {
// User fill blank name, which means we reset the custom nick
db_unset(hChatContact, "UsersNicks", user_id);
- tnick_new = GetChatContactNick(chat_id, user_id, _T2A(gch->ptszText));
+ tnick_new = GetChatContactNick(gch->si->hContact, gch->ptszUID, gch->ptszText);
}
- if (!mir_strcmp(tnick_old, tnick_new))
+ if (!mir_wstrcmp(tnick_old, tnick_new))
break; // New nick is same, do nothing
- GCEVENT gce = { m_szModuleName, chat_id, GC_EVENT_NICK };
- gce.dwFlags = GCEF_UTF8 + GCEF_ADDTOLOG;
- gce.pszNick.a = tnick_old;
+ GCEVENT gce = { m_szModuleName, 0, GC_EVENT_NICK };
+ gce.pszID.w = gch->si->ptszID;
+ gce.dwFlags = GCEF_ADDTOLOG;
+ gce.pszNick.w = tnick_old;
gce.bIsMe = IsMe(user_id);
- gce.pszUID.a = user_id;
- gce.pszText.a = tnick_new;
+ gce.pszUID.w = gch->ptszUID;
+ gce.pszText.w= tnick_new;
gce.time = time(0);
Chat_Event(&gce);
if (!reset)
- db_set_utf(hChatContact, "UsersNicks", user_id, tnick_new);
+ db_set_ws(hChatContact, "UsersNicks", user_id, tnick_new);
}
break;
}
@@ -249,91 +246,105 @@ INT_PTR CSkypeProto::OnLeaveChatRoom(WPARAM hContact, LPARAM)
void CSkypeProto::OnChatEvent(const JSONNode &node)
{
- CMStringA szConversationName(UrlToSkypename(node["conversationLink"].as_string().c_str()));
- CMStringA szFromSkypename(UrlToSkypename(node["from"].as_string().c_str()));
+ CMStringW wszChatId(UrlToSkypeId(node["conversationLink"].as_mstring()));
+ CMStringW szFromId(UrlToSkypeId(node["from"].as_mstring()));
- CMStringW szTopic(node["threadtopic"].as_mstring());
+ CMStringW wszTopic(node["threadtopic"].as_mstring());
+ CMStringW wszContent(node["content"].as_mstring());
time_t timestamp = IsoToUnixTime(node["composetime"].as_string());
- std::string strContent = node["content"].as_string();
int nEmoteOffset = node["skypeemoteoffset"].as_int();
- if (FindChatRoom(szConversationName) == NULL)
- PushRequest(new GetChatInfoRequest(szConversationName, szTopic));
+ SESSION_INFO *si = g_chatApi.SM_FindSession(wszChatId, m_szModuleName);
+ if (si == nullptr) {
+ si = StartChatRoom(wszChatId, wszTopic);
+ if (si == nullptr) {
+ debugLogW(L"unable to create chat %s", wszChatId.c_str());
+ return;
+ }
+ PushRequest(new GetChatInfoRequest(T2Utf(wszChatId), wszTopic));
+ }
std::string messageType = node["messagetype"].as_string();
if (messageType == "Text" || messageType == "RichText") {
- std::string szClearedContent(messageType == "RichText" ? RemoveHtml(strContent) : strContent);
- AddMessageToChat(szConversationName, szFromSkypename, szClearedContent.c_str(), nEmoteOffset != NULL, nEmoteOffset, timestamp);
+ CMStringW wszClearedContent(messageType == "RichText" ? RemoveHtml(wszContent) : wszContent);
+ AddMessageToChat(si->hContact, szFromId, wszClearedContent, nEmoteOffset != NULL, nEmoteOffset, timestamp);
}
else if (messageType == "ThreadActivity/AddMember") {
// <addmember><eventtime>1429186229164</eventtime><initiator>8:initiator</initiator><target>8:user</target></addmember>
TiXmlDocument doc;
- if (0 != doc.Parse(strContent.c_str()))
+ if (0 != doc.Parse(T2Utf(wszContent)))
return;
if (auto *pRoot = doc.FirstChildElement("addMember")) {
- CMStringA target = ParseUrl(pRoot->FirstChildElement("target")->Value(), "8:");
- AddChatContact(szConversationName, target, target, "User");
+ CMStringW target = UrlToSkypeId(pRoot->FirstChildElement("target")->Value());
+ AddChatContact(si->hContact, target, L"User");
}
}
else if (messageType == "ThreadActivity/DeleteMember") {
// <deletemember><eventtime>1429186229164</eventtime><initiator>8:initiator</initiator><target>8:user</target></deletemember>
TiXmlDocument doc;
- if (0 != doc.Parse(strContent.c_str()))
+ if (0 != doc.Parse(T2Utf(wszContent)))
return;
if (auto *pRoot = doc.FirstChildElement("deletemember")) {
- CMStringA target = ParseUrl(pRoot->FirstChildElement("target")->Value(), "8:");
- CMStringA initiator = ParseUrl(pRoot->FirstChildElement("initiator")->Value(), "8:");
- RemoveChatContact(szConversationName, target, target, true, initiator);
+ CMStringW target = Utf2T(UrlToSkypeId(pRoot->FirstChildElement("target")->Value()));
+ CMStringW initiator = Utf2T(UrlToSkypeId(pRoot->FirstChildElement("initiator")->Value()));
+ RemoveChatContact(si->hContact, target, true, initiator);
}
}
else if (messageType == "ThreadActivity/TopicUpdate") {
// <topicupdate><eventtime>1429532702130</eventtime><initiator>8:user</initiator><value>test topic</value></topicupdate>
TiXmlDocument doc;
- if (0 != doc.Parse(strContent.c_str()))
+ if (0 != doc.Parse(T2Utf(wszContent)))
return;
auto *pRoot = doc.FirstChildElement("topicupdate");
if (pRoot) {
- CMStringA initiator = ParseUrl(pRoot->FirstChildElement("initiator")->Value(), "8:");
- CMStringA value = pRoot->FirstChildElement("value")->Value();
- RenameChat(szConversationName, value);
- ChangeChatTopic(szConversationName, value, initiator);
+ CMStringW initiator = Utf2T(UrlToSkypeId(pRoot->FirstChildElement("initiator")->Value()));
+ CMStringW value = Utf2T(pRoot->FirstChildElement("value")->Value());
+ Chat_ChangeSessionName(m_szModuleName, wszChatId, value);
+
+ GCEVENT gce = { m_szModuleName, 0, GC_EVENT_TOPIC };
+ gce.pszID.w = wszChatId;
+ gce.pszUID.w = initiator;
+ gce.pszNick.w = initiator;
+ gce.pszText.w = wszTopic;
+ Chat_Event(&gce);
}
}
else if (messageType == "ThreadActivity/RoleUpdate") {
// <roleupdate><eventtime>1429551258363</eventtime><initiator>8:user</initiator><target><id>8:user1</id><role>admin</role></target></roleupdate>
TiXmlDocument doc;
- if (0 != doc.Parse(strContent.c_str()))
+ if (0 != doc.Parse(T2Utf(wszContent)))
return;
auto *pRoot = doc.FirstChildElement("roleupdate");
if (pRoot) {
- CMStringA initiator = ParseUrl(pRoot->FirstChildElement("initiator")->Value(), "8:");
+ CMStringW initiator = Utf2T(UrlToSkypeId(pRoot->FirstChildElement("initiator")->Value()));
auto *pTarget = pRoot->FirstChildElement("target");
if (pTarget) {
- CMStringA id = ParseUrl(pTarget->FirstChildElement("id")->Value(), "8:");
+ CMStringW id = Utf2T(UrlToSkypeId(pTarget->FirstChildElement("id")->Value()));
const char *role = pTarget->FirstChildElement("role")->Value();
- GCEVENT gce = { m_szModuleName, szConversationName, !mir_strcmpi(role, "Admin") ? GC_EVENT_ADDSTATUS : GC_EVENT_REMOVESTATUS };
- gce.dwFlags = GCEF_ADDTOLOG + GCEF_UTF8;
- gce.pszNick.a = id;
- gce.pszUID.a = id;
- gce.pszText.a = initiator;
+ GCEVENT gce = { m_szModuleName, 0, !mir_strcmpi(role, "Admin") ? GC_EVENT_ADDSTATUS : GC_EVENT_REMOVESTATUS };
+ gce.pszID.w = wszChatId;
+ gce.dwFlags = GCEF_ADDTOLOG;
+ gce.pszNick.w = id;
+ gce.pszUID.w = id;
+ gce.pszText.w = initiator;
gce.time = time(0);
- gce.bIsMe = IsMe(id);
- gce.pszStatus.a = TranslateU("Admin");
+ gce.bIsMe = IsMe(T2Utf(id));
+ gce.pszStatus.w = TranslateT("Admin");
Chat_Event(&gce);
}
}
}
}
-void CSkypeProto::OnSendChatMessage(const char *chat_id, const wchar_t *tszMessage)
+void CSkypeProto::OnSendChatMessage(MCONTACT hContact, const wchar_t *tszMessage)
{
if (!IsOnline())
return;
@@ -342,6 +353,7 @@ void CSkypeProto::OnSendChatMessage(const char *chat_id, const wchar_t *tszMessa
rtrimw(buf);
Chat_UnescapeTags(buf);
+ CMStringA chat_id(getId(hContact));
ptrA szMessage(mir_utf8encodeW(buf));
if (strncmp(szMessage, "/me ", 4) == 0)
@@ -350,16 +362,18 @@ void CSkypeProto::OnSendChatMessage(const char *chat_id, const wchar_t *tszMessa
PushRequest(new SendChatMessageRequest(chat_id, time(0), szMessage));
}
-void CSkypeProto::AddMessageToChat(const char *chat_id, const char *from, const char *content, bool isAction, int emoteOffset, time_t timestamp, bool isLoading)
+void CSkypeProto::AddMessageToChat(MCONTACT hContact, const wchar_t *from, const wchar_t *content, bool isAction, int emoteOffset, time_t timestamp, bool isLoading)
{
- ptrA tnick(GetChatContactNick(chat_id, from, from));
+ CMStringW wszChatId(getMStringW(hContact, SKYPE_SETTINGS_ID));
+ ptrW tnick(GetChatContactNick(hContact, from));
- GCEVENT gce = { m_szModuleName, chat_id, isAction ? GC_EVENT_ACTION : GC_EVENT_MESSAGE };
+ GCEVENT gce = { m_szModuleName, 0, isAction ? GC_EVENT_ACTION : GC_EVENT_MESSAGE };
+ gce.pszID.w = wszChatId;
gce.dwFlags = GCEF_UTF8;
gce.bIsMe = IsMe(from);
- gce.pszNick.a = tnick;
+ gce.pszNick.w = tnick;
gce.time = timestamp;
- gce.pszUID.a = from;
+ gce.pszUID.w = from;
CMStringA szText(content);
szText.Replace("%", "%%");
@@ -378,108 +392,98 @@ void CSkypeProto::AddMessageToChat(const char *chat_id, const char *from, const
void CSkypeProto::OnGetChatInfo(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest)
{
- ptrW topic((wchar_t*)pRequest->pUserInfo); // memory must be freed in any case
+ ptrW wszTopic((wchar_t *)pRequest->pUserInfo);
JsonReply reply(response);
if (reply.error())
return;
auto &root = reply.data();
- const JSONNode &members = root["members"];
const JSONNode &properties = root["properties"];
if (!properties["capabilities"] || properties["capabilities"].empty())
return;
- CMStringA chatId(UrlToSkypename(root["messages"].as_string().c_str()));
- StartChatRoom(_A2T(chatId), topic);
- for (auto &member : members) {
- CMStringA username(UrlToSkypename(member["userLink"].as_string().c_str()));
- std::string role = member["role"].as_string();
- AddChatContact(chatId, username, username, role.c_str(), true);
+ CMStringW wszChatId(UrlToSkypeId(root["messages"].as_mstring()));
+ auto *si = g_chatApi.SM_FindSession(wszChatId, m_szModuleName);
+ if (si == nullptr) {
+ si = StartChatRoom(wszChatId, wszTopic);
+ if (si == nullptr)
+ return;
}
- PushRequest(new GetHistoryRequest(chatId, 15, true, 0));
-}
-
-void CSkypeProto::RenameChat(const char *chat_id, const char *name)
-{
- ptrW tchat_id(mir_a2u(chat_id));
- ptrW tname(mir_utf8decodeW(name));
- Chat_ChangeSessionName(m_szModuleName, tchat_id, tname);
-}
-void CSkypeProto::ChangeChatTopic(const char *chat_id, const char *topic, const char *initiator)
-{
- GCEVENT gce = { m_szModuleName, chat_id, GC_EVENT_TOPIC };
- gce.dwFlags = GCEF_UTF8;
- gce.pszUID.a = initiator;
- gce.pszNick.a = initiator;
- gce.pszText.a = topic;
- Chat_Event(&gce);
+ for (auto &member : root["members"]) {
+ CMStringW username(UrlToSkypeId(member["userLink"].as_mstring()));
+ CMStringW role = member["role"].as_mstring();
+ AddChatContact(si->hContact, username, role, true);
+ }
+
+ PushRequest(new GetHistoryRequest(getId(si->hContact), true, 0));
}
-char* CSkypeProto::GetChatContactNick(const char *chat_id, const char *id, const char *name)
+wchar_t* CSkypeProto::GetChatContactNick(MCONTACT hContact, const wchar_t *id, const wchar_t *name)
{
// Check if there is custom nick for this chat contact
- if (chat_id != nullptr) {
- if (char *tname = db_get_utfa(FindChatRoom(chat_id), "UsersNicks", id))
+ if (hContact)
+ if (auto *tname = getWStringA(hContact, "UsersNicks"))
return tname;
- }
// Check if we have this contact in database
if (IsMe(id)) {
// Return my nick
- if (char *tname = getUStringA("Nick"))
+ if (auto *tname = getWStringA("Nick"))
return tname;
}
else {
- MCONTACT hContact = FindContact(id);
+ hContact = FindContact(id);
if (hContact != NULL) {
// Primarily return custom name
- if (char *tname = db_get_utfa(hContact, "CList", "MyHandle"))
+ if (auto *tname = db_get_wsa(hContact, "CList", "MyHandle"))
return tname;
// If not exists, then user nick
- if (char *tname = getUStringA(hContact, "Nick"))
+ if (auto *tname = getWStringA(hContact, "Nick"))
return tname;
}
}
// Return default value as nick - given name or user id
if (name != nullptr)
- return mir_strdup(name);
- return mir_strdup(id);
+ return mir_wstrdup(name);
+ return mir_wstrdup(GetSkypeNick(id));
}
-void CSkypeProto::AddChatContact(const char *chat_id, const char *id, const char *name, const char *role, bool isChange)
+void CSkypeProto::AddChatContact(MCONTACT hContact, const wchar_t *id, const wchar_t *role, bool isChange)
{
- ptrA szNick(GetChatContactNick(chat_id, id, name));
-
- GCEVENT gce = { m_szModuleName, chat_id, GC_EVENT_JOIN };
- gce.dwFlags = GCEF_UTF8 + GCEF_ADDTOLOG;
- gce.pszNick.a = szNick;
- gce.pszUID.a = id;
+ CMStringW chat_id(getMStringW(hContact, SKYPE_SETTINGS_ID));
+ ptrW szNick(GetChatContactNick(hContact, id));
+
+ GCEVENT gce = { m_szModuleName, 0, GC_EVENT_JOIN };
+ gce.pszID.w = chat_id;
+ gce.dwFlags = GCEF_ADDTOLOG;
+ gce.pszNick.w = szNick;
+ gce.pszUID.w = id;
gce.time = !isChange ? time(0) : NULL;
gce.bIsMe = IsMe(id);
- gce.pszStatus.a = TranslateU(role);
+ gce.pszStatus.w = TranslateW(role);
Chat_Event(&gce);
}
-void CSkypeProto::RemoveChatContact(const char *chat_id, const char *id, const char *name, bool isKick, const char *initiator)
+void CSkypeProto::RemoveChatContact(MCONTACT hContact, const wchar_t *id, bool isKick, const wchar_t *initiator)
{
if (IsMe(id))
return;
- ptrA szNick(GetChatContactNick(chat_id, id, name));
- ptrA szInitiator(GetChatContactNick(chat_id, initiator, initiator));
- ptrW tid(mir_a2u(id));
-
- GCEVENT gce = { m_szModuleName, chat_id, isKick ? GC_EVENT_KICK : GC_EVENT_PART };
- gce.dwFlags = GCEF_UTF8;
- gce.pszNick.a = szNick;
- gce.pszUID.a = id;
+ CMStringW chat_id(getMStringW(hContact, SKYPE_SETTINGS_ID));
+ ptrW szNick(GetChatContactNick(hContact, id));
+ ptrW szInitiator(GetChatContactNick(hContact, initiator));
+
+ GCEVENT gce = { m_szModuleName, 0, isKick ? GC_EVENT_KICK : GC_EVENT_PART };
+ gce.pszID.w = chat_id;
+ gce.pszNick.w = szNick;
+ gce.pszUID.w = id;
gce.time = time(0);
if (isKick)
- gce.pszStatus.a = szInitiator;
+ gce.pszStatus.w = szInitiator;
else {
gce.dwFlags += GCEF_ADDTOLOG;
gce.bIsMe = IsMe(id);
diff --git a/protocols/SkypeWeb/src/skype_contacts.cpp b/protocols/SkypeWeb/src/skype_contacts.cpp
index 0e8c4d34a8..f45fd19a66 100644
--- a/protocols/SkypeWeb/src/skype_contacts.cpp
+++ b/protocols/SkypeWeb/src/skype_contacts.cpp
@@ -57,25 +57,35 @@ MCONTACT CSkypeProto::GetContactFromAuthEvent(MEVENT hEvent)
return DbGetAuthEventContact(&dbei);
}
-MCONTACT CSkypeProto::FindContact(const char *skypename)
+MCONTACT CSkypeProto::FindContact(const char *skypeId)
{
for (auto &hContact : AccContacts())
- if (!mir_strcmpi(skypename, getId(hContact)))
+ if (!mir_strcmpi(skypeId, ptrA(getUStringA(hContact, SKYPE_SETTINGS_ID))))
return hContact;
return 0;
}
-MCONTACT CSkypeProto::AddContact(const char *skypename, bool isTemporary)
+MCONTACT CSkypeProto::FindContact(const wchar_t *skypeId)
{
- MCONTACT hContact = FindContact(skypename);
+ for (auto &hContact : AccContacts())
+ if (!mir_wstrcmpi(skypeId, getMStringW(hContact, SKYPE_SETTINGS_ID)))
+ return hContact;
+
+ return 0;
+}
+
+MCONTACT CSkypeProto::AddContact(const char *skypeId, bool isTemporary)
+{
+ MCONTACT hContact = FindContact(skypeId);
if (hContact)
return hContact;
hContact = db_add_contact();
Proto_AddToContact(hContact, m_szModuleName);
- setString(hContact, SKYPE_SETTINGS_ID, skypename);
+ setString(hContact, SKYPE_SETTINGS_ID, skypeId);
+ setUString(hContact, "Nick", GetSkypeNick(skypeId));
if (m_opts.wstrCListGroup) {
Clist_GroupCreate(0, m_opts.wstrCListGroup);
@@ -98,27 +108,27 @@ void CSkypeProto::LoadContactsAuth(NETLIBHTTPREQUEST *response, AsyncHttpRequest
auto &root = reply.data();
for (auto &item : root["invite_list"]) {
- std::string skypename = item["mri"].as_string().erase(0, 2);
+ std::string skypeId = item["mri"].as_string().erase(0, 2);
std::string reason = item["greeting"].as_string();
time_t eventTime = 0;
for (auto &it : item["invites"])
eventTime = IsoToUnixTime(it["time"].as_string());
- MCONTACT hContact = AddContact(skypename.c_str());
+ MCONTACT hContact = AddContact(skypeId.c_str());
time_t lastEventTime = getDword(hContact, "LastAuthRequestTime");
if (lastEventTime && lastEventTime >= eventTime)
continue;
std::string displayName = item["displayname"].as_string();
if (displayName.empty())
- displayName = skypename;
+ displayName = skypeId;
setUString(hContact, "Nick", displayName.c_str());
setDword(hContact, "LastAuthRequestTime", eventTime);
delSetting(hContact, "Auth");
- DB::AUTH_BLOB blob(hContact, displayName.c_str(), nullptr, nullptr, skypename.c_str(), reason.c_str());
+ DB::AUTH_BLOB blob(hContact, displayName.c_str(), nullptr, nullptr, skypeId.c_str(), reason.c_str());
PROTORECVEVENT pre = { 0 };
pre.timestamp = time(0);
@@ -129,7 +139,7 @@ void CSkypeProto::LoadContactsAuth(NETLIBHTTPREQUEST *response, AsyncHttpRequest
}
}
-//[{"skypename":"echo123", "authorized" : true, "blocked" : false, ...},...]
+//[{"skypeId":"echo123", "authorized" : true, "blocked" : false, ...},...]
// other properties is exists but empty
void CSkypeProto::LoadContactList(NETLIBHTTPREQUEST *response, AsyncHttpRequest*)
@@ -144,7 +154,7 @@ void CSkypeProto::LoadContactList(NETLIBHTTPREQUEST *response, AsyncHttpRequest*
for (auto &item : root["contacts"]) {
const JSONNode &name = item["name"];
- std::string skypename = item["id"].as_string();
+ std::string skypeId = item["id"].as_string();
CMStringW display_name = item["display_name"].as_mstring();
CMStringW first_name = name["first"].as_mstring();
CMStringW last_name = name["surname"].as_mstring();
@@ -152,7 +162,7 @@ void CSkypeProto::LoadContactList(NETLIBHTTPREQUEST *response, AsyncHttpRequest*
std::string type = item["type"].as_string();
if (type == "skype" || loadAll) {
- MCONTACT hContact = AddContact(skypename.c_str());
+ MCONTACT hContact = AddContact(skypeId.c_str());
if (hContact) {
if (item["authorized"].as_bool()) {
delSetting(hContact, "Auth");
@@ -183,7 +193,7 @@ void CSkypeProto::LoadContactList(NETLIBHTTPREQUEST *response, AsyncHttpRequest*
setWString(hContact, "LastName", last_name);
if (item["mood"])
- db_set_utf(hContact, "CList", "StatusMsg", RemoveHtml(item["mood"].as_string()).c_str());
+ db_set_ws(hContact, "CList", "StatusMsg", RemoveHtml(item["mood"].as_mstring()));
SetAvatarUrl(hContact, avatar_url);
ReloadAvatarInfo(hContact);
diff --git a/protocols/SkypeWeb/src/skype_db.cpp b/protocols/SkypeWeb/src/skype_db.cpp
index dc102efb8f..d90d255231 100644
--- a/protocols/SkypeWeb/src/skype_db.cpp
+++ b/protocols/SkypeWeb/src/skype_db.cpp
@@ -38,23 +38,24 @@ MEVENT CSkypeProto::GetMessageFromDb(const char *messageId)
return db_event_getById(m_szModuleName, messageId);
}
-MEVENT CSkypeProto::AddDbEvent(WORD type, MCONTACT hContact, DWORD timestamp, DWORD flags, const char *content, const char *uid)
+MEVENT CSkypeProto::AddDbEvent(WORD type, MCONTACT hContact, DWORD timestamp, DWORD flags, const CMStringW &content, const CMStringA &msgId)
{
- if (MEVENT hDbEvent = GetMessageFromDb(uid))
+ if (MEVENT hDbEvent = GetMessageFromDb(msgId))
return hDbEvent;
+ T2Utf szMsg(content);
DBEVENTINFO dbei = {};
dbei.szModule = m_szModuleName;
dbei.timestamp = timestamp;
dbei.eventType = type;
- dbei.cbBlob = (DWORD)mir_strlen(content) + 1;
- dbei.pBlob = (BYTE *)content;
+ dbei.cbBlob = (DWORD)mir_strlen(szMsg) + 1;
+ dbei.pBlob = (BYTE *)szMsg;
dbei.flags = flags;
- dbei.szId = uid;
+ dbei.szId = msgId;
return db_event_add(hContact, &dbei);
}
-void CSkypeProto::EditEvent(MCONTACT hContact, MEVENT hEvent, const char *szContent, time_t edit_time)
+void CSkypeProto::EditEvent(MCONTACT hContact, MEVENT hEvent, const CMStringW &szContent, time_t edit_time)
{
mir_cslock lck(m_AppendMessageLock);
DBEVENTINFO dbei = {};
@@ -72,7 +73,7 @@ void CSkypeProto::EditEvent(MCONTACT hContact, MEVENT hEvent, const char *szCont
return;
JSONNode jEdit;
- jEdit << INT_PARAM("time", (long)edit_time) << CHAR_PARAM("text", szContent);
+ jEdit << INT_PARAM("time", (long)edit_time) << WCHAR_PARAM("text", szContent);
jEdits << jEdit;
}
}
@@ -84,7 +85,7 @@ void CSkypeProto::EditEvent(MCONTACT hContact, MEVENT hEvent, const char *szCont
jMsg << jOriginalMsg;
JSONNode jEdit;
- jEdit << INT_PARAM("time", (long)edit_time) << CHAR_PARAM("text", szContent);
+ jEdit << INT_PARAM("time", (long)edit_time) << WCHAR_PARAM("text", szContent);
JSONNode jEdits(JSON_ARRAY); jEdits.set_name("edits");
jEdits << jEdit;
diff --git a/protocols/SkypeWeb/src/skype_db.h b/protocols/SkypeWeb/src/skype_db.h
index d8dbaa4005..8175940b7b 100644
--- a/protocols/SkypeWeb/src/skype_db.h
+++ b/protocols/SkypeWeb/src/skype_db.h
@@ -31,9 +31,11 @@ enum SKYPE_DB_EVENT_TYPE
SKYPE_DB_EVENT_TYPE_UNKNOWN
};
-#define SKYPE_SETTINGS_ID "Skypename"
+#define SKYPE_SETTINGS_ID "SkypeId"
+#define SKYPE_SETTINGS_LOGIN "Skypename"
+#define SKYPE_SETTINGS_USERTYPE "UserType"
#define SKYPE_SETTINGS_PASSWORD "Password"
-#define SKYPE_SETTINGS_GROUP "DefaultGroup"
+#define SKYPE_SETTINGS_GROUP "DefaultGroup"
struct CSkypeOptions
{
diff --git a/protocols/SkypeWeb/src/skype_history_sync.cpp b/protocols/SkypeWeb/src/skype_history_sync.cpp
index 3d2280b506..d69620dd86 100644
--- a/protocols/SkypeWeb/src/skype_history_sync.cpp
+++ b/protocols/SkypeWeb/src/skype_history_sync.cpp
@@ -42,17 +42,19 @@ void CSkypeProto::OnGetServerHistory(NETLIBHTTPREQUEST *response, AsyncHttpReque
CMStringA szMessageId = message["clientmessageid"] ? message["clientmessageid"].as_string().c_str() : message["skypeeditedid"].as_string().c_str();
+ int userType;
+ CMStringW wszChatId = UrlToSkypeId(message["conversationLink"].as_mstring(), &userType);
+ CMStringW wszContent = message["content"].as_mstring();
+
std::string messageType = message["messagetype"].as_string();
std::string from = message["from"].as_string();
- std::string content = message["content"].as_string();
- std::string conversationLink = message["conversationLink"].as_string();
int emoteOffset = message["skypeemoteoffset"].as_int();
time_t timestamp = IsoToUnixTime(message["composetime"].as_string());
- CMStringA skypename(UrlToSkypename(from.c_str()));
+ CMStringA skypename(UrlToSkypeId(from.c_str()));
bool isEdited = message["skypeeditedid"];
- MCONTACT hContact = FindContact(UrlToSkypename(conversationLink.c_str()));
+ MCONTACT hContact = FindContact(wszChatId);
if (timestamp > getDword(hContact, "LastMsgTime", 0))
setDword(hContact, "LastMsgTime", timestamp);
@@ -65,39 +67,37 @@ void CSkypeProto::OnGetServerHistory(NETLIBHTTPREQUEST *response, AsyncHttpReque
if (IsMe(skypename))
iFlags |= DBEF_SENT;
- if (strstr(conversationLink.c_str(), "/8:")) {
+ if (userType == 8 || userType == 2) {
if (messageType == "Text" || messageType == "RichText") {
- std::string szMessage(messageType == "RichText" ? RemoveHtml(content) : content);
+ CMStringW szMessage(messageType == "RichText" ? RemoveHtml(wszContent) : wszContent);
MEVENT dbevent = GetMessageFromDb(szMessageId);
if (isEdited && dbevent != NULL)
- EditEvent(hContact, dbevent, szMessage.c_str(), timestamp);
+ EditEvent(hContact, dbevent, szMessage, timestamp);
else
- AddDbEvent(emoteOffset == 0 ? EVENTTYPE_MESSAGE : SKYPE_DB_EVENT_TYPE_ACTION, hContact, timestamp, iFlags, &szMessage[emoteOffset], szMessageId);
+ AddDbEvent(emoteOffset == 0 ? EVENTTYPE_MESSAGE : SKYPE_DB_EVENT_TYPE_ACTION, hContact, timestamp, iFlags, szMessage.c_str()+emoteOffset, szMessageId);
}
else if (messageType == "Event/Call") {
- AddDbEvent(SKYPE_DB_EVENT_TYPE_CALL_INFO, hContact, timestamp, iFlags, content.c_str(), szMessageId);
+ AddDbEvent(SKYPE_DB_EVENT_TYPE_CALL_INFO, hContact, timestamp, iFlags, wszContent, szMessageId);
}
else if (messageType == "RichText/Files") {
- AddDbEvent(SKYPE_DB_EVENT_TYPE_FILETRANSFER_INFO, hContact, timestamp, iFlags, content.c_str(), szMessageId);
+ AddDbEvent(SKYPE_DB_EVENT_TYPE_FILETRANSFER_INFO, hContact, timestamp, iFlags, wszContent, szMessageId);
}
else if (messageType == "RichText/UriObject") {
- AddDbEvent(SKYPE_DB_EVENT_TYPE_URIOBJ, hContact, timestamp, iFlags, content.c_str(), szMessageId);
+ AddDbEvent(SKYPE_DB_EVENT_TYPE_URIOBJ, hContact, timestamp, iFlags, wszContent, szMessageId);
}
else if (messageType == "RichText/Contacts") {
- ProcessContactRecv(hContact, timestamp, content.c_str(), szMessageId);
+ ProcessContactRecv(hContact, timestamp, T2Utf(wszContent), szMessageId);
}
else if (messageType == "RichText/Media_Album") {
// do nothing
}
else {
- AddDbEvent(SKYPE_DB_EVENT_TYPE_UNKNOWN, hContact, timestamp, iFlags, content.c_str(), szMessageId);
+ AddDbEvent(SKYPE_DB_EVENT_TYPE_UNKNOWN, hContact, timestamp, iFlags, wszContent, szMessageId);
}
}
- else if (conversationLink.find("/19:") != -1) {
- CMStringA chatname(UrlToSkypename(conversationLink.c_str()));
- std::string szMessage(messageType == "RichText" ? RemoveHtml(content) : content);
+ else if (userType == 19) {
if (messageType == "Text" || messageType == "RichText")
- AddMessageToChat(chatname, skypename, szMessage.c_str(), emoteOffset != NULL, emoteOffset, timestamp, true);
+ AddMessageToChat(hContact, wszChatId, messageType == "RichText" ? RemoveHtml(wszContent) : wszContent, emoteOffset != NULL, emoteOffset, timestamp, true);
}
}
}
@@ -111,7 +111,7 @@ void CSkypeProto::ReadHistoryRest(const char *szUrl)
INT_PTR CSkypeProto::GetContactHistory(WPARAM hContact, LPARAM)
{
- PushRequest(new GetHistoryRequest(getId(hContact), 100, false, 0));
+ PushRequest(new GetHistoryRequest(getId(hContact), 100, 0));
return 0;
}
@@ -136,14 +136,15 @@ void CSkypeProto::OnSyncHistory(NETLIBHTTPREQUEST *response, AsyncHttpRequest*)
if (lastMessage) {
std::string strConversationLink = lastMessage["conversationLink"].as_string();
- if (strConversationLink.find("/8:") != -1) {
- CMStringA szSkypename = UrlToSkypename(strConversationLink.c_str());
+ int iUserType;
+ CMStringA szSkypename = UrlToSkypeId(strConversationLink.c_str(), &iUserType);
+ if (iUserType == 8 || iUserType == 2) {
time_t composeTime(IsoToUnixTime(lastMessage["composetime"].as_string()));
MCONTACT hContact = FindContact(szSkypename);
if (hContact != NULL)
if (getDword(hContact, "LastMsgTime", 0) < composeTime)
- PushRequest(new GetHistoryRequest(szSkypename, 100, false, 0));
+ PushRequest(new GetHistoryRequest(szSkypename, 100, 0));
}
}
}
diff --git a/protocols/SkypeWeb/src/skype_login.cpp b/protocols/SkypeWeb/src/skype_login.cpp
index 7ee951fa70..bb920fb00e 100644
--- a/protocols/SkypeWeb/src/skype_login.cpp
+++ b/protocols/SkypeWeb/src/skype_login.cpp
@@ -24,8 +24,6 @@ void CSkypeProto::Login()
StartQueue();
int tokenExpires = getDword("TokenExpiresIn");
- m_szSkypename = getMStringA(SKYPE_SETTINGS_ID);
-
pass_ptrA szPassword(getStringA(SKYPE_SETTINGS_PASSWORD));
if (m_szSkypename.IsEmpty() || szPassword == NULL) {
ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN);
@@ -233,7 +231,7 @@ void CSkypeProto::OnCapabilitiesSended(NETLIBHTTPREQUEST *response, AsyncHttpReq
LIST<char> skypenames(1);
for (auto &hContact : AccContacts())
if (!isChatRoom(hContact))
- skypenames.insert(getStringA(hContact, SKYPE_SETTINGS_ID));
+ skypenames.insert(getId(hContact).Detach());
PushRequest(new CreateContactsSubscriptionRequest(skypenames));
FreeList(skypenames);
@@ -250,7 +248,7 @@ void CSkypeProto::OnCapabilitiesSended(NETLIBHTTPREQUEST *response, AsyncHttpReq
JSONNode root = JSONNode::parse(response->pData);
if (root)
- setString("SelfEndpointName", UrlToSkypename(root["selfLink"].as_string().c_str()));
+ setString("SelfEndpointName", UrlToSkypeId(root["selfLink"].as_string().c_str()));
PushRequest(new GetProfileRequest(this, 0));
}
diff --git a/protocols/SkypeWeb/src/skype_messages.cpp b/protocols/SkypeWeb/src/skype_messages.cpp
index 222c67e59a..cf06476f55 100644
--- a/protocols/SkypeWeb/src/skype_messages.cpp
+++ b/protocols/SkypeWeb/src/skype_messages.cpp
@@ -32,13 +32,13 @@ int CSkypeProto::OnSendMessage(MCONTACT hContact, int, const char *szMessage)
Utils_GetRandom(&param->hMessage, sizeof(param->hMessage));
param->hMessage &= ~0x80000000;
- ptrA username(getStringA(hContact, "Skypename"));
+ CMStringA id(getId(hContact));
AsyncHttpRequest *pReq;
if (strncmp(szMessage, "/me ", 4) == 0)
- pReq = new SendActionRequest(username, param->hMessage, &szMessage[4], this);
+ pReq = new SendActionRequest(id, param->hMessage, &szMessage[4], this);
else
- pReq = new SendMessageRequest(username, param->hMessage, szMessage);
+ pReq = new SendMessageRequest(id, param->hMessage, szMessage);
pReq->pUserInfo = param;
PushRequest(pReq);
{
@@ -93,17 +93,19 @@ int CSkypeProto::OnPreCreateMessage(WPARAM, LPARAM lParam)
void CSkypeProto::OnPrivateMessageEvent(const JSONNode &node)
{
CMStringA szMessageId = node["clientmessageid"] ? node["clientmessageid"].as_string().c_str() : node["skypeeditedid"].as_string().c_str();
- CMStringA szConversationName(UrlToSkypename(node["conversationLink"].as_string().c_str()));
- CMStringA szFromSkypename(UrlToSkypename(node["from"].as_string().c_str()));
+ CMStringA szConversationName(UrlToSkypeId(node["conversationLink"].as_string().c_str()));
+ CMStringA szFromSkypename(UrlToSkypeId(node["from"].as_string().c_str()));
+
+ CMStringW wszContent = node["content"].as_mstring();
std::string strMessageType = node["messagetype"].as_string();
- std::string strContent = node["content"].as_string();
- std::string szClearedContent(strMessageType == "RichText" ? RemoveHtml(strContent) : strContent);
+ if (strMessageType == "RichText")
+ wszContent = RemoveHtml(wszContent);
bool bEdited = node["skypeeditedid"];
time_t timestamp = time(0); // fuck the server time, we need to place events in the order of our local time
- int nEmoteOffset = atoi(node["skypeemoteoffset"].as_string().c_str());
+ int nEmoteOffset = node["skypeemoteoffset"].as_int();
MCONTACT hContact = AddContact(szConversationName, true);
@@ -125,18 +127,19 @@ void CSkypeProto::OnPrivateMessageEvent(const JSONNode &node)
mir_cslock lck(m_lckOutMessagesList);
m_OutMessages.remove(hMessage);
}
- else AddDbEvent(nEmoteOffset == 0 ? EVENTTYPE_MESSAGE : SKYPE_DB_EVENT_TYPE_ACTION, hContact, timestamp, DBEF_UTF | DBEF_SENT, &szClearedContent[nEmoteOffset], szMessageId);
+ else AddDbEvent(nEmoteOffset == 0 ? EVENTTYPE_MESSAGE : SKYPE_DB_EVENT_TYPE_ACTION, hContact, timestamp, DBEF_UTF | DBEF_SENT, wszContent.c_str()+nEmoteOffset, szMessageId);
}
else {
CallService(MS_PROTO_CONTACTISTYPING, hContact, PROTOTYPE_CONTACTTYPING_OFF);
MEVENT hDbEvent = GetMessageFromDb(szMessageId);
if (bEdited && hDbEvent != NULL)
- EditEvent(hContact, hDbEvent, szClearedContent.c_str(), timestamp);
+ EditEvent(hContact, hDbEvent, wszContent, timestamp);
else {
+ T2Utf szMsg(wszContent);
PROTORECVEVENT recv = {};
recv.timestamp = timestamp;
- recv.szMessage = (char*)szClearedContent.c_str();
+ recv.szMessage = szMsg;
recv.lParam = nEmoteOffset;
recv.szMsgId = szMessageId;
ProtoChainRecvMsg(hContact, &recv);
@@ -144,28 +147,28 @@ void CSkypeProto::OnPrivateMessageEvent(const JSONNode &node)
}
}
else if (strMessageType == "Event/Call") {
- AddDbEvent(SKYPE_DB_EVENT_TYPE_CALL_INFO, hContact, timestamp, DBEF_UTF, strContent.c_str(), szMessageId);
+ AddDbEvent(SKYPE_DB_EVENT_TYPE_CALL_INFO, hContact, timestamp, DBEF_UTF, wszContent, szMessageId);
}
else if (strMessageType == "RichText/Files") {
- AddDbEvent(SKYPE_DB_EVENT_TYPE_FILETRANSFER_INFO, hContact, timestamp, DBEF_UTF, strContent.c_str(), szMessageId);
+ AddDbEvent(SKYPE_DB_EVENT_TYPE_FILETRANSFER_INFO, hContact, timestamp, DBEF_UTF, wszContent , szMessageId);
}
else if (strMessageType == "RichText/UriObject") {
- AddDbEvent(SKYPE_DB_EVENT_TYPE_URIOBJ, hContact, timestamp, DBEF_UTF, strContent.c_str(), szMessageId);
+ AddDbEvent(SKYPE_DB_EVENT_TYPE_URIOBJ, hContact, timestamp, DBEF_UTF, wszContent, szMessageId);
}
else if (strMessageType == "RichText/Contacts") {
- ProcessContactRecv(hContact, timestamp, strContent.c_str(), szMessageId);
+ ProcessContactRecv(hContact, timestamp, T2Utf(wszContent), szMessageId);
}
else if (strMessageType == "RichText/Media_FlikMsg") {
- AddDbEvent(SKYPE_DB_EVENT_TYPE_MOJI, hContact, timestamp, DBEF_UTF, strContent.c_str(), szMessageId);
+ AddDbEvent(SKYPE_DB_EVENT_TYPE_MOJI, hContact, timestamp, DBEF_UTF, wszContent, szMessageId);
}
else if (strMessageType == "RichText/Media_GenericFile") {
- AddDbEvent(SKYPE_DB_EVENT_TYPE_FILE, hContact, timestamp, DBEF_UTF, strContent.c_str(), szMessageId);
+ AddDbEvent(SKYPE_DB_EVENT_TYPE_FILE, hContact, timestamp, DBEF_UTF, wszContent, szMessageId);
}
else if (strMessageType == "RichText/Media_Album") {
// do nothing
}
else {
- AddDbEvent(SKYPE_DB_EVENT_TYPE_UNKNOWN, hContact, timestamp, DBEF_UTF, strContent.c_str(), szMessageId);
+ AddDbEvent(SKYPE_DB_EVENT_TYPE_UNKNOWN, hContact, timestamp, DBEF_UTF, wszContent, szMessageId);
}
}
diff --git a/protocols/SkypeWeb/src/skype_polling.cpp b/protocols/SkypeWeb/src/skype_polling.cpp
index c4d0f695c4..7bb3117574 100644
--- a/protocols/SkypeWeb/src/skype_polling.cpp
+++ b/protocols/SkypeWeb/src/skype_polling.cpp
@@ -102,7 +102,7 @@ void CSkypeProto::ProcessEndpointPresence(const JSONNode &node)
{
debugLogA(__FUNCTION__);
std::string selfLink = node["selfLink"].as_string();
- CMStringA skypename(UrlToSkypename(selfLink.c_str()));
+ CMStringA skypename(UrlToSkypeId(selfLink.c_str()));
MCONTACT hContact = FindContact(skypename);
if (hContact == NULL)
@@ -169,7 +169,7 @@ void CSkypeProto::ProcessUserPresence(const JSONNode &node)
std::string selfLink = node["selfLink"].as_string();
std::string status = node["status"].as_string();
- CMStringA skypename = UrlToSkypename(selfLink.c_str());
+ CMStringA skypename = UrlToSkypeId(selfLink.c_str());
if (!skypename.IsEmpty()) {
if (IsMe(skypename)) {
@@ -195,9 +195,12 @@ void CSkypeProto::ProcessNewMessage(const JSONNode &node)
std::string conversationLink = node["conversationLink"].as_string();
- if (conversationLink.find("/8:") != std::string::npos)
+ int iUserType;
+ UrlToSkypeId(conversationLink.c_str(), &iUserType);
+
+ if (iUserType == 2 || iUserType == 8)
OnPrivateMessageEvent(node);
- else if (conversationLink.find("/19:") != std::string::npos)
+ else if (iUserType == 19)
OnChatEvent(node);
}
diff --git a/protocols/SkypeWeb/src/skype_proto.cpp b/protocols/SkypeWeb/src/skype_proto.cpp
index 9be4467492..34c9adcf27 100644
--- a/protocols/SkypeWeb/src/skype_proto.cpp
+++ b/protocols/SkypeWeb/src/skype_proto.cpp
@@ -55,6 +55,27 @@ CSkypeProto::CSkypeProto(const char* protoName, const wchar_t* userName) :
m_hPollingThread = ForkThreadEx(&CSkypeProto::PollingThread, NULL, NULL);
+ m_szSkypename = getMStringA(SKYPE_SETTINGS_ID);
+ if (m_szSkypename.IsEmpty()) {
+ m_szSkypename = getMStringA(SKYPE_SETTINGS_LOGIN);
+ if (!m_szSkypename.IsEmpty()) { // old settings format, need to update all settings
+ m_szSkypename.Insert(0, "8:");
+ setString(SKYPE_SETTINGS_ID, m_szSkypename);
+
+ for (auto &hContact : AccContacts()) {
+ CMStringA id(ptrA(getUStringA(hContact, "Skypename")));
+ if (!id.IsEmpty())
+ setString(hContact, SKYPE_SETTINGS_ID, (isChatRoom(hContact)) ? "19:"+id : "8:"+id);
+
+ ptrW wszNick(getWStringA(hContact, "Nick"));
+ if (wszNick == nullptr)
+ setUString(hContact, "Nick", id);
+
+ delSetting(hContact, "Skypename");
+ }
+ }
+ }
+
InitGroupChatModule();
}
diff --git a/protocols/SkypeWeb/src/skype_proto.h b/protocols/SkypeWeb/src/skype_proto.h
index 3facd417fc..8264f4dc50 100644
--- a/protocols/SkypeWeb/src/skype_proto.h
+++ b/protocols/SkypeWeb/src/skype_proto.h
@@ -241,7 +241,9 @@ private:
void ReloadAvatarInfo(MCONTACT hContact);
void GetAvatarFileName(MCONTACT hContact, wchar_t* pszDest, size_t cbLen);
- MCONTACT FindContact(const char *skypename);
+ MCONTACT FindContact(const char *skypeId);
+ MCONTACT FindContact(const wchar_t *skypeId);
+
MCONTACT AddContact(const char *skypename, bool isTemporary = false);
MCONTACT GetContactFromAuthEvent(MEVENT hEvent);
@@ -250,8 +252,8 @@ private:
std::map<ULONGLONG, HANDLE> m_mpOutMessagesIds;
MEVENT GetMessageFromDb(const char *messageId);
- MEVENT AddDbEvent(WORD type, MCONTACT hContact, DWORD timestamp, DWORD flags, const char *content, const char *uid);
- void EditEvent(MCONTACT hContact, MEVENT hEvent, const char *szContent, time_t edit_time);
+ MEVENT AddDbEvent(WORD type, MCONTACT hContact, DWORD timestamp, DWORD flags, const CMStringW &content, const CMStringA &msgId);
+ void EditEvent(MCONTACT hContact, MEVENT hEvent, const CMStringW &content, time_t edit_time);
int OnSendMessage(MCONTACT hContact, int flags, const char *message);
int __cdecl OnPreCreateMessage(WPARAM, LPARAM lParam);
@@ -265,24 +267,19 @@ private:
// chats
void InitGroupChatModule();
- MCONTACT FindChatRoom(const char *chatname);
-
int __cdecl OnGroupChatEventHook(WPARAM, LPARAM lParam);
int __cdecl OnGroupChatMenuHook(WPARAM, LPARAM lParam);
INT_PTR __cdecl OnJoinChatRoom(WPARAM hContact, LPARAM);
INT_PTR __cdecl OnLeaveChatRoom(WPARAM hContact, LPARAM);
- void StartChatRoom(const wchar_t *tid, const wchar_t *tname);
+ SESSION_INFO* StartChatRoom(const wchar_t *tid, const wchar_t *tname);
void OnChatEvent(const JSONNode &node);
- void OnSendChatMessage(const char *chat_id, const wchar_t *tszMessage);
- void AddMessageToChat(const char *chat_id, const char *from, const char *content, bool isAction, int emoteOffset, time_t timestamp, bool isLoading = false);
- void AddChatContact(const char *chat_id, const char *id, const char *name, const char *role, bool isChange = false);
- void RemoveChatContact(const char *chat_id, const char *id, const char *name, bool isKick = false, const char *initiator = "");
- char* GetChatContactNick(const char *chat_id, const char *id, const char *name);
-
- void RenameChat(const char *chat_id, const char *name);
- void ChangeChatTopic(const char * chat_id, const char *topic, const char *initiator);
+ void OnSendChatMessage(MCONTACT hContact, const wchar_t *tszMessage);
+ void AddMessageToChat(MCONTACT hContact, const wchar_t *from, const wchar_t *content, bool isAction, int emoteOffset, time_t timestamp, bool isLoading = false);
+ void AddChatContact(MCONTACT hContact, const wchar_t *id, const wchar_t *role, bool isChange = false);
+ void RemoveChatContact(MCONTACT hContact, const wchar_t *id, bool isKick = false, const wchar_t *initiator = L"");
+ wchar_t* GetChatContactNick(MCONTACT hContact, const wchar_t *id, const wchar_t *name = nullptr);
void SetChatStatus(MCONTACT hContact, int iStatus);
@@ -312,12 +309,15 @@ private:
{ return (m_iStatus > ID_STATUS_OFFLINE);
}
+ __forceinline bool IsMe(const wchar_t *str)
+ { return (!mir_wstrcmpi(str, Utf2T(m_szMyname)) || !mir_wstrcmp(str, getMStringW("SelfEndpointName")));
+ }
+
__forceinline bool IsMe(const char *str)
- { return (!mir_strcmpi(str, m_szMyname) || !mir_strcmp(str, ptrA(getStringA("SelfEndpointName"))));
+ { return (!mir_strcmpi(str, m_szMyname) || !mir_strcmp(str, ptrA(getUStringA("SelfEndpointName"))));
}
static time_t IsoToUnixTime(const std::string &stamp);
- static CMStringA GetStringChunk(const char *haystack, const char *start, const char *end);
static int SkypeToMirandaStatus(const char *status);
static const char *MirandaToSkypeStatus(int status);
@@ -328,11 +328,6 @@ private:
static LRESULT CALLBACK PopupDlgProcCall(HWND hPopup, UINT uMsg, WPARAM wParam, LPARAM lParam);
- static CMStringA ParseUrl(const char *url, const char *token);
-
- static CMStringA UrlToSkypename(const char *url);
- static CMStringA GetServerFromUrl(const char *url);
-
void ProcessTimer();
CMStringW RunConfirmationCode();
diff --git a/protocols/SkypeWeb/src/skype_trouter.cpp b/protocols/SkypeWeb/src/skype_trouter.cpp
index 9d9a9a9cb0..163c7776df 100644
--- a/protocols/SkypeWeb/src/skype_trouter.cpp
+++ b/protocols/SkypeWeb/src/skype_trouter.cpp
@@ -35,7 +35,7 @@ void CSkypeProto::OnReceiveStatus(NETLIBHTTPREQUEST *response, AsyncHttpRequest*
auto &root = reply.data();
for (auto &it : root["Responses"]) {
std::string id = it["Contact"].as_string();
- id.erase(0, 2);
+
MCONTACT hContact = AddContact(id.c_str());
if (hContact) {
int status = SkypeToMirandaStatus(it["Payload"]["status"].as_string().c_str());
@@ -59,7 +59,7 @@ void CSkypeProto::RefreshStatuses(void)
nRecs = 0;
}
- pReq << CHAR_PARAM("cMri", "8:" + id);
+ pReq << CHAR_PARAM("cMri", id);
nRecs++;
if (nRecs >= 10) {
diff --git a/protocols/SkypeWeb/src/skype_utils.cpp b/protocols/SkypeWeb/src/skype_utils.cpp
index 2c088b2d37..305bf1c102 100644
--- a/protocols/SkypeWeb/src/skype_utils.cpp
+++ b/protocols/SkypeWeb/src/skype_utils.cpp
@@ -342,43 +342,43 @@ const HtmlEntity htmlEntities[] =
{ "zwnj", "\xE2\x80\x8C" }
};
-std::string RemoveHtml(const std::string &data)
+CMStringW RemoveHtml(const CMStringW &data)
{
- std::string new_string;
+ CMStringW new_string;
- for (std::string::size_type i = 0; i < data.length(); i++) {
- if (data.at(i) == '<') {
- i = data.find('>', i);
- if (i == std::string::npos)
+ for (int i = 0; i < data.GetLength(); i++) {
+ wchar_t c = data[i];
+ if (c == '<') {
+ i = data.Find('>', i);
+ if (i == -1)
break;
continue;
}
- if (data.at(i) == '&') {
- std::string::size_type begin = i;
- i = data.find(';', i);
- if (i == std::string::npos) {
+ // special character
+ if (c == '&') {
+ int begin = i;
+ i = data.Find(';', i);
+ if (i == -1)
i = begin;
- }
else {
- std::string entity = data.substr(begin + 1, i - begin - 1);
+ CMStringW entity = data.Mid(begin + 1, i - begin - 1);
bool found = false;
- if (entity.length() > 1 && entity.at(0) == '#') {
+ if (entity.GetLength() > 1 && entity[0] == '#') {
// Numeric replacement
bool hex = false;
- if (entity.at(1) == 'x') {
+ if (entity[1] == 'x') {
hex = true;
- entity = entity.substr(2);
- }
- else {
- entity = entity.substr(1);
+ entity.Delete(0, 2);
}
- if (!entity.empty()) {
+ else entity.Delete(0, 1);
+
+ if (!entity.IsEmpty()) {
found = true;
errno = 0;
- unsigned long value = strtoul(entity.c_str(), nullptr, hex ? 16 : 10);
+ unsigned long value = wcstoul(entity, nullptr, hex ? 16 : 10);
if (errno != 0) { // error with conversion in strtoul, ignore the result
found = false;
}
@@ -404,8 +404,9 @@ std::string RemoveHtml(const std::string &data)
}
else {
// Keyword replacement
+ CMStringA tmp = entity;
for (auto &it : htmlEntities) {
- if (!mir_strcmpi(entity.c_str(), it.entity)) {
+ if (!mir_strcmpi(tmp, it.entity)) {
new_string += it.symbol;
found = true;
break;
@@ -420,7 +421,7 @@ std::string RemoveHtml(const std::string &data)
}
}
- new_string += data.at(i);
+ new_string.AppendChar(c);
}
return new_string;
@@ -453,7 +454,7 @@ int CSkypeProto::SkypeToMirandaStatus(const char *status)
else if (!mir_strcmpi(status, "Away"))
return ID_STATUS_AWAY;
else if (!mir_strcmpi(status, "Idle"))
- return /*ID_STATUS_IDLE*/ID_STATUS_AWAY;
+ return ID_STATUS_AWAY;
else if (!mir_strcmpi(status, "Busy"))
return ID_STATUS_DND;
else
@@ -465,52 +466,106 @@ bool CSkypeProto::IsFileExists(std::wstring path)
return _waccess(path.c_str(), 0) == 0;
}
+const char* GetSkypeNick(const char *szSkypeId)
+{
+ if (auto *p = strchr(szSkypeId, ':'))
+ return p + 1;
+ return szSkypeId;
+}
+
+const wchar_t* GetSkypeNick(const wchar_t *szSkypeId)
+{
+ if (auto *p = wcsrchr(szSkypeId, ':'))
+ return p + 1;
+ return szSkypeId;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
// url parsing
-CMStringA CSkypeProto::ParseUrl(const char *url, const char *token)
+CMStringA ParseUrl(const char *url, const char *token)
{
if (url == nullptr)
return CMStringA();
- const char *start = strstr(url, token);
+ auto *start = strstr(url, token);
if (start == nullptr)
return CMStringA();
- start = start + mir_strlen(token);
- const char *end = strchr(start, '/');
+ auto *end = strchr(++start, '/');
if (end == nullptr)
return CMStringA(start);
return CMStringA(start, end - start);
}
-CMStringA CSkypeProto::GetStringChunk(const char *haystack, const char *start, const char *end)
+CMStringW ParseUrl(const wchar_t *url, const wchar_t *token)
{
- const char *sstart = strstr(haystack, start);
- if (sstart == nullptr)
- return CMStringA();
+ if (url == nullptr)
+ return CMStringW();
- sstart = sstart + mir_strlen(start);
- const char *send = strstr(sstart, end);
- if (send == nullptr)
- return CMStringA(sstart);
- return CMStringA(sstart, send - sstart);
+ auto *start = wcsstr(url, token);
+ if (start == nullptr)
+ return CMStringW();
+
+ auto *end = wcschr(++start, '/');
+ if (end == nullptr)
+ return CMStringW(start);
+ return CMStringW(start, end - start);
}
-CMStringA CSkypeProto::UrlToSkypename(const char *url)
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static int possibleTypes[] = { 1, 2, 8, 19 };
+
+CMStringA UrlToSkypeId(const char *url, int *pUserType)
{
+ int userType = -1;
CMStringA szResult;
- if (strstr(url, "/1:"))
- szResult = ParseUrl(url, "/1:");
- else if (strstr(url, "/8:"))
- szResult = ParseUrl(url, "/8:");
- else if (strstr(url, "/19:"))
- szResult = ParseUrl(url, "/19:");
+ if (url != nullptr) {
+ for (auto &it : possibleTypes) {
+ char tmp[10];
+ sprintf_s(tmp, "/%d:", it);
+ if (strstr(url, tmp)) {
+ userType = it;
+ szResult = ParseUrl(url, tmp);
+ break;
+ }
+ }
+ }
+
+ if (pUserType)
+ *pUserType = userType;
+
+ return szResult;
+}
+
+CMStringW UrlToSkypeId(const wchar_t *url, int *pUserType)
+{
+ int userType = -1;
+ CMStringW szResult;
+
+ if (url != nullptr) {
+ for (auto &it : possibleTypes) {
+ wchar_t tmp[10];
+ swprintf_s(tmp, L"/%d:", it);
+ if (wcsstr(url, tmp)) {
+ userType = it;
+ szResult = ParseUrl(url, tmp);
+ break;
+ }
+ }
+ }
+
+ if (pUserType)
+ *pUserType = userType;
return szResult;
}
-CMStringA CSkypeProto::GetServerFromUrl(const char *url)
+/////////////////////////////////////////////////////////////////////////////////////////
+
+CMStringA GetServerFromUrl(const char *url)
{
return ParseUrl(url, "://");
}
diff --git a/protocols/SkypeWeb/src/skype_utils.h b/protocols/SkypeWeb/src/skype_utils.h
index a79b17b1e5..77278f9346 100644
--- a/protocols/SkypeWeb/src/skype_utils.h
+++ b/protocols/SkypeWeb/src/skype_utils.h
@@ -18,7 +18,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef _UTILS_H_
#define _UTILS_H_
-std::string RemoveHtml(const std::string &src);
+CMStringW RemoveHtml(const CMStringW &src);
+
+const char* GetSkypeNick(const char *pszSkypeId);
+const wchar_t* GetSkypeNick(const wchar_t *szSkypeId);
+
+CMStringA ParseUrl(const char *url, const char *token);
+CMStringW ParseUrl(const wchar_t *url, const wchar_t *token);
+
+CMStringA UrlToSkypeId(const char *url, int *pUserType = nullptr);
+CMStringW UrlToSkypeId(const wchar_t *url, int *pUserType = nullptr);
+
+CMStringA GetServerFromUrl(const char *url);
class EventHandle
{
diff --git a/protocols/SkypeWeb/src/stdafx.h b/protocols/SkypeWeb/src/stdafx.h
index 090b107555..d4c8db6a92 100644
--- a/protocols/SkypeWeb/src/stdafx.h
+++ b/protocols/SkypeWeb/src/stdafx.h
@@ -102,6 +102,7 @@ enum SkypeHost
struct AsyncHttpRequest : public MTHttpRequest<CSkypeProto>
{
SkypeHost m_host;
+ MCONTACT hContact = 0;
AsyncHttpRequest(int type, SkypeHost host, LPCSTR url = nullptr, MTHttpRequestHandler pFunc = nullptr);
};
diff --git a/protocols/SkypeWeb/src/version.h b/protocols/SkypeWeb/src/version.h
index c89475f2d6..3e0c412e5d 100644
--- a/protocols/SkypeWeb/src/version.h
+++ b/protocols/SkypeWeb/src/version.h
@@ -1,7 +1,7 @@
#define __MAJOR_VERSION 0
#define __MINOR_VERSION 95
-#define __RELEASE_NUM 12
-#define __BUILD_NUM 3
+#define __RELEASE_NUM 13
+#define __BUILD_NUM 1
#include <stdver.h>