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 <hurtta+elm@posti.FMI.FI>
* (was hurtta+elm@ozone.FMI.FI)
*
* Based on mime_parse.c, which is initially
* written by: Michael Elkins <elkins@aero.org>, 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:
*/
syntax highlighted by Code2HTML, v. 0.9.1