1 #if !defined(lint) && !defined(DOS)
2 static char rcsid
[] = "$Id: addrstring.c 770 2007-10-24 00:23:09Z hubert@u.washington.edu $";
6 * ========================================================================
7 * Copyright 2006-2007 University of Washington
8 * Copyright 2013-2019 Eduardo Chappa
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
19 #include "../pith/headers.h"
20 #include "../pith/addrstring.h"
21 #include "../pith/state.h"
22 #include "../pith/copyaddr.h"
23 #include "../pith/charset.h"
24 #include "../pith/stream.h"
30 void rfc822_write_address_decode(char *, size_t, ADDRESS
*, int);
34 * Format an address structure into a string
36 * Args: addr -- Single ADDRESS structure to turn into a string
38 * Result: Fills in buf and returns pointer to it.
39 * Just uses the c-client call to do this.
40 * (the address is not rfc1522 decoded)
43 addr_string(struct mail_address
*addr
, char *buf
, size_t buflen
)
49 next_addr
= addr
->next
;
55 rbuf
.end
= buf
+buflen
-1;
56 rfc822_output_address_list(&rbuf
, addr
, 0L, NULL
);
58 addr
->next
= next_addr
;
64 * Same as addr_string only it doesn't have to be a
68 addr_string_mult(struct mail_address
*addr
, char *buf
, size_t buflen
)
77 rbuf
.end
= buf
+buflen
-1;
78 rfc822_output_address_list(&rbuf
, addr
, 0L, NULL
);
85 * Format an address structure into a simple string: "mailbox@host"
87 * Args: addr -- Single ADDRESS structure to turn into a string
88 * buf -- buffer to write address in;
90 * Result: Returns pointer to buf;
93 simple_addr_string(struct mail_address
*addr
, char *buf
, size_t buflen
)
101 rbuf
.end
= buf
+buflen
-1;
102 rfc822_output_address(&rbuf
, addr
);
110 * Format an address structure into a simple string: "mailbox@host"
111 * Like simple_addr_string but can be multiple addresses.
113 * Args: addr -- ADDRESS structure to turn into a string
114 * buf -- buffer to write address in;
115 * buflen -- length of buffer
116 * sep -- separator string
118 * Result: Returns pointer to internal static formatted string.
119 * Just uses the c-client call to do this.
122 simple_mult_addr_string(struct mail_address
*addr
, char *buf
, size_t buflen
, char *sep
)
129 seplen
= strlen(sep
);
132 for(a
= addr
; a
; a
= a
->next
){
133 if(dest
> buf
&& seplen
> 0 && buflen
-1-(dest
-buf
) >= seplen
){
134 strncpy(dest
, sep
, seplen
);
139 simple_addr_string(a
, dest
, buflen
-(dest
-buf
));
140 dest
+= strlen(dest
);
143 buf
[buflen
-1] = '\0';
150 * 1522 encode the personal name portion of addr and return an allocated
151 * copy of the resulting address string.
154 encode_fullname_of_addrstring(char *addr
, char *charset
)
160 static char *fakedomain
= "@";
164 tmp_a_string
= cpystr(addr
? addr
: "");
166 rfc822_parse_adrlist(&adr
, tmp_a_string
, fakedomain
);
167 fs_give((void **)&tmp_a_string
);
172 if(adr
->personal
&& adr
->personal
[0]){
173 pers_encoded
= cpystr(rfc1522_encode(tmp_20k_buf
, SIZEOF_20KBUF
,
174 (unsigned char *)adr
->personal
,
176 fs_give((void **)&adr
->personal
);
177 adr
->personal
= pers_encoded
;
181 ret
= (char *) fs_get(len
* sizeof(char));
183 rbuf
.f
= dummy_soutr
;
187 rbuf
.end
= ret
+len
-1;
188 rfc822_output_address_list(&rbuf
, adr
, 0L, NULL
);
190 mail_free_address(&adr
);
196 * 1522 decode the personal name portion of addr and return an allocated
197 * copy of the resulting address string.
200 decode_fullname_of_addrstring(char *addr
, int verbose
)
206 static char *fakedomain
= "@";
210 tmp_a_string
= cpystr(addr
? addr
: "");
212 rfc822_parse_adrlist(&adr
, tmp_a_string
, fakedomain
);
213 fs_give((void **)&tmp_a_string
);
218 if(adr
->personal
&& adr
->personal
[0]){
220 = cpystr((char *)rfc1522_decode_to_utf8((unsigned char *)tmp_20k_buf
,
221 SIZEOF_20KBUF
, adr
->personal
));
222 fs_give((void **)&adr
->personal
);
223 adr
->personal
= pers_decoded
;
227 ret
= (char *) fs_get(len
* sizeof(char));
229 rbuf
.f
= dummy_soutr
;
233 rbuf
.end
= ret
+len
-1;
234 rfc822_output_address_list(&rbuf
, adr
, 0L, NULL
);
236 mail_free_address(&adr
);
242 * Turn a list of address structures into a formatted string
244 * Args: adrlist -- An adrlist
245 * f -- Function to use to print one address in list. If NULL,
246 * use rfc822_write_address_decode to print whole list.
247 * do_quote -- Quote quotes and dots (only used if f == NULL).
248 * Result: comma separated list of addresses which is
249 * malloced here and returned
250 * (the list is rfc1522 decoded unless f is *not* NULL)
253 addr_list_string(struct mail_address
*adrlist
,
254 char *(*f
)(struct mail_address
*, char *, size_t),
258 char *list
, *s
, string
[MAX_ADDR_EXPN
+1];
266 for(a
= adrlist
; a
; a
= a
->next
)
267 len
+= (strlen((*f
)(a
, string
, sizeof(string
))) + 2);
269 list
= (char *) fs_get((len
+1) * sizeof(char));
273 for(a
= adrlist
; a
; a
= a
->next
){
274 sstrncpy(&s
, (*f
)(a
, string
, sizeof(string
)), len
-(s
-list
));
275 if(a
->next
&& len
-(s
-list
) > 2){
282 len
= est_size(adrlist
);
283 list
= (char *) fs_get((len
+1) * sizeof(char));
285 rfc822_write_address_decode(list
, len
+1, adrlist
, do_quote
);
286 removing_leading_and_trailing_white_space(list
);
294 static long rfc822_dummy_soutr (void *stream
, char *string
)
300 * Copied from c-client/rfc822.c buf with dot and double quote removed.
302 static const char *rspecials_minus_quote_and_dot
= "()<>@,;:\\[]\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37\177";
304 /* Write RFC822 address with 1522 decoding of personal name
305 * and optional quoting.
307 * The idea is that there are some places where we'd just like to display
308 * the personal name as is before applying confusing quoting. However,
309 * we do want to be careful not to break things that should be quoted so
310 * we'll only use this where we are sure. Quoting may look ugly but it
311 * doesn't usually break anything.
314 rfc822_write_address_decode(char *dest
, size_t destlen
, struct mail_address
*adr
, int do_quote
)
317 extern const char *rspecials
;
321 * We want to print the adr list after decoding it. C-client knows
322 * how to parse and print, so we want to use that. But c-client
323 * doesn't decode. So we make a copy of the address list, decode
324 * things there, and let c-client print that.
326 copy
= copyaddrlist(adr
);
327 for(a
= copy
; a
; a
= a
->next
){
328 if(a
->host
){ /* ordinary address? */
329 if(a
->personal
&& *a
->personal
){
332 p
= rfc1522_decode_to_utf8((unsigned char *) tmp_20k_buf
,
333 SIZEOF_20KBUF
, a
->personal
);
335 if(p
&& (char *) p
!= a
->personal
){
336 fs_give((void **) &a
->personal
);
337 a
->personal
= cpystr((char *) p
);
341 else if(a
->mailbox
&& *a
->mailbox
){ /* start of group? */
344 p
= rfc1522_decode_to_utf8((unsigned char *) tmp_20k_buf
, SIZEOF_20KBUF
, a
->mailbox
);
346 if(p
&& (char *) p
!= a
->mailbox
){
347 fs_give((void **) &a
->mailbox
);
348 a
->mailbox
= cpystr((char *) p
);
353 buf
.end
= (buf
.beg
= buf
.cur
= dest
) + destlen
;
354 buf
.f
= rfc822_dummy_soutr
;
358 (void) rfc822_output_address_list(&buf
, copy
, 0,
359 do_quote
? rspecials
: rspecials_minus_quote_and_dot
);
364 mail_free_address(©
);
369 * Compute an upper bound on the size of the array required by
370 * rfc822_write_address for this list of addresses.
372 * Args: adrlist -- The address list.
374 * Returns -- an integer giving the upper bound
377 est_size(struct mail_address
*a
)
381 for(; a
; a
= a
->next
){
383 /* two times personal for possible quoting */
384 cnt
+= 2 * (a
->personal
? (strlen(a
->personal
)+1) : 0);
385 cnt
+= 2 * (a
->mailbox
? (strlen(a
->mailbox
)+1) : 0);
386 cnt
+= (a
->adl
? strlen(a
->adl
) : 0);
387 cnt
+= (a
->host
? strlen(a
->host
) : 0);
391 * possible single space between fullname and addr
392 * left and right brackets
394 * possible : for route addr
397 * So I really think that adding 7 is enough. Instead, I'll add 10.
402 return(MAX(cnt
, 50)); /* just making sure */
407 * Returns the number of addresses in the list.
410 count_addrs(struct mail_address
*adrlist
)
415 if(adrlist
->mailbox
&& adrlist
->mailbox
[0])
418 adrlist
= adrlist
->next
;
426 * Buf is at least size maxlen+1
429 a_little_addr_string(struct mail_address
*addr
, char *buf
, size_t maxlen
)
433 if(addr
->personal
&& addr
->personal
[0]){
434 char tmp
[MAILTMPLEN
];
436 snprintf(tmp
, sizeof(tmp
), "%s", addr
->personal
);
437 iutf8ncpy(buf
, (char *)rfc1522_decode_to_utf8((unsigned char *)tmp_20k_buf
,
441 else if(addr
->mailbox
&& addr
->mailbox
[0]){
442 strncpy(buf
, addr
->mailbox
, maxlen
);
444 if(addr
->host
&& addr
->host
[0] && addr
->host
[0] != '.'){
445 strncat(buf
, "@", maxlen
+1-1-strlen(buf
));
446 strncat(buf
, addr
->host
, maxlen
+1-1-strlen(buf
));