Commit 21c93d68 21c93d68a227295380ec45ea4a05620bac047eb9 by Sergey Poznyakoff

(_address_get_nth): Get nth sub-address from an address.

(most of the functions): Rewritten using _address_get_nth
(address_aget_personal, address_aget_comments): new functions.
(address_dup): New function. Create a copy of a (single) address.
(address_contains_email): New function. Check if the given email
is contained in the address.
(address_union): New function. Create a union of two addresses.
1 parent 46ff1b74
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
37 37
38 /* Get email addresses from rfc822 address. */ 38 /* Get email addresses from rfc822 address. */
39 int 39 int
40 address_create (address_t *a, const char *s) 40 address_create (address_t * a, const char *s)
41 { 41 {
42 /* 'a' must exist, and can't already have been initialized 42 /* 'a' must exist, and can't already have been initialized
43 */ 43 */
...@@ -46,7 +46,7 @@ address_create (address_t *a, const char *s) ...@@ -46,7 +46,7 @@ address_create (address_t *a, const char *s)
46 if (!a) 46 if (!a)
47 return MU_ERR_OUT_PTR_NULL; 47 return MU_ERR_OUT_PTR_NULL;
48 48
49 if(!s) 49 if (!s)
50 return EINVAL; 50 return EINVAL;
51 51
52 *a = NULL; 52 *a = NULL;
...@@ -63,29 +63,29 @@ address_create (address_t *a, const char *s) ...@@ -63,29 +63,29 @@ address_create (address_t *a, const char *s)
63 { 63 {
64 address_destroy (a); 64 address_destroy (a);
65 return ENOMEM; 65 return ENOMEM;
66 } 66 }
67 } 67 }
68 return status; 68 return status;
69 } 69 }
70 70
71 /* Get email addresses from array of rfc822 addresses. */ 71 /* Get email addresses from array of rfc822 addresses. */
72 int 72 int
73 address_createv (address_t *a, const char *sv[], size_t len) 73 address_createv (address_t * a, const char *sv[], size_t len)
74 { 74 {
75 int status = 0; 75 int status = 0;
76 size_t buflen = 0; 76 size_t buflen = 0;
77 char* buf = 0; 77 char *buf = 0;
78 size_t i; 78 size_t i;
79 79
80 if(!a) 80 if (!a)
81 return MU_ERR_OUT_PTR_NULL; 81 return MU_ERR_OUT_PTR_NULL;
82 82
83 if (!sv) 83 if (!sv)
84 return EINVAL; 84 return EINVAL;
85 85
86 if (len == (size_t)-1) 86 if (len == (size_t) - 1)
87 { 87 {
88 const char** vp = sv; 88 const char **vp = sv;
89 89
90 len = 0; 90 len = 0;
91 91
...@@ -97,14 +97,14 @@ address_createv (address_t *a, const char *sv[], size_t len) ...@@ -97,14 +97,14 @@ address_createv (address_t *a, const char *sv[], size_t len)
97 return EINVAL; 97 return EINVAL;
98 98
99 for (i = 0; i < len; i++) 99 for (i = 0; i < len; i++)
100 { 100 {
101 /* NULL strings are allowed */ 101 /* NULL strings are allowed */
102 if(sv[i]) 102 if (sv[i])
103 buflen += strlen(sv[i]); 103 buflen += strlen (sv[i]);
104 } 104 }
105 105
106 buflen += (len - 1) * strlen (", "); 106 buflen += (len - 1) * strlen (", ");
107 buflen += 1; /* Termination null. */ 107 buflen += 1; /* Termination null. */
108 108
109 buf = malloc (buflen); 109 buf = malloc (buflen);
110 110
...@@ -113,11 +113,11 @@ address_createv (address_t *a, const char *sv[], size_t len) ...@@ -113,11 +113,11 @@ address_createv (address_t *a, const char *sv[], size_t len)
113 113
114 for (i = 0, buf[0] = '\0'; i < len; i++) 114 for (i = 0, buf[0] = '\0'; i < len; i++)
115 { 115 {
116 if(i != 0) 116 if (i != 0)
117 strcat (buf, ", "); 117 strcat (buf, ", ");
118 118
119 if(sv[i]) 119 if (sv[i])
120 strcat (buf, sv[i]); 120 strcat (buf, sv[i]);
121 } 121 }
122 122
123 status = address_create (a, buf); 123 status = address_create (a, buf);
...@@ -128,7 +128,7 @@ address_createv (address_t *a, const char *sv[], size_t len) ...@@ -128,7 +128,7 @@ address_createv (address_t *a, const char *sv[], size_t len)
128 } 128 }
129 129
130 void 130 void
131 address_destroy (address_t *paddress) 131 address_destroy (address_t * paddress)
132 { 132 {
133 if (paddress && *paddress) 133 if (paddress && *paddress)
134 { 134 {
...@@ -157,181 +157,299 @@ address_destroy (address_t *paddress) ...@@ -157,181 +157,299 @@ address_destroy (address_t *paddress)
157 } 157 }
158 } 158 }
159 159
160 int address_concatenate (address_t to, address_t* from) 160 int
161 address_concatenate (address_t to, address_t * from)
161 { 162 {
162 if(!to || !from || !*from) 163 if (!to || !from || !*from)
163 return EINVAL; 164 return EINVAL;
164 165
165 while(to->next) 166 while (to->next)
166 to = to->next; 167 to = to->next;
167 168
168 assert(to && !to->next); 169 assert (to && !to->next);
169 170
170 to->next = *from; 171 to->next = *from;
171 *from = NULL; 172 *from = NULL;
172 173
173 to = to->next; 174 to = to->next;
174 175
175 if(to->addr) 176 if (to->addr)
176 { 177 {
177 free(to->addr); 178 free (to->addr);
178 to->addr = NULL; 179 to->addr = NULL;
179 } 180 }
180 181
181 return 0; 182 return 0;
182 } 183 }
183 184
185 address_t
186 _address_get_nth (address_t addr, size_t no)
187 {
188 int i;
189
190 for (i = 1; addr; addr = addr->next, i++)
191 if (i == no)
192 break;
193 return addr;
194 }
195
184 int 196 int
185 address_get_personal (address_t addr, size_t no, char *buf, size_t len, 197 address_get_personal (address_t addr, size_t no, char *buf, size_t len,
186 size_t *n) 198 size_t * n)
187 { 199 {
188 size_t i, j; 200 size_t i;
189 int status = ENOENT; 201 address_t subaddr;
202
190 if (addr == NULL) 203 if (addr == NULL)
191 return EINVAL; 204 return EINVAL;
192 for (i = 0, j = 1; addr; addr = addr->next, j++) 205
193 { 206 subaddr = _address_get_nth (addr, no);
194 if (j == no) 207 if (!subaddr)
195 { 208 return ENOENT;
196 i = mu_cpystr (buf, addr->personal, len); 209
197 status = 0; 210 i = mu_cpystr (buf, subaddr->personal, len);
198 break;
199 }
200 }
201 if (n) 211 if (n)
202 *n = i; 212 *n = i;
203 return status; 213 return 0;
204 } 214 }
205 215
206 int 216 int
207 address_get_comments (address_t addr, size_t no, char *buf, size_t len, 217 address_get_comments (address_t addr, size_t no, char *buf, size_t len,
208 size_t *n) 218 size_t * n)
209 { 219 {
210 size_t i, j; 220 size_t i;
211 int status = ENOENT; 221 address_t subaddr;
222
223 if (addr == NULL)
224 return EINVAL;
225
226 subaddr = _address_get_nth (addr, no);
227 if (!subaddr)
228 return ENOENT;
229
230 i = mu_cpystr (buf, subaddr->comments, len);
231 if (n)
232 *n = i;
233 return 0;
234 }
235
236 int
237 address_get_email (address_t addr, size_t no, char *buf, size_t len,
238 size_t * n)
239 {
240 size_t i;
241 address_t subaddr;
242
212 if (addr == NULL) 243 if (addr == NULL)
213 return EINVAL; 244 return EINVAL;
214 for (j = 1; addr; addr = addr->next, j++) 245
246 subaddr = _address_get_nth (addr, no);
247 if (!subaddr)
248 return ENOENT;
249
250 i = mu_cpystr (buf, subaddr->email, len);
251 if (n)
252 *n = i;
253 return 0;
254 }
255
256 #define format_char(c) do {\
257 if (buflen) \
258 {\
259 *buf++ = c;\
260 buflen--;\
261 }\
262 else\
263 rc++;\
264 } while(0)
265
266 #define format_string(str) do {\
267 if (buflen) \
268 {\
269 int n = snprintf (buf, buflen, "%s", str);\
270 buf += n;\
271 buflen -= n;\
272 }\
273 else\
274 rc += strlen (str);\
275 } while (0)
276
277 size_t
278 address_format_string (address_t addr, char *buf, size_t buflen)
279 {
280 int rc = 0;
281 int comma = 0;
282
283 for (;addr; addr = addr->next)
215 { 284 {
216 if (j == no) 285 if (addr->email)
217 { 286 {
218 i = mu_cpystr (buf, addr->comments, len); 287 int space = 0;
219 if (n) 288
220 *n = i; 289 if (comma)
221 status = 0; 290 format_char (',');
222 break; 291
292 if (addr->personal)
293 {
294 format_char ('"');
295 format_string (addr->personal);
296 format_char ('"');
297 space++;
298 }
299
300 if (addr->comments)
301 {
302 if (space)
303 format_char (' ');
304 format_char ('(');
305 format_string (addr->comments);
306 format_char (')');
307 space++;
308 }
309
310 if (space)
311 format_char (' ');
312 format_char ('<');
313 format_string (addr->email);
314 format_char ('>');
315 comma++;
223 } 316 }
224 } 317 }
318 format_char (0);
319 return rc;
320 }
321
322 int
323 address_aget_personal (address_t addr, size_t no, char **buf)
324 {
325 int status;
326 address_t subaddr;
327
328 if (addr == NULL)
329 return EINVAL;
330
331 subaddr = _address_get_nth (addr, no);
332 if (!subaddr)
333 return ENOENT;
334
335 if (subaddr->personal)
336 {
337 *buf = strdup (subaddr->personal);
338 if (!*buf)
339 status = ENOMEM;
340 }
341 else
342 buf = NULL;
225 return status; 343 return status;
226 } 344 }
227 345
228 int 346 int
229 address_get_email (address_t addr, size_t no, char *buf, size_t len, size_t *n) 347 address_aget_comments (address_t addr, size_t no, char **buf)
230 { 348 {
231 size_t i, j; 349 int status;
232 int status = ENOENT; 350 address_t subaddr;
351
233 if (addr == NULL) 352 if (addr == NULL)
234 return EINVAL; 353 return EINVAL;
235 for (j = 1; addr; addr = addr->next, j++) 354
355 subaddr = _address_get_nth (addr, no);
356 if (!subaddr)
357 return ENOENT;
358
359 if (subaddr->comments)
236 { 360 {
237 if (j == no) 361 *buf = strdup (subaddr->comments);
238 { 362 if (!*buf)
239 i = mu_cpystr (buf, addr->email, len); 363 status = ENOMEM;
240 if (n)
241 *n = i;
242 status = 0;
243 break;
244 }
245 } 364 }
365 else
366 buf = NULL;
246 return status; 367 return status;
247 } 368 }
248 369
249 int 370 int
250 address_aget_email (address_t addr, size_t no, char **buf) 371 address_aget_email (address_t addr, size_t no, char **buf)
251 { 372 {
252 size_t j; 373 int status = 0;
253 int status = ENOENT; 374 address_t subaddr;
375
254 if (addr == NULL || buf == NULL) 376 if (addr == NULL || buf == NULL)
255 return EINVAL; 377 return EINVAL;
256 for (j = 1; addr; addr = addr->next, j++) 378
379 subaddr = _address_get_nth (addr, no);
380 if (!subaddr)
381 return ENOENT;
382
383 if (subaddr->email)
257 { 384 {
258 if (j == no) 385 *buf = strdup (subaddr->email);
259 { 386 if (!*buf)
260 status = 0; 387 status = ENOMEM;
261 *buf = NULL;
262 if (addr->email)
263 {
264 *buf = strdup (addr->email);
265 if (!*buf)
266 status = ENOMEM;
267 }
268 break;
269 }
270 } 388 }
389 else
390 *buf = NULL;
391
271 return status; 392 return status;
272 } 393 }
273 394
274 int 395 int
275 address_get_local_part (address_t addr, size_t no, char *buf, size_t len, size_t *n) 396 address_get_local_part (address_t addr, size_t no, char *buf, size_t len,
397 size_t * n)
276 { 398 {
277 size_t i, j; 399 size_t i;
278 int status = ENOENT; 400 address_t subaddr;
401
279 if (addr == NULL) 402 if (addr == NULL)
280 return EINVAL; 403 return EINVAL;
281 for (j = 1; addr; addr = addr->next, j++) 404
282 { 405 subaddr = _address_get_nth (addr, no);
283 if (j == no) 406 if (!subaddr)
284 { 407 return ENOENT;
285 i = mu_cpystr (buf, addr->local_part, len); 408
286 if (n) 409 i = mu_cpystr (buf, subaddr->local_part, len);
287 *n = i; 410 if (n)
288 status = 0; 411 *n = i;
289 break; 412 return 0;
290 }
291 }
292 return status;
293 } 413 }
294 414
295 int 415 int
296 address_get_domain (address_t addr, size_t no, char *buf, size_t len, size_t *n) 416 address_get_domain (address_t addr, size_t no, char *buf, size_t len,
417 size_t * n)
297 { 418 {
298 size_t i, j; 419 size_t i;
299 int status = ENOENT; 420 address_t subaddr;
421
300 if (addr == NULL) 422 if (addr == NULL)
301 return EINVAL; 423 return EINVAL;
302 for (j = 1; addr; addr = addr->next, j++) 424
303 { 425 subaddr = _address_get_nth (addr, no);
304 if (j == no) 426 if (!subaddr)
305 { 427 return ENOENT;
306 i = mu_cpystr (buf, addr->domain, len); 428
307 if (n) 429 i = mu_cpystr (buf, subaddr->domain, len);
308 *n = i; 430 if (n)
309 status = 0; 431 *n = i;
310 break; 432 return 0;
311 }
312 }
313 return status;
314 } 433 }
315 434
316 int 435 int
317 address_get_route (address_t addr, size_t no, char *buf, size_t len, size_t *n) 436 address_get_route (address_t addr, size_t no, char *buf, size_t len,
437 size_t * n)
318 { 438 {
319 size_t i, j; 439 size_t i;
320 int status = ENOENT; 440 address_t subaddr;
441
321 if (addr == NULL) 442 if (addr == NULL)
322 return EINVAL; 443 return EINVAL;
323 for (j = 1; addr; addr = addr->next, j++) 444
324 { 445 subaddr = _address_get_nth (addr, no);
325 if (j == no) 446 if (!subaddr)
326 { 447 return ENOENT;
327 i = mu_cpystr (buf, addr->route, len); 448
328 if (n) 449 i = mu_cpystr (buf, subaddr->route, len);
329 *n = i; 450 if (n)
330 status = 0; 451 *n = i;
331 break; 452 return 0;
332 }
333 }
334 return status;
335 } 453 }
336 454
337 static int 455 static int
...@@ -359,35 +477,40 @@ _address_is_unix_mailbox (address_t addr) ...@@ -359,35 +477,40 @@ _address_is_unix_mailbox (address_t addr)
359 } 477 }
360 478
361 int 479 int
362 address_is_group (address_t addr, size_t no, int* yes) 480 address_is_group (address_t addr, size_t no, int *yes)
363 { 481 {
364 size_t j; 482 address_t subaddr;
365 int status = ENOENT; 483
366 if(addr == NULL) 484 if (addr == NULL)
367 return EINVAL; 485 return EINVAL;
368 for (j = 1; addr; addr = addr->next, j++) 486
369 { 487 subaddr = _address_get_nth (addr, no);
370 if (j == no) 488 if (!subaddr)
371 { 489 return ENOENT;
372 status = 0; 490
373 if(yes) 491 if (yes)
374 { 492 *yes = _address_is_group (subaddr);
375 *yes = _address_is_group(addr); 493 return 0;
376 }
377 break;
378 }
379 }
380 return status;
381 } 494 }
382 495
383 int 496 int
384 address_to_string (address_t addr, char *buf, size_t len, size_t *n) 497 address_to_string (address_t addr, char *buf, size_t len, size_t * n)
385 { 498 {
386 size_t i; 499 size_t i;
387 if (addr == NULL) 500 if (addr == NULL)
388 return EINVAL; 501 return EINVAL;
389 if (buf) 502 if (buf)
390 *buf = '\0'; 503 *buf = '\0';
504
505 if (!addr->addr)
506 {
507 i = address_format_string (addr, NULL, 0);
508 addr->addr = malloc (i + 1);
509 if (!addr->addr)
510 return ENOMEM;
511 address_format_string (addr, addr->addr, i+1);
512 }
513
391 i = mu_cpystr (buf, addr->addr, len); 514 i = mu_cpystr (buf, addr->addr, len);
392 if (n) 515 if (n)
393 *n = i; 516 *n = i;
...@@ -395,7 +518,7 @@ address_to_string (address_t addr, char *buf, size_t len, size_t *n) ...@@ -395,7 +518,7 @@ address_to_string (address_t addr, char *buf, size_t len, size_t *n)
395 } 518 }
396 519
397 int 520 int
398 address_get_count (address_t addr, size_t *pcount) 521 address_get_count (address_t addr, size_t * pcount)
399 { 522 {
400 size_t j; 523 size_t j;
401 for (j = 0; addr; addr = addr->next, j++) 524 for (j = 0; addr; addr = addr->next, j++)
...@@ -404,45 +527,118 @@ address_get_count (address_t addr, size_t *pcount) ...@@ -404,45 +527,118 @@ address_get_count (address_t addr, size_t *pcount)
404 *pcount = j; 527 *pcount = j;
405 return 0; 528 return 0;
406 } 529 }
530
407 int 531 int
408 address_get_group_count (address_t addr, size_t *pcount) 532 address_get_group_count (address_t addr, size_t * pcount)
409 { 533 {
410 size_t j; 534 size_t j;
411 for (j = 0; addr; addr = addr->next) 535 for (j = 0; addr; addr = addr->next)
412 { 536 {
413 if(_address_is_group(addr)) 537 if (_address_is_group (addr))
414 j++; 538 j++;
415 } 539 }
416 if (pcount) 540 if (pcount)
417 *pcount = j; 541 *pcount = j;
418 return 0; 542 return 0;
419 } 543 }
420 544
421 int 545 int
422 address_get_email_count (address_t addr, size_t *pcount) 546 address_get_email_count (address_t addr, size_t * pcount)
423 { 547 {
424 size_t j; 548 size_t j;
425 for (j = 0; addr; addr = addr->next) 549 for (j = 0; addr; addr = addr->next)
426 { 550 {
427 if(_address_is_email(addr)) 551 if (_address_is_email (addr))
428 j++; 552 j++;
429 } 553 }
430 if (pcount) 554 if (pcount)
431 *pcount = j; 555 *pcount = j;
432 return 0; 556 return 0;
433 } 557 }
434 558
435 int 559 int
436 address_get_unix_mailbox_count (address_t addr, size_t *pcount) 560 address_get_unix_mailbox_count (address_t addr, size_t * pcount)
437 { 561 {
438 size_t j; 562 size_t j;
439 for (j = 0; addr; addr = addr->next) 563 for (j = 0; addr; addr = addr->next)
440 { 564 {
441 if(_address_is_unix_mailbox(addr)) 565 if (_address_is_unix_mailbox (addr))
442 j++; 566 j++;
443 } 567 }
444 if (pcount) 568 if (pcount)
445 *pcount = j; 569 *pcount = j;
446 return 0; 570 return 0;
447 } 571 }
448 572
573 int
574 address_contains_email (address_t addr, const char *email)
575 {
576 for (; addr; addr = addr->next)
577 if (strcasecmp (addr->email, email) == 0)
578 return 1;
579 return 0;
580 }
581
582 address_t
583 address_dup (address_t src)
584 {
585 address_t dst = calloc (1, sizeof (*dst));
586
587 if (!dst)
588 return NULL;
589
590 if (src->comments)
591 dst->comments = strdup (src->comments);
592 if (src->personal)
593 dst->personal = strdup (src->personal);
594 if (src->email)
595 dst->email = strdup (src->email);
596 if (src->local_part)
597 dst->local_part = strdup (src->local_part);
598 if (src->domain)
599 dst->domain = strdup (src->domain);
600 if (src->route)
601 dst->route = strdup (src->route);
602
603 return dst;
604 }
605
606 int
607 address_union (address_t *a, address_t b)
608 {
609 address_t last = NULL;
610
611 if (!a || !b)
612 return EINVAL;
613
614 if (!*a)
615 {
616 *a = address_dup (b);
617 if (!*a)
618 return ENOMEM;
619 last = *a;
620 b = b->next;
621 }
622 else
623 {
624 if ((*a)->addr)
625 {
626 free ((*a)->addr);
627 (*a)->addr = NULL;
628 }
629 for (last = *a; last->next; last = last->next)
630 ;
631 }
632
633 for (; b; b = b->next)
634 if (!address_contains_email (*a, b->email))
635 {
636 address_t next = address_dup (b);
637 if (!next)
638 return ENOMEM;
639 last->next = next;
640 last = next;
641 }
642 return 0;
643 }
644
......