diff options
Diffstat (limited to 'protocols/JabberG/src/jabber_misc.cpp')
-rwxr-xr-x | protocols/JabberG/src/jabber_misc.cpp | 136 |
1 files changed, 97 insertions, 39 deletions
diff --git a/protocols/JabberG/src/jabber_misc.cpp b/protocols/JabberG/src/jabber_misc.cpp index b83bd2b87a..4d96430685 100755 --- a/protocols/JabberG/src/jabber_misc.cpp +++ b/protocols/JabberG/src/jabber_misc.cpp @@ -137,7 +137,7 @@ void CJabberProto::GetAvatarFileName(MCONTACT hContact, wchar_t* pszDest, size_t {
int tPathLen = mir_snwprintf(pszDest, cbLen, L"%s\\%S", VARSW(L"%miranda_avatarcache%").get(), m_szModuleName);
- DWORD dwAttributes = GetFileAttributes(pszDest);
+ DWORD dwAttributes = GetFileAttributesW(pszDest);
if (dwAttributes == 0xffffffff || (dwAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
CreateDirectoryTreeW(pszDest);
@@ -440,48 +440,106 @@ void CJabberProto::MsgPopup(MCONTACT hContact, const wchar_t *szMsg, const wchar Popup_AddClass(&ppd);
}
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static const TiXmlElement* XmlFindChildRecursively(const TiXmlElement *p, const char *elem)
+{
+ if (auto *res = XmlFirstChild(p, elem))
+ return res;
+
+ for (auto *n : TiXmlEnum(p))
+ if (auto *res = XmlFindChildRecursively(n, elem))
+ return res;
+
+ return nullptr;
+}
+
+static bool SaveBlobToFile(const wchar_t *pwszFileName, const CMStringA &body)
+{
+ HANDLE h = CreateFile(pwszFileName, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, nullptr);
+ if (h == INVALID_HANDLE_VALUE)
+ return false;
+
+ DWORD n;
+ size_t bufferLen;
+ ptrA buffer((char *)mir_base64_decode(body, &bufferLen));
+ WriteFile(h, buffer, (DWORD)bufferLen, &n, nullptr);
+ CloseHandle(h);
+ return true;
+}
+
+void CJabberProto::OnGetBob(const TiXmlElement *node, CJabberIqInfo *pReq)
+{
+ if (auto *data = XmlFirstChild(node, "data")) {
+ if (auto *cid = XmlGetAttr(data, "cid")) {
+ if (auto *src = data->GetText()) {
+ VARSW wszTempPath(L"%miranda_userdata%\\JabberTmp");
+ DWORD dwAttributes = GetFileAttributesW(wszTempPath);
+ if (dwAttributes == 0xffffffff || (dwAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
+ CreateDirectoryTreeW(wszTempPath);
+
+ const wchar_t *pwszExt = L".bin";
+ if (auto *pszType = XmlGetAttr(data, "type"))
+ pwszExt = ProtoGetAvatarExtension(ProtoGetAvatarFormatByMimeType(pszType));
+
+ CMStringA szHash = CMStringA(cid).Mid(5, 40);
+ CMStringW wszFileName(FORMAT, L"%s\\%S%s", wszTempPath.get(), szHash.c_str(), pwszExt);
+ SaveBlobToFile(wszFileName, src);
+
+ wszFileName.Insert(0, L"[img]"); wszFileName.Append(L"[/img]");
+ T2Utf szMsg(wszFileName);
+ PROTORECVEVENT pre = {};
+ pre.timestamp = time(0);
+ pre.szMessage = szMsg;
+ ProtoChainRecvMsg(pReq->GetHContact(), &pre);
+ }
+ }
+ }
+}
+
CMStringA CJabberProto::ExtractImage(const TiXmlElement *node)
{
- const TiXmlElement *nHtml, *nBody, *nImg;
- const char *src;
CMStringA link;
- if ((nHtml = XmlFirstChild(node, "html")) != nullptr &&
- (nBody = XmlFirstChild(nHtml, "body")) != nullptr &&
- (nImg = XmlFirstChild(nBody, "img")) != nullptr &&
- (src = XmlGetAttr(nImg, "src")) != nullptr) {
-
- CMStringA strSrc(src);
- if (strSrc.Left(11).Compare("data:image/") == 0) {
- int end = strSrc.Find(';');
- if (end != -1) {
- CMStringW ext(strSrc.c_str() + 11, end - 11);
- int comma = strSrc.Find(L',', end);
- if (comma != -1) {
- CMStringA image(strSrc.c_str() + comma + 1, strSrc.GetLength() - comma - 1);
- image.Replace("%2B", "+");
- image.Replace("%2F", "/");
- image.Replace("%3D", "=");
-
- wchar_t tszTempPath[MAX_PATH], tszTempFile[MAX_PATH];
- GetTempPath(_countof(tszTempPath), tszTempPath);
- GetTempFileName(tszTempPath, L"jab", InterlockedIncrement(&g_nTempFileId), tszTempFile);
- wcsncat_s(tszTempFile, L".", 1);
- wcsncat_s(tszTempFile, ext, ext.GetLength());
-
- HANDLE h = CreateFile(tszTempFile, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL, nullptr);
-
- if (h != INVALID_HANDLE_VALUE) {
- DWORD n;
- size_t bufferLen;
- ptrA buffer((char*)mir_base64_decode(image, &bufferLen));
- WriteFile(h, buffer, (DWORD)bufferLen, &n, nullptr);
- CloseHandle(h);
-
- link = " file:///";
- link += T2Utf(tszTempFile);
+ if (auto *nHtml = XmlFirstChild(node, "html")) {
+ if (auto *nBody = XmlFirstChild(nHtml, "body")) {
+ if (auto *nImg = XmlFindChildRecursively(nBody, "img")) {
+ if (auto *src = XmlGetAttr(nImg, "src")) {
+ CMStringA strSrc(src);
+
+ // direct inline
+ if (strSrc.Left(11).Compare("data:image/") == 0) {
+ int end = strSrc.Find(';');
+ if (end != -1) {
+ CMStringW ext(strSrc.c_str() + 11, end - 11);
+ int comma = strSrc.Find(L',', end);
+ if (comma != -1) {
+ CMStringA image(strSrc.c_str() + comma + 1, strSrc.GetLength() - comma - 1);
+ image.Replace("%2B", "+");
+ image.Replace("%2F", "/");
+ image.Replace("%3D", "=");
+
+ wchar_t tszTempPath[MAX_PATH], tszTempFile[MAX_PATH];
+ GetTempPath(_countof(tszTempPath), tszTempPath);
+ GetTempFileName(tszTempPath, L"jab", InterlockedIncrement(&g_nTempFileId), tszTempFile);
+ wcsncat_s(tszTempFile, L".", 1);
+ wcsncat_s(tszTempFile, ext, ext.GetLength());
+
+ if (SaveBlobToFile(tszTempFile, image))
+ link.AppendFormat(" file://%s", T2Utf(tszTempFile).get());
+ }
+ }
+ }
+
+ // XEP-0231: Bits Of Bytes
+ else if (strSrc.Left(9) == "cid:sha1+" && strSrc.Right(13) == "@bob.xmpp.org") {
+ auto *pIQ = AddIQ(&CJabberProto::OnGetBob, JABBER_IQ_TYPE_GET, XmlGetAttr(node, "from"));
+ pIQ->SetParamsToParse(JABBER_IQ_PARSE_HCONTACT);
+
+ strSrc.Delete(0, 4);
+ m_ThreadInfo->send(XmlNodeIq(pIQ) << XCHILDNS("data", JABBER_FEAT_BITS) << XATTR("cid", strSrc));
}
}
}
|