summaryrefslogtreecommitdiff
path: root/src/dkimbase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/dkimbase.cpp')
-rw-r--r--src/dkimbase.cpp320
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;
+}