Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Enumerations | Functions | Variables
sspm.c File Reference
#include <stdio.h>
#include <string.h>
#include "sspm.h"
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>

Go to the source code of this file.

Classes

struct  mime_impl
struct  major_content_type_map
struct  minor_content_type_map
struct  encoding_map
struct  sspm_buffer

Defines

#define TMP_BUF_SIZE   1024
#define BUF_SIZE   1024
#define MAX_HEADER_LINES   25

Enumerations

enum  mime_state {
  UNKNOWN_STATE, IN_HEADER, END_OF_HEADER, IN_BODY,
  OPENING_PART, END_OF_PART, TERMINAL_END_OF_PART, END_OF_INPUT
}
enum  line_type {
  EMPTY, BLANK, MIME_HEADER, MAIL_HEADER,
  HEADER_CONTINUATION, BOUNDARY, TERMINATING_BOUNDARY, UNKNOWN_TYPE
}

Functions

void sspm_free_header (struct sspm_header *header)
voidsspm_make_multipart_part (struct mime_impl *impl, struct sspm_header *header)
void sspm_read_header (struct mime_impl *impl, struct sspm_header *header)
char * sspm_strdup (char *str)
char * sspm_get_parameter (char *line, char *parameter)
char * sspm_property_name (char *line)
char * sspm_value (char *line)
voidsspm_default_new_part ()
void sspm_default_add_line (void *part, struct sspm_header *header, char *line, size_t size)
voidsspm_default_end_part (void *part)
void sspm_default_free_part (void *part)
int sspm_is_mime_header (char *line)
int sspm_is_mail_header (char *line)
int sspm_is_blank (char *line)
int sspm_is_continuation_line (char *line)
int sspm_is_mime_boundary (char *line)
int sspm_is_mime_terminating_boundary (char *line)
static enum line_type get_line_type (char *line)
static struct sspm_action_map get_action (struct mime_impl *impl, enum sspm_major_type major, enum sspm_minor_type minor)
char * sspm_lowercase (char *str)
enum sspm_major_type sspm_find_major_content_type (char *type)
enum sspm_minor_type sspm_find_minor_content_type (char *type)
char * sspm_major_type_string (enum sspm_major_type type)
char * sspm_minor_type_string (enum sspm_minor_type type)
char * sspm_encoding_string (enum sspm_encoding type)
void sspm_build_header (struct sspm_header *header, char *line)
char * sspm_get_next_line (struct mime_impl *impl)
void sspm_store_part (struct mime_impl *impl, struct sspm_header header, int level, void *part, size_t size)
void sspm_set_error (struct sspm_header *header, enum sspm_error error, char *message)
voidsspm_make_part (struct mime_impl *impl, struct sspm_header *header, struct sspm_header *parent_header, void **end_part, size_t *size)
voidsspm_make_multipart_subpart (struct mime_impl *impl, struct sspm_header *parent_header)
int sspm_parse_mime (struct sspm_part *parts, size_t max_parts, struct sspm_action_map *actions, char *(*get_string)(char *s, size_t size, void *data), void *get_string_data, struct sspm_header *first_header)
void sspm_free_parts (struct sspm_part *parts, size_t max_parts)
char * decode_quoted_printable (char *dest, char *src, size_t *size)
char * decode_base64 (char *dest, char *src, size_t *size)
void sspm_append_string (struct sspm_buffer *buf, char *string)
void sspm_write_part (struct sspm_buffer *buf, struct sspm_part *part, int *part_num)
void sspm_append_hex (struct sspm_buffer *buf, char ch)
void sspm_append_char (struct sspm_buffer *buf, char ch)
static int sspm_is_printable (char c)
void sspm_encode_quoted_printable (struct sspm_buffer *buf, char *data)
void sspm_write_base64 (struct sspm_buffer *buf, char *inbuf, int size)
void sspm_encode_base64 (struct sspm_buffer *buf, char *data, size_t size)
void sspm_write_header (struct sspm_buffer *buf, struct sspm_header *header)
void sspm_write_multipart_part (struct sspm_buffer *buf, struct sspm_part *parts, int *part_num)
int sspm_write_mime (struct sspm_part *parts, size_t num_parts, char **output_string, char *header)

Variables

static struct
major_content_type_map 
major_content_type_map []
static struct
minor_content_type_map 
minor_content_type_map []
struct encoding_map sspm_encoding_map []
static char * mime_headers []
static char BaseTable [64]

Class Documentation

struct major_content_type_map

Definition at line 93 of file sspm.c.

struct minor_content_type_map

Definition at line 112 of file sspm.c.

struct encoding_map

Definition at line 133 of file sspm.c.

struct sspm_buffer

Definition at line 1241 of file sspm.c.

Collaboration diagram for sspm_buffer:
Class Members
size_t buf_size
char * buffer
int line_pos
char * pos

Define Documentation

#define BUF_SIZE   1024
#define TMP_BUF_SIZE   1024

Definition at line 53 of file sspm.c.


Enumeration Type Documentation

enum line_type
Enumerator:
EMPTY 
BLANK 
MIME_HEADER 
MAIL_HEADER 
HEADER_CONTINUATION 
BOUNDARY 
TERMINATING_BOUNDARY 
UNKNOWN_TYPE 

Definition at line 354 of file sspm.c.

enum mime_state
Enumerator:
UNKNOWN_STATE 
IN_HEADER 
END_OF_HEADER 
IN_BODY 
OPENING_PART 
END_OF_PART 
TERMINAL_END_OF_PART 
END_OF_INPUT 

Definition at line 56 of file sspm.c.


Function Documentation

char* decode_base64 ( char *  dest,
char *  src,
size_t *  size 
)

Definition at line 1170 of file sspm.c.

{
    int cc = 0;
    char buf[4] = {0,0,0,0};  
    int p = 0;
    int valid_data = 0;
    size_t size_out=0;
    
    while (*src && p<(int)*size && (cc!=  -1)) {
       
       /* convert a character into the Base64 alphabet */
       cc = *src++;
       
       if     ((cc >= 'A') && (cc <= 'Z')) cc = cc - 'A';
       else if ((cc >= 'a') && (cc <= 'z')) cc = cc - 'a' + 26;
       else if ((cc >= '0') && (cc <= '9')) cc = cc - '0' + 52;
       else if  (cc == '/')             cc = 63;
       else if  (cc == '+')             cc = 62;
       else                                 cc = -1;
       
       assert(cc<64);

       /* If we've reached the end, fill the remaining slots in
          the bucket and do a final conversion */
       if(cc== -1){
           if(valid_data == 0){
              return 0;
           }

           while(p%4!=3){
              p++;
              buf[p%4] = 0;
           }
       } else {
           buf[p%4] = cc;
           size_out++;
           valid_data = 1;
       }

       
       /* When we have 4 base64 letters, convert them into three
          bytes */
       if (p%4 == 3) {
           *dest++ =(buf[0]<< 2)|((buf[1] & 0x30) >> 4);
           *dest++ =((buf[1] & 0x0F) << 4)|((buf[2] & 0x3C) >> 2);
           *dest++ =((buf[2] & 0x03) << 6)|(buf[3] & 0x3F);

           memset(buf,0,4);
       }

       p++;

    }
    /* Calculate the size of the converted data*/
   *size = ((int)(size_out/4))*3;
    if(size_out%4 == 2) *size+=1;
    if(size_out%4 == 3) *size+=2;

    return(dest);
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* decode_quoted_printable ( char *  dest,
char *  src,
size_t *  size 
)

Definition at line 1121 of file sspm.c.

{
    int cc;
    size_t i=0;

    while (*src != 0 && i < *size) {
       if (*src == '=') {

           src++; 
           if (!*src) {
              break;
           }

           /* remove soft line breaks*/
           if ((*src == '\n') || (*src == '\r')){
              src++;
              if ((*src == '\n') || (*src == '\r')){
                  src++;
              }
              continue;
           }

           cc  = isdigit(*src) ? (*src - '0') : (*src - 55);
           cc *= 0x10;
           src++; 
           if (!*src) {
              break;
           }
           cc += isdigit(*src) ? (*src - '0') : (*src - 55);

           *dest = cc;

       } else {
           *dest = *src;
       }
       
       dest++;
       src++;
       i++;
    }
    
    *dest = '\0';
    
    *size = i;
    return(dest);
}

Here is the caller graph for this function:

static struct sspm_action_map get_action ( struct mime_impl impl,
enum sspm_major_type  major,
enum sspm_minor_type  minor 
) [static, read]

Definition at line 390 of file sspm.c.

{
    int i;

    /* Read caller suppled action map */

    if (impl->actions != 0){
       for(i=0; impl->actions[i].major != SSPM_UNKNOWN_MAJOR_TYPE; i++){
           if((major == impl->actions[i].major &&
              minor == impl->actions[i].minor) ||
              (major == impl->actions[i].major &&
              minor == SSPM_ANY_MINOR_TYPE)){
              return impl->actions[i];
           }
       }
    }

    /* Else, read default action map */

    for(i=0; sspm_action_map[i].major != SSPM_UNKNOWN_MAJOR_TYPE; i++){
           if((major == sspm_action_map[i].major &&
              minor == sspm_action_map[i].minor) ||
              (major == sspm_action_map[i].major &&
              minor == SSPM_ANY_MINOR_TYPE)){
           break;
       }
    }
    
    return sspm_action_map[i];
}

Here is the caller graph for this function:

static enum line_type get_line_type ( char *  line) [static]

Definition at line 366 of file sspm.c.

                                               {

    if (line == 0){
       return EMPTY;
    } else if(sspm_is_blank(line)){
       return BLANK;
    } else if (sspm_is_mime_header(line)){
       return MIME_HEADER;
    } else if (sspm_is_mail_header(line)){
       return MAIL_HEADER;
    } else if (sspm_is_continuation_line(line)){
       return HEADER_CONTINUATION;
    } else if (sspm_is_mime_terminating_boundary(line)){
       return TERMINATING_BOUNDARY;
    } else if (sspm_is_mime_boundary(line)) {
       return BOUNDARY;
    } else {
       return UNKNOWN_TYPE;
    }


}

Here is the call graph for this function:

Here is the caller graph for this function:

void sspm_append_char ( struct sspm_buffer buf,
char  ch 
)

Definition at line 1261 of file sspm.c.

{
    char *new_buf;
    char *new_pos;

    size_t data_length, final_length;

    data_length = (size_t)buf->pos - (size_t)buf->buffer;

    final_length = data_length + 2; 

    if ( final_length > (size_t) buf->buf_size ) {
       
       buf->buf_size  = (buf->buf_size) * 2  + final_length +1;

       new_buf = realloc(buf->buffer,buf->buf_size);

       new_pos = (void*)((size_t)new_buf + data_length);
       
       buf->pos = new_pos;
       buf->buffer = new_buf;
    }

    *(buf->pos) = ch;
    buf->pos += 1;
    *(buf->pos) = 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void sspm_append_hex ( struct sspm_buffer buf,
char  ch 
)

Definition at line 1251 of file sspm.c.

{
    char tmp[4];

    snprintf(tmp,sizeof(tmp),"=%02X",ch);

    sspm_append_string(buf,tmp);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void sspm_append_string ( struct sspm_buffer buf,
char *  string 
)

Definition at line 1289 of file sspm.c.

{
    char *new_buf;
    char *new_pos;

    size_t data_length, final_length, string_length;

    string_length = strlen(string);
    data_length = (size_t)buf->pos - (size_t)buf->buffer;    
    final_length = data_length + string_length; 

    if ( final_length >= (size_t) buf->buf_size) {

       
       buf->buf_size  = (buf->buf_size) * 2  + final_length;

       new_buf = realloc(buf->buffer,buf->buf_size);

       new_pos = (void*)((size_t)new_buf + data_length);
       
       buf->pos = new_pos;
       buf->buffer = new_buf;
    }
    
    strcpy(buf->pos, string);

    buf->pos += string_length;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void sspm_build_header ( struct sspm_header header,
char *  line 
)

Definition at line 528 of file sspm.c.

{
    char *prop;
    char *val;
    
    val = sspm_strdup(sspm_value(line));
    prop = sspm_strdup(sspm_property_name(line));

    if(strcmp(prop,"Content-Type") == 0){
       
       /* Create a new mime_header, fill in content-type
          and possibly boundary */
       
       char* boundary= sspm_get_parameter(line,"boundary");
       
       header->def = 0;
       header->major = sspm_find_major_content_type(val);
       header->minor = sspm_find_minor_content_type(val);
       
       if(header->minor == SSPM_UNKNOWN_MINOR_TYPE){
           char *p = strchr(val,'/');
           
           if (p != 0){
              p++; /* Skip the '/' */
              
              header->minor_text = sspm_strdup(p);
           } else {
              /* Error, malformed content type */
              header->minor_text = sspm_strdup("unknown");
           }
       }
       if (boundary != 0){
           header->boundary = sspm_strdup(boundary);
       }
       
    } else if(strcmp(prop,"Content-Transfer-Encoding")==0){
       char* encoding = sspm_value(line);
       char* lencoding = sspm_lowercase(encoding);

       if(strcmp(lencoding,"base64")==0){
           header->encoding = SSPM_BASE64_ENCODING;
       } else        if(strcmp(lencoding,"quoted-printable")==0){
           header->encoding = SSPM_QUOTED_PRINTABLE_ENCODING;
       } else        if(strcmp(lencoding,"binary")==0){
           header->encoding = SSPM_BINARY_ENCODING;
       } else        if(strcmp(lencoding,"7bit")==0){
           header->encoding = SSPM_7BIT_ENCODING;
       } else        if(strcmp(lencoding,"8bit")==0){
           header->encoding = SSPM_8BIT_ENCODING;
       } else {
           header->encoding = SSPM_UNKNOWN_ENCODING;
       }


       free(lencoding);

       header->def = 0;
       
    } else if(strcmp(prop,"Content-Id")==0){
       char* cid = sspm_value(line);
       header->content_id = sspm_strdup(cid);
       header->def = 0;
       
    }
    free(val);
    free(prop);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void sspm_default_add_line ( void part,
struct sspm_header header,
char *  line,
size_t  size 
)

Definition at line 255 of file sspm.c.

{
}

Definition at line 260 of file sspm.c.

{
    return 0;
}

Definition at line 265 of file sspm.c.

{
}

Definition at line 251 of file sspm.c.

{
    return 0;
}
void sspm_encode_base64 ( struct sspm_buffer buf,
char *  data,
size_t  size 
)

Definition at line 1417 of file sspm.c.

{

    char *p;
    char inbuf[3];
    int i = 0;
    int first = 1;
    int lpos = 0;

    inbuf[0] = inbuf[1] = inbuf[2]  = 0;

    for (p = data; *p !=0; p++){
                         
       if (i%3 == 0 && first == 0){

           sspm_write_base64(buf, inbuf, 4);
           lpos+=4;

           inbuf[0] = inbuf[1] = inbuf[2] = 0;
       }

       assert(lpos%4 == 0);

       if (lpos == 72){
           sspm_append_string(buf,"\n");
           lpos = 0;
       }

       inbuf[i%3] = *p;

       i++;
       first = 0;

    }

    
    /* If the inbuf was not exactly filled on the last byte, we need
       to spit out the odd bytes that did get in -- either one or
       two. This will result in an output of two bytes and '==' or
       three bytes and '=', respectively */
    
    if (i%3 == 1 && first == 0){
           sspm_write_base64(buf, inbuf, 2);
    } else if (i%3 == 2 && first == 0){
           sspm_write_base64(buf, inbuf, 3);
    }

}

Here is the call graph for this function:

Here is the caller graph for this function:

void sspm_encode_quoted_printable ( struct sspm_buffer buf,
char *  data 
)

Definition at line 1327 of file sspm.c.

{
    char *p;
    int lpos = 0;

    for(p = data; *p != 0; p++){

       if(sspm_is_printable(*p)){
           /* plain characters can represent themselves */
           /* RFC2045 Rule #2 */
              sspm_append_char(buf,*p);
              lpos++;
       } else if ( *p == '\t' || *p == ' ' ) {

           /* For tabs and spaces, only encode if they appear at the
               end of the line */
           /* RFC2045 Rule #3 */

          char n = *(p+1);

          if( n == '\n' || n == '\r'){
              sspm_append_hex(buf,*p);
              lpos += 3;
          } else {
              sspm_append_char(buf,*p);
              lpos++;
          }

       } else if( *p == '\n' || *p == '\r'){
           sspm_append_char(buf,*p);

           lpos=0;

       } else {
           /* All others need to be encoded */
           sspm_append_hex(buf,*p);
           lpos+=3;
       }


       /* Add line breaks */
       if (lpos > 72){
           lpos = 0;
           sspm_append_string(buf,"=\n");
       }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* sspm_encoding_string ( enum sspm_encoding  type)

Definition at line 513 of file sspm.c.

{
    int i;
    for (i=0; sspm_encoding_map[i].encoding !=  SSPM_UNKNOWN_ENCODING; 
        i++){
       if(type == sspm_encoding_map[i].encoding){
           return sspm_encoding_map[i].str;
       }
    }
    
    return sspm_encoding_map[i].str; /* Should return SSPM_UNKNOWN_MINOR_TYPE */
}

Here is the caller graph for this function:

Definition at line 442 of file sspm.c.

{
    int i;

    char* ltype = sspm_lowercase(type);

    for (i=0; major_content_type_map[i].type !=  SSPM_UNKNOWN_MINOR_TYPE; i++){
       if(strncmp(ltype, major_content_type_map[i].str,
                 strlen(major_content_type_map[i].str))==0){
           free(ltype);
           return major_content_type_map[i].type;
       }
    }
    free(ltype);
    return major_content_type_map[i].type; /* Should return SSPM_UNKNOWN_MINOR_TYPE */
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 459 of file sspm.c.

{
    int i;
    char* ltype = sspm_lowercase(type);

    char *p = strchr(ltype,'/');

    if (p==0){
       return SSPM_UNKNOWN_MINOR_TYPE; 
    }

    p++; /* Skip the '/' */

    for (i=0; minor_content_type_map[i].type !=  SSPM_UNKNOWN_MINOR_TYPE; i++){
       if(strncmp(p, minor_content_type_map[i].str,
                 strlen(minor_content_type_map[i].str))==0){
           free(ltype);
           return minor_content_type_map[i].type;
       }
    }
    
    free(ltype);
    return minor_content_type_map[i].type; /* Should return SSPM_UNKNOWN_MINOR_TYPE */
}

Here is the call graph for this function:

Here is the caller graph for this function:

void sspm_free_header ( struct sspm_header header)

Definition at line 1083 of file sspm.c.

{
    if(header->boundary!=0){
       free(header->boundary);
    }
    if(header->minor_text!=0){
       free(header->minor_text);
    }
    if(header->charset!=0){
       free(header->charset);
    }
    if(header->filename!=0){
       free(header->filename);
    }
    if(header->content_id!=0){
       free(header->content_id);
    }
    if(header->error_text!=0){
       free(header->error_text);
    }
}

Here is the caller graph for this function:

void sspm_free_parts ( struct sspm_part parts,
size_t  max_parts 
)

Definition at line 1073 of file sspm.c.

{
     int i;
    
    for(i = 0; i<(int)max_parts && parts[i].header.major != SSPM_NO_MAJOR_TYPE;
       i++){
       sspm_free_header(&(parts[i].header));
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* sspm_get_next_line ( struct mime_impl impl)

Definition at line 596 of file sspm.c.

{
    char* s;
    s = impl->get_string(impl->temp,TMP_BUF_SIZE,impl->get_string_data);
    
    if(s == 0){
       impl->state = END_OF_INPUT;
    }
    return s;
}

Here is the caller graph for this function:

char* sspm_get_parameter ( char *  line,
char *  parameter 
)

Definition at line 149 of file sspm.c.

{
    char *p,*s,*q;
    static char name[1024];
    
    /* Find where the parameter name is in the line */
    p = strstr(line,parameter);

    if( p == 0){
       return 0;
    }

    /* skip over the parameter name, the '=' and any blank spaces */

    p+=strlen(parameter);

    while(*p==' ' || *p == '='){
       p++;
    }

    /*now find the next semicolon*/

    s = strchr(p,';');

    /* Strip of leading quote */
    q = strchr(p,'\"');

    if(q !=0){
       p = q+1;
    }

    if(s != 0){
       strncpy(name,p,(size_t)s-(size_t)p);
    } else {
       strcpy(name,p);
    }

    /* Strip off trailing quote, if it exists */

    q = strrchr(name,'\"');

    if (q != 0){
       *q='\0';
    }
    
    return name;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int sspm_is_blank ( char *  line)

Definition at line 305 of file sspm.c.

{
    char *p;
    char c =0;

    for(p=line; *p!=0; p++){
       if( ! (*p == ' '|| *p == '\t' || *p=='\n') ){
           c++;
       }
    }

    if (c==0){
       return 1;
    }

    return 0;
    
}

Here is the caller graph for this function:

int sspm_is_continuation_line ( char *  line)

Definition at line 324 of file sspm.c.

{
    if (line[0] == ' '|| line[0] == '\t' ) {
       return 1;
    }

    return 0;
}

Here is the caller graph for this function:

int sspm_is_mail_header ( char *  line)

Definition at line 293 of file sspm.c.

{
    char *name = sspm_property_name(line);

    if (name != 0){
       return 1;
    }

    return 0;

}

Here is the call graph for this function:

Here is the caller graph for this function:

int sspm_is_mime_boundary ( char *  line)

Definition at line 333 of file sspm.c.

{
    if( line[0] == '-' && line[1] == '-') {
       return 1;
    } 

    return 0;
}

Here is the caller graph for this function:

int sspm_is_mime_header ( char *  line)

Definition at line 276 of file sspm.c.

{
    char *name = sspm_property_name(line);
    int i;

    if(name == 0){ 
       return 0;
    }

    for(i = 0; mime_headers[i] != 0; i++){
       if(strcasecmp(name, mime_headers[i]) == 0)
           return 1;
    }
    
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 342 of file sspm.c.

{


    if (sspm_is_mime_boundary(line) &&
       strstr(line,"--\n")){
       return 1;
    } 

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int sspm_is_printable ( char  c) [static]

Definition at line 1320 of file sspm.c.

{
    return (c >= 33) && (c <= 126) && (c != '=');

} 

Here is the caller graph for this function:

char* sspm_lowercase ( char *  str)

Definition at line 424 of file sspm.c.

{
    char* p = 0;
    char* ret;

    if(str ==0){
       return 0;
    }

    ret = sspm_strdup(str);

    for(p = ret; *p!=0; p++){
       *p = tolower(*p);
    }

    return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 484 of file sspm.c.

{
    int i;

    for (i=0; major_content_type_map[i].type !=  SSPM_UNKNOWN_MINOR_TYPE; 
        i++){

       if(type == major_content_type_map[i].type){
           return major_content_type_map[i].str;
       }
    }
    
    return major_content_type_map[i].str; /* Should return SSPM_UNKNOWN_MINOR_TYPE */
}

Here is the caller graph for this function:

void * sspm_make_multipart_part ( struct mime_impl impl,
struct sspm_header header 
)

Definition at line 887 of file sspm.c.

{
    void *part=0;

    /* Now descend a level into each of the children of this part */
    impl->level++;

    /* Now we are working on the CHILD */
    memset(&(impl->parts[impl->part_no]), 0, sizeof(struct sspm_part));

    do{
       part = sspm_make_multipart_subpart(impl,header);

       if (part==0){
           /* Clean up the part in progress */
           impl->parts[impl->part_no].header.major 
              = SSPM_NO_MAJOR_TYPE;
           impl->parts[impl->part_no].header.minor 
              = SSPM_NO_MINOR_TYPE;

       }
       

    } while (get_line_type(impl->temp) != TERMINATING_BOUNDARY &&
       impl->state != END_OF_INPUT);

    impl->level--;

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void* sspm_make_multipart_subpart ( struct mime_impl impl,
struct sspm_header parent_header 
)

Definition at line 771 of file sspm.c.

{
    struct sspm_header header;
    char *line;
    void* part;
    size_t size;

    if(parent_header->boundary == 0){
       /* Error. Multipart headers must have a boundary*/
       
       sspm_set_error(parent_header,SSPM_NO_BOUNDARY_ERROR,0);
       /* read all of the reamining lines */
       while((line = sspm_get_next_line(impl)) != 0){
       }  

       return 0;
    }


    /* Step 1: Read the opening boundary */

    if(get_line_type(impl->temp) != BOUNDARY){
       while((line=sspm_get_next_line(impl)) != 0 ){
           if(sspm_is_mime_boundary(line)){

              assert(parent_header != 0);

              /* Check if it is the right boundary */
              if(!sspm_is_mime_terminating_boundary(line) &&
                 strncmp((line+2),parent_header->boundary, 
                        sizeof(parent_header->boundary)) 
                 == 0){
                  /* The +2 in strncmp skips over the leading "--" */
                  
                  break;
              } else {
                  /* Got the wrong boundary, so read and discard
                       until we get the right boundary.  */
                  char* boundary;
                  char msg[256];
                  
                  snprintf(msg,256,
                          "Expected: %s. Got: %s",
                          parent_header->boundary,line);

                  sspm_set_error(parent_header,
                               SSPM_WRONG_BOUNDARY_ERROR,msg);

                  /* Read until the paired terminating boundary */
                  if((boundary = (char*)malloc(strlen(line)+5)) == 0){
                     fprintf(stderr,"Out of memory");
                     abort();
                  }
                  strcpy(boundary,line);
                  strcat(boundary,"--");
                  while((line = sspm_get_next_line(impl)) != 0){
                     if(strcmp(boundary,line)==0){
                         break;
                     }
                  }
                  free(boundary);
                  
                  return 0;
              }
           }
       }
    }

    /* Step 2: Get the part header */
    sspm_read_header(impl,&header);

    /* If the header is still listed as default, there was probably an
       error */
    if(header.def == 1 && header.error != SSPM_NO_ERROR){
       sspm_set_error(&header,SSPM_NO_HEADER_ERROR,0);
       return 0;
    }

    if(header.error!= SSPM_NO_ERROR){
       sspm_store_part(impl,header,impl->level,0,0);
       return 0;
    }  

    /* Step 3: read the body */
    
    if(header.major == SSPM_MULTIPART_MAJOR_TYPE){
       struct sspm_header *child_header;
       child_header = &(impl->parts[impl->part_no].header);

       /* Store the multipart part */
       sspm_store_part(impl,header,impl->level,0,0);

       /* now get all of the sub-parts */
       part = sspm_make_multipart_part(impl,child_header);

       if(get_line_type(impl->temp) != TERMINATING_BOUNDARY){

           sspm_set_error(child_header,SSPM_NO_BOUNDARY_ERROR,impl->temp);
           return 0;
       }
       
       sspm_get_next_line(impl); /* Step past the terminating boundary */

    } else {
       sspm_make_part(impl, &header,parent_header,&part,&size);

       memset(&(impl->parts[impl->part_no]), 0, sizeof(struct sspm_part));

       sspm_store_part(impl,header,impl->level,part,size);

    }

    return part;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void* sspm_make_part ( struct mime_impl impl,
struct sspm_header header,
struct sspm_header parent_header,
void **  end_part,
size_t *  size 
)

Definition at line 638 of file sspm.c.

{

    /* For a single part type, read to the boundary, if there is a
   boundary. Otherwise, read until the end of input.  This routine
   assumes that the caller has read the header and has left the input
   at the first blank line */

    char *line;
    void *part;
    int end = 0;

    struct sspm_action_map action = get_action(
       impl,
       header->major,
       header->minor);

    *size = 0;
    part =action.new_part();

    impl->state = IN_BODY;

    while(end == 0 && (line = sspm_get_next_line(impl)) != 0){
       
       if(sspm_is_mime_boundary(line)){
           
           /* If there is a boundary, then this must be a multipart
               part, so there must be a parent_header. */
           if(parent_header == 0){
              char* boundary;
              end = 1;
              *end_part = 0;

              sspm_set_error(header,SSPM_UNEXPECTED_BOUNDARY_ERROR,line);

              /* Read until the paired terminating boundary */
              if((boundary = (char*)malloc(strlen(line)+5)) == 0){
                  fprintf(stderr,"Out of memory");
                  abort();
              }
              strcpy(boundary,line);
              strcat(boundary,"--");
              while((line = sspm_get_next_line(impl)) != 0){
                  /*printf("Error: %s\n",line);*/
                  if(strcmp(boundary,line)==0){
                     break;
                  }
              }
              free(boundary);

              break;
           }
           
           if(strncmp((line+2),parent_header->boundary,
                     sizeof(parent_header->boundary)) == 0){
              *end_part = action.end_part(part);

              if(sspm_is_mime_boundary(line)){
                  impl->state = END_OF_PART;
              } else if ( sspm_is_mime_terminating_boundary(line)){
                  impl->state = TERMINAL_END_OF_PART;
              }
              end = 1;
           } else {
              /* Error, this is not the correct terminating boundary*/

              /* read and discard until we get the right boundary.  */
                  char* boundary;
                  char msg[256];

                  snprintf(msg,256,
                          "Expected: %s--. Got: %s",
                          parent_header->boundary,line);

                  sspm_set_error(parent_header,
                    SSPM_WRONG_BOUNDARY_ERROR,msg);

                  /* Read until the paired terminating boundary */
                  if((boundary = (char*)malloc(strlen(line)+5)) == 0){
                     fprintf(stderr,"Out of memory");
                     abort();
                  }          
                  strcpy(boundary,line);
                  strcat(boundary,"--");
                  while((line = sspm_get_next_line(impl)) != 0){
                     if(strcmp(boundary,line)==0){
                         break;
                     }
                  }
                  free(boundary);

           }  
       } else {
           char* data=0;
           char* rtrn=0;
           *size = strlen(line);

           data = (char*)malloc(*size+2);
           assert(data != 0);
           if (header->encoding == SSPM_BASE64_ENCODING){
              rtrn = decode_base64(data,line,size); 
           } else if(header->encoding == SSPM_QUOTED_PRINTABLE_ENCODING){
              rtrn = decode_quoted_printable(data,line,size); 
           } 

           if(rtrn == 0){
              strcpy(data,line);
           }

           /* add a end-of-string after the data, just in case binary
               data from decode64 gets passed to a tring handling
               routine in add_line  */
           data[*size+1]='\0';

           action.add_line(part,header,data,*size);

           free(data);
       }
    }

    if (end == 0){
       /* End the part if the input is exhausted */
       *end_part = action.end_part(part);
    }

    return end_part;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 499 of file sspm.c.

{
    int i;
    for (i=0; minor_content_type_map[i].type !=  SSPM_UNKNOWN_MINOR_TYPE; 
        i++){
       if(type == minor_content_type_map[i].type){
           return minor_content_type_map[i].str;
       }
    }
    
    return minor_content_type_map[i].str; /* Should return SSPM_UNKNOWN_MINOR_TYPE */
}

Here is the caller graph for this function:

int sspm_parse_mime ( struct sspm_part parts,
size_t  max_parts,
struct sspm_action_map actions,
char *(*)(char *s, size_t size, void *data get_string,
void get_string_data,
struct sspm_header first_header 
)

Definition at line 1018 of file sspm.c.

{
    struct mime_impl impl;
    struct sspm_header header;
    void *part;
    int i;

    /* Initialize all of the data */
    memset(&impl,0,sizeof(struct mime_impl));
    memset(&header,0,sizeof(struct sspm_header));

    for(i = 0; i<(int)max_parts; i++){
       parts[i].header.major = SSPM_NO_MAJOR_TYPE;
       parts[i].header.minor = SSPM_NO_MINOR_TYPE;
    }
       
    impl.parts = parts;
    impl.max_parts = max_parts;
    impl.part_no = 0;
    impl.actions = actions;
    impl.get_string = get_string;
    impl.get_string_data = get_string_data;

    /* Read the header of the message. This will be the email header,
       unless first_header is specified. But ( HACK) that var is not
       currently being used */
    sspm_read_header(&impl,&header);

    if(header.major == SSPM_MULTIPART_MAJOR_TYPE){
       struct sspm_header *child_header;
       child_header = &(impl.parts[impl.part_no].header);
       
       sspm_store_part(&impl,header,impl.level,0,0);

       part = sspm_make_multipart_part(&impl,child_header);

    } else {
       void *part;
       size_t size;
       sspm_make_part(&impl, &header, 0,&part,&size);

       memset(&(impl.parts[impl.part_no]), 0, sizeof(struct sspm_part));
       
       sspm_store_part(&impl,header,impl.level,part,size);
    }

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* sspm_property_name ( char *  line)

Definition at line 197 of file sspm.c.

{
    static char name[1024];
    char *c = strchr(line,':');

    if(c != 0){
       strncpy(name,line,(size_t)c-(size_t)line);
       name[(size_t)c-(size_t)line] = '\0';
       return name;
    } else {
       return 0;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void sspm_read_header ( struct mime_impl impl,
struct sspm_header header 
)

Definition at line 919 of file sspm.c.

{
#define BUF_SIZE 1024
#define MAX_HEADER_LINES 25

    char *buf;
    char header_lines[MAX_HEADER_LINES][BUF_SIZE]; /* HACK, hard limits */
    int current_line = -1;
    int end = 0;

    memset(header_lines,0,sizeof(header_lines));
    memset(header,0,sizeof(struct sspm_header));

    /* Set up default header */
    header->def = 1;
    header->major = SSPM_TEXT_MAJOR_TYPE;
    header->minor = SSPM_PLAIN_MINOR_TYPE;
    header->error = SSPM_NO_ERROR;
    header->error_text = 0;

    /* Read all of the lines into memory */
    while(end==0&& (buf=sspm_get_next_line(impl)) != 0){

       enum line_type line_type = get_line_type(buf);
       
       switch(line_type){
           case BLANK: {
              end = 1;
              impl->state = END_OF_HEADER;
              break;
           }

           case MAIL_HEADER:
           case MIME_HEADER: {         
              impl->state = IN_HEADER;
              current_line++;
              
              assert(strlen(buf) < BUF_SIZE);
              
              strncpy(header_lines[current_line],buf,BUF_SIZE-1);
              header_lines[current_line][BUF_SIZE-1] = '\0';
              
              break;
           }
           
           case HEADER_CONTINUATION: {
              char* last_line, *end;
              char *buf_start;

              if(current_line < 0){
                  /* This is not really a continuation line, since
                       we have not see any header line yet */
                  sspm_set_error(header,SSPM_MALFORMED_HEADER_ERROR,buf);
                  return;
              }

              last_line = header_lines[current_line];
              end = (char*) ( (size_t)strlen(last_line)+
                                  (size_t)last_line);
              
              impl->state = IN_HEADER;

              
              /* skip over the spaces in buf start, and remove the new
                 line at the end of the lat line */
              if (last_line[strlen(last_line)-1] == '\n'){
                  last_line[strlen(last_line)-1] = '\0';
              }
              buf_start = buf;
              while(*buf_start == ' ' ||*buf_start == '\t' ){
                  buf_start++;
              }
              
              assert( strlen(buf_start) + strlen(last_line) < BUF_SIZE);
              
              strncat(last_line,buf_start,BUF_SIZE-strlen(last_line)-1);
              
              break;
           }
           
           default: {
              sspm_set_error(header,SSPM_MALFORMED_HEADER_ERROR,buf);
              return;
           }
       }
    }
       

    for(current_line = 0;
       current_line < MAX_HEADER_LINES && header_lines[current_line][0] != 0;
       current_line++){
       
       sspm_build_header(header,header_lines[current_line]);
    }


}

Here is the call graph for this function:

Here is the caller graph for this function:

void sspm_set_error ( struct sspm_header header,
enum sspm_error  error,
char *  message 
)

Definition at line 619 of file sspm.c.

{
    header->error = error;

    if(header->error_text!=0){
       free(header->error_text);
    }

    header->def = 0;

    if(message != 0){
       header->error_text = sspm_strdup(message);  
    } else {
       header->error_text = 0;
    }

}

Here is the call graph for this function:

Here is the caller graph for this function:

void sspm_store_part ( struct mime_impl impl,
struct sspm_header  header,
int  level,
void part,
size_t  size 
)

Definition at line 608 of file sspm.c.

{
    
    impl->parts[impl->part_no].header = header;
    impl->parts[impl->part_no].level = level;
    impl->parts[impl->part_no].data = part;  
    impl->parts[impl->part_no].data_size = size;  
    impl->part_no++;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* sspm_strdup ( char *  str)

Definition at line 83 of file sspm.c.

                            {

    char* s;

    s = strdup(str);

    return s;
}

Here is the caller graph for this function:

char* sspm_value ( char *  line)

Definition at line 211 of file sspm.c.

{
    static char value[1024];

    char *c,*s, *p;

    /* Find the first colon and the next semicolon */

    c = strchr(line,':');
    s = strchr(c,';');

    /* Skip the colon */
    c++;

    if (s == 0){
       s = c+strlen(line);
    }

    for(p=value; c != s; c++){
       if(*c!=' ' && *c!='\n'){
           *(p++) = *c;
       }
    }

    *p='\0';

    return value;

}

Here is the call graph for this function:

Here is the caller graph for this function:

void sspm_write_base64 ( struct sspm_buffer buf,
char *  inbuf,
int  size 
)

Definition at line 1382 of file sspm.c.

{
    
    char outbuf[4];
    int i;

    outbuf[0] = outbuf[1] = outbuf[2] = outbuf[3] = 65;

    switch(size){
       
       case 4:
           outbuf[3] =   inbuf[2] & 0x3F;

       case 3:
           outbuf[2] = ((inbuf[1] & 0x0F) << 2) | ((inbuf[2] & 0xC0) >> 6);

       case 2:       
           outbuf[0] =  (inbuf[0] & 0xFC) >> 2;
           outbuf[1] = ((inbuf[0] & 0x03) << 4) | ((inbuf[1] & 0xF0) >> 4);
           break;

       default:
           assert(0);
    }

    for(i = 0; i < 4; i++){

       if(outbuf[i] == 65){
           sspm_append_char(buf,'=');
       } else {
           sspm_append_char(buf,BaseTable[(int)outbuf[i]]);
       }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void sspm_write_header ( struct sspm_buffer buf,
struct sspm_header header 
)

Definition at line 1466 of file sspm.c.

{
    
    int i;
    char temp[TMP_BUF_SIZE];                            
    char* major; 
    char* minor; 
    
    /* Content-type */

    major = sspm_major_type_string(header->major);
    minor = sspm_minor_type_string(header->minor);

    if(header->minor == SSPM_UNKNOWN_MINOR_TYPE ){
       assert(header->minor_text !=0);
       minor = header->minor_text;
    }
    
    snprintf(temp,sizeof(temp),"Content-Type: %s/%s",major,minor);

    sspm_append_string(buf,temp);

    if(header->boundary != 0){
       snprintf(temp,sizeof(temp),";boundary=\"%s\"",header->boundary);
       sspm_append_string(buf,temp);
    }
    
    /* Append any content type parameters */    
    if(header->content_type_params != 0){
       for(i=0; *(header->content_type_params[i])!= 0;i++){
           snprintf(temp,sizeof(temp),header->content_type_params[i]);
           sspm_append_char(buf,';');
           sspm_append_string(buf,temp);
       }
    }
    
    sspm_append_char(buf,'\n');

    /*Content-Transfer-Encoding */

    if(header->encoding != SSPM_UNKNOWN_ENCODING &&
       header->encoding != SSPM_NO_ENCODING){
       snprintf(temp,sizeof(temp),"Content-Transfer-Encoding: %s\n",
              sspm_encoding_string(header->encoding));
    }

    sspm_append_char(buf,'\n');

}

Here is the call graph for this function:

Here is the caller graph for this function:

int sspm_write_mime ( struct sspm_part parts,
size_t  num_parts,
char **  output_string,
char *  header 
)

Definition at line 1580 of file sspm.c.

{
    struct sspm_buffer buf;
    int part_num =0;

    buf.buffer = malloc(4096);
    buf.pos = buf.buffer;
    buf.buf_size = 10;
    buf.line_pos = 0;

    /* write caller's header */
    if(header != 0){
       sspm_append_string(&buf,header);
    }

    if(buf.buffer[strlen(buf.buffer)-1] != '\n'){
       sspm_append_char(&buf,'\n');
    }

    /* write mime-version header */
    sspm_append_string(&buf,"Mime-Version: 1.0\n");

    /* End of header */

    /* Write body parts */
    while(parts[part_num].header.major != SSPM_NO_MAJOR_TYPE){
       if (parts[part_num].header.major == SSPM_MULTIPART_MAJOR_TYPE){
           sspm_write_multipart_part(&buf,parts,&part_num);
       } else {
           sspm_write_part(&buf, &(parts[part_num]), &part_num);
       }      

       part_num++;
    }


    *output_string = buf.buffer;

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void sspm_write_multipart_part ( struct sspm_buffer buf,
struct sspm_part parts,
int part_num 
)

Definition at line 1516 of file sspm.c.

{

    int parent_level, level;
    struct sspm_header *header = &(parts[*part_num].header);
    /* Write the header for the multipart part */
    sspm_write_header(buf,header);

    parent_level = parts[*part_num].level;

    (*part_num)++;

    level = parts[*part_num].level;

    while(parts[*part_num].header.major != SSPM_NO_MAJOR_TYPE &&
         level == parent_level+1){

       assert(header->boundary);
       sspm_append_string(buf,header->boundary);
       sspm_append_char(buf,'\n');
       
       if (parts[*part_num].header.major == SSPM_MULTIPART_MAJOR_TYPE){
           sspm_write_multipart_part(buf,parts,part_num);
       } else {
           sspm_write_part(buf, &(parts[*part_num]), part_num);
       }      

       (*part_num)++;
       level =  parts[*part_num].level;
    }
   
    sspm_append_string(buf,"\n\n--");
    sspm_append_string(buf,header->boundary);
    sspm_append_string(buf,"\n");

    (*part_num)--; /* undo last, spurious, increment */
}

Here is the call graph for this function:

Here is the caller graph for this function:

void sspm_write_part ( struct sspm_buffer buf,
struct sspm_part part,
int part_num 
)

Definition at line 1556 of file sspm.c.

{

    /* Write header */
    sspm_write_header(buf,&(part->header));

    /* Write part data */

    if(part->data == 0){
       return;
    }

    if(part->header.encoding == SSPM_BASE64_ENCODING) {
       assert(part->data_size != 0);
       sspm_encode_base64(buf,part->data,part->data_size);
    } else if(part->header.encoding == SSPM_QUOTED_PRINTABLE_ENCODING) {
       sspm_encode_quoted_printable(buf,part->data);
    } else {
       sspm_append_string(buf,part->data);
    }

    sspm_append_string(buf,"\n\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

char BaseTable[64] [static]
Initial value:
 {
    'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
    'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
    'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
    'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
}

Definition at line 1375 of file sspm.c.

char* mime_headers[] [static]
Initial value:
 {
    "Content-Type",
    "Content-Transfer-Encoding",
    "Content-Disposition",
    "Content-Id",
    "Mime-Version",
    0 
}

Definition at line 241 of file sspm.c.