summaryrefslogtreecommitdiff
path: root/protocols/YAMN/src/mails
diff options
context:
space:
mode:
authordartraiden <wowemuh@gmail.com>2023-01-14 01:30:59 +0300
committerdartraiden <wowemuh@gmail.com>2023-01-14 01:30:59 +0300
commitde40f3be3f08487937525c2ef096dad665dda61d (patch)
treeeb1205f8dca7c30b561a2776f9527072bd92eaf1 /protocols/YAMN/src/mails
parentdd743899a769120ba2321230afddd6e4f1271872 (diff)
Convert sources to CR+LF
Diffstat (limited to 'protocols/YAMN/src/mails')
-rw-r--r--protocols/YAMN/src/mails/decode.cpp1068
-rw-r--r--protocols/YAMN/src/mails/mails.cpp946
-rw-r--r--protocols/YAMN/src/mails/mime.cpp1390
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;
+}