/[mailutils]/mailutils/mailbox/mime.c
ViewVC logotype

Diff of /mailutils/mailbox/mime.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.34 by polak, Sun Feb 9 20:39:58 2003 UTC revision 1.35 by gray, Wed Aug 27 14:09:18 2003 UTC
# Line 46  Line 46 
46   */   */
47    
48  static int  static int
49  _mime_is_multipart_digest(mime_t mime)  _mime_is_multipart_digest (mime_t mime)
50  {  {
51          if ( mime->content_type )    if (mime->content_type)
52                  return(strncasecmp("multipart/digest", mime->content_type, strlen("multipart/digest")) ? 0: 1);      return (strncasecmp
53          return 0;              ("multipart/digest", mime->content_type,
54  }               strlen ("multipart/digest")) ? 0 : 1);
55      return 0;
56  static int  }
57  _mime_append_part(mime_t mime, message_t msg, int offset, int len, int lines)  
58  {  static int
59          struct _mime_part       *mime_part, **part_arr;  _mime_append_part (mime_t mime, message_t msg, int offset, int len, int lines)
60          int                             ret;  {
61          size_t                          size;    struct _mime_part *mime_part, **part_arr;
62          header_t                        hdr;    int ret;
63      size_t size;
64          if ( ( mime_part = calloc(1, sizeof(*mime_part)) ) == NULL )    header_t hdr;
65                  return ENOMEM;  
66      if ((mime_part = calloc (1, sizeof (*mime_part))) == NULL)
67          if ( mime->nmtp_parts >= mime->tparts ) {      return ENOMEM;
68                  if ( ( part_arr = realloc(mime->mtp_parts, ( mime->tparts + 5 ) * sizeof(mime_part)) ) == NULL ) {  
69                          free(mime_part);    if (mime->nmtp_parts >= mime->tparts)
70                          return ENOMEM;      {
71                  }        if ((part_arr =
72                  mime->mtp_parts = part_arr;             realloc (mime->mtp_parts,
73                  mime->tparts += 5;                      (mime->tparts + 5) * sizeof (mime_part))) == NULL)
74          }          {
75          mime->mtp_parts[mime->nmtp_parts++] = mime_part;            free (mime_part);
76          if ( msg == NULL ) {            return ENOMEM;
77                  if ( ( ret = message_create(&(mime_part->msg), mime_part) ) == 0 ) {          }
78                          if ( ( ret = header_create(&hdr, mime->header_buf, mime->header_length, mime_part->msg) ) != 0 ) {        mime->mtp_parts = part_arr;
79                                  message_destroy(&mime_part->msg, mime_part);        mime->tparts += 5;
80                                  free(mime_part);      }
81                                  return ret;    mime->mtp_parts[mime->nmtp_parts++] = mime_part;
82                          }    if (msg == NULL)
83                          message_set_header(mime_part->msg, hdr, mime_part);      {
84                  } else {        if ((ret = message_create (&(mime_part->msg), mime_part)) == 0)
85                          free(mime_part);          {
86                          return ret;            if ((ret =
87                  }                 header_create (&hdr, mime->header_buf,
88                  mime->header_length = 0;                                mime->header_length, mime_part->msg)) != 0)
89                  if ( ( ret = header_get_value(hdr, MU_HEADER_CONTENT_TYPE, NULL, 0, &size) ) != 0 || size == 0 ) {              {
90                          if ( _mime_is_multipart_digest(mime) )                message_destroy (&mime_part->msg, mime_part);
91                                  header_set_value(hdr, MU_HEADER_CONTENT_TYPE, "message/rfc822", 0);                free (mime_part);
92                          else                return ret;
93                                  header_set_value(hdr, MU_HEADER_CONTENT_TYPE, "text/plain", 0);              }
94                  }            message_set_header (mime_part->msg, hdr, mime_part);
95                  mime_part->len = len;          }
96                  mime_part->lines = lines;        else
97                  mime_part->offset = offset;          {
98          } else {            free (mime_part);
99                  message_ref(msg);            return ret;
100                  message_size(msg, &mime_part->len);          }
101                  message_lines(msg, &mime_part->lines);        mime->header_length = 0;
102                  if ( mime->nmtp_parts > 1 )        if ((ret =
103                          mime_part->offset = mime->mtp_parts[mime->nmtp_parts-2]->len;             header_get_value (hdr, MU_HEADER_CONTENT_TYPE, NULL,
104                  mime_part->msg = msg;                               0, &size)) != 0 || size == 0)
105          }          {
106          mime_part->mime = mime;            if (_mime_is_multipart_digest (mime))
107          return 0;              header_set_value (hdr,
108                                  MU_HEADER_CONTENT_TYPE, "message/rfc822", 0);
109              else
110                header_set_value (hdr, MU_HEADER_CONTENT_TYPE, "text/plain", 0);
111            }
112          mime_part->len = len;
113          mime_part->lines = lines;
114          mime_part->offset = offset;
115        }
116      else
117        {
118          message_ref (msg);
119          message_size (msg, &mime_part->len);
120          message_lines (msg, &mime_part->lines);
121          if (mime->nmtp_parts > 1)
122            mime_part->offset = mime->mtp_parts[mime->nmtp_parts - 2]->len;
123          mime_part->msg = msg;
124        }
125      mime_part->mime = mime;
126      return 0;
127  }  }
128    
129  static char *  static char *
130  _strltrim(char *str)  _strltrim (char *str)
131  {  {
132          char    *p;    char *p;
133    
134          for (p = str; isspace((unsigned char)*p) && *p != '\0'; ++p)    for (p = str; isspace ((unsigned char) *p) && *p != '\0'; ++p);
135                  ;    return ((p != str) ? memmove (str, p, strlen (p) + 1) : str);
         return((p != str) ? memmove(str, p, strlen(p)+1) : str);  
136  }  }
137    
138  static char *  static char *
139  _strttrim(char *str)  _strttrim (char *str)
140  {  {
141          char    *p;    char *p;
142    
143          for (p = str + strlen(str) - 1; isspace((unsigned char)*p) && p >= str; --p)    for (p = str + strlen (str) - 1;
144                  ;         isspace ((unsigned char) *p) && p >= str; --p);
145          *++p = '\0';    *++p = '\0';
146          return(str);    return (str);
147  }  }
148    
149  char *_strtrim(char *str);  char *_strtrim (char *str);
150  #define _strtrim(str) _strltrim(_strttrim(str))  #define _strtrim(str) _strltrim(_strttrim(str))
151    
152  #define _ISSPECIAL(c) ( \  #define _ISSPECIAL(c) ( \
# Line 138  char *_strtrim(char *str); Line 156  char *_strtrim(char *str);
156      || ((c) == ']') )      || ((c) == ']') )
157    
158  static void  static void
159  _mime_munge_content_header(char *field_body )  _mime_munge_content_header (char *field_body)
160  {  {
161          char *p, *e, *str = field_body;    char *p, *e, *str = field_body;
162          int quoted = 0;    int quoted = 0;
163    
164          _strtrim(field_body);    _strtrim (field_body);
165    
166          if ( ( e = strchr(str, ';') ) == NULL )    if ((e = strchr (str, ';')) == NULL)
167                  return;      return;
168          while( *e == ';' ) {    while (*e == ';')
169                  p = e;      {
170                  e++;        p = e;
171                  while ( *e && isspace((unsigned char)*e) )  /* remove space upto param */        e++;
172                          e++;        while (*e && isspace ((unsigned char) *e))        /* remove space upto param */
173                  memmove(p+1, e, strlen(e)+1);          e++;
174                  e = p+1;        memmove (p + 1, e, strlen (e) + 1);
175          e = p + 1;
176                  while ( *e && *e != '=' )   /* find end of value */  
177                          e++;        while (*e && *e != '=')   /* find end of value */
178                  e = p = e+1;          e++;
179                  while ( *e && (quoted || ( !_ISSPECIAL(*e) && !isspace((unsigned char)*e) ) ) ) {        e = p = e + 1;
180                          if ( *e == '\\' ) {                /* escaped */        while (*e
181                                  memmove(e, e+1, strlen(e)+2);               && (quoted
182                          } else if ( *e == '\"' )                   || (!_ISSPECIAL (*e) && !isspace ((unsigned char) *e))))
183                                  quoted = ~quoted;          {
184                          e++;            if (*e == '\\')
185                  }              {                   /* escaped */
186                  memmove (e, e + 1, strlen (e) + 2);
187                }
188              else if (*e == '\"')
189                quoted = ~quoted;
190              e++;
191          }          }
192        }
193  }  }
194    
195  static char *  static char *
196  _mime_get_param(char *field_body, const char *param, int *len)  _mime_get_param (char *field_body, const char *param, int *len)
197  {  {
198          char *str, *p, *v, *e;    char *str, *p, *v, *e;
199          int quoted = 0, was_quoted = 0;    int quoted = 0, was_quoted = 0;
200    
201          if ( len == NULL || ( str = field_body ) == NULL )    if (len == NULL || (str = field_body) == NULL)
202                  return NULL;      return NULL;
203    
204          p = strchr(str, ';' );    p = strchr (str, ';');
205          while ( p ) {    while (p)
206                  p++;      {
207                  if ( ( v = strchr(p, '=' ) ) == NULL )        p++;
208                          break;        if ((v = strchr (p, '=')) == NULL)
209                  *len = 0;          break;
210                  v = e = v + 1;        *len = 0;
211                  while ( *e && (quoted || ( !_ISSPECIAL(*e) && !isspace((unsigned char)*e) ) ) ) {       /* skip pass value and calc len */        v = e = v + 1;
212                          if ( *e == '\"' )        while (*e
213                                  quoted = ~quoted, was_quoted = 1;               && (quoted
214                          else                   || (!_ISSPECIAL (*e) && !isspace ((unsigned char) *e))))
215                                  (*len)++;          {                       /* skip pass value and calc len */
216                          e++;            if (*e == '\"')
217                  }              quoted = ~quoted, was_quoted = 1;
218                  if ( strncasecmp(p, param, strlen(param)) ) {   /* no match jump to next */            else
219                          p = strchr(e, ';' );              (*len)++;
220                          continue;            e++;
221                  }          }
222                  else        if (strncasecmp (p, param, strlen (param)))
223                          return was_quoted ? v + 1 : v;                  /* return unquoted value */          {                       /* no match jump to next */
224          }            p = strchr (e, ';');
225          return NULL;            continue;
226            }
227          else
228            return was_quoted ? v + 1 : v;  /* return unquoted value */
229        }
230      return NULL;
231  }  }
232    
233  static int  static int
234  _mime_setup_buffers(mime_t mime)  _mime_setup_buffers (mime_t mime)
235  {  {
236          if ( mime->cur_buf == NULL && ( mime->cur_buf = malloc( mime->buf_size ) ) == NULL ) {    if (mime->cur_buf == NULL
237                  return ENOMEM;        && (mime->cur_buf = malloc (mime->buf_size)) == NULL)
238          }      {
239          if ( mime->cur_line == NULL && ( mime->cur_line = calloc( MIME_MAX_HDR_LEN, 1 ) ) == NULL ) {        return ENOMEM;
240                  free(mime->cur_buf);      }
241                  return ENOMEM;    if (mime->cur_line == NULL
242          }        && (mime->cur_line = calloc (MIME_MAX_HDR_LEN, 1)) == NULL)
243          return 0;      {
244          free (mime->cur_buf);
245          return ENOMEM;
246        }
247      return 0;
248  }  }
249    
250  static void  static void
251  _mime_append_header_line(mime_t mime)  _mime_append_header_line (mime_t mime)
252  {  {
253          if ( mime->header_length + mime->line_ndx > mime->header_buf_size) {    if (mime->header_length + mime->line_ndx > mime->header_buf_size)
254                  char *nhb;      {
255                  if ( ( nhb = realloc( mime->header_buf, mime->header_length + mime->line_ndx + 128 ) ) == NULL )        char *nhb;
256                          return;        if ((nhb =
257                  mime->header_buf = nhb;             realloc (mime->header_buf,
258                  mime->header_buf_size = mime->header_length + mime->line_ndx + 128;                      mime->header_length + mime->line_ndx + 128)) == NULL)
259          }          return;
260          memcpy(mime->header_buf + mime->header_length, mime->cur_line, mime->line_ndx);        mime->header_buf = nhb;
261          mime->header_length += mime->line_ndx;        mime->header_buf_size = mime->header_length + mime->line_ndx + 128;
262  }      }
263      memcpy (mime->header_buf + mime->header_length, mime->cur_line,
264  static int            mime->line_ndx);
265  _mime_parse_mpart_message(mime_t mime)    mime->header_length += mime->line_ndx;
266  {  }
267          char            *cp, *cp2;  
268          int             blength, mb_length, mb_offset, mb_lines, ret;  static int
269          size_t          nbytes;  _mime_parse_mpart_message (mime_t mime)
270    {
271          if ( !(mime->flags & MIME_PARSER_ACTIVE) ) {    char *cp, *cp2;
272                  char *boundary;    int blength, mb_length, mb_offset, mb_lines, ret;
273                  int len;    size_t nbytes;
274    
275                  if ( ( ret = _mime_setup_buffers(mime) ) != 0 )    if (!(mime->flags & MIME_PARSER_ACTIVE))
276                          return ret;      {
277                  if ( ( boundary = _mime_get_param(mime->content_type, "boundary", &len) ) == NULL )        char *boundary;
278                          return EINVAL;        int len;
279                  if ( ( mime->boundary = calloc(1, len + 1) ) == NULL )  
280                          return ENOMEM;        if ((ret = _mime_setup_buffers (mime)) != 0)
                 strncpy(mime->boundary, boundary, len );  
   
                 mime->cur_offset = 0;  
                 mime->line_ndx = 0;  
                 mime->parser_state = MIME_STATE_SCAN_BOUNDARY;  
                 mime->flags |= MIME_PARSER_ACTIVE;  
         }  
         mb_length = mime->body_length;  
         mb_offset = mime->body_offset;  
         mb_lines = mime->body_lines;  
         blength = strlen(mime->boundary);  
   
         while ( ( ret = stream_read(mime->stream, mime->cur_buf, mime->buf_size, mime->cur_offset, &nbytes) ) == 0 && nbytes ) {  
                 cp = mime->cur_buf;  
                 while ( nbytes ) {  
                         mime->cur_line[mime->line_ndx] = *cp;  
                         if ( *cp == '\n' ) {  
                                 switch( mime->parser_state ) {  
                                         case MIME_STATE_BEGIN_LINE:  
                                                 mime->cur_line[0] = *cp;  
                                                 mime->line_ndx = 0;  
                                                 mime->parser_state = MIME_STATE_SCAN_BOUNDARY;  
                                                 break;  
                                         case MIME_STATE_SCAN_BOUNDARY:  
                                                 cp2 = mime->cur_line[0] == '\n' ? mime->cur_line + 1 : mime->cur_line;  
                                                 if ( mime->header_length )  
                                                         mb_lines++;  
                                                 if ( mime->line_ndx >= blength ) {  
                                                         if ( ( !strncasecmp(cp2,"--", 2) && !strncasecmp(cp2+2, mime->boundary, blength) )  
                                                                 || !strncasecmp(cp2, mime->boundary, blength) ) {  
                                                                 mime->parser_state = MIME_STATE_HEADERS;  
                                                                 mime->flags &= ~MIME_PARSER_HAVE_CR;  
                                                                 mb_length = mime->cur_offset - mb_offset - mime->line_ndx + 1;  
                                                                 if ( mime->header_length ) /* this skips the preamble */  
                                                                         _mime_append_part(mime, NULL, mb_offset, mb_length, mb_lines);  
                                                                 if ( ( &mime->cur_line[mime->line_ndx] - cp2 - 1 > blength  
                                                                         && !strncasecmp(cp2+blength+2, "--",2) )  
                                                                         || ( &mime->cur_line[mime->line_ndx] - cp2 - 1 == blength  
                                                                         && !strncasecmp(cp2+blength, "--",2) ) ) { /* last boundary */  
                                                                         mime->parser_state = MIME_STATE_BEGIN_LINE;  
                                                                         mime->header_length = 0;  
                                                                         break;  
                                                                 }  
                                                                 mime->line_ndx = -1; /* headers parsing requires empty line */  
                                                                 break;  
                                                         }  
                                                 }  
                                                 mime->line_ndx = 0;  
                                                 mime->cur_line[0] = *cp; /* stay in this state but leave '\n' at begining */  
                                                 break;  
                                         case MIME_STATE_HEADERS:  
                                                 mime->line_ndx++;  
                                                 _mime_append_header_line(mime);  
                                                 if ( mime->line_ndx == 1 || mime->cur_line[0] == '\r' ) {  
                                                         mime->parser_state = MIME_STATE_BEGIN_LINE;  
                                                         mb_offset = mime->cur_offset + 1;  
                                                         mb_lines = 0;  
                                                 }  
                                                 mime->line_ndx = -1;  
                                                 break;  
                                 }  
                         }  
                         mime->line_ndx++;  
                         if ( mime->line_ndx >= MIME_MAX_HDR_LEN ) {  
                                 mime->line_ndx = 0;  
                                 mime->parser_state = MIME_STATE_BEGIN_LINE;  
                         }  
                         mime->cur_offset++;  
                         nbytes--;  
                         cp++;  
                 }  
         }  
         mime->body_lines = mb_lines;  
         mime->body_length = mb_length;  
         mime->body_offset = mb_offset;  
         if ( ret != EAGAIN ) { /* finished cleanup */  
                 if ( mime->header_length ) /* this skips the preamble */  
                         _mime_append_part(mime, NULL, mb_offset, mb_length, mb_lines);  
                 mime->flags &= ~MIME_PARSER_ACTIVE;  
                 mime->body_offset = mime->body_length = mime->header_length = mime->body_lines = 0;  
         }  
281          return ret;          return ret;
282          if ((boundary =
283               _mime_get_param (mime->content_type, "boundary", &len)) == NULL)
284            return EINVAL;
285          if ((mime->boundary = calloc (1, len + 1)) == NULL)
286            return ENOMEM;
287          strncpy (mime->boundary, boundary, len);
288    
289          mime->cur_offset = 0;
290          mime->line_ndx = 0;
291          mime->parser_state = MIME_STATE_SCAN_BOUNDARY;
292          mime->flags |= MIME_PARSER_ACTIVE;
293        }
294      mb_length = mime->body_length;
295      mb_offset = mime->body_offset;
296      mb_lines = mime->body_lines;
297      blength = strlen (mime->boundary);
298    
299      while ((ret =
300              stream_read (mime->stream, mime->cur_buf, mime->buf_size,
301                           mime->cur_offset, &nbytes)) == 0 && nbytes)
302        {
303          cp = mime->cur_buf;
304          while (nbytes)
305            {
306              mime->cur_line[mime->line_ndx] = *cp;
307              if (*cp == '\n')
308                {
309                  switch (mime->parser_state)
310                    {
311                    case MIME_STATE_BEGIN_LINE:
312                      mime->cur_line[0] = *cp;
313                      mime->line_ndx = 0;
314                      mime->parser_state = MIME_STATE_SCAN_BOUNDARY;
315                      break;
316                      
317                    case MIME_STATE_SCAN_BOUNDARY:
318                      cp2 =
319                        mime->cur_line[0] ==
320                        '\n' ? mime->cur_line + 1 : mime->cur_line;
321                      if (mime->header_length)
322                        mb_lines++;
323                      if (mime->line_ndx >= blength)
324                        {
325                          if ((!strncasecmp (cp2, "--", 2)
326                               && !strncasecmp (cp2 + 2, mime->boundary,
327                                blength))
328                              || !strncasecmp (cp2, mime->boundary, blength))
329                            {
330                              mime->parser_state = MIME_STATE_HEADERS;
331                              mime->flags &= ~MIME_PARSER_HAVE_CR;
332                              mb_length = mime->cur_offset -
333                                          mb_offset - mime->line_ndx;
334                              if (mb_lines > 1)
335                                mb_length++;
336                              if (mime->header_length) /* this skips the preamble */
337                                _mime_append_part (mime, NULL,
338                                                   mb_offset, mb_length, mb_lines-1);
339                              if ((&mime->cur_line[mime->line_ndx] - cp2 - 1 >
340                                   blength
341                                   && !strncasecmp (cp2 + blength + 2, "--", 2))
342                                  || (&mime->cur_line[mime->line_ndx] - cp2 - 1 ==
343                                      blength
344                                      && !strncasecmp (cp2 + blength, "--", 2)))
345                                {   /* last boundary */
346                                  mime->parser_state = MIME_STATE_BEGIN_LINE;
347                                  mime->header_length = 0;
348                                  break;
349                                }
350                              mime->line_ndx = -1;  /* headers parsing requires empty line */
351                              break;
352                            }
353                        }
354                      mime->line_ndx = 0;
355                      mime->cur_line[0] = *cp; /* stay in this state but
356                                                  leave '\n' at begining */
357                      break;
358                      
359                    case MIME_STATE_HEADERS:
360                      mime->line_ndx++;
361                      _mime_append_header_line (mime);
362                      if (mime->line_ndx == 1 || mime->cur_line[0] == '\r')
363                        {
364                          mime->parser_state = MIME_STATE_SCAN_BOUNDARY;
365                          mb_offset = mime->cur_offset + 1;
366                          mb_lines = 0;
367                        }
368                      mime->line_ndx = -1;
369                      break;
370                    }
371                }
372              mime->line_ndx++;
373              if (mime->line_ndx >= MIME_MAX_HDR_LEN)
374                {
375                  mime->line_ndx = 0;
376                  mime->parser_state = MIME_STATE_BEGIN_LINE;
377                }
378              mime->cur_offset++;
379              nbytes--;
380              cp++;
381            }
382        }
383      mime->body_lines = mb_lines;
384      mime->body_length = mb_length;
385      mime->body_offset = mb_offset;
386      if (ret != EAGAIN)
387        {                           /* finished cleanup */
388          if (mime->header_length)  /* this skips the preamble */
389            _mime_append_part (mime, NULL, mb_offset, mb_length, mb_lines);
390          mime->flags &= ~MIME_PARSER_ACTIVE;
391          mime->body_offset = mime->body_length =
392            mime->header_length = mime->body_lines = 0;
393        }
394      return ret;
395  }  }
396    
397  /*------ Mime message functions for READING a multipart message -----*/  /*------ Mime message functions for READING a multipart message -----*/
398    
399  static int  static int
400  _mimepart_body_read(stream_t stream, char *buf, size_t buflen, off_t off, size_t *nbytes)  _mimepart_body_read (stream_t stream, char *buf, size_t buflen, off_t off,
401                         size_t * nbytes)
402  {  {
403          body_t                          body = stream_get_owner(stream);    body_t body = stream_get_owner (stream);
404          message_t                       msg = body_get_owner(body);    message_t msg = body_get_owner (body);
405          struct _mime_part       *mime_part = message_get_owner(msg);    struct _mime_part *mime_part = message_get_owner (msg);
406          size_t                          read_len;    size_t read_len;
407          int                 ret = 0;    int ret = 0;
408    
409          if ( nbytes == NULL )    if (nbytes == NULL)
410                  return(EINVAL);      return (EINVAL);
411    
412          *nbytes = 0;    *nbytes = 0;
413          read_len = (int)mime_part->len - (int)off;    read_len = (int) mime_part->len - (int) off;
414          if ( read_len <= 0 ) {    if (read_len <= 0)
415                  if ( !stream_is_seekable (mime_part->mime->stream) ) {      {
416                          while( ( ret = stream_read(mime_part->mime->stream, buf, buflen, mime_part->offset + off, nbytes) ) == 0 && *nbytes )        if (!stream_is_seekable (mime_part->mime->stream))
417                             off += *nbytes;          {
418                          *nbytes = 0;                  while ((ret =
419                  }                    stream_read (mime_part->mime->stream,
420                  return ret;                                 buf, buflen,
421                                   mime_part->offset + off,
422                                   nbytes)) == 0 && *nbytes)
423                off += *nbytes;
424              *nbytes = 0;
425          }          }
426          read_len = (buflen <= read_len)? buflen : read_len;        return ret;
427        }
428      read_len = (buflen <= read_len) ? buflen : read_len;
429    
430          return stream_read(mime_part->mime->stream, buf, read_len, mime_part->offset + off, nbytes );    return stream_read (mime_part->mime->stream, buf, read_len,
431                          mime_part->offset + off, nbytes);
432  }  }
433    
434  static int  static int
435  _mimepart_body_fd(stream_t stream, int *fd)  _mimepart_body_fd (stream_t stream, int *fd)
436  {  {
437          body_t                          body = stream_get_owner(stream);    body_t body = stream_get_owner (stream);
438          message_t                       msg = body_get_owner(body);    message_t msg = body_get_owner (body);
439          struct _mime_part       *mime_part = message_get_owner(msg);    struct _mime_part *mime_part = message_get_owner (msg);
440    
441          return stream_get_fd(mime_part->mime->stream, fd);    return stream_get_fd (mime_part->mime->stream, fd);
442  }  }
443    
444  static int  static int
445  _mimepart_body_size (body_t body, size_t *psize)  _mimepart_body_size (body_t body, size_t * psize)
446  {  {
447          message_t                       msg = body_get_owner(body);    message_t msg = body_get_owner (body);
448          struct _mime_part       *mime_part = message_get_owner(msg);    struct _mime_part *mime_part = message_get_owner (msg);
449    
450          if (mime_part == NULL)    if (mime_part == NULL)
451                  return EINVAL;      return EINVAL;
452          if (psize)    if (psize)
453                  *psize = mime_part->len;      *psize = mime_part->len;
454          return 0;    return 0;
455  }  }
456    
457  static int  static int
458  _mimepart_body_lines (body_t body, size_t *plines)  _mimepart_body_lines (body_t body, size_t * plines)
459  {  {
460          message_t                       msg = body_get_owner(body);    message_t msg = body_get_owner (body);
461          struct _mime_part       *mime_part = message_get_owner(msg);    struct _mime_part *mime_part = message_get_owner (msg);
462    
463          if (mime_part == NULL)    if (mime_part == NULL)
464                  return EINVAL;      return EINVAL;
465          if (plines)    if (plines)
466                  *plines = mime_part->lines;      *plines = mime_part->lines;
467          return 0;    return 0;
468  }  }
469    
470  /*------ Mime message/header functions for CREATING multipart message -----*/  /*------ Mime message/header functions for CREATING multipart message -----*/
471  static int  static int
472  _mime_set_content_type(mime_t mime)  _mime_set_content_type (mime_t mime)
473  {  {
474          char content_type[256], * content_te;    char content_type[256], *content_te;
475          char boundary[128];    char boundary[128];
476          header_t        hdr = NULL;    header_t hdr = NULL;
477          size_t          size;    size_t size;
478          int             ret;    int ret;
479    
480          /* Delayed the creation of the header 'til they create the final message via    /* Delayed the creation of the header 'til they create the final message via
481             mime_get_message()  */       mime_get_message()  */
482          if (mime->hdrs == NULL)    if (mime->hdrs == NULL)
483             return 0;      return 0;
484          if ( mime->nmtp_parts > 1 ) {    if (mime->nmtp_parts > 1)
485                  if ( mime->flags & MIME_ADDED_MULTIPART_CT )      {
486                          return 0;        if (mime->flags & MIME_ADDED_MULTIPART_CT)
487                  if ( mime->flags & MIME_MULTIPART_MIXED )          return 0;
488                          strcpy(content_type, "multipart/mixed; boundary=");        if (mime->flags & MIME_MULTIPART_MIXED)
489                  else          strcpy (content_type, "multipart/mixed; boundary=");
490                          strcpy(content_type, "multipart/alternative; boundary=");        else
491                  if ( mime->boundary == NULL ) {          strcpy (content_type, "multipart/alternative; boundary=");
492                          sprintf (boundary,"%ld-%ld=:%ld",(long)random (), (long)time (0), (long)getpid ());        if (mime->boundary == NULL)
493                          if ( ( mime->boundary = strdup(boundary) ) == NULL )          {
494                                  return ENOMEM;            sprintf (boundary, "%ld-%ld=:%ld",
495                  }                     (long) random (), (long) time (0), (long) getpid ());
496                  strcat(content_type, "\"");            if ((mime->boundary = strdup (boundary)) == NULL)
497                  strcat(content_type, mime->boundary);              return ENOMEM;
498                  strcat(content_type, "\"");          }
499                  mime->flags |= MIME_ADDED_MULTIPART_CT;        strcat (content_type, "\"");
500          strcat (content_type, mime->boundary);
501                  ret = header_set_value(mime->hdrs, MU_HEADER_CONTENT_TYPE, content_type, 1);        strcat (content_type, "\"");
502          } else {        mime->flags |= MIME_ADDED_MULTIPART_CT;
503                  if ( (mime->flags & (MIME_ADDED_CT|MIME_ADDED_MULTIPART_CT)) == MIME_ADDED_CT )  
504                          return 0;        ret =
505                  mime->flags &= ~MIME_ADDED_MULTIPART_CT;          header_set_value (mime->hdrs, MU_HEADER_CONTENT_TYPE,
506                  if ( mime->nmtp_parts )                            content_type, 1);
507                          message_get_header(mime->mtp_parts[0]->msg, &hdr);      }
508                  if ( hdr == NULL || header_get_value(hdr, MU_HEADER_CONTENT_TYPE, NULL, 0, &size) != 0 || size == 0 )    else
509                          strcpy(content_type, "text/plain; charset=us-ascii");      {
510                  else        if ((mime->
511                          header_get_value(hdr, MU_HEADER_CONTENT_TYPE, content_type, sizeof(content_type), &size);             flags & (MIME_ADDED_CT | MIME_ADDED_MULTIPART_CT))
512              == MIME_ADDED_CT)
513                  ret = header_set_value(mime->hdrs, MU_HEADER_CONTENT_TYPE, content_type, 1);          return 0;
514                  if (ret) return ret;        mime->flags &= ~MIME_ADDED_MULTIPART_CT;
515          if (mime->nmtp_parts)
516                  /* if the only part contains a transfer-encoding          message_get_header (mime->mtp_parts[0]->msg, &hdr);
517                     field, set it on the message header too */        if (hdr == NULL
518                  if (hdr &&            || header_get_value (hdr, MU_HEADER_CONTENT_TYPE,
519                      header_aget_value (hdr,                                 NULL, 0, &size) != 0 || size == 0)
520                                         MU_HEADER_CONTENT_TRANSFER_ENCODING,          strcpy (content_type, "text/plain; charset=us-ascii");
521                                         & content_te) == 0)        else
522                    {          header_get_value (hdr, MU_HEADER_CONTENT_TYPE,
523                      ret = header_set_value (mime->hdrs,                            content_type, sizeof (content_type), &size);
524                                              MU_HEADER_CONTENT_TRANSFER_ENCODING,  
525                                              content_te, 1);        ret =
526                      free (content_te);          header_set_value (mime->hdrs, MU_HEADER_CONTENT_TYPE,
527                    }                            content_type, 1);
528          }        if (ret)
         mime->flags |= MIME_ADDED_CT;  
         return ret;  
 }  
   
 #define ADD_CHAR(buf, c, offset, buflen, nbytes) {*(buf)++ = c; (offset)++; (nbytes)++;if (--(buflen) == 0) return 0;}  
   
 static int  
 _mime_body_read(stream_t stream, char *buf, size_t buflen, off_t off, size_t *nbytes)  
 {  
         body_t          body = stream_get_owner(stream);  
         message_t       msg = body_get_owner(body);  
         mime_t          mime = message_get_owner(msg);  
         int             ret = 0;  
         size_t          part_nbytes = 0;  
         stream_t        msg_stream = NULL;  
   
         if ( mime->nmtp_parts == 0 )  
                 return EINVAL;  
   
         if ( off == 0 ) {                       /* reset message */  
                 mime->cur_offset = 0;  
                 mime->cur_part = 0;  
                 mime->part_offset = 0;  
   
                 if ( mime->nmtp_parts > 1 )  
                         mime->flags |= MIME_INSERT_BOUNDARY;  
         }  
   
         if ( off != mime->cur_offset )  
                 return ESPIPE;  
   
         if ( nbytes )  
                 *nbytes = 0;  
   
         if ( ( ret = _mime_set_content_type(mime) ) == 0 ) {  
                 do {  
                         if ( mime->nmtp_parts > 1 ) {  
                                 int len;  
                                 if ( mime->flags & MIME_INSERT_BOUNDARY ) {  
                                         if ( ( mime->flags & MIME_ADDING_BOUNDARY ) == 0 ) {  
                                                 mime->boundary_len = strlen(mime->boundary);  
                                                 mime->preamble = 2;  
                                                 if ( mime->cur_part == mime->nmtp_parts )  
                                                         mime->postamble = 2;  
                                                 mime->flags |= MIME_ADDING_BOUNDARY;  
                                         }  
                                         while(mime->preamble) {  
                                                 mime->preamble--;  
                                                 ADD_CHAR(buf, '-', mime->cur_offset, buflen, *nbytes);  
                                         }  
                                         len = strlen(mime->boundary) - mime->boundary_len;  
                                         while(mime->boundary_len) {  
                                                 mime->boundary_len--;  
                                                 ADD_CHAR(buf, mime->boundary[len++], mime->cur_offset, buflen, *nbytes);  
                                         }  
                                         while(mime->postamble) {  
                                                 mime->postamble--;  
                                                 ADD_CHAR(buf, '-', mime->cur_offset, buflen, *nbytes);  
                                         }  
                                         mime->flags &= ~(MIME_INSERT_BOUNDARY|MIME_ADDING_BOUNDARY);  
                                         mime->part_offset = 0;  
                                         ADD_CHAR(buf, '\n',mime->cur_offset, buflen, *nbytes);  
                                 }  
                                 if ( mime->cur_part >= mime->nmtp_parts )  
                                    return 0;  
                                 message_get_stream(mime->mtp_parts[mime->cur_part]->msg, &msg_stream);  
                         } else {  
                                 body_t part_body;  
   
                                 if ( mime->cur_part >= mime->nmtp_parts )  
                                    return 0;  
                                 message_get_body(mime->mtp_parts[mime->cur_part]->msg, &part_body);  
                                 body_get_stream(part_body, &msg_stream);  
                         }  
                         ret = stream_read(msg_stream, buf, buflen, mime->part_offset, &part_nbytes );  
                         if ( part_nbytes ) {  
                                 mime->part_offset += part_nbytes;  
                                 mime->cur_offset += part_nbytes;  
                                 if ( nbytes )  
                                         *nbytes += part_nbytes;  
                         }  
                         if ( ret == 0 && part_nbytes == 0 ) {  
                                 mime->flags |= MIME_INSERT_BOUNDARY;  
                                 mime->cur_part++;  
                                 ADD_CHAR(buf, '\n', mime->cur_offset, buflen, *nbytes);  
                         }  
                 } while( ret == 0 && part_nbytes == 0 && mime->cur_part <= mime->nmtp_parts );  
         }  
529          return ret;          return ret;
 }  
   
 static int  
 _mime_body_fd(stream_t stream, int *fd)  
 {  
         body_t          body = stream_get_owner(stream);  
         message_t       msg = body_get_owner(body);  
         mime_t          mime = message_get_owner(msg);  
         stream_t        msg_stream = NULL;  
530    
531          if ( mime->nmtp_parts == 0 || mime->cur_offset == 0 )        /* if the only part contains a transfer-encoding
532                  return EINVAL;           field, set it on the message header too */
533          message_get_stream(mime->mtp_parts[mime->cur_part]->msg, &msg_stream);        if (hdr &&
534          return stream_get_fd(msg_stream, fd);            header_aget_value (hdr,
535                                 MU_HEADER_CONTENT_TRANSFER_ENCODING,
536                                 &content_te) == 0)
537            {
538              ret = header_set_value (mime->hdrs,
539                                      MU_HEADER_CONTENT_TRANSFER_ENCODING,
540                                      content_te, 1);
541              free (content_te);
542            }
543        }
544      mime->flags |= MIME_ADDED_CT;
545      return ret;
546  }  }
547    
548  static int  #define ADD_CHAR(buf, c, offset, buflen, nbytes) {*(buf)++ = c; (offset)++; (nbytes)++;if (--(buflen) == 0) return 0;}
 _mime_body_size (body_t body, size_t *psize)  
 {  
         message_t       msg = body_get_owner(body);  
         mime_t          mime = message_get_owner(msg);  
         int             i, ret;  
         size_t          size;  
   
         if ( mime->nmtp_parts == 0 )  
                 return EINVAL;  
   
         if ( (ret = _mime_set_content_type(mime) ) != 0 )  
                 return ret;  
         for ( i=0;i<mime->nmtp_parts;i++ ) {  
                 message_size(mime->mtp_parts[i]->msg, &size);  
                 *psize+=size;  
                 if ( mime->nmtp_parts > 1 )             /* boundary line */  
                         *psize+= strlen(mime->boundary) + 3;  
         }  
         if ( mime->nmtp_parts > 1 )             /* ending boundary line */  
                 *psize+= 2;  
   
         return 0;  
 }  
549    
550  static int  static int
551  _mime_body_lines (body_t body, size_t *plines)  _mime_body_read (stream_t stream, char *buf, size_t buflen, off_t off,
552                     size_t * nbytes)
553  {  {
554          message_t       msg = body_get_owner(body);    body_t body = stream_get_owner (stream);
555          mime_t          mime = message_get_owner(msg);    message_t msg = body_get_owner (body);
556          int             i, ret;    mime_t mime = message_get_owner (msg);
557          size_t          lines;    int ret = 0;
558      size_t part_nbytes = 0;
559          if ( mime->nmtp_parts == 0 )    stream_t msg_stream = NULL;
560                  return EINVAL;  
561      if (mime->nmtp_parts == 0)
562          if ( (ret = _mime_set_content_type(mime) ) != 0 )      return EINVAL;
563                  return ret;  
564          for ( i = 0; i < mime->nmtp_parts; i++ ) {    if (off == 0)
565                  message_lines(mime->mtp_parts[i]->msg, &lines);      {                           /* reset message */
566                  plines+=lines;        mime->cur_offset = 0;
567                  if ( mime->nmtp_parts > 1 )             /* boundary line */        mime->cur_part = 0;
568                          plines++;        mime->part_offset = 0;
569          }  
570          return 0;        if (mime->nmtp_parts > 1)
571            mime->flags |= MIME_INSERT_BOUNDARY;
572        }
573    
574      if (off != mime->cur_offset)
575        return ESPIPE;
576    
577      if (nbytes)
578        *nbytes = 0;
579    
580      if ((ret = _mime_set_content_type (mime)) == 0)
581        {
582          do
583            {
584              if (mime->nmtp_parts > 1)
585                {
586                  int len;
587                  if (mime->flags & MIME_INSERT_BOUNDARY)
588                    {
589                      if ((mime->flags & MIME_ADDING_BOUNDARY) == 0)
590                        {
591                          mime->boundary_len = strlen (mime->boundary);
592                          mime->preamble = 2;
593                          if (mime->cur_part == mime->nmtp_parts)
594                            mime->postamble = 2;
595                          mime->flags |= MIME_ADDING_BOUNDARY;
596                        }
597                      while (mime->preamble)
598                        {
599                          mime->preamble--;
600                          ADD_CHAR (buf, '-', mime->cur_offset, buflen, *nbytes);
601                        }
602                      len = strlen (mime->boundary) - mime->boundary_len;
603                      while (mime->boundary_len)
604                        {
605                          mime->boundary_len--;
606                          ADD_CHAR (buf,
607                                    mime->
608                                    boundary
609                                    [len++], mime->cur_offset, buflen, *nbytes);
610                        }
611                      while (mime->postamble)
612                        {
613                          mime->postamble--;
614                          ADD_CHAR (buf, '-', mime->cur_offset, buflen, *nbytes);
615                        }
616                      mime->flags &=
617                        ~(MIME_INSERT_BOUNDARY | MIME_ADDING_BOUNDARY);
618                      mime->part_offset = 0;
619                      ADD_CHAR (buf, '\n', mime->cur_offset, buflen, *nbytes);
620                    }
621                  if (mime->cur_part >= mime->nmtp_parts)
622                    return 0;
623                  message_get_stream (mime->mtp_parts[mime->cur_part]->msg,
624                                      &msg_stream);
625                }
626              else
627                {
628                  body_t part_body;
629    
630                  if (mime->cur_part >= mime->nmtp_parts)
631                    return 0;
632                  message_get_body (mime->mtp_parts[mime->cur_part]->msg,
633                                    &part_body);
634                  body_get_stream (part_body, &msg_stream);
635                }
636              ret =
637                stream_read (msg_stream, buf, buflen,
638                             mime->part_offset, &part_nbytes);
639              if (part_nbytes)
640                {
641                  mime->part_offset += part_nbytes;
642                  mime->cur_offset += part_nbytes;
643                  if (nbytes)
644                    *nbytes += part_nbytes;
645                }
646              if (ret == 0 && part_nbytes == 0)
647                {
648                  mime->flags |= MIME_INSERT_BOUNDARY;
649                  mime->cur_part++;
650                  ADD_CHAR (buf, '\n', mime->cur_offset, buflen, *nbytes);
651                }
652            }
653          while (ret == 0 && part_nbytes == 0
654                 && mime->cur_part <= mime->nmtp_parts);
655        }
656      return ret;
657    }
658    
659    static int
660    _mime_body_fd (stream_t stream, int *fd)
661    {
662      body_t body = stream_get_owner (stream);
663      message_t msg = body_get_owner (body);
664      mime_t mime = message_get_owner (msg);
665      stream_t msg_stream = NULL;
666    
667      if (mime->nmtp_parts == 0 || mime->cur_offset == 0)
668        return EINVAL;
669      message_get_stream (mime->mtp_parts[mime->cur_part]->msg, &msg_stream);
670      return stream_get_fd (msg_stream, fd);
671    }
672    
673    static int
674    _mime_body_size (body_t body, size_t * psize)
675    {
676      message_t msg = body_get_owner (body);
677      mime_t mime = message_get_owner (msg);
678      int i, ret;
679      size_t size;
680    
681      if (mime->nmtp_parts == 0)
682        return EINVAL;
683    
684      if ((ret = _mime_set_content_type (mime)) != 0)
685        return ret;
686      for (i = 0; i < mime->nmtp_parts; i++)
687        {
688          message_size (mime->mtp_parts[i]->msg, &size);
689          *psize += size;
690          if (mime->nmtp_parts > 1) /* boundary line */
691            *psize += strlen (mime->boundary) + 3;
692        }
693      if (mime->nmtp_parts > 1)     /* ending boundary line */
694        *psize += 2;
695    
696      return 0;
697    }
698    
699    static int
700    _mime_body_lines (body_t body, size_t * plines)
701    {
702      message_t msg = body_get_owner (body);
703      mime_t mime = message_get_owner (msg);
704      int i, ret;
705      size_t lines;
706    
707      if (mime->nmtp_parts == 0)
708        return EINVAL;
709    
710      if ((ret = _mime_set_content_type (mime)) != 0)
711        return ret;
712      for (i = 0; i < mime->nmtp_parts; i++)
713        {
714          message_lines (mime->mtp_parts[i]->msg, &lines);
715          plines += lines;
716          if (mime->nmtp_parts > 1) /* boundary line */
717            plines++;
718        }
719      return 0;
720  }  }
721    
722  int  int
723  mime_create(mime_t *pmime, message_t msg, int flags)  mime_create (mime_t * pmime, message_t msg, int flags)
724  {  {
725          mime_t  mime = NULL;    mime_t mime = NULL;
726          int     ret = 0;    int ret = 0;
727          size_t  size;    size_t size;
728          body_t  body;    body_t body;
729    
730          if (pmime == NULL)    if (pmime == NULL)
731                  return EINVAL;      return EINVAL;
732          *pmime = NULL;    *pmime = NULL;
733          if ( ( mime = calloc(1, sizeof (*mime)) ) == NULL )    if ((mime = calloc (1, sizeof (*mime))) == NULL)
734                  return ENOMEM;      return ENOMEM;
735          if ( msg )  {    if (msg)
736                  if ( ( ret = message_get_header(msg, &(mime->hdrs)) ) == 0 ) {      {
737                          if ( ( ret = header_get_value(mime->hdrs, MU_HEADER_CONTENT_TYPE, NULL, 0, &size) ) == 0 && size ) {        if ((ret = message_get_header (msg, &mime->hdrs)) == 0)
738                                  if ( ( mime->content_type = malloc(size+1) ) == NULL )          {
739                                          ret = ENOMEM;            if ((ret =
740                                  else if ( ( ret = header_get_value(mime->hdrs, MU_HEADER_CONTENT_TYPE, mime->content_type, size+1, 0) ) == 0 )                 header_get_value (mime->hdrs,
741                                          _mime_munge_content_header(mime->content_type);                                   MU_HEADER_CONTENT_TYPE,
742                          } else {                                   NULL, 0, &size)) == 0 && size)
743                                  if (ret == ENOENT) {              {
744                                          ret = 0;                if ((mime->content_type = malloc (size + 1)) == NULL)
745                                          if ( ( mime->content_type = strdup("text/plain; charset=us-ascii") ) == NULL ) /* default as per spec. */                  ret = ENOMEM;
746                                                  ret = ENOMEM;                else if ((ret =
747                                  }                          header_get_value (mime->hdrs,
748                          }                                            MU_HEADER_CONTENT_TYPE,
749                          if  (ret == 0 ) {                                            mime->content_type,
750                                  mime->msg = msg;                                            size + 1, 0)) == 0)
751                                  mime->buf_size = MIME_DFLT_BUF_SIZE;                  _mime_munge_content_header (mime->content_type);
752                                  message_get_body(msg, &body);              }
753                                  body_get_stream(body, &(mime->stream));            else
754                          }              {
755                  }                if (ret == ENOENT)
756          }                  {
757          else {                    ret = 0;
758                  mime->flags |= MIME_NEW_MESSAGE | MIME_MULTIPART_MIXED;                    if ((mime->content_type =
759          }                         strdup ("text/plain; charset=us-ascii")) == NULL)
760          if ( ret != 0 ) {                      /* default as per spec. */
761                  if ( mime->content_type )                      ret = ENOMEM;
762                          free(mime->content_type);                  }
763                  free(mime);              }
764          }            if (ret == 0)
765          else {              {
766                  mime->flags |= (flags & MIME_FLAG_MASK);                mime->msg = msg;
767                  *pmime = mime;                mime->buf_size = MIME_DFLT_BUF_SIZE;
768          }                message_get_body (msg, &body);
769          return ret;                body_get_stream (body, &(mime->stream));
770                }
771            }
772        }
773      else
774        {
775          mime->flags |= MIME_NEW_MESSAGE | MIME_MULTIPART_MIXED;
776        }
777      if (ret != 0)
778        {
779          if (mime->content_type)
780            free (mime->content_type);
781          free (mime);
782        }
783      else
784        {
785          mime->flags |= (flags & MIME_FLAG_MASK);
786          *pmime = mime;
787        }
788      return ret;
789  }  }
790    
791  void  void
792  mime_destroy(mime_t *pmime)  mime_destroy (mime_t * pmime)
793  {  {
794          mime_t mime;    mime_t mime;
795          struct _mime_part *mime_part;    struct _mime_part *mime_part;
796          int i;    int i;
797    
798          if (pmime && *pmime) {    if (pmime && *pmime)
799                  mime = *pmime;      {
800                  if ( mime->mtp_parts != NULL ) {        mime = *pmime;
801                          for ( i = 0; i < mime->nmtp_parts; i++ ) {        if (mime->mtp_parts != NULL)
802                                  mime_part = mime->mtp_parts[i];          {
803                                  if ( mime_part->msg && mime->flags & MIME_NEW_MESSAGE )            for (i = 0; i < mime->nmtp_parts; i++)
804                                          message_unref(mime_part->msg);              {
805                                  else                mime_part = mime->mtp_parts[i];
806                                          message_destroy(&mime_part->msg, mime_part);                if (mime_part->msg && mime->flags & MIME_NEW_MESSAGE)
807                                  free (mime_part);                  message_unref (mime_part->msg);
808                          }                else
809                          free (mime->mtp_parts);                  message_destroy (&mime_part->msg, mime_part);
810                  }                free (mime_part);
811                  if ( mime->msg && mime->flags & MIME_NEW_MESSAGE )              }
812                          message_destroy(&mime->msg, mime);            free (mime->mtp_parts);
813                  if ( mime->content_type )          }
814                          free(mime->content_type);        if (mime->msg && mime->flags & MIME_NEW_MESSAGE)
815                  if ( mime->cur_buf )          message_destroy (&mime->msg, mime);
816                          free(mime->cur_buf);        if (mime->content_type)
817                  if ( mime->cur_line )          free (mime->content_type);
818                          free(mime->cur_line);        if (mime->cur_buf)
819                  if ( mime->boundary )          free (mime->cur_buf);
820                          free(mime->boundary);        if (mime->cur_line)
821                  if ( mime->header_buf )          free (mime->cur_line);
822                          free(mime->header_buf);        if (mime->boundary)
823                  free (mime);          free (mime->boundary);
824                  *pmime = NULL;        if (mime->header_buf)
825          }          free (mime->header_buf);
826          free (mime);
827          *pmime = NULL;
828        }
829  }  }
830    
831  int  int
832  mime_get_part(mime_t mime, size_t part, message_t *msg)  mime_get_part (mime_t mime, size_t part, message_t * msg)
833  {  {
834          size_t                          nmtp_parts;    size_t nmtp_parts;
835          int                                     ret = 0, flags = 0;    int ret = 0, flags = 0;
836          stream_t                        stream;    stream_t stream;
837          body_t                          body;    body_t body;
838          struct _mime_part       *mime_part;    struct _mime_part *mime_part;
839    
840          if ( ( ret = mime_get_num_parts(mime, &nmtp_parts ) ) == 0 ) {    if ((ret = mime_get_num_parts (mime, &nmtp_parts)) == 0)
841                  if ( part < 1 || part > nmtp_parts )      {
842                          return EINVAL;        if (part < 1 || part > nmtp_parts)
843                  if ( nmtp_parts == 1 && mime->mtp_parts == NULL )          return EINVAL;
844                          *msg = mime->msg;        if (nmtp_parts == 1 && mime->mtp_parts == NULL)
845                  else {          *msg = mime->msg;
846                          mime_part = mime->mtp_parts[part-1];        else
847                          if ( !mime_part->body_created && ( ret = body_create(&body, mime_part->msg) ) == 0 ) {          {
848                                  body_set_size (body, _mimepart_body_size, mime_part->msg);            mime_part = mime->mtp_parts[part - 1];
849                                  body_set_lines (body, _mimepart_body_lines, mime_part->msg);            if (!mime_part->body_created
850                                  stream_get_flags(mime->stream, &flags);                && (ret = body_create (&body, mime_part->msg)) == 0)
851                                  if ( ( ret = stream_create(&stream, MU_STREAM_READ | (flags & (MU_STREAM_SEEKABLE|MU_STREAM_NONBLOCK)), body) ) == 0 ) {              {
852                                          stream_set_read(stream, _mimepart_body_read, body);                body_set_size (body, _mimepart_body_size, mime_part->msg);
853                                          stream_set_fd(stream, _mimepart_body_fd, body);                body_set_lines (body, _mimepart_body_lines, mime_part->msg);
854                                          body_set_stream(body, stream, mime_part->msg);                stream_get_flags (mime->stream, &flags);
855                                          message_set_body(mime_part->msg, body, mime_part);                if ((ret =
856                                          mime_part->body_created = 1;                     stream_create (&stream,
857                                  }                                    MU_STREAM_READ | (flags &
858                          }                                                      (MU_STREAM_SEEKABLE
859                     *msg = mime_part->msg;                                                       | MU_STREAM_NONBLOCK)),
860                                      body)) == 0)
861                    {
862                      stream_set_read (stream, _mimepart_body_read, body);
863                      stream_set_fd (stream, _mimepart_body_fd, body);
864                      body_set_stream (body, stream, mime_part->msg);
865                      message_set_body (mime_part->msg, body, mime_part);
866                      mime_part->body_created = 1;
867                  }                  }
868                }
869              *msg = mime_part->msg;
870          }          }
871          return ret;      }
872      return ret;
873  }  }
874    
875  int  int
876  mime_get_num_parts(mime_t mime, size_t *nmtp_parts)  mime_get_num_parts (mime_t mime, size_t * nmtp_parts)
877  {  {
878          int             ret = 0;    int ret = 0;
879    
880          if ( mime->nmtp_parts == 0 || mime->flags & MIME_PARSER_ACTIVE ) {    if (mime->nmtp_parts == 0 || mime->flags & MIME_PARSER_ACTIVE)
881                  if ( mime_is_multipart(mime) ) {      {
882                          if ( ( ret = _mime_parse_mpart_message(mime) ) != 0 )        if (mime_is_multipart (mime))
883                                  return(ret);          {
884                  } else            if ((ret = _mime_parse_mpart_message (mime)) != 0)
885                          mime->nmtp_parts = 1;              return (ret);
886          }          }
887          *nmtp_parts = mime->nmtp_parts;        else
888          return(ret);          mime->nmtp_parts = 1;
889        }
890      *nmtp_parts = mime->nmtp_parts;
891      return (ret);
892    
893  }  }
894    
895  int  int
896  mime_add_part(mime_t mime, message_t msg)  mime_add_part (mime_t mime, message_t msg)
897  {  {
898          int ret;    int ret;
899    
900          if ( mime == NULL || msg == NULL || ( mime->flags & MIME_NEW_MESSAGE ) == 0 )    if (mime == NULL || msg == NULL || (mime->flags & MIME_NEW_MESSAGE) == 0)
901                  return EINVAL;      return EINVAL;
902          if ( ( ret = _mime_append_part(mime, msg, 0, 0, 0) ) == 0 )    if ((ret = _mime_append_part (mime, msg, 0, 0, 0)) == 0)
903                  ret = _mime_set_content_type(mime);      ret = _mime_set_content_type (mime);
904          return ret;    return ret;
905  }  }
906    
907  int  int
908  mime_get_message(mime_t mime, message_t *msg)  mime_get_message (mime_t mime, message_t * msg)
909  {  {
910          stream_t body_stream;    stream_t body_stream;
911          body_t  body;    body_t body;
912          int ret = 0;    int ret = 0;
913    
914          if ( mime == NULL || msg == NULL )    if (mime == NULL || msg == NULL)
915                  return EINVAL;      return EINVAL;
916          if ( mime->msg == NULL ) {    if (mime->msg == NULL)
917                  if ( ( mime->flags & MIME_NEW_MESSAGE ) == 0 )      {
918                          return EINVAL;        if ((mime->flags & MIME_NEW_MESSAGE) == 0)
919                  if ( ( ret = message_create(&(mime->msg), mime) ) == 0 ) {          return EINVAL;
920                          if ( ( ret = header_create(&(mime->hdrs), NULL, 0, mime->msg) ) == 0 ) {        if ((ret = message_create (&mime->msg, mime)) == 0)
921                                  message_set_header(mime->msg, mime->hdrs, mime);          {
922                                  header_set_value(mime->hdrs, MU_HEADER_MIME_VERSION, "1.0", 0);            if ((ret = header_create (&mime->hdrs, NULL, 0, mime->msg)) == 0)
923                                  if ( ( ret = _mime_set_content_type(mime) ) == 0 )  {              {
924                                          if ( ( ret = body_create(&body, mime->msg) ) == 0 ) {                message_set_header (mime->msg, mime->hdrs, mime);
925                                                  message_set_body(mime->msg, body, mime);                header_set_value (mime->hdrs, MU_HEADER_MIME_VERSION, "1.0", 0);
926                                                  body_set_size (body, _mime_body_size, mime->msg);                if ((ret = _mime_set_content_type (mime)) == 0)
927                                                  body_set_lines (body, _mime_body_lines, mime->msg);                  {
928                                                  if ( ( ret = stream_create(&body_stream, MU_STREAM_READ, body) ) == 0 ) {                    if ((ret = body_create (&body, mime->msg)) == 0)
929                                                          stream_set_read(body_stream, _mime_body_read, body);                      {
930                                                          stream_set_fd(body_stream, _mime_body_fd, body);                        message_set_body (mime->msg, body, mime);
931                                                          body_set_stream(body, body_stream, mime->msg);                        body_set_size (body, _mime_body_size, mime->msg);
932                                                          *msg = mime->msg;                        body_set_lines (body, _mime_body_lines, mime->msg);
933                                                          return 0;                        if ((ret =
934                                                  }                             stream_create (&body_stream, MU_STREAM_READ, body))
935                                          }                            == 0)
936                                  }                          {
937                          }                            stream_set_read (body_stream, _mime_body_read, body);
938                          message_destroy(&(mime->msg), mime);                            stream_set_fd (body_stream, _mime_body_fd, body);
939                          mime->msg = NULL;                            body_set_stream (body, body_stream, mime->msg);
940                  }                            *msg = mime->msg;
941          }                            return 0;
942          if ( ret == 0 )                          }
943                  *msg = mime->msg;                      }
944          return ret;                  }
945                }
946              message_destroy (&mime->msg, mime);
947              mime->msg = NULL;
948            }
949        }
950      if (ret == 0)
951        *msg = mime->msg;
952      return ret;
953  }  }
954    
955  int  int
956  mime_is_multipart(mime_t mime)  mime_is_multipart (mime_t mime)
957  {  {
958          if ( mime->content_type )    if (mime->content_type)
959                  return(strncasecmp("multipart", mime->content_type, strlen("multipart")) ? 0: 1);      return (strncasecmp ("multipart", mime->content_type,
960          return 0;                           strlen ("multipart")) ? 0 : 1);
961      return 0;
962  }  }

Legend:
Removed from v.1.34  
changed lines
  Added in v.1.35

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26