/* $Source: /v/ossp/cvs/ossp-pkg/petidomo/librfc822/decomment.c,v $ $Revision: 1.4 $ Copyright (C) 2000 by CyberSolutions GmbH, Germany. This file is part of OpenPetidomo. OpenPetidomo is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. OpenPetidomo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #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 0; } /* 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 (*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; }