1/*++ 2/* NAME 3/* mail_addr_crunch 3 4/* SUMMARY 5/* parse and canonicalize addresses, apply address extension 6/* SYNOPSIS 7/* #include <mail_addr_crunch.h> 8/* 9/* ARGV *mail_addr_crunch(string, extension) 10/* const char *string; 11/* const char *extension; 12/* DESCRIPTION 13/* mail_addr_crunch() parses a string with zero or more addresses, 14/* rewrites each address to canonical form, and optionally applies 15/* an address extension to each resulting address. Input and result 16/* are in external (quoted) format. The caller is expected to pass 17/* the result to argv_free(). 18/* 19/* Arguments: 20/* .IP string 21/* A string with zero or more addresses in RFC 822 (external) format. 22/* .IP extension 23/* A null pointer, or an address extension (including the recipient 24/* address delimiter) that is propagated to all result addresses. 25/* DIAGNOSTICS 26/* Fatal error: out of memory. 27/* SEE ALSO 28/* tok822_parse(3), address parser 29/* canon_addr(3), address canonicalization 30/* LICENSE 31/* .ad 32/* .fi 33/* The Secure Mailer license must be distributed with this software. 34/* AUTHOR(S) 35/* Wietse Venema 36/* IBM T.J. Watson Research 37/* P.O. Box 704 38/* Yorktown Heights, NY 10598, USA 39/*--*/ 40 41/* System library. */ 42 43#include <sys_defs.h> 44#include <string.h> 45 46/* Utility library. */ 47 48#include <mymalloc.h> 49#include <argv.h> 50#include <vstring.h> 51 52/* Global library. */ 53 54#include <tok822.h> 55#include <canon_addr.h> 56#include <mail_addr_crunch.h> 57 58/* mail_addr_crunch - break string into addresses, optionally add extension */ 59 60ARGV *mail_addr_crunch(const char *string, const char *extension) 61{ 62 VSTRING *extern_addr = vstring_alloc(100); 63 VSTRING *canon_addr = vstring_alloc(100); 64 ARGV *argv = argv_alloc(1); 65 TOK822 *tree; 66 TOK822 **addr_list; 67 TOK822 **tpp; 68 char *ratsign; 69 ssize_t extlen; 70 71 if (extension) 72 extlen = strlen(extension); 73 74#define STR(x) vstring_str(x) 75 76 /* 77 * Parse the string, rewrite each address to canonical form, and convert 78 * the result to external (quoted) form. Optionally apply the extension 79 * to each address found. 80 * 81 * XXX Workaround for the null address. This works for envelopes but 82 * produces ugly results for message headers. 83 */ 84 if (*string == 0 || strcmp(string, "<>") == 0) 85 string = "\"\""; 86 tree = tok822_parse(string); 87 addr_list = tok822_grep(tree, TOK822_ADDR); 88 for (tpp = addr_list; *tpp; tpp++) { 89 tok822_externalize(extern_addr, tpp[0]->head, TOK822_STR_DEFL); 90 canon_addr_external(canon_addr, STR(extern_addr)); 91 if (extension) { 92 VSTRING_SPACE(canon_addr, extlen + 1); 93 if ((ratsign = strrchr(STR(canon_addr), '@')) == 0) { 94 vstring_strcat(canon_addr, extension); 95 } else { 96 memmove(ratsign + extlen, ratsign, strlen(ratsign) + 1); 97 memcpy(ratsign, extension, extlen); 98 VSTRING_SKIP(canon_addr); 99 } 100 } 101 argv_add(argv, STR(canon_addr), ARGV_END); 102 } 103 argv_terminate(argv); 104 myfree((char *) addr_list); 105 tok822_free_tree(tree); 106 vstring_free(canon_addr); 107 vstring_free(extern_addr); 108 return (argv); 109} 110 111#ifdef TEST 112 113 /* 114 * Stand-alone test program, sort of interactive. 115 */ 116#include <stdlib.h> 117#include <unistd.h> 118#include <msg.h> 119#include <vstream.h> 120#include <vstring_vstream.h> 121#include <mail_conf.h> 122#include <mail_params.h> 123 124int main(int unused_argc, char **unused_argv) 125{ 126 VSTRING *extension = vstring_alloc(1); 127 VSTRING *buf = vstring_alloc(1); 128 ARGV *argv; 129 char **cpp; 130 131 mail_conf_read(); 132 if (chdir(var_queue_dir) < 0) 133 msg_fatal("chdir %s: %m", var_queue_dir); 134 135 vstream_printf("extension: (CR for none): "); 136 vstream_fflush(VSTREAM_OUT); 137 if (vstring_get_nonl(extension, VSTREAM_IN) == VSTREAM_EOF) 138 exit(0); 139 140 vstream_printf("print strings to be translated, one per line\n"); 141 vstream_fflush(VSTREAM_OUT); 142 while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF) { 143 argv = mail_addr_crunch(STR(buf), VSTRING_LEN(extension) ? STR(extension) : 0); 144 for (cpp = argv->argv; *cpp; cpp++) 145 vstream_printf(" %s\n", *cpp); 146 vstream_fflush(VSTREAM_OUT); 147 } 148 return (0); 149} 150 151#endif 152