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

WEB邮件程序

开发平台:

C/C++

  1. /*
  2. ** Copyright 2000 Double Precision, Inc.  See COPYING for
  3. ** distribution information.
  4. */
  5. /*
  6. ** $Id: addressbook.c,v 1.5 2000/06/17 18:15:52 mrsam Exp $
  7. */
  8. #include "sqwebmail.h"
  9. #include "addressbook.h"
  10. #include "maildir.h"
  11. #include "cgi/cgi.h"
  12. #include "rfc822/rfc822.h"
  13. #include "maildir/maildirmisc.h"
  14. #include "numlib/numlib.h"
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <ctype.h>
  18. #define ADDRESSBOOK "sqwebmail-addressbook"
  19. extern char form_args[];
  20. extern void output_attrencoded(const char *);
  21. extern void output_attrencoded_fp(const char *, FILE *);
  22. /*
  23. ** When adding a new name/address pair into the address book delete
  24. ** bad characters from both.
  25. */
  26. static void fix_nameaddr(const char *name, const char *addr,
  27. char **nameret, char **addrret)
  28. {
  29. char *names, *addresss;
  30. char *p, *q;
  31. names=strdup(name);
  32. if (!names)
  33. {
  34. enomem();
  35. }
  36. for (p=q=names; *p; p++)
  37. {
  38. if (iscntrl((int)(unsigned char)*p)) continue;
  39. if (*p == '"' || *p == '\') continue;
  40. *q++=*p;
  41. }
  42. *q=0;
  43. if ((addresss=strdup(addr)) == 0)
  44. {
  45. free(names);
  46. enomem();
  47. }
  48. for (p=q=addresss; *p; p++)
  49. {
  50. if (isspace((int)(unsigned char)*p)) continue;
  51. if (iscntrl((int)(unsigned char)*p)) continue;
  52. if (*p == '<' || *p == '>' || *p == '(' || *p == ')' ||
  53. *p == '\')
  54. continue;
  55. *q++=*p;
  56. }
  57. *q=0;
  58. *nameret=names;
  59. *addrret=addresss;
  60. }
  61. void ab_add(const char *name, const char *address, const char *nick)
  62. {
  63. char *nicks, *names, *addresss, *p, *q;
  64. FILE *fp;
  65. char *header, *value;
  66. int new_fd;
  67. char *new_name;
  68. FILE *new_fp;
  69. int written;
  70. if (*nick == 0 || *address == 0)
  71. return;
  72. /* Delete bad characters from nickname, name, address */
  73. if ((nicks=strdup(nick)) == 0) enomem();
  74. for (p=q=nicks; *p; p++)
  75. {
  76. if (isspace((int)(unsigned char)*p)) continue;
  77. if (iscntrl((int)(unsigned char)*p)) continue;
  78. if (strchr(":;,<>@\", *p)) continue;
  79. *q++=*p;
  80. }
  81. *q=0;
  82. if (*nicks == 0)
  83. {
  84. free(nicks);
  85. return;
  86. }
  87. /* Remove quotes from name */
  88. fix_nameaddr(name, address, &names, &addresss);
  89. if (*addresss == 0)
  90. {
  91. free(addresss);
  92. free(nicks);
  93. free(names);
  94. return;
  95. }
  96. fp=fopen(ADDRESSBOOK, "r");
  97. new_fd=maildir_createmsg(INBOX, "addressbook", &new_name);
  98. p=malloc(sizeof("tmp/")+strlen(new_name));
  99. if (!p)
  100. {
  101. close(new_fd);
  102. free(new_name);
  103. enomem();
  104. }
  105. strcat(strcpy(p, "tmp/"), new_name);
  106. free(new_name);
  107. new_name=p;
  108. if (new_fd < 0 || (new_fp=fdopen(new_fd, "w")) == 0)
  109. {
  110. if (new_fd >= 0) close(new_fd);
  111. free(addresss);
  112. free(nicks);
  113. free(names);
  114. enomem();
  115. return;
  116. }
  117. written=0;
  118. while (fp && (header=maildir_readheader(fp, &value, 1)) != 0)
  119. {
  120. if (strcmp(header, nicks) == 0)
  121. {
  122. fprintf(new_fp, "%s: %s,n    ",
  123. nicks, value);
  124. written=1;
  125. break;
  126. }
  127. fprintf(new_fp, "%s: %sn", header, value);
  128. }
  129. if (!written)
  130. fprintf(new_fp, "%s: ", nicks);
  131. if (*names)
  132. fprintf(new_fp, ""%s" <%s>n",
  133. names, addresss);
  134. else
  135. fprintf(new_fp, "<%s>n", addresss);
  136. free(names);
  137. free(addresss);
  138. free(nicks);
  139. while (fp && (header=maildir_readheader(fp, &value, 1)) != 0)
  140. fprintf(new_fp, "%s: %sn", header, value);
  141. if (fp) fclose(fp);
  142. if (fflush(new_fp) || ferror(new_fp))
  143. {
  144. fclose(new_fp);
  145. close(new_fd);
  146. unlink(new_name);
  147. free(new_name);
  148. error("Unable to write out new address book -- write error, or out of disk space.");
  149. return;
  150. }
  151. fclose(new_fp);
  152. rename(new_name, ADDRESSBOOK);
  153. free(new_name);
  154. }
  155. static void dodel(const char *nick, struct rfc822a *a, int n,
  156. const char *replace_name, const char *replace_addr)
  157. {
  158. char *p;
  159. FILE *fp, *new_fp;
  160. char *new_name;
  161. int new_fd;
  162. char *header, *value;
  163. char *namebuf=0, *addrbuf=0;
  164. struct rfc822token namet, addresst;
  165. if (replace_name && replace_addr && n < a->naddrs)
  166. {
  167. fix_nameaddr(replace_name, replace_addr, &namebuf, &addrbuf);
  168. namet.token='"';
  169. namet.ptr=namebuf;
  170. namet.len=strlen(namebuf);
  171. namet.next=0;
  172. a->addrs[n].name= &namet;
  173. addresst.token=0;
  174. addresst.ptr=addrbuf;
  175. addresst.len=strlen(addrbuf);
  176. addresst.next=0;
  177. a->addrs[n].tokens= &addresst;
  178. }
  179. else
  180. {
  181. while (++n < a->naddrs)
  182. a->addrs[n-1]=a->addrs[n];
  183. --a->naddrs; /* It's that simple... */
  184. }
  185. fp=fopen(ADDRESSBOOK, "r");
  186. new_fd=maildir_createmsg(INBOX, "addressbook", &new_name);
  187. if (new_fd < 0 || (new_fp=fdopen(new_fd, "w")) == 0)
  188. {
  189. if (new_fd >= 0) close(new_fd);
  190. fclose(fp);
  191. enomem();
  192. return;
  193. }
  194. p=malloc(sizeof("tmp/")+strlen(new_name));
  195. if (!p)
  196. {
  197. unlink(new_name);
  198. fclose(fp);
  199. fclose(new_fp);
  200. free(new_name);
  201. enomem();
  202. }
  203. strcat(strcpy(p, "tmp/"), new_name);
  204. free(new_name);
  205. new_name=p;
  206. while (fp && (header=maildir_readheader(fp, &value, 1)) != 0)
  207. {
  208. if (strcmp(header, nick) == 0)
  209. {
  210. char *s, *t;
  211. if (a->naddrs == 0)
  212. continue;
  213. s=rfc822_getaddrs_wrap(a, 70);
  214. if (!s)
  215. {
  216. fclose(new_fp);
  217. close(new_fd);
  218. fclose(fp);
  219. unlink(new_name);
  220. enomem();
  221. }
  222. fprintf(new_fp, "%s: ", header);
  223. for (t=s; *t; t++)
  224. {
  225. putc(*t, new_fp);
  226. if (*t == 'n')
  227. fprintf(new_fp, "    ");
  228. }
  229. fprintf(new_fp, "n");
  230. free(s);
  231. continue;
  232. }
  233. fprintf(new_fp, "%s: %sn", header, value);
  234. }
  235. if (fp) fclose(fp);
  236. if (namebuf) free(namebuf);
  237. if (addrbuf) free(addrbuf);
  238. if (fflush(new_fp) || ferror(new_fp))
  239. {
  240. fclose(new_fp);
  241. unlink(new_name);
  242. free(new_name);
  243. error("Unable to write out new address book -- write error, or out of disk space.");
  244. return;
  245. }
  246. fclose(new_fp);
  247. rename(new_name, ADDRESSBOOK);
  248. free(new_name);
  249. }
  250. static void dodelall(const char *nick)
  251. {
  252. FILE *fp, *new_fp;
  253. int new_fd;
  254. char *new_name, *p;
  255. char *header, *value;
  256. fp=fopen(ADDRESSBOOK, "r");
  257. new_fd=maildir_createmsg(INBOX, "addressbook", &new_name);
  258. if (new_fd < 0 || (new_fp=fdopen(new_fd, "w")) == 0)
  259. {
  260. if (new_fd >= 0) close(new_fd);
  261. fclose(fp);
  262. enomem();
  263. return;
  264. }
  265. p=malloc(sizeof("tmp/")+strlen(new_name));
  266. if (!p)
  267. {
  268. unlink(new_name);
  269. fclose(fp);
  270. fclose(new_fp);
  271. free(new_name);
  272. enomem();
  273. }
  274. strcat(strcpy(p, "tmp/"), new_name);
  275. free(new_name);
  276. new_name=p;
  277. while (fp && (header=maildir_readheader(fp, &value, 1)) != 0)
  278. {
  279. if (strcmp(header, nick) == 0) continue;
  280. fprintf(new_fp, "%s: %sn", header, value);
  281. }
  282. if (fp) fclose(fp);
  283. if (fflush(new_fp) || ferror(new_fp))
  284. {
  285. fclose(new_fp);
  286. unlink(new_name);
  287. free(new_name);
  288. error("Unable to write out new address book -- write error, or out of disk space.");
  289. return;
  290. }
  291. fclose(new_fp);
  292. rename(new_name, ADDRESSBOOK);
  293. free(new_name);
  294. }
  295. void ab_listselect()
  296. {
  297. ab_listselect_fp(stdout);
  298. }
  299. struct abooklist {
  300. struct abooklist *next;
  301. char *name;
  302. } ;
  303. static void abl_free(struct abooklist *a)
  304. {
  305. struct abooklist *b;
  306. while (a)
  307. {
  308. b=a->next;
  309. free(a->name);
  310. free(a);
  311. a=b;
  312. }
  313. }
  314. static int sortabook(const void *a, const void *b)
  315. {
  316. return ( strcmp( (*(struct abooklist * const *)a)->name,
  317. (*(struct abooklist * const *)b)->name));
  318. }
  319. void ab_listselect_fp(FILE *w)
  320. {
  321. FILE *fp;
  322. char *header, *value;
  323. struct abooklist *a=0, *b, **aa;
  324. size_t acnt=0, i;
  325. if ((fp=fopen(ADDRESSBOOK, "r")) != 0)
  326. {
  327. while ((header=maildir_readheader(fp, &value, 1)) != NULL)
  328. {
  329. if ((b=malloc(sizeof(struct abooklist))) == 0 ||
  330. (b->name=strdup(header)) == 0)
  331. {
  332. if (b) free(b);
  333. abl_free(a);
  334. enomem();
  335. }
  336. b->next=a;
  337. a=b;
  338. acnt++;
  339. }
  340. fclose(fp);
  341. if ((aa=malloc(sizeof(struct abooklist *)*(acnt+1))) == 0)
  342. {
  343. abl_free(a);
  344. enomem();
  345. }
  346. for (acnt=0, b=a; b; b=b->next)
  347. aa[acnt++]=b;
  348. qsort(aa, acnt, sizeof(*aa), sortabook);
  349. for (i=0; i<acnt; i++)
  350. {
  351. fprintf(w, "<option value="");
  352. output_attrencoded_fp(aa[i]->name, w);
  353. fprintf(w, "">");
  354. output_attrencoded_fp(aa[i]->name, w);
  355. fprintf(w, "n");
  356. }
  357. free(aa);
  358. abl_free(a);
  359. }
  360. }
  361. const char *ab_find(const char *nick)
  362. {
  363. FILE *fp;
  364. char *header, *value;
  365. if ((fp=fopen(ADDRESSBOOK, "r")) != 0)
  366. {
  367. while ((header=maildir_readheader(fp, &value, 1)) != NULL)
  368. {
  369. if (strcmp(header, nick) == 0)
  370. {
  371. fclose(fp);
  372. return (value);
  373. }
  374. }
  375. fclose(fp);
  376. }
  377. return (0);
  378. }
  379. void addressbook()
  380. {
  381. FILE *fp;
  382. char    *header, *value;
  383. const char *nick_prompt=strtok(form_args, "|");
  384. const char *nick_submit=strtok(0, "|");
  385. const char *nick_title1=strtok(0, "|");
  386. const char *nick_title2=strtok(0, "|");
  387. const char *nick_delete=strtok(0, "|");
  388. const char *nick_name=strtok(0, "|");
  389. const char *nick_address=strtok(0, "|");
  390. const char *nick_add=strtok(0, "|");
  391. const char *nick_edit=strtok(0, "|");
  392. const char *nick1;
  393. int do_edit;
  394. char *s, *q, *r;
  395. char *edit_name=0;
  396. char *edit_addr=0;
  397. int replace_index=0;
  398. if (!nick_prompt) nick_prompt="";
  399. if (!nick_submit) nick_submit="";
  400. if (!nick_title1) nick_title1="";
  401. if (!nick_title2) nick_title2="";
  402. if (!nick_delete) nick_delete="";
  403. if (!nick_name) nick_name="";
  404. if (!nick_address) nick_address="";
  405. if (!nick_add) nick_add="";
  406. if (!nick_edit) nick_edit="";
  407. nick1=cgi("nick");
  408. do_edit=0;
  409. if (*cgi("nick.edit"))
  410. do_edit=1;
  411. else if (*cgi("nick.edit2"))
  412. {
  413. do_edit=1;
  414. nick1=cgi("nick2");
  415. }
  416. else if (*cgi("editnick"))
  417. {
  418. do_edit=1;
  419. nick1=cgi("editnick");
  420. }
  421. if (*cgi("ADDYCNT")) /* Import from LDAP */
  422. {
  423. unsigned counter=atoi(cgi("ADDYCNT"));
  424. char numbuf[NUMBUFSIZE];
  425. char numbuf2[NUMBUFSIZE+10];
  426. unsigned i;
  427. if (counter < 1 || counter > 1000)
  428. counter=1000;
  429. nick1=cgi("nick2");
  430. if (!*nick1)
  431. nick1=cgi("nick1");
  432. if (*nick1)
  433. {
  434. do_edit=1;
  435. for (i=0; i<counter; i++)
  436. {
  437. const char *addy=cgi(strcat(strcpy(numbuf2, "ADDY"),
  438.                                         str_size_t(i, numbuf)));
  439. char *addycpy;
  440. char *name;
  441. if (*addy == 0) continue;
  442. addycpy=strdup(addy);
  443. if (!addycpy) enomem();
  444. name=strchr(addycpy, '>');
  445. if (!name)
  446. {
  447. free(addycpy);
  448. continue;
  449. }
  450. *name++=0;
  451. while (*name == ' ') ++name;
  452. addy=addycpy;
  453. if (*addy == '<') ++addy;
  454. ab_add(name, addy, nick1);
  455. }
  456. }
  457. }
  458. if (*cgi("nick.delete"))
  459. {
  460. do_edit=0;
  461. dodelall(cgi("nick"));
  462. }
  463. else if (*cgi("add"))
  464. {
  465. const char *newname=cgi("newname");
  466. const char *newaddr=cgi("newaddress");
  467. const char *editnick=cgi("editnick");
  468. const char *replacenum=cgi("replacenick");
  469. if (*replacenum)
  470. {
  471. if ((fp=fopen(ADDRESSBOOK, "r")) != 0)
  472. {
  473. while ((header=maildir_readheader(fp,
  474. &value, 1)) != NULL)
  475. if (strcmp(header, editnick) == 0)
  476. break;
  477. if (header)
  478. {
  479. struct rfc822t *t;
  480. struct rfc822a *a;
  481. t=rfc822t_alloc(value, 0);
  482. a=t ? rfc822a_alloc(t):0;
  483. if (a)
  484. {
  485. dodel(editnick, a,
  486. atoi(replacenum),
  487. newname,
  488. newaddr);
  489. rfc822a_free(a);
  490. }
  491. if (t) rfc822t_free(t);
  492. }
  493. fclose(fp);
  494. }
  495. }
  496. else
  497. ab_add(newname, newaddr, editnick);
  498. do_edit=1;
  499. nick1=editnick;
  500. }
  501. printf("%s", nick_prompt);
  502. printf("<select name="nick">n");
  503. printf("<option value="">n");
  504. ab_listselect();
  505. printf("</select>n");
  506. printf("%s", nick_submit);
  507. s=strdup(nick1);
  508. if (!s) enomem();
  509. for (q=r=s; *q; q++)
  510. {
  511. if (isspace((int)(unsigned char)*q) ||
  512. strchr(",;:()"%@<>'!", *q))
  513. continue;
  514. *r++=*q;
  515. }
  516. *r=0;
  517. if (do_edit && *s)
  518. {
  519. printf("%s%s%s", nick_title1, s, nick_title2);
  520. printf("<input type=hidden name="editnick" value="");
  521. output_attrencoded(s);
  522. printf("">n");
  523. printf("<table border=0 align=center>");
  524. if ((fp=fopen(ADDRESSBOOK, "r")) != 0)
  525. {
  526. while ((header=maildir_readheader(fp, &value, 1))
  527. != NULL)
  528. if (strcmp(header, s) == 0)
  529. break;
  530. if (header)
  531. {
  532. struct rfc822t *t;
  533. struct rfc822a *a;
  534. char *save_value=strdup(value);
  535. if (!save_value)
  536. {
  537. fclose(fp);
  538. free(s);
  539. enomem();
  540. }
  541. strcpy(save_value, value);
  542. /* Need copy 'cause dodel also
  543. ** calls maildir_readheader */
  544. t=rfc822t_alloc(save_value, 0);
  545. a=t ? rfc822a_alloc(t):0;
  546. if (a)
  547. {
  548. int i;
  549. for (i=0; i<a->naddrs; i++)
  550. {
  551. char buf[100];
  552. sprintf(buf, "del%d", i);
  553. if (*cgi(buf))
  554. {
  555. dodel(s, a, i, 0, 0);
  556. break;
  557. }
  558. sprintf(buf, "startedit%d", i);
  559. if (*cgi(buf))
  560. {
  561. if (edit_name)
  562. free(edit_name);
  563. edit_name=
  564. rfc822_getname(
  565. a, i);
  566. if (edit_addr)
  567. free(edit_addr);
  568. edit_addr=
  569. rfc822_getaddr(
  570. a, i);
  571. replace_index=i;
  572. break;
  573. }
  574. }
  575. }
  576. if (a)
  577. {
  578. int i;
  579. for (i=0; i<a->naddrs; i++)
  580. {
  581. char *s;
  582. if (a->addrs[i].tokens == 0)
  583. continue;
  584. printf("<tr><td align=right>");
  585. s=rfc822_getname(a, i);
  586. if (s && a->addrs[i].name)
  587. /* getname defaults it
  588. ** here.
  589. */
  590. {
  591. printf(""");
  592. output_attrencoded(s);
  593. free(s);
  594. printf(""");
  595. }
  596. printf("</td><td align=left>&lt;");
  597. s=rfc822_getaddr(a, i);
  598. if (s)
  599. {
  600. output_attrencoded(s);
  601. free(s);
  602. }
  603. printf("&gt;</td><td><input type=submit name="startedit%d" value="%s">&nbsp;<input type=submit name="del%d" value="%s"></td></tr>n",
  604. i, nick_edit,
  605. i, nick_delete);
  606. }
  607. rfc822a_free(a);
  608. }
  609. if (t) rfc822t_free(t);
  610. free(save_value);
  611. }
  612. fclose(fp);
  613. }
  614. printf("<tr><td colspan=3><hr width="90%%"></td></tr>n");
  615. printf("<tr><td align=right>%s</td><td colspan=2><input type=text name=newname", nick_name);
  616. if (edit_name)
  617. {
  618. printf(" value="");
  619. output_attrencoded(edit_name);
  620. printf(""");
  621. }
  622. printf("></td></tr>n");
  623. printf("<tr><td align=right>%s</td><td><input type=text name=newaddress", nick_address);
  624. if (edit_addr)
  625. {
  626. printf(" value="");
  627. output_attrencoded(edit_addr);
  628. printf(""");
  629. }
  630. printf("></td><td>");
  631. if (edit_name || edit_addr)
  632. printf("<input type=hidden name=replacenick value=%d>",
  633. replace_index);
  634. printf("<input type=submit name=add value="%s"></td></tr>n",
  635. edit_name || edit_addr ? nick_edit:nick_add);
  636. printf("</table>");
  637. }
  638. free(s);
  639. if (edit_name)
  640. free(edit_name);
  641. if (edit_addr)
  642. free(edit_addr);
  643. }