summaryrefslogtreecommitdiff
path: root/plugins/YAMN/mails
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
commit48540940b6c28bb4378abfeb500ec45a625b37b6 (patch)
tree2ef294c0763e802f91d868bdef4229b6868527de /plugins/YAMN/mails
parent5c350913f011e119127baeb32a6aedeb4f0d33bc (diff)
initial commit
git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/YAMN/mails')
-rw-r--r--plugins/YAMN/mails/decode.cpp558
-rw-r--r--plugins/YAMN/mails/m_decode.h25
-rw-r--r--plugins/YAMN/mails/m_mails.h285
-rw-r--r--plugins/YAMN/mails/mails.cpp499
-rw-r--r--plugins/YAMN/mails/mime.cpp732
-rw-r--r--plugins/YAMN/mails/test/header.txt28
-rw-r--r--plugins/YAMN/mails/test/header2.txt97
-rw-r--r--plugins/YAMN/mails/test/readme.txt4
-rw-r--r--plugins/YAMN/mails/test/test.cpp42
-rw-r--r--plugins/YAMN/mails/test/test.dsp112
-rw-r--r--plugins/YAMN/mails/test/test.dsw29
11 files changed, 2411 insertions, 0 deletions
diff --git a/plugins/YAMN/mails/decode.cpp b/plugins/YAMN/mails/decode.cpp
new file mode 100644
index 0000000000..15c23e9f34
--- /dev/null
+++ b/plugins/YAMN/mails/decode.cpp
@@ -0,0 +1,558 @@
+/*
+ * 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 "../yamn.h"
+//--------------------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------
+
+struct _tcptable CodePageNamesAll[]=
+{
+ {_T("ANSI"),_T(""),TRUE,CP_ACP},
+ {_T("WINDOWS-1"),_T("250"),0,1250},
+ {_T("WINDOWS-1"),_T("251"),0,1251},
+ {_T("WINDOWS-1"),_T("252"),0,1252},
+ {_T("WINDOWS-1"),_T("253"),0,1253},
+ {_T("WINDOWS-1"),_T("254"),0,1254},
+ {_T("WINDOWS-1"),_T("255"),0,1255},
+ {_T("WINDOWS-1"),_T("256"),0,1256},
+ {_T("WINDOWS-1"),_T("257"),0,1257},
+ {_T("WINDOWS-1"),_T("258"),0,1258},
+ {_T("CP1"),_T("250"),0,1250},
+ {_T("CP1"),_T("251"),0,1251},
+ {_T("CP1"),_T("252"),0,1252},
+ {_T("CP1"),_T("253"),0,1253},
+ {_T("CP1"),_T("254"),0,1254},
+ {_T("CP1"),_T("255"),0,1255},
+ {_T("CP1"),_T("256"),0,1256},
+ {_T("CP1"),_T("257"),0,1257},
+ {_T("CP1"),_T("258"),0,1258},
+ {_T("ANSI-1"),_T("250"),0,1250},
+ {_T("ANSI-1"),_T("251"),0,1251},
+ {_T("ANSI-1"),_T("252"),0,1252},
+ {_T("ANSI-1"),_T("253"),0,1253},
+ {_T("ANSI-1"),_T("254"),0,1254},
+ {_T("ANSI-1"),_T("255"),0,1255},
+ {_T("ANSI-1"),_T("256"),0,1256},
+ {_T("ANSI-1"),_T("257"),0,1257},
+ {_T("ANSI-1"),_T("258"),0,1258},
+ {_T("KOI8"),_T("-R"),0,20866},
+ {_T("KOI8"),_T(""),0,20866},
+ {_T("KOI8"),_T("-U"),0,21866},
+ {_T("KOI8"),_T("-RU"),0,21866},
+ {_T("US-"),_T("ASCII"),0,20127},
+ {_T("CP"),_T("367"),0,20127},
+ {_T("ASCII"),_T(""),0,20127},
+ {_T("ASCII"),_T("7"),0,20127},
+ {_T("ISO-8859"),_T("-1"),0,28591},
+ {_T("ISO-8859"),_T("-2"),0,28592},
+ {_T("ISO-8859"),_T("-3"),0,28593},
+ {_T("ISO-8859"),_T("-4"),0,28594},
+ {_T("ISO-8859"),_T("-5"),0,28595},
+ {_T("ISO-8859"),_T("-6"),0,28596},
+ {_T("ISO-8859"),_T("-7"),0,28597},
+ {_T("ISO-8859"),_T("-8"),0,28598},
+ {_T("ISO-8859"),_T("-9"),0,28599},
+ {_T("ISO-8859"),_T("-15"),0,28605},
+ {_T("ISO_8859"),_T("-1"),0,28591},
+ {_T("ISO_8859"),_T("-2"),0,28592},
+ {_T("ISO_8859"),_T("-3"),0,28593},
+ {_T("ISO_8859"),_T("-4"),0,28594},
+ {_T("ISO_8859"),_T("-5"),0,28595},
+ {_T("ISO_8859"),_T("-6"),0,28596},
+ {_T("ISO_8859"),_T("-7"),0,28597},
+ {_T("ISO_8859"),_T("-8"),0,28598},
+ {_T("ISO_8859"),_T("-9"),0,28599},
+ {_T("ISO_8859"),_T("-15"),0,28605},
+ {_T("ISO-"),_T("10646-USC2"),0,1200},
+ {_T("ISO-2022"),_T("/2-JP"),0,50220},
+ {_T("ISO-2022"),_T("-JP"),0,50221},
+ {_T("ISO-2022"),_T("/JIS-JP"),0,50222},
+ {_T("ISO-2022"),_T("-KR"),0,50225},
+ {_T("ISO-2022"),_T("-CH(SP)"),0,50227},
+ {_T("ISO-2022"),_T("-CH(TR)"),0,50229},
+ {_T("UTF-"),_T("7"),0,65000},
+ {_T("UTF-"),_T("8"),0,65001},
+ {_T("ARAB-"),_T("TRANSPARENT"),0,710},
+ {_T("ASMO-"),_T("TRANSPARENT"),0,720},
+ {_T("ASMO-"),_T("449"),0,709},
+ {_T("ASMO-"),_T("708"),0,708},
+ {_T("BIG5"),_T(""),0,950},
+ {_T("EUC-"),_T("CH(SP)"),0,51936},
+ {_T("EUC-"),_T("CH(TR)"),0,51950},
+ {_T("EUC-"),_T("JP"),0,51932},
+ {_T("EUC-"),_T("KR"),0,51949},
+ {_T("GB-"),_T("2312"),0,20936},
+ {_T("GB"),_T("2312"),0,20936},
+ {_T("HZGB-"),_T("2312"),0,52936},
+ {_T("IBM-"),_T("037"),0,37},
+ {_T("IBM-"),_T("290"),0,290},
+ {_T("IBM-"),_T("437"),0,437},
+ {_T("IBM-"),_T("500"),0,500},
+ {_T("IBM-"),_T("775"),0,775},
+ {_T("IBM-"),_T("850"),0,850},
+ {_T("IBM-"),_T("852"),0,852},
+ {_T("IBM-"),_T("855"),0,855},
+ {_T("IBM-"),_T("857"),0,857},
+ {_T("IBM-"),_T("860"),0,860},
+ {_T("IBM-"),_T("861"),0,861},
+ {_T("IBM-"),_T("862"),0,862},
+ {_T("IBM-"),_T("863"),0,863},
+ {_T("IBM-"),_T("864"),0,864},
+ {_T("IBM-"),_T("865"),0,865},
+ {_T("IBM-"),_T("866"),0,866},
+ {_T("IBM-"),_T("869"),0,869},
+ {_T("IBM-"),_T("870"),0,870},
+ {_T("IBM-"),_T("875"),0,875},
+ {_T("IBM-"),_T("1026"),0,1026},
+ {_T("IBM-"),_T("273"),0,20273},
+ {_T("IBM-"),_T("277"),0,20277},
+ {_T("IBM-"),_T("278"),0,20278},
+ {_T("IBM-"),_T("280"),0,20280},
+ {_T("IBM-"),_T("284"),0,20284},
+ {_T("IBM-"),_T("285"),0,20285},
+ {_T("IBM-"),_T("290"),0,20290},
+ {_T("IBM-"),_T("297"),0,20297},
+ {_T("IBM-"),_T("420"),0,20420},
+ {_T("IBM-"),_T("423"),0,20423},
+ {_T("IBM-"),_T("871"),0,20871},
+ {_T("IBM-"),_T("880"),0,20880},
+ {_T("IBM-"),_T("905"),0,20905},
+ {_T("IBM-"),_T("THAI"),0,20838},
+ {_T("ISCII-"),_T("DEVANAGARI"),0,57002},
+ {_T("ISCII-"),_T("BENGALI"),0,57003},
+ {_T("ISCII-"),_T("TAMIL"),0,57004},
+ {_T("ISCII-"),_T("TELUGU"),0,57005},
+ {_T("ISCII-"),_T("ASSAMESE"),0,57006},
+ {_T("ISCII-"),_T("ORIYA"),0,57007},
+ {_T("ISCII-"),_T("KANNADA"),0,57008},
+ {_T("ISCII-"),_T("MALAYALAM"),0,57009},
+ {_T("ISCII-"),_T("GUJARATI"),0,57010},
+ {_T("ISCII-"),_T("PUNJABI"),0,57011},
+ {_T("KOR-"),_T("JOHAB"),0,1361},
+ {_T("KSC-"),_T("5601"),0,1361},
+ {_T("MAC-"),_T("ROMAN"),0,10000},
+ {_T("MAC-"),_T("JP"),0,10001},
+ {_T("MAC-"),_T("CH(SP)(BIG5)"),0,10002},
+ {_T("MAC-"),_T("KR"),0,10003},
+ {_T("MAC-"),_T("AR"),0,10004},
+ {_T("MAC-"),_T("HW"),0,10005},
+ {_T("MAC-"),_T("GR"),0,10006},
+ {_T("MAC-"),_T("CY"),0,10007},
+ {_T("MAC-"),_T("CH(SP)(GB2312)"),0,10008},
+ {_T("MAC-"),_T("ROMANIA"),0,10010},
+ {_T("MAC-"),_T("UA"),0,10017},
+ {_T("MAC-"),_T("TH"),0,10021},
+ {_T("MAC-"),_T("LAT2"),0,10029},
+ {_T("MAC-"),_T("ICE"),0,10079},
+ {_T("MAC-"),_T("TR"),0,10081},
+ {_T("MAC-"),_T("CR"),0,10082},
+};
+
+int CPLENALL = (sizeof(CodePageNamesAll)/sizeof(CodePageNamesAll[0]));
+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 **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 **storeto,DWORD 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])==NULL)
+ 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=(char)0;
+
+#ifdef DEBUG_DECODECODEPAGE
+ DebugLog(DecodeFile,"<CodePage>%s</CodePage>",pout);
+#endif
+ for(int i=0;i<CPLENALL;i++){
+ size_t len = strlen(CodePageNamesAll[i].NameBase);
+ if(0==strncmp(pout,CodePageNamesAll[i].NameBase,len)){
+ if (0==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;((char)*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=(char)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 **out)
+{
+ CPINFO CPInfo;
+ WCHAR *temp,*src=*out,*dest;
+ size_t outlen;
+ int streamlen,Index;
+
+ //codepages, which require to have set 0 in dwFlags parameter when calling MultiByteToWideChar
+ DWORD 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,NULL,0);
+ else
+ streamlen=MultiByteToWideChar(cp,MB_USEGLYPHCHARS,stream,-1,NULL,0);
+
+ if(*out!=NULL)
+ outlen=wcslen(*out);
+ else
+ outlen=0;
+ temp=new WCHAR[streamlen+outlen+1];
+
+ if(*out!=NULL)
+ {
+ for(dest=temp;*src!=(WCHAR)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 **storeto,DWORD cp,int mode)
+{
+ char *start=stream,*finder,*finderend;
+ char Encoding=0;
+ char *DecodedResult=NULL;
+
+ if(stream==NULL)
+ return;
+
+ while(WS(start)) start++;
+ WCHAR *tempstore=0;
+ if(!ConvertStringToUnicode(stream,cp,&tempstore))return;
+
+ size_t tempstoreLength = wcslen(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=(DWORD)GetCharsetFromString(finder,finderend-finder)))
+ cp=CP_ACP;
+ if(Encoding!=0)
+ {
+ int size,codeend;
+ char *pcodeend;
+
+ 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--;
+ }
+ //*finderend=(char)0;
+ 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;
+ }
+ if(DecodedResult!=NULL)
+ delete[] DecodedResult;
+ 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=strlen(DecodedResult);
+ DecodedResult[len]=' ';
+ DecodedResult[len+1]=0;
+ finderend++;
+ }
+ WCHAR *oneWord=0;
+ if(ConvertStringToUnicode(DecodedResult,cp,&oneWord)){
+ size_t len = wcslen(oneWord);
+ memcpy(&tempstore[outind],oneWord,len*sizeof(WCHAR));
+ outind += len;
+ }
+ delete oneWord;
+ oneWord = 0;
+ delete[] DecodedResult; DecodedResult = 0;
+ 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/plugins/YAMN/mails/m_decode.h b/plugins/YAMN/mails/m_decode.h
new file mode 100644
index 0000000000..e6d2b52fae
--- /dev/null
+++ b/plugins/YAMN/mails/m_decode.h
@@ -0,0 +1,25 @@
+#ifndef __DECODE_H
+#define __DECODE_H
+
+#include "../debug.h"
+
+#define DOTLINE(s) ((((s)[-2]=='\r') || ((s)[-2]=='\n')) && ((s)[-1]=='.') && (((s)[0]=='\r') || ((s)[0]=='\n') || ((s)[0]=='\0'))) // be careful, it's different to ESR's pop3.c ;-)
+#define ENDLINE(s) (((s)[0]=='\r') || ((s)[0]=='\n')) //endline
+#define WS(s) (((s)[0]==' ') || ((s)[0]=='\t')) //whitespace
+#define ENDLINEWS(s) ((((s)[0]=='\r') || ((s)[0]=='\n')) && (((((s)[1]=='\r') || ((s)[1]=='\n')) && (((s)[2]==' ') || ((s)[2]=='\t'))) || (((s)[1]==' ') || ((s)[1]=='\t')))) //endline+whitespace: enters(CR or LF and their combinations) followed by space or tab
+#define EOS(s) ((s)[0]==0) //end of string (stream)
+
+#define CODES(s) ((s[0]=='=') && (s[1]=='?')) //start of coded string
+#define CODEE(s) ((s[0]=='?') && (s[1]=='=')) //end of coded string
+#define CODED(s) (s[0]=='?') //code delimiter
+
+#define MIME_PLAIN 1
+#define MIME_MAIL 2
+
+struct cptable
+{
+ char *name;
+ unsigned int ID;
+};
+
+#endif
diff --git a/plugins/YAMN/mails/m_mails.h b/plugins/YAMN/mails/m_mails.h
new file mode 100644
index 0000000000..adcaa56a88
--- /dev/null
+++ b/plugins/YAMN/mails/m_mails.h
@@ -0,0 +1,285 @@
+#ifndef __MAILS_H
+#define __MAILS_H
+
+#include <windows.h>
+#include <tchar.h>
+#include "m_account.h"
+
+//
+//================================== OTHER DEFINITIONS ========================================
+//
+
+typedef struct CShortNames
+{
+ char *Value;
+ char *ValueNick;
+ struct CShortNames *Next;
+} YAMN_MIMESHORTNAMES,*PYAMN_MIMESHORTNAMES;
+
+typedef struct CNames
+{
+ WCHAR *Value;
+ WCHAR *ValueNick;
+ struct CNames *Next;
+} YAMN_MIMENAMES,*PYAMN_MIMENAMES;
+
+struct CShortHeader
+//this header is used in to get non-unicode data from mime header
+{
+ char *From;
+ char *FromNick;
+ char *ReturnPath;
+ char *ReturnPathNick;
+ char *Subject;
+ PYAMN_MIMESHORTNAMES To;
+ PYAMN_MIMESHORTNAMES Cc;
+ PYAMN_MIMESHORTNAMES Bcc;
+ char *Date;
+ char Priority;
+ char *Body;
+
+ int CP;
+
+ CShortHeader() {}
+ ~CShortHeader() {}
+};
+
+struct CHeader
+//this header is used in miranda to store final results of mime reading in Unicode
+{
+ WCHAR *From;
+ WCHAR *FromNick;
+ WCHAR *ReturnPath;
+ WCHAR *ReturnPathNick;
+ WCHAR *Subject;
+ PYAMN_MIMENAMES To;
+ PYAMN_MIMENAMES Cc;
+ PYAMN_MIMENAMES Bcc;
+ WCHAR *Date;
+ TCHAR Priority;
+ WCHAR *Body;
+
+ CHeader() {}
+ ~CHeader() {}
+};
+
+struct CMimeItem
+{
+ char *name;
+ char *value;
+ struct CMimeItem *Next;
+ CMimeItem(): name(NULL), value(NULL), Next(NULL){}
+};
+
+typedef struct CMailData //this is plugin-independent
+{
+#define YAMN_MAILDATAVERSION 3
+
+ DWORD Size;
+ int CP;
+
+ struct CMimeItem *TranslatedHeader; //MIME items
+ struct CMimeItem *Additional; //MIME items not read from server (custom, for filter plugins etc.)
+ char *Body; //Message body
+
+ CMailData(): CP(-1), Size(0), TranslatedHeader(NULL), Body(NULL){}
+} MAILDATA,*PMAILDATA;
+
+typedef struct CMimeMsgQueue
+{
+#define YAMN_MAILVERSION 3
+ char *ID; //The ID of mail. This ID identifies every mail in the account, so plugin should set it
+
+ DWORD Number;
+
+#define YAMN_MSG_ANY 0xffffffff //any mail
+
+//The difference between new and unseen: when new mail is found in account, it becomes unseen and new. But in the next check, if the same mail is found, it is not new.
+//However, when user was not near computer, he does not know about this mail- it is unseen. After user accepts, that he saw new mails, it becomes seen.
+#define YAMN_MSG_NEW 0x80000000 //this mail is new
+#define YAMN_MSG_UNSEEN 0x40000000 //this mail is mailbrowser unseen
+#define YAMN_MSG_DISPLAY 0x20000000 //this mail can be displayed in mailbrowser
+#define YAMN_MSG_POPUP 0x10000000 //this mail can be displayed in popup and can invoke a popup
+#define YAMN_MSG_SYSTRAY 0x08000000 //this mail can invoke systray icon
+#define YAMN_MSG_BROWSER 0x04000000 //this mail can run mailbrowser
+#define YAMN_MSG_DISPLAYC 0x02000000 //this mail is inserted to browser mail counter system (the "Account - xx new mails, yy total" phrase)
+#define YAMN_MSG_POPUPC 0x01000000 //this mail is inserted to popup counter system (the "Account - xx new mails, yy total" phrase)
+
+#define YAMN_MSG_SOUND 0x00800000 //this mail can "play sound"
+#define YAMN_MSG_APP 0x00400000 //this mail can "launch application"
+#define YAMN_MSG_NEVENT 0x00100000 //this mail can launch Miranda "new mail" event
+
+#define YAMN_MSG_VIRTUAL 0x00080000 //this mail is not real- does not exists
+
+#define YAMN_MSG_FILTERED 0x00040000 //this mail has been filtered
+
+#define YAMN_MSG_DELETETRASH 0x00020000 //this mail should be moved to the trash bin rather than really deleting from mailbox (this is only switch doing nothing, perhaps usefull for filter plugins)
+#define YAMN_MSG_DELETED 0x00010000 //this mail is already deleted from server (also must be set virtual flag) (when doing synchronizations between 2 queues, YAMN then does not touch this mail)
+#define YAMN_MSG_MEMDELETE 0x00008000 //this mail will be deleted immidiatelly from memory (and disk) when deleted from server (some opposite of YAMN_MSG_DELETED)
+#define YAMN_MSG_USERDELETE 0x00004000 //this mail is about to delete from server (user deletes manually)
+#define YAMN_MSG_AUTODELETE 0x00002000 //this mail is about to delete from server (plugin marks it for deleting)
+#define YAMN_MSG_DELETEOK 0x00001000 //this mail is confirmed to delete (this flag must be set to delete this mail)
+
+#define YAMN_MSG_BODYREQUESTED 0x00000800 //user requested (part of) the body. In POP3 it should be (TOP <nr> <lines>)
+#define YAMN_MSG_BODYRECEIVED 0x00000200 //(part of) the body.received;
+#define YAMN_MSG_STAYUNSEEN 0x00000400 //this mail stays unseen while user does not really see it
+
+#define YAMN_MSG_DELETE (YAMN_MSG_USERDELETE | YAMN_MSG_AUTODELETE)
+
+#define YAMN_MSG_NORMALNEW (YAMN_MSG_NEW | YAMN_MSG_UNSEEN | YAMN_MSG_BROWSER | YAMN_MSG_DISPLAY | YAMN_MSG_DISPLAYC | YAMN_MSG_POPUP | YAMN_MSG_POPUPC | YAMN_MSG_SYSTRAY | YAMN_MSG_SOUND | YAMN_MSG_APP | YAMN_MSG_NEVENT | YAMN_MSG_MEMDELETE | YAMN_MSG_STAYUNSEEN)
+
+#define YAMN_MSG_FLAGSSET(maildata,flag) ((maildata & flag)==flag)
+
+#define YAMN_MSG_SPAML1 1 //spam level 1: notify, show in another color in mail browser
+#define YAMN_MSG_SPAML2 2 //spam level 2: do not notify, show in another color in mail browser
+#define YAMN_MSG_SPAML3 3 //spam level 3: delete, show in another color in mail browser that it was deleted, you do not need to set YAMN_MSG_AUTODELETE
+#define YAMN_MSG_SPAML4 4 //spam level 4: delete, do not show, you do not need to set YAMN_MSG_AUTODELETE
+#define YAMN_MSG_SPAMMASK 0x0000000F
+
+#define YAMN_MSG_SPAML(maildata,level) ((maildata & YAMN_MSG_SPAMMASK)==level)
+ DWORD Flags;
+//Plugins can read mail data, but it can be NULL!!! So plugin should use Load and Save services to load or save data and Unload to release data from memory
+ PMAILDATA MailData;
+//Here YAMN stores its own informations about this mail. Not usefull for plugins...
+// void *YAMNData;
+ HWND MsgWindow;
+//plugins can store here its own data
+ void *PluginData;
+
+ CMimeMsgQueue(): ID(NULL), Number(0), Flags(0), MailData(NULL), MsgWindow(NULL), PluginData(NULL), Next(NULL){}
+ ~CMimeMsgQueue(){}
+
+ struct CMimeMsgQueue *Next;
+} YAMNMAIL,*HYAMNMAIL;
+
+#define LoadedMailData(x) (x->MailData!=NULL)
+
+//
+//================================== YAMN MAIL SERVICES ==================================
+//
+
+//CreateAccountMail Service
+//Your plugin should call this to create new mail for your plugin.
+//WPARAM- (HACCOUNT) Account handle
+//LPARAM- CMailData version (use YAMN_MAILVERSION definition)
+//returns pointer to (HYAMNMAIL) or pointer to your structure returned from imported NewMailFcnPtr, if implemented
+#define MS_YAMN_CREATEACCOUNTMAIL "YAMN/Service/CreateMail"
+#define CreateAccountMail(x) (HYAMNMAIL)CallService(MS_YAMN_CREATEACCOUNTMAIL,(WPARAM)x,(LPARAM)YAMN_MAILVERSION)
+
+//DeleteAccountMail Service
+//Deletes plugin's mail from memory. You probably won't use this service, because it deletes only account
+//without any synchronization. Use MS_YAMN_DELETEACCOUNT instead. Note that deleting mail is something like "this mail is
+//not more in the account".
+//WPARAM- (HYAMNPROTOPLUGIN) handle of plugin, which is going to delete mail
+//LPARAM- (HYAMNMAIL) mail going to delete
+//returns zero if failed, otherwise returns nonzero
+#define MS_YAMN_DELETEACCOUNTMAIL "YAMN/Service/DeletePluginMail"
+#define DeleteAccountMail(x,y) CallService(MS_YAMN_DELETEACCOUNTMAIL,(WPARAM)x,(LPARAM)y)
+
+//LoadMailData Service
+//This service loads mail from standard YAMN storage (now it is 1 file, from which mails are loaded once at startup, but
+//in the future it can be Miranda profile file or separate file (1 file per 1 mail). It depends on YAMN implementation...
+//Use this function if you want to read or write to MailData member of mail structure. Please use synchronization obejcts
+//before calling this service (so you must have read or write access to mails)
+//WPARAM- (HYAMNMAIL) mail where to load data
+//LPARAM- (DWORD) version of MAILDATA structure (use YAMN_MAILDATAVERSION definition)
+//returns pointer to new allocated MailData structure (the same value as MailData member)
+#define MS_YAMN_LOADMAILDATA "YAMN/Service/LoadMailData"
+#define LoadMailData(x) (PMAILDATA)CallService(MS_YAMN_LOADMAILDATA,(WPARAM)x,(LPARAM)YAMN_MAILDATAVERSION)
+
+//UnloadMailData Service
+//This service frees mail data from memory. It does not care if data were saved or not. So you should save mail before you
+//release data from memory.
+//WPARAM- (HYAMNMAIL) mail whose data are about to free
+//LPARAM- nothing yet
+//returns nonzero if success
+#define MS_YAMN_UNLOADMAILDATA "YAMN/Service/UnloadMailData"
+#define UnloadMailData(x) CallService(MS_YAMN_UNLOADMAILDATA,(WPARAM)x,(LPARAM)0)
+
+//SaveMailData Service
+//This service saves mail to standard YAMN storage (when using now 1 book file, it does nothing, because save is done when
+//using MS_YAMN_WRITEACCOUNT service. In the future, mail can be saved to Miranda profile or to separate file...)
+//WPARAM- (HYAMNMAIL) mail to save
+//LPARAM- (DWORD) version of MAILDATA structure (use YAMN_MAILDATAVERSION definition)
+//returns ZERO! if succes
+#define MS_YAMN_SAVEMAILDATA "YAMN/Service/SaveMailData"
+#define SaveMailData(x) CallService(MS_YAMN_SAVEMAILDATA,(WPARAM)x,(LPARAM)YAMN_MAILDATAVERSION)
+
+//
+//================================== FUNCTIONS DEFINITIONS ========================================
+//
+
+//typedef void (WINAPI *YAMN_SENDMESSAGEFCN)(UINT,WPARAM,LPARAM);
+typedef void (WINAPI *YAMN_SYNCHROMIMEMSGSFCN)(HACCOUNT,HYAMNMAIL *,HYAMNMAIL *,HYAMNMAIL *,HYAMNMAIL *);
+typedef void (WINAPI *YAMN_TRANSLATEHEADERFCN)(char *,int,struct CMimeItem **);
+typedef void (WINAPI *YAMN_APPENDQUEUEFCN)(HYAMNMAIL,HYAMNMAIL);
+typedef void (WINAPI *YAMN_DELETEMIMEQUEUEFCN)(HACCOUNT,HYAMNMAIL);
+typedef void (WINAPI *YAMN_DELETEMIMEMESSAGEFCN)(HYAMNMAIL *,HYAMNMAIL,int);
+typedef HYAMNMAIL (WINAPI *YAMN_FINDMIMEMESSAGEFCN)(HYAMNMAIL,char *);
+typedef HYAMNMAIL (WINAPI *YAMN_CREATENEWDELETEQUEUEFCN)(HYAMNMAIL);
+typedef void (WINAPI *YAMN_SETREMOVEQUEUEFLAGSFCN)(HYAMNMAIL,DWORD,DWORD,DWORD,int);
+
+//
+//================================== QUICK FUNCTION CALL DEFINITIONS ========================================
+//
+
+//These are defininitions for YAMN exported functions. Your plugin can use them.
+//pYAMNFcn is global variable, it is pointer to your structure containing YAMN functions.
+//It is something similar like pluginLink variable in Miranda plugin. If you use
+//this name of variable, you have already defined these functions and you can use them.
+//It's similar to Miranda's CreateService function.
+
+//How to use YAMN functions:
+//Create a structure containing pointer to functions you want to use in your plugin
+//This structure can look something like this:
+//
+// struct
+// {
+// YAMN_SYNCHROMIMEMSGSFCN SynchroMessagesFcn;
+// YAMN_APPENDQUEUEFCN AppendQueueFcn;
+// } *pYAMNMailFcn;
+//
+//then you have to fill this structure with pointers...
+//you have to use YAMN service to get pointer, like this (I wrote here all functions you may need,
+//you can copy to your sources only those you need):
+//
+// pYAMNMailFcn->SynchroMessagesFcn=(YAMN_SYNCHROMIMEMSGSFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SYNCHROMIMEMSGSID,(LPARAM)0);
+// pYAMNMailFcn->TranslateHeaderFcn=(YAMN_TRANSLATEHEADERFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_TRANSLATEHEADERID,(LPARAM)0);
+// pYAMNMailFcn->AppendQueueFcn=(YAMN_APPENDQUEUEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_APPENDQUEUEID,(LPARAM)0);
+// pYAMNMailFcn->DeleteMessagesToEndFcn=(YAMN_DELETEMIMEQUEUEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_DELETEMIMEQUEUEID,(LPARAM)0);
+// pYAMNMailFcn->DeleteMessageFromQueueFcn=(YAMN_DELETEMIMEMESSAGEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_DELETEMIMEMESSAGEID,(LPARAM)0);
+// pYAMNMailFcn->FindMessageByIDFcn=(YAMN_FINDMIMEMESSAGEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_FINDMIMEMESSAGEID,(LPARAM)0);
+// pYAMNMailFcn->CreateNewDeleteQueueFcn=(YAMN_CREATENEWDELETEQUEUEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_CREATENEWDELETEQUEUEID,(LPARAM)0);
+// pYAMNMailFcn->SetRemoveQueueFlagsFcn=(YAMN_SETREMOVEQUEUEFLAGSFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SETREMOVEQUEUEFLAGSID,(LPARAM)0);
+//
+//
+//and in your plugin just simply use e.g.:
+//
+// DeleteMIMEQueue(MyAccount,OldMessages); //this command deletes all messages in the mail queue OldMessages
+//
+
+#define YAMN_SYNCHROMIMEMSGSID "YAMN/SynchroMessages"
+#define YAMN_TRANSLATEHEADERID "YAMN/TranslateHeader"
+#define YAMN_APPENDQUEUEID "YAMN/AppendQueue"
+#define YAMN_DELETEMIMEQUEUEID "YAMN/DeleteMIMEQueue"
+#define YAMN_DELETEMIMEMESSAGEID "YAMN/DeleteMIMEMessage"
+#define YAMN_FINDMIMEMESSAGEID "YAMN/FindMIMEMessageByID"
+#define YAMN_CREATENEWDELETEQUEUEID "YAMN/CreateNewDeleteQueue"
+#define YAMN_SETREMOVEQUEUEFLAGSID "YAMN/SetRemoveQueueFlags"
+
+#define YAMN_FLAG_REMOVE 0
+#define YAMN_FLAG_SET 1
+
+
+#define SynchroMessages(a,b,c,d,e) pYAMNMailFcn->SynchroMessagesFcn(a,b,c,d,e)
+#define TranslateHeader(a,b,c) pYAMNMailFcn->TranslateHeaderFcn(a,b,c)
+#define AppendQueue(x,y) pYAMNMailFcn->AppendQueueFcn(x,y)
+#define DeleteMIMEQueue(x,y) pYAMNMailFcn->DeleteMessagesToEndFcn(x,y)
+#define DeleteMIMEMessage(x,y) pYAMNMailFcn->DeleteMessageFromQueueFcn(x,y,0)
+#define DeleteMIMEMessageEx(x,y,z) pYAMNMailFcn->DeleteMessageFromQueueFcn(x,y,z)
+#define FindMIMEMessageByID(x,y) pYAMNMailFcn->FindMessageByIDFcn(x,y)
+#define CreateNewDeleteQueue(x) pYAMNMailFcn->CreateNewDeleteQueueFcn(x)
+#define SetQueueFlags(a,b,c,d) pYAMNMailFcn->SetRemoveQueueFlagsFcn(a,b,c,d,1)
+#define RemoveQueueFlags(a,b,c,d) pYAMNMailFcn->SetRemoveQueueFlagsFcn(a,b,c,d,0)
+
+#endif
diff --git a/plugins/YAMN/mails/mails.cpp b/plugins/YAMN/mails/mails.cpp
new file mode 100644
index 0000000000..b99a9fd560
--- /dev/null
+++ b/plugins/YAMN/mails/mails.cpp
@@ -0,0 +1,499 @@
+/*
+ * This code implements retrieving info from MIME header
+ *
+ * (c) majvan 2002-2004
+ */
+
+#pragma warning( disable : 4290 )
+#include "../yamn.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(HACCOUNT 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(HACCOUNT 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,DWORD FlagsSet,DWORD FlagsNotSet,DWORD 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)
+{
+ HACCOUNT Account=(HACCOUNT)wParam;
+ DWORD MailVersion=(DWORD)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!=NULL)
+ {
+ if(Account->Plugin->MailFcn->NewMailFcnPtr!=NULL)
+ {
+//Let plugin create its own structure, which can be derived from CAccount structure
+ if(NULL==(NewMail=Account->Plugin->MailFcn->NewMailFcnPtr(Account,YAMN_MAILVERSION)))
+ return NULL;
+ }
+ else
+ {
+//We suggest plugin uses standard CAccount structure, so we create it
+ if(NULL==(NewMail=new YAMNMAIL))
+//If not created successfully
+ return NULL;
+ NewMail->MailData=NULL;
+ }
+//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!=NULL){
+ if(Plugin->MailFcn->DeleteMailFcnPtr!=NULL) {
+ //Let plugin delete its own CMimeMsgQueue derived structure
+ Plugin->MailFcn->DeleteMailFcnPtr(OldMail);
+ return 1;
+ }
+ }
+ if(OldMail->MailData!=NULL) {
+ if(OldMail->MailData->Body!=NULL)
+ delete[] OldMail->MailData->Body;
+ if((TH=OldMail->MailData->TranslatedHeader)!=NULL)
+ for(;OldMail->MailData->TranslatedHeader!=NULL;) {
+ TH=TH->Next;
+ if(OldMail->MailData->TranslatedHeader->name!=NULL)
+ delete[] OldMail->MailData->TranslatedHeader->name;
+ if(OldMail->MailData->TranslatedHeader->value!=NULL)
+ delete[] OldMail->MailData->TranslatedHeader->value;
+ delete OldMail->MailData->TranslatedHeader;
+ OldMail->MailData->TranslatedHeader=TH;
+ }
+ delete OldMail->MailData;
+ }
+ if(OldMail->ID!=NULL)
+ 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!=NULL) Finder=Finder->Next;
+ Finder->Next=second;
+}
+
+INT_PTR LoadMailDataSvc(WPARAM wParam,LPARAM lParam)
+{
+ HYAMNMAIL Mail=(HYAMNMAIL)wParam;
+ DWORD MailVersion=(DWORD)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 wParam,LPARAM)
+{
+ HYAMNMAIL Mail=(HYAMNMAIL)wParam;
+
+//now we should delete structure from memory, but it will be made in future YAMN version
+ return 1;
+}
+
+INT_PTR SaveMailDataSvc(WPARAM wParam,LPARAM lParam)
+{
+ HYAMNMAIL Mail=(HYAMNMAIL)wParam;
+ DWORD MailVersion=(DWORD)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(HACCOUNT 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 =NULL;
+ HYAMNMAIL RemovedNewParser =NULL;
+ if(RemovedOld!=NULL) *RemovedOld=NULL;
+ if(RemovedNew!=NULL) *RemovedNew=NULL;
+
+ for(FinderPrev=NULL,Finder=*OldQueue;Finder!=NULL;)
+ {
+ 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=NULL,Parser=*NewQueue;Parser!=NULL;ParserPrev=Parser,Parser=Parser->Next)
+ {
+ if(Parser->Flags & YAMN_MSG_DELETED)
+ continue;
+
+ if(Parser->ID==NULL) //simply ignore the message, that has not filled its ID
+ continue;
+
+ if(0==strcmp(Parser->ID,Finder->ID)) //search for equal message in new queue
+ break;
+ }
+ if(Parser!=NULL) //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==NULL) //delete from new queue
+ DeleteAccountMailSvc((WPARAM)Account->Plugin,(LPARAM)Parser);
+ else //or move to RemovedNew
+ {
+ if(RemovedNewParser==NULL) //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=NULL;
+ }
+ 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==NULL) //delete from old queue
+ DeleteAccountMailSvc((WPARAM)Account->Plugin,(LPARAM)Finder);
+ else //or move to RemovedOld
+ {
+ if(RemovedOldParser==NULL) //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=NULL;
+ }
+ Finder=*OldQueue;
+ }
+ else
+ {
+ FinderPrev->Next=Finder->Next;
+ if(RemovedOld==NULL) //delete from old queue
+ DeleteAccountMailSvc((WPARAM)Account->Plugin,(LPARAM)Finder);
+ else //or move to RemovedOld
+ {
+ if(RemovedOldParser==NULL) //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=NULL;
+ }
+ Finder=FinderPrev->Next;
+ }
+ }
+ }
+}
+
+void WINAPI DeleteMessagesToEndFcn(HACCOUNT Account,HYAMNMAIL From)
+{
+ HYAMNMAIL Temp;
+ while(From!=NULL)
+ {
+ Temp=From;
+ From=From->Next;
+ DeleteAccountMailSvc((WPARAM)Account->Plugin,(LPARAM)Temp);
+ }
+}
+
+void WINAPI DeleteMessageFromQueueFcn(HYAMNMAIL *From,HYAMNMAIL Which,int mode=0)
+{
+ DWORD 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!=NULL;Parser=Parser->Next)
+ if(Parser->Number>Number) Parser->Number--;
+}
+
+void DeleteMessagesFromQueue(HYAMNMAIL *From,HYAMNMAIL Which,int mode=0)
+{
+ HYAMNMAIL Parser;
+
+ for(Parser=Which;Parser!=NULL;Parser=Parser->Next)
+ DeleteMessageFromQueueFcn(From,Parser,mode);
+}
+
+HYAMNMAIL WINAPI FindMessageByIDFcn(HYAMNMAIL From,char *ID)
+{
+ HYAMNMAIL Browser;
+
+ for(Browser=From;Browser!=NULL;Browser=Browser->Next)
+ if(0==lstrcmp(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=NULL;
+
+ 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!=NULL)
+ {
+ if(NULL==(Item->Next=new struct CMimeItem))
+ break;
+ Item=Item->Next;
+ }
+ else
+ {
+ Item = new CMimeItem;
+ *head = Item;
+ }
+
+ Item->Next=NULL;
+ Item->name=new char [prev2-prev1+1];
+ lstrcpyn(Item->name,prev1,prev2-prev1+1);
+ Item->value=new char [finder-prev3+1];
+ lstrcpyn(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(NULL==(Item->Next=new struct CMimeItem)) break; // Cant create new item?!
+ Item=Item->Next;
+ Item->Next=NULL;//just in case;
+ Item->name=new char[5]; strncpy(Item->name,"Body",5);
+ Item->value=new char [prev2-prev1];
+ lstrcpyn(Item->value,prev1,prev2-prev1-1);
+ }
+ break; // there is nothing else
+ }
+ }
+ }
+ }
+ catch(...)
+ {
+ MessageBox(NULL,"Translate header error","",0);
+ }
+}
+
+HYAMNMAIL WINAPI CreateNewDeleteQueueFcn(HYAMNMAIL From)
+{
+ HYAMNMAIL FirstMail,Browser;
+
+ for(FirstMail=NULL;From!=NULL;From=From->Next)
+ {
+ if((From->Flags & (YAMN_MSG_USERDELETE | YAMN_MSG_AUTODELETE)) && !(From->Flags & YAMN_MSG_DELETED))
+ {
+ if(FirstMail==NULL)
+ {
+ FirstMail=Browser=new YAMNMAIL;
+ if(FirstMail==NULL)
+ break;
+ }
+ else
+ {
+ Browser->Next=new YAMNMAIL;
+ Browser=Browser->Next;
+ }
+ Browser->ID=new char[strlen(From->ID)+1];
+ strcpy(Browser->ID,From->ID);
+ Browser->Number=From->Number;
+ Browser->Flags=From->Flags;
+ }
+ }
+ return FirstMail;
+}
+
+void WINAPI SetRemoveFlagsInQueueFcn(HYAMNMAIL From,DWORD FlagsSet,DWORD FlagsNotSet,DWORD FlagsToSetRemove,int mode)
+{
+ HYAMNMAIL msgq;
+
+ for(msgq=(HYAMNMAIL)From;msgq!=NULL;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/plugins/YAMN/mails/mime.cpp b/plugins/YAMN/mails/mime.cpp
new file mode 100644
index 0000000000..f2364c91c1
--- /dev/null
+++ b/plugins/YAMN/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<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==NULL)
+ {
+ *storeto=*storetonick=NULL;
+ 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==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,"<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==NULL)
+ 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==NULL)
+ 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==NULL)
+ 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==NULL)
+ 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==NULL)
+ continue;
+
+ char *ContentType=NULL,*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(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,"<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==NULL)
+ 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;
+
+ ZeroMemory(&ShortHeader,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!=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<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(NULL!=(CharSetStr=ExtractFromContentType(partData[i].ContType,"charset=")))
+ {
+ partData[i].CodePage=GetCharsetFromString(CharSetStr,strlen(CharSetStr));
+ delete[] CharSetStr;
+ }
+ }
+ if (partData[i].ContType && !_strnicmp(partData[i].ContType,"text",4)) {
+ char *localBody=0;
+ 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=NULL;
+ if(NULL!=(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 += wcslen(partData[i].wBody);
+ }// if (partData[i].body)
+ resultSize += 100+4+3; //cr+nl+100+ 3*bullet
+ }
+ dest = new WCHAR[resultSize+1];
+ size_t destpos = 0;
+ for (i=0;i<numparts;i++){
+ if (i){ // part before first boudary should not have headers
+ char infoline[104]; size_t linesize = 0;
+ _snprintf(infoline,100,"%s %d",Translate("Part"),i);
+ linesize = strlen(infoline);
+ if (partData[i].TransEnc){
+ _snprintf(infoline+linesize,100-linesize,"; %s",partData[i].TransEnc);
+ linesize = strlen(infoline);
+ }
+ if (partData[i].ContType){
+ char *CharSetStr=strchr(partData[i].ContType,';');
+ if (CharSetStr){
+ CharSetStr[0]=0;
+ _snprintf(infoline+linesize,100-linesize,"; %s",partData[i].ContType);
+ linesize = strlen(infoline);
+ partData[i].ContType=CharSetStr+1;
+ if(NULL!=(CharSetStr=ExtractFromContentType(partData[i].ContType,"charset=")))
+ {
+ _snprintf(infoline+linesize,100-linesize,"; %s",CharSetStr);
+ linesize = strlen(infoline);
+ delete[] CharSetStr;
+ }
+ if(NULL!=(CharSetStr=ExtractFromContentType(partData[i].ContType,"name=")))
+ {
+ _snprintf(infoline+linesize,100-linesize,"; \"%s\"",CharSetStr);
+ linesize = strlen(infoline);
+ delete[] CharSetStr;
+ }
+ } else {
+ _snprintf(infoline+linesize,100-linesize,"; %s",partData[i].ContType);
+ linesize = strlen(infoline);
+ }
+ }
+ sprintf(infoline+linesize,".\r\n");
+ {WCHAR *temp=0;
+ dest[destpos] = dest[destpos+1] = dest[destpos+2] = 0x2022; // bullet;
+ destpos+=3;
+ ConvertStringToUnicode(infoline,CP_ACP,&temp);
+ size_t wsize = wcslen(temp);
+ wcscpy(&dest[destpos],temp);
+ destpos += wsize;
+ delete[] temp;
+ }
+ } // if (i)
+ if (partData[i].wBody){
+ size_t wsize = wcslen(partData[i].wBody);
+ wcscpy(&dest[destpos],partData[i].wBody);
+ destpos += wsize;
+ delete[] partData[i].wBody;
+ }
+ }
+
+ free (srcback);
+ delete[] partData;
+ dest[resultSize] = 0;//just in case
+ return dest;
+}
diff --git a/plugins/YAMN/mails/test/header.txt b/plugins/YAMN/mails/test/header.txt
new file mode 100644
index 0000000000..55a4d86d65
--- /dev/null
+++ b/plugins/YAMN/mails/test/header.txt
@@ -0,0 +1,28 @@
+Return-Path: <foromundial-return-1047-decode.com.ar-pablo=decode.com.ar@decode.com.ar>
+Delivered-To: pablo@decode.com.ar
+Received: (qmail 5438 invoked by uid 618); 5 Sep 2003 19:49:16 -0000
+Mailing-List: contact foromundial-help@decode.com.ar; run by ezmlm
+Precedence: bulk
+X-No-Archive: yes
+List-Post: <mailto:foromundial@decode.com.ar>
+List-Help: <mailto:foromundial-help@decode.com.ar>
+List-Unsubscribe: <mailto:foromundial-unsubscribe@decode.com.ar>
+List-Subscribe: <mailto:foromundial-subscribe@decode.com.ar>
+X-Seq: 1047
+Delivered-To: mailing list foromundial@decode.com.ar
+Received: (qmail 5432 invoked by uid 618); 5 Sep 2003 19:49:15 -0000
+X-Spam-Status: No, hits=3.9 required=7.5
+Message-Id: <4.2.1.20030905163128.00a998a0@mail.labsem.cetuc.puc-rio.br>
+X-Sender: sandra@mail.labsem.cetuc.puc-rio.br
+X-Mailer: QUALCOMM Windows Eudora Pro Version 4.2.1
+Date: Fri, 05 Sep 2003 16:48:12 -0300
+To: foromundial@decode.com.ar
+From: "Sandra M. Landi" <sandra@labsem.cetuc.puc-rio.br>
+Mime-Version: 1.0
+Content-Type: multipart/alternative;
+ boundary="=====================_4293080==_.ALT"
+X-Antirelay: Good relay from local net2 139.82.127.0/26
+Subject: [foromundial-1047] frases para un viernes
+
+
+.
diff --git a/plugins/YAMN/mails/test/header2.txt b/plugins/YAMN/mails/test/header2.txt
new file mode 100644
index 0000000000..3ba81a2bd0
--- /dev/null
+++ b/plugins/YAMN/mails/test/header2.txt
@@ -0,0 +1,97 @@
+Return-Path: <miranda@megami.sprintserve.net>
+Received: [from megami.sprintserve.net (megami.sprintserve.net [207.142.136.160])
+ by mail2.ba.psg.sk with ESMTP id i4FHNUY6018585
+ for <om3tn@psg.sk>; Sat, 15 May 2004 19:23:31 +0200]
+X-Envelope-To: <om3tn@psg.sk>
+Received: from miranda by megami.sprintserve.net with local (Exim 4.34)
+ id 1BP2sS-0006W6-MS
+ for om3tn@psg.sk; Sat, 15 May 2004 13:23:12 -0400
+To: Undisclosed-recipients:;
+Subject: UpozornØn¡ na odpovØÔ v t‚matu - YAMN problem
+Reply-to: forum@miranda-im.org
+From: forum@miranda-im.org:
+Message-ID: <e003226b4a46a7ca6b490345f21b91af@forums.miranda-im.org>
+MIME-Version: 1.0
+Content-type: text/plain; charset=Windows-1250
+Content-transfer-encoding: 8bit
+Date: Sat, 15 May 2004 13:23:12 -0400
+X-Priority: 3
+X-MSMail-Priority: Normal
+X-Mailer: PHP
+X-MimeOLE: Produced By phpBB2
+X-MailScanner-Information: Please contact the ISP for more information
+X-MailScanner: Found to be clean
+X-AntiAbuse: This header was added to track abuse, please include it with any abuse report
+X-AntiAbuse: Primary Hostname - megami.sprintserve.net
+X-AntiAbuse: Original Domain - psg.sk
+X-AntiAbuse: Originator/Caller UID/GID - [32110 32110] / [47 12]
+X-AntiAbuse: Sender Address Domain - megami.sprintserve.net
+X-Source:
+X-Source-Args:
+X-Source-Dir:
+.
+
+Subject: UpozornØn¡ na odpovØÔ v t‚matu - YAMN problem
+
+Return-Path: <miranda@megami.sprintserve.net>
+Received: [from megami.sprintserve.net (megami.sprintserve.net [207.142.136.160])
+ by mail2.ba.psg.sk with ESMTP id i4FHX2Y6020695
+ for <om3tn@psg.sk>; Sat, 15 May 2004 19:33:03 +0200]
+X-Envelope-To: <om3tn@psg.sk>
+Received: from miranda by megami.sprintserve.net with local (Exim 4.34)
+ id 1BP31h-0001cs-Ai
+ for om3tn@psg.sk; Sat, 15 May 2004 13:32:45 -0400
+To: Undisclosed-recipients:;
+Subject: UpozornØn¡ na odpovØÔ v t‚matu - YAMN problem
+Reply-to: forum@miranda-im.org
+From: forum@miranda-im.org
+Message-ID: <0873b36d0931479c4ebe23ba71ff4810@forums.miranda-im.org>
+MIME-Version: 1.0
+Content-type: text/plain; charset=Windows-1250
+Content-transfer-encoding: 8bit
+Date: Sat, 15 May 2004 13:32:45 -0400
+X-Priority: 3
+X-MSMail-Priority: Normal
+X-Mailer: PHP
+X-MimeOLE: Produced By phpBB2
+X-MailScanner-Information: Please contact the ISP for more information
+X-MailScanner: Found to be clean
+X-AntiAbuse: This header was added to track abuse, please include it with any abuse report
+X-AntiAbuse: Primary Hostname - megami.sprintserve.net
+X-AntiAbuse: Original Domain - psg.sk
+X-AntiAbuse: Originator/Caller UID/GID - [32110 32110] / [47 12]
+X-AntiAbuse: Sender Address Domain - megami.sprintserve.net
+X-Source:
+X-Source-Args:
+X-Source-Dir:
+
+.
+
+Received: by hplm (mbox om3tn)
+ (with POP3 daemon cucipop (v1.31 1998/05/13) Tue May 27 18:42:20 2003)
+X-From_: HMF@hotbox.ru Tue May 20 18:11:44 2003
+Return-Path: <HMF@hotbox.ru>
+Received: from ns1.slovanet.net (ns1.slovanet.net [195.28.64.119])
+ by hplm.psg.sk (8.12.9/8.12.7) with SMTP id h4KGBfxJ003732
+ for <om3tn@psg.sk>; Tue, 20 May 2003 18:11:44 +0200
+X-Envelope-To: <om3tn@psg.sk>
+Received: (qmail 6339 invoked from network); 20 May 2003 18:11:45 +0200
+Received: from unknown (HELO ??+???) (61.33.134.106)
+ by ns1.slovanet.net with SMTP; 20 May 2003 18:11:45 +0200
+Received: by london.com (Postfix, from userid 302)
+ id WTS; Tue, 20 May 2003 20:13:19
+Received: from Œù+⌥ (Œù+⌥ [61.33.134.106])
+ by mill.co.uk (Postfix) with ESMTP id 613
+ for <om3tn@psg.sk>; Tue, 20 May 2003 20:13:19
+Subject: Òàìîæåííàî÷èñòêà. ÔèíëäèÌîñêâà. Îò 0,8 çà êã, âêëþ÷àâñå ! 20:13:19
+From: <HMF@hotbox.ru>
+To: OM3TN <om3tn@psg.sk>
+Reply-To: <>
+X-Mailer: AOL 7.0 for Windows UK sub 52
+X-Priority: 1
+X-MSMail-Priority: High
+Mime-Version: 1.0
+Content-Type: text/html; charset="Windows-1251"
+Content-Transfer-Encoding: 7bit
+Date: Tue, 20 May 2003 20:13:21
+Message-Id: <DED-173-MCL662@mail-relay2.slovanet.net> \ No newline at end of file
diff --git a/plugins/YAMN/mails/test/readme.txt b/plugins/YAMN/mails/test/readme.txt
new file mode 100644
index 0000000000..35a30b255a
--- /dev/null
+++ b/plugins/YAMN/mails/test/readme.txt
@@ -0,0 +1,4 @@
+This is project for testing mime encoding/decoding. It
+is very usefull for developers, when some problems with
+non-standard headers occured. You can use it to step through
+MIME decoding functions.
diff --git a/plugins/YAMN/mails/test/test.cpp b/plugins/YAMN/mails/test/test.cpp
new file mode 100644
index 0000000000..f8dcd14e89
--- /dev/null
+++ b/plugins/YAMN/mails/test/test.cpp
@@ -0,0 +1,42 @@
+/*
+ * This file is for testing purposes. Save in header.txt your problem header and you can
+ * browse through functions to get result
+ *
+ * (c) majvan 2002-2004
+ */
+
+#include <stdio.h>
+#include "../m_mails.h"
+
+extern void WINAPI TranslateHeaderFcn(char *stream,int len,struct CMimeItem **head);
+extern void ExtractHeader(struct CMimeItem *items,int CP,struct CHeader *head);
+
+void main()
+{
+ char Buffer[8192]; //we do not suppose longer header
+ FILE *fp;
+ YAMNMAIL *Mail;
+ PMAILDATA *MailData;
+ CMimeItem *head;
+
+ struct CHeader ExtractedHeader;
+
+ if(NULL==(fp=fopen("header2.txt","r")))
+ return;
+ fread(Buffer,sizeof(Buffer),1,fp);
+ if(ferror(fp))
+ {
+ fclose(fp);
+ return;
+ }
+ fclose(fp);
+ Mail = new YAMNMAIL;
+ MailData = new PMAILDATA;
+ head = new CMimeItem;
+ Mail->MailData = *MailData;
+ Mail->MailData->TranslatedHeader = head;
+
+ TranslateHeaderFcn(Buffer,strlen(Buffer), &Mail->MailData->TranslatedHeader);
+ ExtractHeader(Mail->MailData->TranslatedHeader,CP_ACP,&ExtractedHeader);
+ return;
+} \ No newline at end of file
diff --git a/plugins/YAMN/mails/test/test.dsp b/plugins/YAMN/mails/test/test.dsp
new file mode 100644
index 0000000000..6d01b3669a
--- /dev/null
+++ b/plugins/YAMN/mails/test/test.dsp
@@ -0,0 +1,112 @@
+# Microsoft Developer Studio Project File - Name="test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=test - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "test.mak" CFG="test - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "test - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "test - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "test - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x405 /d "NDEBUG"
+# ADD RSC /l 0x405 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "test - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c
+# ADD BASE RSC /l 0x405 /d "_DEBUG"
+# ADD RSC /l 0x405 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "test - Win32 Release"
+# Name "test - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\decode.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\mails.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\mime.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\test.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/plugins/YAMN/mails/test/test.dsw b/plugins/YAMN/mails/test/test.dsw
new file mode 100644
index 0000000000..e25096d17d
--- /dev/null
+++ b/plugins/YAMN/mails/test/test.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "test"=.\test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+