1 /* $NetBSD: strip_addr.c,v 1.3 2020/03/18 19:05:16 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 76 char *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 120 char *var_double_bounce_sender = DEF_DOUBLE_BOUNCE; 121 122 int main(int unused_argc, char **unused_argv) 123 { 124 char *extension; 125 char *stripped; 126 char *delim = "+-"; 127 128 #define NO_DELIM "" 129 130 /* 131 * Incredible. This function takes only three arguments, and the tests 132 * already take more lines of code than the code being tested. 133 */ 134 stripped = strip_addr_internal("foo", (char **) 0, NO_DELIM); 135 if (stripped != 0) 136 msg_panic("strip_addr botch 1"); 137 138 stripped = strip_addr_internal("foo", &extension, NO_DELIM); 139 if (stripped != 0) 140 msg_panic("strip_addr botch 2"); 141 if (extension != 0) 142 msg_panic("strip_addr botch 3"); 143 144 stripped = strip_addr_internal("foo", (char **) 0, delim); 145 if (stripped != 0) 146 msg_panic("strip_addr botch 4"); 147 148 stripped = strip_addr_internal("foo", &extension, delim); 149 if (stripped != 0) 150 msg_panic("strip_addr botch 5"); 151 if (extension != 0) 152 msg_panic("strip_addr botch 6"); 153 154 stripped = strip_addr_internal("foo@bar", (char **) 0, NO_DELIM); 155 if (stripped != 0) 156 msg_panic("strip_addr botch 7"); 157 158 stripped = strip_addr_internal("foo@bar", &extension, NO_DELIM); 159 if (stripped != 0) 160 msg_panic("strip_addr botch 8"); 161 if (extension != 0) 162 msg_panic("strip_addr botch 9"); 163 164 stripped = strip_addr_internal("foo@bar", (char **) 0, delim); 165 if (stripped != 0) 166 msg_panic("strip_addr botch 10"); 167 168 stripped = strip_addr_internal("foo@bar", &extension, delim); 169 if (stripped != 0) 170 msg_panic("strip_addr botch 11"); 171 if (extension != 0) 172 msg_panic("strip_addr botch 12"); 173 174 stripped = strip_addr_internal("foo-ext", (char **) 0, NO_DELIM); 175 if (stripped != 0) 176 msg_panic("strip_addr botch 13"); 177 178 stripped = strip_addr_internal("foo-ext", &extension, NO_DELIM); 179 if (stripped != 0) 180 msg_panic("strip_addr botch 14"); 181 if (extension != 0) 182 msg_panic("strip_addr botch 15"); 183 184 stripped = strip_addr_internal("foo-ext", (char **) 0, delim); 185 if (stripped == 0) 186 msg_panic("strip_addr botch 16"); 187 msg_info("wanted: foo-ext -> %s", "foo"); 188 msg_info("strip_addr foo-ext -> %s", stripped); 189 myfree(stripped); 190 191 stripped = strip_addr_internal("foo-ext", &extension, delim); 192 if (stripped == 0) 193 msg_panic("strip_addr botch 17"); 194 if (extension == 0) 195 msg_panic("strip_addr botch 18"); 196 msg_info("wanted: foo-ext -> %s %s", "foo", "-ext"); 197 msg_info("strip_addr foo-ext -> %s %s", stripped, extension); 198 myfree(stripped); 199 myfree(extension); 200 201 stripped = strip_addr_internal("foo-ext@bar", (char **) 0, NO_DELIM); 202 if (stripped != 0) 203 msg_panic("strip_addr botch 19"); 204 205 stripped = strip_addr_internal("foo-ext@bar", &extension, NO_DELIM); 206 if (stripped != 0) 207 msg_panic("strip_addr botch 20"); 208 if (extension != 0) 209 msg_panic("strip_addr botch 21"); 210 211 stripped = strip_addr_internal("foo-ext@bar", (char **) 0, delim); 212 if (stripped == 0) 213 msg_panic("strip_addr botch 22"); 214 msg_info("wanted: foo-ext@bar -> %s", "foo@bar"); 215 msg_info("strip_addr foo-ext@bar -> %s", stripped); 216 myfree(stripped); 217 218 stripped = strip_addr_internal("foo-ext@bar", &extension, delim); 219 if (stripped == 0) 220 msg_panic("strip_addr botch 23"); 221 if (extension == 0) 222 msg_panic("strip_addr botch 24"); 223 msg_info("wanted: foo-ext@bar -> %s %s", "foo@bar", "-ext"); 224 msg_info("strip_addr foo-ext@bar -> %s %s", stripped, extension); 225 myfree(stripped); 226 myfree(extension); 227 228 stripped = strip_addr_internal("foo+ext@bar", &extension, delim); 229 if (stripped == 0) 230 msg_panic("strip_addr botch 25"); 231 if (extension == 0) 232 msg_panic("strip_addr botch 26"); 233 msg_info("wanted: foo+ext@bar -> %s %s", "foo@bar", "+ext"); 234 msg_info("strip_addr foo+ext@bar -> %s %s", stripped, extension); 235 myfree(stripped); 236 myfree(extension); 237 238 stripped = strip_addr_internal("foo bar+ext", &extension, delim); 239 if (stripped == 0) 240 msg_panic("strip_addr botch 27"); 241 if (extension == 0) 242 msg_panic("strip_addr botch 28"); 243 msg_info("wanted: foo bar+ext -> %s %s", "foo bar", "+ext"); 244 msg_info("strip_addr foo bar+ext -> %s %s", stripped, extension); 245 myfree(stripped); 246 myfree(extension); 247 248 return (0); 249 } 250 251 #endif 252