diff options
Diffstat (limited to 'src/dkimbase.cpp')
-rw-r--r-- | src/dkimbase.cpp | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/src/dkimbase.cpp b/src/dkimbase.cpp new file mode 100644 index 0000000..f6abf45 --- /dev/null +++ b/src/dkimbase.cpp @@ -0,0 +1,320 @@ +/***************************************************************************** +* Copyright 2005 Alt-N Technologies, Ltd. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* This code incorporates intellectual property owned by Yahoo! and licensed +* pursuant to the Yahoo! DomainKeys Patent License Agreement. +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* Changes done by ¢feh@fehcom.de obeying the above license +* +*****************************************************************************/ +#include <string.h> +#include <algorithm> +#include "dkim.h" +#include "dkimbase.h" + + +CDKIMBase::CDKIMBase() +{ + m_From = NULL; + m_Sender = NULL; + m_hTag = NULL; + m_hTagSize = 0; + m_hTagPos = 0; + m_Line = NULL; + m_LineSize = 0; + m_LinePos = 0; + m_InHeaders = true; +} + +CDKIMBase::~CDKIMBase() // delete +{ + Free(m_Line); + Free(m_From); + Free(m_Sender); + Free(m_hTag); +} + +int CDKIMBase::Init(void) +{ + return DKIM_SUCCESS; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// Alloc - allocate buffer +// +//////////////////////////////////////////////////////////////////////////////// +int CDKIMBase::Alloc(char*& szBuffer,int nRequiredSize) +{ + szBuffer = new char[nRequiredSize]; + + return (szBuffer == NULL) ? DKIM_OUT_OF_MEMORY : DKIM_SUCCESS; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// ReAlloc - extend buffer if necessary, leaving room for future expansion +// +//////////////////////////////////////////////////////////////////////////////// +int CDKIMBase::ReAlloc(char*& szBuffer,int& nBufferSize,int nRequiredSize) +{ + if (nRequiredSize > nBufferSize) { + char* newp; + int nNewSize = nRequiredSize + BUFFER_ALLOC_INCREMENT; + + if (Alloc(newp,nNewSize) == DKIM_SUCCESS) { + if (szBuffer != NULL && nBufferSize > 0) { + memcpy(newp,szBuffer,nBufferSize); + delete[] szBuffer; + } + szBuffer = newp; + nBufferSize = nNewSize; + } else { + return DKIM_OUT_OF_MEMORY; // memory alloc error! + } + } + + return DKIM_SUCCESS; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// Process - split buffers into lines without any CRs or LFs at the end. +// +//////////////////////////////////////////////////////////////////////////////// +void CDKIMBase::Free(char* szBuffer) +{ + if (szBuffer) + delete[] szBuffer; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// Process - split buffers into lines without any CRs or LFs at the end. +// +//////////////////////////////////////////////////////////////////////////////// +int CDKIMBase::Process(const char* szBuffer,int nBufLength,bool bEOF) +{ const char* p = szBuffer; + const char* e = szBuffer + nBufLength; + + while (p < e) { + if (*p != '\n' || m_LinePos == 0 || m_Line[m_LinePos - 1] != '\r') { + // add char to line + if (m_LinePos >= m_LineSize) { + int nRet = ReAlloc(m_Line,m_LineSize,m_LinePos + 1); + if (nRet != DKIM_SUCCESS) return nRet; + } + m_Line[m_LinePos++] = *p; + } else { + // back up past the CR + m_LinePos--; + + if (m_InHeaders) { + // process header line + if (m_LinePos == 0) { + m_InHeaders = false; + int Result = ProcessHeaders(); + if (Result != DKIM_SUCCESS) + return Result; + } else { + // append the header to the headers list + if (m_Line[0] != ' ' && m_Line[0] != '\t') { + HeaderList.push_back(string(m_Line,m_LinePos)); +// fprintf(stderr," dkimbase.cpp:Process:Input: %s \n",m_Line); + } else { + if (!HeaderList.empty()) { + HeaderList.back().append("\r\n",2).append(m_Line,m_LinePos); + } else { + // no header to append to... + } + } + } + } else { + // process body line + int Result = ProcessBody(m_Line,m_LinePos,bEOF); + if (Result != DKIM_SUCCESS) { + m_LinePos = 0; + return Result; + } + } + + m_LinePos = 0; + } + + p++; + } + + return DKIM_SUCCESS; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// ProcessFinal - process leftovers if stopping before the body or mid-line +// +//////////////////////////////////////////////////////////////////////////////// +int CDKIMBase::ProcessFinal(void) +{ + if (m_LinePos > 0) { + Process("\r\n",2,true); + } + + if (m_InHeaders) { + m_InHeaders = false; + ProcessHeaders(); + /* type conversion should be safe as length is zero */ + ProcessBody((char *)"",0,true); + } + + return DKIM_SUCCESS; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// ProcessHeaders - process the headers (to be implemented by derived class) +// +//////////////////////////////////////////////////////////////////////////////// +int CDKIMBase::ProcessHeaders() +{ + return DKIM_SUCCESS; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// ProcessBody - process body line (to be implemented by derived class) +// +//////////////////////////////////////////////////////////////////////////////// +int CDKIMBase::ProcessBody(char* szBuffer, int nBufLength, bool bEOF) +{ + return DKIM_SUCCESS; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// RemoveSWSP - remove streaming white space from buffer/string inline +// +//////////////////////////////////////////////////////////////////////////////// + +struct isswsp +{ + bool operator()(char ch) { return(ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'); } +}; + +void CDKIMBase::RemoveSWSP(char* szBuffer) +{ + *remove_if(szBuffer,szBuffer + strlen(szBuffer),isswsp()) = '\0'; +} + +void CDKIMBase::RemoveSWSP(char* pBuffer,int& nBufLength) +{ + nBufLength = remove_if(pBuffer,pBuffer+nBufLength,isswsp()) - pBuffer; +} + +void CDKIMBase::RemoveSWSP(string& sBuffer) +{ + sBuffer.erase(remove_if(sBuffer.begin(),sBuffer.end(),isswsp()),sBuffer.end()); +} + +////////////////////////////////////////////////////////////////////////////////////////// +// +// CompressSWSP - compress streaming white space into single spaces from buffer/string inline +// +////////////////////////////////////////////////////////////////////////////////////////// + +void CDKIMBase::CompressSWSP(char* pBuffer,int& nBufLength) +{ + char* pSrc = pBuffer; + char* pDst = pBuffer; + char* pEnd = pBuffer + nBufLength; + + while (pSrc != pEnd) { + if (isswsp()(*pSrc)) { + + do { + ++pSrc; + } while (pSrc != pEnd && isswsp()(*pSrc)); + + if (pSrc == pEnd) + break; + + *pDst++ = ' '; + } + + *pDst++ = *pSrc++; + } + + nBufLength = pDst - pBuffer; +} + +void CDKIMBase::CompressSWSP(string& sBuffer) +{ + string::iterator iSrc = sBuffer.begin(); + string::iterator iDst = sBuffer.begin(); + string::iterator iEnd = sBuffer.end(); + + while (iSrc != iEnd) { + if (isswsp()(*iSrc)) { + + do { + ++iSrc; + } while (iSrc != iEnd && isswsp()(*iSrc)); + + if (iSrc == iEnd) + break; + + *iDst++ = ' '; + } + + *iDst++ = *iSrc++; + } + + sBuffer.erase(iDst, iEnd); +} + +////////////////////////////////////////////////////////////////////////////////////////// +// +// RelaxHeader - relax a header field (lower case the name, remove swsp before and after :) +// +// modified 4/21/06 STB to remove white space before colon +// +////////////////////////////////////////////////////////////////////////////////////////// + +string CDKIMBase::RelaxHeader(const string& sHeader) +{ + string sTemp = sHeader; + + CompressSWSP(sTemp); + + string::size_type cpos = sTemp.find(':'); + + if (cpos == string::npos) { + // no colon?! + } else { + // lower case the header field name + for (unsigned i = 0; i < cpos; i++) { + if (sTemp[i] >= 'A' && sTemp[i] <= 'Z') + sTemp[i] += 'a'-'A'; + } + + // remove the space after the : + if (cpos + 1 < sTemp.length() && sTemp[cpos+1] == ' ') + sTemp.erase(cpos + 1, 1); + + // remove the space before the : + if (cpos > 0 && sTemp[cpos - 1] == ' ') + sTemp.erase(cpos - 1,1); + } + + return sTemp; +} |