OSDN Git Service

Add smtp email send code
authorFrank Li <lznuaa@gmail.com>
Wed, 15 Apr 2009 08:09:09 +0000 (16:09 +0800)
committerFrank Li <lznuaa@gmail.com>
Wed, 15 Apr 2009 08:09:09 +0000 (16:09 +0800)
Signed-off-by: Frank Li <lznuaa@gmail.com>
src/Utils/CSmtp.cpp [new file with mode: 0644]
src/Utils/CSmtp.h [new file with mode: 0644]
src/Utils/base64.cpp [new file with mode: 0644]
src/Utils/base64.h [new file with mode: 0644]

diff --git a/src/Utils/CSmtp.cpp b/src/Utils/CSmtp.cpp
new file mode 100644 (file)
index 0000000..2a8b8b1
--- /dev/null
@@ -0,0 +1,1144 @@
+//////////////////////////////////////////////////////////////////////\r
+// Original class CFastSmtp written by \r
+// christopher w. backen <immortal@cox.net>\r
+// More details at: http://www.codeproject.com/KB/IP/zsmtp.aspx\r
+// \r
+// Modifications:\r
+// 1. name of the class and some functions\r
+// 2. new functions added: SendData,ReceiveData and more\r
+// 3. authentication added\r
+// 4. attachments added\r
+// introduced by Jakub Piwowarczyk\r
+// More details at: http://www.codeproject.com/KB/mcpp/CSmtp.aspx\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#include "CSmtp.h"\r
+\r
+#pragma warning(push)\r
+#pragma warning(disable:4786)\r
+\r
+//////////////////////////////////////////////////////////////////////\r
+// Construction/Destruction\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+CSmtp::CSmtp()\r
+{\r
+       // Initialize variables\r
+       m_oError = CSMTP_NO_ERROR;\r
+       m_iXPriority = XPRIORITY_NORMAL;\r
+       m_iSMTPSrvPort = 0;\r
+\r
+       m_pcLocalHostName = NULL;\r
+       m_pcMailFrom = NULL;\r
+       m_pcNameFrom = NULL;\r
+       m_pcSubject = NULL;\r
+       m_pcMsgBody = NULL;\r
+       m_pcXMailer = NULL;\r
+       m_pcReplyTo = NULL;\r
+       m_pcLogin = NULL;\r
+       m_pcPassword = NULL;\r
+       m_pcSMTPSrvName = NULL;\r
+       \r
+       if((RecvBuf = new char[BUFFER_SIZE]) == NULL)\r
+       {\r
+               m_oError = CSMTP_LACK_OF_MEMORY;\r
+               return;\r
+       }\r
+       \r
+       if((SendBuf = new char[BUFFER_SIZE]) == NULL)\r
+       {\r
+               m_oError = CSMTP_LACK_OF_MEMORY;\r
+               return;\r
+       }\r
+       \r
+       // Initialize WinSock\r
+       WORD wVer = MAKEWORD(2,2);    \r
+       if (WSAStartup(wVer,&wsaData) != NO_ERROR)\r
+       {\r
+               m_oError = CSMTP_WSA_STARTUP;\r
+               return;\r
+       }\r
+       if (LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) \r
+       {\r
+               m_oError = CSMTP_WSA_VER;\r
+               WSACleanup();\r
+               return;\r
+       }\r
+}\r
+\r
+CSmtp::~CSmtp()\r
+{\r
+       // Clear vectors\r
+       Recipients.clear();\r
+       CCRecipients.clear();\r
+       BCCRecipients.clear();\r
+       Attachments.clear();\r
+\r
+       // Free memory\r
+       if (m_pcLocalHostName)\r
+               delete[] m_pcLocalHostName;\r
+       if (m_pcMailFrom)\r
+               delete[] m_pcMailFrom;\r
+       if (m_pcNameFrom)\r
+               delete[] m_pcNameFrom;\r
+       if (m_pcSubject)\r
+               delete[] m_pcSubject;\r
+       if (m_pcMsgBody)\r
+               delete[] m_pcMsgBody;\r
+       if (m_pcXMailer)\r
+               delete[] m_pcXMailer;\r
+       if (m_pcReplyTo)\r
+               delete[] m_pcReplyTo;\r
+       if (m_pcLogin)\r
+               delete[] m_pcLogin;\r
+       if (m_pcPassword)\r
+               delete[] m_pcPassword;\r
+       if(SendBuf)\r
+               delete[] SendBuf;\r
+       if(RecvBuf)\r
+               delete[] RecvBuf;\r
+       \r
+       // Cleanup\r
+       WSACleanup();\r
+}\r
+\r
+//////////////////////////////////////////////////////////////////////\r
+// Methods\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+bool CSmtp::AddAttachment(const char *path)\r
+{\r
+       std::string str(path);\r
+       Attachments.insert(Attachments.end(),str);\r
+       return true;\r
+}\r
+\r
+bool CSmtp::AddRecipient(const char *email, const char *name)\r
+{\r
+       assert(email);\r
+       \r
+       if(!email)\r
+       {\r
+               m_oError = CSMTP_UNDEF_RECIPENT_MAIL;\r
+               return false;\r
+       }\r
+\r
+       Recipent recipent;\r
+       recipent.Mail.insert(0,email);\r
+       name!=NULL ? recipent.Name.insert(0,name) : recipent.Name.insert(0,"");\r
+\r
+       Recipients.insert(Recipients.end(), recipent);\r
+\r
+       return true;    \r
+}\r
+\r
+bool CSmtp::AddCCRecipient(const char *email, const char *name)\r
+{\r
+       assert(email);\r
+       \r
+       if(!email)\r
+       {\r
+               m_oError = CSMTP_UNDEF_RECIPENT_MAIL;\r
+               return false;\r
+       }\r
+\r
+       Recipent recipent;\r
+       recipent.Mail.insert(0,email);\r
+       name!=NULL ? recipent.Name.insert(0,name) : recipent.Name.insert(0,"");\r
+\r
+       CCRecipients.insert(CCRecipients.end(), recipent);\r
+\r
+       return true;\r
+}\r
+\r
+bool CSmtp::AddBCCRecipient(const char *email, const char *name)\r
+{\r
+       assert(email);\r
+       \r
+       if(!email)\r
+       {\r
+               m_oError = CSMTP_UNDEF_RECIPENT_MAIL;\r
+               return false;\r
+       }\r
+\r
+       Recipent recipent;\r
+       recipent.Mail.insert(0,email);\r
+       name!=NULL ? recipent.Name.insert(0,name) : recipent.Name.insert(0,"");\r
+\r
+       BCCRecipients.insert(BCCRecipients.end(), recipent);\r
+\r
+       return true;\r
+}\r
+\r
+bool CSmtp::Send()\r
+{\r
+       unsigned int i,rcpt_count,res,FileId;\r
+       char *FileBuf = NULL, *FileName = NULL;\r
+       FILE* hFile = NULL;\r
+       unsigned long int FileSize,TotalSize,MsgPart;\r
+\r
+       // ***** CONNECTING TO SMTP SERVER *****\r
+\r
+       assert(m_pcSMTPSrvName);\r
+\r
+       // connecting to remote host:\r
+       if( (hSocket = ConnectRemoteServer(m_pcSMTPSrvName, m_iSMTPSrvPort)) == INVALID_SOCKET ) \r
+       {\r
+               m_oError = CSMTP_WSA_INVALID_SOCKET;\r
+               return false;\r
+       }\r
+       Sleep(DELAY_IN_MS);\r
+       if(!ReceiveData())\r
+               return false;\r
+\r
+       switch(SmtpXYZdigits())\r
+       {\r
+               case 220:\r
+                       break;\r
+               default:\r
+                       m_oError = CSMTP_SERVER_NOT_READY;\r
+                       return false;\r
+       }\r
+\r
+       // EHLO <SP> <domain> <CRLF>\r
+       sprintf(SendBuf,"EHLO %s\r\n",GetLocalHostName()!=NULL ? m_pcLocalHostName : "domain");\r
+       if(!SendData())\r
+               return false;\r
+       Sleep(DELAY_IN_MS);\r
+       if(!ReceiveData())\r
+               return false;\r
+\r
+       switch(SmtpXYZdigits())\r
+       {\r
+               case 250:\r
+                       break;\r
+               default:\r
+                       m_oError = CSMTP_COMMAND_EHLO;\r
+                       return false;\r
+       }\r
+\r
+       // AUTH <SP> LOGIN <CRLF>\r
+       strcpy(SendBuf,"AUTH LOGIN\r\n");\r
+       if(!SendData())\r
+               return false;\r
+       Sleep(DELAY_IN_MS);\r
+       if(!ReceiveData())\r
+               return false;\r
+\r
+       switch(SmtpXYZdigits())\r
+       {\r
+               case 334:\r
+                       break;\r
+               default:\r
+                       m_oError = CSMTP_COMMAND_AUTH_LOGIN;\r
+                       return false;\r
+       }\r
+\r
+       // send login:\r
+       if(!m_pcLogin)\r
+       {\r
+               m_oError = CSMTP_UNDEF_LOGIN;\r
+               return false;\r
+       }\r
+       std::string encoded_login = base64_encode(reinterpret_cast<const unsigned char*>(m_pcLogin),strlen(m_pcLogin));\r
+       sprintf(SendBuf,"%s\r\n",encoded_login.c_str());\r
+       if(!SendData())\r
+               return false;\r
+       Sleep(DELAY_IN_MS);\r
+       if(!ReceiveData())\r
+               return false;\r
+\r
+       switch(SmtpXYZdigits())\r
+       {\r
+               case 334:\r
+                       break;\r
+               default:\r
+                       m_oError = CSMTP_UNDEF_XYZ_RESPOMSE;\r
+                       return false;\r
+       }\r
+       \r
+       // send password:\r
+       if(!m_pcPassword)\r
+       {\r
+               m_oError = CSMTP_UNDEF_PASSWORD;\r
+               return false;\r
+       }\r
+       std::string encoded_password = base64_encode(reinterpret_cast<const unsigned char*>(m_pcPassword),strlen(m_pcPassword));\r
+       sprintf(SendBuf,"%s\r\n",encoded_password.c_str());\r
+       if(!SendData())\r
+               return false;\r
+       Sleep(DELAY_IN_MS);\r
+       if(!ReceiveData())\r
+               return false;\r
+\r
+       switch(SmtpXYZdigits())\r
+       {\r
+               case 235:\r
+                       break;\r
+               case 535:\r
+                       m_oError = CSMTP_BAD_LOGIN_PASS;\r
+                       return false;\r
+               default:\r
+                       m_oError = CSMTP_UNDEF_XYZ_RESPOMSE;\r
+                       return false;\r
+       }\r
+\r
+       // ***** SENDING E-MAIL *****\r
+       \r
+       // MAIL <SP> FROM:<reverse-path> <CRLF>\r
+       if(m_pcMailFrom == NULL)\r
+       {\r
+               m_oError = CSMTP_UNDEF_MAILFROM;\r
+               return false;\r
+       }\r
+       sprintf(SendBuf,"MAIL FROM:<%s>\r\n",m_pcMailFrom);\r
+       if(!SendData())\r
+               return false;\r
+       Sleep(DELAY_IN_MS);\r
+       if(!ReceiveData())\r
+               return false;\r
+\r
+       switch(SmtpXYZdigits())\r
+       {\r
+               case 250:\r
+                       break;\r
+               default:\r
+                       m_oError = CSMTP_COMMAND_MAIL_FROM;\r
+                       return false;\r
+       }\r
+\r
+       // RCPT <SP> TO:<forward-path> <CRLF>\r
+       rcpt_count = Recipients.size();\r
+       for(i=0;i<Recipients.size();i++)\r
+       {\r
+               sprintf(SendBuf,"RCPT TO:<%s>\r\n",(Recipients.at(i).Mail).c_str());\r
+               if(!SendData())\r
+                       return false;\r
+               Sleep(DELAY_IN_MS);\r
+               if(!ReceiveData())\r
+                       return false;\r
+\r
+               switch(SmtpXYZdigits())\r
+               {\r
+                       case 250:\r
+                               break;\r
+                       default:\r
+                               m_oError = CSMTP_COMMAND_RCPT_TO;\r
+                               rcpt_count--;\r
+               }\r
+       }\r
+       if(!rcpt_count)\r
+               return false;\r
+       for(i=0;i<CCRecipients.size();i++)\r
+       {\r
+               sprintf(SendBuf,"RCPT TO:<%s>\r\n",(CCRecipients.at(i).Mail).c_str());\r
+               if(!SendData())\r
+                       return false;\r
+               Sleep(DELAY_IN_MS);\r
+               if(!ReceiveData())\r
+                       return false;\r
+       }\r
+       for(i=0;i<BCCRecipients.size();i++)\r
+       {\r
+               sprintf(SendBuf,"RCPT TO:<%s>\r\n",(BCCRecipients.at(i).Mail).c_str());\r
+               if(!SendData())\r
+                       return false;\r
+               Sleep(DELAY_IN_MS);\r
+               if(!ReceiveData())\r
+                       return false;\r
+       }\r
+       \r
+       // DATA <CRLF>\r
+       strcpy(SendBuf,"DATA\r\n");\r
+       if(!SendData())\r
+               return false;\r
+       Sleep(DELAY_IN_MS);\r
+       if(!ReceiveData())\r
+               return false;\r
+       \r
+       switch(SmtpXYZdigits())\r
+       {\r
+               case 354:\r
+                       break;\r
+               default:\r
+                       m_oError = CSMTP_COMMAND_DATA;\r
+                       return false;\r
+       }\r
+       \r
+       // send header(s)\r
+       if(!FormatHeader(SendBuf))\r
+       {\r
+               m_oError = CSMTP_UNDEF_MSG_HEADER;\r
+               return false;\r
+       }\r
+       if(!SendData())\r
+               return false;\r
+\r
+       // send text message\r
+       sprintf(SendBuf,"%s\r\n",m_pcMsgBody); // NOTICE: each line ends with <CRLF>\r
+       if(!SendData())\r
+               return false;\r
+\r
+       // next goes attachments (if they are)\r
+       if((FileBuf = new char[55]) == NULL)\r
+       {\r
+               m_oError = CSMTP_LACK_OF_MEMORY;\r
+               return false;\r
+       }\r
+       if((FileName = new char[255]) == NULL)\r
+       {\r
+               m_oError = CSMTP_LACK_OF_MEMORY;\r
+               return false;\r
+       }\r
+       TotalSize = 0;\r
+       for(FileId=0;FileId<Attachments.size();FileId++)\r
+       {\r
+               strcpy(FileName,Attachments[FileId].c_str());\r
+\r
+               sprintf(SendBuf,"--%s\r\n",BOUNDARY_TEXT);\r
+               strcat(SendBuf,"Content-Type: application/x-msdownload; name=\"");\r
+               strcat(SendBuf,&FileName[Attachments[FileId].find_last_of("\\") + 1]);\r
+               strcat(SendBuf,"\"\r\n");\r
+               strcat(SendBuf,"Content-Transfer-Encoding: base64\r\n");\r
+               strcat(SendBuf,"Content-Disposition: attachment; filename=\"");\r
+               strcat(SendBuf,&FileName[Attachments[FileId].find_last_of("\\") + 1]);\r
+               strcat(SendBuf,"\"\r\n");\r
+               strcat(SendBuf,"\r\n");\r
+\r
+               if(!SendData())\r
+                       return false;\r
+\r
+               // opening the file:\r
+               hFile = fopen(FileName,"rb");\r
+               if(hFile == NULL)\r
+               {\r
+                       m_oError = CSMTP_FILE_NOT_EXIST;\r
+                       break;\r
+               }\r
+               \r
+               // checking file size:\r
+               FileSize = 0;\r
+               while(!feof(hFile))\r
+                       FileSize += fread(FileBuf,sizeof(char),54,hFile);\r
+               TotalSize += FileSize;\r
+\r
+               // sending the file:\r
+               if(TotalSize/1024 > MSG_SIZE_IN_MB*1024)\r
+                       m_oError = CSMTP_MSG_TOO_BIG;\r
+               else\r
+               {\r
+                       fseek (hFile,0,SEEK_SET);\r
+\r
+                       MsgPart = 0;\r
+                       for(i=0;i<FileSize/54+1;i++)\r
+                       {\r
+                               res = fread(FileBuf,sizeof(char),54,hFile);\r
+                               MsgPart ? strcat(SendBuf,base64_encode(reinterpret_cast<const unsigned char*>(FileBuf),res).c_str())\r
+                                             : strcpy(SendBuf,base64_encode(reinterpret_cast<const unsigned char*>(FileBuf),res).c_str());\r
+                               strcat(SendBuf,"\r\n");\r
+                               MsgPart += res + 2;\r
+                               if(MsgPart >= BUFFER_SIZE/2)\r
+                               { // sending part of the message\r
+                                       MsgPart = 0;\r
+                                       if(!SendData())\r
+                                       {\r
+                                               delete[] FileBuf;\r
+                                               delete[] FileName;\r
+                                               fclose(hFile);\r
+                                               return false;\r
+                                       }\r
+                               }\r
+                       }\r
+                       if(MsgPart)\r
+                       {\r
+                               if(!SendData())\r
+                               {\r
+                                       delete[] FileBuf;\r
+                                       delete[] FileName;\r
+                                       fclose(hFile);\r
+                                       return false;\r
+                               }\r
+                       }\r
+               }\r
+               fclose(hFile);\r
+       }\r
+       delete[] FileBuf;\r
+       delete[] FileName;\r
+       \r
+       // sending last message block (if there is one or more attachments)\r
+       if(Attachments.size())\r
+       {\r
+               sprintf(SendBuf,"\r\n--%s--\r\n",BOUNDARY_TEXT);\r
+               if(!SendData())\r
+                       return false;\r
+       }\r
+       \r
+       // <CRLF> . <CRLF>\r
+       strcpy(SendBuf,"\r\n.\r\n");\r
+       if(!SendData())\r
+               return false;\r
+       Sleep(DELAY_IN_MS);\r
+       if(!ReceiveData())\r
+               return false;\r
+\r
+       switch(SmtpXYZdigits())\r
+       {\r
+               case 250:\r
+                       break;\r
+               default:\r
+                       m_oError = CSMTP_MSG_BODY_ERROR;\r
+                       return false;\r
+       }\r
+\r
+       // ***** CLOSING CONNECTION *****\r
+       \r
+       // QUIT <CRLF>\r
+       strcpy(SendBuf,"QUIT\r\n");\r
+       if(!SendData())\r
+               return false;\r
+       Sleep(DELAY_IN_MS);\r
+       if(!ReceiveData())\r
+               return false;\r
+\r
+       switch(SmtpXYZdigits())\r
+       {\r
+               case 221:\r
+                       break;\r
+               default:\r
+                       m_oError = CSMTP_COMMAND_QUIT;\r
+                       hSocket = NULL;\r
+                       return false;\r
+       }\r
+\r
+       closesocket(hSocket);\r
+       hSocket = NULL;\r
+       return true;\r
+}\r
+\r
+SOCKET CSmtp::ConnectRemoteServer(const char *server,const unsigned short port)\r
+{\r
+       short nProtocolPort;\r
+       LPHOSTENT lpHostEnt;\r
+       LPSERVENT lpServEnt;\r
+       SOCKADDR_IN sockAddr;\r
+       SOCKET hServerSocket = INVALID_SOCKET;\r
+       struct in_addr addr;\r
+       \r
+       // If the user input is an alpha name for the host, use gethostbyname()\r
+       // If not, get host by addr (assume IPv4)\r
+       if(isalpha(server[0]))\r
+               lpHostEnt = gethostbyname(server);\r
+       else\r
+       {\r
+               addr.s_addr = inet_addr(server);\r
+    if(addr.s_addr == INADDR_NONE) \r
+               {\r
+                       m_oError = CSMTP_BAD_IPV4_ADDR;\r
+                       return INVALID_SOCKET;\r
+               } \r
+               else\r
+                       lpHostEnt = gethostbyaddr((char *) &addr, 4, AF_INET);\r
+       }\r
+\r
+       if(lpHostEnt != NULL)\r
+       {\r
+               if((hServerSocket = socket(PF_INET, SOCK_STREAM,0)) != INVALID_SOCKET)\r
+               {\r
+                       if(port != NULL)\r
+                               nProtocolPort = htons(port);\r
+                       else\r
+                       {\r
+                               lpServEnt = getservbyname("mail", 0);\r
+                               if (lpServEnt == NULL)\r
+                                       nProtocolPort = htons(25);\r
+                               else \r
+                                       nProtocolPort = lpServEnt->s_port;\r
+                       }\r
+                       \r
+                       sockAddr.sin_family = AF_INET;\r
+                       sockAddr.sin_port = nProtocolPort;\r
+                       sockAddr.sin_addr = *((LPIN_ADDR)*lpHostEnt->h_addr_list);\r
+                       if(connect(hServerSocket,(PSOCKADDR)&sockAddr,sizeof(sockAddr)) == SOCKET_ERROR)\r
+                       {\r
+                               m_oError = CSMTP_WSA_CONNECT;\r
+                               hServerSocket = INVALID_SOCKET;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       m_oError = CSMTP_WSA_INVALID_SOCKET;\r
+                       return INVALID_SOCKET;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               m_oError = CSMTP_WSA_GETHOSTBY_NAME_ADDR;\r
+               return INVALID_SOCKET;\r
+       }\r
+\r
+       return hServerSocket;\r
+}\r
+\r
+int CSmtp::SmtpXYZdigits()\r
+{\r
+       assert(RecvBuf);\r
+       if(RecvBuf == NULL)\r
+               return 0;\r
+       return (RecvBuf[0]-'0')*100 + (RecvBuf[1]-'0')*10 + RecvBuf[2]-'0';\r
+}\r
+\r
+bool CSmtp::FormatHeader(char* header)\r
+{\r
+       int i,s = 0;\r
+       TCHAR szDate[500];\r
+       TCHAR sztTime[500];\r
+       char *to = NULL;\r
+       char *cc = NULL;\r
+       char *bcc = NULL;\r
+\r
+       // check for at least one recipient\r
+       if(Recipients.size())\r
+       {\r
+               for (unsigned int i=s=0;i<Recipients.size();i++)\r
+                       s += Recipients[i].Mail.size() + Recipients[i].Name.size() + 3;\r
+               if (s == 0) \r
+                       s = 1;\r
+               if((to = new char[s]) == NULL)\r
+               {\r
+                       m_oError = CSMTP_LACK_OF_MEMORY;\r
+                       return false;\r
+               }\r
+\r
+               to[0] = '\0';\r
+               for (i=0;i<Recipients.size();i++)\r
+               {\r
+                       i > 0 ? strcat(to,","):strcpy(to,"");\r
+                       strcat(to,Recipients[i].Name.c_str());\r
+                       strcat(to,"<");\r
+                       strcat(to,Recipients[i].Mail.c_str());\r
+                       strcat(to,">");\r
+               }\r
+       }\r
+       else\r
+       {\r
+               m_oError = CSMTP_UNDEF_RECIPENTS;\r
+               return false;\r
+       }\r
+\r
+       if(CCRecipients.size())\r
+       {\r
+               for (i=s=0;i<CCRecipients.size();i++)\r
+                       s += CCRecipients[i].Mail.size() + CCRecipients[i].Name.size() + 3;\r
+               if (s == 0)\r
+                       s = 1;\r
+               if((cc = new char[s]) == NULL)\r
+               {\r
+                       m_oError = CSMTP_LACK_OF_MEMORY;\r
+                       delete[] to;\r
+                       return false;\r
+               }\r
+\r
+               cc[0] = '\0';\r
+               for (i=0;i<CCRecipients.size();i++)\r
+               {\r
+                       i > 0 ? strcat(cc,","):strcpy(cc,"");\r
+                       strcat(cc,CCRecipients[i].Name.c_str());\r
+                       strcat(cc,"<");\r
+                       strcat(cc,CCRecipients[i].Mail.c_str());\r
+                       strcat(cc,">");\r
+               }\r
+       }\r
+\r
+       if(BCCRecipients.size())\r
+       {\r
+               for (i=s=0;i<BCCRecipients.size();i++)\r
+                       s += BCCRecipients[i].Mail.size() + BCCRecipients[i].Name.size() + 3;\r
+               if(s == 0)\r
+                       s=1;\r
+               if((bcc = new char[s]) == NULL)\r
+               {\r
+                       m_oError = CSMTP_LACK_OF_MEMORY;\r
+                       delete[] to;\r
+                       delete[] cc;\r
+                       return false;\r
+               }\r
+\r
+               bcc[0] = '\0';\r
+               for (i=0;i<BCCRecipients.size();i++)\r
+               {\r
+                       i > 0 ? strcat(bcc,","):strcpy(bcc,"");\r
+                       strcat(bcc,BCCRecipients[i].Name.c_str());\r
+                       strcat(bcc,"<");\r
+                       strcat(bcc,BCCRecipients[i].Mail.c_str());\r
+                       strcat(bcc,">");\r
+               }\r
+       }\r
+       \r
+       // Date: <SP> <dd> <SP> <mon> <SP> <yy> <SP> <hh> ":" <mm> ":" <ss> <SP> <zone> <CRLF>\r
+       SYSTEMTIME st={0};\r
+       ::GetSystemTime(&st);\r
+       ::GetDateFormat(MAKELCID(0x0409,SORT_DEFAULT),0,&st,"ddd\',\' dd MMM yyyy",szDate,sizeof(szDate));\r
+       ::GetTimeFormat(MAKELCID(0x0409,SORT_DEFAULT),TIME_FORCE24HOURFORMAT,&st,"HH\':\'mm\':\'ss",sztTime,sizeof(sztTime));\r
+       sprintf(header,"Date: %s %s\r\n", szDate, sztTime); \r
+       \r
+       // From: <SP> <sender>  <SP> "<" <sender-email> ">" <CRLF>\r
+       if(m_pcMailFrom == NULL)\r
+       {\r
+               m_oError = CSMTP_UNDEF_MAILFROM;\r
+    delete[] to;\r
+    delete[] cc;\r
+    delete[] bcc;\r
+               return false;\r
+       }\r
+       strcat(header,"From: ");        \r
+       if(m_pcNameFrom)\r
+               strcat(header, m_pcNameFrom);\r
+       strcat(header," <");\r
+       strcat(header,m_pcMailFrom);\r
+       strcat(header, ">\r\n");\r
+\r
+       // X-Mailer: <SP> <xmailer-app> <CRLF>\r
+       if (m_pcXMailer != NULL)\r
+       {\r
+               strcat(header,"X-Mailer: ");\r
+               strcat(header, m_pcXMailer);\r
+               strcat(header, "\r\n");\r
+       }\r
+\r
+       // Reply-To: <SP> <reverse-path> <CRLF>\r
+       if(m_pcReplyTo != NULL)\r
+       {\r
+               strcat(header, "Reply-To: ");\r
+               strcat(header, m_pcReplyTo);\r
+               strcat(header, "\r\n");\r
+       }\r
+\r
+       // X-Priority: <SP> <number> <CRLF>\r
+       switch(m_iXPriority)\r
+       {\r
+               case XPRIORITY_HIGH:\r
+                       strcat(header,"X-Priority: 2 (High)\r\n");\r
+                       break;\r
+               case XPRIORITY_NORMAL:\r
+                       strcat(header,"X-Priority: 3 (Normal)\r\n");\r
+                       break;\r
+               case XPRIORITY_LOW:\r
+                       strcat(header,"X-Priority: 4 (Low)\r\n");\r
+                       break;\r
+               default:\r
+                       strcat(header,"X-Priority: 3 (Normal)\r\n");\r
+       }\r
+\r
+       // To: <SP> <remote-user-mail> <CRLF>\r
+       strcat(header,"To: ");\r
+       strcat(header, to);\r
+       strcat(header, "\r\n");\r
+\r
+       // Cc: <SP> <remote-user-mail> <CRLF>\r
+       if(CCRecipients.size())\r
+       {\r
+               strcat(header,"Cc: ");\r
+               strcat(header, cc);\r
+               strcat(header, "\r\n");\r
+       }\r
+\r
+       if(BCCRecipients.size())\r
+       {\r
+               strcat(header,"Bcc: ");\r
+               strcat(header, bcc);\r
+               strcat(header, "\r\n");\r
+       }\r
+\r
+       // Subject: <SP> <subject-text> <CRLF>\r
+       if(m_pcSubject == NULL) \r
+       {\r
+               m_oError = CSMTP_UNDEF_SUBJECT;\r
+               strcat(header, "Subject:  ");\r
+       }\r
+       else\r
+       {\r
+         strcat(header, "Subject: ");\r
+         strcat(header, m_pcSubject);\r
+       }\r
+       strcat(header, "\r\n");\r
+       \r
+       // MIME-Version: <SP> 1.0 <CRLF>\r
+       strcat(header,"MIME-Version: 1.0\r\n");\r
+       if(!Attachments.size())\r
+       { // no attachments\r
+               strcat(header,"Content-type: text/plain; charset=US-ASCII\r\n");\r
+               strcat(header,"Content-Transfer-Encoding: 7bit\r\n");\r
+               strcat(SendBuf,"\r\n");\r
+       }\r
+       else\r
+       { // there is one or more attachments\r
+               strcat(header,"Content-Type: multipart/mixed; boundary=\"");\r
+               strcat(header,BOUNDARY_TEXT);\r
+               strcat(header,"\"\r\n");\r
+               strcat(header,"\r\n");\r
+               // first goes text message\r
+               strcat(SendBuf,"--");\r
+               strcat(SendBuf,BOUNDARY_TEXT);\r
+               strcat(SendBuf,"\r\n");\r
+               strcat(SendBuf,"Content-type: text/plain; charset=US-ASCII\r\n");\r
+               strcat(SendBuf,"Content-Transfer-Encoding: 7bit\r\n");\r
+               strcat(SendBuf,"\r\n");\r
+       }\r
+       \r
+       // clean up\r
+       delete[] to;\r
+       delete[] cc;\r
+       delete[] bcc;\r
+       \r
+       // done    \r
+       return true;    \r
+}\r
+\r
+bool CSmtp::ReceiveData()\r
+{\r
+       assert(RecvBuf);\r
+\r
+       int res;\r
+\r
+       if(RecvBuf == NULL)\r
+               return false;\r
+       \r
+       if( (res = recv(hSocket,RecvBuf,BUFFER_SIZE,0)) == SOCKET_ERROR )\r
+       {\r
+               m_oError = CSMTP_WSA_RECV;\r
+               return false;\r
+       }\r
+       if(res == 0)\r
+       {\r
+               m_oError = CSMTP_CONNECTION_CLOSED;\r
+               return false;\r
+       }\r
+       RecvBuf[res] = '\0';\r
+\r
+       return true;\r
+}\r
+\r
+bool CSmtp::SendData()\r
+{\r
+       assert(SendBuf);\r
+\r
+       int idx = 0,res,nLeft = strlen(SendBuf);\r
+       while(nLeft > 0)\r
+       {\r
+               if( res = send(hSocket,&SendBuf[idx],nLeft,0) == SOCKET_ERROR)\r
+               {\r
+                       m_oError = CSMTP_WSA_SEND;\r
+                       return false;\r
+               }\r
+               if(!res)\r
+                       break;\r
+               nLeft -= res;\r
+               idx += res;\r
+       }\r
+       return true;\r
+}\r
+\r
+CSmtpError CSmtp::GetLastError()\r
+{\r
+       return m_oError;\r
+}\r
+\r
+/*\r
+const char* const CSmtp::GetLocalHostIP()\r
+{\r
+       in_addr *iaHost = NULL;\r
+       HOSTENT *pHe = NULL;\r
+       \r
+       if (m_pcIPAddr)\r
+               delete[] m_pcIPAddr;\r
+       \r
+       if(gethostname(m_pcHostName,255) != SOCKET_ERROR)\r
+       {\r
+               pHe = gethostbyname(m_pcHostName);\r
+               if (pHe != NULL) \r
+               {\r
+                       for (int i=0;pHe->h_addr_list[i] != 0;i++)\r
+                       {\r
+                               iaHost = (LPIN_ADDR)pHe->h_addr_list[i];\r
+                               m_pcIPAddr = inet_ntoa(*iaHost);\r
+                       }\r
+               }            \r
+       } \r
+       else \r
+       {\r
+               m_oError = CSMTP_WSA_GETHOSTBY_NAME_ADDR;\r
+               m_pcIPAddr = NULL;\r
+       }\r
+       \r
+       return m_pcIPAddr;\r
+}\r
+*/\r
+\r
+const char* const CSmtp::GetLocalHostName() \r
+{\r
+       if(m_pcLocalHostName)\r
+               delete[] m_pcLocalHostName;\r
+       if((m_pcLocalHostName = new char[255]) == NULL)\r
+       {\r
+               m_oError = CSMTP_LACK_OF_MEMORY;\r
+               return NULL;\r
+       }\r
+       if(gethostname((char FAR*)m_pcLocalHostName,255) == SOCKET_ERROR)\r
+               m_oError = CSMTP_WSA_HOSTNAME;\r
+       return m_pcLocalHostName;\r
+}\r
+\r
+unsigned const int CSmtp::GetBCCRecipientCount()\r
+{\r
+       return BCCRecipients.size();\r
+}\r
+\r
+unsigned const int CSmtp::GetCCRecipientCount() \r
+{\r
+       return CCRecipients.size();\r
+}\r
+\r
+const char* const CSmtp::GetMessageBody() \r
+{\r
+       return m_pcMsgBody;\r
+}\r
+\r
+unsigned const int CSmtp::GetRecipientCount()\r
+{\r
+       return Recipients.size();\r
+}\r
+\r
+const char* const CSmtp::GetReplyTo()  \r
+{\r
+       return m_pcReplyTo;\r
+}\r
+\r
+const char* const CSmtp::GetMailFrom() \r
+{\r
+       return m_pcMailFrom;\r
+}\r
+\r
+const char* const CSmtp::GetSenderName() \r
+{\r
+       return m_pcNameFrom;\r
+}\r
+\r
+const char* const CSmtp::GetSubject() \r
+{\r
+       return m_pcSubject;\r
+}\r
+\r
+const char* const CSmtp::GetXMailer() \r
+{\r
+       return m_pcXMailer;\r
+}\r
+\r
+CSmptXPriority CSmtp::GetXPriority()\r
+{\r
+       return m_iXPriority;\r
+}\r
+\r
+void CSmtp::SetXPriority(CSmptXPriority priority)\r
+{\r
+       m_iXPriority = priority;\r
+}\r
+\r
+void CSmtp::SetMessageBody(const char *body)\r
+{\r
+       assert(body);\r
+       int s = strlen(body);\r
+       if (m_pcMsgBody)\r
+               delete[] m_pcMsgBody;\r
+       if((m_pcMsgBody = new char[s+1]) == NULL)\r
+       {\r
+               m_oError = CSMTP_LACK_OF_MEMORY;\r
+               return;\r
+       }\r
+       strcpy(m_pcMsgBody, body);    \r
+}\r
+\r
+void CSmtp::SetReplyTo(const char *replyto)\r
+{\r
+       assert(replyto);\r
+       int s = strlen(replyto);\r
+       if (m_pcReplyTo)\r
+               delete[] m_pcReplyTo;\r
+       if((m_pcReplyTo = new char[s+1]) == NULL)\r
+       {\r
+               m_oError = CSMTP_LACK_OF_MEMORY;\r
+               return;\r
+       }\r
+       strcpy(m_pcReplyTo, replyto);\r
+}\r
+\r
+void CSmtp::SetSenderMail(const char *email)\r
+{\r
+       assert(email);\r
+       int s = strlen(email);\r
+       if (m_pcMailFrom)\r
+               delete[] m_pcMailFrom;\r
+       if((m_pcMailFrom = new char[s+1]) == NULL)\r
+       {\r
+               m_oError = CSMTP_LACK_OF_MEMORY;\r
+               return;\r
+       }\r
+       strcpy(m_pcMailFrom, email);        \r
+}\r
+\r
+void CSmtp::SetSenderName(const char *name)\r
+{\r
+       assert(name);\r
+       int s = strlen(name);\r
+       if (m_pcNameFrom)\r
+               delete[] m_pcNameFrom;\r
+       if((m_pcNameFrom = new char[s+1]) == NULL)\r
+       {\r
+               m_oError = CSMTP_LACK_OF_MEMORY;\r
+               return;\r
+       }\r
+       strcpy(m_pcNameFrom, name);\r
+}\r
+\r
+void CSmtp::SetSubject(const char *subject)\r
+{\r
+       assert(subject);\r
+       int s = strlen(subject);\r
+       if (m_pcSubject)\r
+               delete[] m_pcSubject;\r
+       m_pcSubject = new char[s+1];\r
+       strcpy(m_pcSubject, subject);\r
+}\r
+\r
+void CSmtp::SetXMailer(const char *xmailer)\r
+{\r
+       assert(xmailer);\r
+       int s = strlen(xmailer);\r
+       if (m_pcXMailer)\r
+               delete[] m_pcXMailer;\r
+       if((m_pcXMailer = new char[s+1]) == NULL)\r
+       {\r
+               m_oError = CSMTP_LACK_OF_MEMORY;\r
+               return;\r
+       }\r
+       strcpy(m_pcXMailer, xmailer);\r
+}\r
+\r
+void CSmtp::SetLogin(const char *login)\r
+{\r
+       assert(login);\r
+       int s = strlen(login);\r
+       if (m_pcLogin)\r
+               delete[] m_pcLogin;\r
+       if((m_pcLogin = new char[s+1]) == NULL)\r
+       {\r
+               m_oError = CSMTP_LACK_OF_MEMORY;\r
+               return;\r
+       }\r
+       strcpy(m_pcLogin, login);\r
+}\r
+\r
+void CSmtp::SetPassword(const char *password)\r
+{\r
+       assert(password);\r
+       int s = strlen(password);\r
+       if (m_pcPassword)\r
+               delete[] m_pcPassword;\r
+       if((m_pcPassword = new char[s+1]) == NULL)\r
+       {\r
+               m_oError = CSMTP_LACK_OF_MEMORY;\r
+               return;\r
+       }\r
+       strcpy(m_pcPassword, password);\r
+}\r
+\r
+void CSmtp::SetSMTPServer(const char* SrvName,const unsigned short SrvPort)\r
+{\r
+       assert(SrvName);\r
+       m_iSMTPSrvPort = SrvPort;\r
+       int s = strlen(SrvName);\r
+       if(m_pcSMTPSrvName)\r
+               delete[] m_pcSMTPSrvName;\r
+       if((m_pcSMTPSrvName = new char[s+1]) == NULL)\r
+       {\r
+               m_oError = CSMTP_LACK_OF_MEMORY;\r
+               return;\r
+       }\r
+       strcpy(m_pcSMTPSrvName, SrvName);\r
+}\r
+\r
+//////////////////////////////////////////////////////////////////////\r
+// Friends\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+char* GetErrorText(CSmtpError ErrorId)\r
+{\r
+       switch(ErrorId)\r
+       {\r
+               case CSMTP_NO_ERROR:\r
+                       return "";\r
+               case CSMTP_WSA_STARTUP:\r
+                       return "Unable to initialise winsock2.";\r
+               case CSMTP_WSA_VER:\r
+                       return "Wrong version of the winsock2.";\r
+               case CSMTP_WSA_SEND:\r
+                       return "Function send() failed.";\r
+               case CSMTP_WSA_RECV:\r
+                       return "Function recv() failed.";\r
+               case CSMTP_WSA_CONNECT:\r
+                       return "Function connect failed.";\r
+               case CSMTP_WSA_GETHOSTBY_NAME_ADDR:\r
+                       return "Functions gethostbyname() or gethostbyaddr() failed.";\r
+               case CSMTP_WSA_INVALID_SOCKET:\r
+                       return "Invalid winsock2 socket.";\r
+               case CSMTP_WSA_HOSTNAME:\r
+                       return "Function hostname() failed.";\r
+               case CSMTP_BAD_IPV4_ADDR:\r
+                       return "Improper IPv4 address.";\r
+               case CSMTP_UNDEF_MSG_HEADER:\r
+                       return "Undefined message header.";\r
+               case CSMTP_UNDEF_MAILFROM:\r
+                       return "Undefined from is the mail.";\r
+               case CSMTP_UNDEF_SUBJECT:\r
+                       return "Undefined message subject.";\r
+               case CSMTP_UNDEF_RECIPENTS:\r
+                       return "Undefined at least one reciepent.";\r
+               case CSMTP_UNDEF_RECIPENT_MAIL:\r
+                       return "Undefined recipent mail.";\r
+               case CSMTP_UNDEF_LOGIN:\r
+                       return "Undefined user login.";\r
+               case CSMTP_UNDEF_PASSWORD:\r
+                       return "Undefined user password.";\r
+               case CSMTP_COMMAND_MAIL_FROM:\r
+                       return "Server returned error after sending MAIL FROM.";\r
+               case CSMTP_COMMAND_EHLO:\r
+                       return "Server returned error after sending EHLO.";\r
+               case CSMTP_COMMAND_AUTH_LOGIN:\r
+                       return "Server returned error after sending AUTH LOGIN.";\r
+               case CSMTP_COMMAND_DATA:\r
+                       return "Server returned error after sending DATA.";\r
+               case CSMTP_COMMAND_QUIT:\r
+                       return "Server returned error after sending QUIT.";\r
+               case CSMTP_COMMAND_RCPT_TO:\r
+                       return "Server returned error after sending RCPT TO.";\r
+               case CSMTP_MSG_BODY_ERROR:\r
+                       return "Error in message body";\r
+               case CSMTP_CONNECTION_CLOSED:\r
+                       return "Server has closed the connection.";\r
+               case CSMTP_SERVER_NOT_READY:\r
+                       return "Server is not ready.";\r
+               case CSMTP_FILE_NOT_EXIST:\r
+                       return "File not exist.";\r
+               case CSMTP_MSG_TOO_BIG:\r
+                       return "Message is too big.";\r
+               case CSMTP_BAD_LOGIN_PASS:\r
+                       return "Bad login or password.";\r
+               case CSMTP_UNDEF_XYZ_RESPOMSE:\r
+                       return "Undefined xyz SMTP response.";\r
+               case CSMTP_LACK_OF_MEMORY:\r
+                       return "Lack of memory.";\r
+               default:\r
+                       return "Undefined error id.";\r
+       }\r
+}\r
+\r
+#pragma warning(pop)\r
diff --git a/src/Utils/CSmtp.h b/src/Utils/CSmtp.h
new file mode 100644 (file)
index 0000000..252e3be
--- /dev/null
@@ -0,0 +1,153 @@
+// CSmtp.h: interface for the Smtp class.\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#if !defined __CSMTP_H__\r
+#define __CSMTP_H__\r
+\r
+#if _MSC_VER > 1000\r
+#pragma once\r
+#endif // _MSC_VER > 1000\r
+\r
+#include <winsock2.h>\r
+\r
+#include <assert.h>\r
+#include "base64.h"\r
+\r
+#pragma comment(lib, "ws2_32.lib")\r
+\r
+#pragma warning(push)\r
+#pragma warning(disable:4786)\r
+\r
+#include <vector>\r
+#include <string>\r
+\r
+#define BUFFER_SIZE 10240        // SendData and RecvData buffers sizes\r
+#define DELAY_IN_MS 10                 // delay between send and recv functions\r
+#define MSG_SIZE_IN_MB 5               // the maximum size of the message with all attachments\r
+\r
+const char BOUNDARY_TEXT[] = "__MESSAGE__ID__54yg6f6h6y456345";\r
+\r
+enum CSmtpError\r
+{\r
+       CSMTP_NO_ERROR = 0,\r
+       CSMTP_WSA_STARTUP = 100, // WSAGetLastError()\r
+       CSMTP_WSA_VER,\r
+       CSMTP_WSA_SEND,\r
+       CSMTP_WSA_RECV,\r
+       CSMTP_WSA_CONNECT,\r
+       CSMTP_WSA_GETHOSTBY_NAME_ADDR,\r
+       CSMTP_WSA_INVALID_SOCKET,\r
+       CSMTP_WSA_HOSTNAME,\r
+       CSMTP_BAD_IPV4_ADDR,\r
+       CSMTP_UNDEF_MSG_HEADER = 200,\r
+       CSMTP_UNDEF_MAILFROM,\r
+       CSMTP_UNDEF_SUBJECT,\r
+       CSMTP_UNDEF_RECIPENTS,\r
+       CSMTP_UNDEF_LOGIN,\r
+       CSMTP_UNDEF_PASSWORD,\r
+       CSMTP_UNDEF_RECIPENT_MAIL,\r
+       CSMTP_COMMAND_MAIL_FROM = 300,\r
+       CSMTP_COMMAND_EHLO,\r
+       CSMTP_COMMAND_AUTH_LOGIN,\r
+       CSMTP_COMMAND_DATA,\r
+       CSMTP_COMMAND_QUIT,\r
+       CSMTP_COMMAND_RCPT_TO,\r
+       CSMTP_MSG_BODY_ERROR,\r
+       CSMTP_CONNECTION_CLOSED = 400, // by server\r
+       CSMTP_SERVER_NOT_READY, // remote server\r
+       CSMTP_FILE_NOT_EXIST,\r
+       CSMTP_MSG_TOO_BIG,\r
+       CSMTP_BAD_LOGIN_PASS,\r
+       CSMTP_UNDEF_XYZ_RESPOMSE,\r
+       CSMTP_LACK_OF_MEMORY\r
+};\r
+\r
+enum CSmptXPriority\r
+{\r
+       XPRIORITY_HIGH = 2,\r
+       XPRIORITY_NORMAL = 3,\r
+       XPRIORITY_LOW = 4\r
+};\r
+\r
+class CSmtp  \r
+{\r
+public:\r
+       CSmtp();\r
+       virtual ~CSmtp();\r
+       bool AddRecipient(const char *email, const char *name=NULL);\r
+       bool AddBCCRecipient(const char *email, const char *name=NULL);\r
+       bool AddCCRecipient(const char *email, const char *name=NULL);    \r
+       bool AddAttachment(const char *path);   \r
+       const unsigned int GetBCCRecipientCount();    \r
+       const unsigned int GetCCRecipientCount();\r
+       const unsigned int GetRecipientCount();    \r
+       const char* const GetLocalHostIP();\r
+       const char* const GetLocalHostName();    \r
+       const char* const GetMessageBody();    \r
+       const char* const GetReplyTo();\r
+       const char* const GetMailFrom();\r
+       const char* const GetSenderName();\r
+       const char* const GetSubject();    \r
+       const char* const GetXMailer();\r
+       CSmptXPriority GetXPriority();\r
+       CSmtpError GetLastError();\r
+       bool Send();\r
+       void SetMessageBody(const char*);\r
+       void SetSubject(const char*);\r
+       void SetSenderName(const char*);\r
+       void SetSenderMail(const char*);\r
+       void SetReplyTo(const char*);\r
+       void SetXMailer(const char*);\r
+       void SetLogin(const char*);\r
+       void SetPassword(const char*);\r
+       void SetXPriority(CSmptXPriority);\r
+       void SetSMTPServer(const char* server,const unsigned short port=0);\r
+\r
+private:       \r
+       CSmtpError m_oError;\r
+       char* m_pcLocalHostName;\r
+       char* m_pcMailFrom;\r
+       char* m_pcNameFrom;\r
+       char* m_pcSubject;\r
+       char* m_pcMsgBody;\r
+       char* m_pcXMailer;\r
+       char* m_pcReplyTo;\r
+       char* m_pcIPAddr;\r
+       char* m_pcLogin;\r
+       char* m_pcPassword;\r
+       char* m_pcSMTPSrvName;\r
+       unsigned short m_iSMTPSrvPort;\r
+       CSmptXPriority m_iXPriority;\r
+       char *SendBuf;\r
+       char *RecvBuf;\r
+\r
+\r
+       \r
+       WSADATA wsaData;\r
+       SOCKET hSocket;\r
+\r
+       struct Recipent\r
+       {\r
+               std::string Name;\r
+               std::string Mail;\r
+       };\r
+\r
+       std::vector<Recipent> Recipients;\r
+       std::vector<Recipent> CCRecipients;\r
+       std::vector<Recipent> BCCRecipients;\r
+       std::vector<std::string> Attachments;\r
\r
+       bool ReceiveData();\r
+       bool SendData();\r
+       bool FormatHeader(char*);\r
+       int SmtpXYZdigits();\r
+       SOCKET ConnectRemoteServer(const char* server, const unsigned short port=NULL);\r
+       \r
+       friend char* GetErrorText(CSmtpError);\r
+};\r
+\r
+\r
+#pragma warning(pop)\r
+\r
+#endif // __CSMTP_H__\r
diff --git a/src/Utils/base64.cpp b/src/Utils/base64.cpp
new file mode 100644 (file)
index 0000000..c1716e8
--- /dev/null
@@ -0,0 +1,127 @@
+/* \r
+   base64.cpp and base64.h\r
+\r
+   Copyright (C) 2004-2008 René Nyffenegger\r
+\r
+   This source code is provided 'as-is', without any express or implied\r
+   warranty. In no event will the author be held liable for any damages\r
+   arising from the use of this software.\r
+\r
+   Permission is granted to anyone to use this software for any purpose,\r
+   including commercial applications, and to alter it and redistribute it\r
+   freely, subject to the following restrictions:\r
+\r
+   1. The origin of this source code must not be misrepresented; you must not\r
+      claim that you wrote the original source code. If you use this source code\r
+      in a product, an acknowledgment in the product documentation would be\r
+      appreciated but is not required.\r
+\r
+   2. Altered source versions must be plainly marked as such, and must not be\r
+      misrepresented as being the original source code.\r
+\r
+   3. This notice may not be removed or altered from any source distribution.\r
+\r
+   René Nyffenegger rene.nyffenegger@adp-gmbh.ch\r
+\r
+*/\r
+\r
+#include "base64.h"\r
+#include <iostream>\r
+\r
+static const std::string base64_chars = \r
+             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"\r
+             "abcdefghijklmnopqrstuvwxyz"\r
+             "0123456789+/";\r
+\r
+\r
+static inline bool is_base64(unsigned char c) \r
+{\r
+  return (isalnum(c) || (c == '+') || (c == '/'));\r
+}\r
+\r
+std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) \r
+{\r
+  std::string ret;\r
+  int i = 0, j = 0;\r
+  unsigned char char_array_3[3], char_array_4[4];\r
+\r
+  while (in_len--)\r
+       {\r
+    char_array_3[i++] = *(bytes_to_encode++);\r
+    if (i == 3) \r
+               {\r
+      char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;\r
+      char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);\r
+      char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);\r
+      char_array_4[3] = char_array_3[2] & 0x3f;\r
+\r
+      for(i = 0; (i <4) ; i++)\r
+        ret += base64_chars[char_array_4[i]];\r
+      i = 0;\r
+    }\r
+  }\r
+\r
+  if (i)\r
+  {\r
+    for(j = i; j < 3; j++)\r
+      char_array_3[j] = '\0';\r
+\r
+    char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;\r
+    char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);\r
+    char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);\r
+    char_array_4[3] = char_array_3[2] & 0x3f;\r
+\r
+    for (j = 0; (j < i + 1); j++)\r
+      ret += base64_chars[char_array_4[j]];\r
+\r
+    while((i++ < 3))\r
+      ret += '=';\r
+\r
+  }\r
+\r
+  return ret;\r
+\r
+}\r
+\r
+std::string base64_decode(std::string const& encoded_string) \r
+{\r
+  int in_len = encoded_string.size();\r
+  int i = 0, j = 0, in_ = 0;\r
+  unsigned char char_array_4[4], char_array_3[3];\r
+  std::string ret;\r
+\r
+  while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) \r
+       {\r
+    char_array_4[i++] = encoded_string[in_]; in_++;\r
+    if (i ==4) {\r
+      for (i = 0; i <4; i++)\r
+        char_array_4[i] = base64_chars.find(char_array_4[i]);\r
+\r
+      char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);\r
+      char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);\r
+      char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];\r
+\r
+      for (i = 0; (i < 3); i++)\r
+        ret += char_array_3[i];\r
+      i = 0;\r
+    }\r
+  }\r
+\r
+  if (i) \r
+       {\r
+    for (j = i; j <4; j++)\r
+      char_array_4[j] = 0;\r
+\r
+    for (j = 0; j <4; j++)\r
+      char_array_4[j] = base64_chars.find(char_array_4[j]);\r
+\r
+    char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);\r
+    char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);\r
+    char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];\r
+\r
+    for (j = 0; (j < i - 1); j++) \r
+                       ret += char_array_3[j];\r
+  }\r
+\r
+  return ret;\r
+}\r
diff --git a/src/Utils/base64.h b/src/Utils/base64.h
new file mode 100644 (file)
index 0000000..9e3017b
--- /dev/null
@@ -0,0 +1,9 @@
+#include <string>\r
+\r
+#ifndef _BASE64_H_\r
+#define _BASE64_H_\r
+\r
+std::string base64_encode(unsigned char const* , unsigned int len);\r
+std::string base64_decode(std::string const& s);\r
+\r
+#endif
\ No newline at end of file