Logo Search packages:      
Sourcecode: libdkim version File versions  Download package

dkimbase.cpp

/*****************************************************************************
*  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.
*
*****************************************************************************/

#ifdef WIN32
#include <windows.h>
#pragma warning( disable: 4786 )
#else
#endif

#include <string.h>

#include "dkim.h"
#include "dkimbase.h"

#include <algorithm>


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()
{
      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( char* szBuffer, int nBufLength, bool bEOF )
{
      char* p = szBuffer;
      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 ) );
                              }
                              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();
            ProcessBody("", 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);

      unsigned cpos = sTemp.find(':');

      if (cpos == -1)
      {
            // 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;
}


Generated by  Doxygen 1.6.0   Back to index