static char rcsid[] = "@(#)$Id: mparse.c,v 1.3 2006/04/09 07:37:08 hurtta Exp $"; /****************************************************************************** * The Elm (ME+) Mail System - $Revision: 1.3 $ $State: Exp $ * * Author: Kari Hurtta * (was hurtta+elm@ozone.FMI.FI) * * Based on mime_parse.c, which is initially * written by: Michael Elkins , 1995 * Based on parse_util.c (rfc822_reap_comments) *****************************************************************************/ #include "headers.h" DEBUG_VAR(Debug,__FILE__,"config"); char * mime_parse_content_opts (str, walk) char *str; char **walk; { /* A routine for parsing the options in a Content-Type: - like field. * The important point here is to skip the semi-colon if it appears * inside of quotes. This works sort of like strtok, except that * the token is already known. */ char *ptr = *walk; char *ret; int in_quote = 0; /* This is the initialization call */ if (str) { DPRINT(Debug,20,(&Debug, "mime_parse_content_opts: string=%s\n", str)); ptr = str; } /* skip leading spaces */ while (*ptr && isascii(*ptr) && isspace (*ptr)) ptr++; if (*ptr == '\0') { DPRINT(Debug,20,(&Debug, "mime_parse_content_opts=NULL: EOS\n")); *walk = ptr; return NULL; } ret = ptr; while (*ptr) { if (*ptr == '\\' && in_quote) { /* \ escapes next character * (not allowed outside of quotes) */ ptr++; if (*ptr == '\0') break; } else if (*ptr == '\"') { if (in_quote) in_quote = 0; else in_quote = 1; } else if (! in_quote) { if (*ptr == ';') { *ptr++ = '\0'; DPRINT(Debug,20,(&Debug, "mime_parse_content_opts=%s (token)\n", ret)); *walk = ptr; return (ret); } } ptr++; } DPRINT(Debug,20,(&Debug, "mime_parse_content_opts=%s (token)\n", ret)); *walk = ptr; return (ret); } /* Used to get charset argument */ int mime_get_param (name, value, opts, size) char *value; CONST char *opts, *name; int size; { char *c, tmp[VERY_LONG_STRING]; int i = 0, quoted = FALSE, found = FALSE; char * WALK = NULL; value[0] = '\0'; if (!opts) { DPRINT(Debug,20,(&Debug, "mime_get_param: name=\"%s\", opts=NULL\n", name)); return 0; } DPRINT(Debug,20,(&Debug, "mime_get_param: name=\"%s\", opts=\"%s\"\n", name,opts)); /* Make sure not to harm opts */ strfcpy (tmp, opts, sizeof (tmp)); rfc822_reap_comments (tmp, NULL, 0); c = tmp; while ((c = mime_parse_content_opts (c, &WALK)) != NULL && !found) { char * d = strchr(c,'='); char * d2 = d; if (!d) { c = NULL; continue; /* bad paramater */ } while (d2 > c && (whitespace (*(d2-1)))) d2--; *d2 = '\0'; while (*c && whitespace(*c)) c++; if (istrcmp (c, name) == 0) { found = TRUE; c = d+1; while (*c && whitespace(*c)) c++; if (*c == '"') { c++; quoted = TRUE; } /* Either look for a trailing quoted (if quoted==TRUE) or a SPACE */ while (*c && ((quoted && *c != '"') || (!quoted && *c != ' '))) { if (*c == '\\' && quoted) { /* \ escapes next character */ c++; if (!*c) break; } if (i >= size-1) break; /* Avoid buffer overflow */ value[i++] = *c++; } value[i] = '\0'; break; } c = NULL; } DPRINT(Debug,20,(&Debug, "mime_get_param: found=%d, value=%s\n",found,value)); return found; } /* Removes comments from string */ void rfc822_reap_comments (ptr, comments, size) char *ptr, *comments; int size; { char *w_ptr = ptr, *c_ptr = comments; int comment_level = 0, saved_level = 0; int in_quote = 0; while (*ptr) { if (*ptr == '\\' && (in_quote || comment_level > 0)) { /* \ escapes next character * (not allowed outside of quotes or comments) */ ptr++; if (*ptr == '\0') break; if (comment_level > 0 && comments) { if (c_ptr < comments + size - saved_level -3) { *c_ptr++ = '\\'; *c_ptr++ = *ptr; } } if (comment_level == 0) { *w_ptr++ = '\\'; *w_ptr++ = *ptr; } ptr++; continue; } else if (comment_level > 0) { if (*ptr == ')') comment_level --; if (*ptr == '(') comment_level ++; if (comments && c_ptr < comments + size - saved_level -3) { *c_ptr++ = *ptr; saved_level = comment_level; } } else if (*ptr == '\"') { if (in_quote) in_quote = 0; else in_quote = 1; } else if (!in_quote && *ptr == '(') { comment_level ++; if (comments && c_ptr < comments + size - saved_level -4) { if (c_ptr != comments) *c_ptr++ = ' '; *c_ptr++ = *ptr; saved_level = comment_level; } *w_ptr++ = ' '; /* RFC 822 (STD 11) says that comments represents one space */ } if (comment_level == 0 && (in_quote || *ptr != ')')) *w_ptr++ = *ptr; ptr++; } while (comments && saved_level > 0) { *c_ptr++ = ')'; saved_level--; } if (comments) *c_ptr = '\0'; *w_ptr = '\0'; } /* * Local Variables: * mode:c * c-basic-offset:4 * buffer-file-coding-system: iso-8859-1 * End: */