summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2023-04-17 20:07:16 +0300
committerGeorge Hazan <ghazan@miranda.im>2023-04-17 20:07:16 +0300
commitf43396cbff99cc7cc9410f12e55783ad12d1d2f7 (patch)
treeb2beeabe2b7df2d4ceeae92e20287d08b0675409
parente0df536066a9299127ffe1f22530eaf7b401d0dc (diff)
Jabber:
- option autoloadoob removed due to offline files support; - added support for encrypted offline files
-rw-r--r--include/m_database.h1
-rw-r--r--include/m_protosvc.h1
-rw-r--r--protocols/JabberG/src/jabber_file.cpp64
-rw-r--r--protocols/JabberG/src/jabber_omemo.cpp36
-rw-r--r--protocols/JabberG/src/jabber_opt.cpp1
-rw-r--r--protocols/JabberG/src/jabber_proto.cpp1
-rw-r--r--protocols/JabberG/src/jabber_proto.h1
-rw-r--r--protocols/JabberG/src/jabber_thread.cpp2
-rw-r--r--src/mir_app/src/srmm_log_rtf.cpp13
9 files changed, 96 insertions, 24 deletions
diff --git a/include/m_database.h b/include/m_database.h
index e927084bed..b55c1abedc 100644
--- a/include/m_database.h
+++ b/include/m_database.h
@@ -177,6 +177,7 @@ struct DBVARIANT
#define DBEF_UTF 0x0010 // event contains a text in utf-8
#define DBEF_ENCRYPTED 0x0020 // event is encrypted (never reported outside a driver)
#define DBEF_HAS_ID 0x0040 // event has unique server id
+#define DBEF_SECURE 0x0080 // event is encrypted
struct DBEVENTINFO
{
diff --git a/include/m_protosvc.h b/include/m_protosvc.h
index a49788f6e6..11963877d0 100644
--- a/include/m_protosvc.h
+++ b/include/m_protosvc.h
@@ -721,6 +721,7 @@ struct PROTOFILERESUME
#define PREF_CREATEREAD 1 // create the database event with the 'read' flag set
#define PREF_RTL 4 // 0.5+ addition: support for right-to-left messages
#define PREF_SENT 16 // message will be created with the DBEF_SENT flag
+#define PREF_ENCRYPTED 32 // message is encrypted
struct PROTORECVEVENT
{
diff --git a/protocols/JabberG/src/jabber_file.cpp b/protocols/JabberG/src/jabber_file.cpp
index c96f6ae92c..0b2767de8d 100644
--- a/protocols/JabberG/src/jabber_file.cpp
+++ b/protocols/JabberG/src/jabber_file.cpp
@@ -34,9 +34,25 @@ INT_PTR __cdecl CJabberProto::OnOfflineFile(WPARAM param, LPARAM)
void __cdecl CJabberProto::OfflineFileThread(OFDTHREAD *param)
{
DB::EventInfo dbei(param->hDbEvent);
- if (dbei && !strcmp(dbei.szModule, m_szModuleName) && dbei.eventType == EVENTTYPE_FILE) {
+ if (m_bJabberOnline && dbei && !strcmp(dbei.szModule, m_szModuleName) && dbei.eventType == EVENTTYPE_FILE) {
DB::FILE_BLOB blob(dbei);
- if (blob.isOffline()) {
+ if (const char *url = blob.getUrl()) {
+ bool encrypted = false;
+ // OMEMO encryped file?
+ char protocol[7], hexkey[100], suburl[5001], newurl[5001];
+ int ret = sscanf(url, "%6[^:]://%5000[^#]#%88s", protocol, suburl, hexkey);
+ protocol[6] = hexkey[88] = 0;
+ if (ret == 3 && !strcmp(protocol, "aesgcm") && strlen(hexkey) == 88) {
+ mir_snprintf(newurl, "https://%s", suburl);
+ url = newurl;
+ encrypted = true;
+ }
+ else if (ret != 2 || (strcmp(protocol, "https") && strcmp(protocol, "http"))) {
+ debugLogA("Wrong url");
+ delete param;
+ return;
+ }
+
// initialize the netlib request
NETLIBHTTPREQUEST nlhr = {};
nlhr.cbSize = sizeof(nlhr);
@@ -48,16 +64,44 @@ void __cdecl CJabberProto::OfflineFileThread(OFDTHREAD *param)
NLHR_PTR nlhrReply(Netlib_HttpTransaction(m_hNetlibUser, &nlhr));
if (nlhrReply && nlhrReply->resultCode == 200) {
FILE *f = _wfopen(param->wszPath, L"wb");
- fwrite(nlhrReply->pData, 1, nlhrReply->dataLength, f);
- fclose(f);
+ size_t written = 0;
+ if (f) {
+ if (encrypted) {
+ int payload_len = nlhrReply->dataLength - 16;
+ if (payload_len > 0) {
+ uint8_t ivkey[44];
+ hex2bin(hexkey, ivkey, 44);
+ EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL);
+ EVP_DecryptInit(ctx, EVP_aes_256_gcm(), ivkey + 12, ivkey);
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, nlhrReply->pData + payload_len);
+
+ int outl = 0, round_len = 0;
+ uint8_t *out = (uint8_t *)mir_alloc(payload_len);
+ EVP_DecryptUpdate(ctx, out, &outl, (uint8_t *)nlhrReply->pData, (int)payload_len);
+ int dec_success = EVP_DecryptFinal(ctx, out + outl, &round_len);
+ outl += round_len;
+ EVP_CIPHER_CTX_free(ctx);
+ if (dec_success && outl == payload_len)
+ if (fwrite(out, 1, payload_len, f) == payload_len)
+ written = payload_len;
+ mir_free(out);
+ }
+ }
+ else if (fwrite(nlhrReply->pData, 1, nlhrReply->dataLength, f) == nlhrReply->dataLength)
+ written = nlhrReply->dataLength;
+ fclose(f);
+ }
- DBVARIANT dbv = { DBVT_DWORD };
- dbv.dVal = nlhrReply->dataLength;
- db_event_setJson(param->hDbEvent, "ft", &dbv);
- db_event_setJson(param->hDbEvent, "fs", &dbv);
+ if (written) {
+ DBVARIANT dbv = { DBVT_DWORD };
+ dbv.dVal = nlhrReply->dataLength;
+ db_event_setJson(param->hDbEvent, "ft", &dbv);
+ db_event_setJson(param->hDbEvent, "fs", &dbv);
- if (param->bOpen)
- ShellExecute(nullptr, L"open", param->wszPath, nullptr, nullptr, SW_SHOWDEFAULT);
+ if (param->bOpen)
+ ShellExecuteW(nullptr, L"open", param->wszPath, nullptr, nullptr, SW_SHOWDEFAULT);
+ }
}
}
}
diff --git a/protocols/JabberG/src/jabber_omemo.cpp b/protocols/JabberG/src/jabber_omemo.cpp
index 9666eec9e7..06ebb64647 100644
--- a/protocols/JabberG/src/jabber_omemo.cpp
+++ b/protocols/JabberG/src/jabber_omemo.cpp
@@ -1431,10 +1431,38 @@ bool CJabberProto::OmemoHandleMessage(const TiXmlElement *node, const char *jid,
if (!msgTime || m_bFixIncorrectTimestamps && (msgTime > now || (msgTime < (time_t)JabberGetLastContactMessageTime(hContact))))
msgTime = now;
- PROTORECVEVENT recv = {};
- recv.timestamp = (uint32_t)msgTime;
- recv.szMessage = result.GetBuffer();
- ProtoChainRecvMsg(hContact, &recv);
+ char protocol[7], hexkey[89], suburl[5001];
+ int ret = sscanf(result.GetBuffer(), "%6[^:]://%5000[^#]#%88s", protocol, suburl, hexkey);
+ protocol[6] = hexkey[88] = suburl[5000] = 0;
+ if (ret == 3 && !strcmp(protocol, "aesgcm") && strlen(hexkey) == 88) {
+ CMStringA szName;
+ const char *b = strrchr(suburl, '/') + 1;
+ while (*b != 0 && *b != '#' && *b != '?')
+ szName.AppendChar(*b++);
+
+ ptrW pwszName(mir_utf8decodeW(szName.c_str()));
+
+ JSONNode root;
+ root << WCHAR_PARAM("f", pwszName) << CHAR_PARAM("u", result.GetBuffer());
+
+ DBEVENTINFO dbei = {};
+ dbei.szModule = Proto_GetBaseAccountName(hContact);
+ dbei.timestamp = msgTime;
+ dbei.eventType = EVENTTYPE_FILE;
+ dbei.flags = DBEF_SECURE;
+
+ std::string text = root.write();
+ dbei.cbBlob = (int)text.size() + 1;
+ dbei.pBlob = (uint8_t *)text.c_str();
+ db_event_add(hContact, &dbei);
+ }
+ else {
+ PROTORECVEVENT recv = {};
+ recv.timestamp = (uint32_t)msgTime;
+ recv.szMessage = result.GetBuffer();
+ recv.flags = PREF_ENCRYPTED;
+ ProtoChainRecvMsg(hContact, &recv);
+ }
return true;
}
diff --git a/protocols/JabberG/src/jabber_opt.cpp b/protocols/JabberG/src/jabber_opt.cpp
index 180f57c74a..4df55c6998 100644
--- a/protocols/JabberG/src/jabber_opt.cpp
+++ b/protocols/JabberG/src/jabber_opt.cpp
@@ -717,7 +717,6 @@ public:
m_options.AddOption(LPGENW("Other"), LPGENW("Show transport agents on contact list"), m_proto->m_bShowTransport);
m_options.AddOption(LPGENW("Other"), LPGENW("Automatically add contact when accept authorization"), m_proto->m_bAutoAdd);
m_options.AddOption(LPGENW("Other"), LPGENW("Automatically accept authorization requests"), m_proto->m_bAutoAcceptAuthorization);
- m_options.AddOption(LPGENW("Other"), LPGENW("Automatically download files passed via HTTP File Upload"), m_proto->m_bAutoLoadOOB);
m_options.AddOption(LPGENW("Other"), LPGENW("Fix incorrect timestamps in incoming messages"), m_proto->m_bFixIncorrectTimestamps);
m_options.AddOption(LPGENW("Other"), LPGENW("Enable XMPP link processing (requires AssocMgr)"), m_proto->m_bProcessXMPPLinks);
m_options.AddOption(LPGENW("Other"), LPGENW("Embrace picture URLs with [img]"), m_proto->m_bEmbraceUrls);
diff --git a/protocols/JabberG/src/jabber_proto.cpp b/protocols/JabberG/src/jabber_proto.cpp
index acc141e114..6ffe603acb 100644
--- a/protocols/JabberG/src/jabber_proto.cpp
+++ b/protocols/JabberG/src/jabber_proto.cpp
@@ -86,7 +86,6 @@ CJabberProto::CJabberProto(const char *aProtoName, const wchar_t *aUserName) :
m_bAutoJoinBookmarks(this, "AutoJoinBookmarks", true),
m_bAutoJoinConferences(this, "AutoJoinConferences", false),
m_bAutoJoinHidden(this, "AutoJoinHidden", true),
- m_bAutoLoadOOB(this, "AutoLoadOOB", true),
m_bAutosaveNotes(this, "AutosaveNotes", false),
m_bBsDirect(this, "BsDirect", true),
m_bBsDirectManual(this, "BsDirectManual", false),
diff --git a/protocols/JabberG/src/jabber_proto.h b/protocols/JabberG/src/jabber_proto.h
index 019ea10d35..52e8b98c91 100644
--- a/protocols/JabberG/src/jabber_proto.h
+++ b/protocols/JabberG/src/jabber_proto.h
@@ -195,7 +195,6 @@ struct CJabberProto : public PROTO<CJabberProto>, public IJabberInterface
CMOption<bool> m_bAutoJoinBookmarks;
CMOption<bool> m_bAutoJoinConferences;
CMOption<bool> m_bAutoJoinHidden;
- CMOption<bool> m_bAutoLoadOOB;
CMOption<bool> m_bAutosaveNotes;
CMOption<bool> m_bBsDirect;
CMOption<bool> m_bBsDirectManual;
diff --git a/protocols/JabberG/src/jabber_thread.cpp b/protocols/JabberG/src/jabber_thread.cpp
index 1475657ecb..5e4fae32b9 100644
--- a/protocols/JabberG/src/jabber_thread.cpp
+++ b/protocols/JabberG/src/jabber_thread.cpp
@@ -1324,7 +1324,7 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info)
szMessage += tempstring;
}
}
- else if (!mir_strcmp(pszXmlns, JABBER_FEAT_OOB2) && m_bAutoLoadOOB) {
+ else if (!mir_strcmp(pszXmlns, JABBER_FEAT_OOB2)) {
if (auto *url = XmlGetChildText(xNode, "url")) {
// create incoming file transfer instead of writing message
CMStringA szName;
diff --git a/src/mir_app/src/srmm_log_rtf.cpp b/src/mir_app/src/srmm_log_rtf.cpp
index b38eb0f4eb..512f4d3344 100644
--- a/src/mir_app/src/srmm_log_rtf.cpp
+++ b/src/mir_app/src/srmm_log_rtf.cpp
@@ -143,7 +143,13 @@ void CRtfLogWindow::InsertFileLink(CMStringA &buf, MEVENT hEvent, const DB::FILE
buf.AppendFormat("ofile:%ul", hEvent);
buf.Append("\"}{\\fldrslt{\\ul ");
AppendUnicodeString(buf, blob.getName());
- buf.AppendFormat("}}} | %uKB", blob.getSize() / 1024);
+ buf.AppendFormat("}}}");
+
+ if (blob.getSize() > 0 && blob.getSize() == blob.getTransferred())
+ buf.Append(" \\u10004? ");
+
+ if (uint32_t size = blob.getSize())
+ buf.AppendFormat(" %uKB", size < 1024 ? 1 : blob.getSize() / 1024);
CMStringA szHost;
if (const char *b = strstr(blob.getUrl(), "://"))
@@ -152,11 +158,6 @@ void CRtfLogWindow::InsertFileLink(CMStringA &buf, MEVENT hEvent, const DB::FILE
if (!szHost.IsEmpty())
buf.AppendFormat(" on %s", szHost.c_str());
-
- if (blob.getSize() > 0 && blob.getSize() == blob.getTransferred()) {
- buf.AppendChar(' ');
- AppendUnicodeString(buf, TranslateT("Completed"));
- }
}
/////////////////////////////////////////////////////////////////////////////////////////