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

WEB邮件程序

开发平台:

C/C++

  1. /*
  2. ** Copyright 1998 - 2000 Double Precision, Inc.  See COPYING for
  3. ** distribution information.
  4. */
  5. /*
  6. ** $Id: attachments.c,v 1.22 2000/06/18 01:26:21 mrsam Exp $
  7. */
  8. #include "config.h"
  9. #include "sqwebmail.h"
  10. #include "cgi/cgi.h"
  11. #include "sqconfig.h"
  12. #include "maildir.h"
  13. #include "folder.h"
  14. #include "rfc822/rfc822.h"
  15. #include "rfc822/rfc2047.h"
  16. #include "rfc2045/rfc2045.h"
  17. #include "token.h"
  18. #include "newmsg.h"
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <ctype.h>
  22. #include <fcntl.h>
  23. #if HAVE_UNISTD_H
  24. #include        <unistd.h>
  25. #endif
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include "maildir/maildirmisc.h"
  29. #include "htmllibdir.h"
  30. extern char *alloc_filename(const char *, const char *, const char *);
  31. extern const char *showsize(unsigned long);
  32. extern void output_attrencoded(const char *);
  33. extern char form_args[];
  34. extern int newdraftfd;
  35. extern void newmsg_hiddenheader(const char *, const char *);
  36. extern void output_scriptptrget();
  37. extern void output_urlencoded(const char *);
  38. extern void sendmsg_done();
  39. extern char *multipart_boundary_create();
  40. extern int multipart_boundary_checkf(const char *, FILE *);
  41. extern void newmsg_create_multipart(int, const char *, const char *);
  42. extern void newmsg_copy_nonmime_headers(FILE *);
  43. extern const char *sqwebmail_content_charset;
  44. static void attachment_showname(const char *);
  45. static off_t max_attach = MAXMSGSIZE;
  46. void attachments_head(const char *folder, const char *pos, const char *draft)
  47. {
  48. char *filename;
  49. FILE *fp;
  50. struct rfc2045 *rfcp;
  51. int cnt=0;
  52. struct rfc2045 *q;
  53. int foundtextplain=0;
  54. char *noattach_lab=strtok(form_args, "|");
  55. char *quotaerr=strtok(0, "|");
  56. char *limiterr=strtok(0, "|");
  57. off_t dummy;
  58. int fd2;
  59. CHECKFILENAME(draft);
  60. filename=maildir_find(DRAFTS, draft);
  61. if (!filename) return;
  62. fd2=maildir_safeopen(filename, O_RDONLY, 0);
  63. fp=0;
  64. if (fd2 >= 0)
  65. {
  66. fp=fdopen(fd2, "r");
  67. if (fp == NULL)
  68. close(fd2);
  69. }
  70. if (fp == NULL)
  71. {
  72. free(filename);
  73. return;
  74. }
  75. rfcp=rfc2045_fromfp(fp);
  76. fclose(fp);
  77. free(filename);
  78. if (strcmp(cgi("error"), "quota") == 0)
  79. {
  80. printf("%s", quotaerr);
  81. }
  82. if (strcmp(cgi("error"), "limits") == 0)
  83. {
  84. printf(limiterr, (unsigned long)(max_attach / 1024));
  85. }
  86. newmsg_hiddenheader("pos", pos);
  87. newmsg_hiddenheader("draft", draft);
  88. tokennew();
  89. printf("<table width="100%%" border=0>");
  90. for (q=rfcp ? rfcp->firstpart:0; q; q=q->next)
  91. {
  92. const char *content_type;
  93. const char *content_transfer_encoding;
  94. const char *charset;
  95. const char *name;
  96. off_t start_pos, end_pos, start_body;
  97. if (q->isdummy) continue;
  98. rfc2045_mimeinfo(q, &content_type,
  99. &content_transfer_encoding, &charset);
  100. if (!foundtextplain && strcmp(content_type,
  101. "text/plain") == 0)
  102. {
  103. foundtextplain=1;
  104. continue;
  105. }
  106. rfc2045_mimepos(q, &start_pos, &end_pos, &start_body,
  107. &dummy, &dummy);
  108. printf("<TR><TD ALIGN=LEFT><INPUT TYPE=CHECKBOX NAME="del%d">&nbsp;",
  109. ++cnt);
  110. name=rfc2045_contentname(q);
  111. attachment_showname(name);
  112. printf("</TD><TD ALIGN=LEFT>&nbsp;&nbsp;");
  113. output_attrencoded( content_type );
  114. printf("</TD><TD ALIGN=RIGHT>%s<BR></TD></TR>",
  115. showsize(end_pos - start_body));
  116. }
  117. if (cnt == 0)
  118. printf("<TR><TD ALIGN=CENTER>%s<BR></TD></TR>n",
  119. noattach_lab);
  120. printf("</table>n");
  121. }
  122. static void attachment_showname(const char *name)
  123. {
  124. char *s;
  125. if (!name || !*name) name="[attachment]"; /* Eh??? */
  126. s=rfc2047_decode_simple(name);
  127. output_attrencoded(s ? s:name);
  128. if (s) free(s);
  129. }
  130. static void attachment_open(const char *draft,
  131. FILE **fp,
  132. int *fd2,
  133. struct rfc2045 **rfcp)
  134. {
  135. char *oldname=maildir_find(DRAFTS, draft);
  136. if (!oldname) enomem();
  137. *fd2=maildir_safeopen(oldname, O_RDONLY, 0);
  138. *fp=0;
  139. if (*fd2 >= 0)
  140. {
  141. *fp=fdopen(*fd2, "r");
  142. if (*fp == NULL)
  143. close(*fd2);
  144. }
  145. if (*fp == NULL) enomem();
  146. *rfcp=rfc2045_fromfp( *fp );
  147. if (!*rfcp) enomem();
  148. }
  149. static int messagecopy(FILE *fp, off_t start, off_t end)
  150. {
  151. char buf[512];
  152. int n;
  153. if (fseek(fp, start, SEEK_SET) == -1) return (-1);
  154. while (start < end)
  155. {
  156. n=sizeof(buf);
  157. if (n > end - start)
  158. n=end - start;
  159. n=fread(buf, 1, n, fp);
  160. if (n <= 0) enomem();
  161. maildir_writemsg(newdraftfd, buf, n);
  162. start += n;
  163. }
  164. return (0);
  165. }
  166. /* Return non-zero if user selected all attachments for deletion */
  167. static int deleting_all_attachments(struct rfc2045 *p)
  168. {
  169. struct rfc2045 *q;
  170. const char *content_type;
  171. const char *content_transfer_encoding;
  172. const char *charset;
  173. int foundtextplain, cnt;
  174. char buf[MAXLONGSIZE+4];
  175. foundtextplain=0;
  176. cnt=0;
  177. for (q=p->firstpart; q; q=q->next)
  178. {
  179. rfc2045_mimeinfo(q, &content_type,
  180. &content_transfer_encoding, &charset);
  181. if (q->isdummy) continue;
  182. if (strcmp(content_type, "text/plain") == 0 &&
  183. !foundtextplain)
  184. {
  185. foundtextplain=1;
  186. continue;
  187. }
  188. sprintf(buf, "del%d", ++cnt);
  189. if (*cgi(buf) == '') return (0);
  190. }
  191. return (1);
  192. }
  193. static int del_final_attachment(FILE *fp, struct rfc2045 *rfcp)
  194. {
  195. struct rfc2045 *q;
  196. const char *content_type;
  197. const char *content_transfer_encoding;
  198. const char *charset;
  199. off_t start_pos, end_pos, start_body;
  200. off_t dummy;
  201. for (q=rfcp->firstpart; q; q=q->next)
  202. {
  203. if (q->isdummy) continue;
  204. rfc2045_mimeinfo(q, &content_type,
  205. &content_transfer_encoding, &charset);
  206. if (strcmp(content_type, "text/plain") == 0)
  207. break;
  208. }
  209. if (!q) return (-1);
  210. if (fseek(fp, 0L, SEEK_SET) == -1) return (-1);
  211. newmsg_copy_nonmime_headers(fp);
  212. maildir_writemsgstr(newdraftfd, "mime-version: 1.0ncontent-type: text/plain; charset="");
  213. maildir_writemsgstr(newdraftfd, sqwebmail_content_charset);
  214. maildir_writemsgstr(newdraftfd, ""ncontent-transfer-encoding: ");
  215. maildir_writemsgstr(newdraftfd, content_transfer_encoding);
  216. maildir_writemsgstr(newdraftfd, "nn");
  217. rfc2045_mimepos(q, &start_pos, &end_pos, &start_body, &dummy, &dummy);
  218. return (messagecopy(fp, start_body, end_pos));
  219. }
  220. static int del_some_attachments(FILE *fp, struct rfc2045 *rfcp)
  221. {
  222. struct rfc2045 *q;
  223. const char *content_type;
  224. const char *content_transfer_encoding;
  225. const char *charset;
  226. int foundtextplain;
  227. int cnt;
  228. const char *boundary=rfc2045_boundary(rfcp);
  229. off_t start_pos, end_pos, start_body;
  230. off_t dummy;
  231. rfc2045_mimepos(rfcp, &start_pos, &end_pos, &start_body, &dummy,
  232. &dummy);
  233. if (messagecopy(fp, 0, start_body)) return (-1);
  234. foundtextplain=0;
  235. cnt=0;
  236. for (q=rfcp->firstpart; q; q=q->next)
  237. {
  238. rfc2045_mimeinfo(q, &content_type,
  239. &content_transfer_encoding, &charset);
  240. if (q->isdummy)
  241. ;
  242. else if (strcmp(content_type, "text/plain") == 0 &&
  243. !foundtextplain)
  244. foundtextplain=1;
  245. else
  246. {
  247. char buf[MAXLONGSIZE+4];
  248. sprintf(buf, "del%d", ++cnt);
  249. if (*cgi(buf)) continue; /* This one's gone */
  250. }
  251. if (!q->isdummy)
  252. {
  253. maildir_writemsgstr(newdraftfd, "n--");
  254. maildir_writemsgstr(newdraftfd, boundary);
  255. maildir_writemsgstr(newdraftfd, "n");
  256. }
  257. rfc2045_mimepos(q, &start_pos, &end_pos, &start_body, &dummy,
  258. &dummy);
  259. if (messagecopy(fp, start_pos, end_pos))
  260. return (-1);
  261. }
  262. maildir_writemsgstr(newdraftfd, "n--");
  263. maildir_writemsgstr(newdraftfd, boundary);
  264. maildir_writemsgstr(newdraftfd, "--n");
  265. return (0);
  266. }
  267. static void deleteattach(const char *folder, const char *draft)
  268. {
  269. FILE *fp;
  270. int fd2;
  271. struct rfc2045 *rfcp;
  272. char *draftfilename;
  273. int isok=1;
  274. struct stat stat_buf;
  275. attachment_open(draft, &fp, &fd2, &rfcp);
  276. if (!rfcp->firstpart)
  277. {
  278. rfc2045_free(rfcp);
  279. fclose(fp);
  280. return; /* No attachments to delete */
  281. }
  282. if (fstat(fileno(fp), &stat_buf))
  283. {
  284. fclose(fp);
  285. enomem();
  286. }
  287. newdraftfd=maildir_recreatemsg(DRAFTS, draft, &draftfilename);
  288. if (newdraftfd < 0)
  289. {
  290. fclose(fp);
  291. enomem();
  292. }
  293. if (deleting_all_attachments(rfcp))
  294. {
  295. /* Deleting all attachments */
  296. if (del_final_attachment(fp, rfcp)) isok=0;
  297. }
  298. else
  299. {
  300. if (del_some_attachments(fp, rfcp)) isok=0;
  301. }
  302. fclose(fp);
  303. rfc2045_free(rfcp);
  304. if ( maildir_closemsg(newdraftfd, DRAFTS, draftfilename, isok,
  305. stat_buf.st_size))
  306. {
  307. free(draftfilename);
  308. enomem();
  309. }
  310. free(draftfilename);
  311. maildir_remcache(DRAFTS); /* Cache file invalid now */
  312. }
  313. /* ---------------------------------------------------------------------- */
  314. /* Upload an attachment */
  315. static int isbinary;
  316. static int attachfd;
  317. static const char *cgi_attachname, *cgi_attachfilename;
  318. static int upload_start(const char *name, const char *filename)
  319. {
  320. const char *p;
  321. p=strrchr(filename, '/');
  322. if (p) filename=p+1;
  323. p=strrchr(filename, '\');
  324. if (p) filename=p+1;
  325. cgi_attachname=name;
  326. cgi_attachfilename=filename;
  327. isbinary=0;
  328. return (0);
  329. }
  330. static int upload_file(const char *ptr, size_t cnt, void *voidptr)
  331. {
  332. size_t i;
  333. for (i=0; i<cnt; i++)
  334. if ( (ptr[i] < ' ' || ptr[i] >= 127) && ptr[i] != 'n' &&
  335. ptr[i] != 'r')
  336. isbinary=1;
  337. maildir_writemsg(attachfd, ptr, cnt);
  338. return (0);
  339. }
  340. static void upload_end()
  341. {
  342. }
  343. static void writebase64encode(const char *p, size_t n)
  344. {
  345. maildir_writemsg(newdraftfd, p, n);
  346. }
  347. static const char *search_mime_type(const char *mimetype, const char *filename)
  348. {
  349. FILE *fp;
  350. char *p, *q;
  351. if (!filename || !(filename=strrchr(filename, '.'))) return (0);
  352. ++filename;
  353. if ((fp=fopen(mimetype, "r")) == NULL) return(0);
  354. while ((p=maildir_readline(fp)) != NULL)
  355. {
  356. if ((q=strchr(p, '#')) != NULL) *q='';
  357. if ((p=strtok(p, " t")) == NULL) continue;
  358. while ((q=strtok(NULL, " t")) != NULL)
  359. if (strcasecmp(q, filename) == 0)
  360. {
  361. fclose(fp);
  362. return (p);
  363. }
  364. }
  365. fclose(fp);
  366. return (NULL);
  367. }
  368. static const char *calc_mime_type(const char *filename)
  369. {
  370. static const char mimetypes[]=MIMETYPES;
  371. const char *p;
  372. char *q;
  373. const char *r;
  374. char *s;
  375. p=mimetypes;
  376. if (!p) enomem();
  377. while (*p)
  378. {
  379. if (*p == ':')
  380. {
  381. ++p;
  382. continue;
  383. }
  384. q=strdup(p);
  385. if (!q) enomem();
  386. if ((s=strchr(q, ':')) != NULL) *s='';
  387. if ((r=search_mime_type(q, filename)) != 0)
  388. {
  389. free(q);
  390. return (r);
  391. }
  392. free(q);
  393. while (*p && *p != ':')
  394. p++;
  395. }
  396. return ("application/octet-stream");
  397. }
  398. static void write_disposition_param(const char *label, const char *value)
  399. {
  400. char *p, *q;
  401. const char *r;
  402.         while (value && ((r=strchr(value, ':')) || (r=strchr(value, '/'))
  403.                 || (r=strchr(value, '\'))))
  404.                 value=r+1;
  405. if (!value || !*value) return;
  406. maildir_writemsgstr(newdraftfd, "; ");
  407. maildir_writemsgstr(newdraftfd, label);
  408. maildir_writemsgstr(newdraftfd, "="");
  409. p=strdup(value);
  410. if (!p) enomem();
  411. while ((q=strchr(p, '\')) || (q=strchr(p, '"')))
  412. *q='_';
  413. maildir_writemsgstr(newdraftfd, p);
  414. maildir_writemsgstr(newdraftfd, """);
  415. free(p);
  416. }
  417. static int uploadattach(const char *draft)
  418. {
  419. char *attachfilename;
  420. char *draftfilename;
  421. FILE *draftfp;
  422. char *boundary;
  423. FILE *tempfp;
  424. struct rfc2045 *rfcp;
  425. const char *content_type;
  426. const char *content_transfer_encoding;
  427. const char *charset;
  428. off_t start_pos, end_pos, start_body;
  429. char buf[BUFSIZ];
  430. int n;
  431. struct stat stat_buf, attach_stat_buf;
  432. off_t dummy;
  433. int fd2;
  434. char *filenamemime;
  435. /* Open the file containing the draft message */
  436. draftfilename=maildir_find(DRAFTS, draft);
  437. if (!draftfilename) return (0);
  438. fd2=maildir_safeopen(draftfilename, O_RDONLY, 0);
  439. draftfp=0;
  440. if (fd2 >= 0)
  441. {
  442. draftfp=fdopen(fd2, "r");
  443. if (draftfp == NULL)
  444. close(fd2);
  445. }
  446. if (draftfp == 0)
  447. enomem();
  448. free(draftfilename);
  449. if (fstat(fileno(draftfp), &stat_buf))
  450. {
  451. fclose(draftfp);
  452. enomem();
  453. }
  454. /* Create a temporary file in tmp where we'll temporarily store the
  455. ** attachment
  456. */
  457. attachfd=maildir_createmsg(DRAFTS, "temp", &attachfilename);
  458. if (attachfd < 0)
  459. {
  460. fclose(draftfp);
  461. enomem();
  462. }
  463. if (cgi_getfiles( &upload_start, &upload_file, &upload_end, 1)
  464. || maildir_writemsg_flush(attachfd))
  465. {
  466. maildir_closemsg(attachfd, DRAFTS, attachfilename, 0, 0);
  467. free(attachfilename);
  468. fclose(draftfp);
  469. close(attachfd);
  470. return (0);
  471. }
  472. if (fstat(attachfd, &attach_stat_buf) ||
  473. attach_stat_buf.st_size + stat_buf.st_size > max_attach)
  474. {
  475. maildir_closemsg(attachfd, DRAFTS, attachfilename, 0, 0);
  476. maildir_deletenewmsg(attachfd, DRAFTS, attachfilename);
  477. free(attachfilename);
  478. fclose(draftfp);
  479. close(attachfd);
  480. return (-2);
  481. }
  482. /* Calculate new MIME content boundary */
  483. /* If the attachment will be encoded in base64, there's no need
  484. ** to scan it for the embedded boundary tag, since we create a
  485. ** boundary that will never occur in base64-encoded text.
  486. */
  487. boundary=0;
  488. tempfp=0;
  489. if (!isbinary)
  490. {
  491. int n=dup(attachfd);
  492. if (n < 0)
  493. {
  494. fclose(draftfp);
  495. enomem();
  496. }
  497. tempfp=fdopen(n, "r");
  498. if (tempfp == 0)
  499. {
  500. fclose(draftfp);
  501. enomem();
  502. }
  503. }
  504. do
  505. {
  506. if (boundary) free(boundary);
  507. boundary=multipart_boundary_create();
  508. } while ( multipart_boundary_checkf(boundary, draftfp) ||
  509. (tempfp && multipart_boundary_checkf(boundary,
  510. tempfp)));
  511. if (tempfp) fclose(tempfp);
  512. /* Parse existing draft for its MIME structure */
  513. rfcp=rfc2045_fromfp(draftfp);
  514. rfc2045_mimeinfo(rfcp, &content_type,
  515. &content_transfer_encoding, &charset);
  516. /* Create a new version of the draft message */
  517. newdraftfd=maildir_recreatemsg(DRAFTS, draft, &draftfilename);
  518. if (newdraftfd < 0)
  519. {
  520. maildir_closemsg(attachfd, DRAFTS, attachfilename, 0, 0);
  521. fclose(draftfp);
  522. close(attachfd);
  523. enomem();
  524. }
  525. if (fseek(draftfp, 0L, SEEK_SET) < 0)
  526. {
  527. maildir_closemsg(newdraftfd, DRAFTS, draftfilename, 0, 0);
  528. maildir_closemsg(attachfd, DRAFTS, attachfilename, 0, 0);
  529. fclose(draftfp);
  530. close(attachfd);
  531. enomem();
  532. }
  533. newmsg_copy_nonmime_headers(draftfp);
  534. /* Create a multipart message, 1st attachment is the existing
  535. ** contents.
  536. */
  537. newmsg_create_multipart(newdraftfd, charset, boundary);
  538. maildir_writemsgstr(newdraftfd, "--");
  539. maildir_writemsgstr(newdraftfd, boundary);
  540. maildir_writemsgstr(newdraftfd, "n");
  541. if (!rfcp->firstpart)
  542. {
  543. /* The current draft does not have attachments.  Take its
  544. ** sole contents, and write it as a text/plain attachment.
  545. */
  546. maildir_writemsgstr(newdraftfd, "Content-Type: ");
  547. maildir_writemsgstr(newdraftfd, content_type);
  548. maildir_writemsgstr(newdraftfd, "; charset="");
  549. maildir_writemsgstr(newdraftfd, sqwebmail_content_charset);
  550. maildir_writemsgstr(newdraftfd, ""nContent-Transfer-Encoding: ");
  551. maildir_writemsgstr(newdraftfd, content_transfer_encoding);
  552. maildir_writemsgstr(newdraftfd, "nn");
  553. rfc2045_mimepos(rfcp, &start_pos, &end_pos, &start_body,
  554. &dummy, &dummy);
  555. if (messagecopy(draftfp, start_body, end_pos))
  556. {
  557. maildir_closemsg(newdraftfd, DRAFTS, draftfilename,
  558. 0, 0);
  559. maildir_closemsg(attachfd, DRAFTS, attachfilename,
  560. 0, 0);
  561. fclose(draftfp);
  562. close(newdraftfd);
  563. close(attachfd);
  564. enomem();
  565. }
  566. maildir_writemsgstr(newdraftfd, "n--");
  567. maildir_writemsgstr(newdraftfd, boundary);
  568. maildir_writemsgstr(newdraftfd, "n");
  569. }
  570. else
  571. {
  572. struct rfc2045 *q;
  573. /* If the current draft already has MIME attachments,
  574. ** just copy them over to the new draft message.
  575. */
  576. for (q=rfcp->firstpart; q; q=q->next)
  577. {
  578. if (q->isdummy) continue;
  579. rfc2045_mimepos(q, &start_pos, &end_pos, &start_body,
  580. &dummy, &dummy);
  581. if (messagecopy(draftfp, start_pos, end_pos))
  582. {
  583. maildir_closemsg(newdraftfd, DRAFTS,
  584. draftfilename, 0, 0);
  585. maildir_closemsg(attachfd, DRAFTS,
  586. attachfilename, 0, 0);
  587. fclose(draftfp);
  588. close(newdraftfd);
  589. close(attachfd);
  590. enomem();
  591. }
  592. maildir_writemsgstr(newdraftfd, "n--");
  593. maildir_writemsgstr(newdraftfd, boundary);
  594. maildir_writemsgstr(newdraftfd, "n");
  595. }
  596. }
  597. filenamemime=rfc2047_encode_str(cgi_attachfilename,
  598. sqwebmail_content_charset);
  599. maildir_writemsgstr(newdraftfd, "Content-Type: ");
  600. maildir_writemsgstr(newdraftfd, calc_mime_type(cgi_attachfilename));
  601. write_disposition_param("name",
  602. filenamemime ? filenamemime:"filename.dat");
  603. maildir_writemsgstr(newdraftfd,
  604. *cgi("attach_inline") ?
  605. "nContent-Disposition: inline":
  606. "nContent-Disposition: attachment");
  607. write_disposition_param("filename",
  608. filenamemime ? filenamemime:"filename.dat");
  609. if (filenamemime)
  610. free(filenamemime);
  611. maildir_writemsgstr(newdraftfd, "n");
  612. if (lseek(attachfd, 0L, SEEK_SET) < 0)
  613. {
  614. maildir_closemsg(newdraftfd, DRAFTS, draftfilename, 0, 0);
  615. maildir_closemsg(attachfd, DRAFTS, attachfilename, 0, 0);
  616. fclose(draftfp);
  617. close(newdraftfd);
  618. close(attachfd);
  619. enomem();
  620. }
  621. /* Save our new attachment */
  622. if (isbinary)
  623. {
  624. maildir_writemsgstr(newdraftfd, "Content-Transfer-Encoding: base64nn");
  625. rfc2045_base64encode_start(&writebase64encode);
  626. }
  627. else
  628. {
  629. maildir_writemsgstr(newdraftfd, "Content-Transfer-Encoding: 7bitnn");
  630. }
  631. while ((n=read(attachfd, buf, sizeof(buf))) > 0)
  632. {
  633. if (isbinary)
  634. rfc2045_base64encode(buf, n);
  635. else
  636. maildir_writemsg(newdraftfd, buf, n);
  637. }
  638. if (n < 0)
  639. {
  640. maildir_closemsg(newdraftfd, DRAFTS, draftfilename, 0, 0);
  641. maildir_closemsg(attachfd, DRAFTS, attachfilename, 0, 0);
  642. fclose(draftfp);
  643. close(newdraftfd);
  644. close(attachfd);
  645. enomem();
  646. }
  647. if (isbinary)
  648. rfc2045_base64encode_end();
  649. maildir_writemsgstr(newdraftfd, "n--");
  650. maildir_writemsgstr(newdraftfd, boundary);
  651. maildir_writemsgstr(newdraftfd, "--n");
  652. /* Finish new draft message, let it replace the current one */
  653. if (maildir_closemsg(newdraftfd, DRAFTS, draftfilename, 1,
  654. stat_buf.st_size))
  655. {
  656. maildir_closemsg(attachfd, DRAFTS, attachfilename, 0, 0);
  657. free(draftfilename);
  658. maildir_deletenewmsg(attachfd, DRAFTS, attachfilename);
  659. free(attachfilename);
  660. rfc2045_free(rfcp);
  661. fclose(draftfp);
  662. close(attachfd);
  663. return (-1);
  664. }
  665. free(draftfilename);
  666. fclose(draftfp);
  667. /* Remove and delete temp attachment file */
  668. maildir_deletenewmsg(attachfd, DRAFTS, attachfilename);
  669. free(attachfilename);
  670. rfc2045_free(rfcp);
  671. return (0);
  672. }
  673. void doattach(const char *folder, const char *draft)
  674. {
  675. int quotaflag=0;
  676. CHECKFILENAME(draft);
  677. if (*cgi("dodelete"))
  678. {
  679. if (!tokencheck())
  680. {
  681. deleteattach(folder, draft);
  682. tokensave();
  683. }
  684. }
  685. else if (*cgi("upload"))
  686. {
  687. if (!tokencheck())
  688. {
  689. quotaflag=uploadattach(draft);
  690. tokensave();
  691. }
  692. }
  693. else if (*cgi("previewmsg"))
  694. {
  695. cgi_put("draft", draft);
  696. newmsg_do(folder);
  697. return;
  698. }
  699. else if (*cgi("sendmsg"))
  700. {
  701. cgi_put("draftmessage", draft);
  702. newmsg_do(folder);
  703. return;
  704. }
  705. else if (*cgi("savedraft"))
  706. {
  707. sendmsg_done();
  708. return;
  709. }
  710. if (quotaflag == -2)
  711.         {
  712.                 http_redirect_argss(
  713.                   "&form=attachments&pos=%s&draft=%s&error=limits",
  714.                   cgi("pos"), draft);
  715.         }
  716.         else
  717.         {
  718.                 http_redirect_argss(
  719.                   (quotaflag ? "&form=attachments&pos=%s&draft=%s&error=quota":
  720.                   "&form=attachments&pos=%s&draft=%s"), cgi("pos"),
  721.                   draft);
  722.         }
  723. }