Index: ossp-pkg/petidomo/librfc822/decomment.c RCS File: /v/ossp/cvs/ossp-pkg/petidomo/librfc822/decomment.c,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/petidomo/librfc822/decomment.c,v' | diff -u /dev/null - -L'ossp-pkg/petidomo/librfc822/decomment.c' 2>/dev/null --- ossp-pkg/petidomo/librfc822/decomment.c +++ - 2026-03-29 10:14:48.542677879 +0200 @@ -0,0 +1,217 @@ +/* + * $Source$ + * $Revision$ + * $Date$ + * + * Copyright (C) 1997 by CyberSolutions GmbH. + * All rights reserved. + */ + +#include +#include +#include +#include +#ifdef DEBUG_DMALLOC +# include +#endif + +#include "rfc822.h" + +static const char * +read_until_next_quote(const char * p) +{ + while (*p) { + if (*p == '"') { + break; + } + if (*p == '\\' && p[1] != '\0') { + p += 2; + continue; + } + p++; + } + return p; +} + +static const char * +read_until_close_bracket(const char * p) +{ + while (*p) { + if (*p == ')') { + break; + } + if (*p == '(') { + p = read_until_close_bracket(p+1); + if (*p == '\0') + break; + else { + p++; + continue; + } + } + else if (*p == '\\' && p[1] != '\0') { + p += 2; + continue; + } + else if (*p == '"') { + p = read_until_next_quote(p+1); + if (*p == '\0') + break; + else { + p++; + continue; + } + } + p++; + } + return p; +} + +/* remove all comments from an rfc822 address + + This routine takes as argument an address string conforming to the + RFC822 syntax and removes all comments from it, returning the + result in the pointer specified as second argument. + + This is very useful if you want to parse the address with a context + free grammer parser, like yacc, because recognizing the various + forms of commenting with a BNF grammar is very complicated. + + RETURNS: The routine returns an integer describing whether the + decommenting process succeeded or not. In case of an error, the + return code described the reason for failure. + + RFC822_OK: Success. + + RFC822_FATAL_ERROR: A fatal system error occured, like malloc() + failed. The global errno variable will be set accordingly. + + RFC822_UNCLOSED_COMMENT: A "(comment)"-like expression was not + closed properly. + + RFC822_UNMATCHED_CLOSE_BRACKET: A close bracket (")") was + encountered outside the comment context. + + RFC822_UNCLOSED_QUOTE: A quoted `"string"'-like expression was not + closed properly. + + RFC822_UNCLOSED_ANGEL_BRACKET: An "
"-like expression was + not closed properly. + + RFC822_NESTED_ANGEL_BRACKET: An open angel bracket ("<") was + encountered inside the "
" context. + + RFC822_UNMATCHED_CLOSE_ANGEL_BRACKET: A close angel bracket (">") was + encountered outside the "
" context. + + RFC822_SYNTAX_ERROR: The address does not follow the rfc822 syntax. + + NOTE: The returned by rfc822_decomment() has been allocated with + malloc(3) and should be freed when not needed anymore. + + AUTHOR: Peter Simons + + */ + +int +rfc822_decomment(const char * source /* String containing a formatted rfc822 address. */, + char ** destination /* Location where to store the parsed string. */) +{ + char * buffer, + * address_start, + * p; + const char * s; + int in_quote, + angel_bracket_count; + + + /* Sanity checks. */ + + assert(source != NULL); + if (!source || *source == '\0') { + errno = EINVAL; + return NULL; + } + + /* Allocate buffer. */ + + buffer = malloc(strlen(source)+1); + if (buffer == NULL) { + errno = ENOMEM; + return RFC822_FATAL_ERROR; + } + + /* Let's parse it. */ + + address_start = p = buffer; + s = source; + in_quote = 0; + angel_bracket_count = 0; + + while(*s) { + + if (*s == '"') { + in_quote = !in_quote; + } + else if (!in_quote && *s == '(') { + s = read_until_close_bracket(s+1); + if (*s == '\0') { + free(buffer); + return RFC822_UNCLOSED_COMMENT; + } + s++; + *p++ = ' '; + continue; + } + else if (!in_quote && *s == ')') { + free(buffer); + return RFC822_UNMATCHED_CLOSE_BRACKET; + } + else if (!in_quote && *s == '<') { + if (angel_bracket_count > 0) { + free(buffer); + return RFC822_NESTED_ANGEL_BRACKET; + } + s++; + p = address_start; + *p = '\0'; + angel_bracket_count++; + continue; + } + else if (!in_quote && *s == '>') { + if (angel_bracket_count == 0) { + free(buffer); + return RFC822_UNMATCHED_CLOSE_ANGEL_BRACKET; + } + *p = '\0'; + angel_bracket_count--; + break; + } + else if (!in_quote && *s == '\\') { + if (s[1] != '\0') { + *p++ = *s++; + } + else { + free(buffer); + return RFC822_SYNTAX_ERROR; + } + } + + + *p++ = *s++; + } + *p = '\0'; + if (in_quote) { + free(buffer); + return RFC822_UNCLOSED_QUOTE; + } + + if (angel_bracket_count > 0) { + free(buffer); + return RFC822_UNCLOSED_ANGEL_BRACKET; + } + + + *destination = buffer; + return RFC822_OK; +}