From 5732a19c7dd15ee2a70fb30b3b27db9514208d2f Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 7 Aug 2024 17:19:37 +0300 Subject: =?UTF-8?q?fixes=20#4542=20(SkypeWeb:=20Load=20Server=20History=20?= =?UTF-8?q?=D0=B2=D1=82=D1=8F=D0=B3=D0=B8=D0=B2=D0=B0=D0=B5=D1=82=20=D1=82?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE=20=D0=BD=D0=B5=D0=BA=D0=BE=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=BE=D0=B5=20=D0=BA=D0=BE=D0=BB=D0=B8=D1=87=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=B2=D0=BE=20=D1=81=D0=B2=D0=B5=D0=B6=D0=B8=D1=85?= =?UTF-8?q?=20=D1=81=D0=BE=D0=BE=D0=B1=D1=89=D0=B5=D0=BD=D0=B8=D0=B9,=20?= =?UTF-8?q?=D0=B0=20=D0=BD=D0=B5=20=D0=B2=D1=81=D1=8E=20=D0=B8=D1=81=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D1=8E)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- protocols/SkypeWeb/src/requests/files.h | 34 +++++++++------ protocols/SkypeWeb/src/requests/history.h | 23 ++++------ protocols/SkypeWeb/src/requests/messages.h | 4 +- protocols/SkypeWeb/src/skype_chatrooms.cpp | 22 +++++----- protocols/SkypeWeb/src/skype_files.cpp | 32 ++++++++------ protocols/SkypeWeb/src/skype_history_sync.cpp | 62 +++++++++------------------ protocols/SkypeWeb/src/skype_messages.cpp | 61 ++++++++++++-------------- protocols/SkypeWeb/src/skype_proto.h | 8 ++-- protocols/SkypeWeb/src/skype_utils.cpp | 17 ++++++++ protocols/SkypeWeb/src/skype_utils.h | 16 +++++-- 10 files changed, 142 insertions(+), 137 deletions(-) (limited to 'protocols') diff --git a/protocols/SkypeWeb/src/requests/files.h b/protocols/SkypeWeb/src/requests/files.h index 0517385bf3..7c04baabfb 100644 --- a/protocols/SkypeWeb/src/requests/files.h +++ b/protocols/SkypeWeb/src/requests/files.h @@ -16,12 +16,15 @@ struct ASMObjectCreateRequest : public AsyncHttpRequest T2Utf uszFileName(fup->tszFileName); const char *szFileName = strrchr(uszFileName.get() + 1, '\\'); - JSONNode node, jPermissions, jPermission(JSON_ARRAY); - jPermissions.set_name("permissions"); - jPermission.set_name(szContact.c_str()); - jPermission << CHAR_PARAM("", "read"); - jPermissions << jPermission; - node << CHAR_PARAM("type", "sharing/file") << CHAR_PARAM("filename", szFileName) << jPermissions; + JSONNode node; + if (fup->isPicture) + node << CHAR_PARAM("type", "pish/image"); + else + node << CHAR_PARAM("type", "sharing/file"); + + JSONNode jPermission(JSON_ARRAY); jPermission.set_name(szContact.c_str()); jPermission << CHAR_PARAM("", "read"); + JSONNode jPermissions; jPermissions.set_name("permissions"); jPermissions << jPermission; + node << CHAR_PARAM("filename", szFileName) << jPermissions; m_szParam = node.write().c_str(); } }; @@ -31,11 +34,12 @@ struct ASMObjectUploadRequest : public AsyncHttpRequest ASMObjectUploadRequest(CSkypeProto *ppro, const char *szObject, const uint8_t *data, int size, CFileUploadParam *fup) : AsyncHttpRequest(REQUEST_PUT, HOST_OTHER, 0, &CSkypeProto::OnASMObjectUploaded) { - m_szUrl.AppendFormat("https://api.asm.skype.com/v1/objects/%s/content/original", szObject); + m_szUrl.AppendFormat("https://api.asm.skype.com/v1/objects/%s/content/%s", + szObject, fup->isPicture ? "imgpsh" : "original"); pUserInfo = fup; AddHeader("Authorization", CMStringA(FORMAT, "skype_token %s", ppro->m_szApiToken.get())); - AddHeader("Content-Type", "application/octet-stream"); + AddHeader("Content-Type", fup->isPicture ? "application" : "application/octet-stream"); m_szParam.Truncate(size); memcpy(m_szParam.GetBuffer(), data, size); @@ -44,16 +48,20 @@ struct ASMObjectUploadRequest : public AsyncHttpRequest struct SendFileRequest : public AsyncHttpRequest { - SendFileRequest(const char *username, time_t timestamp, const char *message, const char *messageType, const char *asmRef) : + SendFileRequest(CFileUploadParam *fup, const char *username, const char *message) : AsyncHttpRequest(REQUEST_POST, HOST_DEFAULT, 0, &CSkypeProto::OnMessageSent) { m_szUrl.AppendFormat("/users/ME/conversations/%s/messages", mir_urlEncode(username).c_str()); - JSONNode node, ref(JSON_ARRAY); - ref.set_name("amsreferences"); ref.push_back(JSONNode("", asmRef)); + JSONNode ref(JSON_ARRAY); ref.set_name("amsreferences"); ref << CHAR_PARAM("", fup->uid); + + JSONNode node; + if (fup->isPicture) + node << CHAR_PARAM("messagetype", "RichText/UriObject"); + else + node << CHAR_PARAM("messagetype", "RichText/Media_GenericFile"); - node << INT64_PARAM("clientmessageid", timestamp) << CHAR_PARAM("messagetype", messageType) - << CHAR_PARAM("contenttype", "text") << CHAR_PARAM("content", message) << ref; + node << INT64_PARAM("clientmessageid", time(0)) << CHAR_PARAM("contenttype", "text") << CHAR_PARAM("content", message) << ref; m_szParam = node.write().c_str(); } }; diff --git a/protocols/SkypeWeb/src/requests/history.h b/protocols/SkypeWeb/src/requests/history.h index ecd3fbcb65..4e63278f8c 100644 --- a/protocols/SkypeWeb/src/requests/history.h +++ b/protocols/SkypeWeb/src/requests/history.h @@ -21,35 +21,28 @@ along with this program. If not, see . struct SyncHistoryFirstRequest : public AsyncHttpRequest { SyncHistoryFirstRequest(int pageSize) : - AsyncHttpRequest(REQUEST_GET, HOST_DEFAULT, "/users/ME/conversations", &CSkypeProto::OnSyncHistory) + AsyncHttpRequest(REQUEST_GET, HOST_DEFAULT, "/users/ME/conversations", &CSkypeProto::OnSyncConversations) { this << INT_PARAM("startTime", 0) << INT_PARAM("pageSize", pageSize) << CHAR_PARAM("view", "msnp24Equivalent") << CHAR_PARAM("targetType", "Passport|Skype|Lync"); } - - SyncHistoryFirstRequest(const char *url) : - AsyncHttpRequest(REQUEST_GET, HOST_DEFAULT, url, &CSkypeProto::OnSyncHistory) - { - } }; struct GetHistoryRequest : public AsyncHttpRequest { - GetHistoryRequest(const char *who, int pageSize, uint32_t timestamp, bool bOperative) : - AsyncHttpRequest(REQUEST_GET, HOST_DEFAULT, "/users/ME/conversations/" + mir_urlEncode(who) + "/messages", &CSkypeProto::OnGetServerHistory) + CMStringA m_who; + + GetHistoryRequest(MCONTACT _1, const char *who, int pageSize, int64_t timestamp, bool bOperative) : + AsyncHttpRequest(REQUEST_GET, HOST_DEFAULT, "/users/ME/conversations/" + mir_urlEncode(who) + "/messages", &CSkypeProto::OnGetServerHistory), + m_who(who) { + hContact = _1; if (bOperative) pUserInfo = this; - this << INT_PARAM("startTime", timestamp) << INT_PARAM("pageSize", pageSize) + this << INT64_PARAM("startTime", timestamp) << INT_PARAM("pageSize", pageSize) << CHAR_PARAM("view", "msnp24Equivalent") << CHAR_PARAM("targetType", "Passport|Skype|Lync|Thread"); } - - GetHistoryRequest(const char *url, void *pInfo) : - AsyncHttpRequest(REQUEST_GET, HOST_DEFAULT, url, &CSkypeProto::OnGetServerHistory) - { - pUserInfo = pInfo; - } }; struct EmptyHistoryRequest : public AsyncHttpRequest diff --git a/protocols/SkypeWeb/src/requests/messages.h b/protocols/SkypeWeb/src/requests/messages.h index e51718e508..a6d9cf4916 100644 --- a/protocols/SkypeWeb/src/requests/messages.h +++ b/protocols/SkypeWeb/src/requests/messages.h @@ -71,13 +71,13 @@ struct SendTypingRequest : public AsyncHttpRequest struct MarkMessageReadRequest : public AsyncHttpRequest { - MarkMessageReadRequest(const char *username, LONGLONG /*msgId*/, LONGLONG msgTimestamp) : + MarkMessageReadRequest(const char *username, int64_t msgTimestamp) : AsyncHttpRequest(REQUEST_PUT, HOST_DEFAULT) { m_szUrl.AppendFormat("/users/ME/conversations/%s/properties?name=consumptionhorizon", mir_urlEncode(username).c_str()); JSONNode node(JSON_NODE); - node << CHAR_PARAM("consumptionhorizon", CMStringA(::FORMAT, "%lld000;%lld000;%lld000", msgTimestamp, time(NULL), msgTimestamp)); + node << CHAR_PARAM("consumptionhorizon", CMStringA(::FORMAT, "%lld;%lld;%lld", msgTimestamp, msgTimestamp, msgTimestamp)); m_szParam = node.write().c_str(); } }; diff --git a/protocols/SkypeWeb/src/skype_chatrooms.cpp b/protocols/SkypeWeb/src/skype_chatrooms.cpp index de29ccfe0e..118a7ec3e8 100644 --- a/protocols/SkypeWeb/src/skype_chatrooms.cpp +++ b/protocols/SkypeWeb/src/skype_chatrooms.cpp @@ -40,15 +40,17 @@ SESSION_INFO* CSkypeProto::StartChatRoom(const wchar_t *tid, const wchar_t *tnam if (!si) return nullptr; - // Create a user statuses - Chat_AddGroup(si, TranslateT("Admin")); - Chat_AddGroup(si, TranslateT("User")); + if (si->arUsers.getCount() == 0) { + // Create a user statuses + Chat_AddGroup(si, TranslateT("Admin")); + Chat_AddGroup(si, TranslateT("User")); + + PushRequest(new GetChatInfoRequest(tid)); + } // Finish initialization Chat_Control(si, (getBool("HideChats", 1) ? WINDOW_HIDDEN : SESSION_INITDONE)); Chat_Control(si, SESSION_ONLINE); - - PushRequest(new GetChatInfoRequest(tid)); return si; } @@ -59,14 +61,10 @@ void CSkypeProto::OnLoadChats(MHttpResponse *response, AsyncHttpRequest*) return; auto &root = reply.data(); - const JSONNode &metadata = root["_metadata"]; + // const JSONNode &metadata = root["_metadata"]; const JSONNode &conversations = root["conversations"].as_array(); - int totalCount = metadata["totalCount"].as_int(); - std::string syncState = metadata["syncState"].as_string(); - - if (totalCount >= 99 || conversations.size() >= 99) - ReadHistoryRest(syncState.c_str()); + // int totalCount = metadata["totalCount"].as_int(); for (auto &it : conversations) { auto &props = it["threadProperties"]; @@ -373,7 +371,7 @@ void CSkypeProto::OnGetChatInfo(MHttpResponse *response, AsyncHttpRequest*) AddChatContact(si, username, role, true); } - PushRequest(new GetHistoryRequest(T2Utf(si->ptszID), 100, 0, true)); + PushRequest(new GetHistoryRequest(si->hContact, T2Utf(si->ptszID), 100, 0, true)); } wchar_t* CSkypeProto::GetChatContactNick(MCONTACT hContact, const wchar_t *id, const wchar_t *name) diff --git a/protocols/SkypeWeb/src/skype_files.cpp b/protocols/SkypeWeb/src/skype_files.cpp index a9d6512498..2d6bd2c163 100644 --- a/protocols/SkypeWeb/src/skype_files.cpp +++ b/protocols/SkypeWeb/src/skype_files.cpp @@ -28,10 +28,13 @@ void CSkypeProto::ReceiveFileThread(void *param) CMStringA szCookie, szUrl; szCookie.AppendFormat("skypetoken_asm=%s", m_szApiToken.get()); { + auto &json = dbei.getJson(); + auto skft = json["skft"].as_string(); + MHttpRequest nlhr(REQUEST_GET); nlhr.flags = NLHRF_HTTP11 | NLHRF_NOUSERAGENT; nlhr.m_szUrl = blob.getUrl(); - nlhr.m_szUrl += "/views/original/status"; + nlhr.m_szUrl.AppendFormat("/views/%s/status", skft == "Picture.1" ? "imgpsh_mobile_save_anim" : "original"); nlhr.AddHeader("Accept", "*/*"); nlhr.AddHeader("Accept-Encoding", "gzip, deflate"); nlhr.AddHeader("Cookie", szCookie); @@ -105,6 +108,13 @@ void CSkypeProto::SendFileThread(void *p) return; } + if (auto *pBitmap = FreeImage_LoadU(FreeImage_GetFIFFromFilenameU(fup->tszFileName), fup->tszFileName)) { + fup->isPicture = true; + fup->width = FreeImage_GetWidth(pBitmap); + fup->height = FreeImage_GetHeight(pBitmap); + FreeImage_Unload(pBitmap); + } + ProtoBroadcastAck(fup->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, (HANDLE)fup); PushRequest(new ASMObjectCreateRequest(this, fup)); } @@ -174,22 +184,20 @@ void CSkypeProto::OnASMObjectUploaded(MHttpResponse *response, AsyncHttpRequest // is that a picture? CMStringA href; - bool bIsPictture = false; - if (auto *pBitmap = FreeImage_LoadU(FreeImage_GetFIFFromFilenameU(fup->tszFileName), fup->tszFileName)) { - bIsPictture = true; - pRoot->SetAttribute("type", "File.1" /*"Picture.1"*/); + if (fup->isPicture) { + pRoot->SetAttribute("type", "Picture.1"); pRoot->SetAttribute("url_thumbnail", CMStringA(FORMAT, "https://api.asm.skype.com/v1/objects/%s/views/imgt1_anim", fup->uid.get())); - pRoot->SetAttribute("width", FreeImage_GetWidth(pBitmap)); - pRoot->SetAttribute("height", FreeImage_GetHeight(pBitmap)); - pRoot->SetText("To view this file, go to:"); - FreeImage_Unload(pBitmap); + pRoot->SetAttribute("width", fup->width); + pRoot->SetAttribute("height", fup->height); + pRoot->SetText("To view this shared photo, go to:"); href.Format("https://login.skype.com/login/sso?go=xmmfallback?pic=%s", fup->uid.get()); } else { pRoot->SetAttribute("type", "File.1"); pRoot->SetAttribute("url_thumbnail", CMStringA(FORMAT, "https://api.asm.skype.com/v1/objects/%s/views/original", fup->uid.get())); - pRoot->SetText("To view this shared photo, go to:"); + pRoot->SetText("To view this file, go to:"); + href.Format("https://login.skype.com/login/sso?go=webclient.xmm&docid=%s", fup->uid.get()); } @@ -200,7 +208,7 @@ void CSkypeProto::OnASMObjectUploaded(MHttpResponse *response, AsyncHttpRequest auto *xmlOrigName = doc.NewElement("OriginalName"); xmlOrigName->SetAttribute("v", tszFile); pRoot->InsertEndChild(xmlOrigName); auto *xmlSize = doc.NewElement("FileSize"); xmlSize->SetAttribute("v", (int)fup->size); pRoot->InsertEndChild(xmlSize); - if (bIsPictture) { + if (fup->isPicture) { auto xmlMeta = doc.NewElement("meta"); xmlMeta->SetAttribute("type", "photo"); xmlMeta->SetAttribute("originalName", tszFile); pRoot->InsertEndChild(xmlMeta); @@ -214,7 +222,7 @@ void CSkypeProto::OnASMObjectUploaded(MHttpResponse *response, AsyncHttpRequest Utils_GetRandom(¶m->hMessage, sizeof(param->hMessage)); param->hMessage &= ~0x80000000; - auto *pReq = new SendFileRequest(getId(fup->hContact), time(NULL), printer.CStr(), "RichText/Media_GenericFile", fup->uid); + auto *pReq = new SendFileRequest(fup, getId(fup->hContact), printer.CStr()); pReq->pUserInfo = param; PushRequest(pReq); diff --git a/protocols/SkypeWeb/src/skype_history_sync.cpp b/protocols/SkypeWeb/src/skype_history_sync.cpp index 294800d304..a1e86c777b 100644 --- a/protocols/SkypeWeb/src/skype_history_sync.cpp +++ b/protocols/SkypeWeb/src/skype_history_sync.cpp @@ -25,6 +25,7 @@ void CSkypeProto::OnGetServerHistory(MHttpResponse *response, AsyncHttpRequest * if (reply.error()) return; + auto *pOrig = (GetHistoryRequest *)pRequest; auto &root = reply.data(); const JSONNode &metadata = root["_metadata"]; @@ -33,7 +34,9 @@ void CSkypeProto::OnGetServerHistory(MHttpResponse *response, AsyncHttpRequest * bool markAllAsUnread = getBool("MarkMesUnread", true); bool bUseLocalTime = !bUseServerTime && pRequest->pUserInfo != 0; - uint32_t lastMsgTime = 0; + bool bSetLastTime = false; + + int64_t lastMsgTime = 0; // max timestamp on this page time_t iLocalTime = time(0); auto &conv = root["messages"]; @@ -47,24 +50,19 @@ void CSkypeProto::OnGetServerHistory(MHttpResponse *response, AsyncHttpRequest * MCONTACT hContact = FindContact(szChatId); - time_t timestamp = IsoToUnixTime(message["composetime"].as_string()); - if (timestamp > getDword(hContact, "LastMsgTime", 0)) - setDword(hContact, "LastMsgTime", timestamp); - DB::EventInfo dbei(db_event_getById(m_szModuleName, szMessageId)); dbei.hContact = hContact; dbei.szModule = m_szModuleName; - dbei.timestamp = timestamp; + dbei.timestamp = (bUseLocalTime) ? iLocalTime : IsoToUnixTime(message["composetime"].as_string()); dbei.szId = szMessageId; if (iUserType == 19) dbei.szUserId = szFrom; - uint32_t id = message["id"].as_int(); - if (id > lastMsgTime) + int64_t id = _atoi64(message["id"].as_string().c_str()); + if (id > lastMsgTime) { + bSetLastTime = true; lastMsgTime = id; - - if (bUseLocalTime) - timestamp = iLocalTime; + } dbei.flags = DBEF_UTF; if (!markAllAsUnread) @@ -80,37 +78,20 @@ void CSkypeProto::OnGetServerHistory(MHttpResponse *response, AsyncHttpRequest * } } - if (totalCount >= 99 || conv.size() >= 99) { - CMStringA szUrl(pRequest->m_szUrl); - int i1 = szUrl.Find("startTime="); - int i2 = szUrl.Find("&", i1); - if (i1 != -1 && i2 != -1) { - i1 += 10; - szUrl.Delete(i1, i2 - i1); - - char buf[100]; - itoa(lastMsgTime, buf, sizeof(buf)); - szUrl.Insert(i1, buf); - - PushRequest(new GetHistoryRequest(szUrl, pRequest->pUserInfo)); - } - } -} + if (bSetLastTime && lastMsgTime > getLastTime(pOrig->hContact)) + setLastTime(pOrig->hContact, lastMsgTime); -void CSkypeProto::ReadHistoryRest(const char *szUrl) -{ - auto *p = strstr(szUrl, g_plugin.szDefaultServer); - if (p) - PushRequest(new SyncHistoryFirstRequest(p+ g_plugin.szDefaultServer.GetLength()+3)); + if (totalCount >= 99 || conv.size() >= 99) + PushRequest(new GetHistoryRequest(pOrig->hContact, pOrig->m_who, 100, lastMsgTime, pRequest->pUserInfo != 0)); } INT_PTR CSkypeProto::SvcLoadHistory(WPARAM hContact, LPARAM) { - PushRequest(new GetHistoryRequest(getId(hContact), 100, 0, false)); + PushRequest(new GetHistoryRequest(hContact, getId(hContact), 100, 0, false)); return 0; } -void CSkypeProto::OnSyncHistory(MHttpResponse *response, AsyncHttpRequest*) +void CSkypeProto::OnSyncConversations(MHttpResponse *response, AsyncHttpRequest*) { JsonReply reply(response); if (reply.error()) @@ -120,12 +101,9 @@ void CSkypeProto::OnSyncHistory(MHttpResponse *response, AsyncHttpRequest*) const JSONNode &metadata = root["_metadata"]; const JSONNode &conversations = root["conversations"].as_array(); - int totalCount = metadata["totalCount"].as_int(); + // int totalCount = metadata["totalCount"].as_int(); std::string syncState = metadata["syncState"].as_string(); - if (totalCount >= 99 || conversations.size() >= 99) - ReadHistoryRest(syncState.c_str()); - for (auto &conversation : conversations) { const JSONNode &lastMessage = conversation["lastMessage"]; if (!lastMessage) @@ -135,13 +113,13 @@ void CSkypeProto::OnSyncHistory(MHttpResponse *response, AsyncHttpRequest*) std::string strConversationLink = lastMessage["conversationLink"].as_string(); CMStringA szSkypename = UrlToSkypeId(strConversationLink.c_str(), &iUserType); if (iUserType == 8 || iUserType == 2) { - time_t composeTime(IsoToUnixTime(lastMessage["composetime"].as_string())); + int64_t id = _atoi64(lastMessage["id"].as_string().c_str()); MCONTACT hContact = FindContact(szSkypename); if (hContact != NULL) { - uint32_t lastMsgTime = getDword(hContact, "LastMsgTime", 0); - if (lastMsgTime && lastMsgTime < composeTime) - PushRequest(new GetHistoryRequest(szSkypename, 100, lastMsgTime, true)); + auto lastMsgTime = getLastTime(hContact); + if (lastMsgTime && lastMsgTime < id) + PushRequest(new GetHistoryRequest(hContact, szSkypename, 100, lastMsgTime, true)); } } } diff --git a/protocols/SkypeWeb/src/skype_messages.cpp b/protocols/SkypeWeb/src/skype_messages.cpp index 8ceb243d0a..22ad6918b9 100644 --- a/protocols/SkypeWeb/src/skype_messages.cpp +++ b/protocols/SkypeWeb/src/skype_messages.cpp @@ -93,7 +93,7 @@ bool CSkypeProto::ParseMessage(const JSONNode &node, DB::EventInfo &dbei) CMStringW wszContent = node["content"].as_mstring(); std::string strMessageType = node["messagetype"].as_string(); - if (strMessageType == "RichText/Media_GenericFile") { + if (strMessageType == "RichText/Media_GenericFile" || strMessageType == "RichText/UriObject") { ProcessFileRecv(dbei.hContact, node["content"].as_string().c_str(), dbei); return false; } @@ -152,9 +152,11 @@ void CSkypeProto::ProcessNewMessage(const JSONNode &node) MCONTACT hContact = AddContact(szConversationName, nullptr, true); - time_t timestamp = time(0); // fuck the server time, we need to place events in the order of our local time - if (m_bHistorySynced) - setDword(hContact, "LastMsgTime", timestamp); + if (m_bHistorySynced) { + int64_t lastMsgId = _atoi64(node["id"].as_string().c_str()); + if (lastMsgId > getLastTime(hContact)) + setLastTime(hContact, lastMsgId); + } if (iUserType == 19) if (OnChatEvent(node)) @@ -172,7 +174,7 @@ void CSkypeProto::ProcessNewMessage(const JSONNode &node) DB::EventInfo dbei(db_event_getById(m_szModuleName, szMessageId)); dbei.hContact = hContact; - dbei.timestamp = timestamp; + dbei.timestamp = time(0); dbei.szId = szMessageId; dbei.flags = DBEF_UTF; if (IsMe(szFromSkypename)) @@ -190,20 +192,11 @@ void CSkypeProto::ProcessNewMessage(const JSONNode &node) void CSkypeProto::OnMarkRead(MCONTACT hContact, MEVENT hDbEvent) { - if (IsOnline() && !isChatRoom(hContact)) - MarkMessagesRead(hContact, hDbEvent); -} - -void CSkypeProto::MarkMessagesRead(MCONTACT hContact, MEVENT hDbEvent) -{ - debugLogA(__FUNCTION__); - - DBEVENTINFO dbei = {}; - db_event_get(hDbEvent, &dbei); - time_t timestamp = dbei.timestamp; - - if (getDword(hContact, "LastMsgTime") > (timestamp - 300)) - PushRequest(new MarkMessageReadRequest(getId(hContact), timestamp, timestamp)); + if (IsOnline()) { + DB::EventInfo dbei(hDbEvent, false); + if (dbei && dbei.szId) + PushRequest(new MarkMessageReadRequest(getId(hContact), _atoi64(dbei.szId))); + } } void CSkypeProto::OnReceiveOfflineFile(DB::FILE_BLOB &blob) @@ -247,22 +240,24 @@ void CSkypeProto::ProcessFileRecv(MCONTACT hContact, const char *szContent, DB:: } // ordinary file - if (!mir_strcmp(pszFileType, "File.1")) { - } - else { - debugLogA("Invalid or unsupported file type <%s> ignored", pszFileType); - return; - } + if (!mir_strcmp(pszFileType, "File.1") || !mir_strcmp(pszFileType, "Picture.1")) { + MEVENT hEvent; + dbei.flags |= DBEF_TEMPORARY | DBEF_JSON; + if (dbei) { + DB::FILE_BLOB blob(dbei); + OnReceiveOfflineFile(blob); + blob.write(dbei); + db_event_edit(dbei.getEvent(), &dbei, true); + delete ft; + hEvent = dbei.getEvent(); + } + else hEvent = ProtoChainRecvFile(hContact, DB::FILE_BLOB(ft, ft->fileName), dbei); - dbei.flags |= DBEF_TEMPORARY; - if (dbei) { - DB::FILE_BLOB blob(dbei); - OnReceiveOfflineFile(blob); - blob.write(dbei); - db_event_edit(dbei.getEvent(), &dbei, true); - delete ft; + DBVARIANT dbv = { DBVT_UTF8 }; + dbv.pszVal = (char*)pszFileType; + db_event_setJson(hEvent, "skft", &dbv); } - else ProtoChainRecvFile(hContact, DB::FILE_BLOB(ft, ft->fileName), dbei); + else debugLogA("Invalid or unsupported file type <%s> ignored", pszFileType); } void CSkypeProto::ProcessContactRecv(MCONTACT hContact, const char *szContent, DB::EventInfo &dbei) diff --git a/protocols/SkypeWeb/src/skype_proto.h b/protocols/SkypeWeb/src/skype_proto.h index 1a4cccda18..c3fd62b343 100644 --- a/protocols/SkypeWeb/src/skype_proto.h +++ b/protocols/SkypeWeb/src/skype_proto.h @@ -159,7 +159,7 @@ public: void OnMessageSent(MHttpResponse *response, AsyncHttpRequest *pRequest); void OnGetServerHistory(MHttpResponse *response, AsyncHttpRequest *pRequest); - void OnSyncHistory(MHttpResponse *response, AsyncHttpRequest *pRequest); + void OnSyncConversations(MHttpResponse *response, AsyncHttpRequest *pRequest); void OnLoadChats(MHttpResponse *response, AsyncHttpRequest *pRequest); void OnGetChatInfo(MHttpResponse *response, AsyncHttpRequest *pRequest); @@ -261,8 +261,6 @@ private: int __cdecl OnPreCreateMessage(WPARAM, LPARAM lParam); - void MarkMessagesRead(MCONTACT hContact, MEVENT hDbEvent); - void ProcessContactRecv(MCONTACT hContact, const char *szContent, DB::EventInfo &dbei); void ProcessFileRecv(MCONTACT hContact, const char *szContent, DB::EventInfo &dbei); @@ -298,7 +296,6 @@ private: void ProcessConversationUpdate(const JSONNode &node); void RefreshStatuses(void); - void ReadHistoryRest(const char *url); // utils template @@ -315,6 +312,9 @@ private: bool IsMe(const wchar_t *str); bool IsMe(const char *str); + int64_t getLastTime(MCONTACT); + void setLastTime(MCONTACT, int64_t); + static time_t IsoToUnixTime(const std::string &stamp); static int SkypeToMirandaStatus(const char *status); diff --git a/protocols/SkypeWeb/src/skype_utils.cpp b/protocols/SkypeWeb/src/skype_utils.cpp index e3af5b6c74..78487e0850 100644 --- a/protocols/SkypeWeb/src/skype_utils.cpp +++ b/protocols/SkypeWeb/src/skype_utils.cpp @@ -79,6 +79,8 @@ time_t CSkypeProto::IsoToUnixTime(const std::string &stamp) return (t >= 0) ? t : 0; } +////////////////////////////////////////////////////////////////////////////////////////// + struct HtmlEntity { const char *entity; @@ -477,6 +479,21 @@ bool CSkypeProto::IsMe(const char *str) ////////////////////////////////////////////////////////////////////////////////////////// +int64_t CSkypeProto::getLastTime(MCONTACT hContact) +{ + ptrA szLastTime(getStringA(hContact, "LastMsgTime")); + return (szLastTime) ? _atoi64(szLastTime) : 0; +} + +void CSkypeProto::setLastTime(MCONTACT hContact, int64_t iValue) +{ + char buf[100]; + _i64toa(iValue, buf, 10); + setString(hContact, "LastMsgTime", buf); +} + +////////////////////////////////////////////////////////////////////////////////////////// + bool CSkypeProto::IsFileExists(std::wstring path) { return _waccess(path.c_str(), 0) == 0; diff --git a/protocols/SkypeWeb/src/skype_utils.h b/protocols/SkypeWeb/src/skype_utils.h index 5acdb1b856..2835ae45da 100644 --- a/protocols/SkypeWeb/src/skype_utils.h +++ b/protocols/SkypeWeb/src/skype_utils.h @@ -42,16 +42,24 @@ public: __inline operator HANDLE() { return _hEvent; } }; -struct CFileUploadParam : public MZeroedObject { +struct CFileUploadParam : public MZeroedObject +{ ptrW tszFileName; ptrW tszDesc; ptrA atr; ptrA fname; ptrA uid; - size_t size; + long size; + int width, height; MCONTACT hContact; - - __forceinline CFileUploadParam(MCONTACT _hContact, const wchar_t* _desc, wchar_t** _files) : hContact(_hContact), tszDesc(mir_wstrdup(_desc)), tszFileName(mir_wstrdup(_files[0])) {}; + bool isPicture; + + __forceinline CFileUploadParam(MCONTACT _hContact, const wchar_t* _desc, wchar_t** _files) : + hContact(_hContact), + tszDesc(mir_wstrdup(_desc)), + tszFileName(mir_wstrdup(_files[0])) + {}; + __forceinline bool IsAccess() { return ::_waccess(tszFileName, 0) == 0; } }; -- cgit v1.2.3