From a0e7d1f91b0c85f5fdc13bc5cc505018e63d465d Mon Sep 17 00:00:00 2001 From: George Hazan Date: Tue, 10 Oct 2023 14:13:03 +0300 Subject: =?UTF-8?q?fixes=20#3724=20(YAMN:=20=D0=BB=D0=B8=D1=88=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=BF=D1=80=D0=BE=D0=B1=D0=B5=D0=BB=D1=8B=20=D0=B2=20?= =?UTF-8?q?=D0=B7=D0=B0=D0=B3=D0=BE=D0=BB=D0=BE=D0=B2=D0=BA=D0=B5=20=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D1=8C=D0=BC=D0=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- protocols/YAMN/src/browser/mailbrowser.cpp | 76 +++--- protocols/YAMN/src/mails/decode.cpp | 140 +++++------ protocols/YAMN/src/mails/mime.cpp | 377 ++++++++++++++--------------- protocols/YAMN/src/stdafx.h | 3 +- 4 files changed, 275 insertions(+), 321 deletions(-) (limited to 'protocols') diff --git a/protocols/YAMN/src/browser/mailbrowser.cpp b/protocols/YAMN/src/browser/mailbrowser.cpp index 727110be89..24a2effdff 100644 --- a/protocols/YAMN/src/browser/mailbrowser.cpp +++ b/protocols/YAMN/src/browser/mailbrowser.cpp @@ -433,7 +433,7 @@ int ChangeExistingMailStatus(HWND hListView, CAccount *ActualAccount) void MimeDateToLocalizedDateTime(char *datein, wchar_t *dateout, int lendateout); int AddNewMailsToListView(HWND hListView, CAccount *ActualAccount, uint32_t nflags) { - wchar_t *FromStr; + CMStringW FromStr; wchar_t SizeStr[20]; wchar_t LocalDateStr[128]; @@ -441,11 +441,10 @@ int AddNewMailsToListView(HWND hListView, CAccount *ActualAccount, uint32_t nfla LVFINDINFO fi; int foundi = 0, lfoundi = 0; - struct CHeader UnicodeHeader; + CHeader UnicodeHeader; BOOL Loaded, Extracted, FromStrNew = FALSE; memset(&item, 0, sizeof(item)); - memset(&UnicodeHeader, 0, sizeof(UnicodeHeader)); if (hListView != nullptr) { item.mask = LVIF_TEXT | LVIF_PARAM; @@ -472,9 +471,8 @@ int AddNewMailsToListView(HWND hListView, CAccount *ActualAccount, uint32_t nfla NewMailPopup.PluginData = nullptr; //it's new mail popup for (HYAMNMAIL msgq = (HYAMNMAIL)ActualAccount->Mails; msgq != nullptr; msgq = msgq->Next, lfoundi++) { - // now we hide mail pointer to item's lParam member. We can later use it to retrieve mail datas - - Extracted = FALSE; FromStr = nullptr; FromStrNew = FALSE; + // now we hide mail pointer to item's lParam member. We can later use it to retrieve mail datas + Extracted = FALSE; FromStr.Empty(); if (hListView != nullptr) { fi.lParam = (LPARAM)msgq; @@ -500,32 +498,23 @@ int AddNewMailsToListView(HWND hListView, CAccount *ActualAccount, uint32_t nfla if (!Extracted) ExtractHeader(msgq->MailData->TranslatedHeader, msgq->MailData->CP, &UnicodeHeader); Extracted = TRUE; - if ((UnicodeHeader.From != nullptr) && (UnicodeHeader.FromNick != nullptr)) { - size_t size = mir_wstrlen(UnicodeHeader.From) + mir_wstrlen(UnicodeHeader.FromNick) + 4; - FromStr = new wchar_t[size]; - mir_snwprintf(FromStr, size, L"%s <%s>", UnicodeHeader.FromNick, UnicodeHeader.From); - FromStrNew = TRUE; - } - else if (UnicodeHeader.From != nullptr) - FromStr = UnicodeHeader.From; - else if (UnicodeHeader.FromNick != nullptr) - FromStr = UnicodeHeader.FromNick; - else if (UnicodeHeader.ReturnPath != nullptr) - FromStr = UnicodeHeader.ReturnPath; - - if (nullptr == FromStr) { - FromStr = L""; - FromStrNew = FALSE; - } + if (!UnicodeHeader.wszFrom.IsEmpty() && !UnicodeHeader.wszFromNick.IsEmpty()) + FromStr = UnicodeHeader.wszFromNick + L" " + UnicodeHeader.wszFrom; + else if (!UnicodeHeader.wszFrom.IsEmpty()) + FromStr = UnicodeHeader.wszFrom; + else if (!UnicodeHeader.wszFromNick.IsEmpty()) + FromStr = UnicodeHeader.wszFromNick; + else if (!UnicodeHeader.wszReturnPath.IsEmpty()) + FromStr = UnicodeHeader.wszReturnPath; } if ((hListView != nullptr) && (msgq->Flags & YAMN_MSG_DISPLAY)) { item.iSubItem = 0; - item.pszText = FromStr; + item.pszText = FromStr.GetBuffer(); item.iItem = SendMessage(hListView, LVM_INSERTITEM, 0, (LPARAM)&item); item.iSubItem = 1; - item.pszText = (nullptr != UnicodeHeader.Subject ? UnicodeHeader.Subject : (wchar_t *)L""); + item.pszText = UnicodeHeader.wszSubject.GetBuffer(); SendMessage(hListView, LVM_SETITEMTEXT, (WPARAM)item.iItem, (LPARAM)&item); item.iSubItem = 2; @@ -548,7 +537,7 @@ int AddNewMailsToListView(HWND hListView, CAccount *ActualAccount, uint32_t nfla if ((nflags & YAMN_ACC_POP) && (ActualAccount->Flags & YAMN_ACC_POPN) && (msgq->Flags & YAMN_MSG_POPUP) && (msgq->Flags & YAMN_MSG_NEW)) { mir_wstrncpy(NewMailPopup.lpwzContactName, FromStr, _countof(NewMailPopup.lpwzContactName)); - mir_wstrncpy(NewMailPopup.lpwzText, UnicodeHeader.Subject, _countof(NewMailPopup.lpwzText)); + mir_wstrncpy(NewMailPopup.lpwzText, UnicodeHeader.wszSubject, _countof(NewMailPopup.lpwzText)); auto *MailParam = new YAMN_MAILSHOWPARAM; MailParam->account = ActualAccount; @@ -562,11 +551,6 @@ int AddNewMailsToListView(HWND hListView, CAccount *ActualAccount, uint32_t nfla if (FromStrNew) delete[] FromStr; - - if (Extracted) { - DeleteHeaderContent(&UnicodeHeader); - memset(&UnicodeHeader, 0, sizeof(UnicodeHeader)); - } } return TRUE; @@ -1116,7 +1100,6 @@ static LRESULT CALLBACK SplitterSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, return mir_callNextSubclass(hwnd, SplitterSubclassProc, msg, wParam, lParam); } -void ConvertCodedStringToUnicode(char *stream, wchar_t **storeto, uint32_t cp, int mode); int ConvertStringToUnicode(char *stream, unsigned int cp, wchar_t **out); INT_PTR CALLBACK DlgProcYAMNShowMessage(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) @@ -1174,41 +1157,40 @@ INT_PTR CALLBACK DlgProcYAMNShowMessage(HWND hDlg, UINT msg, WPARAM wParam, LPAR char *contentType = nullptr, *transEncoding = nullptr, *body = nullptr; //should not be delete[]-ed for (Header = MailParam->mail->MailData->TranslatedHeader; Header != nullptr; Header = Header->Next) { wchar_t *str1 = nullptr; - wchar_t *str2 = nullptr; - wchar_t str_nul[2] = { 0 }; + if (!body) if (!_stricmp(Header->name, "Body")) { body = Header->value; continue; } if (!contentType) if (!_stricmp(Header->name, "Content-Type")) contentType = Header->value; if (!transEncoding) if (!_stricmp(Header->name, "Content-Transfer-Encoding")) transEncoding = Header->value; - //ConvertCodedStringToUnicode(Header->name,&str1,MailParam->mail->MailData->CP,1); { int streamsize = MultiByteToWideChar(20127, 0, Header->name, -1, nullptr, 0); str1 = (wchar_t *)malloc(sizeof(wchar_t) * (streamsize + 1)); MultiByteToWideChar(20127, 0, Header->name, -1, str1, streamsize);//US-ASCII } - ConvertCodedStringToUnicode(Header->value, &str2, MailParam->mail->MailData->CP, 1); - if (!str2) { str2 = (wchar_t *)str_nul; }// the header value may be NULL + + CMStringW wszTmp = ConvertCodedStringToUnicode(Header->value, MailParam->mail->MailData->CP, 1); if (!From) if (!_stricmp(Header->name, "From")) { - From = new wchar_t[mir_wstrlen(str2) + 1]; - mir_wstrcpy(From, str2); + From = new wchar_t[mir_wstrlen(wszTmp) + 1]; + mir_wstrcpy(From, wszTmp); } + if (!Subj) if (!_stricmp(Header->name, "Subject")) { - Subj = new wchar_t[mir_wstrlen(str2) + 1]; - mir_wstrcpy(Subj, str2); + Subj = new wchar_t[mir_wstrlen(wszTmp) + 1]; + mir_wstrcpy(Subj, wszTmp); } - //if (!hasBody) if (!mir_strcmp(Header->name,"Body")) hasBody = true; + int count = 0; wchar_t **split = nullptr; int ofs = 0; + auto *str2 = wszTmp.GetBuffer(); while (str2[ofs]) { - if ((str2[ofs] == 0x266A) || (str2[ofs] == 0x25D9) || (str2[ofs] == 0x25CB) || - (str2[ofs] == 0x09) || (str2[ofs] == 0x0A) || (str2[ofs] == 0x0D))count++; + if ((str2[ofs] == 0x266A) || (str2[ofs] == 0x25D9) || (str2[ofs] == 0x25CB) || (str2[ofs] == 0x09) || (str2[ofs] == 0x0A) || (str2[ofs] == 0x0D)) + count++; ofs++; } split = new wchar_t *[count + 1]; count = 0; ofs = 0; split[0] = str2; while (str2[ofs]) { - if ((str2[ofs] == 0x266A) || (str2[ofs] == 0x25D9) || (str2[ofs] == 0x25CB) || - (str2[ofs] == 0x09) || (str2[ofs] == 0x0A) || (str2[ofs] == 0x0D)) { + if ((str2[ofs] == 0x266A) || (str2[ofs] == 0x25D9) || (str2[ofs] == 0x25CB) || (str2[ofs] == 0x09) || (str2[ofs] == 0x0A) || (str2[ofs] == 0x0D)) { if (str2[ofs - 1]) { count++; } @@ -1239,8 +1221,6 @@ INT_PTR CALLBACK DlgProcYAMNShowMessage(HWND hDlg, UINT msg, WPARAM wParam, LPAR if (str1) free(str1); - if (str2 != (wchar_t *)str_nul) - free(str2); } if (body) { wchar_t *bodyDecoded = nullptr; diff --git a/protocols/YAMN/src/mails/decode.cpp b/protocols/YAMN/src/mails/decode.cpp index 7306376c2e..436f55c641 100644 --- a/protocols/YAMN/src/mails/decode.cpp +++ b/protocols/YAMN/src/mails/decode.cpp @@ -155,56 +155,12 @@ int CPLENALL = _countof(CodePageNamesAll); struct _tcptable *CodePageNamesSupp; int CPLENSUPP = 1; -//Gets codepage ID from string representing charset such as "iso-8859-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; @@ -238,6 +194,12 @@ int GetCharsetFromString(char *input, size_t size) return -1; //not found } +///////////////////////////////////////////////////////////////////////////////////////// +// 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) { if (HexValue >= '0' && HexValue <= '9') { @@ -255,6 +217,12 @@ int FromHexa(char HexValue, char *DecValue) return 0; } +///////////////////////////////////////////////////////////////////////////////////////// +// 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) { if (Base64Value >= 'A' && Base64Value <= 'Z') { @@ -284,6 +252,14 @@ int FromBase64(char Base64Value, char *DecValue) return 0; } +///////////////////////////////////////////////////////////////////////////////////////// +// 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) { #ifdef DEBUG_DECODEQUOTED @@ -327,6 +303,13 @@ int DecodeQuotedPrintable(char *Src, char *Dst, int DstLen, BOOL isQ) return 1; } +///////////////////////////////////////////////////////////////////////////////////////// +// 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) { int Result = 0; @@ -366,7 +349,11 @@ end: return 1; } - +///////////////////////////////////////////////////////////////////////////////////////// +// 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) { @@ -403,11 +390,10 @@ int ConvertStringToUnicode(char *stream, unsigned int cp, wchar_t **out) 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; + + delete[] *out; } - else - dest = temp; + else dest = temp; *out = temp; if (Index == -1) { @@ -421,21 +407,25 @@ int ConvertStringToUnicode(char *stream, unsigned int cp, wchar_t **out) return 1; } -void ConvertCodedStringToUnicode(char *stream, wchar_t **storeto, uint32_t cp, int mode) +///////////////////////////////////////////////////////////////////////////////////////// +// 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) + +CMStringW ConvertCodedStringToUnicode(char *stream, uint32_t cp, int mode) { char *start = stream, *finder, *finderend; char Encoding = 0; + CMStringW ret; if (stream == nullptr) - return; + return ret; - while (WS(start)) start++; - wchar_t *tempstore = nullptr; - if (!ConvertStringToUnicode(stream, cp, &tempstore))return; + while (WS(start)) + start++; - size_t tempstoreLength = mir_wstrlen(tempstore); - - size_t outind = 0; while (*start != 0) { if (CODES(start)) { finder = start + 2; finderend = finder; @@ -499,36 +489,32 @@ void ConvertCodedStringToUnicode(char *stream, wchar_t **storeto, uint32_t cp, i 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; + + // if string continues and there's some whitespace, add space to string that is to be converted + if (WS(finderend)) 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; - } + if (ConvertStringToUnicode(DecodedResult, cp, &oneWord)) + ret.Append(oneWord); + delete oneWord; oneWord = nullptr; delete[] DecodedResult; start = finderend; } - else if (!EOS(start)) start++; + else if (!EOS(start)) + start++; } - else if (!EOS(start)) start++; + else if (!EOS(start)) + start++; } else { NotEncoded: - tempstore[outind] = tempstore[start - stream]; - outind++; - if (outind > tempstoreLength) break; + ret.AppendChar(*start); start++; } } - tempstore[outind] = 0; - *storeto = tempstore; + + return ret; } diff --git a/protocols/YAMN/src/mails/mime.cpp b/protocols/YAMN/src/mails/mime.cpp index 2a2e7b4665..265bab30d9 100644 --- a/protocols/YAMN/src/mails/mime.cpp +++ b/protocols/YAMN/src/mails/mime.cpp @@ -6,69 +6,26 @@ #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 +///////////////////////////////////////////////////////////////////////////////////////// +// Makes a string lowercase // string- string to be lowercased -void inline ToLower(char *string); - -//-------------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------------- -void CopyToHeader(char *srcstart, char *srcend, char **dest, int mode) +void inline ToLower(char *string) { - char *dst; + for (; *string != 0; string++) + if (*string >= 'A' && *string <= 'Z') + *string = *string - 'A' + 'a'; +} +///////////////////////////////////////////////////////////////////////////////////////// +// 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 + +static void CopyToHeader(char *srcstart, char *srcend, char **dest, int mode) +{ if (dest == nullptr) return; if (srcstart >= srcend) @@ -87,21 +44,26 @@ void CopyToHeader(char *srcstart, char *srcend, char **dest, int mode) if (nullptr == (*dest = new char[srcend - srcstart + 1])) return; - dst = *dest; + char *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 + srcstart--; // because at the end of "for loop" we increment srcstart } - else - *dst = *srcstart; + else *dst = *srcstart; } *dst = 0; } -void ExtractAddressFromLine(char *finder, char **storeto, char **storetonick) +///////////////////////////////////////////////////////////////////////////////////////// +// 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 + +static void ExtractAddressFromLine(char *finder, char **storeto, char **storetonick) { if (finder == nullptr) { *storeto = *storetonick = nullptr; @@ -111,67 +73,85 @@ void ExtractAddressFromLine(char *finder, char **storeto, char **storetonick) if ((*finder) != '<') { char *finderend = finder + 1; do { - if (ENDLINEWS(finderend)) //after endline information continues + 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 (!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 + 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 '>' - { + else { // at the end of line, there's '>' char *finder2 = finderend; - while ((*finder2 != '<') && (finder2 > finder)) finder2--; //go to matching '<' or to the start + 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 + 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 + 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 + 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 + + // seek to the matching < or to the end of line or to the end of string + while (!ENDLINE(finderend) && (*finderend != '>') && !EOS(finderend)) + finderend++; } while (ENDLINEWS(finderend)); - CopyToHeader(finder, finderend + 1, storeto, MIME_MAIL); //go to first '>' or to the end and copy + + 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 - { + while (WS(finder)) // parse whitespace + finder++; + 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 + 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 + while (WS(finderend)) // find the end of line, no whitespace + finderend--; CopyToHeader(finder, finderend + 1, storetonick, MIME_MAIL); } } } -void ExtractStringFromLine(char *finder, char **storeto) +///////////////////////////////////////////////////////////////////////////////////////// +// Extracts simple text from string +// finder- source string +// storeto- pointer that receives address of string + +static void ExtractStringFromLine(char *finder, char **storeto) { if (finder == nullptr) { *storeto = nullptr; return; } - while (WS(finder)) finder++; + while (WS(finder)) + finder++; char *finderend = finder; do { - if (ENDLINEWS(finderend)) finderend++; //after endline information continues + 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 + while (WS(finderend)) // find the end of line, no whitespace + finderend--; CopyToHeader(finder, finderend + 1, storeto, MIME_PLAIN); } -char *ExtractFromContentType(char *ContentType, char *value) +///////////////////////////////////////////////////////////////////////////////////////// +// 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) { char *lowered = _strdup(ContentType); ToLower(lowered); @@ -183,37 +163,49 @@ char *ExtractFromContentType(char *ContentType, char *value) 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=" + char *temp = finder - 1; + while ((temp > ContentType) && WS(temp)) // now we have to find, if the word "Charset=" is located after ';' like "; Charset=" + temp--; if (*temp != ';' && !ENDLINE(temp) && temp != ContentType) return nullptr; - finder = finder + mir_strlen(value); //jump over value string + + finder = finder + mir_strlen(value); // jump over value string - while (WS(finder)) finder++; //jump over whitespaces + while (WS(finder)) // jump over whitespaces + finder++; temp = finder; - while (*temp != 0 && *temp != ';') temp++; //jump to the end of setting (to the next ;) + while (*temp != 0 && *temp != ';') // jump to the end of setting (to the next ;) + temp++; temp--; - while (WS(temp)) temp--; //remove whitespaces from the end - if (*finder == '\"') { //remove heading and tailing quotes + while (WS(temp)) // remove whitespaces from the end + temp--; + if (*finder == '\"') { // remove heading and tailing quotes finder++; - if (*temp == '\"') temp--; + 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 + + char *CopiedString = new char[++temp - finder + 1]; + + char *copier; + for (copier = CopiedString; finder != temp; *copier++ = *finder++); + *copier = 0; // and end it with zero character return CopiedString; } -void ExtractShortHeader(struct CMimeItem *items, struct CShortHeader *head) +///////////////////////////////////////////////////////////////////////////////////////// +// Extracts info from header text into header members +// Note that this function as well as 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(CMimeItem *items, CShortHeader *head) { for (; items != nullptr; items = items->Next) { - //at the start of line - //MessageBox(NULL,items->value,items->name,0); + // at the start of line + // MessageBox(NULL,items->value,items->name,0); if (0 == _strnicmp(items->name, "From", 4)) { if (items->value == nullptr) continue; @@ -322,11 +314,78 @@ void ExtractShortHeader(struct CMimeItem *items, struct CShortHeader *head) } } -void ExtractHeader(struct CMimeItem *items, int &CP, struct CHeader *head) +///////////////////////////////////////////////////////////////////////////////////////// +// Deletes list of YAMN_MIMENAMES structures +// Names- pointer to first item of list + +static 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; + } +} + +CHeader::~CHeader() +{ + DeleteNames(To); + DeleteNames(Cc); + DeleteNames(Bcc); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Deletes list of YAMN_MIMESHORTNAMES structures +// Names- pointer to first item of list + +static 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; + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Deletes items in CShortHeader structure +// head- structure whose items are deleted + +void DeleteShortHeaderContent(CShortHeader *head) { - struct CShortHeader ShortHeader; + 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; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// 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) - memset(&ShortHeader, 0, sizeof(struct CShortHeader)); +void ExtractHeader(CMimeItem *items, int &CP, CHeader *head) +{ + CShortHeader ShortHeader = {}; ShortHeader.Priority = ShortHeader.CP = -1; #ifdef DEBUG_DECODE DebugLog(DecodeFile, "\n"); @@ -352,39 +411,39 @@ void ExtractHeader(struct CMimeItem *items, int &CP, struct CHeader *head) DebugLog(DecodeFile, "\n"); #endif - ConvertCodedStringToUnicode(ShortHeader.From, &head->From, CP, MIME_PLAIN); + head->wszFrom = ConvertCodedStringToUnicode(ShortHeader.From, CP, MIME_PLAIN); #ifdef DEBUG_DECODE if (NULL != head->From) DebugLogW(DecodeFile, L"%s\n", head->From); #endif - ConvertCodedStringToUnicode(ShortHeader.FromNick, &head->FromNick, CP, MIME_MAIL); + head->wszFromNick = ConvertCodedStringToUnicode(ShortHeader.FromNick, CP, MIME_MAIL); #ifdef DEBUG_DECODE if (NULL != head->FromNick) DebugLogW(DecodeFile, L"%s\n", head->FromNick); #endif - ConvertCodedStringToUnicode(ShortHeader.ReturnPath, &head->ReturnPath, CP, MIME_PLAIN); + head->wszReturnPath = ConvertCodedStringToUnicode(ShortHeader.ReturnPath, CP, MIME_PLAIN); #ifdef DEBUG_DECODE if (NULL != head->ReturnPath) DebugLogW(DecodeFile, L"%s\n", head->ReturnPath); #endif - ConvertCodedStringToUnicode(ShortHeader.ReturnPathNick, &head->ReturnPathNick, CP, MIME_MAIL); + head->wszReturnPathNick = ConvertCodedStringToUnicode(ShortHeader.ReturnPathNick, CP, MIME_MAIL); #ifdef DEBUG_DECODE if (NULL != head->ReturnPathNick) DebugLogW(DecodeFile, L"%s\n", head->ReturnPathNick); #endif - ConvertCodedStringToUnicode(ShortHeader.Subject, &head->Subject, CP, MIME_PLAIN); + head->wszSubject = ConvertCodedStringToUnicode(ShortHeader.Subject, CP, MIME_PLAIN); #ifdef DEBUG_DECODE if (NULL != head->Subject) DebugLogW(DecodeFile, L"%s\n", head->Subject); #endif - ConvertCodedStringToUnicode(ShortHeader.Date, &head->Date, CP, MIME_PLAIN); + head->wszDate = ConvertCodedStringToUnicode(ShortHeader.Date, CP, MIME_PLAIN); #ifdef DEBUG_DECODE if (NULL != head->Date) DebugLogW(DecodeFile, L"%s\n", head->Date); #endif - ConvertCodedStringToUnicode(ShortHeader.Body, &head->Body, CP, MIME_PLAIN); + head->wszBody = ConvertCodedStringToUnicode(ShortHeader.Body, CP, MIME_PLAIN); #ifdef DEBUG_DECODE if (NULL != head->Body) DebugLogW(DecodeFile, L"%s\n", head->Body); @@ -395,75 +454,6 @@ void ExtractHeader(struct CMimeItem *items, int &CP, struct CHeader *head) #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 @@ -471,17 +461,16 @@ void inline ToLower(char *string) #define TE_BASE64 2 struct APartDataType { - char *Src;//Input + char *Src;// Input char *ContType; int CodePage; char *TransEnc; - uint8_t TransEncType; //TE_something + uint8_t TransEncType; // TE_something char *body; int bodyLen; wchar_t *wBody; }; - void ParseAPart(APartDataType *data) { size_t len = mir_strlen(data->Src); @@ -492,7 +481,7 @@ void ParseAPart(APartDataType *data) while (finder <= (data->Src + len)) { while (ENDLINEWS(finder)) finder++; - //at the start of line + // at the start of line if (finder > data->Src) { if (*(finder - 2) == '\r' || *(finder - 2) == '\n') *(finder - 2) = 0; @@ -516,7 +505,7 @@ void ParseAPart(APartDataType *data) break; do { - if (ENDLINEWS(finder)) finder += 2; //after endline information continues + if (ENDLINEWS(finder)) finder += 2; // after endline information continues while (!ENDLINE(finder) && !EOS(finder)) finder++; } while (ENDLINEWS(finder)); @@ -560,7 +549,7 @@ void ParseAPart(APartDataType *data) if (data->body) data->bodyLen = (int)mir_strlen(data->body); } -//from decode.cpp +// 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); @@ -617,13 +606,13 @@ wchar_t *ParseMultipartBody(char *src, char *bond) if (localBody) delete[] localBody; } else if (partData[i].ContType && !_strnicmp(partData[i].ContType, "multipart/", 10)) { - //Multipart in mulitipart recursive? should be SPAM. Ah well + // 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 goto FailBackRaw; // multipart with no boundary? badly formatted messages. } else { FailBackRaw: @@ -631,7 +620,7 @@ FailBackRaw: } resultSize += mir_wstrlen(partData[i].wBody); }// if (partData[i].body) - resultSize += 100 + 4 + 3; //cr+nl+100+ 3*bullet + resultSize += 100 + 4 + 3; // cr+nl+100+ 3*bullet } dest = new wchar_t[resultSize + 1]; size_t destpos = 0; @@ -690,6 +679,6 @@ FailBackRaw: free(srcback); delete[] partData; - dest[resultSize] = 0;//just in case + dest[resultSize] = 0;// just in case return dest; } diff --git a/protocols/YAMN/src/stdafx.h b/protocols/YAMN/src/stdafx.h index f26db794ec..92190d9f16 100644 --- a/protocols/YAMN/src/stdafx.h +++ b/protocols/YAMN/src/stdafx.h @@ -174,7 +174,6 @@ void TranslateHeaderFcn(char *stream, int len, struct CMimeItem **head); // From mime.cpp void ExtractHeader(struct CMimeItem *items, int &CP, struct CHeader *head); void ExtractShortHeader(struct CMimeItem *items, struct CShortHeader *head); -void DeleteHeaderContent(struct CHeader *head); void DeleteShortHeaderContent(struct CShortHeader *head); char *ExtractFromContentType(char *ContentType, char *value); wchar_t *ParseMultipartBody(char *src, char *bond); @@ -202,7 +201,7 @@ extern struct WndHandles *MessageWnd; YAMN_PROTOPLUGIN* RegisterProtocolPlugin(YAMN_PROTOREGISTRATION *Registration); int GetCharsetFromString(char *input, size_t size); -void ConvertCodedStringToUnicode(char *stream, wchar_t **storeto, uint32_t cp, int mode); +CMStringW ConvertCodedStringToUnicode(char *stream, uint32_t cp, int mode); extern PVOID TLSCtx; extern PVOID SSLCtx; -- cgit v1.2.3