diff options
author | dartraiden <wowemuh@gmail.com> | 2023-01-14 01:30:59 +0300 |
---|---|---|
committer | dartraiden <wowemuh@gmail.com> | 2023-01-14 01:30:59 +0300 |
commit | de40f3be3f08487937525c2ef096dad665dda61d (patch) | |
tree | eb1205f8dca7c30b561a2776f9527072bd92eaf1 /protocols/YAMN/src/mails | |
parent | dd743899a769120ba2321230afddd6e4f1271872 (diff) |
Convert sources to CR+LF
Diffstat (limited to 'protocols/YAMN/src/mails')
-rw-r--r-- | protocols/YAMN/src/mails/decode.cpp | 1068 | ||||
-rw-r--r-- | protocols/YAMN/src/mails/mails.cpp | 946 | ||||
-rw-r--r-- | protocols/YAMN/src/mails/mime.cpp | 1390 |
3 files changed, 1702 insertions, 1702 deletions
diff --git a/protocols/YAMN/src/mails/decode.cpp b/protocols/YAMN/src/mails/decode.cpp index 414edfce60..7306376c2e 100644 --- a/protocols/YAMN/src/mails/decode.cpp +++ b/protocols/YAMN/src/mails/decode.cpp @@ -1,534 +1,534 @@ -/* - * This code implements decoding encoded MIME header in style - * =?iso-8859-2?Q? "User using email in central Europe characters such as =E9" ?= - * - * (c) majvan 2002-2004 - */ -#include "../stdafx.h" -//-------------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------------- - -struct _tcptable CodePageNamesAll[]= -{ - { "ANSI", "",TRUE,CP_ACP}, - { "WINDOWS-1", "250",0,1250}, - { "WINDOWS-1", "251",0,1251}, - { "WINDOWS-1", "252",0,1252}, - { "WINDOWS-1", "253",0,1253}, - { "WINDOWS-1", "254",0,1254}, - { "WINDOWS-1", "255",0,1255}, - { "WINDOWS-1", "256",0,1256}, - { "WINDOWS-1", "257",0,1257}, - { "WINDOWS-1", "258",0,1258}, - { "CP1", "250",0,1250}, - { "CP1", "251",0,1251}, - { "CP1", "252",0,1252}, - { "CP1", "253",0,1253}, - { "CP1", "254",0,1254}, - { "CP1", "255",0,1255}, - { "CP1", "256",0,1256}, - { "CP1", "257",0,1257}, - { "CP1", "258",0,1258}, - { "ANSI-1", "250",0,1250}, - { "ANSI-1", "251",0,1251}, - { "ANSI-1", "252",0,1252}, - { "ANSI-1", "253",0,1253}, - { "ANSI-1", "254",0,1254}, - { "ANSI-1", "255",0,1255}, - { "ANSI-1", "256",0,1256}, - { "ANSI-1", "257",0,1257}, - { "ANSI-1", "258",0,1258}, - { "KOI8", "-R",0,20866}, - { "KOI8", "",0,20866}, - { "KOI8", "-U",0,21866}, - { "KOI8", "-RU",0,21866}, - { "US-", "ASCII",0,20127}, - { "CP", "367",0,20127}, - { "ASCII", "",0,20127}, - { "ASCII", "7",0,20127}, - { "ISO-8859", "-1",0,28591}, - { "ISO-8859", "-2",0,28592}, - { "ISO-8859", "-3",0,28593}, - { "ISO-8859", "-4",0,28594}, - { "ISO-8859", "-5",0,28595}, - { "ISO-8859", "-6",0,28596}, - { "ISO-8859", "-7",0,28597}, - { "ISO-8859", "-8",0,28598}, - { "ISO-8859", "-9",0,28599}, - { "ISO-8859", "-15",0,28605}, - { "ISO_8859", "-1",0,28591}, - { "ISO_8859", "-2",0,28592}, - { "ISO_8859", "-3",0,28593}, - { "ISO_8859", "-4",0,28594}, - { "ISO_8859", "-5",0,28595}, - { "ISO_8859", "-6",0,28596}, - { "ISO_8859", "-7",0,28597}, - { "ISO_8859", "-8",0,28598}, - { "ISO_8859", "-9",0,28599}, - { "ISO_8859", "-15",0,28605}, - { "ISO-", "10646-USC2",0,1200}, - { "ISO-2022", "/2-JP",0,50220}, - { "ISO-2022", "-JP",0,50221}, - { "ISO-2022", "/JIS-JP",0,50222}, - { "ISO-2022", "-KR",0,50225}, - { "ISO-2022", "-CH(SP)",0,50227}, - { "ISO-2022", "-CH(TR)",0,50229}, - { "UTF-", "7",0,65000}, - { "UTF-", "8",0,65001}, - { "ARAB-", "TRANSPARENT",0,710}, - { "ASMO-", "TRANSPARENT",0,720}, - { "ASMO-", "449",0,709}, - { "ASMO-", "708",0,708}, - { "BIG5", "",0,950}, - { "EUC-", "CH(SP)",0,51936}, - { "EUC-", "CH(TR)",0,51950}, - { "EUC-", "JP",0,51932}, - { "EUC-", "KR",0,51949}, - { "GB-", "2312",0,20936}, - { "GB", "2312",0,20936}, - { "HZGB-", "2312",0,52936}, - { "IBM-", "037",0,37}, - { "IBM-", "290",0,290}, - { "IBM-", "437",0,437}, - { "IBM-", "500",0,500}, - { "IBM-", "775",0,775}, - { "IBM-", "850",0,850}, - { "IBM-", "852",0,852}, - { "IBM-", "855",0,855}, - { "IBM-", "857",0,857}, - { "IBM-", "860",0,860}, - { "IBM-", "861",0,861}, - { "IBM-", "862",0,862}, - { "IBM-", "863",0,863}, - { "IBM-", "864",0,864}, - { "IBM-", "865",0,865}, - { "IBM-", "866",0,866}, - { "IBM-", "869",0,869}, - { "IBM-", "870",0,870}, - { "IBM-", "875",0,875}, - { "IBM-", "1026",0,1026}, - { "IBM-", "273",0,20273}, - { "IBM-", "277",0,20277}, - { "IBM-", "278",0,20278}, - { "IBM-", "280",0,20280}, - { "IBM-", "284",0,20284}, - { "IBM-", "285",0,20285}, - { "IBM-", "290",0,20290}, - { "IBM-", "297",0,20297}, - { "IBM-", "420",0,20420}, - { "IBM-", "423",0,20423}, - { "IBM-", "871",0,20871}, - { "IBM-", "880",0,20880}, - { "IBM-", "905",0,20905}, - { "IBM-", "THAI",0,20838}, - { "ISCII-", "DEVANAGARI",0,57002}, - { "ISCII-", "BENGALI",0,57003}, - { "ISCII-", "TAMIL",0,57004}, - { "ISCII-", "TELUGU",0,57005}, - { "ISCII-", "ASSAMESE",0,57006}, - { "ISCII-", "ORIYA",0,57007}, - { "ISCII-", "KANNADA",0,57008}, - { "ISCII-", "MALAYALAM",0,57009}, - { "ISCII-", "GUJARATI",0,57010}, - { "ISCII-", "PUNJABI",0,57011}, - { "KOR-", "JOHAB",0,1361}, - { "KSC-", "5601",0,1361}, - { "MAC-", "ROMAN",0,10000}, - { "MAC-", "JP",0,10001}, - { "MAC-", "CH(SP)(BIG5)",0,10002}, - { "MAC-", "KR",0,10003}, - { "MAC-", "AR",0,10004}, - { "MAC-", "HW",0,10005}, - { "MAC-", "GR",0,10006}, - { "MAC-", "CY",0,10007}, - { "MAC-", "CH(SP)(GB2312)",0,10008}, - { "MAC-", "ROMANIA",0,10010}, - { "MAC-", "UA",0,10017}, - { "MAC-", "TH",0,10021}, - { "MAC-", "LAT2",0,10029}, - { "MAC-", "ICE",0,10079}, - { "MAC-", "TR",0,10081}, - { "MAC-", "CR",0,10082} -}; - -int CPLENALL = _countof(CodePageNamesAll); -struct _tcptable *CodePageNamesSupp; -int CPLENSUPP = 1; - -//Gets codepage ID from string representing charset such as "iso-8859-1" -// input- the string -// size- max length of input string -int GetCharsetFromString(char *input, size_t size); - -//HexValue to DecValue ('a' to 10) -// HexValue- hexa value ('a') -// DecValue- poiner where to store dec value -// returns 0 if not success -int FromHexa(char HexValue, char *DecValue); - -//Decodes a char from Base64 -// Base64Value- input char in Base64 -// DecValue- pointer where to store the result -// returns 0 if not success -int FromBase64(char Base64Value, char *DecValue); - -//Decodes string in quoted printable -// Src- input string -// Dst- where to store output string -// DstLen- how max long should be output string -// isQ- if is "Q-encoding" modification. should be TRUE in headers -// always returns 1 -int DecodeQuotedPrintable(char *Src, char *Dst, int DstLen, BOOL isQ); - -//Decodes string in base64 -// Src- input string -// Dst- where to store output string -// DstLen- how max long should be output string -// returns 0 if string was not properly decoded -int DecodeBase64(char *Src, char *Dst, int DstLen); - -//Converts string to unicode from string with specified codepage -// stream- input string -// cp- codepage of input string -// out- pointer to new allocated memory that contains unicode string -int ConvertStringToUnicode(char *stream, unsigned int cp, wchar_t **out); - -//Converts string from MIME header to unicode -// stream- input string -// cp- codepage of input string -// storeto- pointer to memory that contains unicode string -// mode- MIME_PLAIN or MIME_MAIL (MIME_MAIL deletes '"' from start and end of string) -void ConvertCodedStringToUnicode(char *stream, wchar_t **storeto, uint32_t cp, int mode); - -//-------------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------------- - -int GetCharsetFromString(char *input, size_t size) -//"ISO-8859-1" to ID from table -{ - char *pin = input; - char *pout, *parser; - - if ((size < 1) || (parser = pout = new char[size + 1]) == nullptr) - return -1; - while ((*pin != 0) && (pin - input < (INT_PTR)size)) { - if ((*pin >= 'a') && (*pin <= 'z')) - *parser++ = *(pin++) - ('a' - 'A'); // make it capital - //else if (*pin=='\"') // this is already done in ExtractFromContentType - // *pin++; //skip the quotes if any - else - *parser++ = *pin++; - } - - *parser = 0; - - #ifdef DEBUG_DECODECODEPAGE - DebugLog(DecodeFile, "<CodePage>%s</CodePage>", pout); - #endif - for (int i = 0; i < CPLENALL; i++) { - size_t len = mir_strlen(CodePageNamesAll[i].NameBase); - if (0 == strncmp(pout, CodePageNamesAll[i].NameBase, len)) { - if (0 == mir_strcmp(pout + len, CodePageNamesAll[i].NameSub)) { - delete[] pout; - return CodePageNamesAll[i].CP; - } - } - } - delete[] pout; - return -1; //not found -} - -int FromHexa(char HexValue, char *DecValue) -{ - if (HexValue >= '0' && HexValue <= '9') { - *DecValue = HexValue - '0'; - return 1; - } - if (HexValue >= 'A' && HexValue <= 'F') { - *DecValue = HexValue - 'A' + 10; - return 1; - } - if (HexValue >= 'a' && HexValue <= 'f') { - *DecValue = HexValue - 'a' + 10; - return 1; - } - return 0; -} - -int FromBase64(char Base64Value, char *DecValue) -{ - if (Base64Value >= 'A' && Base64Value <= 'Z') { - *DecValue = Base64Value - 'A'; - return 1; - } - if (Base64Value >= 'a' && Base64Value <= 'z') { - *DecValue = Base64Value - 'a' + 26; - return 1; - } - if (Base64Value >= '0' && Base64Value <= '9') { - *DecValue = Base64Value - '0' + 52; - return 1; - } - if (Base64Value == '+') { - *DecValue = Base64Value - '+' + 62; - return 1; - } - if (Base64Value == '/') { - *DecValue = Base64Value - '/' + 63; - return 1; - } - if (Base64Value == '=') { - *DecValue = 0; - return 1; - } - return 0; -} - -int DecodeQuotedPrintable(char *Src, char *Dst, int DstLen, BOOL isQ) -{ - #ifdef DEBUG_DECODEQUOTED - char *DstTemp = Dst; - DebugLog(DecodeFile, "<Decode Quoted><Input>%s</Input>", Src); - #endif - for (int Counter = 0; (*Src != 0) && DstLen && (Counter++ < DstLen); Src++, Dst++) - if (*Src == '=') { - if (!isQ) { - if (Src[1] == 0x0D) { - Src++; Src++; - if (Src[0] == 0x0A) Src++; - goto CopyCharQuotedPrintable; - } - if (Src[1] == 0x0A) { - Src++; Src++; - goto CopyCharQuotedPrintable; - } - } - char First, Second; - if (!FromHexa(*(++Src), &First)) { - *Dst++ = '='; Src--; - continue; - } - if (!FromHexa(*(++Src), &Second)) { - *Dst++ = '='; Src--; Src--; - continue; - } - *Dst = (char)(First) << 4; - *Dst += Second; - } - else if (isQ && *Src == '_') - *Dst = ' '; - else - CopyCharQuotedPrintable: // Yeah. Bad programming stile. - *Dst = *Src; - *Dst = 0; - #ifdef DEBUG_DECODEQUOTED - DebugLog(DecodeFile, "<Output>%s</Output></Decode Quoted>", DstTemp); - #endif - return 1; -} - -int DecodeBase64(char *Src, char *Dst, int DstLen) -{ - int Result = 0; - char Locator = 0, MiniResult[4]; - char *End = Dst + DstLen; - - MiniResult[0] = MiniResult[1] = MiniResult[2] = MiniResult[3] = 0; - - #ifdef DEBUG_DECODEBASE64 - char *DstTemp = Dst; - DebugLog(DecodeFile, "<Decode Base64><Input>\n%s\n</Input>\n", Src); - #endif - while (*Src != 0 && DstLen && Dst != End) { - if ((*Src == 0x0D) || (*Src == 0x0A)) { - Src++; - continue; - } - if ((!(Result = FromBase64(*Src, MiniResult + Locator)) && (*Src == 0)) || Locator++ == 3) //end_of_str || end_of_4_bytes - { - Locator = 0; //next write to the first byte - *Dst++ = (char)((MiniResult[0] << 2) | (MiniResult[1] >> 4)); - if (Dst == End) goto end; //DstLen exceeded? - *Dst++ = (char)((MiniResult[1] << 4) | (MiniResult[2] >> 2)); - if (Dst == End) goto end; //someones don't like goto, but not me - *Dst++ = (char)((MiniResult[2] << 6) | MiniResult[3]); - if (!Result && (*Src == 0)) goto end; //end of string? - MiniResult[0] = MiniResult[1] = MiniResult[2] = MiniResult[3] = 0; //zero 4byte buffer for next loop - } - if (!Result) return 0; //unrecognised character occured - Src++; - } -end: - *Dst = 0; - #ifdef DEBUG_DECODEBASE64 - DebugLog(DecodeFile, "<Output>\n%s\n</Output></Decode Base64>", DstTemp); - #endif - return 1; -} - - - -int ConvertStringToUnicode(char *stream, unsigned int cp, wchar_t **out) -{ - CPINFO CPInfo; - wchar_t *temp, *src = *out, *dest; - size_t outlen; - int streamlen, Index; - - //codepages, which require to have set 0 in dwFlags parameter when calling MultiByteToWideChar - uint32_t CodePagesZeroFlags[] = {50220, 50221, 50222, 50225, 50227, 50229, 52936, 54936, 57002, 57003, 57004, 57005, 57006, 57007, 57008, 57009, 57010, 57011, 65000, 65001}; - - if ((cp != CP_ACP) && (cp != CP_OEMCP) && (cp != CP_MACCP) && (cp != CP_THREAD_ACP) && (cp != CP_SYMBOL) && (cp != CP_UTF7) && (cp != CP_UTF8) && !GetCPInfo(cp, &CPInfo)) - cp = CP_ACP; - #ifdef DEBUG_DECODECODEPAGE - DebugLog(DecodeFile, "<CodePage #>%d</CodePage #>", cp); - #endif - - for (Index = 0; Index < sizeof(CodePagesZeroFlags) / sizeof(CodePagesZeroFlags[0]); Index++) - if (CodePagesZeroFlags[Index] == cp) { - Index = -1; - break; - } - if (Index == -1) - streamlen = MultiByteToWideChar(cp, 0, stream, -1, nullptr, 0); - else - streamlen = MultiByteToWideChar(cp, MB_USEGLYPHCHARS, stream, -1, nullptr, 0); - - if (*out != nullptr) - outlen = mir_wstrlen(*out); - else - outlen = 0; - temp = new wchar_t[streamlen + outlen + 1]; - - if (*out != nullptr) { - for (dest = temp; *src != (wchar_t)0; src++, dest++) //copy old string from *out to temp - *dest = *src; - // *dest++=L' '; //add space? - delete[] * out; - } - else - dest = temp; - *out = temp; - - if (Index == -1) { - if (!MultiByteToWideChar(cp, 0, stream, -1, dest, streamlen)) - return 0; - } - else { - if (!MultiByteToWideChar(cp, MB_USEGLYPHCHARS, stream, -1, dest, streamlen)) - return 0; - } - return 1; -} - -void ConvertCodedStringToUnicode(char *stream, wchar_t **storeto, uint32_t cp, int mode) -{ - char *start = stream, *finder, *finderend; - char Encoding = 0; - - if (stream == nullptr) - return; - - while (WS(start)) start++; - wchar_t *tempstore = nullptr; - if (!ConvertStringToUnicode(stream, cp, &tempstore))return; - - size_t tempstoreLength = mir_wstrlen(tempstore); - - size_t outind = 0; - while (*start != 0) { - if (CODES(start)) { - finder = start + 2; finderend = finder; - while (!CODED(finderend) && !EOS(finderend)) finderend++; - start = finderend; - if (CODED(finderend)) { - Encoding = *(finderend + 1); - switch (Encoding) { - case 'b': - case 'B': - case 'q': - case 'Q': - break; - default: - goto NotEncoded; - } - if (-1 == (cp = (uint32_t)GetCharsetFromString(finder, finderend - finder))) - cp = CP_ACP; - if (Encoding != 0) { - int size = 0, codeend; - char *pcodeend = nullptr; - - finder = finderend + 2; - if (CODED(finder)) - finder++; - while (WS(finder)) finder++; - finderend = finder; - while (!CODEE(finderend) && !EOS(finderend)) finderend++; - if (codeend = CODEE(finderend)) - pcodeend = finderend; - while (WS(finderend - 1)) finderend--; - if ((mode == MIME_MAIL) && (((*finder == '"') && (*(finderend - 1) == '"')))) { - finder++; - finderend--; - } - char *oneWordEncoded = new char[finderend - finder + 1]; - strncpy(oneWordEncoded, finder, finderend - finder); - oneWordEncoded[finderend - finder] = 0; - switch (Encoding) { - case 'b': - case 'B': - size = (finderend - finder) * 3 / 4 + 3 + 1 + 1; - break; - case 'q': - case 'Q': - size = finderend - finder + 1 + 1; - break; - } - - char *DecodedResult = new char[size + 1]; - switch (Encoding) { - case 'q': - case 'Q': - DecodeQuotedPrintable(oneWordEncoded, DecodedResult, size, TRUE); - break; - case 'b': - case 'B': - DecodeBase64(oneWordEncoded, DecodedResult, size); - break; - } - delete[] oneWordEncoded; - if (codeend) - finderend = pcodeend + 2; - if (WS(finderend)) //if string continues and there's some whitespace, add space to string that is to be converted - { - size_t len = mir_strlen(DecodedResult); - DecodedResult[len] = ' '; - DecodedResult[len + 1] = 0; - finderend++; - } - wchar_t *oneWord = nullptr; - if (ConvertStringToUnicode(DecodedResult, cp, &oneWord)) { - size_t len = mir_wstrlen(oneWord); - memcpy(&tempstore[outind], oneWord, len * sizeof(wchar_t)); - outind += len; - } - delete oneWord; - oneWord = nullptr; - delete[] DecodedResult; - start = finderend; - } - else if (!EOS(start)) start++; - } - else if (!EOS(start)) start++; - } - else { -NotEncoded: - tempstore[outind] = tempstore[start - stream]; - outind++; - if (outind > tempstoreLength) break; - start++; - } - } - tempstore[outind] = 0; - *storeto = tempstore; -} +/*
+ * This code implements decoding encoded MIME header in style
+ * =?iso-8859-2?Q? "User using email in central Europe characters such as =E9" ?=
+ *
+ * (c) majvan 2002-2004
+ */
+#include "../stdafx.h"
+//--------------------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------
+
+struct _tcptable CodePageNamesAll[]=
+{
+ { "ANSI", "",TRUE,CP_ACP},
+ { "WINDOWS-1", "250",0,1250},
+ { "WINDOWS-1", "251",0,1251},
+ { "WINDOWS-1", "252",0,1252},
+ { "WINDOWS-1", "253",0,1253},
+ { "WINDOWS-1", "254",0,1254},
+ { "WINDOWS-1", "255",0,1255},
+ { "WINDOWS-1", "256",0,1256},
+ { "WINDOWS-1", "257",0,1257},
+ { "WINDOWS-1", "258",0,1258},
+ { "CP1", "250",0,1250},
+ { "CP1", "251",0,1251},
+ { "CP1", "252",0,1252},
+ { "CP1", "253",0,1253},
+ { "CP1", "254",0,1254},
+ { "CP1", "255",0,1255},
+ { "CP1", "256",0,1256},
+ { "CP1", "257",0,1257},
+ { "CP1", "258",0,1258},
+ { "ANSI-1", "250",0,1250},
+ { "ANSI-1", "251",0,1251},
+ { "ANSI-1", "252",0,1252},
+ { "ANSI-1", "253",0,1253},
+ { "ANSI-1", "254",0,1254},
+ { "ANSI-1", "255",0,1255},
+ { "ANSI-1", "256",0,1256},
+ { "ANSI-1", "257",0,1257},
+ { "ANSI-1", "258",0,1258},
+ { "KOI8", "-R",0,20866},
+ { "KOI8", "",0,20866},
+ { "KOI8", "-U",0,21866},
+ { "KOI8", "-RU",0,21866},
+ { "US-", "ASCII",0,20127},
+ { "CP", "367",0,20127},
+ { "ASCII", "",0,20127},
+ { "ASCII", "7",0,20127},
+ { "ISO-8859", "-1",0,28591},
+ { "ISO-8859", "-2",0,28592},
+ { "ISO-8859", "-3",0,28593},
+ { "ISO-8859", "-4",0,28594},
+ { "ISO-8859", "-5",0,28595},
+ { "ISO-8859", "-6",0,28596},
+ { "ISO-8859", "-7",0,28597},
+ { "ISO-8859", "-8",0,28598},
+ { "ISO-8859", "-9",0,28599},
+ { "ISO-8859", "-15",0,28605},
+ { "ISO_8859", "-1",0,28591},
+ { "ISO_8859", "-2",0,28592},
+ { "ISO_8859", "-3",0,28593},
+ { "ISO_8859", "-4",0,28594},
+ { "ISO_8859", "-5",0,28595},
+ { "ISO_8859", "-6",0,28596},
+ { "ISO_8859", "-7",0,28597},
+ { "ISO_8859", "-8",0,28598},
+ { "ISO_8859", "-9",0,28599},
+ { "ISO_8859", "-15",0,28605},
+ { "ISO-", "10646-USC2",0,1200},
+ { "ISO-2022", "/2-JP",0,50220},
+ { "ISO-2022", "-JP",0,50221},
+ { "ISO-2022", "/JIS-JP",0,50222},
+ { "ISO-2022", "-KR",0,50225},
+ { "ISO-2022", "-CH(SP)",0,50227},
+ { "ISO-2022", "-CH(TR)",0,50229},
+ { "UTF-", "7",0,65000},
+ { "UTF-", "8",0,65001},
+ { "ARAB-", "TRANSPARENT",0,710},
+ { "ASMO-", "TRANSPARENT",0,720},
+ { "ASMO-", "449",0,709},
+ { "ASMO-", "708",0,708},
+ { "BIG5", "",0,950},
+ { "EUC-", "CH(SP)",0,51936},
+ { "EUC-", "CH(TR)",0,51950},
+ { "EUC-", "JP",0,51932},
+ { "EUC-", "KR",0,51949},
+ { "GB-", "2312",0,20936},
+ { "GB", "2312",0,20936},
+ { "HZGB-", "2312",0,52936},
+ { "IBM-", "037",0,37},
+ { "IBM-", "290",0,290},
+ { "IBM-", "437",0,437},
+ { "IBM-", "500",0,500},
+ { "IBM-", "775",0,775},
+ { "IBM-", "850",0,850},
+ { "IBM-", "852",0,852},
+ { "IBM-", "855",0,855},
+ { "IBM-", "857",0,857},
+ { "IBM-", "860",0,860},
+ { "IBM-", "861",0,861},
+ { "IBM-", "862",0,862},
+ { "IBM-", "863",0,863},
+ { "IBM-", "864",0,864},
+ { "IBM-", "865",0,865},
+ { "IBM-", "866",0,866},
+ { "IBM-", "869",0,869},
+ { "IBM-", "870",0,870},
+ { "IBM-", "875",0,875},
+ { "IBM-", "1026",0,1026},
+ { "IBM-", "273",0,20273},
+ { "IBM-", "277",0,20277},
+ { "IBM-", "278",0,20278},
+ { "IBM-", "280",0,20280},
+ { "IBM-", "284",0,20284},
+ { "IBM-", "285",0,20285},
+ { "IBM-", "290",0,20290},
+ { "IBM-", "297",0,20297},
+ { "IBM-", "420",0,20420},
+ { "IBM-", "423",0,20423},
+ { "IBM-", "871",0,20871},
+ { "IBM-", "880",0,20880},
+ { "IBM-", "905",0,20905},
+ { "IBM-", "THAI",0,20838},
+ { "ISCII-", "DEVANAGARI",0,57002},
+ { "ISCII-", "BENGALI",0,57003},
+ { "ISCII-", "TAMIL",0,57004},
+ { "ISCII-", "TELUGU",0,57005},
+ { "ISCII-", "ASSAMESE",0,57006},
+ { "ISCII-", "ORIYA",0,57007},
+ { "ISCII-", "KANNADA",0,57008},
+ { "ISCII-", "MALAYALAM",0,57009},
+ { "ISCII-", "GUJARATI",0,57010},
+ { "ISCII-", "PUNJABI",0,57011},
+ { "KOR-", "JOHAB",0,1361},
+ { "KSC-", "5601",0,1361},
+ { "MAC-", "ROMAN",0,10000},
+ { "MAC-", "JP",0,10001},
+ { "MAC-", "CH(SP)(BIG5)",0,10002},
+ { "MAC-", "KR",0,10003},
+ { "MAC-", "AR",0,10004},
+ { "MAC-", "HW",0,10005},
+ { "MAC-", "GR",0,10006},
+ { "MAC-", "CY",0,10007},
+ { "MAC-", "CH(SP)(GB2312)",0,10008},
+ { "MAC-", "ROMANIA",0,10010},
+ { "MAC-", "UA",0,10017},
+ { "MAC-", "TH",0,10021},
+ { "MAC-", "LAT2",0,10029},
+ { "MAC-", "ICE",0,10079},
+ { "MAC-", "TR",0,10081},
+ { "MAC-", "CR",0,10082}
+};
+
+int CPLENALL = _countof(CodePageNamesAll);
+struct _tcptable *CodePageNamesSupp;
+int CPLENSUPP = 1;
+
+//Gets codepage ID from string representing charset such as "iso-8859-1"
+// input- the string
+// size- max length of input string
+int GetCharsetFromString(char *input, size_t size);
+
+//HexValue to DecValue ('a' to 10)
+// HexValue- hexa value ('a')
+// DecValue- poiner where to store dec value
+// returns 0 if not success
+int FromHexa(char HexValue, char *DecValue);
+
+//Decodes a char from Base64
+// Base64Value- input char in Base64
+// DecValue- pointer where to store the result
+// returns 0 if not success
+int FromBase64(char Base64Value, char *DecValue);
+
+//Decodes string in quoted printable
+// Src- input string
+// Dst- where to store output string
+// DstLen- how max long should be output string
+// isQ- if is "Q-encoding" modification. should be TRUE in headers
+// always returns 1
+int DecodeQuotedPrintable(char *Src, char *Dst, int DstLen, BOOL isQ);
+
+//Decodes string in base64
+// Src- input string
+// Dst- where to store output string
+// DstLen- how max long should be output string
+// returns 0 if string was not properly decoded
+int DecodeBase64(char *Src, char *Dst, int DstLen);
+
+//Converts string to unicode from string with specified codepage
+// stream- input string
+// cp- codepage of input string
+// out- pointer to new allocated memory that contains unicode string
+int ConvertStringToUnicode(char *stream, unsigned int cp, wchar_t **out);
+
+//Converts string from MIME header to unicode
+// stream- input string
+// cp- codepage of input string
+// storeto- pointer to memory that contains unicode string
+// mode- MIME_PLAIN or MIME_MAIL (MIME_MAIL deletes '"' from start and end of string)
+void ConvertCodedStringToUnicode(char *stream, wchar_t **storeto, uint32_t cp, int mode);
+
+//--------------------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------
+
+int GetCharsetFromString(char *input, size_t size)
+//"ISO-8859-1" to ID from table
+{
+ char *pin = input;
+ char *pout, *parser;
+
+ if ((size < 1) || (parser = pout = new char[size + 1]) == nullptr)
+ return -1;
+ while ((*pin != 0) && (pin - input < (INT_PTR)size)) {
+ if ((*pin >= 'a') && (*pin <= 'z'))
+ *parser++ = *(pin++) - ('a' - 'A'); // make it capital
+ //else if (*pin=='\"') // this is already done in ExtractFromContentType
+ // *pin++; //skip the quotes if any
+ else
+ *parser++ = *pin++;
+ }
+
+ *parser = 0;
+
+ #ifdef DEBUG_DECODECODEPAGE
+ DebugLog(DecodeFile, "<CodePage>%s</CodePage>", pout);
+ #endif
+ for (int i = 0; i < CPLENALL; i++) {
+ size_t len = mir_strlen(CodePageNamesAll[i].NameBase);
+ if (0 == strncmp(pout, CodePageNamesAll[i].NameBase, len)) {
+ if (0 == mir_strcmp(pout + len, CodePageNamesAll[i].NameSub)) {
+ delete[] pout;
+ return CodePageNamesAll[i].CP;
+ }
+ }
+ }
+ delete[] pout;
+ return -1; //not found
+}
+
+int FromHexa(char HexValue, char *DecValue)
+{
+ if (HexValue >= '0' && HexValue <= '9') {
+ *DecValue = HexValue - '0';
+ return 1;
+ }
+ if (HexValue >= 'A' && HexValue <= 'F') {
+ *DecValue = HexValue - 'A' + 10;
+ return 1;
+ }
+ if (HexValue >= 'a' && HexValue <= 'f') {
+ *DecValue = HexValue - 'a' + 10;
+ return 1;
+ }
+ return 0;
+}
+
+int FromBase64(char Base64Value, char *DecValue)
+{
+ if (Base64Value >= 'A' && Base64Value <= 'Z') {
+ *DecValue = Base64Value - 'A';
+ return 1;
+ }
+ if (Base64Value >= 'a' && Base64Value <= 'z') {
+ *DecValue = Base64Value - 'a' + 26;
+ return 1;
+ }
+ if (Base64Value >= '0' && Base64Value <= '9') {
+ *DecValue = Base64Value - '0' + 52;
+ return 1;
+ }
+ if (Base64Value == '+') {
+ *DecValue = Base64Value - '+' + 62;
+ return 1;
+ }
+ if (Base64Value == '/') {
+ *DecValue = Base64Value - '/' + 63;
+ return 1;
+ }
+ if (Base64Value == '=') {
+ *DecValue = 0;
+ return 1;
+ }
+ return 0;
+}
+
+int DecodeQuotedPrintable(char *Src, char *Dst, int DstLen, BOOL isQ)
+{
+ #ifdef DEBUG_DECODEQUOTED
+ char *DstTemp = Dst;
+ DebugLog(DecodeFile, "<Decode Quoted><Input>%s</Input>", Src);
+ #endif
+ for (int Counter = 0; (*Src != 0) && DstLen && (Counter++ < DstLen); Src++, Dst++)
+ if (*Src == '=') {
+ if (!isQ) {
+ if (Src[1] == 0x0D) {
+ Src++; Src++;
+ if (Src[0] == 0x0A) Src++;
+ goto CopyCharQuotedPrintable;
+ }
+ if (Src[1] == 0x0A) {
+ Src++; Src++;
+ goto CopyCharQuotedPrintable;
+ }
+ }
+ char First, Second;
+ if (!FromHexa(*(++Src), &First)) {
+ *Dst++ = '='; Src--;
+ continue;
+ }
+ if (!FromHexa(*(++Src), &Second)) {
+ *Dst++ = '='; Src--; Src--;
+ continue;
+ }
+ *Dst = (char)(First) << 4;
+ *Dst += Second;
+ }
+ else if (isQ && *Src == '_')
+ *Dst = ' ';
+ else
+ CopyCharQuotedPrintable: // Yeah. Bad programming stile.
+ *Dst = *Src;
+ *Dst = 0;
+ #ifdef DEBUG_DECODEQUOTED
+ DebugLog(DecodeFile, "<Output>%s</Output></Decode Quoted>", DstTemp);
+ #endif
+ return 1;
+}
+
+int DecodeBase64(char *Src, char *Dst, int DstLen)
+{
+ int Result = 0;
+ char Locator = 0, MiniResult[4];
+ char *End = Dst + DstLen;
+
+ MiniResult[0] = MiniResult[1] = MiniResult[2] = MiniResult[3] = 0;
+
+ #ifdef DEBUG_DECODEBASE64
+ char *DstTemp = Dst;
+ DebugLog(DecodeFile, "<Decode Base64><Input>\n%s\n</Input>\n", Src);
+ #endif
+ while (*Src != 0 && DstLen && Dst != End) {
+ if ((*Src == 0x0D) || (*Src == 0x0A)) {
+ Src++;
+ continue;
+ }
+ if ((!(Result = FromBase64(*Src, MiniResult + Locator)) && (*Src == 0)) || Locator++ == 3) //end_of_str || end_of_4_bytes
+ {
+ Locator = 0; //next write to the first byte
+ *Dst++ = (char)((MiniResult[0] << 2) | (MiniResult[1] >> 4));
+ if (Dst == End) goto end; //DstLen exceeded?
+ *Dst++ = (char)((MiniResult[1] << 4) | (MiniResult[2] >> 2));
+ if (Dst == End) goto end; //someones don't like goto, but not me
+ *Dst++ = (char)((MiniResult[2] << 6) | MiniResult[3]);
+ if (!Result && (*Src == 0)) goto end; //end of string?
+ MiniResult[0] = MiniResult[1] = MiniResult[2] = MiniResult[3] = 0; //zero 4byte buffer for next loop
+ }
+ if (!Result) return 0; //unrecognised character occured
+ Src++;
+ }
+end:
+ *Dst = 0;
+ #ifdef DEBUG_DECODEBASE64
+ DebugLog(DecodeFile, "<Output>\n%s\n</Output></Decode Base64>", DstTemp);
+ #endif
+ return 1;
+}
+
+
+
+int ConvertStringToUnicode(char *stream, unsigned int cp, wchar_t **out)
+{
+ CPINFO CPInfo;
+ wchar_t *temp, *src = *out, *dest;
+ size_t outlen;
+ int streamlen, Index;
+
+ //codepages, which require to have set 0 in dwFlags parameter when calling MultiByteToWideChar
+ uint32_t CodePagesZeroFlags[] = {50220, 50221, 50222, 50225, 50227, 50229, 52936, 54936, 57002, 57003, 57004, 57005, 57006, 57007, 57008, 57009, 57010, 57011, 65000, 65001};
+
+ if ((cp != CP_ACP) && (cp != CP_OEMCP) && (cp != CP_MACCP) && (cp != CP_THREAD_ACP) && (cp != CP_SYMBOL) && (cp != CP_UTF7) && (cp != CP_UTF8) && !GetCPInfo(cp, &CPInfo))
+ cp = CP_ACP;
+ #ifdef DEBUG_DECODECODEPAGE
+ DebugLog(DecodeFile, "<CodePage #>%d</CodePage #>", cp);
+ #endif
+
+ for (Index = 0; Index < sizeof(CodePagesZeroFlags) / sizeof(CodePagesZeroFlags[0]); Index++)
+ if (CodePagesZeroFlags[Index] == cp) {
+ Index = -1;
+ break;
+ }
+ if (Index == -1)
+ streamlen = MultiByteToWideChar(cp, 0, stream, -1, nullptr, 0);
+ else
+ streamlen = MultiByteToWideChar(cp, MB_USEGLYPHCHARS, stream, -1, nullptr, 0);
+
+ if (*out != nullptr)
+ outlen = mir_wstrlen(*out);
+ else
+ outlen = 0;
+ temp = new wchar_t[streamlen + outlen + 1];
+
+ if (*out != nullptr) {
+ for (dest = temp; *src != (wchar_t)0; src++, dest++) //copy old string from *out to temp
+ *dest = *src;
+ // *dest++=L' '; //add space?
+ delete[] * out;
+ }
+ else
+ dest = temp;
+ *out = temp;
+
+ if (Index == -1) {
+ if (!MultiByteToWideChar(cp, 0, stream, -1, dest, streamlen))
+ return 0;
+ }
+ else {
+ if (!MultiByteToWideChar(cp, MB_USEGLYPHCHARS, stream, -1, dest, streamlen))
+ return 0;
+ }
+ return 1;
+}
+
+void ConvertCodedStringToUnicode(char *stream, wchar_t **storeto, uint32_t cp, int mode)
+{
+ char *start = stream, *finder, *finderend;
+ char Encoding = 0;
+
+ if (stream == nullptr)
+ return;
+
+ while (WS(start)) start++;
+ wchar_t *tempstore = nullptr;
+ if (!ConvertStringToUnicode(stream, cp, &tempstore))return;
+
+ size_t tempstoreLength = mir_wstrlen(tempstore);
+
+ size_t outind = 0;
+ while (*start != 0) {
+ if (CODES(start)) {
+ finder = start + 2; finderend = finder;
+ while (!CODED(finderend) && !EOS(finderend)) finderend++;
+ start = finderend;
+ if (CODED(finderend)) {
+ Encoding = *(finderend + 1);
+ switch (Encoding) {
+ case 'b':
+ case 'B':
+ case 'q':
+ case 'Q':
+ break;
+ default:
+ goto NotEncoded;
+ }
+ if (-1 == (cp = (uint32_t)GetCharsetFromString(finder, finderend - finder)))
+ cp = CP_ACP;
+ if (Encoding != 0) {
+ int size = 0, codeend;
+ char *pcodeend = nullptr;
+
+ finder = finderend + 2;
+ if (CODED(finder))
+ finder++;
+ while (WS(finder)) finder++;
+ finderend = finder;
+ while (!CODEE(finderend) && !EOS(finderend)) finderend++;
+ if (codeend = CODEE(finderend))
+ pcodeend = finderend;
+ while (WS(finderend - 1)) finderend--;
+ if ((mode == MIME_MAIL) && (((*finder == '"') && (*(finderend - 1) == '"')))) {
+ finder++;
+ finderend--;
+ }
+ char *oneWordEncoded = new char[finderend - finder + 1];
+ strncpy(oneWordEncoded, finder, finderend - finder);
+ oneWordEncoded[finderend - finder] = 0;
+ switch (Encoding) {
+ case 'b':
+ case 'B':
+ size = (finderend - finder) * 3 / 4 + 3 + 1 + 1;
+ break;
+ case 'q':
+ case 'Q':
+ size = finderend - finder + 1 + 1;
+ break;
+ }
+
+ char *DecodedResult = new char[size + 1];
+ switch (Encoding) {
+ case 'q':
+ case 'Q':
+ DecodeQuotedPrintable(oneWordEncoded, DecodedResult, size, TRUE);
+ break;
+ case 'b':
+ case 'B':
+ DecodeBase64(oneWordEncoded, DecodedResult, size);
+ break;
+ }
+ delete[] oneWordEncoded;
+ if (codeend)
+ finderend = pcodeend + 2;
+ if (WS(finderend)) //if string continues and there's some whitespace, add space to string that is to be converted
+ {
+ size_t len = mir_strlen(DecodedResult);
+ DecodedResult[len] = ' ';
+ DecodedResult[len + 1] = 0;
+ finderend++;
+ }
+ wchar_t *oneWord = nullptr;
+ if (ConvertStringToUnicode(DecodedResult, cp, &oneWord)) {
+ size_t len = mir_wstrlen(oneWord);
+ memcpy(&tempstore[outind], oneWord, len * sizeof(wchar_t));
+ outind += len;
+ }
+ delete oneWord;
+ oneWord = nullptr;
+ delete[] DecodedResult;
+ start = finderend;
+ }
+ else if (!EOS(start)) start++;
+ }
+ else if (!EOS(start)) start++;
+ }
+ else {
+NotEncoded:
+ tempstore[outind] = tempstore[start - stream];
+ outind++;
+ if (outind > tempstoreLength) break;
+ start++;
+ }
+ }
+ tempstore[outind] = 0;
+ *storeto = tempstore;
+}
diff --git a/protocols/YAMN/src/mails/mails.cpp b/protocols/YAMN/src/mails/mails.cpp index 168c6c9397..1385cb649d 100644 --- a/protocols/YAMN/src/mails/mails.cpp +++ b/protocols/YAMN/src/mails/mails.cpp @@ -1,473 +1,473 @@ -/* - * This code implements retrieving info from MIME header - * - * (c) majvan 2002-2004 - */ - -#include "../stdafx.h" - - //-------------------------------------------------------------------------------------------------- - //-------------------------------------------------------------------------------------------------- - - // SMALL INTRO - // Mails are queued in a queue (chained list). Pointer to first mail is pointed from Account structure - // member called Mails. - // Mail queue is ended with NULL- pointered mail (NULL handle) - - //Creates new mail for plugin (calling plugin's constructor, when plugin imported to YAMN) -INT_PTR CreateAccountMailSvc(WPARAM wParam, LPARAM lParam); - -//Deletes mail for plugin (calling plugin's destructor, when plugin imported to YAMN) -INT_PTR DeleteAccountMailSvc(WPARAM wParam, LPARAM lParam); - -//Loads mail data from standard storage to memory -INT_PTR LoadMailDataSvc(WPARAM wParam, LPARAM lParam); - -//Deletes mail data from memory -INT_PTR UnloadMailDataSvc(WPARAM wParam, LPARAM); - -//Saves mail data from memory to standard storage -INT_PTR SaveMailDataSvc(WPARAM wParam, LPARAM lParam); - -//Appends second MIME mail queue to the first one -//Only finds the end of first queue and its Next memember repoints to second one -void WINAPI AppendQueueFcn(HYAMNMAIL first, HYAMNMAIL second); - -//Synchronizes two accounts -//Function finds, if there were some mails deleted from mailbox and deletes (depends on RemovedOld param) them from OldQueue -//Next finds, if there are new mails. Mails that are still on mailbox are deleted (depends on RemovedNew param) from NewQueue -//After this, OldQueue is pointer to mails that are on mailbox, but not new mails -//and NewQueue contains new mails in account -//New accounts can be then appended to account mails queue, but they have set the New flag -// -//Two mails equals if they have the same ID -// -// hPlugin- handle of plugin going to delete mails -// OldQueue- queue of mails that we found on mailbox last time, after function finishes queue contains all mails except new ones -// RemovedOld- queue of mails where to store removed mails from OldQueue, if NULL deletes mails from OldQueue -// NewQueue- queue of mails that we found on mailbox (all mails), after function finishes queue contains only new mails -// RemovedNew- queue of mails where to store removed mails from NewQueue, if NULL deletes mails from NewQueue -//So function works like: -//1. delete (or move to RemovedOld queue if RemovedOld is not NULL) all mails from OldQueue not found in NewQueue -//2. delete (or move to RemovedNew queue if RemovedNew is not NULL) all mails from NewQueue found in OldQueue -void WINAPI SynchroMessagesFcn(CAccount *Account, HYAMNMAIL *OldQueue, HYAMNMAIL *RemovedOld, HYAMNMAIL *NewQueue, HYAMNMAIL *RemovedNew); - -//Deletes messages from mail From to the end -// Account- account who owns mails -// From- first mail in queue, which is going to delete -void WINAPI DeleteMessagesToEndFcn(CAccount *Account, HYAMNMAIL From); - -//Removes message from queue, does not delete from memory -// From- queue pointer -// Which- mail to delete -// mode- nonzero if you want to decrement numbers in messages that are bigger than the one in Which mail, 0 if not -void WINAPI DeleteMessageFromQueueFcn(HYAMNMAIL *From, HYAMNMAIL Which, int mode); - -//Finds message in queue that has the same ID number -// From- message queue -// ID- pointer to ID -// returns pointer to found message, NULL if not found -HYAMNMAIL WINAPI FindMessageByIDFcn(HYAMNMAIL From, char *ID); - -//Translate header from text to queue of CMimeItem structures -//This means that new queue will contain all info about headers -// stream- pointer to text containing header (can be ended with zero) -// len- length of stream -// head- function fills this pointer to first header item in queue -void WINAPI TranslateHeaderFcn(char *stream, int len, struct CMimeItem **head); - -//Creates new mail queue, copying only these mails, that have set flag for deleting -// From- message queue, whose mail with given flag are duplicated -// returns new mail queue (or NULL when no mail with flag is in From queue) -//Function does not copy the whole mails, it copies only ID string. And ID is copied as string, so -//you can use this fcn only if you have your ID as pointer to char string ended with zero character -HYAMNMAIL WINAPI CreateNewDeleteQueueFcn(HYAMNMAIL From); - -//Sets/removes flags from specific mails -// From- pointer to first message -// FlagsSet- mail must have set these flags... -// FlagsNotSet- ...and must not have set these flags... -// FlagsToSetRemove- ...to set/remove these flags (see mode) -// mode- nonzero to set, else remove -void WINAPI SetRemoveFlagsInQueueFcn(HYAMNMAIL From, uint32_t FlagsSet, uint32_t FlagsNotSet, uint32_t FlagsToSetRemove, int mode); - -struct CExportedFunctions MailExportedFcn[] = -{ - {YAMN_SYNCHROMIMEMSGSID, (void *)SynchroMessagesFcn}, - {YAMN_TRANSLATEHEADERID, (void *)TranslateHeaderFcn}, - {YAMN_APPENDQUEUEID, (void *)AppendQueueFcn}, - {YAMN_DELETEMIMEQUEUEID, (void *)DeleteMessagesToEndFcn}, - {YAMN_DELETEMIMEMESSAGEID, (void *)DeleteMessageFromQueueFcn}, - {YAMN_FINDMIMEMESSAGEID, (void *)FindMessageByIDFcn}, - {YAMN_CREATENEWDELETEQUEUEID, (void *)CreateNewDeleteQueueFcn}, - {YAMN_SETREMOVEQUEUEFLAGSID, (void *)SetRemoveFlagsInQueueFcn}, -}; - -struct CExportedServices MailExportedSvc[] = -{ - {MS_YAMN_CREATEACCOUNTMAIL, CreateAccountMailSvc}, - {MS_YAMN_DELETEACCOUNTMAIL, DeleteAccountMailSvc}, - {MS_YAMN_LOADMAILDATA, LoadMailDataSvc}, - {MS_YAMN_UNLOADMAILDATA, UnloadMailDataSvc}, - {MS_YAMN_SAVEMAILDATA, SaveMailDataSvc}, -}; - - -//-------------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------------- - -INT_PTR CreateAccountMailSvc(WPARAM wParam, LPARAM lParam) -{ - CAccount *Account = (CAccount *)wParam; - uint32_t MailVersion = (uint32_t)lParam; - HYAMNMAIL NewMail; - - //test if we are going to initialize members of suitable structure (structures of plugin and YAMN must match) - if (MailVersion != YAMN_MAILVERSION) - return NULL; - - if (Account->Plugin != nullptr) { - if (Account->Plugin->MailFcn->NewMailFcnPtr != nullptr) { - //Let plugin create its own structure, which can be derived from CAccount structure - if (nullptr == (NewMail = Account->Plugin->MailFcn->NewMailFcnPtr(Account, YAMN_MAILVERSION))) - return NULL; - } - else { - //We suggest plugin uses standard CAccount structure, so we create it - if (nullptr == (NewMail = new YAMNMAIL)) - //If not created successfully - return NULL; - NewMail->MailData = nullptr; - } - //Init every members of structure, used by YAMN - return (INT_PTR)NewMail; - } - return NULL; -} - -INT_PTR DeleteAccountMailSvc(WPARAM wParam, LPARAM lParam) -{ - HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam; - HYAMNMAIL OldMail = (HYAMNMAIL)lParam; - struct CMimeItem *TH; - - if (Plugin->MailFcn != nullptr) { - if (Plugin->MailFcn->DeleteMailFcnPtr != nullptr) { - //Let plugin delete its own CMimeMsgQueue derived structure - Plugin->MailFcn->DeleteMailFcnPtr(OldMail); - return 1; - } - } - if (OldMail->MailData != nullptr) { - if (OldMail->MailData->Body != nullptr) - delete[] OldMail->MailData->Body; - if ((TH = OldMail->MailData->TranslatedHeader) != nullptr) - for (; OldMail->MailData->TranslatedHeader != nullptr;) { - TH = TH->Next; - if (OldMail->MailData->TranslatedHeader->name != nullptr) - delete[] OldMail->MailData->TranslatedHeader->name; - if (OldMail->MailData->TranslatedHeader->value != nullptr) - delete[] OldMail->MailData->TranslatedHeader->value; - delete OldMail->MailData->TranslatedHeader; - OldMail->MailData->TranslatedHeader = TH; - } - delete OldMail->MailData; - } - if (OldMail->ID != nullptr) - delete[] OldMail->ID; - - delete OldMail; //consider mail as standard HYAMNMAIL, not initialized before and use its own destructor - return 1; -} - - -void WINAPI AppendQueueFcn(HYAMNMAIL first, HYAMNMAIL second) -{ - HYAMNMAIL Finder = first; - while (Finder->Next != nullptr) Finder = Finder->Next; - Finder->Next = second; -} - -INT_PTR LoadMailDataSvc(WPARAM wParam, LPARAM lParam) -{ - HYAMNMAIL Mail = (HYAMNMAIL)wParam; - uint32_t MailVersion = (uint32_t)lParam; - - if (MailVersion != YAMN_MAILDATAVERSION) - return NULL; - - // now we have all data to memory persisting, so no loading is needed - return (INT_PTR)Mail->MailData; -} - -INT_PTR UnloadMailDataSvc(WPARAM, LPARAM) -{ - return 1; -} - -INT_PTR SaveMailDataSvc(WPARAM, LPARAM lParam) -{ - uint32_t MailVersion = (uint32_t)lParam; - - if (MailVersion != YAMN_MAILDATAVERSION) - return (INT_PTR)-1; - - // now we have all data to memory persisting, so no saving is needed - return (INT_PTR)0; -} - -void WINAPI SynchroMessagesFcn(CAccount *Account, HYAMNMAIL *OldQueue, HYAMNMAIL *RemovedOld, HYAMNMAIL *NewQueue, HYAMNMAIL *RemovedNew) -//deletes messages from new queue, if they are old -//it also deletes messages from old queue, if they are not in mailbox anymore -//"YAMN_MSG_DELETED" messages in old queue remain in old queue (are never removed, although they are not in new queue) -//"YAMN_MSG_DELETED" messages in new queue remain in new queue (are never removed, although they can be in old queue) -{ - HYAMNMAIL Finder, FinderPrev; - HYAMNMAIL Parser, ParserPrev; - HYAMNMAIL RemovedOldParser = nullptr; - HYAMNMAIL RemovedNewParser = nullptr; - if (RemovedOld != nullptr) *RemovedOld = nullptr; - if (RemovedNew != nullptr) *RemovedNew = nullptr; - - for (FinderPrev = nullptr, Finder = *OldQueue; Finder != nullptr;) { - if (Finder->Flags & YAMN_MSG_DELETED) //if old queue contains deleted mail - { - FinderPrev = Finder; - Finder = Finder->Next; //get next message in old queue for testing - continue; - } - for (ParserPrev = nullptr, Parser = *NewQueue; Parser != nullptr; ParserPrev = Parser, Parser = Parser->Next) { - if (Parser->Flags & YAMN_MSG_DELETED) - continue; - - if (Parser->ID == nullptr) //simply ignore the message, that has not filled its ID - continue; - - if (0 == mir_strcmp(Parser->ID, Finder->ID)) //search for equal message in new queue - break; - } - if (Parser != nullptr) //found equal message in new queue - { - if (Parser == *NewQueue) - *NewQueue = (*NewQueue)->Next; - else - ParserPrev->Next = Parser->Next; - Finder->Number = Parser->Number; //rewrite the number of current message in old queue - - if (RemovedNew == nullptr) //delete from new queue - DeleteAccountMailSvc((WPARAM)Account->Plugin, (LPARAM)Parser); - else //or move to RemovedNew - { - if (RemovedNewParser == nullptr) //if it is first mail removed from NewQueue - *RemovedNew = Parser; //set RemovedNew queue to point to first message in removed queue - else - RemovedNewParser->Next = Parser; //else don't forget to show to next message in RemovedNew queue - RemovedNewParser = Parser; //follow RemovedNew queue - RemovedNewParser->Next = nullptr; - } - FinderPrev = Finder; - Finder = Finder->Next; //get next message in old queue for testing - } - else //a message was already deleted from mailbox - { - if (Finder == *OldQueue) //if we are at the first item in OldQueue - { - *OldQueue = (*OldQueue)->Next; //set OldQueue to next item - if (RemovedOld == nullptr) //delete from old queue - DeleteAccountMailSvc((WPARAM)Account->Plugin, (LPARAM)Finder); - else //or move to RemovedOld - { - if (RemovedOldParser == nullptr) //if it is first mail removed from OldQueue - *RemovedOld = Finder; //set RemovedOld queue to point to first message in removed queue - else - RemovedOldParser->Next = Finder; //else don't forget to show to next message in RemovedNew queue - RemovedOldParser = Finder; //follow RemovedOld queue - RemovedOldParser->Next = nullptr; - } - Finder = *OldQueue; - } - else { - FinderPrev->Next = Finder->Next; - if (RemovedOld == nullptr) //delete from old queue - DeleteAccountMailSvc((WPARAM)Account->Plugin, (LPARAM)Finder); - else //or move to RemovedOld - { - if (RemovedOldParser == nullptr) //if it is first mail removed from OldQueue - *RemovedOld = Finder; //set RemovedOld queue to point to first message in removed queue - else - RemovedOldParser->Next = Finder; //else don't forget to show to next message in RemovedNew queue - RemovedOldParser = Finder; //follow RemovedOld queue - RemovedOldParser->Next = nullptr; - } - Finder = FinderPrev->Next; - } - } - } -} - -void WINAPI DeleteMessagesToEndFcn(CAccount *Account, HYAMNMAIL From) -{ - HYAMNMAIL Temp; - while (From != nullptr) { - Temp = From; - From = From->Next; - DeleteAccountMailSvc((WPARAM)Account->Plugin, (LPARAM)Temp); - } -} - -void WINAPI DeleteMessageFromQueueFcn(HYAMNMAIL *From, HYAMNMAIL Which, int mode = 0) -{ - uint32_t Number = Which->Number; - HYAMNMAIL Parser; - - if (*From == Which) { - Parser = Which->Next; - *From = Parser; - } - else { - for (Parser = *From; Which != Parser->Next; Parser = Parser->Next) - if (mode && (Parser->Number > Number)) Parser->Number--; - if (mode && (Parser->Number > Number)) Parser->Number--; - Parser->Next = Parser->Next->Next; - Parser = Which->Next; - } - if (mode) - for (; Parser != nullptr; Parser = Parser->Next) - if (Parser->Number > Number) Parser->Number--; -} - -void DeleteMessagesFromQueue(HYAMNMAIL *From, HYAMNMAIL Which, int mode = 0) -{ - HYAMNMAIL Parser; - - for (Parser = Which; Parser != nullptr; Parser = Parser->Next) - DeleteMessageFromQueueFcn(From, Parser, mode); -} - -HYAMNMAIL WINAPI FindMessageByIDFcn(HYAMNMAIL From, char *ID) -{ - HYAMNMAIL Browser; - - for (Browser = From; Browser != nullptr; Browser = Browser->Next) - if (0 == mir_strcmp(Browser->ID, ID)) - break; - return Browser; -} - -void WINAPI TranslateHeaderFcn(char *stream, int len, struct CMimeItem **head) -{ - try { - char *finder = stream; - char *prev1, *prev2, *prev3; - struct CMimeItem *Item = nullptr; - - while (finder <= (stream + len)) { - while (ENDLINEWS(finder)) finder++; - - //at the start of line - if (DOTLINE(finder + 1)) //at the end of stream - break; - - prev1 = finder; - - while (*finder != ':' && !EOS(finder)) finder++; - if (!EOS(finder)) - prev2 = finder++; - else - break; - - while (WS(finder) && !EOS(finder)) finder++; - if (!EOS(finder)) - prev3 = finder; - else - break; - - do { - if (ENDLINEWS(finder)) finder += 2; //after endline information continues - while (!ENDLINE(finder) && !EOS(finder)) finder++; - } while (ENDLINEWS(finder)); - - if (Item != nullptr) { - if (nullptr == (Item->Next = new struct CMimeItem)) - break; - Item = Item->Next; - } - else { - Item = new CMimeItem; - *head = Item; - } - - Item->Next = nullptr; - Item->name = new char[prev2 - prev1 + 1]; - mir_strncpy(Item->name, prev1, prev2 - prev1 + 1); - Item->value = new char[finder - prev3 + 1]; - mir_strncpy(Item->value, prev3, finder - prev3 + 1); - - if (EOS(finder)) - break; - finder++; - if (ENDLINE(finder)) { - finder++; - if (ENDLINE(finder)) { - // end of headers. message body begins - finder++; - if (ENDLINE(finder))finder++; - prev1 = finder; - while (!DOTLINE(finder + 1))finder++; - if (ENDLINE(finder))finder--; - prev2 = finder; - if (prev2 > prev1) { // yes, we have body - if (nullptr == (Item->Next = new struct CMimeItem)) break; // Cant create new item?! - Item = Item->Next; - Item->Next = nullptr;//just in case; - Item->name = new char[5]; strncpy(Item->name, "Body", 5); - Item->value = new char[prev2 - prev1]; - mir_strncpy(Item->value, prev1, prev2 - prev1 - 1); - } - break; // there is nothing else - } - } - } - } - catch (...) { - MessageBoxA(nullptr, "Translate header error", "", 0); - } -} - -HYAMNMAIL WINAPI CreateNewDeleteQueueFcn(HYAMNMAIL From) -{ - HYAMNMAIL FirstMail, Browser = nullptr; - - for (FirstMail = nullptr; From != nullptr; From = From->Next) { - if ((From->Flags & (YAMN_MSG_USERDELETE | YAMN_MSG_AUTODELETE)) && !(From->Flags & YAMN_MSG_DELETED)) { - if (FirstMail == nullptr) { - FirstMail = Browser = new YAMNMAIL; - if (FirstMail == nullptr) - break; - } - else { - Browser->Next = new YAMNMAIL; - Browser = Browser->Next; - } - Browser->ID = new char[mir_strlen(From->ID) + 1]; - mir_strcpy(Browser->ID, From->ID); - Browser->Number = From->Number; - Browser->Flags = From->Flags; - } - } - return FirstMail; -} - -void WINAPI SetRemoveFlagsInQueueFcn(HYAMNMAIL From, uint32_t FlagsSet, uint32_t FlagsNotSet, uint32_t FlagsToSetRemove, int mode) -{ - HYAMNMAIL msgq; - - for (msgq = (HYAMNMAIL)From; msgq != nullptr; msgq = msgq->Next) { - if ((FlagsSet == (msgq->Flags & FlagsSet)) && (0 == (msgq->Flags & FlagsNotSet))) { - if (mode) - msgq->Flags = msgq->Flags | FlagsToSetRemove; - else - msgq->Flags = msgq->Flags & ~FlagsToSetRemove; - } - } -} +/*
+ * This code implements retrieving info from MIME header
+ *
+ * (c) majvan 2002-2004
+ */
+
+#include "../stdafx.h"
+
+ //--------------------------------------------------------------------------------------------------
+ //--------------------------------------------------------------------------------------------------
+
+ // SMALL INTRO
+ // Mails are queued in a queue (chained list). Pointer to first mail is pointed from Account structure
+ // member called Mails.
+ // Mail queue is ended with NULL- pointered mail (NULL handle)
+
+ //Creates new mail for plugin (calling plugin's constructor, when plugin imported to YAMN)
+INT_PTR CreateAccountMailSvc(WPARAM wParam, LPARAM lParam);
+
+//Deletes mail for plugin (calling plugin's destructor, when plugin imported to YAMN)
+INT_PTR DeleteAccountMailSvc(WPARAM wParam, LPARAM lParam);
+
+//Loads mail data from standard storage to memory
+INT_PTR LoadMailDataSvc(WPARAM wParam, LPARAM lParam);
+
+//Deletes mail data from memory
+INT_PTR UnloadMailDataSvc(WPARAM wParam, LPARAM);
+
+//Saves mail data from memory to standard storage
+INT_PTR SaveMailDataSvc(WPARAM wParam, LPARAM lParam);
+
+//Appends second MIME mail queue to the first one
+//Only finds the end of first queue and its Next memember repoints to second one
+void WINAPI AppendQueueFcn(HYAMNMAIL first, HYAMNMAIL second);
+
+//Synchronizes two accounts
+//Function finds, if there were some mails deleted from mailbox and deletes (depends on RemovedOld param) them from OldQueue
+//Next finds, if there are new mails. Mails that are still on mailbox are deleted (depends on RemovedNew param) from NewQueue
+//After this, OldQueue is pointer to mails that are on mailbox, but not new mails
+//and NewQueue contains new mails in account
+//New accounts can be then appended to account mails queue, but they have set the New flag
+//
+//Two mails equals if they have the same ID
+//
+// hPlugin- handle of plugin going to delete mails
+// OldQueue- queue of mails that we found on mailbox last time, after function finishes queue contains all mails except new ones
+// RemovedOld- queue of mails where to store removed mails from OldQueue, if NULL deletes mails from OldQueue
+// NewQueue- queue of mails that we found on mailbox (all mails), after function finishes queue contains only new mails
+// RemovedNew- queue of mails where to store removed mails from NewQueue, if NULL deletes mails from NewQueue
+//So function works like:
+//1. delete (or move to RemovedOld queue if RemovedOld is not NULL) all mails from OldQueue not found in NewQueue
+//2. delete (or move to RemovedNew queue if RemovedNew is not NULL) all mails from NewQueue found in OldQueue
+void WINAPI SynchroMessagesFcn(CAccount *Account, HYAMNMAIL *OldQueue, HYAMNMAIL *RemovedOld, HYAMNMAIL *NewQueue, HYAMNMAIL *RemovedNew);
+
+//Deletes messages from mail From to the end
+// Account- account who owns mails
+// From- first mail in queue, which is going to delete
+void WINAPI DeleteMessagesToEndFcn(CAccount *Account, HYAMNMAIL From);
+
+//Removes message from queue, does not delete from memory
+// From- queue pointer
+// Which- mail to delete
+// mode- nonzero if you want to decrement numbers in messages that are bigger than the one in Which mail, 0 if not
+void WINAPI DeleteMessageFromQueueFcn(HYAMNMAIL *From, HYAMNMAIL Which, int mode);
+
+//Finds message in queue that has the same ID number
+// From- message queue
+// ID- pointer to ID
+// returns pointer to found message, NULL if not found
+HYAMNMAIL WINAPI FindMessageByIDFcn(HYAMNMAIL From, char *ID);
+
+//Translate header from text to queue of CMimeItem structures
+//This means that new queue will contain all info about headers
+// stream- pointer to text containing header (can be ended with zero)
+// len- length of stream
+// head- function fills this pointer to first header item in queue
+void WINAPI TranslateHeaderFcn(char *stream, int len, struct CMimeItem **head);
+
+//Creates new mail queue, copying only these mails, that have set flag for deleting
+// From- message queue, whose mail with given flag are duplicated
+// returns new mail queue (or NULL when no mail with flag is in From queue)
+//Function does not copy the whole mails, it copies only ID string. And ID is copied as string, so
+//you can use this fcn only if you have your ID as pointer to char string ended with zero character
+HYAMNMAIL WINAPI CreateNewDeleteQueueFcn(HYAMNMAIL From);
+
+//Sets/removes flags from specific mails
+// From- pointer to first message
+// FlagsSet- mail must have set these flags...
+// FlagsNotSet- ...and must not have set these flags...
+// FlagsToSetRemove- ...to set/remove these flags (see mode)
+// mode- nonzero to set, else remove
+void WINAPI SetRemoveFlagsInQueueFcn(HYAMNMAIL From, uint32_t FlagsSet, uint32_t FlagsNotSet, uint32_t FlagsToSetRemove, int mode);
+
+struct CExportedFunctions MailExportedFcn[] =
+{
+ {YAMN_SYNCHROMIMEMSGSID, (void *)SynchroMessagesFcn},
+ {YAMN_TRANSLATEHEADERID, (void *)TranslateHeaderFcn},
+ {YAMN_APPENDQUEUEID, (void *)AppendQueueFcn},
+ {YAMN_DELETEMIMEQUEUEID, (void *)DeleteMessagesToEndFcn},
+ {YAMN_DELETEMIMEMESSAGEID, (void *)DeleteMessageFromQueueFcn},
+ {YAMN_FINDMIMEMESSAGEID, (void *)FindMessageByIDFcn},
+ {YAMN_CREATENEWDELETEQUEUEID, (void *)CreateNewDeleteQueueFcn},
+ {YAMN_SETREMOVEQUEUEFLAGSID, (void *)SetRemoveFlagsInQueueFcn},
+};
+
+struct CExportedServices MailExportedSvc[] =
+{
+ {MS_YAMN_CREATEACCOUNTMAIL, CreateAccountMailSvc},
+ {MS_YAMN_DELETEACCOUNTMAIL, DeleteAccountMailSvc},
+ {MS_YAMN_LOADMAILDATA, LoadMailDataSvc},
+ {MS_YAMN_UNLOADMAILDATA, UnloadMailDataSvc},
+ {MS_YAMN_SAVEMAILDATA, SaveMailDataSvc},
+};
+
+
+//--------------------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------
+
+INT_PTR CreateAccountMailSvc(WPARAM wParam, LPARAM lParam)
+{
+ CAccount *Account = (CAccount *)wParam;
+ uint32_t MailVersion = (uint32_t)lParam;
+ HYAMNMAIL NewMail;
+
+ //test if we are going to initialize members of suitable structure (structures of plugin and YAMN must match)
+ if (MailVersion != YAMN_MAILVERSION)
+ return NULL;
+
+ if (Account->Plugin != nullptr) {
+ if (Account->Plugin->MailFcn->NewMailFcnPtr != nullptr) {
+ //Let plugin create its own structure, which can be derived from CAccount structure
+ if (nullptr == (NewMail = Account->Plugin->MailFcn->NewMailFcnPtr(Account, YAMN_MAILVERSION)))
+ return NULL;
+ }
+ else {
+ //We suggest plugin uses standard CAccount structure, so we create it
+ if (nullptr == (NewMail = new YAMNMAIL))
+ //If not created successfully
+ return NULL;
+ NewMail->MailData = nullptr;
+ }
+ //Init every members of structure, used by YAMN
+ return (INT_PTR)NewMail;
+ }
+ return NULL;
+}
+
+INT_PTR DeleteAccountMailSvc(WPARAM wParam, LPARAM lParam)
+{
+ HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam;
+ HYAMNMAIL OldMail = (HYAMNMAIL)lParam;
+ struct CMimeItem *TH;
+
+ if (Plugin->MailFcn != nullptr) {
+ if (Plugin->MailFcn->DeleteMailFcnPtr != nullptr) {
+ //Let plugin delete its own CMimeMsgQueue derived structure
+ Plugin->MailFcn->DeleteMailFcnPtr(OldMail);
+ return 1;
+ }
+ }
+ if (OldMail->MailData != nullptr) {
+ if (OldMail->MailData->Body != nullptr)
+ delete[] OldMail->MailData->Body;
+ if ((TH = OldMail->MailData->TranslatedHeader) != nullptr)
+ for (; OldMail->MailData->TranslatedHeader != nullptr;) {
+ TH = TH->Next;
+ if (OldMail->MailData->TranslatedHeader->name != nullptr)
+ delete[] OldMail->MailData->TranslatedHeader->name;
+ if (OldMail->MailData->TranslatedHeader->value != nullptr)
+ delete[] OldMail->MailData->TranslatedHeader->value;
+ delete OldMail->MailData->TranslatedHeader;
+ OldMail->MailData->TranslatedHeader = TH;
+ }
+ delete OldMail->MailData;
+ }
+ if (OldMail->ID != nullptr)
+ delete[] OldMail->ID;
+
+ delete OldMail; //consider mail as standard HYAMNMAIL, not initialized before and use its own destructor
+ return 1;
+}
+
+
+void WINAPI AppendQueueFcn(HYAMNMAIL first, HYAMNMAIL second)
+{
+ HYAMNMAIL Finder = first;
+ while (Finder->Next != nullptr) Finder = Finder->Next;
+ Finder->Next = second;
+}
+
+INT_PTR LoadMailDataSvc(WPARAM wParam, LPARAM lParam)
+{
+ HYAMNMAIL Mail = (HYAMNMAIL)wParam;
+ uint32_t MailVersion = (uint32_t)lParam;
+
+ if (MailVersion != YAMN_MAILDATAVERSION)
+ return NULL;
+
+ // now we have all data to memory persisting, so no loading is needed
+ return (INT_PTR)Mail->MailData;
+}
+
+INT_PTR UnloadMailDataSvc(WPARAM, LPARAM)
+{
+ return 1;
+}
+
+INT_PTR SaveMailDataSvc(WPARAM, LPARAM lParam)
+{
+ uint32_t MailVersion = (uint32_t)lParam;
+
+ if (MailVersion != YAMN_MAILDATAVERSION)
+ return (INT_PTR)-1;
+
+ // now we have all data to memory persisting, so no saving is needed
+ return (INT_PTR)0;
+}
+
+void WINAPI SynchroMessagesFcn(CAccount *Account, HYAMNMAIL *OldQueue, HYAMNMAIL *RemovedOld, HYAMNMAIL *NewQueue, HYAMNMAIL *RemovedNew)
+//deletes messages from new queue, if they are old
+//it also deletes messages from old queue, if they are not in mailbox anymore
+//"YAMN_MSG_DELETED" messages in old queue remain in old queue (are never removed, although they are not in new queue)
+//"YAMN_MSG_DELETED" messages in new queue remain in new queue (are never removed, although they can be in old queue)
+{
+ HYAMNMAIL Finder, FinderPrev;
+ HYAMNMAIL Parser, ParserPrev;
+ HYAMNMAIL RemovedOldParser = nullptr;
+ HYAMNMAIL RemovedNewParser = nullptr;
+ if (RemovedOld != nullptr) *RemovedOld = nullptr;
+ if (RemovedNew != nullptr) *RemovedNew = nullptr;
+
+ for (FinderPrev = nullptr, Finder = *OldQueue; Finder != nullptr;) {
+ if (Finder->Flags & YAMN_MSG_DELETED) //if old queue contains deleted mail
+ {
+ FinderPrev = Finder;
+ Finder = Finder->Next; //get next message in old queue for testing
+ continue;
+ }
+ for (ParserPrev = nullptr, Parser = *NewQueue; Parser != nullptr; ParserPrev = Parser, Parser = Parser->Next) {
+ if (Parser->Flags & YAMN_MSG_DELETED)
+ continue;
+
+ if (Parser->ID == nullptr) //simply ignore the message, that has not filled its ID
+ continue;
+
+ if (0 == mir_strcmp(Parser->ID, Finder->ID)) //search for equal message in new queue
+ break;
+ }
+ if (Parser != nullptr) //found equal message in new queue
+ {
+ if (Parser == *NewQueue)
+ *NewQueue = (*NewQueue)->Next;
+ else
+ ParserPrev->Next = Parser->Next;
+ Finder->Number = Parser->Number; //rewrite the number of current message in old queue
+
+ if (RemovedNew == nullptr) //delete from new queue
+ DeleteAccountMailSvc((WPARAM)Account->Plugin, (LPARAM)Parser);
+ else //or move to RemovedNew
+ {
+ if (RemovedNewParser == nullptr) //if it is first mail removed from NewQueue
+ *RemovedNew = Parser; //set RemovedNew queue to point to first message in removed queue
+ else
+ RemovedNewParser->Next = Parser; //else don't forget to show to next message in RemovedNew queue
+ RemovedNewParser = Parser; //follow RemovedNew queue
+ RemovedNewParser->Next = nullptr;
+ }
+ FinderPrev = Finder;
+ Finder = Finder->Next; //get next message in old queue for testing
+ }
+ else //a message was already deleted from mailbox
+ {
+ if (Finder == *OldQueue) //if we are at the first item in OldQueue
+ {
+ *OldQueue = (*OldQueue)->Next; //set OldQueue to next item
+ if (RemovedOld == nullptr) //delete from old queue
+ DeleteAccountMailSvc((WPARAM)Account->Plugin, (LPARAM)Finder);
+ else //or move to RemovedOld
+ {
+ if (RemovedOldParser == nullptr) //if it is first mail removed from OldQueue
+ *RemovedOld = Finder; //set RemovedOld queue to point to first message in removed queue
+ else
+ RemovedOldParser->Next = Finder; //else don't forget to show to next message in RemovedNew queue
+ RemovedOldParser = Finder; //follow RemovedOld queue
+ RemovedOldParser->Next = nullptr;
+ }
+ Finder = *OldQueue;
+ }
+ else {
+ FinderPrev->Next = Finder->Next;
+ if (RemovedOld == nullptr) //delete from old queue
+ DeleteAccountMailSvc((WPARAM)Account->Plugin, (LPARAM)Finder);
+ else //or move to RemovedOld
+ {
+ if (RemovedOldParser == nullptr) //if it is first mail removed from OldQueue
+ *RemovedOld = Finder; //set RemovedOld queue to point to first message in removed queue
+ else
+ RemovedOldParser->Next = Finder; //else don't forget to show to next message in RemovedNew queue
+ RemovedOldParser = Finder; //follow RemovedOld queue
+ RemovedOldParser->Next = nullptr;
+ }
+ Finder = FinderPrev->Next;
+ }
+ }
+ }
+}
+
+void WINAPI DeleteMessagesToEndFcn(CAccount *Account, HYAMNMAIL From)
+{
+ HYAMNMAIL Temp;
+ while (From != nullptr) {
+ Temp = From;
+ From = From->Next;
+ DeleteAccountMailSvc((WPARAM)Account->Plugin, (LPARAM)Temp);
+ }
+}
+
+void WINAPI DeleteMessageFromQueueFcn(HYAMNMAIL *From, HYAMNMAIL Which, int mode = 0)
+{
+ uint32_t Number = Which->Number;
+ HYAMNMAIL Parser;
+
+ if (*From == Which) {
+ Parser = Which->Next;
+ *From = Parser;
+ }
+ else {
+ for (Parser = *From; Which != Parser->Next; Parser = Parser->Next)
+ if (mode && (Parser->Number > Number)) Parser->Number--;
+ if (mode && (Parser->Number > Number)) Parser->Number--;
+ Parser->Next = Parser->Next->Next;
+ Parser = Which->Next;
+ }
+ if (mode)
+ for (; Parser != nullptr; Parser = Parser->Next)
+ if (Parser->Number > Number) Parser->Number--;
+}
+
+void DeleteMessagesFromQueue(HYAMNMAIL *From, HYAMNMAIL Which, int mode = 0)
+{
+ HYAMNMAIL Parser;
+
+ for (Parser = Which; Parser != nullptr; Parser = Parser->Next)
+ DeleteMessageFromQueueFcn(From, Parser, mode);
+}
+
+HYAMNMAIL WINAPI FindMessageByIDFcn(HYAMNMAIL From, char *ID)
+{
+ HYAMNMAIL Browser;
+
+ for (Browser = From; Browser != nullptr; Browser = Browser->Next)
+ if (0 == mir_strcmp(Browser->ID, ID))
+ break;
+ return Browser;
+}
+
+void WINAPI TranslateHeaderFcn(char *stream, int len, struct CMimeItem **head)
+{
+ try {
+ char *finder = stream;
+ char *prev1, *prev2, *prev3;
+ struct CMimeItem *Item = nullptr;
+
+ while (finder <= (stream + len)) {
+ while (ENDLINEWS(finder)) finder++;
+
+ //at the start of line
+ if (DOTLINE(finder + 1)) //at the end of stream
+ break;
+
+ prev1 = finder;
+
+ while (*finder != ':' && !EOS(finder)) finder++;
+ if (!EOS(finder))
+ prev2 = finder++;
+ else
+ break;
+
+ while (WS(finder) && !EOS(finder)) finder++;
+ if (!EOS(finder))
+ prev3 = finder;
+ else
+ break;
+
+ do {
+ if (ENDLINEWS(finder)) finder += 2; //after endline information continues
+ while (!ENDLINE(finder) && !EOS(finder)) finder++;
+ } while (ENDLINEWS(finder));
+
+ if (Item != nullptr) {
+ if (nullptr == (Item->Next = new struct CMimeItem))
+ break;
+ Item = Item->Next;
+ }
+ else {
+ Item = new CMimeItem;
+ *head = Item;
+ }
+
+ Item->Next = nullptr;
+ Item->name = new char[prev2 - prev1 + 1];
+ mir_strncpy(Item->name, prev1, prev2 - prev1 + 1);
+ Item->value = new char[finder - prev3 + 1];
+ mir_strncpy(Item->value, prev3, finder - prev3 + 1);
+
+ if (EOS(finder))
+ break;
+ finder++;
+ if (ENDLINE(finder)) {
+ finder++;
+ if (ENDLINE(finder)) {
+ // end of headers. message body begins
+ finder++;
+ if (ENDLINE(finder))finder++;
+ prev1 = finder;
+ while (!DOTLINE(finder + 1))finder++;
+ if (ENDLINE(finder))finder--;
+ prev2 = finder;
+ if (prev2 > prev1) { // yes, we have body
+ if (nullptr == (Item->Next = new struct CMimeItem)) break; // Cant create new item?!
+ Item = Item->Next;
+ Item->Next = nullptr;//just in case;
+ Item->name = new char[5]; strncpy(Item->name, "Body", 5);
+ Item->value = new char[prev2 - prev1];
+ mir_strncpy(Item->value, prev1, prev2 - prev1 - 1);
+ }
+ break; // there is nothing else
+ }
+ }
+ }
+ }
+ catch (...) {
+ MessageBoxA(nullptr, "Translate header error", "", 0);
+ }
+}
+
+HYAMNMAIL WINAPI CreateNewDeleteQueueFcn(HYAMNMAIL From)
+{
+ HYAMNMAIL FirstMail, Browser = nullptr;
+
+ for (FirstMail = nullptr; From != nullptr; From = From->Next) {
+ if ((From->Flags & (YAMN_MSG_USERDELETE | YAMN_MSG_AUTODELETE)) && !(From->Flags & YAMN_MSG_DELETED)) {
+ if (FirstMail == nullptr) {
+ FirstMail = Browser = new YAMNMAIL;
+ if (FirstMail == nullptr)
+ break;
+ }
+ else {
+ Browser->Next = new YAMNMAIL;
+ Browser = Browser->Next;
+ }
+ Browser->ID = new char[mir_strlen(From->ID) + 1];
+ mir_strcpy(Browser->ID, From->ID);
+ Browser->Number = From->Number;
+ Browser->Flags = From->Flags;
+ }
+ }
+ return FirstMail;
+}
+
+void WINAPI SetRemoveFlagsInQueueFcn(HYAMNMAIL From, uint32_t FlagsSet, uint32_t FlagsNotSet, uint32_t FlagsToSetRemove, int mode)
+{
+ HYAMNMAIL msgq;
+
+ for (msgq = (HYAMNMAIL)From; msgq != nullptr; msgq = msgq->Next) {
+ if ((FlagsSet == (msgq->Flags & FlagsSet)) && (0 == (msgq->Flags & FlagsNotSet))) {
+ if (mode)
+ msgq->Flags = msgq->Flags | FlagsToSetRemove;
+ else
+ msgq->Flags = msgq->Flags & ~FlagsToSetRemove;
+ }
+ }
+}
diff --git a/protocols/YAMN/src/mails/mime.cpp b/protocols/YAMN/src/mails/mime.cpp index 69099af808..2a2e7b4665 100644 --- a/protocols/YAMN/src/mails/mime.cpp +++ b/protocols/YAMN/src/mails/mime.cpp @@ -1,695 +1,695 @@ -/* - * This code implements retrieving info from MIME header - * - * (c) majvan 2002-2004 - */ - -#include "../stdafx.h" - - //-------------------------------------------------------------------------------------------------- - - //Copies one string to another - // srcstart- source string - // srcend- address to the end of source string - // dest- pointer that stores new allocated string that contains copy of source string - // mode- MIME_PLAIN or MIME_MAIL (MIME_MAIL deletes '"' characters (or '<' and '>') if they are at start and end of source string -void CopyToHeader(char *srcstart, char *srcend, char **dest, int mode); - -//Extracts email address (finds nick name and mail and then stores them to strings) -// finder- source string -// storeto- pointer that receives address of mail string -// storetonick- pointer that receives address of nickname -void ExtractAddressFromLine(char *finder, char **storeto, char **storetonick); - -//Extracts simple text from string -// finder- source string -// storeto- pointer that receives address of string -void ExtractStringFromLine(char *finder, char **storeto); - -//Extracts some item from content-type string -//Example: ContentType string: "TEXT/PLAIN; charset=US-ASCII", item:"charset=", returns: "US-ASCII" -// ContetType- content-type string -// value- string item -// returns extracted string (or NULL when not found) -char *ExtractFromContentType(char *ContentType, char *value); - -//Extracts info from header text into header members -//Note that this function as well as struct CShortHeadwer can be always changed, because there are many items to extract -//(e.g. the X-Priority and Importance and so on) -// items- translated header (see TranslateHeaderFcn) -// head- header to be filled with values extracted from items -void ExtractShortHeader(struct CMimeItem *items, struct CShortHeader *head); - -//Extracts header to mail using ExtractShortHeader fcn. -// items- translated header (see TranslateHeaderFcn) -// CP- codepage used when no default found -// head- header to be filled with values extracted from items, in unicode (wide char) -void ExtractHeader(struct CMimeItem *items, int &CP, struct CHeader *head); - -//Deletes items in CShortHeader structure -// head- structure whose items are deleted -void DeleteShortHeaderContent(struct CShortHeader *head); - -//Deletes list of YAMN_MIMENAMES structures -// Names- pointer to first item of list -void DeleteNames(CMimeNames *Names); - -//Deletes list of YAMN_MIMESHORTNAMES structures -// Names- pointer to first item of list -void DeleteShortNames(CShortNames *Names); - -//Makes a string lowercase -// string- string to be lowercased -void inline ToLower(char *string); - -//-------------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------------- - -void CopyToHeader(char *srcstart, char *srcend, char **dest, int mode) -{ - char *dst; - - if (dest == nullptr) - return; - if (srcstart >= srcend) - return; - - if ((mode == MIME_MAIL) && (((*srcstart == '"') && (*(srcend - 1) == '"')) || ((*srcstart == '<') && (*(srcend - 1) == '>')))) { - srcstart++; - srcend--; - } - - if (srcstart >= srcend) - return; - - if (nullptr != *dest) - delete[] * dest; - if (nullptr == (*dest = new char[srcend - srcstart + 1])) - return; - - dst = *dest; - - for (; srcstart < srcend; dst++, srcstart++) { - if (ENDLINE(srcstart)) { - while (ENDLINE(srcstart) || WS(srcstart)) srcstart++; - *dst = ' '; - srcstart--; //because at the end of "for loop" we increment srcstart - } - else - *dst = *srcstart; - } - *dst = 0; -} - -void ExtractAddressFromLine(char *finder, char **storeto, char **storetonick) -{ - if (finder == nullptr) { - *storeto = *storetonick = nullptr; - return; - } - while (WS(finder)) finder++; - if ((*finder) != '<') { - char *finderend = finder + 1; - do { - if (ENDLINEWS(finderend)) //after endline information continues - finderend += 2; - while (!ENDLINE(finderend) && !EOS(finderend)) finderend++; //seek to the end of line or to the end of string - } while (ENDLINEWS(finderend)); - finderend--; - while (WS(finderend) || ENDLINE(finderend)) finderend--; //find the end of text, no whitespace - if (*finderend != '>') //not '>' at the end of line - CopyToHeader(finder, finderend + 1, storeto, MIME_MAIL); - else //at the end of line, there's '>' - { - char *finder2 = finderend; - while ((*finder2 != '<') && (finder2 > finder)) finder2--; //go to matching '<' or to the start - CopyToHeader(finder2, finderend + 1, storeto, MIME_MAIL); - if (*finder2 == '<') //if we found '<', the rest copy as from nick - { - finder2--; - while (WS(finder2) || ENDLINE(finder2)) finder2--; //parse whitespace - CopyToHeader(finder, finder2 + 1, storetonick, MIME_MAIL); //and store nickname - } - } - } - else { - char *finderend = finder + 1; - do { - if (ENDLINEWS(finderend)) //after endline information continues - finderend += 2; - while (!ENDLINE(finderend) && (*finderend != '>') && !EOS(finderend)) finderend++; //seek to the matching < or to the end of line or to the end of string - } while (ENDLINEWS(finderend)); - CopyToHeader(finder, finderend + 1, storeto, MIME_MAIL); //go to first '>' or to the end and copy - finder = finderend + 1; - while (WS(finder)) finder++; //parse whitespace - if (!ENDLINE(finder) && !EOS(finder)) //if there are chars yet, it's nick - { - finderend = finder + 1; - while (!ENDLINE(finderend) && !EOS(finderend)) finderend++; //seek to the end of line or to the end of string - finderend--; - while (WS(finderend)) finderend--; //find the end of line, no whitespace - CopyToHeader(finder, finderend + 1, storetonick, MIME_MAIL); - } - } -} - -void ExtractStringFromLine(char *finder, char **storeto) -{ - if (finder == nullptr) { - *storeto = nullptr; - return; - } - while (WS(finder)) finder++; - char *finderend = finder; - - do { - if (ENDLINEWS(finderend)) finderend++; //after endline information continues - while (!ENDLINE(finderend) && !EOS(finderend)) finderend++; - } while (ENDLINEWS(finderend)); - finderend--; - while (WS(finderend)) finderend--; //find the end of line, no whitespace - CopyToHeader(finder, finderend + 1, storeto, MIME_PLAIN); -} - -char *ExtractFromContentType(char *ContentType, char *value) -{ - char *lowered = _strdup(ContentType); - ToLower(lowered); - char *finder = strstr(lowered, value); - if (finder == nullptr) { - free(lowered); - return nullptr; - } - finder = finder - lowered + ContentType; - free(lowered); - - char *temp, *copier; - char *CopiedString; - - temp = finder - 1; - while ((temp > ContentType) && WS(temp)) temp--; //now we have to find, if the word "Charset=" is located after ';' like "; Charset=" - if (*temp != ';' && !ENDLINE(temp) && temp != ContentType) - return nullptr; - finder = finder + mir_strlen(value); //jump over value string - - while (WS(finder)) finder++; //jump over whitespaces - temp = finder; - while (*temp != 0 && *temp != ';') temp++; //jump to the end of setting (to the next ;) - temp--; - while (WS(temp)) temp--; //remove whitespaces from the end - if (*finder == '\"') { //remove heading and tailing quotes - finder++; - if (*temp == '\"') temp--; - } - if (nullptr == (CopiedString = new char[++temp - finder + 1])) - return nullptr; - for (copier = CopiedString; finder != temp; *copier++ = *finder++); //copy string - *copier = 0; //and end it with zero character - - return CopiedString; -} - -void ExtractShortHeader(struct CMimeItem *items, struct CShortHeader *head) -{ - for (; items != nullptr; items = items->Next) { - //at the start of line - //MessageBox(NULL,items->value,items->name,0); - if (0 == _strnicmp(items->name, "From", 4)) { - if (items->value == nullptr) - continue; - #ifdef DEBUG_DECODE - DebugLog(DecodeFile, "<Extracting from>"); - #endif - ExtractAddressFromLine(items->value, &head->From, &head->FromNick); - #ifdef DEBUG_DECODE - DebugLog(DecodeFile, "</Extracting>\n"); - #endif - } - else if (0 == _strnicmp(items->name, "Return-Path", 11)) { - if (items->value == nullptr) - continue; - #ifdef DEBUG_DECODE - DebugLog(DecodeFile, "<Extracting return-path>"); - #endif - ExtractAddressFromLine(items->value, &head->ReturnPath, &head->ReturnPathNick); - #ifdef DEBUG_DECODE - DebugLog(DecodeFile, "</Extracting>\n"); - #endif - } - else if (0 == _strnicmp(items->name, "Subject", 7)) { - if (items->value == nullptr) - continue; - #ifdef DEBUG_DECODE - DebugLog(DecodeFile, "<Extracting subject>"); - #endif - ExtractStringFromLine(items->value, &head->Subject); - #ifdef DEBUG_DECODE - DebugLog(DecodeFile, "</Extracting>\n"); - #endif - } - else if (0 == _strnicmp(items->name, "Body", 4)) { - if (items->value == nullptr) - continue; - #ifdef DEBUG_DECODE - DebugLog(DecodeFile, "<Extracting body>"); - #endif - ExtractStringFromLine(items->value, &head->Body); - #ifdef DEBUG_DECODE - DebugLog(DecodeFile, "</Extracting>\n"); - #endif - } - else if (0 == _strnicmp(items->name, "Date", 4)) { - if (items->value == nullptr) - continue; - #ifdef DEBUG_DECODE - DebugLog(DecodeFile, "<Extracting date>"); - #endif - ExtractStringFromLine(items->value, &head->Date); - #ifdef DEBUG_DECODE - DebugLog(DecodeFile, "</Extracting>\n"); - #endif - } - else if (0 == _strnicmp(items->name, "Content-Type", 12)) { - if (items->value == nullptr) - continue; - - char *ContentType = nullptr, *CharSetStr; - #ifdef DEBUG_DECODE - DebugLog(DecodeFile, "<Extracting Content-Type>"); - #endif - ExtractStringFromLine(items->value, &ContentType); - #ifdef DEBUG_DECODE - DebugLog(DecodeFile, "</Extracting>\n"); - #endif - ToLower(ContentType); - if (nullptr != (CharSetStr = ExtractFromContentType(ContentType, "charset="))) { - head->CP = GetCharsetFromString(CharSetStr, mir_strlen(CharSetStr)); - delete[] CharSetStr; - } - delete[] ContentType; - } - else if (0 == _strnicmp(items->name, "Importance", 10)) { - if (items->value == nullptr) - continue; - #ifdef DEBUG_DECODE - DebugLog(DecodeFile, "<Extracting importance>"); - #endif - if (head->Priority != -1) { - if (0 == strncmp(items->value, "low", 3)) - head->Priority = 5; - else if (0 == strncmp(items->value, "normal", 6)) - head->Priority = 3; - else if (0 == strncmp(items->value, "high", 4)) - head->Priority = 1; - } - #ifdef DEBUG_DECODE - DebugLog(DecodeFile, "</Extracting>\n"); - #endif - } - else if (0 == _strnicmp(items->name, "X-Priority", 10)) { - if (items->value == nullptr) - continue; - #ifdef DEBUG_DECODE - DebugLog(DecodeFile, "<X-Priority>"); - #endif - if ((*items->value >= '1') && (*items->value <= '5')) - head->Priority = *items->value - '0'; - #ifdef DEBUG_DECODE - DebugLog(DecodeFile, "</Extracting>\n"); - #endif - } - - } -} - -void ExtractHeader(struct CMimeItem *items, int &CP, struct CHeader *head) -{ - struct CShortHeader ShortHeader; - - memset(&ShortHeader, 0, sizeof(struct CShortHeader)); - ShortHeader.Priority = ShortHeader.CP = -1; - #ifdef DEBUG_DECODE - DebugLog(DecodeFile, "<Extracting header>\n"); - #endif - ExtractShortHeader(items, &ShortHeader); - - head->Priority = ShortHeader.Priority == -1 ? 3 : ShortHeader.Priority; - CP = ShortHeader.CP == -1 ? CP : ShortHeader.CP; - #ifdef DEBUG_DECODE - if (NULL != ShortHeader.From) - DebugLog(DecodeFile, "<Decoded from>%s</Decoded)\n", ShortHeader.From); - if (NULL != ShortHeader.FromNick) - DebugLog(DecodeFile, "<Decoded from-nick>%s</Decoded)\n", ShortHeader.FromNick); - if (NULL != ShortHeader.ReturnPath) - DebugLog(DecodeFile, "<Decoded return-path>%s</Decoded)\n", ShortHeader.ReturnPath); - if (NULL != ShortHeader.ReturnPathNick) - DebugLog(DecodeFile, "<Decoded return-path nick>%s</Decoded)\n", ShortHeader.ReturnPathNick); - if (NULL != ShortHeader.Subject) - DebugLog(DecodeFile, "<Decoded subject>%s</Decoded)\n", ShortHeader.Subject); - if (NULL != ShortHeader.Date) - DebugLog(DecodeFile, "<Decoded date>%s</Decoded)\n", ShortHeader.Date); - DebugLog(DecodeFile, "</Extracting header>\n"); - DebugLog(DecodeFile, "<Convert>\n"); - #endif - - ConvertCodedStringToUnicode(ShortHeader.From, &head->From, CP, MIME_PLAIN); - - #ifdef DEBUG_DECODE - if (NULL != head->From) - DebugLogW(DecodeFile, L"<Converted from>%s</Converted>\n", head->From); - #endif - ConvertCodedStringToUnicode(ShortHeader.FromNick, &head->FromNick, CP, MIME_MAIL); - #ifdef DEBUG_DECODE - if (NULL != head->FromNick) - DebugLogW(DecodeFile, L"<Converted from-nick>%s</Converted>\n", head->FromNick); - #endif - ConvertCodedStringToUnicode(ShortHeader.ReturnPath, &head->ReturnPath, CP, MIME_PLAIN); - #ifdef DEBUG_DECODE - if (NULL != head->ReturnPath) - DebugLogW(DecodeFile, L"<Converted return-path>%s</Converted>\n", head->ReturnPath); - #endif - ConvertCodedStringToUnicode(ShortHeader.ReturnPathNick, &head->ReturnPathNick, CP, MIME_MAIL); - #ifdef DEBUG_DECODE - if (NULL != head->ReturnPathNick) - DebugLogW(DecodeFile, L"<Converted return-path nick>%s</Converted>\n", head->ReturnPathNick); - #endif - ConvertCodedStringToUnicode(ShortHeader.Subject, &head->Subject, CP, MIME_PLAIN); - #ifdef DEBUG_DECODE - if (NULL != head->Subject) - DebugLogW(DecodeFile, L"<Converted subject>%s</Converted>\n", head->Subject); - #endif - ConvertCodedStringToUnicode(ShortHeader.Date, &head->Date, CP, MIME_PLAIN); - #ifdef DEBUG_DECODE - if (NULL != head->Date) - DebugLogW(DecodeFile, L"<Converted date>%s</Converted>\n", head->Date); - #endif - - ConvertCodedStringToUnicode(ShortHeader.Body, &head->Body, CP, MIME_PLAIN); - #ifdef DEBUG_DECODE - if (NULL != head->Body) - DebugLogW(DecodeFile, L"<Converted Body>%s</Converted>\n", head->Body); - #endif - - #ifdef DEBUG_DECODE - DebugLog(DecodeFile, "</Convert>\n"); - #endif - - DeleteShortHeaderContent(&ShortHeader); - - // head->From=L"Frommmm"; - // head->Subject=L"Subject"; - return; -} - -void DeleteShortHeaderContent(struct CShortHeader *head) -{ - if (head->From != nullptr) delete[] head->From; - if (head->FromNick != nullptr) delete[] head->FromNick; - if (head->ReturnPath != nullptr) delete[] head->ReturnPath; - if (head->ReturnPathNick != nullptr) delete[] head->ReturnPathNick; - if (head->Subject != nullptr) delete[] head->Subject; - if (head->Date != nullptr) delete[] head->Date; - if (head->To != nullptr) DeleteShortNames(head->To); - if (head->Cc != nullptr) DeleteShortNames(head->Cc); - if (head->Bcc != nullptr) DeleteShortNames(head->Bcc); - if (head->Body != nullptr) delete[] head->Body; -} - -void DeleteHeaderContent(struct CHeader *head) -{ - if (head->From != nullptr) delete[] head->From; - if (head->FromNick != nullptr) delete[] head->FromNick; - if (head->ReturnPath != nullptr) delete[] head->ReturnPath; - if (head->ReturnPathNick != nullptr) delete[] head->ReturnPathNick; - if (head->Subject != nullptr) delete[] head->Subject; - if (head->Date != nullptr) delete[] head->Date; - if (head->Body != nullptr) delete[] head->Body; - if (head->To != nullptr) DeleteNames(head->To); - if (head->Cc != nullptr) DeleteNames(head->Cc); - if (head->Bcc != nullptr) DeleteNames(head->Bcc); -} - -void DeleteNames(CMimeNames *Names) -{ - CMimeNames *Parser = Names; - for (; Parser != nullptr; Parser = Parser->Next) { - if (Parser->Value != nullptr) - delete[] Parser->Value; - if (Parser->ValueNick != nullptr) - delete[] Parser->ValueNick; - - CMimeNames *Old = Parser; - Parser = Parser->Next; - delete Old; - } -} - -void DeleteShortNames(CShortNames *Names) -{ - CShortNames *Parser = Names; - for (; Parser != nullptr; Parser = Parser->Next) { - if (Parser->Value != nullptr) - delete[] Parser->Value; - if (Parser->ValueNick != nullptr) - delete[] Parser->ValueNick; - - CShortNames *Old = Parser; - Parser = Parser->Next; - delete Old; - } -} - - -void inline ToLower(char *string) -{ - for (; *string != 0; string++) - if (*string >= 'A' && *string <= 'Z') *string = *string - 'A' + 'a'; -} - -#define TE_UNKNOWN -#define TE_QUOTEDPRINTABLE 1 -#define TE_BASE64 2 -struct APartDataType -{ - char *Src;//Input - char *ContType; - int CodePage; - char *TransEnc; - uint8_t TransEncType; //TE_something - char *body; - int bodyLen; - wchar_t *wBody; -}; - - -void ParseAPart(APartDataType *data) -{ - size_t len = mir_strlen(data->Src); - try { - char *finder = data->Src; - char *prev1, *prev2, *prev3; - - while (finder <= (data->Src + len)) { - while (ENDLINEWS(finder)) finder++; - - //at the start of line - if (finder > data->Src) { - if (*(finder - 2) == '\r' || *(finder - 2) == '\n') - *(finder - 2) = 0; - if (*(finder - 1) == '\r' || *(finder - 1) == '\n') - *(finder - 1) = 0; - } - prev1 = finder; - - while (*finder != ':' && !EOS(finder) && !ENDLINE(finder)) finder++; - if (ENDLINE(finder) || EOS(finder)) { - // no ":" in the line? here the body begins; - data->body = prev1; - break; - } - prev2 = finder++; - - while (WS(finder) && !EOS(finder)) finder++; - if (!EOS(finder)) - prev3 = finder; - else - break; - - do { - if (ENDLINEWS(finder)) finder += 2; //after endline information continues - while (!ENDLINE(finder) && !EOS(finder)) finder++; - } while (ENDLINEWS(finder)); - - if (!_strnicmp(prev1, "Content-type", prev2 - prev1)) { - data->ContType = prev3; - } - else if (!_strnicmp(prev1, "Content-Transfer-Encoding", prev2 - prev1)) { - data->TransEnc = prev3; - } - - if (EOS(finder)) - break; - finder++; - if (ENDLINE(finder)) { - finder++; - if (ENDLINE(finder)) { - // end of headers. message body begins - if (finder > data->Src) { - if (*(finder - 2) == '\r' || *(finder - 2) == '\n') - *(finder - 2) = 0; - if (*(finder - 1) == '\r' || *(finder - 1) == '\n') - *(finder - 1) = 0; - } - finder++; - if (ENDLINE(finder))finder++; - prev1 = finder; - while (!EOS(finder + 1))finder++; - if (ENDLINE(finder))finder--; - prev2 = finder; - if (prev2 > prev1) { // yes, we have body - data->body = prev1; - } - break; // there is nothing else - } - } - } - } - catch (...) { - MessageBox(nullptr, TranslateT("Translate header error"), L"", 0); - } - if (data->body) data->bodyLen = (int)mir_strlen(data->body); -} - -//from decode.cpp -int DecodeQuotedPrintable(char *Src, char *Dst, int DstLen, BOOL isQ); -int DecodeBase64(char *Src, char *Dst, int DstLen); -int ConvertStringToUnicode(char *stream, unsigned int cp, wchar_t **out); - -wchar_t *ParseMultipartBody(char *src, char *bond) -{ - char *srcback = _strdup(src); - size_t sizebond = mir_strlen(bond); - int numparts = 1; - int i; - char *courbond = srcback; - wchar_t *dest; - for (; (courbond = strstr(courbond, bond)); numparts++, courbond += sizebond); - APartDataType *partData = new APartDataType[numparts]; - memset(partData, 0, sizeof(APartDataType) * numparts); - partData[0].Src = courbond = srcback; - for (i = 1; (courbond = strstr(courbond, bond)); i++, courbond += sizebond) { - *(courbond - 2) = 0; - partData[i].Src = courbond + sizebond; - while (ENDLINE(partData[i].Src)) partData[i].Src++; - } - size_t resultSize = 0; - for (i = 0; i < numparts; i++) { - ParseAPart(&partData[i]); - if (partData[i].body) { - if (partData[i].TransEnc) { - if (!_stricmp(partData[i].TransEnc, "base64")) partData[i].TransEncType = TE_BASE64; - else if (!_stricmp(partData[i].TransEnc, "quoted-printable"))partData[i].TransEncType = TE_QUOTEDPRINTABLE; - } - if (partData[i].ContType) { - char *CharSetStr; - if (nullptr != (CharSetStr = ExtractFromContentType(partData[i].ContType, "charset="))) { - partData[i].CodePage = GetCharsetFromString(CharSetStr, mir_strlen(CharSetStr)); - delete[] CharSetStr; - } - } - if (partData[i].ContType && !_strnicmp(partData[i].ContType, "text", 4)) { - char *localBody = nullptr; - switch (partData[i].TransEncType) { - case TE_BASE64: - { - int size = partData[i].bodyLen * 3 / 4 + 5; - localBody = new char[size + 1]; - DecodeBase64(partData[i].body, localBody, size); - }break; - case TE_QUOTEDPRINTABLE: - { - int size = partData[i].bodyLen + 2; - localBody = new char[size + 1]; - DecodeQuotedPrintable(partData[i].body, localBody, size, FALSE); - }break; - } - ConvertStringToUnicode(localBody ? localBody : partData[i].body, partData[i].CodePage, &partData[i].wBody); - if (localBody) delete[] localBody; - } - else if (partData[i].ContType && !_strnicmp(partData[i].ContType, "multipart/", 10)) { - //Multipart in mulitipart recursive? should be SPAM. Ah well - char *bondary = nullptr; - if (nullptr != (bondary = ExtractFromContentType(partData[i].ContType, "boundary="))) { - partData[i].wBody = ParseMultipartBody(partData[i].body, bondary); - delete[] bondary; - } - else goto FailBackRaw; //multipart with no boundary? badly formatted messages. - } - else { -FailBackRaw: - ConvertStringToUnicode(partData[i].body, partData[i].CodePage, &partData[i].wBody); - } - resultSize += mir_wstrlen(partData[i].wBody); - }// if (partData[i].body) - resultSize += 100 + 4 + 3; //cr+nl+100+ 3*bullet - } - dest = new wchar_t[resultSize + 1]; - size_t destpos = 0; - for (i = 0; i < numparts; i++) { - if (i) { // part before first boudary should not have headers - char infoline[1024]; size_t linesize = 0; - mir_snprintf(infoline, "%s %d", Translate("Part"), i); - linesize = mir_strlen(infoline); - if (partData[i].TransEnc) { - mir_snprintf(infoline + linesize, _countof(infoline) - linesize, "; %s", partData[i].TransEnc); - linesize = mir_strlen(infoline); - } - if (partData[i].ContType) { - char *CharSetStr = strchr(partData[i].ContType, ';'); - if (CharSetStr) { - CharSetStr[0] = 0; - mir_snprintf(infoline + linesize, _countof(infoline) - linesize, "; %s", partData[i].ContType); - linesize = mir_strlen(infoline); - partData[i].ContType = CharSetStr + 1; - if (nullptr != (CharSetStr = ExtractFromContentType(partData[i].ContType, "charset="))) { - mir_snprintf(infoline + linesize, _countof(infoline) - linesize, "; %s", CharSetStr); - linesize = mir_strlen(infoline); - delete[] CharSetStr; - } - if (nullptr != (CharSetStr = ExtractFromContentType(partData[i].ContType, "name="))) { - mir_snprintf(infoline + linesize, _countof(infoline) - linesize, "; \"%s\"", CharSetStr); - linesize = mir_strlen(infoline); - delete[] CharSetStr; - } - } - else { - mir_snprintf(infoline + linesize, _countof(infoline) - linesize, "; %s", partData[i].ContType); - linesize = mir_strlen(infoline); - } - } - mir_snprintf(infoline + linesize, _countof(infoline) - linesize, ".\r\n"); - { - wchar_t *temp = nullptr; - dest[destpos] = dest[destpos + 1] = dest[destpos + 2] = 0x2022; // bullet; - destpos += 3; - ConvertStringToUnicode(infoline, CP_ACP, &temp); - size_t wsize = mir_wstrlen(temp); - mir_wstrcpy(&dest[destpos], temp); - destpos += wsize; - delete[] temp; - } - } // if (i) - - if (partData[i].wBody) { - size_t wsize = mir_wstrlen(partData[i].wBody); - mir_wstrcpy(&dest[destpos], partData[i].wBody); - destpos += wsize; - delete[] partData[i].wBody; - } - } - - free(srcback); - delete[] partData; - dest[resultSize] = 0;//just in case - return dest; -} +/*
+ * This code implements retrieving info from MIME header
+ *
+ * (c) majvan 2002-2004
+ */
+
+#include "../stdafx.h"
+
+ //--------------------------------------------------------------------------------------------------
+
+ //Copies one string to another
+ // srcstart- source string
+ // srcend- address to the end of source string
+ // dest- pointer that stores new allocated string that contains copy of source string
+ // mode- MIME_PLAIN or MIME_MAIL (MIME_MAIL deletes '"' characters (or '<' and '>') if they are at start and end of source string
+void CopyToHeader(char *srcstart, char *srcend, char **dest, int mode);
+
+//Extracts email address (finds nick name and mail and then stores them to strings)
+// finder- source string
+// storeto- pointer that receives address of mail string
+// storetonick- pointer that receives address of nickname
+void ExtractAddressFromLine(char *finder, char **storeto, char **storetonick);
+
+//Extracts simple text from string
+// finder- source string
+// storeto- pointer that receives address of string
+void ExtractStringFromLine(char *finder, char **storeto);
+
+//Extracts some item from content-type string
+//Example: ContentType string: "TEXT/PLAIN; charset=US-ASCII", item:"charset=", returns: "US-ASCII"
+// ContetType- content-type string
+// value- string item
+// returns extracted string (or NULL when not found)
+char *ExtractFromContentType(char *ContentType, char *value);
+
+//Extracts info from header text into header members
+//Note that this function as well as struct CShortHeadwer can be always changed, because there are many items to extract
+//(e.g. the X-Priority and Importance and so on)
+// items- translated header (see TranslateHeaderFcn)
+// head- header to be filled with values extracted from items
+void ExtractShortHeader(struct CMimeItem *items, struct CShortHeader *head);
+
+//Extracts header to mail using ExtractShortHeader fcn.
+// items- translated header (see TranslateHeaderFcn)
+// CP- codepage used when no default found
+// head- header to be filled with values extracted from items, in unicode (wide char)
+void ExtractHeader(struct CMimeItem *items, int &CP, struct CHeader *head);
+
+//Deletes items in CShortHeader structure
+// head- structure whose items are deleted
+void DeleteShortHeaderContent(struct CShortHeader *head);
+
+//Deletes list of YAMN_MIMENAMES structures
+// Names- pointer to first item of list
+void DeleteNames(CMimeNames *Names);
+
+//Deletes list of YAMN_MIMESHORTNAMES structures
+// Names- pointer to first item of list
+void DeleteShortNames(CShortNames *Names);
+
+//Makes a string lowercase
+// string- string to be lowercased
+void inline ToLower(char *string);
+
+//--------------------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------
+
+void CopyToHeader(char *srcstart, char *srcend, char **dest, int mode)
+{
+ char *dst;
+
+ if (dest == nullptr)
+ return;
+ if (srcstart >= srcend)
+ return;
+
+ if ((mode == MIME_MAIL) && (((*srcstart == '"') && (*(srcend - 1) == '"')) || ((*srcstart == '<') && (*(srcend - 1) == '>')))) {
+ srcstart++;
+ srcend--;
+ }
+
+ if (srcstart >= srcend)
+ return;
+
+ if (nullptr != *dest)
+ delete[] * dest;
+ if (nullptr == (*dest = new char[srcend - srcstart + 1]))
+ return;
+
+ dst = *dest;
+
+ for (; srcstart < srcend; dst++, srcstart++) {
+ if (ENDLINE(srcstart)) {
+ while (ENDLINE(srcstart) || WS(srcstart)) srcstart++;
+ *dst = ' ';
+ srcstart--; //because at the end of "for loop" we increment srcstart
+ }
+ else
+ *dst = *srcstart;
+ }
+ *dst = 0;
+}
+
+void ExtractAddressFromLine(char *finder, char **storeto, char **storetonick)
+{
+ if (finder == nullptr) {
+ *storeto = *storetonick = nullptr;
+ return;
+ }
+ while (WS(finder)) finder++;
+ if ((*finder) != '<') {
+ char *finderend = finder + 1;
+ do {
+ if (ENDLINEWS(finderend)) //after endline information continues
+ finderend += 2;
+ while (!ENDLINE(finderend) && !EOS(finderend)) finderend++; //seek to the end of line or to the end of string
+ } while (ENDLINEWS(finderend));
+ finderend--;
+ while (WS(finderend) || ENDLINE(finderend)) finderend--; //find the end of text, no whitespace
+ if (*finderend != '>') //not '>' at the end of line
+ CopyToHeader(finder, finderend + 1, storeto, MIME_MAIL);
+ else //at the end of line, there's '>'
+ {
+ char *finder2 = finderend;
+ while ((*finder2 != '<') && (finder2 > finder)) finder2--; //go to matching '<' or to the start
+ CopyToHeader(finder2, finderend + 1, storeto, MIME_MAIL);
+ if (*finder2 == '<') //if we found '<', the rest copy as from nick
+ {
+ finder2--;
+ while (WS(finder2) || ENDLINE(finder2)) finder2--; //parse whitespace
+ CopyToHeader(finder, finder2 + 1, storetonick, MIME_MAIL); //and store nickname
+ }
+ }
+ }
+ else {
+ char *finderend = finder + 1;
+ do {
+ if (ENDLINEWS(finderend)) //after endline information continues
+ finderend += 2;
+ while (!ENDLINE(finderend) && (*finderend != '>') && !EOS(finderend)) finderend++; //seek to the matching < or to the end of line or to the end of string
+ } while (ENDLINEWS(finderend));
+ CopyToHeader(finder, finderend + 1, storeto, MIME_MAIL); //go to first '>' or to the end and copy
+ finder = finderend + 1;
+ while (WS(finder)) finder++; //parse whitespace
+ if (!ENDLINE(finder) && !EOS(finder)) //if there are chars yet, it's nick
+ {
+ finderend = finder + 1;
+ while (!ENDLINE(finderend) && !EOS(finderend)) finderend++; //seek to the end of line or to the end of string
+ finderend--;
+ while (WS(finderend)) finderend--; //find the end of line, no whitespace
+ CopyToHeader(finder, finderend + 1, storetonick, MIME_MAIL);
+ }
+ }
+}
+
+void ExtractStringFromLine(char *finder, char **storeto)
+{
+ if (finder == nullptr) {
+ *storeto = nullptr;
+ return;
+ }
+ while (WS(finder)) finder++;
+ char *finderend = finder;
+
+ do {
+ if (ENDLINEWS(finderend)) finderend++; //after endline information continues
+ while (!ENDLINE(finderend) && !EOS(finderend)) finderend++;
+ } while (ENDLINEWS(finderend));
+ finderend--;
+ while (WS(finderend)) finderend--; //find the end of line, no whitespace
+ CopyToHeader(finder, finderend + 1, storeto, MIME_PLAIN);
+}
+
+char *ExtractFromContentType(char *ContentType, char *value)
+{
+ char *lowered = _strdup(ContentType);
+ ToLower(lowered);
+ char *finder = strstr(lowered, value);
+ if (finder == nullptr) {
+ free(lowered);
+ return nullptr;
+ }
+ finder = finder - lowered + ContentType;
+ free(lowered);
+
+ char *temp, *copier;
+ char *CopiedString;
+
+ temp = finder - 1;
+ while ((temp > ContentType) && WS(temp)) temp--; //now we have to find, if the word "Charset=" is located after ';' like "; Charset="
+ if (*temp != ';' && !ENDLINE(temp) && temp != ContentType)
+ return nullptr;
+ finder = finder + mir_strlen(value); //jump over value string
+
+ while (WS(finder)) finder++; //jump over whitespaces
+ temp = finder;
+ while (*temp != 0 && *temp != ';') temp++; //jump to the end of setting (to the next ;)
+ temp--;
+ while (WS(temp)) temp--; //remove whitespaces from the end
+ if (*finder == '\"') { //remove heading and tailing quotes
+ finder++;
+ if (*temp == '\"') temp--;
+ }
+ if (nullptr == (CopiedString = new char[++temp - finder + 1]))
+ return nullptr;
+ for (copier = CopiedString; finder != temp; *copier++ = *finder++); //copy string
+ *copier = 0; //and end it with zero character
+
+ return CopiedString;
+}
+
+void ExtractShortHeader(struct CMimeItem *items, struct CShortHeader *head)
+{
+ for (; items != nullptr; items = items->Next) {
+ //at the start of line
+ //MessageBox(NULL,items->value,items->name,0);
+ if (0 == _strnicmp(items->name, "From", 4)) {
+ if (items->value == nullptr)
+ continue;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Extracting from>");
+ #endif
+ ExtractAddressFromLine(items->value, &head->From, &head->FromNick);
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "</Extracting>\n");
+ #endif
+ }
+ else if (0 == _strnicmp(items->name, "Return-Path", 11)) {
+ if (items->value == nullptr)
+ continue;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Extracting return-path>");
+ #endif
+ ExtractAddressFromLine(items->value, &head->ReturnPath, &head->ReturnPathNick);
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "</Extracting>\n");
+ #endif
+ }
+ else if (0 == _strnicmp(items->name, "Subject", 7)) {
+ if (items->value == nullptr)
+ continue;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Extracting subject>");
+ #endif
+ ExtractStringFromLine(items->value, &head->Subject);
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "</Extracting>\n");
+ #endif
+ }
+ else if (0 == _strnicmp(items->name, "Body", 4)) {
+ if (items->value == nullptr)
+ continue;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Extracting body>");
+ #endif
+ ExtractStringFromLine(items->value, &head->Body);
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "</Extracting>\n");
+ #endif
+ }
+ else if (0 == _strnicmp(items->name, "Date", 4)) {
+ if (items->value == nullptr)
+ continue;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Extracting date>");
+ #endif
+ ExtractStringFromLine(items->value, &head->Date);
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "</Extracting>\n");
+ #endif
+ }
+ else if (0 == _strnicmp(items->name, "Content-Type", 12)) {
+ if (items->value == nullptr)
+ continue;
+
+ char *ContentType = nullptr, *CharSetStr;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Extracting Content-Type>");
+ #endif
+ ExtractStringFromLine(items->value, &ContentType);
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "</Extracting>\n");
+ #endif
+ ToLower(ContentType);
+ if (nullptr != (CharSetStr = ExtractFromContentType(ContentType, "charset="))) {
+ head->CP = GetCharsetFromString(CharSetStr, mir_strlen(CharSetStr));
+ delete[] CharSetStr;
+ }
+ delete[] ContentType;
+ }
+ else if (0 == _strnicmp(items->name, "Importance", 10)) {
+ if (items->value == nullptr)
+ continue;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Extracting importance>");
+ #endif
+ if (head->Priority != -1) {
+ if (0 == strncmp(items->value, "low", 3))
+ head->Priority = 5;
+ else if (0 == strncmp(items->value, "normal", 6))
+ head->Priority = 3;
+ else if (0 == strncmp(items->value, "high", 4))
+ head->Priority = 1;
+ }
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "</Extracting>\n");
+ #endif
+ }
+ else if (0 == _strnicmp(items->name, "X-Priority", 10)) {
+ if (items->value == nullptr)
+ continue;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<X-Priority>");
+ #endif
+ if ((*items->value >= '1') && (*items->value <= '5'))
+ head->Priority = *items->value - '0';
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "</Extracting>\n");
+ #endif
+ }
+
+ }
+}
+
+void ExtractHeader(struct CMimeItem *items, int &CP, struct CHeader *head)
+{
+ struct CShortHeader ShortHeader;
+
+ memset(&ShortHeader, 0, sizeof(struct CShortHeader));
+ ShortHeader.Priority = ShortHeader.CP = -1;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Extracting header>\n");
+ #endif
+ ExtractShortHeader(items, &ShortHeader);
+
+ head->Priority = ShortHeader.Priority == -1 ? 3 : ShortHeader.Priority;
+ CP = ShortHeader.CP == -1 ? CP : ShortHeader.CP;
+ #ifdef DEBUG_DECODE
+ if (NULL != ShortHeader.From)
+ DebugLog(DecodeFile, "<Decoded from>%s</Decoded)\n", ShortHeader.From);
+ if (NULL != ShortHeader.FromNick)
+ DebugLog(DecodeFile, "<Decoded from-nick>%s</Decoded)\n", ShortHeader.FromNick);
+ if (NULL != ShortHeader.ReturnPath)
+ DebugLog(DecodeFile, "<Decoded return-path>%s</Decoded)\n", ShortHeader.ReturnPath);
+ if (NULL != ShortHeader.ReturnPathNick)
+ DebugLog(DecodeFile, "<Decoded return-path nick>%s</Decoded)\n", ShortHeader.ReturnPathNick);
+ if (NULL != ShortHeader.Subject)
+ DebugLog(DecodeFile, "<Decoded subject>%s</Decoded)\n", ShortHeader.Subject);
+ if (NULL != ShortHeader.Date)
+ DebugLog(DecodeFile, "<Decoded date>%s</Decoded)\n", ShortHeader.Date);
+ DebugLog(DecodeFile, "</Extracting header>\n");
+ DebugLog(DecodeFile, "<Convert>\n");
+ #endif
+
+ ConvertCodedStringToUnicode(ShortHeader.From, &head->From, CP, MIME_PLAIN);
+
+ #ifdef DEBUG_DECODE
+ if (NULL != head->From)
+ DebugLogW(DecodeFile, L"<Converted from>%s</Converted>\n", head->From);
+ #endif
+ ConvertCodedStringToUnicode(ShortHeader.FromNick, &head->FromNick, CP, MIME_MAIL);
+ #ifdef DEBUG_DECODE
+ if (NULL != head->FromNick)
+ DebugLogW(DecodeFile, L"<Converted from-nick>%s</Converted>\n", head->FromNick);
+ #endif
+ ConvertCodedStringToUnicode(ShortHeader.ReturnPath, &head->ReturnPath, CP, MIME_PLAIN);
+ #ifdef DEBUG_DECODE
+ if (NULL != head->ReturnPath)
+ DebugLogW(DecodeFile, L"<Converted return-path>%s</Converted>\n", head->ReturnPath);
+ #endif
+ ConvertCodedStringToUnicode(ShortHeader.ReturnPathNick, &head->ReturnPathNick, CP, MIME_MAIL);
+ #ifdef DEBUG_DECODE
+ if (NULL != head->ReturnPathNick)
+ DebugLogW(DecodeFile, L"<Converted return-path nick>%s</Converted>\n", head->ReturnPathNick);
+ #endif
+ ConvertCodedStringToUnicode(ShortHeader.Subject, &head->Subject, CP, MIME_PLAIN);
+ #ifdef DEBUG_DECODE
+ if (NULL != head->Subject)
+ DebugLogW(DecodeFile, L"<Converted subject>%s</Converted>\n", head->Subject);
+ #endif
+ ConvertCodedStringToUnicode(ShortHeader.Date, &head->Date, CP, MIME_PLAIN);
+ #ifdef DEBUG_DECODE
+ if (NULL != head->Date)
+ DebugLogW(DecodeFile, L"<Converted date>%s</Converted>\n", head->Date);
+ #endif
+
+ ConvertCodedStringToUnicode(ShortHeader.Body, &head->Body, CP, MIME_PLAIN);
+ #ifdef DEBUG_DECODE
+ if (NULL != head->Body)
+ DebugLogW(DecodeFile, L"<Converted Body>%s</Converted>\n", head->Body);
+ #endif
+
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "</Convert>\n");
+ #endif
+
+ DeleteShortHeaderContent(&ShortHeader);
+
+ // head->From=L"Frommmm";
+ // head->Subject=L"Subject";
+ return;
+}
+
+void DeleteShortHeaderContent(struct CShortHeader *head)
+{
+ if (head->From != nullptr) delete[] head->From;
+ if (head->FromNick != nullptr) delete[] head->FromNick;
+ if (head->ReturnPath != nullptr) delete[] head->ReturnPath;
+ if (head->ReturnPathNick != nullptr) delete[] head->ReturnPathNick;
+ if (head->Subject != nullptr) delete[] head->Subject;
+ if (head->Date != nullptr) delete[] head->Date;
+ if (head->To != nullptr) DeleteShortNames(head->To);
+ if (head->Cc != nullptr) DeleteShortNames(head->Cc);
+ if (head->Bcc != nullptr) DeleteShortNames(head->Bcc);
+ if (head->Body != nullptr) delete[] head->Body;
+}
+
+void DeleteHeaderContent(struct CHeader *head)
+{
+ if (head->From != nullptr) delete[] head->From;
+ if (head->FromNick != nullptr) delete[] head->FromNick;
+ if (head->ReturnPath != nullptr) delete[] head->ReturnPath;
+ if (head->ReturnPathNick != nullptr) delete[] head->ReturnPathNick;
+ if (head->Subject != nullptr) delete[] head->Subject;
+ if (head->Date != nullptr) delete[] head->Date;
+ if (head->Body != nullptr) delete[] head->Body;
+ if (head->To != nullptr) DeleteNames(head->To);
+ if (head->Cc != nullptr) DeleteNames(head->Cc);
+ if (head->Bcc != nullptr) DeleteNames(head->Bcc);
+}
+
+void DeleteNames(CMimeNames *Names)
+{
+ CMimeNames *Parser = Names;
+ for (; Parser != nullptr; Parser = Parser->Next) {
+ if (Parser->Value != nullptr)
+ delete[] Parser->Value;
+ if (Parser->ValueNick != nullptr)
+ delete[] Parser->ValueNick;
+
+ CMimeNames *Old = Parser;
+ Parser = Parser->Next;
+ delete Old;
+ }
+}
+
+void DeleteShortNames(CShortNames *Names)
+{
+ CShortNames *Parser = Names;
+ for (; Parser != nullptr; Parser = Parser->Next) {
+ if (Parser->Value != nullptr)
+ delete[] Parser->Value;
+ if (Parser->ValueNick != nullptr)
+ delete[] Parser->ValueNick;
+
+ CShortNames *Old = Parser;
+ Parser = Parser->Next;
+ delete Old;
+ }
+}
+
+
+void inline ToLower(char *string)
+{
+ for (; *string != 0; string++)
+ if (*string >= 'A' && *string <= 'Z') *string = *string - 'A' + 'a';
+}
+
+#define TE_UNKNOWN
+#define TE_QUOTEDPRINTABLE 1
+#define TE_BASE64 2
+struct APartDataType
+{
+ char *Src;//Input
+ char *ContType;
+ int CodePage;
+ char *TransEnc;
+ uint8_t TransEncType; //TE_something
+ char *body;
+ int bodyLen;
+ wchar_t *wBody;
+};
+
+
+void ParseAPart(APartDataType *data)
+{
+ size_t len = mir_strlen(data->Src);
+ try {
+ char *finder = data->Src;
+ char *prev1, *prev2, *prev3;
+
+ while (finder <= (data->Src + len)) {
+ while (ENDLINEWS(finder)) finder++;
+
+ //at the start of line
+ if (finder > data->Src) {
+ if (*(finder - 2) == '\r' || *(finder - 2) == '\n')
+ *(finder - 2) = 0;
+ if (*(finder - 1) == '\r' || *(finder - 1) == '\n')
+ *(finder - 1) = 0;
+ }
+ prev1 = finder;
+
+ while (*finder != ':' && !EOS(finder) && !ENDLINE(finder)) finder++;
+ if (ENDLINE(finder) || EOS(finder)) {
+ // no ":" in the line? here the body begins;
+ data->body = prev1;
+ break;
+ }
+ prev2 = finder++;
+
+ while (WS(finder) && !EOS(finder)) finder++;
+ if (!EOS(finder))
+ prev3 = finder;
+ else
+ break;
+
+ do {
+ if (ENDLINEWS(finder)) finder += 2; //after endline information continues
+ while (!ENDLINE(finder) && !EOS(finder)) finder++;
+ } while (ENDLINEWS(finder));
+
+ if (!_strnicmp(prev1, "Content-type", prev2 - prev1)) {
+ data->ContType = prev3;
+ }
+ else if (!_strnicmp(prev1, "Content-Transfer-Encoding", prev2 - prev1)) {
+ data->TransEnc = prev3;
+ }
+
+ if (EOS(finder))
+ break;
+ finder++;
+ if (ENDLINE(finder)) {
+ finder++;
+ if (ENDLINE(finder)) {
+ // end of headers. message body begins
+ if (finder > data->Src) {
+ if (*(finder - 2) == '\r' || *(finder - 2) == '\n')
+ *(finder - 2) = 0;
+ if (*(finder - 1) == '\r' || *(finder - 1) == '\n')
+ *(finder - 1) = 0;
+ }
+ finder++;
+ if (ENDLINE(finder))finder++;
+ prev1 = finder;
+ while (!EOS(finder + 1))finder++;
+ if (ENDLINE(finder))finder--;
+ prev2 = finder;
+ if (prev2 > prev1) { // yes, we have body
+ data->body = prev1;
+ }
+ break; // there is nothing else
+ }
+ }
+ }
+ }
+ catch (...) {
+ MessageBox(nullptr, TranslateT("Translate header error"), L"", 0);
+ }
+ if (data->body) data->bodyLen = (int)mir_strlen(data->body);
+}
+
+//from decode.cpp
+int DecodeQuotedPrintable(char *Src, char *Dst, int DstLen, BOOL isQ);
+int DecodeBase64(char *Src, char *Dst, int DstLen);
+int ConvertStringToUnicode(char *stream, unsigned int cp, wchar_t **out);
+
+wchar_t *ParseMultipartBody(char *src, char *bond)
+{
+ char *srcback = _strdup(src);
+ size_t sizebond = mir_strlen(bond);
+ int numparts = 1;
+ int i;
+ char *courbond = srcback;
+ wchar_t *dest;
+ for (; (courbond = strstr(courbond, bond)); numparts++, courbond += sizebond);
+ APartDataType *partData = new APartDataType[numparts];
+ memset(partData, 0, sizeof(APartDataType) * numparts);
+ partData[0].Src = courbond = srcback;
+ for (i = 1; (courbond = strstr(courbond, bond)); i++, courbond += sizebond) {
+ *(courbond - 2) = 0;
+ partData[i].Src = courbond + sizebond;
+ while (ENDLINE(partData[i].Src)) partData[i].Src++;
+ }
+ size_t resultSize = 0;
+ for (i = 0; i < numparts; i++) {
+ ParseAPart(&partData[i]);
+ if (partData[i].body) {
+ if (partData[i].TransEnc) {
+ if (!_stricmp(partData[i].TransEnc, "base64")) partData[i].TransEncType = TE_BASE64;
+ else if (!_stricmp(partData[i].TransEnc, "quoted-printable"))partData[i].TransEncType = TE_QUOTEDPRINTABLE;
+ }
+ if (partData[i].ContType) {
+ char *CharSetStr;
+ if (nullptr != (CharSetStr = ExtractFromContentType(partData[i].ContType, "charset="))) {
+ partData[i].CodePage = GetCharsetFromString(CharSetStr, mir_strlen(CharSetStr));
+ delete[] CharSetStr;
+ }
+ }
+ if (partData[i].ContType && !_strnicmp(partData[i].ContType, "text", 4)) {
+ char *localBody = nullptr;
+ switch (partData[i].TransEncType) {
+ case TE_BASE64:
+ {
+ int size = partData[i].bodyLen * 3 / 4 + 5;
+ localBody = new char[size + 1];
+ DecodeBase64(partData[i].body, localBody, size);
+ }break;
+ case TE_QUOTEDPRINTABLE:
+ {
+ int size = partData[i].bodyLen + 2;
+ localBody = new char[size + 1];
+ DecodeQuotedPrintable(partData[i].body, localBody, size, FALSE);
+ }break;
+ }
+ ConvertStringToUnicode(localBody ? localBody : partData[i].body, partData[i].CodePage, &partData[i].wBody);
+ if (localBody) delete[] localBody;
+ }
+ else if (partData[i].ContType && !_strnicmp(partData[i].ContType, "multipart/", 10)) {
+ //Multipart in mulitipart recursive? should be SPAM. Ah well
+ char *bondary = nullptr;
+ if (nullptr != (bondary = ExtractFromContentType(partData[i].ContType, "boundary="))) {
+ partData[i].wBody = ParseMultipartBody(partData[i].body, bondary);
+ delete[] bondary;
+ }
+ else goto FailBackRaw; //multipart with no boundary? badly formatted messages.
+ }
+ else {
+FailBackRaw:
+ ConvertStringToUnicode(partData[i].body, partData[i].CodePage, &partData[i].wBody);
+ }
+ resultSize += mir_wstrlen(partData[i].wBody);
+ }// if (partData[i].body)
+ resultSize += 100 + 4 + 3; //cr+nl+100+ 3*bullet
+ }
+ dest = new wchar_t[resultSize + 1];
+ size_t destpos = 0;
+ for (i = 0; i < numparts; i++) {
+ if (i) { // part before first boudary should not have headers
+ char infoline[1024]; size_t linesize = 0;
+ mir_snprintf(infoline, "%s %d", Translate("Part"), i);
+ linesize = mir_strlen(infoline);
+ if (partData[i].TransEnc) {
+ mir_snprintf(infoline + linesize, _countof(infoline) - linesize, "; %s", partData[i].TransEnc);
+ linesize = mir_strlen(infoline);
+ }
+ if (partData[i].ContType) {
+ char *CharSetStr = strchr(partData[i].ContType, ';');
+ if (CharSetStr) {
+ CharSetStr[0] = 0;
+ mir_snprintf(infoline + linesize, _countof(infoline) - linesize, "; %s", partData[i].ContType);
+ linesize = mir_strlen(infoline);
+ partData[i].ContType = CharSetStr + 1;
+ if (nullptr != (CharSetStr = ExtractFromContentType(partData[i].ContType, "charset="))) {
+ mir_snprintf(infoline + linesize, _countof(infoline) - linesize, "; %s", CharSetStr);
+ linesize = mir_strlen(infoline);
+ delete[] CharSetStr;
+ }
+ if (nullptr != (CharSetStr = ExtractFromContentType(partData[i].ContType, "name="))) {
+ mir_snprintf(infoline + linesize, _countof(infoline) - linesize, "; \"%s\"", CharSetStr);
+ linesize = mir_strlen(infoline);
+ delete[] CharSetStr;
+ }
+ }
+ else {
+ mir_snprintf(infoline + linesize, _countof(infoline) - linesize, "; %s", partData[i].ContType);
+ linesize = mir_strlen(infoline);
+ }
+ }
+ mir_snprintf(infoline + linesize, _countof(infoline) - linesize, ".\r\n");
+ {
+ wchar_t *temp = nullptr;
+ dest[destpos] = dest[destpos + 1] = dest[destpos + 2] = 0x2022; // bullet;
+ destpos += 3;
+ ConvertStringToUnicode(infoline, CP_ACP, &temp);
+ size_t wsize = mir_wstrlen(temp);
+ mir_wstrcpy(&dest[destpos], temp);
+ destpos += wsize;
+ delete[] temp;
+ }
+ } // if (i)
+
+ if (partData[i].wBody) {
+ size_t wsize = mir_wstrlen(partData[i].wBody);
+ mir_wstrcpy(&dest[destpos], partData[i].wBody);
+ destpos += wsize;
+ delete[] partData[i].wBody;
+ }
+ }
+
+ free(srcback);
+ delete[] partData;
+ dest[resultSize] = 0;//just in case
+ return dest;
+}
|