From a70382b0e8bed265a1d314d9f6aae8f2dd48d20b Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 28 Nov 2012 18:45:54 +0000 Subject: ex-protos moved to the Plugins folder git-svn-id: http://svn.miranda-ng.org/main/trunk@2545 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/YAMN/src/mails/mime.cpp | 732 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 732 insertions(+) create mode 100644 plugins/YAMN/src/mails/mime.cpp (limited to 'plugins/YAMN/src/mails/mime.cpp') diff --git a/plugins/YAMN/src/mails/mime.cpp b/plugins/YAMN/src/mails/mime.cpp new file mode 100644 index 0000000000..2a66b80e2b --- /dev/null +++ b/plugins/YAMN/src/mails/mime.cpp @@ -0,0 +1,732 @@ +/* + * This code implements retrieving info from MIME header + * + * (c) majvan 2002-2004 + */ + +#pragma warning( disable : 4290 ) +#include "../yamn.h" + +//- imported --------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +extern SWMRG *AccountBrowserSO; +extern struct WndHandles *MessageWnd; + +extern int GetCharsetFromString(char *input,size_t size); +extern void SendMsgToRecepients(struct WndHandles *FirstWin,UINT msg,WPARAM wParam,LPARAM lParam); +extern void ConvertCodedStringToUnicode(char *stream,WCHAR **storeto,DWORD cp,int mode); +extern DWORD WINAPI MailBrowser(LPVOID Param); +extern DWORD WINAPI NoNewMailProc(LPVOID Param); +extern DWORD WINAPI BadConnection(LPVOID Param); + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +//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(PYAMN_MIMENAMES Names); + +//Deletes list of YAMN_MIMESHORTNAMES structures +// Names- pointer to first item of list +void DeleteShortNames(PYAMN_MIMESHORTNAMES 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==NULL) + return; + if (srcstart>=srcend) + return; + + if ((mode==MIME_MAIL) && (((*srcstart=='"') && (*(srcend-1)=='"')) || ((*srcstart=='<') && (*(srcend-1)=='>')))) + { + srcstart++; + srcend--; + } + + if (srcstart>=srcend) + return; + + if (NULL!=*dest) + delete[] *dest; + if (NULL==(*dest=new char[srcend-srcstart+1])) + return; + + dst=*dest; + + for (;srcstart' 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==NULL) + { + *storeto=NULL; + 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==NULL){ + free (lowered); + return NULL; + } + 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 NULL; + finder=finder+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 (NULL==(CopiedString=new char[++temp-finder+1])) + return NULL; + 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!=NULL;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==NULL) + continue; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,""); + #endif + ExtractAddressFromLine(items->value,&head->From,&head->FromNick); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + } + else if (0==_strnicmp(items->name,"Return-Path",11)) + { + if (items->value==NULL) + continue; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,""); + #endif + ExtractAddressFromLine(items->value,&head->ReturnPath,&head->ReturnPathNick); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + } + else if (0==_strnicmp(items->name,"Subject",7)) + { + if (items->value==NULL) + continue; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,""); + #endif + ExtractStringFromLine(items->value,&head->Subject); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + } + else if (0==_strnicmp(items->name,"Body",4)) + { + if (items->value==NULL) + continue; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,""); + #endif + ExtractStringFromLine(items->value,&head->Body); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + } + else if (0==_strnicmp(items->name,"Date",4)) + { + if (items->value==NULL) + continue; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,""); + #endif + ExtractStringFromLine(items->value,&head->Date); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + } + else if (0==_strnicmp(items->name,"Content-Type",12)) + { + if (items->value==NULL) + continue; + + char *ContentType=NULL,*CharSetStr; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,""); + #endif + ExtractStringFromLine(items->value,&ContentType); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + ToLower(ContentType); + if (NULL!=(CharSetStr=ExtractFromContentType(ContentType,"charset="))) + { + head->CP=GetCharsetFromString(CharSetStr,strlen(CharSetStr)); + delete[] CharSetStr; + } + delete[] ContentType; + } + else if (0==_strnicmp(items->name,"Importance",10)) + { + if (items->value==NULL) + continue; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,""); + #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,"\n"); + #endif + } + else if (0==_strnicmp(items->name,"X-Priority",10)) + { + if (items->value==NULL) + continue; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,""); + #endif + if ((*items->value>='1') && (*items->value<='5')) + head->Priority=*items->value-'0'; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + } + + } +} + +void ExtractHeader(struct CMimeItem *items,int &CP,struct CHeader *head) +{ + struct CShortHeader ShortHeader; + + ZeroMemory(&ShortHeader,sizeof(struct CShortHeader)); + ShortHeader.Priority=ShortHeader.CP=-1; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\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,"%s%s%s%s%s%s\n"); + DebugLog(DecodeFile,"\n"); + #endif + + ConvertCodedStringToUnicode(ShortHeader.From,&head->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); + #ifdef DEBUG_DECODE + if (NULL!=head->FromNick) + DebugLogW(DecodeFile,L"%s\n",head->FromNick); + #endif + ConvertCodedStringToUnicode(ShortHeader.ReturnPath,&head->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); + #ifdef DEBUG_DECODE + if (NULL!=head->ReturnPathNick) + DebugLogW(DecodeFile,L"%s\n",head->ReturnPathNick); + #endif + ConvertCodedStringToUnicode(ShortHeader.Subject,&head->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); + #ifdef DEBUG_DECODE + if (NULL!=head->Date) + DebugLogW(DecodeFile,L"%s\n",head->Date); + #endif + + ConvertCodedStringToUnicode(ShortHeader.Body,&head->Body,CP,MIME_PLAIN); + #ifdef DEBUG_DECODE + if (NULL!=head->Body) + DebugLogW(DecodeFile,L"%s\n",head->Body); + #endif + + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + + DeleteShortHeaderContent(&ShortHeader); + +// head->From=L"Frommmm"; +// head->Subject=L"Subject"; + return; +} + +void DeleteShortHeaderContent(struct CShortHeader *head) +{ + if (head->From!=NULL) delete[] head->From; + if (head->FromNick!=NULL) delete[] head->FromNick; + if (head->ReturnPath!=NULL) delete[] head->ReturnPath; + if (head->ReturnPathNick!=NULL) delete[] head->ReturnPathNick; + if (head->Subject!=NULL) delete[] head->Subject; + if (head->Date!=NULL) delete[] head->Date; + if (head->To!=NULL) DeleteShortNames(head->To); + if (head->Cc!=NULL) DeleteShortNames(head->Cc); + if (head->Bcc!=NULL) DeleteShortNames(head->Bcc); + if (head->Body!=NULL) delete[] head->Body; +} + +void DeleteHeaderContent(struct CHeader *head) +{ + if (head->From!=NULL) delete[] head->From; + if (head->FromNick!=NULL) delete[] head->FromNick; + if (head->ReturnPath!=NULL) delete[] head->ReturnPath; + if (head->ReturnPathNick!=NULL) delete[] head->ReturnPathNick; + if (head->Subject!=NULL) delete[] head->Subject; + if (head->Date!=NULL) delete[] head->Date; + if (head->Body!=NULL) delete[] head->Body; + if (head->To!=NULL) DeleteNames(head->To); + if (head->Cc!=NULL) DeleteNames(head->Cc); + if (head->Bcc!=NULL) DeleteNames(head->Bcc); +} + +void DeleteNames(PYAMN_MIMENAMES Names) +{ + PYAMN_MIMENAMES Parser=Names,Old; + for (;Parser!=NULL;Parser=Parser->Next) + { + if (Parser->Value!=NULL) + delete[] Parser->Value; + if (Parser->ValueNick!=NULL) + delete[] Parser->ValueNick; + Old=Parser; + Parser=Parser->Next; + delete Old; + } +} + +void DeleteShortNames(PYAMN_MIMESHORTNAMES Names) +{ + PYAMN_MIMESHORTNAMES Parser=Names,Old; + for (;Parser!=NULL;Parser=Parser->Next) + { + if (Parser->Value!=NULL) + delete[] Parser->Value; + if (Parser->ValueNick!=NULL) + delete[] Parser->ValueNick; + 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; + BYTE TransEncType; //TE_something + char *body; + int bodyLen; + WCHAR *wBody; +}; + + +void ParseAPart(APartDataType *data) +{ + size_t len = 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(NULL,_T("Translate header error"),_T(""),0); + } + if (data->body) data->bodyLen = (int)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 **out); + +WCHAR *ParseMultipartBody(char *src, char *bond) +{ + char *srcback = _strdup(src); + size_t sizebond = strlen(bond); + int numparts = 1; + int i; + char *courbond = srcback; + WCHAR *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