rfc822.c
上传用户:s81996212
上传日期:2007-01-04
资源大小:722k
文件大小:13k
源码类别:

WEB邮件程序

开发平台:

C/C++

  1. /*
  2. ** Copyright 1998 - 1999 Double Precision, Inc.
  3. ** See COPYING for distribution information.
  4. */
  5. /*
  6. ** $Id: rfc822.c,v 1.12 2000/02/23 02:41:19 mrsam Exp $
  7. */
  8. #include <stdio.h>
  9. #include <ctype.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include "rfc822.h"
  13. static void tokenize(const char *p, struct rfc822token *tokp, int *toklen,
  14. void (*err_func)(const char *, int))
  15. {
  16. const char *addr=p;
  17. int i=0;
  18. int inbracket=0;
  19. *toklen=0;
  20. while (*p)
  21. {
  22. if (isspace((int)(unsigned char)*p))
  23. {
  24. p++;
  25. i++;
  26. continue;
  27. }
  28. switch (*p) {
  29. int level;
  30. case '(':
  31. if (tokp)
  32. {
  33. tokp->token='(';
  34. tokp->ptr=p;
  35. tokp->len=0;
  36. }
  37. level=0;
  38. for (;;)
  39. {
  40. if (!*p)
  41. {
  42. if (err_func) (*err_func)(addr, i);
  43. if (tokp) tokp->token='"';
  44. ++*toklen;
  45. return;
  46. }
  47. if (*p == '(')
  48. ++level;
  49. if (*p == ')' && --level == 0)
  50. {
  51. p++;
  52. i++;
  53. if (tokp) tokp->len++;
  54. break;
  55. }
  56. if (*p == '\' && p[1])
  57. {
  58. p++;
  59. i++;
  60. if (tokp) tokp->len++;
  61. }
  62. i++;
  63. if (tokp) tokp->len++;
  64. p++;
  65. }
  66. if (tokp) ++tokp;
  67. ++*toklen;
  68. continue;
  69. case '"':
  70. p++;
  71. i++;
  72. if (tokp)
  73. {
  74. tokp->token='"';
  75. tokp->ptr=p;
  76. }
  77. while (*p != '"')
  78. {
  79. if (!*p)
  80. {
  81. if (err_func) (*err_func)(addr, i);
  82. ++*toklen;
  83. return;
  84. }
  85. if (*p == '\' && p[1])
  86. {
  87. if (tokp) tokp->len++;
  88. p++;
  89. i++;
  90. }
  91. if (tokp) tokp->len++;
  92. p++;
  93. i++;
  94. }
  95. ++*toklen;
  96. if (tokp) ++tokp;
  97. p++;
  98. i++;
  99. continue;
  100. case '\':
  101. case ')':
  102. if (err_func) (*err_func)(addr, i);
  103. ++p;
  104. ++i;
  105. continue;
  106. case '<':
  107. case '>':
  108. case '@':
  109. case ',':
  110. case ';':
  111. case ':':
  112. case '.':
  113. case '[':
  114. case ']':
  115. case '%':
  116. case '!':
  117. case '?':
  118. case '=':
  119. case '/':
  120. if ( (*p == '<' && inbracket) ||
  121. (*p == '>' && !inbracket))
  122. {
  123. if (err_func) (*err_func)(addr, i);
  124. ++p;
  125. ++i;
  126. continue;
  127. }
  128. if (*p == '<')
  129. inbracket=1;
  130. if (*p == '>')
  131. inbracket=0;
  132. if (tokp)
  133. {
  134. tokp->token= *p;
  135. tokp->ptr=p;
  136. tokp->len=1;
  137. ++tokp;
  138. }
  139. ++*toklen;
  140. if (*p == '<' && p[1] == '>')
  141. /* Fake a null address */
  142. {
  143. if (tokp)
  144. {
  145. tokp->token=0;
  146. tokp->ptr="";
  147. tokp->len=0;
  148. ++tokp;
  149. }
  150. ++*toklen;
  151. }
  152. ++p;
  153. ++i;
  154. continue;
  155. default:
  156. if (tokp)
  157. {
  158. tokp->token=0;
  159. tokp->ptr=p;
  160. tokp->len=0;
  161. }
  162. while (*p && !isspace((int)(unsigned char)*p) && strchr(
  163. "<>@,;:.[]()%!"\?=/", *p) == 0)
  164. {
  165. if (tokp) ++tokp->len;
  166. ++p;
  167. ++i;
  168. }
  169. if (i == 0) /* Idiot check */
  170. {
  171. if (err_func) (*err_func)(addr, i);
  172. if (tokp)
  173. {
  174. tokp->token='"';
  175. tokp->ptr=p;
  176. tokp->len=1;
  177. ++tokp;
  178. }
  179. ++*toklen;
  180. ++p;
  181. ++i;
  182. continue;
  183. }
  184. if (tokp) ++tokp;
  185. ++*toklen;
  186. }
  187. }
  188. }
  189. static void parseaddr(struct rfc822token *tokens, int ntokens,
  190. struct rfc822addr *addrs, int *naddrs)
  191. {
  192. int flag, j, k;
  193. struct rfc822token save_token;
  194. *naddrs=0;
  195. while (ntokens)
  196. {
  197. int i;
  198. /* atoms (token=0) or quoted strings, followed by a : token
  199. is a list name. */
  200. for (i=0; i<ntokens; i++)
  201. if (tokens[i].token && tokens[i].token != '"')
  202. break;
  203. if (i < ntokens && tokens[i].token == ':')
  204. {
  205. ++i;
  206. if (addrs)
  207. {
  208. addrs->tokens=0;
  209. addrs->name=i ? tokens:0;
  210. for (j=1; j<i; j++)
  211. addrs->name[j-1].next=addrs->name+j;
  212. if (i)
  213. addrs->name[i-1].next=0;
  214. addrs++;
  215. }
  216. ++*naddrs;
  217. tokens += i;
  218. ntokens -= i;
  219. continue;  /* Group=phrase ":" */
  220. }
  221. /* Spurious commas are skipped, ;s are recorded */
  222. if (tokens->token == ',' || tokens->token == ';')
  223. {
  224. if (tokens->token == ';')
  225. {
  226. if (addrs)
  227. {
  228. addrs->tokens=0;
  229. addrs->name=tokens;
  230. addrs->name->next=0;
  231. addrs++;
  232. }
  233. ++*naddrs;
  234. }
  235. ++tokens;
  236. --ntokens;
  237. continue;
  238. }
  239. /* If we can find a '<' before the next comma or semicolon,
  240. we have new style RFC path address */
  241. for (i=0; i<ntokens && tokens[i].token != ';' &&
  242. tokens[i].token != ',' &&
  243. tokens[i].token != '<'; i++)
  244. ;
  245. if (i < ntokens && tokens[i].token == '<')
  246. {
  247. int j;
  248. /* Ok -- what to do with the stuff before '>'???
  249. If it consists exclusively of atoms, leave them alone.
  250. Else, make them all a quoted string. */
  251. for (j=0; j<i && (tokens[j].token == 0 ||
  252. tokens[j].token == '('); j++)
  253. ;
  254. if (j == i)
  255. {
  256. if (addrs)
  257. {
  258. addrs->name= i ? tokens:0;
  259. for (k=1; k<i; k++)
  260. addrs->name[k-1].next=addrs->name+k;
  261. if (i)
  262. addrs->name[i-1].next=0;
  263. }
  264. }
  265. else /* Intentionally corrupt the original toks */
  266. {
  267. if (addrs)
  268. {
  269. tokens->len= tokens[i-1].ptr
  270. + tokens[i-1].len
  271. - tokens->ptr;
  272. /* We know that all the ptrs point
  273. to parts of the same string. */
  274. tokens->token='"';
  275. /* Quoted string. */
  276. addrs->name=tokens;
  277. addrs->name->next=0;
  278. }
  279. }
  280. /* Any comments in the name part are changed to quotes */
  281. if (addrs)
  282. {
  283. struct rfc822token *t;
  284. for (t=addrs->name; t; t=t->next)
  285. if (t->token == '(')
  286. t->token='"';
  287. }
  288. /* Now that's done and over with, see what can
  289. be done with the <...> part. */
  290. ++i;
  291. tokens += i;
  292. ntokens -= i;
  293. for (i=0; i<ntokens && tokens[i].token != '>'; i++)
  294. ;
  295. if (addrs)
  296. {
  297. addrs->tokens=i ? tokens:0;
  298. for (k=1; k<i; k++)
  299. addrs->tokens[k-1].next=addrs->tokens+k;
  300. if (i)
  301. addrs->tokens[i-1].next=0;
  302. ++addrs;
  303. }
  304. ++*naddrs;
  305. tokens += i;
  306. ntokens -= i;
  307. if (ntokens) /* Skip the '>' token */
  308. {
  309. --ntokens;
  310. ++tokens;
  311. }
  312. continue;
  313. }
  314. /* Ok - old style address.  Assume the worst */
  315. /* Try to figure out where the address ends.  It ends upon:
  316. a comma, semicolon, or two consecutive atoms. */
  317. flag=0;
  318. for (i=0; i<ntokens && tokens[i].token != ',' &&
  319. tokens[i].token != ';'; i++)
  320. {
  321. if (tokens[i].token == '(') continue;
  322. /* Ignore comments */
  323. if (tokens[i].token == 0 || tokens[i].token == '"')
  324. /* Atom */
  325. {
  326. if (flag) break;
  327. flag=1;
  328. }
  329. else flag=0;
  330. }
  331. if (i == 0) /* Must be spurious comma, or something */
  332. {
  333. ++tokens;
  334. --ntokens;
  335. continue;
  336. }
  337. if (addrs)
  338. {
  339. addrs->name=0;
  340. }
  341. /* Ok, now get rid of embedded comments in the address.
  342. Consider the last comment to be the real name */
  343. if (addrs)
  344. {
  345. save_token.ptr=0;
  346. save_token.len=0;
  347. for (j=k=0; j<i; j++)
  348. {
  349. if (tokens[j].token == '(')
  350. {
  351. save_token=tokens[j];
  352. continue;
  353. }
  354. tokens[k]=tokens[j];
  355. k++;
  356. }
  357. if (save_token.ptr)
  358. {
  359. tokens[i-1]=save_token;
  360. addrs->name=tokens+i-1;
  361. addrs->name->next=0;
  362. }
  363. addrs->tokens=k ? tokens:NULL;
  364. for (j=1; j<k; j++)
  365. addrs->tokens[j-1].next=addrs->tokens+j;
  366. if (k)
  367. addrs->tokens[k-1].next=0;
  368. ++addrs;
  369. }
  370. ++*naddrs;
  371. tokens += i;
  372. ntokens -= i;
  373. }
  374. }
  375. static void print_token(const struct rfc822token *token,
  376. void (*print_func)(char, void *), void *ptr)
  377. {
  378. const char *p;
  379. int n;
  380. if (token->token == 0 || token->token == '(')
  381. {
  382. for (n=token->len, p=token->ptr; n; --n, ++p)
  383. (*print_func)(*p, ptr);
  384. return;
  385. }
  386. if (token->token != '"')
  387. {
  388. (*print_func)(token->token, ptr);
  389. return;
  390. }
  391. (*print_func)('"', ptr);
  392. n=token->len;
  393. p=token->ptr;
  394. while (n)
  395. {
  396. if (*p == '"' || (*p == '\' && n == 1)) (*print_func)('\', ptr);
  397. if (*p == '\' && n > 1)
  398. {
  399. (*print_func)('\', ptr);
  400. ++p;
  401. --n;
  402. }
  403. (*print_func)(*p++, ptr);
  404. --n;
  405. }
  406. (*print_func)('"', ptr);
  407. }
  408. void rfc822tok_print(const struct rfc822token *token,
  409. void (*print_func)(char, void *), void *ptr)
  410. {
  411. int prev_isatom=0;
  412. int isatom;
  413. while (token)
  414. {
  415. isatom=rfc822_is_atom(token->token);
  416. if (prev_isatom && isatom)
  417. (*print_func)(' ', ptr);
  418. print_token(token, print_func, ptr);
  419. prev_isatom=isatom;
  420. token=token->next;
  421. }
  422. }
  423. void rfc822_print(const struct rfc822a *rfcp, void (*print_func)(char, void *),
  424. void (*print_separator)(const char *s, void *), void *ptr)
  425. {
  426. rfc822_print_common(rfcp, 0, 0, print_func, print_separator, ptr);
  427. }
  428. void rfc822_print_common(const struct rfc822a *rfcp,
  429. char *(*decode_func)(const char *, const char *), const char *chset,
  430. void (*print_func)(char, void *),
  431. void (*print_separator)(const char *, void *), void *ptr)
  432. {
  433. const struct rfc822addr *addrs=rfcp->addrs;
  434. int naddrs=rfcp->naddrs;
  435. while (naddrs)
  436. {
  437. if (addrs->tokens == 0)
  438. {
  439. rfc822tok_print(addrs->name, print_func, ptr);
  440. ++addrs;
  441. --naddrs;
  442. if (addrs[-1].name && naddrs)
  443. {
  444. struct rfc822token *t;
  445. for (t=addrs[-1].name; t && t->next; t=t->next)
  446. ;
  447. if (t && (t->token == ':' || t->token == ';'))
  448. (*print_separator)(" ", ptr);
  449. }
  450. continue;
  451. }
  452. else if (addrs->name && addrs->name->token == '(')
  453. { /* old style */
  454. char *p;
  455. rfc822tok_print(addrs->tokens, print_func, ptr);
  456. (*print_func)(' ', ptr);
  457. if (decode_func && (p=rfc822_gettok(addrs->name))!=0)
  458. {
  459. char *q= (*decode_func)(p, chset);
  460. char *r;
  461. for (r=q; r && *r; r++)
  462. (*print_func)( (int)(unsigned char)*r,
  463. ptr);
  464. if (q) free(q);
  465. free(p);
  466. }
  467. else rfc822tok_print(addrs->name, print_func, ptr);
  468. }
  469. else
  470. {
  471. int print_braces=0;
  472. char *p;
  473. if (addrs->name)
  474. {
  475. if (decode_func &&
  476. (p=rfc822_gettok(addrs->name)) != 0)
  477. {
  478. char *q= (*decode_func)(p, chset);
  479. char *r;
  480. for (r=q; r && *r; r++)
  481. (*print_func)(
  482. (int)(unsigned char)*r,
  483. ptr);
  484. if (q) free(q);
  485. free(p);
  486. }
  487. else rfc822tok_print(addrs->name,
  488. print_func, ptr);
  489. (*print_func)(' ', ptr);
  490. print_braces=1;
  491. }
  492. else
  493. {
  494. struct rfc822token *p;
  495. for (p=addrs->tokens; p && p->next; p=p->next)
  496. if (rfc822_is_atom(p->token) &&
  497. rfc822_is_atom(p->next->token))
  498. print_braces=1;
  499. }
  500. if (print_braces)
  501. (*print_func)('<', ptr);
  502. rfc822tok_print(addrs->tokens, print_func, ptr);
  503. if (print_braces)
  504. {
  505. (*print_func)('>', ptr);
  506. }
  507. }
  508. ++addrs;
  509. --naddrs;
  510. if (naddrs)
  511. if (addrs->tokens || (addrs->name &&
  512. rfc822_is_atom(addrs->name->token)))
  513. (*print_separator)(", ", ptr);
  514. }
  515. }
  516. void rfc822t_free(struct rfc822t *p)
  517. {
  518. if (p->tokens) free(p->tokens);
  519. free(p);
  520. }
  521. void rfc822a_free(struct rfc822a *p)
  522. {
  523. if (p->addrs) free(p->addrs);
  524. free(p);
  525. }
  526. void rfc822_deladdr(struct rfc822a *rfcp, int index)
  527. {
  528. int i;
  529. if (index < 0 || index >= rfcp->naddrs) return;
  530. for (i=index+1; i<rfcp->naddrs; i++)
  531. rfcp->addrs[i-1]=rfcp->addrs[i];
  532. if (--rfcp->naddrs == 0)
  533. {
  534. free(rfcp->addrs);
  535. rfcp->addrs=0;
  536. }
  537. }
  538. struct rfc822t *rfc822t_alloc(const char *addr,
  539. void (*err_func)(const char *, int))
  540. {
  541. struct rfc822t *p=(struct rfc822t *)malloc(sizeof(struct rfc822t));
  542. if (!p) return (NULL);
  543. memset(p, 0, sizeof(*p));
  544. tokenize(addr, NULL, &p->ntokens, err_func);
  545. p->tokens=p->ntokens ? (struct rfc822token *)
  546. calloc(p->ntokens, sizeof(struct rfc822token)):0;
  547. if (p->ntokens && !p->tokens)
  548. {
  549. rfc822t_free(p);
  550. return (NULL);
  551. }
  552. tokenize(addr, p->tokens, &p->ntokens, NULL);
  553. return (p);
  554. }
  555. struct rfc822a *rfc822a_alloc(struct rfc822t *t)
  556. {
  557. struct rfc822a *p=(struct rfc822a *)malloc(sizeof(struct rfc822a));
  558. if (!p) return (NULL);
  559. memset(p, 0, sizeof(*p));
  560. parseaddr(t->tokens, t->ntokens, NULL, &p->naddrs);
  561. p->addrs=p->naddrs ? (struct rfc822addr *)
  562. calloc(p->naddrs, sizeof(struct rfc822addr)):0;
  563. if (p->naddrs && !p->addrs)
  564. {
  565. rfc822a_free(p);
  566. return (NULL);
  567. }
  568. parseaddr(t->tokens, t->ntokens, p->addrs, &p->naddrs);
  569. return (p);
  570. }
  571. void rfc822_praddr(const struct rfc822a *rfcp, int index,
  572. void (*print_func)(char, void *), void *ptr)
  573. {
  574. const struct rfc822addr *addrs;
  575. if (index < 0 || index >= rfcp->naddrs) return;
  576. addrs=rfcp->addrs+index;
  577. if (addrs->tokens)
  578. {
  579. rfc822tok_print(addrs->tokens, print_func, ptr);
  580. (*print_func)('n', ptr);
  581. }
  582. }
  583. void rfc822_addrlist(const struct rfc822a *rfcp,
  584. void (*print_func)(char, void *), void *ptr)
  585. {
  586. int i;
  587. for (i=0; i<rfcp->naddrs; i++)
  588. rfc822_praddr(rfcp, i, print_func, ptr);
  589. }
  590. void rfc822_prname(const struct rfc822a *rfcp, int index,
  591. void (*print_func)(char, void *), void *ptr)
  592. {
  593. const struct rfc822addr *addrs;
  594. if (index < 0 || index >= rfcp->naddrs) return;
  595. addrs=rfcp->addrs+index;
  596. if (!addrs->tokens) return;
  597. if (addrs->name)
  598. {
  599. struct rfc822token *i;
  600. int n;
  601. int prev_isatom=0;
  602. int isatom=0;
  603. for (i=addrs->name; i; i=i->next, prev_isatom=isatom)
  604. {
  605. isatom=rfc822_is_atom(i->token);
  606. if (isatom && prev_isatom)
  607. (*print_func)(' ', ptr);
  608. if (i->token != '(')
  609. {
  610. print_token(i, print_func, ptr);
  611. continue;
  612. }
  613. for (n=2; n<i->len; n++)
  614. (*print_func)(i->ptr[n-1], ptr);
  615. }
  616. } else
  617. rfc822tok_print(addrs->tokens, print_func, ptr);
  618. (*print_func)('n', ptr);
  619. }
  620. void rfc822_namelist(const struct rfc822a *rfcp,
  621. void (*print_func)(char, void *), void *ptr)
  622. {
  623. int i;
  624. for (i=0; i<rfcp->naddrs; i++)
  625. rfc822_prname(rfcp, i, print_func, ptr);
  626. }