1/* $NetBSD: strip_addr.c,v 1.4 2022/10/08 16:12:45 christos Exp $ */ 2 3/*++ 4/* NAME 5/* strip_addr 3 6/* SUMMARY 7/* strip extension from full or localpart-only address 8/* SYNOPSIS 9/* #include <strip_addr.h> 10/* 11/* char *strip_addr_internal(address, extension, delimiter_set) 12/* const char *address; 13/* char **extension; 14/* const char *delimiter_set; 15/* LEGACY SUPPORT 16/* char *strip_addr(address, extension, delimiter_set) 17/* const char *address; 18/* char **extension; 19/* const char *delimiter_set; 20/* DESCRIPTION 21/* strip_addr*() takes an address and either returns a null 22/* pointer when the address contains no address extension, 23/* or returns a copy of the address without address extension. 24/* The caller is expected to pass the copy to myfree(). 25/* 26/* With strip_addr_internal(), the input and result are in 27/* internal form. 28/* 29/* strip_addr() is a backwards-compatible form for legacy code. 30/* 31/* Arguments: 32/* .IP address 33/* Address localpart or user@domain form. 34/* .IP extension 35/* A null pointer, or the address of a pointer that is set to 36/* the address of a dynamic memory copy of the address extension 37/* that had to be chopped off. 38/* The copy includes the recipient address delimiter. 39/* The caller is expected to pass the copy to myfree(). 40/* .IP delimiter_set 41/* Set of recipient address delimiter characters. 42/* SEE ALSO 43/* split_addr(3) strip extension from localpart 44/* LICENSE 45/* .ad 46/* .fi 47/* The Secure Mailer license must be distributed with this software. 48/* AUTHOR(S) 49/* Wietse Venema 50/* IBM T.J. Watson Research 51/* P.O. Box 704 52/* Yorktown Heights, NY 10598, USA 53/* 54/* Wietse Venema 55/* Google, Inc. 56/* 111 8th Avenue 57/* New York, NY 10011, USA 58/*--*/ 59 60/* System library. */ 61 62#include <sys_defs.h> 63#include <string.h> 64 65/* Utility library. */ 66 67#include <mymalloc.h> 68 69/* Global library. */ 70 71#include <split_addr.h> 72#include <strip_addr.h> 73 74/* strip_addr - strip extension from address */ 75 76char *strip_addr_internal(const char *full, char **extension, 77 const char *delimiter_set) 78{ 79 char *ratsign; 80 char *extent; 81 char *saved_ext; 82 char *stripped; 83 84 /* 85 * A quick test to eliminate inputs without delimiter anywhere. 86 */ 87 if (*delimiter_set == 0 || full[strcspn(full, delimiter_set)] == 0) { 88 stripped = saved_ext = 0; 89 } else { 90 stripped = mystrdup(full); 91 if ((ratsign = strrchr(stripped, '@')) != 0) 92 *ratsign = 0; 93 if ((extent = split_addr(stripped, delimiter_set)) != 0) { 94 extent -= 1; 95 if (extension) { 96 *extent = full[strlen(stripped)]; 97 saved_ext = mystrdup(extent); 98 *extent = 0; 99 } else 100 saved_ext = 0; 101 if (ratsign != 0) { 102 *ratsign = '@'; 103 memmove(extent, ratsign, strlen(ratsign) + 1); 104 } 105 } else { 106 myfree(stripped); 107 stripped = saved_ext = 0; 108 } 109 } 110 if (extension) 111 *extension = saved_ext; 112 return (stripped); 113} 114 115#ifdef TEST 116 117#include <msg.h> 118#include <mail_params.h> 119 120int main(int unused_argc, char **unused_argv) 121{ 122 char *extension; 123 char *stripped; 124 char *delim = "+-"; 125 126#define NO_DELIM "" 127 128 /* 129 * No static initializer, because this is owned by a library. 130 */ 131 var_double_bounce_sender = DEF_DOUBLE_BOUNCE; 132 133 /* 134 * Incredible. This function takes only three arguments, and the tests 135 * already take more lines of code than the code being tested. 136 */ 137 stripped = strip_addr_internal("foo", (char **) 0, NO_DELIM); 138 if (stripped != 0) 139 msg_panic("strip_addr botch 1"); 140 141 stripped = strip_addr_internal("foo", &extension, NO_DELIM); 142 if (stripped != 0) 143 msg_panic("strip_addr botch 2"); 144 if (extension != 0) 145 msg_panic("strip_addr botch 3"); 146 147 stripped = strip_addr_internal("foo", (char **) 0, delim); 148 if (stripped != 0) 149 msg_panic("strip_addr botch 4"); 150 151 stripped = strip_addr_internal("foo", &extension, delim); 152 if (stripped != 0) 153 msg_panic("strip_addr botch 5"); 154 if (extension != 0) 155 msg_panic("strip_addr botch 6"); 156 157 stripped = strip_addr_internal("foo@bar", (char **) 0, NO_DELIM); 158 if (stripped != 0) 159 msg_panic("strip_addr botch 7"); 160 161 stripped = strip_addr_internal("foo@bar", &extension, NO_DELIM); 162 if (stripped != 0) 163 msg_panic("strip_addr botch 8"); 164 if (extension != 0) 165 msg_panic("strip_addr botch 9"); 166 167 stripped = strip_addr_internal("foo@bar", (char **) 0, delim); 168 if (stripped != 0) 169 msg_panic("strip_addr botch 10"); 170 171 stripped = strip_addr_internal("foo@bar", &extension, delim); 172 if (stripped != 0) 173 msg_panic("strip_addr botch 11"); 174 if (extension != 0) 175 msg_panic("strip_addr botch 12"); 176 177 stripped = strip_addr_internal("foo-ext", (char **) 0, NO_DELIM); 178 if (stripped != 0) 179 msg_panic("strip_addr botch 13"); 180 181 stripped = strip_addr_internal("foo-ext", &extension, NO_DELIM); 182 if (stripped != 0) 183 msg_panic("strip_addr botch 14"); 184 if (extension != 0) 185 msg_panic("strip_addr botch 15"); 186 187 stripped = strip_addr_internal("foo-ext", (char **) 0, delim); 188 if (stripped == 0) 189 msg_panic("strip_addr botch 16"); 190 msg_info("wanted: foo-ext -> %s", "foo"); 191 msg_info("strip_addr foo-ext -> %s", stripped); 192 myfree(stripped); 193 194 stripped = strip_addr_internal("foo-ext", &extension, delim); 195 if (stripped == 0) 196 msg_panic("strip_addr botch 17"); 197 if (extension == 0) 198 msg_panic("strip_addr botch 18"); 199 msg_info("wanted: foo-ext -> %s %s", "foo", "-ext"); 200 msg_info("strip_addr foo-ext -> %s %s", stripped, extension); 201 myfree(stripped); 202 myfree(extension); 203 204 stripped = strip_addr_internal("foo-ext@bar", (char **) 0, NO_DELIM); 205 if (stripped != 0) 206 msg_panic("strip_addr botch 19"); 207 208 stripped = strip_addr_internal("foo-ext@bar", &extension, NO_DELIM); 209 if (stripped != 0) 210 msg_panic("strip_addr botch 20"); 211 if (extension != 0) 212 msg_panic("strip_addr botch 21"); 213 214 stripped = strip_addr_internal("foo-ext@bar", (char **) 0, delim); 215 if (stripped == 0) 216 msg_panic("strip_addr botch 22"); 217 msg_info("wanted: foo-ext@bar -> %s", "foo@bar"); 218 msg_info("strip_addr foo-ext@bar -> %s", stripped); 219 myfree(stripped); 220 221 stripped = strip_addr_internal("foo-ext@bar", &extension, delim); 222 if (stripped == 0) 223 msg_panic("strip_addr botch 23"); 224 if (extension == 0) 225 msg_panic("strip_addr botch 24"); 226 msg_info("wanted: foo-ext@bar -> %s %s", "foo@bar", "-ext"); 227 msg_info("strip_addr foo-ext@bar -> %s %s", stripped, extension); 228 myfree(stripped); 229 myfree(extension); 230 231 stripped = strip_addr_internal("foo+ext@bar", &extension, delim); 232 if (stripped == 0) 233 msg_panic("strip_addr botch 25"); 234 if (extension == 0) 235 msg_panic("strip_addr botch 26"); 236 msg_info("wanted: foo+ext@bar -> %s %s", "foo@bar", "+ext"); 237 msg_info("strip_addr foo+ext@bar -> %s %s", stripped, extension); 238 myfree(stripped); 239 myfree(extension); 240 241 stripped = strip_addr_internal("foo bar+ext", &extension, delim); 242 if (stripped == 0) 243 msg_panic("strip_addr botch 27"); 244 if (extension == 0) 245 msg_panic("strip_addr botch 28"); 246 msg_info("wanted: foo bar+ext -> %s %s", "foo bar", "+ext"); 247 msg_info("strip_addr foo bar+ext -> %s %s", stripped, extension); 248 myfree(stripped); 249 myfree(extension); 250 251 return (0); 252} 253 254#endif 255