xref: /netbsd-src/external/ibm-public/postfix/dist/src/global/fold_addr.c (revision e89934bbf778a6d6d6894877c4da59d0c7835b0f)
1 /*	$NetBSD: fold_addr.c,v 1.2 2017/02/14 01:16:45 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	fold_addr 3
6 /* SUMMARY
7 /*	address case folding
8 /* SYNOPSIS
9 /*	#include <fold_addr.h>
10 /*
11 /*	char	*fold_addr(result, addr, flags)
12 /*	VSTRING *result;
13 /*	const char *addr;
14 /*	int	flags;
15 /* DESCRIPTION
16 /*	fold_addr() case folds an address according to the options
17 /*	specified with \fIflags\fR. The result value is the output
18 /*	address.
19 /*
20 /*	Arguments
21 /* .IP result
22 /*	Result buffer with the output address. Note: casefolding
23 /*	may change the string length.
24 /* .IP addr
25 /*	Null-terminated read-only string with the input address.
26 /* .IP flags
27 /*	Zero or the bit-wise OR of:
28 /* .RS
29 /* .IP FOLD_ADDR_USER
30 /*	Case fold the address local part.
31 /* .IP FOLD_ADDR_HOST
32 /*	Case fold the address domain part.
33 /* .IP FOLD_ADDR_ALL
34 /*	Alias for (FOLD_ADDR_USER | FOLD_ADDR_HOST).
35 /* .RE
36 /* SEE ALSO
37 /*	msg(3) diagnostics interface
38 /*	casefold(3) casefold text
39 /* DIAGNOSTICS
40 /*	Fatal errors: memory allocation problem.
41 /* LICENSE
42 /* .ad
43 /* .fi
44 /*	The Secure Mailer license must be distributed with this software.
45 /* AUTHOR(S)
46 /*	Wietse Venema
47 /*	IBM T.J. Watson Research
48 /*	P.O. Box 704
49 /*	Yorktown Heights, NY 10598, USA
50 /*--*/
51 
52 /* System library. */
53 
54 #include <sys_defs.h>
55 #include <string.h>
56 
57 /* Utility library. */
58 
59 #include <stringops.h>
60 
61 /* Global library. */
62 
63 #include <fold_addr.h>
64 
65 #define STR(x)	vstring_str(x)
66 
67 /* fold_addr - case fold mail address */
68 
fold_addr(VSTRING * result,const char * addr,int flags)69 char   *fold_addr(VSTRING *result, const char *addr, int flags)
70 {
71     char   *cp;
72 
73     /*
74      * Fold the address as appropriate.
75      */
76     switch (flags & FOLD_ADDR_ALL) {
77     case FOLD_ADDR_HOST:
78 	if ((cp = strrchr(addr, '@')) != 0) {
79 	    cp += 1;
80 	    vstring_strncpy(result, addr, cp - addr);
81 	    casefold_append(result, cp);
82 	    break;
83 	}
84 	/* FALLTHROUGH */
85     case 0:
86 	vstring_strcpy(result, addr);
87 	break;
88     case FOLD_ADDR_USER:
89 	if ((cp = strrchr(addr, '@')) != 0) {
90 	    casefold_len(result, addr, cp - addr);
91 	    vstring_strcat(result, cp);
92 	    break;
93 	}
94 	/* FALLTHROUGH */
95     case FOLD_ADDR_USER | FOLD_ADDR_HOST:
96 	casefold(result, addr);
97 	break;
98     }
99     return (STR(result));
100 }
101 
102 #ifdef TEST
103 #include <stdlib.h>
104 #include <vstream.h>
105 #include <vstring_vstream.h>
106 #include <msg_vstream.h>
107 #include <argv.h>
108 
main(int argc,char ** argv)109 int     main(int argc, char **argv)
110 {
111     VSTRING *line_buffer = vstring_alloc(1);
112     VSTRING *fold_buffer = vstring_alloc(1);
113     ARGV   *cmd;
114     char  **args;
115 
116     msg_vstream_init(argv[0], VSTREAM_ERR);
117     util_utf8_enable = 1;
118     while (vstring_fgets_nonl(line_buffer, VSTREAM_IN)) {
119 	vstream_printf("> %s\n", STR(line_buffer));
120 	cmd = argv_split(STR(line_buffer), CHARS_SPACE);
121 	if (cmd->argc == 0 || cmd->argv[0][0] == '#') {
122 	    argv_free(cmd);
123 	    continue;
124 	}
125 	args = cmd->argv;
126 
127 	/*
128 	 * Fold the host.
129 	 */
130 	if (strcmp(args[0], "host") == 0 && cmd->argc == 2) {
131 	    vstream_printf("\"%s\" -> \"%s\"\n", args[1], fold_addr(fold_buffer,
132 						  args[1], FOLD_ADDR_HOST));
133 	}
134 
135 	/*
136 	 * Fold the user.
137 	 */
138 	else if (strcmp(args[0], "user") == 0 && cmd->argc == 2) {
139 	    vstream_printf("\"%s\" -> \"%s\"\n", args[1], fold_addr(fold_buffer,
140 						  args[1], FOLD_ADDR_USER));
141 	}
142 
143 	/*
144 	 * Fold user and host.
145 	 */
146 	else if (strcmp(args[0], "all") == 0 && cmd->argc == 2) {
147 	    vstream_printf("\"%s\" -> \"%s\"\n", args[1], fold_addr(fold_buffer,
148 						   args[1], FOLD_ADDR_ALL));
149 	}
150 
151 	/*
152 	 * Fold none.
153 	 */
154 	else if (strcmp(args[0], "none") == 0 && cmd->argc == 2) {
155 	    vstream_printf("\"%s\" -> \"%s\"\n", args[1], fold_addr(fold_buffer,
156 							       args[1], 0));
157 	}
158 
159 	/*
160 	 * Usage.
161 	 */
162 	else {
163 	    vstream_printf("Usage: %s host <addr> | user <addr> | all <addr>\n",
164 			   argv[0]);
165 	}
166 	vstream_fflush(VSTREAM_OUT);
167 	argv_free(cmd);
168     }
169     vstring_free(line_buffer);
170     vstring_free(fold_buffer);
171     exit(0);
172 }
173 
174 #endif					/* TEST */
175