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

boundary-stack.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <syslog.h>
#include <ctype.h>

#include "logger.h"
#include "pldstr.h"
#include "boundary-stack.h"

#ifndef FL
#define FL __FILE__,__LINE__
#endif

#define BS_STRLEN_MAX 1024
#define BS_BOUNDARY_DETECT_LIMIT_DEFAULT 4
#define DBS if (glb.debug)

struct BS_globals {
      int debug;
      int verbose;
      int syslogging;
      int errlogging;
      int count;
      int detect_limit;
      int hold_limit;
      int smallest_length;
      int have_empty_boundary;
      struct BS_node *boundarystack;
      char boundarystacksafe[BS_STRLEN_MAX];
};

struct BS_node {
      char *boundary;
      int boundary_length;
      int boundary_nhl;  // length of boundary without hyphens
      struct BS_node *next;
};


static struct BS_globals glb;





/*-----------------------------------------------------------------\
 Function Name    : BS_init
 Returns Type     : int
      ----Parameter List
      1. void , 
      ------------------
 Exit Codes : 
 Side Effects     : 
--------------------------------------------------------------------
 Comments:
 
--------------------------------------------------------------------
 Changes:
 
\------------------------------------------------------------------*/
int BS_init( void )
{
      glb.debug = 0;
      glb.verbose = 0;
      glb.syslogging = 1;
      glb.errlogging = 0;
      glb.count = 0;
      glb.detect_limit = BS_BOUNDARY_DETECT_LIMIT_DEFAULT;
      glb.hold_limit = 0;
      glb.boundarystack = NULL;
      glb.smallest_length = -1;
      glb.have_empty_boundary = 0;

      return 0;
}

/*-----------------------------------------------------------------\
 Function Name    : BS_set_hold_limit
 Returns Type     : int
      ----Parameter List
      1. int limit , how many boundary strings to hold
      ------------------
 Exit Codes : 
 Side Effects     : 
--------------------------------------------------------------------
 Comments:
 
--------------------------------------------------------------------
 Changes:
 
\------------------------------------------------------------------*/
int BS_set_hold_limit( int limit )
{
      glb.hold_limit = limit;

      return 0;
}

/*-----------------------------------------------------------------\
 Function Name    : BS_set_verbose
 Returns Type     : int
      ----Parameter List
      1. int level , 
      ------------------
 Exit Codes : 
 Side Effects     : 
--------------------------------------------------------------------
 Comments:
 
--------------------------------------------------------------------
 Changes:
 
\------------------------------------------------------------------*/
int BS_set_verbose( int level )
{
      glb.verbose = level;

      return glb.verbose;
}

/*-----------------------------------------------------------------\
 Function Name    : BS_set_debug
 Returns Type     : int
      ----Parameter List
      1. int level , 
      ------------------
 Exit Codes : 
 Side Effects     : 
--------------------------------------------------------------------
 Comments:
 
--------------------------------------------------------------------
 Changes:
 
\------------------------------------------------------------------*/
int BS_set_debug( int level )
{
      glb.debug = level;

      return glb.debug;
}

/*-----------------------------------------------------------------\
 Function Name    : BS_set_boundary_detect_limit
 Returns Type     : int
      ----Parameter List
      1. int limit , 
      ------------------
 Exit Codes : 
 Side Effects     : 
--------------------------------------------------------------------
 Comments:
 
--------------------------------------------------------------------
 Changes:
 
\------------------------------------------------------------------*/
int BS_set_boundary_detect_limit( int limit )
{
      if ((limit > 0)&&(limit < BS_STRLEN_MAX))
      {
            glb.detect_limit = limit;
      }

      return glb.detect_limit;
}


/*-----------------------------------------------------------------\
 Function Name    : BS_clear
 Returns Type     : int
      ----Parameter List
      1. void , 
      ------------------
 Exit Codes : 
 Side Effects     : 
--------------------------------------------------------------------
 Comments:
 
--------------------------------------------------------------------
 Changes:
 
\------------------------------------------------------------------*/
int BS_clear( void )
{
      struct BS_node *next;

      while (glb.boundarystack)
      {
            DBS LOGGER_log("%s:%d:BS_clear:DEBUG: Popping off %p",FL,glb.boundarystack);
            next = glb.boundarystack->next;
            free(glb.boundarystack->boundary);
            free(glb.boundarystack);
            glb.boundarystack = next;
      }

      glb.boundarystack = NULL;
      glb.count = 0;
      glb.smallest_length = -1;

      return 0;
}



/*-----------------------------------------------------------------\
 Function Name    : BS_non_hyphen_length
 Returns Type     : int
      ----Parameter List
      1. char *boundary , 
      ------------------
 Exit Codes : 
 Side Effects     : 
--------------------------------------------------------------------
 Comments:
 
--------------------------------------------------------------------
 Changes:
 
\------------------------------------------------------------------*/
int BS_non_hyphen_length( char *boundary )
{
      int count = 0;
      char *p = boundary;

      while (*p) { if (isalnum((int)*p)) count++; p++; };

      return count;
}

/*-----------------------------------------------------------------\
 Function Name    : BS_push
 Returns Type     : int
      ----Parameter List
      1. char *boundary , 
      ------------------
 Exit Codes : 
 Side Effects     : 
--------------------------------------------------------------------
 Comments:
 
--------------------------------------------------------------------
 Changes:
 
\------------------------------------------------------------------*/
int BS_push( char *boundary )
{

      struct BS_node *node;

      if ((glb.hold_limit > 0)&&(glb.count >= glb.hold_limit)) 
      {
            DBS LOGGER_log("%s:%d:BS_push:DEBUG: Number of boundaries to hold is at limit (limit=%d)",FL,glb.hold_limit);
            return 0;
      }
  
      node  = malloc(sizeof(struct BS_node));

      DBS LOGGER_log("%s:%d:BS_push:DEBUG: head = %p, nn = %p boundary = '%s'",FL, glb.boundarystack, node, boundary);

      if (node)
      {
            node->next = glb.boundarystack;
            glb.boundarystack = node;
            glb.boundarystack->boundary = strdup(boundary);
            glb.boundarystack->boundary_length = strlen(glb.boundarystack->boundary);
            if (glb.boundarystack->boundary_length == 0) glb.have_empty_boundary = 1;
            glb.boundarystack->boundary_nhl = BS_non_hyphen_length(boundary);
            glb.count++;

            // Set the smallest length
            if (glb.smallest_length == -1) glb.smallest_length = glb.boundarystack->boundary_length;
            else if (glb.boundarystack->boundary_length < glb.smallest_length) glb.smallest_length = glb.boundarystack->boundary_length;

            DBS LOGGER_log("%s:%d:DEBUGX: smallest = %d, NHL = %d,  boundary = '%s'",FL,glb.smallest_length, node->boundary_nhl, boundary);
      }
      else
          {
            LOGGER_log("%s:%d:BS_push:ERROR: Cannot allocate memory for boundary stack PUSH, %s", FL, strerror(errno));
      }

      return 0;
}


/*-----------------------------------------------------------------\
 Function Name    : *BS_pop
 Returns Type     : char
      ----Parameter List
      1. void , 
      ------------------
 Exit Codes : 
 Side Effects     : 
--------------------------------------------------------------------
 Comments:
 
--------------------------------------------------------------------
 Changes:
 
\------------------------------------------------------------------*/
char *BS_pop( void )
{

      struct BS_node *node = glb.boundarystack;

      if (glb.boundarystack)
      {
            glb.boundarystack = glb.boundarystack->next;
            PLD_strncpy(glb.boundarystacksafe,node->boundary, BS_STRLEN_MAX);
            free(node->boundary);
            free(node);
            glb.count--;
      }

      return glb.boundarystacksafe;
}

/*-----------------------------------------------------------------\
 Function Name    : *BS_top
 Returns Type     : char
      ----Parameter List
      1. void , 
      ------------------
 Exit Codes : 
 Side Effects     : 
--------------------------------------------------------------------
 Comments:
 
--------------------------------------------------------------------
 Changes:
 
\------------------------------------------------------------------*/
char *BS_top( void )
{

      if (glb.boundarystack)
      {
            return glb.boundarystack->boundary;
      }
      else return NULL;
}

/*-----------------------------------------------------------------\
 Function Name    : BS_count
 Returns Type     : int
      ----Parameter List
      1. void , 
      ------------------
 Exit Codes : 
 Side Effects     : 
--------------------------------------------------------------------
 Comments:
 
--------------------------------------------------------------------
 Changes:
 
\------------------------------------------------------------------*/
int BS_count( void )
{
      return glb.count;
}


/*-----------------------------------------------------------------\
 Function Name    : BS_is_long_enough
 Returns Type     : int
      ----Parameter List
      1. int blen , 
      ------------------
 Exit Codes : 
 Side Effects     : 
--------------------------------------------------------------------
 Comments:
 
--------------------------------------------------------------------
 Changes:
 
\------------------------------------------------------------------*/
int BS_is_long_enough( int blen )
{
      if (glb.smallest_length == -1) return 0;
      if (blen >= glb.smallest_length) return 1;

      return 0;
}

/*-----------------------------------------------------------------\
 Function Name    : BS_boundary_detect
 Returns Type     : int
      ----Parameter List
      1. char *needle, 
      2.  char *haystack , 
      ------------------
 Exit Codes : 
 Side Effects     : 
--------------------------------------------------------------------
 Comments:
 
--------------------------------------------------------------------
 Changes:
 
\------------------------------------------------------------------*/
int BS_boundary_detect( char *haystack, char *needle, int needle_length )
{
      int result=1;
      int current_start = glb.detect_limit;
      char *haystack_start;

      if ((glb.have_empty_boundary == 1)&&(needle_length < 1))
      {
            result = strncmp(haystack,"--",2);
            DBS LOGGER_log("%s:%d:BS_boundary_detect:DEBUG: empty-boundary test, result = %d",FL, result);
            return result;

      }

      if ((needle_length < 1)&&(glb.have_empty_boundary == 0)) return 1;


      DBS LOGGER_log("%s:%d:BS_boundary_detect: needle='%s', length=%d, haystack='%s', shift-window=%d"
                  ,FL
                  ,needle
                  ,needle_length
                  ,haystack
                  ,current_start
                  );

      haystack_start = haystack;
      while ((current_start-- > 0)&&(*haystack_start != '\0'))
      {
            DBS LOGGER_log("%s:%d:BS_boundary_detect:DEBUG: CMP '%s' to '%s'",FL, needle, haystack_start);
            if (strncmp( needle, haystack_start, needle_length )==0)
            {
                  DBS LOGGER_log("%s:%d:BS_boundary_detect:DEBUG: Hit on compare",FL);
                  result = 0;  
                  break; 
            }
            haystack_start++;
      }

      return result;
}



/*-----------------------------------------------------------------\
 Function Name    : BS_cmp
 Returns Type     : int
      ----Parameter List
      1. char *boundary, the boundary we want to check to see if is in
                                                the stack
      2.  int len , the length of the boundary
      ------------------
 Exit Codes : 1 == boundary found, 0 == no boundary found
 Side Effects     : 
--------------------------------------------------------------------
 Comments:
 
--------------------------------------------------------------------
 Changes:
 
\------------------------------------------------------------------*/
int BS_cmp( char *boundary, int len )
{

      char testspace[128]; // was 1024
      int testspacelen=127; // was 1023
      int spin=1;
      int nhl=0;
      struct BS_node *node=glb.boundarystack;
      struct BS_node *nodetmp=NULL, *nodedel=NULL;

      if ((!boundary)||(glb.count == 0)) return 0;
      //if ((glb.smallest_length > 0)&&(len < glb.smallest_length)) return 0;
      if (BS_is_long_enough(len) == 0) return 0;

      nhl = BS_non_hyphen_length(boundary);

      DBS LOGGER_log("%s:%d:BS_cmp:DEBUG: possible-boundary='%s', len=%d, smallest=%d, count=%d, NHL=%d"
                  , FL
                  , boundary
                  , len
                  , glb.smallest_length
                  , glb.count
                  , nhl
                  );


      // Crop the incoming string to fit in our testspace length
      if (len > testspacelen) len = testspacelen;

      // Copy the potential boundary into our testspace
      snprintf(testspace, testspacelen, "%s", boundary);

      // First, search through the stack looking for a boundary that matches
      // our search criterion
      //
      // When we do find one, we will jump out of this WHILE loop by setting
      // 'spin' to 0.

      while((node)&&(spin))
      {
//          if (node->boundary_length <= len)
            if (node->boundary_nhl == nhl)
            {     
                  DBS LOGGER_log("%s:%d:BS_cmp:DEBUG: Comparing '%s' to '%s'", FL, boundary, node->boundary);
                  // * 20040903-08H57:PLD: Set boundary length comparison from > 0 to >= 0
                  if ((node->boundary != NULL)&&(node->boundary_length >= 0))
                  {
                        if ((BS_boundary_detect(testspace, node->boundary, node->boundary_length))==0)
                        {
                              DBS LOGGER_log("%s:%d:BS_cmp:DEBUG: Boundary HIT",FL);
                              spin = 0;
                        }
                  }
            }

            if (spin != 0) node = node->next;
      }

      // If we have a hit on the matching, then, according
      // to nested MIME rules, we must "remove" any previous
      // boundaries
      //
      // We know that we had a HIT in matching if spin == 0, because
      // in our previous code block that's what we set spin to if
      if(spin==0)
      {

            DBS LOGGER_log("%s:%d:BS_cmp:DEBUG: Boundary hit on '%s' == '%s'",FL, boundary,node->boundary);

            // If our "HIT" node is /NOT/ the one on the top of the
            // stack, then we need to pop off and deallocate the nodes
            // PRIOR/Above the hit node.
            //
            // ie, if "NODE" is not the top, then pop off until we
            // do get to the node

            if (node != glb.boundarystack)
            {
                  nodetmp = glb.boundarystack;
                  while ((nodetmp)&&(nodetmp != node))
                  {
                        // - Set the node to delete (nodedel) to the current temp
                        // node (notetmp)
                        // - Increment the nodetmp to the next node in the stack
                        // - Free the node to delete (nodedel)

                        nodedel = nodetmp;
                        nodetmp = nodetmp->next;
                        free(nodedel->boundary);
                        free(nodedel);
                  }
                  glb.boundarystack = node;
            }
            return 1;

      }
      else
      {
            return 0;
      }

      return 0;
}




Generated by  Doxygen 1.6.0   Back to index