Back to index

opendkim  2.6.2
Defines | Typedefs | Functions | Variables
dkim-mailparse.c File Reference
#include <sys/types.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>
#include <stdio.h>
#include "dkim-mailparse.h"

Go to the source code of this file.

Defines

#define DKIM_MAILPARSE_OK   0 /* success */
#define DKIM_MAILPARSE_ERR_PUNBALANCED   1 /* unbalanced parentheses */
#define DKIM_MAILPARSE_ERR_QUNBALANCED   2 /* unbalanced quotes */
#define DKIM_MAILPARSE_ERR_SUNBALANCED   3 /* unbalanced sq. brackets */
#define CMAP_NBITS   (sizeof(cmap_elem_type) * CHAR_BIT)
#define CMAP_NELEMS   ((1 + UCHAR_MAX) / CMAP_NBITS)
#define CMAP_INDEX(i)   ((unsigned char)(i) / CMAP_NBITS)
#define CMAP_BIT(i)   (1L << (unsigned char)(i) % CMAP_NBITS)
#define CMAP_TST(ar, c)   ((ar)[CMAP_INDEX(c)] & CMAP_BIT(c))
#define CMAP_SET(ar, c)   ((ar)[CMAP_INDEX(c)] |= CMAP_BIT(c))

Typedefs

typedef unsigned long cmap_elem_type

Functions

static u_char * dkim_mail_matching_paren (u_char *s, u_char *e, int open_paren, int close_paren)
static int dkim_mail_first_special (u_char *p, u_char *e, u_char **special_out)
static int dkim_mail_token (u_char *s, u_char *e, int *type_out, u_char **start_out, u_char **end_out, int *uncommented_whitespace)
int dkim_mail_parse (unsigned char *line, unsigned char **user_out, unsigned char **domain_out)

Variables

static char dkim_mailparse_c_id [] = "@(#)$Id: dkim-mailparse.c,v 1.5.34.1 2010/10/27 21:43:08 cm-msk Exp $"
static unsigned char const SPECIALS [] = "<>@,;:\\\"/[]?="

Define Documentation

#define CMAP_BIT (   i)    (1L << (unsigned char)(i) % CMAP_NBITS)

Definition at line 35 of file dkim-mailparse.c.

#define CMAP_INDEX (   i)    ((unsigned char)(i) / CMAP_NBITS)

Definition at line 34 of file dkim-mailparse.c.

#define CMAP_NBITS   (sizeof(cmap_elem_type) * CHAR_BIT)

Definition at line 32 of file dkim-mailparse.c.

#define CMAP_NELEMS   ((1 + UCHAR_MAX) / CMAP_NBITS)

Definition at line 33 of file dkim-mailparse.c.

#define CMAP_SET (   ar,
 
)    ((ar)[CMAP_INDEX(c)] |= CMAP_BIT(c))

Definition at line 37 of file dkim-mailparse.c.

#define CMAP_TST (   ar,
 
)    ((ar)[CMAP_INDEX(c)] & CMAP_BIT(c))

Definition at line 36 of file dkim-mailparse.c.

#define DKIM_MAILPARSE_ERR_PUNBALANCED   1 /* unbalanced parentheses */

Definition at line 27 of file dkim-mailparse.c.

#define DKIM_MAILPARSE_ERR_QUNBALANCED   2 /* unbalanced quotes */

Definition at line 28 of file dkim-mailparse.c.

#define DKIM_MAILPARSE_ERR_SUNBALANCED   3 /* unbalanced sq. brackets */

Definition at line 29 of file dkim-mailparse.c.

#define DKIM_MAILPARSE_OK   0 /* success */

Definition at line 26 of file dkim-mailparse.c.


Typedef Documentation

typedef unsigned long cmap_elem_type

Definition at line 23 of file dkim-mailparse.c.


Function Documentation

static int dkim_mail_first_special ( u_char *  p,
u_char *  e,
u_char **  special_out 
) [static]

Definition at line 154 of file dkim-mailparse.c.

{
       size_t        i;
       cmap_elem_type       is_special[CMAP_NELEMS] = { 0 };
       u_char        *at_ptr = NULL;

       /* set up special finder */
       for (i = 0; SPECIALS[i] != '\0'; i++)
              CMAP_SET(is_special, SPECIALS[i]);

       for (; p < e && *p != '\0'; p++)
       {
              /* skip white space between tokens */
              while (p < e && (*p == '(' ||
                               (isascii(*p) && isspace(*p))))
              {
                     if (*p != '(')
                     {
                            p++;
                     }
                     else
                     {
                            p = dkim_mail_matching_paren(p + 1, e,
                                                         '(', ')');
                            if (*p == '\0')
                                   return DKIM_MAILPARSE_ERR_PUNBALANCED;
                            else
                                   p++;
                     }
              }

              if (*p == '\0')
                     break;

              if (*p == '"')
              {
                     p = dkim_mail_matching_paren(p + 1, e, '\0', '"');
                     if (*p == '\0')
                            return DKIM_MAILPARSE_ERR_QUNBALANCED;
              }
              else if (*p == '[')
              {
                     p = dkim_mail_matching_paren(p + 1, e, '\0', ']');
                     if (*p == '\0')
                            return DKIM_MAILPARSE_ERR_SUNBALANCED;
              }
              else if (CMAP_TST(is_special, *p))
              {
                     if (*p == '<')
                     {
                            *special_out = p;
                            return 0;
                     }
                     else if (*p == ':' || *p == ';' || *p == ',')
                     {
                            if (at_ptr != NULL)
                                   *special_out = at_ptr;
                            else
                                   *special_out = p;
                            return 0; 
                     }
                     else if (*p == '@')
                     {
                            at_ptr = p;
                     }
              }
              else
              {
                     while (*p != '\0' &&
                            !CMAP_TST(is_special, *p) &&
                            (!isascii(*p) ||
                             !isspace((unsigned char) *p)) &&
                            *p != '(')
                            p++;
                     p--;
              }
       }

       *special_out = p;
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static u_char* dkim_mail_matching_paren ( u_char *  s,
u_char *  e,
int  open_paren,
int  close_paren 
) [static]

Definition at line 116 of file dkim-mailparse.c.

{
       int           paren = 1;

       for (; s < e; s++)
       {
              if (*s == close_paren)
              {
                     if (--paren == 0)
                            break;
              }
              else if (*s == open_paren)
              {
                     paren++;
              }
              else if (*s == '\\')
              {
                     if (s[1] != '\0')
                            s++;
              }
       }

       return s;
}

Here is the caller graph for this function:

int dkim_mail_parse ( unsigned char *  line,
unsigned char **  user_out,
unsigned char **  domain_out 
)

Definition at line 360 of file dkim-mailparse.c.

{
       int type;
       int ws;
       int err;
       u_char *e, *special;
       u_char *tok_s, *tok_e;
       u_char *w;

       *user_out = NULL;
       *domain_out = NULL;

       err = 0;
       w = line;
       e = line + strlen((char *) line);
       ws = 0;

       for (;;)
       {
              err = dkim_mail_first_special(line, e, &special);
              if (err != 0)
                     return err;
              
              /* given the construct we're looking at, do the right thing */
              switch (*special)
              {
                case '<':
                     /* display name <address> */
                     line = special + 1;
                     for (;;)
                     {
                            err = dkim_mail_token(line, e, &type, &tok_s,
                                                  &tok_e, &ws);
                            if (err != 0)
                                   return err;

                            if (type == '>' || type == '\0')
                            {
                                   *w = '\0';
                                   return 0;
                            }
                            else if (type == '@')
                            {
                                   *w++ = '\0';
                                   *domain_out = w;
                            }
                            else if (type == ',' || type == ':')
                            {
                                   /* source route punctuation */
                                   *user_out = NULL;
                                   *domain_out = NULL;
                            }
                            else
                            {
                                   if (*user_out == NULL)
                                          *user_out = w;
                                   memmove(w, tok_s, tok_e - tok_s);
                                   w += tok_e - tok_s;
                            }
                            line = tok_e;
                     }

                case ';':
                case ':':
                case ',':
                     /* skip a group name or result */
                     line = special + 1;
                     break;

                default:
                     /* (display name) addr(display name)ess */
                     ws = 0;
                     for (;;)
                     {
                            err = dkim_mail_token(line, e, &type, &tok_s,
                                                  &tok_e, &ws);
                            if (err != 0)
                                   return err;

                            if (type == '\0' ||  type == ',' || type == ';')
                            {
                                   *w = '\0';
                                   break;
                            }
                            else if (type == '@')
                            {
                                   *w++ = '\0';
                                   *domain_out = w;
                                   ws = 0;
                            }
                            else
                            {

                                   if (*user_out == NULL)
                                          *user_out = w;
                                   else if (type == 'x' && ws == 1)
                                          *w++ = ' ';

                                   memmove(w, tok_s, tok_e - tok_s);
                                   w += tok_e - tok_s;

                                   ws = 0;
                            }

                            line = tok_e;
                     }
                     return 0;
              }
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int dkim_mail_token ( u_char *  s,
u_char *  e,
int *  type_out,
u_char **  start_out,
u_char **  end_out,
int *  uncommented_whitespace 
) [static]

Definition at line 253 of file dkim-mailparse.c.

{
       u_char *p;
       int err = 0;
       size_t i;
       int token_type;
       cmap_elem_type is_special[CMAP_NELEMS] = { 0 };
       u_char *token_start, *token_end;

       *start_out = NULL;
       *end_out   = NULL;
       *type_out  = 0;

       err = 0;

       /* set up special finder */
       for (i = 0; SPECIALS[i] != '\0'; i++)
              CMAP_SET(is_special, SPECIALS[i]);

       p = s;

       /* skip white space between tokens */
       while (p < e && (*p == '(' ||
                        (isascii((unsigned char) *p) &&
                         isspace((unsigned char) *p))))
       {
              if (*p != '(')
              {
                     *uncommented_whitespace = 1;
                     p++;
              }
              else
              {
                     p = dkim_mail_matching_paren(p + 1, e, '(', ')');
                     if (*p == '\0')
                            return DKIM_MAILPARSE_ERR_PUNBALANCED;
                     else
                            p++;
              }
       }

       if (p >= e || *p == '\0')
              return 0;

       /* our new token starts here */
       token_start = p;

       /* fill in the token contents and type */
       if (*p == '"')
       {
              token_end = dkim_mail_matching_paren(p + 1, e, '\0', '"');
              token_type = '"';
              if (*token_end != '\0')
                     token_end++;
              else
                     err = DKIM_MAILPARSE_ERR_QUNBALANCED;
       }
       else if (*p == '[')
       {
              token_end = p = dkim_mail_matching_paren(p + 1, e, '\0', ']');
              token_type = '[';
              if (*token_end != '\0')
                     token_end++;
              else
                     err = DKIM_MAILPARSE_ERR_SUNBALANCED;
       }
       else if (CMAP_TST(is_special, *p))
       {
              token_end  = p + 1;
              token_type = *p;
       }
       else
       {
              while (p < e && *p != '\0' && !CMAP_TST(is_special, *p) &&
                     (!isascii(*p) || !isspace((unsigned char) *p)) &&
                     *p != '(')
                     p++;

              token_end = p;
              token_type = 'x';
       }

       *start_out = token_start;
       *end_out   = token_end;
       *type_out  = token_type;

       return err;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

char dkim_mailparse_c_id[] = "@(#)$Id: dkim-mailparse.c,v 1.5.34.1 2010/10/27 21:43:08 cm-msk Exp $" [static]

Definition at line 9 of file dkim-mailparse.c.

unsigned char const SPECIALS[] = "<>@,;:\\\"/[]?=" [static]

Definition at line 39 of file dkim-mailparse.c.