summaryrefslogtreecommitdiff
path: root/protocols/MRA/src/MraOfflineMsg.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/MRA/src/MraOfflineMsg.cpp')
-rw-r--r--protocols/MRA/src/MraOfflineMsg.cpp432
1 files changed, 432 insertions, 0 deletions
diff --git a/protocols/MRA/src/MraOfflineMsg.cpp b/protocols/MRA/src/MraOfflineMsg.cpp
new file mode 100644
index 0000000000..e3e8b76aff
--- /dev/null
+++ b/protocols/MRA/src/MraOfflineMsg.cpp
@@ -0,0 +1,432 @@
+#include "Mra.h"
+#include "MraOfflineMsg.h"
+#include "MraConstans.h"
+
+
+#define LF "\n"
+#define LFLF "\n\n"
+#define CRLF "\r\n"
+#define CRLFCRLF "\r\n\r\n"
+
+
+DWORD MraOfflineMessageGetMIMEHeadAndBody (LPSTR lpszMessage, size_t dwMessageSize, LPSTR *plpszHeader, size_t *pdwHeaderSize, LPSTR *plpszBody, size_t *pdwBodySize);
+DWORD MraOfflineMessageGetNextMIMEPart (LPSTR lpszBody, size_t dwBodySize, LPSTR lpszBoundary, size_t dwBoundarySize, LPSTR *plpszCurMIMEPos, LPSTR *plpszMIMEPart, size_t *pdwMIMEPartSize);
+DWORD MraOfflineMessageGetHeaderValue (LPSTR lpszHeader, LPSTR lpszHeaderLow, size_t dwHeaderSize, LPSTR lpszValueName, size_t dwValueNameSize, LPSTR *plpszValue, size_t *pdwValueSize);
+DWORD MraOfflineMessageGetHeaderValueLow (LPSTR lpszHeaderLow, size_t dwHeaderSize, LPSTR lpszValueName, size_t dwValueNameSize, LPSTR *plpszValue, size_t *pdwValueSize);
+DWORD MraOfflineMessageConvertTime (INTERNET_TIME *pitTime);
+
+
+
+
+DWORD MraOfflineMessageGet(MRA_LPS *plpsMsg, DWORD *pdwTime, DWORD *pdwFlags, MRA_LPS *plpsEMail, MRA_LPS *plpsText, MRA_LPS *plpsRTFText, MRA_LPS *plpsMultiChatData, LPBYTE *plpbBuff)
+{// Сообщение
+ DWORD dwRetErrorCode = ERROR_INVALID_HANDLE;
+
+
+ if (plpsMsg)
+ if (plpsMsg->lpszData && plpsMsg->dwSize)
+ {
+ LPSTR lpszHeader, lpszHeaderLow, lpszBody, lpszContentTypeLow, lpszTemp;
+ size_t dwHeaderSize, dwBodySize, dwContentTypeSize, dwTempSize;
+ DWORD dwMultichatType;
+
+ #ifdef _DEBUG
+ DebugPrintCRLFA(plpsMsg->lpszData);
+ #endif
+
+ if (MraOfflineMessageGetMIMEHeadAndBody(plpsMsg->lpszData, plpsMsg->dwSize, &lpszHeader, &dwHeaderSize, &lpszBody, &dwBodySize) == NO_ERROR)
+ {
+ lpszHeaderLow = (LPSTR)mir_calloc(dwHeaderSize);
+ if (lpszHeaderLow) BuffToLowerCase(lpszHeaderLow, lpszHeader, dwHeaderSize);
+
+ if (pdwTime)
+ if (MraOfflineMessageGetHeaderValue(lpszHeader, lpszHeaderLow, dwHeaderSize, "date", 4, &lpszTemp, &dwTempSize) == NO_ERROR)
+ {
+ INTERNET_TIME itTime;
+ InternetTimeGetTime(lpszTemp, dwTempSize, &itTime);
+ (*pdwTime) = MraOfflineMessageConvertTime(&itTime);
+ }else {
+ (*pdwTime) = 0;
+ }
+
+ if (pdwFlags)
+ if (MraOfflineMessageGetHeaderValue(lpszHeader, lpszHeaderLow, dwHeaderSize, "x-mrim-flags", 12, &lpszTemp, &dwTempSize) == NO_ERROR)
+ {
+ (*pdwFlags) = StrHexToUNum32(lpszTemp, dwTempSize);
+ }else {
+ (*pdwFlags) = 0;
+ }
+
+ if (MraOfflineMessageGetHeaderValue(lpszHeader, lpszHeaderLow, dwHeaderSize, "x-mrim-multichat-type", 21, &lpszTemp, &dwTempSize) == NO_ERROR)
+ {
+ dwMultichatType = StrHexToUNum32(lpszTemp, dwTempSize);
+ }else {
+ dwMultichatType = 0;
+ }
+
+
+ if (plpsEMail)
+ if (MraOfflineMessageGetHeaderValue(lpszHeader, lpszHeaderLow, dwHeaderSize, "from", 4, &plpsEMail->lpszData, &plpsEMail->dwSize) != NO_ERROR)
+ {
+ plpsEMail->lpszData = NULL;
+ plpsEMail->dwSize = 0;
+ }
+
+
+ if (plpsText)
+ {
+ plpsText->lpszData = NULL;
+ plpsText->dwSize = 0;
+ }
+ if (plpsRTFText)
+ {
+ plpsRTFText->lpszData = NULL;
+ plpsRTFText->dwSize = 0;
+ }
+ if (plpsMultiChatData)
+ {
+ plpsMultiChatData->lpszData = NULL;
+ plpsMultiChatData->dwSize = 0;
+ }
+ if (plpbBuff) (*plpbBuff) = NULL;
+
+ if (plpsText || plpsRTFText)
+ if (MraOfflineMessageGetHeaderValueLow(lpszHeaderLow, dwHeaderSize, "content-type", 12, &lpszContentTypeLow, &dwContentTypeSize) == NO_ERROR)
+ {
+
+ if (MemoryFind(0, lpszContentTypeLow, dwContentTypeSize, "multipart/alternative", 21))
+ {// Content-Type: multipart/alternative; boundary = 1217508709J3777283291217508709T31197726
+ LPSTR lpszBoundary, lpszMIMEPart, lpszCurMIMEPos, lpszMIMEHeader, lpszMIMEHeaderLow, lpszMIMEBody, lpszMIMEContentType;
+ size_t i, dwBoundarySize, dwMIMEPartSize, dwMIMEHeaderSize, dwMIMEBodySize, dwMIMEContentTypeSize;
+
+ lpszBoundary = (LPSTR)MemoryFind(0, lpszContentTypeLow, dwContentTypeSize, "boundary=", 9);
+ if (lpszBoundary)
+ {
+ dwBoundarySize = ((dwContentTypeSize-(lpszBoundary-lpszContentTypeLow))-9);
+ lpszBoundary = (lpszHeader+((lpszBoundary+9)-lpszHeaderLow));
+
+ i = 0;
+ lpszCurMIMEPos = lpszBody;
+ while (MraOfflineMessageGetNextMIMEPart(lpszBody, dwBodySize, lpszBoundary, dwBoundarySize, &lpszCurMIMEPos, &lpszMIMEPart, &dwMIMEPartSize) == NO_ERROR)
+ {
+ if (MraOfflineMessageGetMIMEHeadAndBody(lpszMIMEPart, dwMIMEPartSize, &lpszMIMEHeader, &dwMIMEHeaderSize, &lpszMIMEBody, &dwMIMEBodySize) == NO_ERROR)
+ {
+ lpszMIMEHeaderLow = (LPSTR)mir_calloc(dwMIMEHeaderSize);
+ if (lpszMIMEHeaderLow)
+ {
+ BuffToLowerCase(lpszMIMEHeaderLow, lpszMIMEHeader, dwMIMEHeaderSize);
+ if (MraOfflineMessageGetHeaderValueLow(lpszMIMEHeaderLow, dwMIMEHeaderSize, "content-type", 12, &lpszMIMEContentType, &dwMIMEContentTypeSize) == NO_ERROR)
+ {
+ if (MemoryFind(0, lpszMIMEContentType, dwMIMEContentTypeSize, "text/plain", 10))
+ {// this is simple text part: text/plain
+ if (plpsText)
+ {
+ if (MemoryFind(0, lpszMIMEContentType, dwMIMEContentTypeSize, "utf-16le", 8))
+ {// charset = UTF-16LE// предполагаем что оно в base64
+ if (plpbBuff)
+ {// буффер для декодирования текста можно выделять
+ LPWSTR lpwszText;
+ size_t dwTextSize;
+
+ lpwszText = (LPWSTR)mir_calloc(dwMIMEBodySize);
+ if (lpwszText)
+ {
+ BASE64DecodeFormated(lpszMIMEBody, dwMIMEBodySize, lpwszText, dwMIMEBodySize, &dwTextSize);
+ plpsText->lpwszData = lpwszText;
+ plpsText->dwSize = dwTextSize;
+ if (pdwFlags)
+ {
+ (*pdwFlags) |= MESSAGE_FLAG_v1p16; // set unocode flag if not exist
+ (*pdwFlags) &= ~MESSAGE_FLAG_CP1251; // reset ansi flag if exist
+ }
+ (*plpbBuff) = (LPBYTE)lpwszText;
+ dwRetErrorCode = NO_ERROR;
+ }
+ }
+ }else
+ if (MemoryFind(0, lpszMIMEContentType, dwMIMEContentTypeSize, "cp-1251", 7))
+ {// charset = CP-1251
+ plpsText->lpszData = lpszMIMEBody;
+ plpsText->dwSize = dwMIMEBodySize;
+ if (pdwFlags)
+ {
+ (*pdwFlags) &= ~MESSAGE_FLAG_v1p16; // reset unocode flag if exist
+ (*pdwFlags) |= MESSAGE_FLAG_CP1251; // set ansi flag
+ }
+ dwRetErrorCode = NO_ERROR;
+ }else {
+ DebugBreak();
+ }
+ }
+ }else
+ if (MemoryFind(0, lpszMIMEContentType, dwMIMEContentTypeSize, "application/x-mrim-rtf", 22))
+ {
+ if (plpsRTFText)
+ {
+ plpsRTFText->lpszData = lpszMIMEBody;
+ plpsRTFText->dwSize = dwMIMEBodySize;
+ if (pdwFlags) (*pdwFlags) |= MESSAGE_FLAG_RTF; // set RTF flag if not exist
+ dwRetErrorCode = NO_ERROR;
+ }
+ }else
+ if (MemoryFind(0, lpszMIMEContentType, dwMIMEContentTypeSize, "application/x-mrim+xml", 22))
+ {
+ if (plpsMultiChatData)
+ {
+ plpsMultiChatData->lpszData = lpszMIMEBody;
+ plpsMultiChatData->dwSize = dwMIMEBodySize;
+ if (pdwFlags) (*pdwFlags) |= MESSAGE_FLAG_MULTICHAT; // set MESSAGE_FLAG_MULTICHAT flag if not exist
+ dwRetErrorCode = NO_ERROR;
+ }
+ }else {
+ DebugBreak();
+ }
+ }
+ mir_free(lpszMIMEHeaderLow);
+ }
+ }
+ i++;
+ }
+
+ DebugBreakIf((i>3 || i == 0));
+ }else {// boundary not found
+ DebugBreak();
+ }
+ }else
+ if (MemoryFind(0, lpszContentTypeLow, dwContentTypeSize, "text/plain", 10))
+ {// Content-Type: text/plain; charset = CP-1251
+ if (MemoryFind(0, lpszContentTypeLow, dwContentTypeSize, "utf-16le", 8))
+ {// charset = UTF-16LE// предполагаем что оно в base64
+ if (plpbBuff)
+ {// буффер для декодирования текста можно выделять
+ LPWSTR lpwszText;
+ size_t dwTextSize;
+
+ lpwszText = (LPWSTR)mir_calloc(dwBodySize);
+ if (lpwszText)
+ {
+ BASE64DecodeFormated(lpszBody, dwBodySize, lpwszText, dwBodySize, &dwTextSize);
+ plpsText->lpwszData = lpwszText;
+ plpsText->dwSize = dwTextSize;
+ if (pdwFlags)
+ {
+ (*pdwFlags) |= MESSAGE_FLAG_v1p16; // set unocode flag if not exist
+ (*pdwFlags) &= ~MESSAGE_FLAG_CP1251; // reset ansi flag if exist
+ }
+ (*plpbBuff) = (LPBYTE)lpwszText;
+ dwRetErrorCode = NO_ERROR;
+ }
+ }
+ }else
+ if (MemoryFind(0, lpszContentTypeLow, dwContentTypeSize, "cp-1251", 7))
+ {// charset = CP-1251
+ plpsText->lpszData = lpszBody;
+ plpsText->dwSize = dwBodySize;
+ if (pdwFlags)
+ {
+ (*pdwFlags) &= ~MESSAGE_FLAG_v1p16; // reset unocode flag if exist
+ (*pdwFlags) |= MESSAGE_FLAG_CP1251; // set ansi flag
+ }
+ dwRetErrorCode = NO_ERROR;
+ }else {
+ DebugBreak();
+ }
+ }else
+ if (MemoryFind(0, lpszContentTypeLow, dwContentTypeSize, "application/x-mrim-auth-req", 27))
+ {// Content-Type: application/x-mrim-auth-req
+ if (plpsText)
+ {
+ plpsText->lpszData = lpszBody;
+ plpsText->dwSize = dwBodySize;
+ }
+ dwRetErrorCode = NO_ERROR;
+ }else {
+ DebugBreak();
+ }
+ }else {
+ DebugBreak();
+ }
+
+ mir_free(lpszHeaderLow);
+ }
+ }
+
+return(dwRetErrorCode);
+}
+
+
+DWORD MraOfflineMessageGetMIMEHeadAndBody(LPSTR lpszMessage, size_t dwMessageSize, LPSTR *plpszHeader, size_t *pdwHeaderSize, LPSTR *plpszBody, size_t *pdwBodySize)
+{
+ DWORD dwRetErrorCode = ERROR_NOT_FOUND;
+
+ if (lpszMessage && dwMessageSize)
+ {
+ LPSTR lpszBody;
+ size_t dwBodySize;
+
+ // затычка: майл не придерживается RFC и вместо CRLFCRLF ставит LFLF в MIME частях, иногда ставит
+ lpszBody = (LPSTR)MemoryFind(0, lpszMessage, dwMessageSize, CRLFCRLF, (sizeof(CRLFCRLF)-1));
+ if (lpszBody)
+ {
+ lpszBody += (sizeof(CRLFCRLF)-1);
+ }else {
+ lpszBody = (LPSTR)MemoryFind(0, lpszMessage, dwMessageSize, LFLF, (sizeof(LFLF)-1));
+ if (lpszBody) lpszBody += (sizeof(LFLF)-1);
+ }
+
+ if (lpszBody)
+ {// нашли начало контента миме части
+ dwBodySize = (dwMessageSize-(lpszBody-lpszMessage));
+
+ if (plpszHeader) (*plpszHeader) = lpszMessage;
+ if (pdwHeaderSize) (*pdwHeaderSize) = ((lpszBody-(sizeof(LFLF)-1))-lpszMessage);
+ if (plpszBody) (*plpszBody) = lpszBody;
+ if (pdwBodySize) (*pdwBodySize) = dwBodySize;
+
+ dwRetErrorCode = NO_ERROR;
+ }
+ }else {
+ dwRetErrorCode = ERROR_INVALID_HANDLE;
+ }
+return(dwRetErrorCode);
+}
+
+
+DWORD MraOfflineMessageGetNextMIMEPart(LPSTR lpszBody, size_t dwBodySize, LPSTR lpszBoundary, size_t dwBoundarySize, LPSTR *plpszCurMIMEPos, LPSTR *plpszMIMEPart, size_t *pdwMIMEPartSize)
+{
+ DWORD dwRetErrorCode = ERROR_NOT_FOUND;
+
+ if (lpszBody && dwBodySize)
+ {
+ LPSTR lpszMIMEPart, lpszCurMIMEPos, lpszTemp;
+ size_t dwMIMEPartSize;
+
+ if (plpszCurMIMEPos) lpszCurMIMEPos = (*plpszCurMIMEPos);
+ lpszMIMEPart = (LPSTR)MemoryFind((lpszCurMIMEPos-lpszBody), lpszBody, dwBodySize, lpszBoundary, dwBoundarySize);
+ if (lpszMIMEPart)
+ {// первая миме часть
+ lpszMIMEPart += dwBoundarySize;
+
+ // затычка: майл не придерживается RFC и вместо CRLF ставит LF в MIME частях, иногда ставит
+ if ((*((WORD*)lpszMIMEPart)) == (*((WORD*)CRLF)))
+ {
+ lpszMIMEPart += (sizeof(CRLF)-1);
+ }else
+ if ((*((BYTE*)lpszMIMEPart)) == (*((BYTE*)LF)))
+ {
+ lpszMIMEPart += (sizeof(LF)-1);
+ }else
+ if ((*((WORD*)lpszMIMEPart)) == '--')
+ {
+ lpszMIMEPart = NULL;
+ }else {
+ DebugBreak();
+ }
+
+ if (lpszMIMEPart)
+ {
+ lpszTemp = (LPSTR)MemoryFind((lpszMIMEPart-lpszBody), lpszBody, dwBodySize, lpszBoundary, dwBoundarySize);
+ if (lpszTemp)
+ {// нашли конец миме части с текстом
+ dwMIMEPartSize = (lpszTemp-lpszMIMEPart);// 4 = CRLF"--"Boundary / 3 = LF"--"Boundary
+ // затычка: майл не придерживается RFC и вместо CRLF ставит LF в MIME частях, иногда ставит
+ if ((*((WORD*)(lpszTemp-4))) == (*((WORD*)CRLF)))
+ {
+ dwMIMEPartSize-=4;
+ }else
+ if ((*((BYTE*)(lpszTemp-3))) == (*((BYTE*)LF)))
+ {
+ dwMIMEPartSize-=3;
+ }else {
+ DebugBreak();
+ }
+
+ if (plpszMIMEPart) (*plpszMIMEPart) = lpszMIMEPart;
+ if (pdwMIMEPartSize) (*pdwMIMEPartSize) = dwMIMEPartSize;
+ if (plpszCurMIMEPos) (*plpszCurMIMEPos) = lpszTemp;
+ dwRetErrorCode = NO_ERROR;
+ }
+ }else {
+ dwRetErrorCode = ERROR_NO_MORE_ITEMS;
+ }
+ }
+ }else {
+ dwRetErrorCode = ERROR_INVALID_HANDLE;
+ }
+return(dwRetErrorCode);
+}
+
+
+DWORD MraOfflineMessageGetHeaderValue(LPSTR lpszHeader, LPSTR lpszHeaderLow, size_t dwHeaderSize, LPSTR lpszValueName, size_t dwValueNameSize, LPSTR *plpszValue, size_t *pdwValueSize)
+{
+ DWORD dwRetErrorCode = ERROR_NOT_FOUND;
+ LPSTR lpszValue, lpszValueEnd;
+ size_t dwValueSize;
+
+ lpszValue = (LPSTR)MemoryFind(0, lpszHeaderLow, dwHeaderSize, lpszValueName, dwValueNameSize);
+ if (lpszValue)
+ {
+ lpszValue += dwValueNameSize;
+ lpszValueEnd = (LPSTR)MemoryFind((lpszValue-lpszHeaderLow), lpszHeaderLow, dwHeaderSize, CRLF, (sizeof(CRLF)-1));
+ if (lpszValueEnd == NULL) lpszValueEnd = (LPSTR)MemoryFind((lpszValue-lpszHeaderLow), lpszHeaderLow, dwHeaderSize, LF, (sizeof(LF)-1));
+ if (lpszValueEnd == NULL) lpszValueEnd = (LPSTR)(lpszHeaderLow+dwHeaderSize);
+
+ lpszValue = (LPSTR)MemoryFind((lpszValue-lpszHeaderLow), lpszHeaderLow, (lpszValueEnd-lpszHeaderLow), ":", 1);
+ if (lpszValue)
+ {
+ lpszValue++;
+ dwValueSize = (lpszValueEnd-lpszValue);
+ SkeepSPWSP((lpszHeader+(lpszValue-lpszHeaderLow)), dwValueSize, plpszValue, pdwValueSize);
+ dwRetErrorCode = NO_ERROR;
+ }
+ }
+return(dwRetErrorCode);
+}
+
+
+DWORD MraOfflineMessageGetHeaderValueLow(LPSTR lpszHeaderLow, size_t dwHeaderSize, LPSTR lpszValueName, size_t dwValueNameSize, LPSTR *plpszValue, size_t *pdwValueSize)
+{
+ DWORD dwRetErrorCode = ERROR_NOT_FOUND;
+ LPSTR lpszValue, lpszValueEnd;
+ size_t dwValueSize;
+
+ lpszValue = (LPSTR)MemoryFind(0, lpszHeaderLow, dwHeaderSize, lpszValueName, dwValueNameSize);
+ if (lpszValue)
+ {
+ lpszValue += dwValueNameSize;
+ lpszValueEnd = (LPSTR)MemoryFind((lpszValue-lpszHeaderLow), lpszHeaderLow, dwHeaderSize, CRLF, (sizeof(CRLF)-1));
+ if (lpszValueEnd == NULL) lpszValueEnd = (LPSTR)MemoryFind((lpszValue-lpszHeaderLow), lpszHeaderLow, dwHeaderSize, LF, (sizeof(LF)-1));
+ if (lpszValueEnd == NULL) lpszValueEnd = (LPSTR)(lpszHeaderLow+dwHeaderSize);
+
+ lpszValue = (LPSTR)MemoryFind((lpszValue-lpszHeaderLow), lpszHeaderLow, (lpszValueEnd-lpszHeaderLow), ":", 1);
+ if (lpszValue)
+ {
+ lpszValue++;
+ dwValueSize = (lpszValueEnd-lpszValue);
+ SkeepSPWSP(lpszValue, dwValueSize, plpszValue, pdwValueSize);
+ dwRetErrorCode = NO_ERROR;
+ }
+ }
+return(dwRetErrorCode);
+}
+
+
+DWORD MraOfflineMessageConvertTime(INTERNET_TIME *pitTime)
+{
+ SYSTEMTIME stTime, stUniversalTime;
+ TIME_ZONE_INFORMATION tziTimeZoneMailRu = {0}, tziTimeZoneLocal;
+
+ GetTimeZoneInformation(&tziTimeZoneLocal);
+ if (GetTimeZoneInformation(&tziTimeZoneMailRu) == TIME_ZONE_ID_DAYLIGHT) tziTimeZoneMailRu.DaylightBias *= 2;
+ tziTimeZoneMailRu.Bias = MAILRU_SERVER_TIME_ZONE;
+
+ //TzSpecificLocalTimeToSystemTime(&tziTimeZoneMailRu, &pitTime->stTime, &stUniversalTime);
+ {// for win 2000 compatible
+ tziTimeZoneMailRu.Bias = -tziTimeZoneMailRu.Bias;
+ tziTimeZoneMailRu.DaylightBias = -tziTimeZoneMailRu.DaylightBias;
+ SystemTimeToTzSpecificLocalTime(&tziTimeZoneMailRu, &pitTime->stTime, &stUniversalTime);
+ }//*/
+ SystemTimeToTzSpecificLocalTime(&tziTimeZoneLocal, &stUniversalTime, &stTime);
+
+return((DWORD)MakeTime32FromLocalSystemTime(&stTime));
+}