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

WEB邮件程序

开发平台:

C/C++

  1. /*
  2. ** Copyright 1998 - 1999 Double Precision, Inc.  See COPYING for
  3. ** distribution information.
  4. */
  5. /*
  6. ** $Id: newmsg_create.c,v 1.29 2000/06/18 01:26:21 mrsam Exp $
  7. */
  8. #include "config.h"
  9. #include "cgi/cgi.h"
  10. #include "sqconfig.h"
  11. #include "sqwebmail.h"
  12. #include "auth.h"
  13. #include "maildir.h"
  14. #include "folder.h"
  15. #include "filter.h"
  16. #include "pref.h"
  17. #include "addressbook.h"
  18. #include "maildir/maildirmisc.h"
  19. #include "rfc822/rfc822.h"
  20. #include "rfc2045/rfc2045.h"
  21. #include "rfc822/rfc2047.h"
  22. #include "http11/http11.h"
  23. #include "htmllibdir.h"
  24. #include <stdlib.h>
  25. #if HAVE_UNISTD_H
  26. #include <unistd.h>
  27. #endif
  28. #include <ctype.h>
  29. #include <fcntl.h>
  30. extern const char *rfc822_mkdt(time_t);
  31. extern const char *sqwebmail_content_charset;
  32. extern const char *sqwebmail_content_language;
  33. int newdraftfd;
  34. extern const char *sqwebmail_mailboxid;
  35. const char mimemsg[]="This is a MIME-formatted message.  If you see this text it means that yournmail software cannot handle MIME-formatted messages.nn";
  36. char *newmsg_createdraft_do(const char *, const char *, int);
  37. /* Save message in a draft file */
  38. char *newmsg_createdraft(const char *curdraft)
  39. {
  40. if (curdraft && *curdraft)
  41. {
  42. char *base=maildir_basename(curdraft);
  43. char *filename=maildir_find(DRAFTS, base);
  44. if (filename)
  45. {
  46. char *p=newmsg_createdraft_do(filename, cgi("message"), 0);
  47. free(filename);
  48. free(base);
  49. return (p);
  50. }
  51. free(base);
  52. }
  53. return (newmsg_createdraft_do(0, cgi("message"), 0));
  54. }
  55. static void create_draftheader_do(const char *hdrname, const char *p,
  56. int isrfc822addr);
  57. static void create_draftheader(const char *hdrname, const char *p,
  58. const char *q, int isrfc822addr)
  59. {
  60. if (q && *q) /* Add from address book */
  61. {
  62. char *nick=cgi_multiple("nick", ",");
  63. char *s;
  64. if (nick)
  65. {
  66. s=malloc(strlen(p)+strlen(nick)+2);
  67. if (s)
  68. {
  69. strcpy(s, p);
  70. if (*s && *nick) strcat(s, ",");
  71. strcat(s, nick);
  72. create_draftheader_do(hdrname, s, isrfc822addr);
  73. free(s);
  74. free(nick);
  75. return;
  76. }
  77. free(nick);
  78. }
  79. }
  80. create_draftheader_do(hdrname, p, isrfc822addr);
  81. }
  82. static void create_draftheader_do(const char *hdrname, const char *p,
  83. int isrfc822addr)
  84. {
  85. char *s;
  86. if (!*p) return;
  87. if (!isrfc822addr)
  88. {
  89. s=rfc2047_encode_str(p, sqwebmail_content_charset);
  90. }
  91. else
  92. {
  93. struct rfc822t *t;
  94. struct rfc822a *a;
  95. /*
  96. ** For proper RFC 2047 encoding, we must RFC822-parse
  97. ** this header.
  98. */
  99. s=0;
  100. if ((t=rfc822t_alloc(p, 0)) != 0)
  101. {
  102. if ((a=rfc822a_alloc(t)) != 0)
  103. {
  104. s=rfc2047_encode_header(a,
  105. sqwebmail_content_charset);
  106. rfc822a_free(a);
  107. }
  108. rfc822t_free(t);
  109. }
  110. }
  111. if (!s)
  112. {
  113. close(newdraftfd);
  114. enomem();
  115. }
  116. maildir_writemsgstr(newdraftfd, hdrname);
  117. maildir_writemsgstr(newdraftfd, s);
  118. maildir_writemsgstr(newdraftfd, "n");
  119. free(s);
  120. }
  121. void newmsg_create_multipart(int newdraftfd, const char *charset,
  122. const char *multipart_boundary)
  123. {
  124. maildir_writemsgstr(newdraftfd,
  125. "Mime-version: 1.0n"
  126. "Content-Type: multipart/mixed; boundary="");
  127. maildir_writemsgstr(newdraftfd, multipart_boundary);
  128. maildir_writemsgstr(newdraftfd, ""; charset="");
  129. maildir_writemsgstr(newdraftfd, charset);
  130. maildir_writemsgstr(newdraftfd, 
  131. ""nn");
  132. maildir_writemsgstr(newdraftfd, mimemsg);
  133. }
  134. static char *newmsg_multipart_boundary(FILE *, const char *);
  135. static void newmsg_copy_attachments(FILE *, const char *);
  136. void newmsg_copy_nonmime_headers(FILE *fp)
  137. {
  138. char *header, *value;
  139. char *q;
  140. while ((header=maildir_readheader(fp, &value, 1)) != NULL)
  141. {
  142. if (strcmp(header, "mime-version") == 0 ||
  143. strncmp(header, "content-", 8) == 0) continue;
  144. /* Fluff - capitalize header names */
  145. for (q=header; *q; q++)
  146. {
  147. for (*q=toupper(*q); *q; q++)
  148. if (*q == '-') break;
  149. }
  150. maildir_writemsgstr(newdraftfd, header);
  151. maildir_writemsgstr(newdraftfd, ": ");
  152. maildir_writemsgstr(newdraftfd, value);
  153. maildir_writemsgstr(newdraftfd, "n");
  154. }
  155. }
  156. static void do_save(const char *, size_t);
  157. char *newmsg_createdraft_do(const char *curdraft, const char *newmsg,
  158. int keepheader)
  159. {
  160. char *draftfilename;
  161. FILE *fp=0;
  162. char *multipart_boundary;
  163. const char *content_type;
  164. const char *content_transfer_encoding;
  165. const char *charset;
  166. unsigned long prev_size=0;
  167. off_t transferencodingpos;
  168. if (curdraft) /* Reuse a draft filename */
  169. newdraftfd=maildir_recreatemsg(DRAFTS, curdraft, &draftfilename);
  170. else
  171. newdraftfd=maildir_createmsg(DRAFTS, 0, &draftfilename);
  172. if (newdraftfd < 0) enomem();
  173. fp=NULL;
  174. if (curdraft)
  175. {
  176. int x=maildir_safeopen(curdraft, O_RDONLY, 0);
  177. if (x >= 0)
  178. if ((fp=fdopen(x, "r")) == 0)
  179. close(x);
  180. }
  181. if (fp)
  182. {
  183. char *header, *value;
  184. struct stat stat_buf;
  185. if (fstat(fileno(fp), &stat_buf))
  186. {
  187. fclose(fp);
  188. enomem();
  189. }
  190. prev_size=stat_buf.st_size;
  191. while ((header=maildir_readheader(fp, &value, 1)) != NULL)
  192. {
  193. if (!keepheader)
  194. {
  195. if (strcmp(header, "in-reply-to") &&
  196. strcmp(header, "references") &&
  197. strncmp(header, "x-", 2)) continue;
  198. /* Do not discard these headers */
  199. }
  200. else /* Called from spell */
  201. {
  202. if (strcasecmp(header, "mime-version") == 0 ||
  203. strncasecmp(header, "content-", 8) == 0)
  204. continue;
  205. }
  206. maildir_writemsgstr(newdraftfd, header);
  207. maildir_writemsgstr(newdraftfd, ": ");
  208. maildir_writemsgstr(newdraftfd, value);
  209. maildir_writemsgstr(newdraftfd, "n");
  210. }
  211. }
  212. if (!keepheader) /* Coming back from msg edit, set headers */
  213. {
  214. time_t t;
  215. const char *p=cgi("headerfrom");
  216. if (!*p) p=pref_from;
  217. if (!p || !*p || access(NOCHANGINGFROM, 0) == 0)
  218. p=login_fromhdr();
  219. create_draftheader("From: ", p, 0, 1);
  220. if (!pref_from || strcmp(p, pref_from))
  221. pref_setfrom(p);
  222. /* sam ????
  223. create_draftheader("In-Reply-To: ", cgi("headerin-reply-to"));
  224. */
  225. create_draftheader("To: ", cgi("headerto"),
  226. cgi("addressbook_to"), 1);
  227. create_draftheader("Cc: ", cgi("headercc"),
  228. cgi("addressbook_cc"), 1);
  229. create_draftheader("Bcc: ", cgi("headerbcc"),
  230. cgi("addressbook_bcc"), 1);
  231. create_draftheader("Reply-To: ", cgi("headerreply-to"), 0, 1);
  232. create_draftheader("Subject: ", cgi("headersubject"), 0, 0);
  233. maildir_writemsgstr(newdraftfd, "Date: ");
  234. time (&t);
  235. maildir_writemsgstr(newdraftfd, rfc822_mkdt(t));
  236. maildir_writemsgstr(newdraftfd, "n");
  237. }
  238. /* If the message has attachments, calculate multipart boundary */
  239. multipart_boundary=fp ? newmsg_multipart_boundary(fp, newmsg) : NULL;
  240. if (multipart_boundary)
  241. {
  242. struct rfc2045 *rfcp=rfc2045_fromfp(fp), *q;
  243. /* Copy over existing charset */
  244. if (!rfcp)
  245. {
  246. close(newdraftfd);
  247. fclose(fp);
  248. enomem();
  249. }
  250. rfc2045_mimeinfo(rfcp, &content_type,
  251. &content_transfer_encoding, &charset);
  252. newmsg_create_multipart(newdraftfd,
  253. sqwebmail_content_charset, multipart_boundary);
  254. maildir_writemsgstr(newdraftfd, "--");
  255. maildir_writemsgstr(newdraftfd, multipart_boundary);
  256. for (q=rfcp->firstpart; q; q=q->next)
  257. {
  258. if (q->isdummy) continue;
  259. rfc2045_mimeinfo(q, &content_type,
  260. &content_transfer_encoding, &charset);
  261. if (strcmp(content_type, "text/plain") == 0) break;
  262. }
  263. maildir_writemsgstr(newdraftfd, "nContent-Type: text/plain");
  264. if (q)
  265. {
  266. maildir_writemsgstr(newdraftfd, "; charset="");
  267. maildir_writemsgstr(newdraftfd,
  268. sqwebmail_content_charset);
  269. maildir_writemsgstr(newdraftfd, """);
  270. }
  271. rfc2045_free(rfcp);
  272. maildir_writemsgstr(newdraftfd, "n");
  273. }
  274. else
  275. {
  276. struct rfc2045 *rfcp;
  277. if (fp)
  278. {
  279. rfcp=rfc2045_fromfp(fp);
  280. if (!rfcp)
  281. {
  282. close(newdraftfd);
  283. fclose(fp);
  284. enomem();
  285. }
  286. rfc2045_mimeinfo(rfcp, &content_type,
  287. &content_transfer_encoding, &charset);
  288. }
  289. else
  290. {
  291. rfcp=0;
  292. charset=sqwebmail_content_charset;
  293. }
  294. maildir_writemsgstr(newdraftfd, "Mime-Version: 1.0nContent-Type: text/plain; charset="");
  295. maildir_writemsgstr(newdraftfd, charset);
  296. maildir_writemsgstr(newdraftfd, ""n");
  297. if (rfcp)
  298. rfc2045_free(rfcp);
  299. }
  300. maildir_writemsgstr(newdraftfd, "Content-Transfer-Encoding: ");
  301. transferencodingpos=writebufpos;
  302. maildir_writemsgstr(newdraftfd, "7bitnn");
  303. maildir_writemsgstr(newdraftfd, "n");
  304. {
  305. char *buf=strdup(newmsg);
  306. size_t i,j;
  307. for (i=j=0; buf[i]; i++)
  308. if (buf[i] != 'r') buf[j++]=buf[i];
  309. filter_start(FILTER_FOR_SAVING, &do_save);
  310. filter(buf, j);
  311. if (j && buf[j-1] != 'n')
  312. filter("n", 1);
  313. filter_end();
  314. free(buf);
  315. }
  316. if ( multipart_boundary)
  317. {
  318. newmsg_copy_attachments(fp, multipart_boundary);
  319. maildir_writemsgstr(newdraftfd, "n--");
  320. maildir_writemsgstr(newdraftfd, multipart_boundary);
  321. maildir_writemsgstr(newdraftfd, "--n");
  322. free(multipart_boundary);
  323. }
  324. if (fp) fclose(fp);
  325. if ( maildir_writemsg_flush(newdraftfd) == 0 && writebuf8bit)
  326. {
  327. if (lseek(newdraftfd, transferencodingpos, SEEK_SET) < 0 ||
  328. write(newdraftfd, "8", 1) != 1)
  329. {
  330. close(newdraftfd);
  331. enomem();
  332. }
  333. }
  334. if ( maildir_closemsg(newdraftfd, DRAFTS, draftfilename, -1, prev_size))
  335. cgi_put("error", "quota");
  336. return(draftfilename);
  337. }
  338. static void do_save(const char *p, size_t l)
  339. {
  340. maildir_writemsg(newdraftfd, p, l);
  341. }
  342. /* Create message in the sent folder */
  343. static void sentmsg_copy(FILE *, struct rfc2045 *);
  344. static void sentmsg_reformat(FILE *, struct rfc2045 *);
  345. extern void header_uc(char *h);
  346. struct lookup_buffers {
  347. struct lookup_buffers *next;
  348. char *buf;
  349. char *buf2;
  350. } ;
  351. static int lookup_addressbook_do(const char *header, const char *value,
  352. struct lookup_buffers **lookup_buffer_list)
  353. {
  354. struct rfc822t *t;
  355. struct rfc822a *a;
  356. int i;
  357. char *newbuf;
  358. struct lookup_buffers *ptr;
  359. int expanded=0;
  360. t=rfc822t_alloc(value, 0);
  361. if (!t) enomem();
  362. a=rfc822a_alloc(t);
  363. if (!a)
  364. {
  365. rfc822t_free(t);
  366. enomem();
  367. }
  368. for (i=0; i<a->naddrs; i++)
  369. {
  370. char *p;
  371. const char *q;
  372. struct lookup_buffers *r;
  373. if (a->addrs[i].tokens == 0)
  374. continue;
  375. if (a->addrs[i].name)
  376. continue; /* Can't be a nickname */
  377. p=rfc822_getaddr(a, i);
  378. if (!p)
  379. {
  380. rfc822a_free(a);
  381. rfc822t_free(t);
  382. free(p);
  383. return (-1);
  384. }
  385. for (ptr= *lookup_buffer_list; ptr; ptr=ptr->next)
  386. if (strcmp(ptr->buf2, p) == 0)
  387. break;
  388. if (ptr) /* Address book loop */
  389. {
  390. int j;
  391. for (j=i+1; j<a->naddrs; j++)
  392. a->addrs[j-1]=a->addrs[j];
  393. --a->naddrs;
  394. --i;
  395. free(p);
  396. continue;
  397. }
  398. if ((q=ab_find(p)) == 0)
  399. {
  400. free(p);
  401. continue;
  402. }
  403. r=malloc(sizeof(struct lookup_buffers));
  404. if (r) r->buf=r->buf2=0;
  405. if (!r || !(r->buf=strdup(q)) || !(r->buf2=strdup(p)))
  406. {
  407. free(p);
  408. if (r && r->buf) free(r->buf);
  409. if (r) free(r);
  410. rfc822a_free(a);
  411. rfc822t_free(t);
  412. return (-1);
  413. }
  414. free(p);
  415. r->next= *lookup_buffer_list;
  416. *lookup_buffer_list=r;
  417. a->addrs[i].tokens->next=0;
  418. a->addrs[i].tokens->token=0;
  419. a->addrs[i].tokens->ptr=r->buf;
  420. a->addrs[i].tokens->len=strlen(r->buf);
  421. expanded=1;
  422. }
  423. newbuf=rfc822_getaddrs_wrap(a, 70);
  424. rfc822a_free(a);
  425. rfc822t_free(t);
  426. if (!newbuf) return (-1);
  427. if (expanded) /* Look through the address book again */
  428. {
  429. int rc=lookup_addressbook_do(header, newbuf, lookup_buffer_list);
  430. free(newbuf);
  431. return (rc);
  432. }
  433. create_draftheader_do(header, newbuf, 1);
  434. free(newbuf);
  435. return (0);
  436. }
  437. static void lookup_addressbook(const char *header, const char *value)
  438. {
  439. struct lookup_buffers *lookup_buffer_list=0;
  440. int rc;
  441. char *s=strdup(value);
  442. if (!s) enomem();
  443. rc=lookup_addressbook_do(header, s, &lookup_buffer_list);
  444. free(s);
  445. while (lookup_buffer_list)
  446. {
  447. struct lookup_buffers *p=lookup_buffer_list;
  448. lookup_buffer_list=p->next;
  449. free(p->buf);
  450. free(p->buf2);
  451. free(p);
  452. }
  453. if (rc) enomem();
  454. }
  455. char *newmsg_createsentmsg(const char *draftname)
  456. {
  457. char *filename=maildir_find(DRAFTS, draftname);
  458. FILE *fp;
  459. char *sentname;
  460. char *header, *value;
  461. struct rfc2045 *rfcp;
  462. int x;
  463. #if 0
  464. off_t transferencodingpos;
  465. #endif
  466. if (!filename) return (0);
  467. fp=0;
  468. x=maildir_safeopen(filename, O_RDONLY, 0);
  469. if (x >= 0)
  470. if ((fp=fdopen(x, "r")) == 0)
  471. close(x);
  472. if (fp == 0)
  473. {
  474. free(filename);
  475. enomem();
  476. }
  477. newdraftfd=maildir_createmsg(SENT, 0, &sentname);
  478. if (newdraftfd < 0)
  479. {
  480. free(filename);
  481. fclose(fp);
  482. enomem();
  483. }
  484. /* First, copy all headers except X- headers */
  485. while ((header=maildir_readheader(fp, &value, 1)) != 0)
  486. {
  487. if (strncmp(header, "x-", 2) == 0) continue;
  488. header_uc(header);
  489. if (strcasecmp(header, "To") == 0)
  490. {
  491. lookup_addressbook("To: ", value);
  492. continue;
  493. }
  494. if (strcasecmp(header, "Cc") == 0)
  495. {
  496. lookup_addressbook("Cc: ", value);
  497. continue;
  498. }
  499. if (strcasecmp(header, "Bcc") == 0)
  500. {
  501. lookup_addressbook("Bcc: ", value);
  502. continue;
  503. }
  504. maildir_writemsgstr(newdraftfd, header);
  505. maildir_writemsgstr(newdraftfd, ": ");
  506. maildir_writemsgstr(newdraftfd, value);
  507. maildir_writemsgstr(newdraftfd, "n");
  508. }
  509. if (access(USEXSENDER, 0) == 0)
  510. {
  511. maildir_writemsgstr(newdraftfd, "X-Sender: ");
  512. maildir_writemsgstr(newdraftfd, login_returnaddr());
  513. maildir_writemsgstr(newdraftfd, "n");
  514. }
  515. #if 0
  516. maildir_writemsgstr(newdraftfd, "Content-Transfer-Encoding: ");
  517. transferencodingpos=writebufpos;
  518. maildir_writemsgstr(newdraftfd, "7bitn");
  519. #endif
  520. maildir_writemsgstr(newdraftfd, "n");
  521. rfcp=rfc2045_fromfp(fp);
  522. if (!rfcp)
  523. {
  524. fclose(fp);
  525. close(newdraftfd);
  526. enomem();
  527. }
  528. if (!rfcp->firstpart)
  529. sentmsg_reformat(fp, rfcp);
  530. else
  531. {
  532. int found_textplain=0;
  533. struct rfc2045 *p;
  534. for (p=rfcp->firstpart; p; p=p->next)
  535. {
  536. const char *content_type;
  537. const char *content_transfer_encoding;
  538. const char *charset;
  539. rfc2045_mimeinfo(p, &content_type,
  540. &content_transfer_encoding, &charset);
  541. if (strcmp(content_type, "text/plain") == 0 &&
  542. !p->isdummy && !found_textplain)
  543. {
  544. maildir_writemsgstr(newdraftfd,
  545. "Content-Type: text/plain; charset=");
  546. maildir_writemsgstr(newdraftfd, charset);
  547. maildir_writemsgstr(newdraftfd,
  548. "nContent-Transfer-Encoding: ");
  549. maildir_writemsgstr(newdraftfd,
  550. content_transfer_encoding);
  551. maildir_writemsgstr(newdraftfd, "nn");
  552. sentmsg_reformat(fp, p);
  553. found_textplain=1;
  554. }
  555. else sentmsg_copy(fp, p);
  556. maildir_writemsgstr(newdraftfd, "n--");
  557. maildir_writemsgstr(newdraftfd, rfc2045_boundary(rfcp));
  558. if (!p->next)
  559. maildir_writemsgstr(newdraftfd, "--");
  560. maildir_writemsgstr(newdraftfd, "n");
  561. }
  562. }
  563. if ( maildir_writemsg_flush(newdraftfd))
  564. {
  565. free(sentname);
  566. return (0);
  567. }
  568. #if 0
  569. if (writebuf8bit)
  570. {
  571. if (lseek(newdraftfd, transferencodingpos, SEEK_SET) < 0 ||
  572. write(newdraftfd, "8", 1) != 1)
  573. {
  574. free(sentname);
  575. return (0);
  576. }
  577. }
  578. #endif
  579. if ( maildir_closemsg(newdraftfd, SENT, sentname, 1, 0))
  580. {
  581. free(sentname);
  582. return (0);
  583. }
  584. return (sentname);
  585. }
  586. /* Note - sentmsg_copy is also reused in newmsg_copy_attachments */
  587. static void sentmsg_copy(FILE *f, struct rfc2045 *p)
  588. {
  589. off_t start_pos, end_pos, start_body;
  590. char buf[512];
  591. int n;
  592. off_t dummy;
  593. rfc2045_mimepos(p, &start_pos, &end_pos, &start_body, &dummy, &dummy);
  594. if (fseek(f, start_pos, SEEK_SET) == -1)
  595. {
  596. fclose(f);
  597. close(newdraftfd);
  598. enomem();
  599. }
  600. while (start_pos < end_pos)
  601. {
  602. int cnt=sizeof(buf);
  603. if (cnt > end_pos - start_pos)
  604. cnt=end_pos - start_pos;
  605. if ((n=fread(buf, 1, cnt, f)) <= 0)
  606. {
  607. fclose(f);
  608. close(newdraftfd);
  609. enomem();
  610. }
  611. maildir_writemsg(newdraftfd, buf, n);
  612. start_pos += n;
  613. }
  614. }
  615. static void write_to_draft(const char *p, size_t l)
  616. {
  617. maildir_writemsg(newdraftfd, p, l);
  618. }
  619. static void sentmsg_reformat(FILE *f, struct rfc2045 *p)
  620. {
  621. off_t start_pos, end_pos, start_body;
  622. char buf[BUFSIZ];
  623. int n;
  624. off_t dummy;
  625. FILE *fp;
  626. rfc2045_mimepos(p, &start_pos, &end_pos, &start_body,
  627. &dummy, &dummy);
  628. if (fseek(f, start_body, SEEK_SET) == -1)
  629. {
  630. fclose(f);
  631. close(newdraftfd);
  632. enomem();
  633. }
  634. filter_start(FILTER_FOR_SENDING, &write_to_draft);
  635. while (start_body < end_pos)
  636. {
  637. int cnt=sizeof(buf);
  638. if (cnt > end_pos - start_body)
  639. cnt=end_pos - start_body;
  640. if ((n=fread(buf, 1, cnt, f)) <= 0)
  641. {
  642. fclose(f);
  643. close(newdraftfd);
  644. enomem();
  645. }
  646. filter(buf, n);
  647. start_body += n;
  648. }
  649. fp=http11_open_langfile(HTMLLIBDIR, sqwebmail_content_language,
  650. "footer");
  651. if (fp != 0)
  652. {
  653. while ((n=fread(buf, 1, sizeof(buf), fp)) > 0)
  654. filter(buf, n);
  655. fclose(fp);
  656. }
  657. filter_end();
  658. }
  659. /* ---------------------------------------------------------------------- */
  660. /* Create a potential multipart boundary separator tag */
  661. char *multipart_boundary_create()
  662. {
  663. char pidbuf[MAXLONGSIZE];
  664. char timebuf[MAXLONGSIZE];
  665. time_t t;
  666. char cntbuf[MAXLONGSIZE];
  667. unsigned long cnt=0;
  668. char *p;
  669. sprintf(pidbuf, "%lu", (unsigned long)getpid());
  670. time(&t);
  671. sprintf(timebuf, "%lu", (unsigned long)t);
  672. sprintf(cntbuf, "%lu", cnt++);
  673. p=malloc(strlen(pidbuf)+strlen(timebuf) +strlen(cntbuf)+10);
  674. sprintf(p, "=_%s_%s_%s", cntbuf, pidbuf, timebuf);
  675. return (p);
  676. }
  677. /* Search for the boundary tag in a string buffer - this is the new message
  678. ** we're creating.  We should really look for the tag at the beginning of the
  679. ** line, however, the text is not yet linewrapped, besides, why make your
  680. ** life hard?
  681. */
  682. int multipart_boundary_checks(const char *boundary, const char *msg)
  683. {
  684. size_t boundarylen=strlen(boundary);
  685. while (*msg)
  686. {
  687. if (msg[0] == '-' && msg[1] == '-' && msg[2] != '-' &&
  688. strncasecmp(msg+2, boundary, boundarylen) == 0)
  689. return (-1);
  690. ++msg;
  691. }
  692. return (0);
  693. }
  694. /* Again, just look for it at the beginning of the line -- why make your
  695. ** life hard? */
  696. int multipart_boundary_checkf(const char *boundary, FILE *f)
  697. {
  698. size_t boundarylen=strlen(boundary);
  699. const char *line;
  700. if (fseek(f, 0L, SEEK_SET) == -1)
  701. {
  702. fclose(f);
  703. close(newdraftfd);
  704. enomem();
  705. }
  706. while ((line=maildir_readline(f)) != 0)
  707. if (line[0] == '-' && line[1] == '-' &&
  708. strncasecmp(line+2, boundary, boundarylen) == 0)
  709. return (-1);
  710. return (0);
  711. }
  712. /* ---------------------------------------------------------------------- */
  713. /* Copy existing attachments into the new draft message */
  714. /* multipart_boundary - determine if current draft has attachments */
  715. static struct rfc2045 *copyrfc2045;
  716. static char *newmsg_multipart_boundary(FILE *f, const char *msg)
  717. {
  718. char *p=0;
  719. copyrfc2045=rfc2045_fromfp(f);
  720. if (!copyrfc2045)
  721. {
  722. fclose(f);
  723. close(newdraftfd);
  724. enomem();
  725. }
  726. if ( copyrfc2045->firstpart == 0)
  727. {
  728. rfc2045_free(copyrfc2045);
  729. return (0);
  730. }
  731. do
  732. {
  733. if (p) free(p);
  734. p=multipart_boundary_create();
  735. } while (multipart_boundary_checks(p, msg)
  736. || multipart_boundary_checkf(p, f));
  737. return (p);
  738. }
  739. static void newmsg_copy_attachments(FILE *f, const char *boundary)
  740. {
  741. struct rfc2045 *p;
  742. int foundtextplain=0;
  743. const char *content_type;
  744. const char *content_transfer_encoding;
  745. const char *charset;
  746. for (p=copyrfc2045->firstpart; p; p=p->next)
  747. {
  748. if (p->isdummy) continue;
  749. rfc2045_mimeinfo(p, &content_type,
  750. &content_transfer_encoding, &charset);
  751. if (!foundtextplain && strcmp(content_type,
  752. "text/plain") == 0)
  753. { /* Previous version of this message */
  754. foundtextplain=1;
  755. continue;
  756. }
  757. maildir_writemsgstr(newdraftfd, "n--");
  758. maildir_writemsgstr(newdraftfd, boundary);
  759. maildir_writemsgstr(newdraftfd, "n");
  760. sentmsg_copy(f, p); /* Reuse some code */
  761. }
  762. rfc2045_free(copyrfc2045);
  763. }