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

WEB邮件程序

开发平台:

C/C++

  1. /*
  2. ** Copyright 1998 - 1999 Double Precision, Inc.  See COPYING for
  3. ** distribution information.
  4. */
  5. /*
  6. ** $Id: folder.c,v 1.59 2000/06/03 05:40:27 mrsam Exp $
  7. */
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <ctype.h>
  11. #include <fcntl.h>
  12. #include <stdlib.h>
  13. #include "config.h"
  14. #include "sqwebmail.h"
  15. #include "maildir/maildirmisc.h"
  16. #include "rfc822/rfc822.h"
  17. #include "rfc822/rfc2047.h"
  18. #include "rfc2045/rfc2045.h"
  19. #include "maildir.h"
  20. #include "folder.h"
  21. #include "cgi/cgi.h"
  22. #include "pref.h"
  23. #include "html.h"
  24. #include "token.h"
  25. #include "filter.h"
  26. #include "buf.h"
  27. #include "pref.h"
  28. #if TIME_WITH_SYS_TIME
  29. #include <sys/time.h>
  30. #include <time.h>
  31. #else
  32. #if HAVE_SYS_TIME_H
  33. #include <sys/time.h>
  34. #else
  35. #include <time.h>
  36. #endif
  37. #endif
  38. extern const char *nonloginscriptptr();
  39. extern int pref_flagpagesize;
  40. extern const char *sqwebmail_content_charset;
  41. extern time_t rfc822_parsedt(const char *);
  42. static time_t current_time;
  43. static const char black_color[]="<FONT COLOR="#000000">";
  44. static const char end_font[]="</FONT>";
  45. static char *folder_err_msg=0;
  46. extern const char *sqwebmail_folder;
  47. extern char form_args[];
  48. extern void output_scriptptrget();
  49. extern void output_scriptptr();
  50. extern void output_attrencoded(const char *);
  51. extern void output_urlencoded(const char *);
  52. extern char *scriptptrget();
  53. void print_safe_len(const char *p, size_t n, void (*func)(const char *, size_t))
  54. {
  55. char buf[10];
  56. const char *q=p;
  57. while (n)
  58. {
  59. --n;
  60. if (*p == '<') strcpy(buf, "&lt;");
  61. else if (*p == '>') strcpy(buf, "&gt;");
  62. else if (*p == '&') strcpy(buf, "&amp;");
  63. else if (*p == ' ') strcpy(buf, "&nbsp;");
  64. else if (*p == 'n') strcpy(buf, "<BR>");
  65. else if (ISCTRL(*p))
  66. sprintf(buf, "&#%d;", (int)(unsigned char)*p);
  67. else
  68. {
  69. p++;
  70. continue;
  71. }
  72. (*func)(q, p-q);
  73. (*func)(buf, strlen(buf));
  74. p++;
  75. q=p;
  76. }
  77. (*func)(q, p-q);
  78. }
  79. static void print_safe_to_stdout(const char *p, size_t cnt)
  80. {
  81. fwrite(p, cnt, 1, stdout);
  82. }
  83. void print_safe(const char *p)
  84. {
  85. print_safe_len(p, strlen(p), print_safe_to_stdout);
  86. }
  87. void call_print_safe_to_stdout(const char *p, size_t cnt)
  88. {
  89. print_safe_len(p, cnt, print_safe_to_stdout);
  90. }
  91. void folder_contents_title()
  92. {
  93. char *p;
  94. char *lab;
  95. const char *f;
  96. const char *inbox_lab, *drafts_lab, *trash_lab, *sent_lab;
  97. p=strdup(form_args);
  98. if (!p) return;
  99. (void)strtok(p, "|");
  100. (void)strtok(0, "|");
  101. (void)strtok(0, "|");
  102. (void)strtok(0, "|");
  103. lab=strtok(0, "|");
  104. (void)strtok(0, "|");
  105. (void)strtok(0, "|");
  106. (void)strtok(0, "|");
  107. (void)strtok(0, "|");
  108. (void)strtok(0, "|");
  109. (void)strtok(0, "|");
  110. (void)strtok(0, "|");
  111. (void)strtok(0, "|");
  112. inbox_lab=strtok(0, "|");
  113. drafts_lab=strtok(0, "|");
  114. trash_lab=strtok(0, "|");
  115. sent_lab=strtok(0, "|");
  116. f=sqwebmail_folder;
  117. if (strcmp(f, INBOX) == 0) f=inbox_lab;
  118. else if (strcmp(f, DRAFTS) == 0) f=drafts_lab;
  119. else if (strcmp(f, SENT) == 0) f=sent_lab;
  120. else if (strcmp(f, TRASH) == 0) f=trash_lab;
  121. if (lab)
  122. {
  123. char *q=malloc(strlen(lab)+strlen(f)+1);
  124. if (*f == ':') ++f;
  125. if (!q) enomem();
  126. sprintf(q, lab, f);
  127. output_attrencoded(q);
  128. free(q);
  129. }
  130. free(p);
  131. }
  132. static int group_movedel(const char *folder,
  133. int (*func)(const char *, const char *, size_t))
  134. {
  135. struct cgi_arglist *arg;
  136. if (*cgi("SELECTALL")) /* Everything is selected */
  137. {
  138. for (arg=cgi_arglist; arg; arg=arg->next)
  139. {
  140. const char *f;
  141. if (strncmp(arg->argname, "MOVEFILE-", 9)) continue;
  142. f=cgi(arg->argname);
  143. CHECKFILENAME(f);
  144. if ((*func)(folder, f, atol(arg->argname+9)))
  145. return (-1);
  146. }
  147. return (0);
  148. }
  149. for (arg=cgi_arglist; arg; arg=arg->next)
  150. {
  151. unsigned long l;
  152. char movedel[MAXLONGSIZE+10];
  153. const char *f;
  154. if (strncmp(arg->argname, "MOVE-", 5)) continue;
  155. l=atol(arg->argname+5);
  156. sprintf(movedel, "MOVEFILE-%lu", l);
  157. f=cgi(movedel);
  158. CHECKFILENAME(f);
  159. if ((*func)(folder, f, l))
  160. return (-1);
  161. }
  162. return (0);
  163. }
  164. static int groupdel(const char *folder, const char *file, size_t pos)
  165. {
  166. maildir_msgdeletefile(folder, file, pos);
  167. return (0);
  168. }
  169. static int groupmove(const char *folder, const char *file, size_t pos)
  170. {
  171. return (maildir_msgmovefile(folder, file, cgi("moveto"), pos));
  172. }
  173. void folder_delmsgs(const char *dir, size_t pos)
  174. {
  175. int rc=0;
  176. if (*cgi("cmddel"))
  177. {
  178. rc=group_movedel( dir, &groupdel );
  179. maildir_savefoldermsgs(dir);
  180. }
  181. else if (*cgi("cmdmove"))
  182. {
  183. rc=group_movedel( dir, &groupmove );
  184. maildir_savefoldermsgs(dir);
  185. }
  186. http_redirect_argu(
  187. (rc ? "&error=quota&form=folder&pos=%s":"&form=folder&pos=%s"),
  188. (unsigned long)pos);
  189. }
  190. static void folder_msg_link(const char *, size_t, char);
  191. static void folder_msg_unlink(const char *, size_t, char);
  192. void folder_contents(const char *dir, size_t pos)
  193. {
  194. MSGINFO **contents;
  195. int i, found;
  196. int morebefore, moreafter;
  197. char *argdup;
  198. char *datelab, *fromlab, *subjlab, *sizelab, *beforelab, *afterlab;
  199. char *nomsg, *selectalllab;
  200. char *qerrmsg;
  201. maildir_reload(dir);
  202. contents=maildir_read(dir, pref_flagpagesize, &pos,
  203. &morebefore, &moreafter);
  204. argdup=strdup(form_args);
  205. if (!argdup) return;
  206. time(&current_time);
  207. datelab=strtok(argdup, "|");
  208. fromlab=strtok(0, "|");
  209. subjlab=strtok(0, "|");
  210. sizelab=strtok(0, "|");
  211. (void)strtok(0, "|");
  212. nomsg=strtok(0, "|");
  213. (void)strtok(0, "|");
  214. (void)strtok(0, "|");
  215. (void)strtok(0, "|");
  216. (void)strtok(0, "|");
  217. beforelab=strtok(0, "|");
  218. afterlab=strtok(0, "|");
  219. selectalllab=strtok(0, "|");
  220. if (!beforelab) beforelab="";
  221. if (!afterlab) afterlab="";
  222. if (!selectalllab) selectalllab="";
  223. (void)strtok(0, "|");
  224. (void)strtok(0, "|");
  225. (void)strtok(0, "|");
  226. (void)strtok(0, "|");
  227. qerrmsg=strtok(0, "|");
  228. if (!qerrmsg) qerrmsg="";
  229. if (strcmp(cgi("error"), "quota") == 0)
  230. printf("%s", qerrmsg);
  231. printf("<TABLE WIDTH="100%%" BORDER=0 CELLPADDING=1 CELLSPACING=0>");
  232. printf("<TR><TD ALIGN=LEFT>");
  233. printf("<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=4><TR><TD BGCOLOR="#DDDDDD">");
  234. if (morebefore)
  235. {
  236. size_t beforepos;
  237. if (pos < pref_flagpagesize) beforepos=0;
  238. else beforepos=pos-pref_flagpagesize;
  239. printf("<A HREF="");
  240. output_scriptptrget();
  241. printf("&form=folder&pos=%ld" STYLE="text-decoration: none">",
  242. (long)beforepos);
  243. }
  244. printf("%s", beforelab);
  245. if (morebefore)
  246. printf("</A>");
  247. printf("</TD></TR></TABLE>n");
  248. printf("</TD><TD ALIGN=RIGHT>n");
  249. printf("<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=4><TR><TD BGCOLOR="#DDDDDD">");
  250. if (moreafter)
  251. {
  252. printf("<A HREF="");
  253. output_scriptptrget();
  254. printf("&form=folder&pos=%ld" STYLE="text-decoration: none">",
  255. (long)(pos+pref_flagpagesize));
  256. }
  257. printf("%s", afterlab);
  258. if (moreafter)
  259. printf("</A>");
  260. printf("</TD></TR></TABLE>n");
  261. printf("</TD></TR></TABLE>");
  262. printf("<TABLE WIDTH="100%%" BORDER=0 CELLSPACING=0 CELLPADDING=4><TR BGCOLOR="#000080"><TH ALIGN=CENTER><FONT COLOR="#FFFF00">#</FONT></TH><TH>&nbsp;</TH><TH><FONT COLOR="#FFFF00">%s</FONT></TH><TH><FONT COLOR="#FFFF00">%s</FONT></TH><TH><FONT COLOR="#FFFF00">%s</FONT></TH><TH><FONT COLOR="#FFFF00">%s</FONT><BR></TH></TR>n",
  263. datelab ? datelab:"",
  264. fromlab ? fromlab:"",
  265. subjlab ? subjlab:"",
  266. sizelab ? sizelab:"");
  267. found=0;
  268. for (i=0; i<pref_flagpagesize; i++)
  269. {
  270. const char *date, *from, *subj, *size;
  271. char *froms, *subjs;
  272. const char *p, *q;
  273. size_t l;
  274. char type[8];
  275. char *start_bold, *end_bold;
  276. if (contents[i] == 0) continue;
  277. found=1;
  278. date=MSGINFO_DATE(contents[i]);
  279. from=MSGINFO_FROM(contents[i]);
  280. subj=MSGINFO_SUBJECT(contents[i]);
  281. size=MSGINFO_SIZE(contents[i]);
  282. type[0]=maildirfile_type(MSGINFO_FILENAME(contents[i]));
  283. type[1]='';
  284. if (type[0] == '') strcpy(type, "&nbsp;");
  285. start_bold=""; end_bold="";
  286. if (type[0] == MSGTYPE_NEW)
  287. {
  288. start_bold="<B>";
  289. end_bold="</B>";
  290. }
  291. p=MSGINFO_FILENAME(contents[i]);
  292. if ((q=strrchr(p, '/')) != 0)
  293. p=q+1;
  294. printf("<TR BGCOLOR="%s"><TD ALIGN=RIGHT>%s%s%ld.%s%s</TD><TD><INPUT TYPE=CHECKBOX NAME="MOVE-%ld",
  295. (i & 1 ? "#EEEEEE":"#DDDDDD"),
  296. black_color, start_bold,
  297. (long)(i+pos+1),
  298. end_bold, end_font,
  299. (long) (pos+i));
  300. printf(""%s><INPUT TYPE=HIDDEN NAME="MOVEFILE-%ld" VALUE="",
  301. (type[0] == MSGTYPE_DELETED ? " DISABLED":""),
  302. (long)(pos+i));
  303. output_attrencoded(p);
  304. printf("">&nbsp;%s%s%s%s%s</TD><TD>%s%s",
  305. black_color, start_bold,
  306. type,
  307. end_bold, end_font,
  308. black_color, start_bold
  309. );
  310. if (!*date) date=" ";
  311. folder_msg_link(dir, pos+i, type[0]);
  312. print_safe(date);
  313. folder_msg_unlink(dir, pos+i, type[0]);
  314. printf("%s%s</TD><TD>%s%s", end_bold, end_font,
  315. black_color, start_bold);
  316. if (!*from) from=" ";
  317. folder_msg_link(dir, pos+i, type[0]);
  318. froms=rfc2047_decode_simple(from);
  319. if (froms == 0) enomem();
  320. if (strlen(froms) >= 30)
  321. strcpy(froms+27, "...");
  322. print_safe(froms);
  323. free(froms);
  324. folder_msg_unlink(dir, pos+i, type[0]);
  325. printf("%s%s<BR></TD><TD>%s%s", end_bold, end_font,
  326. black_color, start_bold);
  327. folder_msg_link(dir, pos+i, type[0]);
  328. subjs=rfc2047_decode_simple(subj);
  329. if (subjs == 0) enomem();
  330. if (strlen(subjs) >= 40)
  331. strcpy(subjs+37, "...");
  332. print_safe(subjs);
  333. l=strlen(subjs);
  334. while (l++ < 8)
  335. printf("&nbsp;");
  336. free(subjs);
  337. folder_msg_unlink(dir, pos+i, type[0]);
  338. printf("%s%s</TD><TD ALIGN=RIGHT>%s%s%s%s%s<BR></TD></TR>n", end_bold, end_font, black_color, start_bold, size, end_bold, end_font);
  339. }
  340. if (found)
  341. {
  342. puts("<TR BGCOLOR="#DDDDDD"><TD COLSPAN=6><HR></TD></TR>");
  343. puts("<TR BGCOLOR="#EEEEEE"><TD>&nbsp;</TD>");
  344. printf("<TD COLSPAN=5><INPUT TYPE=CHECKBOX NAME="SELECTALL">&nbsp;%s</TD></TR>",
  345. selectalllab);
  346. }
  347. if (!found && nomsg)
  348. {
  349. puts("<TR BGCOLOR="#FFBBBB"><TD COLSPAN=6 ALIGN=LEFT><P>");
  350. puts(black_color);
  351. puts(nomsg);
  352. puts(end_font);
  353. puts("<BR></TD></TR>");
  354. }
  355. printf("</TABLE>n");
  356. free(argdup);
  357. maildir_free(contents, pref_flagpagesize);
  358. }
  359. static void folder_msg_link(const char *dir, size_t pos, char t)
  360. {
  361. if (t == MSGTYPE_DELETED)
  362. {
  363. printf("<A HREF="");
  364. output_scriptptrget();
  365. printf("&form=folder&pos=%s">", cgi("pos"));
  366. return;
  367. }
  368. printf("<A HREF="");
  369. if (strcmp(dir, DRAFTS))
  370. {
  371. output_scriptptrget();
  372. printf("&form=readmsg&pos=%ld">", (long)pos);
  373. }
  374. else
  375. {
  376. size_t mpos=pos;
  377. char *filename=maildir_posfind(dir, &mpos);
  378. char *basename=filename ? maildir_basename(filename):NULL;
  379. output_scriptptrget();
  380. printf("&form=newmsg&draft=");
  381. output_urlencoded(basename);
  382. printf("">");
  383. if (basename) free(basename);
  384. if (filename) free(filename);
  385. }
  386. }
  387. static void folder_msg_unlink(const char *dir, size_t pos, char t)
  388. {
  389. printf("</A>");
  390. }
  391. static size_t msg_pos, msg_count;
  392. static char *msg_posfile;
  393. static int msg_hasprev, msg_hasnext;
  394. static char *msg_nextlab=0, *msg_prevlab=0, *msg_deletelab=0,
  395. *msg_purgelab=0, *msg_folderlab=0;
  396. static char msg_type;
  397. static char *msg_badcontenttype=0;
  398. static char *msg_dispattachment=0;
  399. static char *msg_downattachment=0;
  400. static char *msg_replylab=0;
  401. static char *msg_replyalllab=0;
  402. static char *msg_forwardlab=0;
  403. static char *msg_forwardattlab=0;
  404. static char *msg_fullheaderlab=0;
  405. static char *msg_movetolab=0;
  406. static char *msg_print=0;
  407. static char *folder_inbox=0;
  408. static char *folder_drafts=0;
  409. static char *folder_trash=0;
  410. static char *folder_sent=0;
  411. static char *msg_golab=0;
  412. static const char *msg_msglab;
  413. static int initnextprevcnt;
  414. void folder_initnextprev(const char *dir, size_t pos)
  415. {
  416. MSGINFO **info;
  417. const char *p;
  418. const char *msg_numlab, *msg_numnewlab;
  419. initnextprevcnt=0;
  420. msg_nextlab=strtok(form_args, "|");
  421. msg_prevlab=strtok(NULL, "|");
  422. msg_deletelab=strtok(NULL, "|");
  423. msg_purgelab=strtok(NULL, "|");
  424. msg_folderlab=strtok(NULL, "|");
  425. msg_badcontenttype=strtok(NULL, "|");
  426. msg_dispattachment=strtok(NULL, "|");
  427. msg_downattachment=strtok(NULL, "|");
  428. msg_replylab=strtok(NULL, "|");
  429. msg_replyalllab=strtok(NULL, "|");
  430. msg_forwardlab=strtok(NULL, "|");
  431. msg_forwardattlab=strtok(NULL, "|");
  432. msg_numlab=strtok(NULL, "|");
  433. msg_numnewlab=strtok(NULL, "|");
  434. msg_fullheaderlab=strtok(NULL, "|");
  435. msg_movetolab=strtok(NULL, "|");
  436. msg_print=strtok(NULL, "|");
  437. folder_inbox=strtok(NULL, "|");
  438. folder_drafts=strtok(NULL, "|");
  439. folder_trash=strtok(NULL, "|");
  440. folder_sent=strtok(NULL, "|");
  441. p=strtok(NULL, "|");
  442. if (!p) p="";
  443. if (strcmp(cgi("error"),"quota") == 0)
  444. printf("%s", p);
  445. msg_golab=strtok(NULL, "|");
  446. info=maildir_read(dir, 1, &pos, &msg_hasprev, &msg_hasnext);
  447. msg_pos=pos;
  448. printf("<INPUT TYPE=HIDDEN NAME="pos" VALUE="%ld">",
  449. (long)msg_pos);
  450. p=strrchr(MSGINFO_FILENAME(info[0]), '/');
  451. if (p) p++;
  452. else p=MSGINFO_FILENAME(info[0]);
  453. msg_posfile=strdup(p);
  454. if (!msg_posfile) enomem();
  455. if ((msg_type=maildirfile_type(MSGINFO_FILENAME(info[0])))
  456. == MSGTYPE_NEW) msg_numlab=msg_numnewlab;
  457. msg_msglab=msg_numlab;
  458. msg_count=maildir_countof(dir);
  459. printf("<INPUT TYPE=HIDDEN NAME="posfile" VALUE="");
  460. output_attrencoded(p);
  461. printf(""><INPUT TYPE=HIDDEN NAME="form" VALUE="delmsg">");
  462. maildir_free(info, 1);
  463. }
  464. void folder_nextprev()
  465. {
  466. printf("<TABLE WIDTH="100%%" BORDER=0 CELLSPACING=0 CELLPADDING=0><TR VALIGN=CENTER>");
  467.     printf("<TD ALIGN=LEFT><TABLE BORDER=0 CELLSPACING=4><TR>");
  468. /* Pmovetolab */
  469. printf("<TD BGCOLOR="#DDDDDD">&nbsp;");
  470. if (msg_hasprev)
  471. {
  472. printf("<A HREF="");
  473. output_scriptptrget();
  474. printf("&form=readmsg&pos=%ld" STYLE="text-decoration: none">",
  475. (long)(msg_pos-1));
  476. }
  477. printf("%s", msg_prevlab ? msg_prevlab:"");
  478. if (msg_hasprev)
  479. {
  480. printf("</A>");
  481. }
  482. printf("&nbsp;</TD>");
  483. /* NEXT */
  484. printf("<TD BGCOLOR="#DDDDDD">&nbsp;");
  485. if (msg_hasnext)
  486. {
  487. printf("<A HREF="");
  488. output_scriptptrget();
  489. printf("&form=readmsg&pos=%ld" STYLE="text-decoration: none">",
  490. (long)(msg_pos+1));
  491. }
  492. printf("%s", msg_nextlab ? msg_nextlab:"");
  493. if (msg_hasnext)
  494. {
  495. printf("</A>");
  496. }
  497. printf("&nbsp;</TD>");
  498. /* DEL */
  499. printf("<TD BGCOLOR="#DDDDDD">&nbsp;");
  500. if (msg_type != MSGTYPE_DELETED)
  501. {
  502. printf("<A HREF="");
  503. output_scriptptrget();
  504. tokennewget();
  505. printf("&posfile=");
  506. output_urlencoded(msg_posfile);
  507. printf("&form=delmsg&pos=%ld" STYLE="text-decoration: none">",
  508. (long)msg_pos);
  509. }
  510. printf("%s", strcmp(sqwebmail_folder, TRASH) == 0
  511. ? msg_purgelab : msg_deletelab);
  512. if (msg_type != MSGTYPE_DELETED)
  513. printf("</A>");
  514. printf("&nbsp;</TD>n");
  515. /* FOLDER */
  516. printf("<TD BGCOLOR="#DDDDDD">&nbsp;<A HREF="");
  517. output_scriptptrget();
  518. printf("&pos=%ld&form=folder"; STYLE="text-decoration: none">%s</A>&nbsp;</TD>n",
  519. (long)( (msg_pos/pref_flagpagesize)*pref_flagpagesize ),
  520. msg_folderlab);
  521. /* REPLY */
  522. printf("<TD BGCOLOR="#DDDDDD">&nbsp;<A HREF="");
  523. output_scriptptrget();
  524. printf("&pos=%ld&reply=1&form=newmsg"; STYLE="text-decoration: none">%s</A>&nbsp;</TD>n",
  525. (long)msg_pos,
  526. msg_replylab);
  527. /* REPLY ALL */
  528. printf("<TD BGCOLOR="#DDDDDD">&nbsp;<A HREF="");
  529. output_scriptptrget();
  530. printf("&pos=%ld&replyall=1&form=newmsg"; STYLE="text-decoration: none">%s</A>&nbsp;</TD>n",
  531. (long)msg_pos,
  532. msg_replyalllab);
  533. printf("</TR></TABLE><TABLE BORDER=0 CELLSPACING=4><TR>");
  534. /* FORWARD */
  535. printf("<TD BGCOLOR="#DDDDDD">&nbsp;<A HREF="");
  536. output_scriptptrget();
  537. printf("&pos=%ld&forward=1&form=newmsg"; STYLE="text-decoration: none">%s</A>&nbsp;</TD>n",
  538. (long)msg_pos,
  539. msg_forwardlab);
  540. /* FORWARD AS ATTACHMENT*/
  541. printf("<TD BGCOLOR="#DDDDDD">&nbsp;<A HREF="");
  542. output_scriptptrget();
  543. printf("&pos=%ld&forwardatt=1&form=newmsg"; STYLE="text-decoration: none">%s</A>&nbsp;</TD>n",
  544. (long)msg_pos,
  545. msg_forwardattlab);
  546. /* FULL HEADERS */
  547. if (!pref_flagfullheaders && !*cgi("fullheaders"))
  548. {
  549. printf("<TD BGCOLOR="#DDDDDD">&nbsp;<A HREF="");
  550. output_scriptptrget();
  551. printf("&pos=%ld&form=readmsg&fullheaders=1"; STYLE="text-decoration: none">%s</A>&nbsp;</TD>n",
  552. (long)msg_pos, msg_fullheaderlab);
  553. }
  554. /* PRINT MESSAGE */
  555. printf("<TD BGCOLOR="#DDDDDD">&nbsp;<A HREF="");
  556. output_scriptptrget();
  557. if (pref_flagfullheaders || *cgi("fullheaders"))
  558. {
  559. printf("&pos=%ld&form=print&setcookie=1&fullheaders=1"; STYLE="text-decoration: none" TARGET="_BLANK">%s</A>&nbsp;</TD>n", (long)msg_pos, msg_print);
  560. }
  561. else
  562. {
  563. printf("&pos=%ld&form=print&setcookie=1"; STYLE="text-decoration: none" TARGET="_BLANK">%s</A>&nbsp;</TD>n", (long)msg_pos, msg_print);
  564. }
  565. printf("</TD>");
  566. /* end PRINT MESSAGE */
  567.     printf("</TR></TABLE></TD><TD ALIGN=RIGHT VALIGN=CENTER>");
  568. printf("<TABLE BORDER=0 CELLSPACING=4><TR><TD BGCOLOR="#666666">&nbsp;<FONT COLOR="#FFFFFF">");
  569. printf(msg_msglab, (int)msg_pos+1, (int)msg_count);
  570. printf("</FONT>&nbsp;</TD></TR></TABLE>");
  571.     printf("</TD></TR></TABLE>n");
  572. }
  573. static void show_transfer_dest(const char *cur_folder)
  574. {
  575. char **folders;
  576. size_t i;
  577. const char *p;
  578. int has_shared=0;
  579. maildir_readfolders(&folders);
  580. for (i=0; folders[i]; i++)
  581. {
  582. /* Transferring TO drafts is prohibited */
  583. if (strcmp(cur_folder, DRAFTS))
  584. {
  585. if (strcmp(folders[i], DRAFTS) == 0)
  586. continue;
  587. }
  588. else
  589. {
  590. if (folders[i][0] != ':' && strcmp(folders[i], TRASH))
  591. continue;
  592. }
  593. if (strcmp(cur_folder, folders[i]) == 0)
  594. continue;
  595. p=folders[i];
  596. if (strcmp(p, INBOX) == 0)
  597. p=folder_inbox;
  598. else if (strcmp(p, DRAFTS) == 0)
  599. p=folder_drafts;
  600. else if (strcmp(p, TRASH) == 0)
  601. p=folder_trash;
  602. else if (strcmp(p, SENT) == 0)
  603. p=folder_sent;
  604. if (!p) p=folders[i];
  605. if (folders[i][0] == ':')
  606. {
  607. char *d=maildir_shareddir(".", folders[i]+1);
  608. if (!d)
  609. {
  610. maildir_freefolders(&folders);
  611. enomem();
  612. }
  613. if (access(d, 0)) /* Not subscribed */
  614. {
  615. free(d);
  616. continue;
  617. }
  618. free(d);
  619. }
  620. if (folders[i][0] == ':' && !has_shared)
  621. {
  622. printf("<OPTION VALUE="">n");
  623. has_shared=1;
  624. }
  625. printf("<OPTION VALUE="");
  626. output_attrencoded(folders[i]);
  627. printf("">");
  628. print_safe(folders[i][0] == ':' ? p+1:p);
  629. printf("n");
  630. }
  631. maildir_freefolders(&folders);
  632. }
  633. void folder_msgmove()
  634. {
  635. ++initnextprevcnt;
  636. printf("<TABLE BORDER=0 BGCOLOR="#000000"><TR><TD>n");
  637. printf("<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0><TR><TD BGCOLOR="#DDDDDD">&nbsp;%s%s&nbsp;<SELECT NAME=list%d>n",
  638. black_color, msg_movetolab, initnextprevcnt);
  639. show_transfer_dest(sqwebmail_folder);
  640. printf("</SELECT><INPUT TYPE=SUBMIT %s NAME=move%d VALUE="%s">%s</TD></TR></TABLE>n",
  641. (msg_type == MSGTYPE_DELETED ? "DISABLED":""),
  642. initnextprevcnt,
  643. msg_golab ? msg_golab:"",
  644. end_font);
  645. printf("</TD></TR></TABLE>n");
  646. }
  647. void folder_delmsg(size_t pos)
  648. {
  649. MSGINFO **info;
  650. int dummy;
  651. const char *f=cgi("posfile");
  652. size_t newpos;
  653. int rc=0;
  654. CHECKFILENAME(f);
  655. if (*cgi("move1"))
  656. {
  657. rc=maildir_msgmovefile(sqwebmail_folder, f, cgi("list1"), pos);
  658. maildir_savefoldermsgs(sqwebmail_folder);
  659. }
  660. else if (*cgi("move2"))
  661. {
  662. rc=maildir_msgmovefile(sqwebmail_folder, f, cgi("list2"), pos);
  663. maildir_savefoldermsgs(sqwebmail_folder);
  664. }
  665. else
  666. {
  667. maildir_msgdeletefile(sqwebmail_folder, f, pos);
  668. maildir_savefoldermsgs(sqwebmail_folder);
  669. }
  670. if (rc)
  671. {
  672. http_redirect_argu("&form=readmsg&pos=%s&error=quota",
  673. (unsigned long)newpos);
  674. return;
  675. }
  676. newpos=pos+1;
  677. info=maildir_read(sqwebmail_folder, 1, &newpos, &dummy, &dummy);
  678. if (info[0] && newpos != pos)
  679. {
  680. maildir_free(info, 1);
  681. http_redirect_argu("&form=readmsg&pos=%s",
  682. (unsigned long)newpos);
  683. }
  684. else
  685. {
  686. maildir_free(info, 1);
  687. http_redirect_argu("&form=folder&pos=%s",
  688. (unsigned long)pos);
  689. }
  690. }
  691. static void showmsgrfc822(FILE *, struct rfc2045 *, struct rfc2045id *);
  692. static void showmsgrfc822_body(FILE *, struct rfc2045 *, struct rfc2045id *, int);
  693. void folder_showmsg(const char *dir, size_t pos)
  694. {
  695. char *filename;
  696. FILE *fp;
  697. struct rfc2045 *rfc;
  698. char buf[512];
  699. int n;
  700. int fd;
  701. filename=maildir_posfind(dir, &pos);
  702. if (!filename) return;
  703. fp=0;
  704. fd=maildir_semisafeopen(filename, O_RDONLY, 0);
  705. if (fd >= 0)
  706. {
  707. if ((fp=fdopen(fd, "r")) == 0)
  708. close(fd);
  709. }
  710. if (!fp)
  711. {
  712. free(filename);
  713. return;
  714. }
  715. msg_pos=pos;
  716. rfc=rfc2045_alloc();
  717. while ((n=fread(buf, 1, sizeof(buf), fp)) > 0)
  718. rfc2045_parse(rfc, buf, n);
  719. showmsgrfc822_body(fp, rfc, NULL, 0);
  720. rfc2045_free(rfc);
  721. fclose(fp);
  722. maildir_markread(dir, pos);
  723. free(filename);
  724. }
  725. static void showtextplain(FILE *, struct rfc2045 *, struct rfc2045id *);
  726. static void showdsn(FILE *, struct rfc2045 *, struct rfc2045id *);
  727. static void showtexthtml(FILE *, struct rfc2045 *, struct rfc2045id *);
  728. static void showmultipart(FILE *, struct rfc2045 *, struct rfc2045id *);
  729. static void showmsgrfc822(FILE *, struct rfc2045 *, struct rfc2045id *);
  730. static void showunknown(FILE *, struct rfc2045 *, struct rfc2045id *);
  731. static void (*get_known_handler(struct rfc2045 *mime))(FILE *, struct rfc2045 *, struct rfc2045id *)
  732. {
  733. const char *content_type, *dummy;
  734. const char *disposition_s;
  735. const char *disposition_name_s;
  736. const char *disposition_filename_s;
  737. rfc2045_mimeinfo(mime, &content_type, &dummy, &dummy);
  738. if (strncmp(content_type, "multipart/", 10) == 0)
  739. return ( &showmultipart );
  740. rfc2045_dispositioninfo(mime, &disposition_s, &disposition_name_s,
  741. &disposition_filename_s);
  742. if (disposition_s && strcmp(disposition_s, "attachment") == 0)
  743. return (0);
  744. if (strcmp(content_type, "text/plain") == 0 ||
  745. strcmp(content_type, "text/rfc822-headers") == 0)
  746. return ( &showtextplain );
  747. if (strcmp(content_type, "message/delivery-status") == 0)
  748. return ( &showdsn);
  749. if (pref_showhtml && strcmp(content_type, "text/html") == 0)
  750. return ( &showtexthtml );
  751. if (strcmp(content_type, "message/rfc822") == 0)
  752. return ( &showmsgrfc822 );
  753. return (0);
  754. }
  755. static void (*get_handler(struct rfc2045 *mime))(FILE *, struct rfc2045 *, struct rfc2045id *)
  756. {
  757. void (*func)(FILE *, struct rfc2045 *, struct rfc2045id *);
  758. if ((func=get_known_handler(mime)) == 0)
  759. func= &showunknown;
  760. return (func);
  761. }
  762. static void showmsgrfc822(FILE *fp, struct rfc2045 *rfc, struct rfc2045id *id)
  763. {
  764. if (rfc->firstpart)
  765. showmsgrfc822_body(fp, rfc->firstpart, id, 1);
  766. }
  767. static void showmsgrfc822_header(const char *);
  768. static void showmsgrfc822_addressheader(const char *);
  769. static void showmsgrfc2369_header(const char *);
  770. static int isaddressheader(const char *header)
  771. {
  772. return (strcmp(header, "to") == 0 ||
  773. strcmp(header, "cc") == 0 ||
  774. strcmp(header, "from") == 0 ||
  775. strcmp(header, "sender") == 0 ||
  776. strcmp(header, "resent-to") == 0 ||
  777. strcmp(header, "resent-cc") == 0 ||
  778. strcmp(header, "reply-to") == 0);
  779. }
  780. static void showmimeid(struct rfc2045id *idptr)
  781. {
  782. char *p="&mimeid=";
  783. while (idptr)
  784. {
  785. printf("%s%d", p, idptr->idnum);
  786. idptr=idptr->next;
  787. p=".";
  788. }
  789. }
  790. static void digestaction(struct rfc2045id *idptr)
  791. {
  792. printf("<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0><TR><TD><A HREF="");
  793. output_scriptptrget();
  794. showmimeid(idptr);
  795. printf("&pos=%ld&reply=1&form=newmsg"><FONT SIZE="-1">%s</FONT></A>&nbsp;</TD><TD>&nbsp;<A HREF="",
  796. (long)msg_pos, msg_replylab);
  797. output_scriptptrget();
  798. showmimeid(idptr);
  799. printf("&pos=%ld&replyall=1&form=newmsg"><FONT SIZE="-1">%s</FONT></A>&nbsp;</TD><TD>&nbsp;<A HREF="",
  800. (long)msg_pos, msg_replyalllab);
  801. output_scriptptrget();
  802. showmimeid(idptr);
  803. printf("&pos=%ld&forward=1&form=newmsg"><FONT SIZE="-1">%s</FONT></A>&nbsp;</TD><TD>&nbsp;<A HREF="",
  804. (long)msg_pos, msg_forwardlab);
  805. output_scriptptrget();
  806. showmimeid(idptr);
  807. printf("&pos=%ld&forwardatt=1&form=newmsg"><FONT SIZE="-1">%s</FONT></A></TD></TR></TABLE>n",
  808. (long)msg_pos, msg_forwardattlab);
  809. }
  810. /* Prettify header name by uppercasing the first character. */
  811. void header_uc(char *h)
  812. {
  813. while (*h)
  814. {
  815. *h=toupper( (int)(unsigned char) *h);
  816. while (*h)
  817. {
  818. if (*h++ == '-') break;
  819. }
  820. }
  821. }
  822. static void showmsgrfc822_body(FILE *fp, struct rfc2045 *rfc, struct rfc2045id *idptr, int flag)
  823. {
  824. char *header, *value;
  825. char *save_subject=0;
  826. char *save_date=0;
  827. char *par;
  828. off_t start_pos, end_pos, start_body;
  829. struct rfc2045id *p, newpart;
  830. off_t dummy;
  831. off_t pos;
  832. rfc2045_mimepos(rfc, &start_pos, &end_pos, &start_body, &dummy, &dummy);
  833. if (fseek(fp, start_pos, SEEK_SET) < 0)
  834. {
  835. error("Seek error.");
  836. return;
  837. }
  838. printf("<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0>n");
  839. par="<P>";
  840. pos=start_pos;
  841. while ((header=maildir_readheader_mimepart(fp, &value, 1,
  842. &pos, &start_body)) != 0)
  843. {
  844. if (strcmp(header, "list-help") == 0 ||
  845. strcmp(header, "list-subscribe") == 0 ||
  846. strcmp(header, "list-unsubscribe") == 0 ||
  847. strcmp(header, "list-owner") == 0 ||
  848. strcmp(header, "list-archive") == 0 ||
  849. strcmp(header, "list-post") == 0)
  850. {
  851. header_uc(header);
  852. printf("<TR VALIGN=BASELINE><TH ALIGN=RIGHT>%s%s:<TT>&nbsp;</TT></TH>",
  853. par, header);
  854. par="";
  855. printf("<TD><TT>");
  856. showmsgrfc2369_header(value);
  857. printf("</TT></TD></TR>n");
  858. continue;
  859. }
  860. if (pref_flagfullheaders || *cgi("fullheaders"))
  861. {
  862. int isaddress=isaddressheader(header);
  863. header_uc(header);
  864. printf("<TR VALIGN=BASELINE><TH ALIGN=RIGHT>%s%s:<TT>&nbsp;</TT></TH>",
  865. par, header);
  866. printf("<TD><TT>");
  867. if (isaddress)
  868. showmsgrfc822_addressheader(value);
  869. else
  870. showmsgrfc822_header(value);
  871. printf("</TT></TD></TR>n");
  872. par="";
  873. continue;
  874. }
  875. if (strcmp(header, "subject") == 0)
  876. {
  877. if (save_subject) free(save_subject);
  878. save_subject=rfc2047_decode_enhanced(value,
  879. sqwebmail_content_charset);
  880. if (save_subject == 0)
  881. enomem();
  882. continue;
  883. }
  884. if (strcmp(header, "date") == 0)
  885. {
  886. if (save_date) free(save_date);
  887. if ((save_date=malloc(strlen(value)+1)) == 0)
  888. enomem();
  889. strcpy(save_date, value);
  890. continue;
  891. }
  892. if (isaddressheader(header))
  893. {
  894. header_uc(header);
  895. printf("<TR VALIGN=BASELINE><TH ALIGN=RIGHT>%s%s:<TT>&nbsp;</TT></TH>",
  896. par, header);
  897. printf("<TD><TT>");
  898. showmsgrfc822_addressheader(value);
  899. printf("</TT></TD></TR>n");
  900. par="";
  901. }
  902. }
  903. if (save_date)
  904. {
  905. time_t t=rfc822_parsedt(save_date);
  906. struct tm *tmp=t ? localtime(&t):0;
  907. char date_buf[100];
  908. if (tmp)
  909. {
  910. printf("<TR VALIGN=BASELINE><TH ALIGN=RIGHT>%sDate:<TT>&nbsp;</TT></TH>",
  911. par);
  912. strftime(date_buf, sizeof(date_buf)-1, "%d %b %Y, %I:%M:%S %p", tmp);
  913. date_buf[sizeof(date_buf)-1]=0;
  914. printf("<TD><TT>");
  915. showmsgrfc822_header(date_buf);
  916. printf("</TT></TD></TR>n");
  917. par="";
  918. }
  919. free(save_date);
  920. }
  921. if (save_subject)
  922. {
  923. printf("<TR VALIGN=BASELINE><TH ALIGN=RIGHT>%sSubject:<TT>&nbsp;</TT></TH>",
  924. par);
  925. printf("<TD><TT>");
  926. showmsgrfc822_header(save_subject);
  927. printf("</TT></TD></TR>n");
  928. par="";
  929. }
  930. if (flag)
  931. {
  932. printf("<TR VALIGN=TOP><TD>&nbsp;</TD><TD ALIGN=LEFT VALIGN=TOP>");
  933. digestaction(idptr);
  934. printf("</TD></TR>n");
  935. }
  936. printf("</TABLE>n<HR WIDTH="100%%">n");
  937. if (!idptr)
  938. {
  939. idptr= &newpart;
  940. p=0;
  941. }
  942. else
  943. {
  944. for (p=idptr; p->next; p=p->next)
  945. ;
  946. p->next=&newpart;
  947. }
  948. newpart.idnum=1;
  949. newpart.next=0;
  950. (*get_handler(rfc))(fp, rfc, idptr);
  951. if (p)
  952. p->next=0;
  953. }
  954. static void showmsgrfc822_headerp(const char *p, size_t l)
  955. {
  956. fwrite(p, 1, l, stdout);
  957. }
  958. static void showmsgrfc822_header(const char *p)
  959. {
  960. filter_start(FILTER_FOR_DISPLAY, showmsgrfc822_headerp);
  961. filter(p, strlen(p));
  962. filter_end();
  963. }
  964. static void showaddressheader_printc(char c, void *p)
  965. {
  966. p=p;
  967. print_safe_len(&c, 1, print_safe_to_stdout);
  968. }
  969. static void showaddressheader_printsep(const char *sep, void *p)
  970. {
  971. p=p;
  972. printf("%s", sep);
  973. }
  974. static void showmsgrfc822_addressheader(const char *p)
  975. {
  976. struct rfc822t *rfcp;
  977. struct  rfc822a *rfca;
  978. rfcp=rfc822t_alloc(p, NULL);
  979. if (!rfcp) enomem();
  980. rfca=rfc822a_alloc(rfcp);
  981. if (!rfca) enomem();
  982. rfc2047_print(rfca, sqwebmail_content_charset,
  983. showaddressheader_printc, showaddressheader_printsep, NULL);
  984. rfc822a_free(rfca);
  985. rfc822t_free(rfcp);
  986. }
  987. static void showrfc2369_printheader(char c, void *p)
  988. {
  989. p=p;
  990. putchar(c);
  991. }
  992. static char *get_textlink(const char *);
  993. static void showmsgrfc2369_header(const char *p)
  994. {
  995. struct rfc822t *rfcp;
  996. struct  rfc822a *rfca;
  997. int i;
  998. rfcp=rfc822t_alloc(p, NULL);
  999. if (!rfcp) enomem();
  1000. rfca=rfc822a_alloc(rfcp);
  1001. if (!rfca) enomem();
  1002. for (i=0; i<rfca->naddrs; i++)
  1003. {
  1004. char *p=rfc822_getaddr(rfca, i);
  1005. char *q=get_textlink(p);
  1006. if (rfca->addrs[i].tokens)
  1007. {
  1008. rfca->addrs[i].tokens->token=0;
  1009. if (*q)
  1010. free(p);
  1011. else
  1012. {
  1013. struct buf b;
  1014. buf_init(&b);
  1015. free(q);
  1016. for (q=p; *q; q++)
  1017. {
  1018. char c[2];
  1019. switch (*q) {
  1020. case '<':
  1021. buf_cat(&b, "&lt;");
  1022. break;
  1023. case '>':
  1024. buf_cat(&b, "&gt;");
  1025. break;
  1026. case '&':
  1027. buf_cat(&b, "&amp;");
  1028. break;
  1029. case ' ':
  1030. buf_cat(&b, "&nbsp;");
  1031. break;
  1032. default:
  1033. c[1]=0;
  1034. c[0]=*q;
  1035. buf_cat(&b, c);
  1036. break;
  1037. }
  1038. }
  1039. free(p);
  1040. q=strdup(b.ptr ? b.ptr:"");
  1041. buf_free(&b);
  1042. if (!q) enomem();
  1043. }
  1044. rfca->addrs[i].tokens->ptr=q;
  1045. rfca->addrs[i].tokens->len=strlen(q);
  1046. rfca->addrs[i].tokens->next=0;
  1047. }
  1048. else
  1049. {
  1050. free(q);
  1051. free(p);
  1052. }
  1053. }
  1054. rfc822_print(rfca, showrfc2369_printheader,
  1055. showaddressheader_printsep, NULL);
  1056. for (i=0; i<rfca->naddrs; i++)
  1057. if (rfca->addrs[i].tokens)
  1058. free((char *)rfca->addrs[i].tokens->ptr);
  1059. rfc822a_free(rfca);
  1060. rfc822t_free(rfcp);
  1061. }
  1062. static void output_mimeurl(struct rfc2045id *id)
  1063. {
  1064. output_scriptptrget();
  1065. printf("&form=fetch&pos=%ld", (long)msg_pos);
  1066. showmimeid(id);
  1067. }
  1068. static void showattname(const char *fmt, const char *name,
  1069. const char *content_type);
  1070. static void showunknown(FILE *fp, struct rfc2045 *rfc, struct rfc2045id *id)
  1071. {
  1072. const char *content_type, *dummy;
  1073. const char *disposition_s;
  1074. const char *disposition_name_s;
  1075. const char *disposition_filename_s;
  1076. id=id;
  1077. rfc2045_mimeinfo(rfc, &content_type, &dummy, &dummy);
  1078. rfc2045_dispositioninfo(rfc, &disposition_s, &disposition_name_s,
  1079. &disposition_filename_s);
  1080. /* Punt for image/ MIMEs */
  1081. if (strncmp(content_type, "image/", 6) == 0 &&
  1082. (disposition_s == 0 || strcmp(disposition_s, "attachment")))
  1083. {
  1084. printf("<A HREF="");
  1085. output_mimeurl(id);
  1086. printf("" TARGET="_blank"><IMG SRC="");
  1087. output_mimeurl(id);
  1088. printf("" ALT="Inline picture: ");
  1089. output_attrencoded(content_type);
  1090. printf(""></A>n");
  1091. return;
  1092. }
  1093. dummy=rfc2045_contentname(rfc);
  1094. printf("<TABLE BORDER=0 CELLPADDING=1 CELLSPACING=0 BGCOLOR="#000000"><TR><TD>");
  1095. printf("<TABLE BORDER=0 CELLPADDING=4 CELLSPACING=0 BGCOLOR="#DDDDDD"><TR><TD>");
  1096. if (msg_dispattachment)
  1097. {
  1098. printf("<CENTER><A HREF="");
  1099. output_mimeurl(id);
  1100. printf("" STYLE="text-decoration: none" TARGET="_blank">");
  1101. showattname(msg_dispattachment, dummy, content_type);
  1102. printf("</A></CENTER>");
  1103. }
  1104. printf("<HR WIDTH="100%%">n");
  1105. if (msg_downattachment)
  1106. {
  1107. printf("<CENTER><A HREF="");
  1108. output_mimeurl(id);
  1109. printf("&download=1" STYLE="text-decoration: none">");
  1110. showattname(msg_downattachment, dummy, content_type);
  1111. printf("</A></CENTER>");
  1112. }
  1113. printf("</TR></TD></TABLE>n");
  1114. printf("</TR></TD></TABLE>n");
  1115. }
  1116. static void showattname(const char *fmt, const char *name,
  1117. const char *content_type)
  1118. {
  1119. char *s, *t;
  1120. if (!name || !*name) name=content_type;
  1121. if (!name) name="";
  1122. s=rfc2047_decode_simple(name);
  1123. if (!s) return;
  1124. t=malloc(strlen(s)+strlen(fmt)+100);
  1125. if (!t)
  1126. {
  1127. free(s);
  1128. return;
  1129. }
  1130. sprintf(t, fmt, s ? s:name);
  1131. if (s) free(s);
  1132. output_attrencoded(t);
  1133. }
  1134. static void showmultipart(FILE *fp, struct rfc2045 *rfc, struct rfc2045id *id)
  1135. {
  1136. const char *content_type, *dummy;
  1137. struct rfc2045 *q;
  1138. struct rfc2045id nextpart;
  1139. struct rfc2045id *p;
  1140. for (p=id; p->next; p=p->next)
  1141. ;
  1142. p->next=&nextpart;
  1143. nextpart.idnum=0;
  1144. nextpart.next=0;
  1145. rfc2045_mimeinfo(rfc, &content_type, &dummy, &dummy);
  1146. if (strcmp(content_type, "multipart/alternative") == 0)
  1147. {
  1148. struct rfc2045 *q, *r=0;
  1149. int idnum=0;
  1150. for (q=rfc->firstpart; q; q=q->next, ++idnum)
  1151. {
  1152. if (q->isdummy) continue;
  1153. if (!r || get_known_handler(q))
  1154. {
  1155. r=q; /* Pick up at least one part */
  1156. nextpart.idnum=idnum;
  1157. }
  1158. }
  1159. if (r)
  1160. (*get_handler(r))(fp, r, id);
  1161. }
  1162. else if (strcmp(content_type, "multipart/related") == 0)
  1163. {
  1164. char *sid=rfc2045_related_start(rfc);
  1165. /*
  1166. ** We can't just walts in, search for the Content-ID:,
  1167. ** and skeddaddle, that's because we need to keep track of
  1168. ** our MIME section.  So we pretend that we're multipart/mixed,
  1169. ** see below, and abort at the first opportunity.
  1170. */
  1171. for (q=rfc->firstpart; q; q=q->next, ++nextpart.idnum)
  1172. {
  1173. const char *cid;
  1174. if (q->isdummy) continue;
  1175. cid=rfc2045_content_id(q);
  1176. if (sid && *sid && strcmp(sid, cid))
  1177. continue;
  1178. (*get_handler(q))(fp, q, id);
  1179. break;
  1180. /* In all cases, we stop after dumping something */
  1181. }
  1182. if (sid) free(sid);
  1183. }
  1184. else
  1185. {
  1186. for (q=rfc->firstpart; q; q=q->next, ++nextpart.idnum)
  1187. {
  1188. if (q->isdummy) continue;
  1189. (*get_handler(q))(fp, q, id);
  1190. if (q->next)
  1191. printf("<HR WIDTH="100%%">n");
  1192. }
  1193. }
  1194. p->next=0;
  1195. }
  1196. static void text_to_stdout(const char *p, size_t n)
  1197. {
  1198. while (n)
  1199. {
  1200. --n;
  1201. putchar(*p++);
  1202. }
  1203. }
  1204. static struct buf showtextplain_buf;
  1205. static const char *skip_text_url(const char *r, const char *end)
  1206. {
  1207. const char *q=r;
  1208. for (; r < end && (isalnum(*r) || *r == ':' || *r == '/'
  1209. || *r == '.' || *r == '~' || *r == '%'
  1210. || *r == '+' || *r == '?' || *r == '&' || *r == '#'
  1211. || *r == '=' || *r == '@' || *r == ';'
  1212. || *r == '-' || *r == '_' || *r == ','); r++)
  1213. {
  1214. if (*r == '&' && (end-r < 5 || strncmp(r, "&amp;", 5)))
  1215. break;
  1216. }
  1217. if (r > q && (r[-1] == ',' || r[-1] == '.')) --r;
  1218. return (r);
  1219. }
  1220. static char *decode_cgiurlencode(const char *s)
  1221. {
  1222. char *q=malloc(strlen(s)+1), *r;
  1223. const char *t;
  1224. if (!q) enomem();
  1225. for (r=q, t=s; *t; )
  1226. {
  1227. if (strncmp(t, "&amp;", 5) == 0)
  1228. {
  1229. *r++ = '&';
  1230. t += 5;
  1231. continue;
  1232. }
  1233. if (strncmp(t, "&lt;", 4) == 0)
  1234. {
  1235. *r++ = '<';
  1236. t += 4;
  1237. continue;
  1238. }
  1239. if (strncmp(t, "&gt;", 4) == 0)
  1240. {
  1241. *r++ = '>';
  1242. t += 4;
  1243. continue;
  1244. }
  1245. if (strncmp(t, "&quot;", 6) == 0)
  1246. {
  1247. *r++ = '"';
  1248. t += 6;
  1249. continue;
  1250. }
  1251. *r++ = *t++;
  1252. }
  1253. *r=0;
  1254. r=cgiurlencode(q);
  1255. free(q);
  1256. return (r);
  1257. }
  1258. static char *get_textlink(const char *s)
  1259. {
  1260. char *t;
  1261. struct buf b;
  1262. buf_init(&b);
  1263. if (strncmp(s, "mailto:", 7) == 0)
  1264. {
  1265. int i;
  1266. buf_cat(&b, "<A HREF="");
  1267. buf_cat(&b, scriptptrget());
  1268. buf_cat(&b, "&form=newmsg&to=");
  1269. for (i=7; s[i]; i++)
  1270. {
  1271. char c[2];
  1272. c[1]=0;
  1273. if ((c[0]=s[i]) == '?')
  1274. c[0]='&';
  1275. buf_cat(&b, c);
  1276. }
  1277. buf_cat(&b, "">");
  1278. buf_cat(&b, s);
  1279. buf_cat(&b, "</A>");
  1280. }
  1281. else if (strncmp(s, "http:", 5) == 0)
  1282. {
  1283. t=decode_cgiurlencode(s);
  1284. buf_cat(&b, "<A HREF="");
  1285. buf_cat(&b, getenv("SCRIPT_NAME"));
  1286. buf_cat(&b, "?redirect=");
  1287. buf_cat(&b, t);
  1288. buf_cat(&b, "" TARGET="_blank">");
  1289. buf_cat(&b, s);
  1290. buf_cat(&b, "</A>");
  1291. free(t);
  1292. }
  1293. t=strdup(b.ptr ? b.ptr:"");
  1294. if (!t) enomem();
  1295. buf_free(&b);
  1296. return (t);
  1297. }
  1298. static void showtextplain_oneline(const char *p, size_t n)
  1299. {
  1300. const char *q, *r;
  1301. char *s, *t;
  1302. for (q=r=p; q < p+n; q++)
  1303. {
  1304. if ( p+n-q > 7 &&
  1305. (strncmp(q, "http://", 7) == 0
  1306. ||
  1307. strncmp(q, "mailto:", 7) == 0)
  1308. )
  1309. {
  1310. fwrite(r, 1, q-r, stdout);
  1311. r=skip_text_url(q, p+n);
  1312. if ((s=malloc(r+1-q)) == NULL) enomem();
  1313. memcpy(s, q, r-q);
  1314. s[r-q]=0;
  1315. printf("%s", (t=get_textlink(s)));
  1316. free(t);
  1317. free(s);
  1318. q=r;
  1319. }
  1320. }
  1321. fwrite(r, 1, q-r, stdout);
  1322. }
  1323. static void showtextplainfunc(const char *txt, size_t l)
  1324. {
  1325. const char *p;
  1326. size_t n;
  1327. if (txt)
  1328. {
  1329. buf_catn(&showtextplain_buf, txt, l);
  1330. while ((p=strchr(showtextplain_buf.ptr, 'n')) != 0)
  1331. {
  1332. n= p+1 - showtextplain_buf.ptr;
  1333. showtextplain_oneline(showtextplain_buf.ptr, n);
  1334. buf_trimleft(&showtextplain_buf, n);
  1335. }
  1336. }
  1337. else if (showtextplain_buf.cnt)
  1338. showtextplain_oneline(showtextplain_buf.ptr,
  1339. showtextplain_buf.cnt);
  1340. }
  1341. static int filter_stub(const char *ptr, size_t cnt, void *voidptr)
  1342. {
  1343. filter(ptr, cnt);
  1344. return (0);
  1345. }
  1346. static void showtextplain(FILE *fp, struct rfc2045 *rfc, struct rfc2045id *id)
  1347. {
  1348. off_t start_pos, end_pos, start_body;
  1349. char buf[512];
  1350. int cnt;
  1351. off_t dummy;
  1352. id=id;
  1353. rfc2045_mimepos(rfc, &start_pos, &end_pos, &start_body, &dummy, &dummy);
  1354. if (fseek(fp, start_body, SEEK_SET) < 0)
  1355. {
  1356. error("Seek error.");
  1357. return;
  1358. }
  1359. printf("<TT><PRE>");
  1360. buf_init(&showtextplain_buf);
  1361. filter_start(FILTER_FOR_DISPLAY, &showtextplainfunc);
  1362. rfc2045_cdecode_start(rfc, &filter_stub, 0);
  1363. while (start_body < end_pos)
  1364. {
  1365. cnt=sizeof(buf);
  1366. if (cnt > end_pos-start_body)
  1367. cnt=end_pos-start_body;
  1368. cnt=fread(buf, 1, cnt, fp);
  1369. if (cnt <= 0) break;
  1370. rfc2045_cdecode(rfc, buf, cnt);
  1371. start_body += cnt;
  1372. }
  1373. rfc2045_cdecode_end(rfc);
  1374. filter_end();
  1375. showtextplainfunc(0, 0);
  1376. buf_free(&showtextplain_buf);
  1377. printf("</PRE></TT><BR>n");
  1378. }
  1379. static void showdsn(FILE *fp, struct rfc2045 *rfc, struct rfc2045id *id)
  1380. {
  1381. off_t start_pos, end_pos, start_body;
  1382. off_t dummy;
  1383. char *par;
  1384. id=id;
  1385. rfc2045_mimepos(rfc, &start_pos, &end_pos, &start_body, &dummy, &dummy);
  1386. if (fseek(fp, start_body, SEEK_SET) < 0)
  1387. {
  1388. error("Seek error.");
  1389. return;
  1390. }
  1391. par="<P>";
  1392. printf("<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0>n");
  1393. while (start_body < end_pos)
  1394. {
  1395. int c=getc(fp);
  1396. char *header, *value;
  1397. if (c == EOF) break;
  1398. if (c == 'n')
  1399. {
  1400. printf("<TR><TD COLSPAN=2><HR></TD></TR>n");
  1401. ++start_body;
  1402. par="<P>";
  1403. continue;
  1404. }
  1405. ungetc(c, fp);
  1406. if ((header=maildir_readheader_mimepart(fp, &value, 1,
  1407. &start_body, &end_pos)) == 0)
  1408. break;
  1409. header_uc(header);
  1410. printf("<TR VALIGN=BASELINE><TH ALIGN=RIGHT><FONT SIZE="-1">%s%s:</FONT><TT>&nbsp;</TT></TH>",
  1411. par, header);
  1412. par="";
  1413. printf("<TD><TT>");
  1414. /* showmsgrfc822_addressheader(value); */
  1415. printf("%s", value);
  1416. printf("</TT></TD></TR>n");
  1417. }
  1418. printf("</TABLE>n");
  1419. }
  1420. static int htmlfilter_stub(const char *ptr, size_t cnt, void *voidptr)
  1421. {
  1422. htmlfilter(ptr, cnt);
  1423. return (0);
  1424. }
  1425. /* Recursive search for a Content-ID: header that we want */
  1426. static struct rfc2045 *find_cid(struct rfc2045 *p, const char *cidurl)
  1427. {
  1428. const char *cid=rfc2045_content_id(p);
  1429. if (cid && strcmp(cid, cidurl) == 0)
  1430. return (p);
  1431. for (p=p->firstpart; p; p=p->next)
  1432. {
  1433. struct rfc2045 *q;
  1434. if (p->isdummy) continue;
  1435. q=find_cid(p, cidurl);
  1436. if (q) return (q);
  1437. }
  1438. return (0);
  1439. }
  1440. /*
  1441. ** Given an rfc2045 ptr, return the mime reference that will resolve to
  1442. ** this MIME part.
  1443. */
  1444. static char *rfc2mimeid(struct rfc2045 *p)
  1445. {
  1446. char buf[MAXLONGSIZE+1];
  1447. char *q=0;
  1448. unsigned n=p->pindex+1; /* mime counts start at one */
  1449. char *r;
  1450. if (p->parent)
  1451. {
  1452. q=rfc2mimeid(p->parent);
  1453. if (p->parent->firstpart->isdummy)
  1454. --n; /* ... except let's ignore the dummy part */
  1455. }
  1456. else n=1;
  1457. sprintf(buf, "%u", n);
  1458. r=malloc( (q ? strlen(q)+1:0)+strlen(buf)+1);
  1459. if (!r) enomem();
  1460. *r=0;
  1461. if (q)
  1462. {
  1463. strcat(strcat(r, q), ".");
  1464. free(q);
  1465. }
  1466. strcat(r, buf);
  1467. return (r);
  1468. }
  1469. /*
  1470. ** Convert cid: url to a http:// reference that will access the indicated
  1471. ** MIME section.
  1472. */
  1473. static char *convertcid(const char *cidurl, void *voidp)
  1474. {
  1475. struct rfc2045 *rfc= (struct rfc2045 *)voidp;
  1476. char *p;
  1477. char *mimeid;
  1478. char *q;
  1479. const char *pos;
  1480. if (rfc->parent) rfc=rfc->parent;
  1481. rfc=find_cid(rfc, cidurl);
  1482. if (!rfc) /* Not found, punt */
  1483. {
  1484. char *p=malloc(1);
  1485. if (!p) enomem();
  1486. *p=0;
  1487. return (p);
  1488. }
  1489. p=scriptptrget();
  1490. mimeid=rfc2mimeid(rfc);
  1491. pos=cgi("pos");
  1492. q=malloc(strlen(p)+strlen(mimeid)+strlen(pos) +
  1493. sizeof("&pos=&form=fetch&mimeid="));
  1494. if (!q) enomem();
  1495. strcpy(q, p);
  1496. strcat(q, "&form=fetch&pos=");
  1497. strcat(q, pos);
  1498. strcat(q, "&mimeid=");
  1499. strcat(q, mimeid);
  1500. free(p);
  1501. free(mimeid);
  1502. return (q);
  1503. }
  1504. static void showtexthtml(FILE *fp, struct rfc2045 *rfc, struct rfc2045id *id)
  1505. {
  1506. off_t start_pos, end_pos, start_body;
  1507. char buf[512];
  1508. int cnt;
  1509. static const char redirect[]="?redirect=";
  1510. const char *script_name=nonloginscriptptr();
  1511. char *washpfix;
  1512. char *washpfixmailto;
  1513. char *scriptnameget=scriptptrget();
  1514. static const char formbuf[]="&form=newmsg&to=";
  1515. off_t dummy;
  1516. char *content_base;
  1517. id=id;
  1518. if (!script_name) enomem();
  1519. rfc2045_mimepos(rfc, &start_pos, &end_pos, &start_body, &dummy, &dummy);
  1520. if (fseek(fp, start_body, SEEK_SET) < 0)
  1521. {
  1522. error("Seek error.");
  1523. return;
  1524. }
  1525. washpfix=malloc(strlen(script_name) + sizeof(redirect));
  1526. if (!washpfix) enomem();
  1527. strcat(strcpy(washpfix, script_name), redirect);
  1528. htmlfilter_washlink(washpfix);
  1529. htmlfilter_convertcid(&convertcid, rfc);
  1530. content_base=rfc2045_content_base(rfc);
  1531. htmlfilter_contentbase(content_base);
  1532. washpfixmailto=malloc(strlen(scriptnameget)+sizeof(formbuf));
  1533. if (!washpfixmailto) enomem();
  1534. strcat(strcpy(washpfixmailto, scriptnameget), formbuf);
  1535. htmlfilter_washlinkmailto(washpfixmailto);
  1536. htmlfilter_init(&text_to_stdout);
  1537. printf("<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0 WIDTH="100%%"><TR><TD>n");
  1538. rfc2045_cdecode_start(rfc, &htmlfilter_stub, 0);
  1539. while (start_body < end_pos)
  1540. {
  1541. cnt=sizeof(buf);
  1542. if (end_pos - start_body < cnt)
  1543. cnt=end_pos - start_body;
  1544. cnt=fread(buf, 1, cnt, fp);
  1545. if (cnt <= 0) break;
  1546. rfc2045_cdecode(rfc, buf, cnt);
  1547. start_body += cnt;
  1548. }
  1549. rfc2045_cdecode_end(rfc);
  1550. printf("</TD></TR></TABLE>n");
  1551. free(washpfix);
  1552. free(washpfixmailto);
  1553. free(content_base);
  1554. }
  1555. static char *get_parent_folder(const char *p)
  1556. {
  1557. const char *q=strrchr(p, '.');
  1558. char *s;
  1559. if (!q)
  1560. {
  1561. s=strdup("");
  1562. if (!s) enomem();
  1563. return (s);
  1564. }
  1565. s=malloc(q-p+1);
  1566. if (!s) enomem();
  1567. memcpy(s, p, q-p);
  1568. s[q-p]=0;
  1569. return (s);
  1570. }
  1571. void folder_list()
  1572. {
  1573. char **folders;
  1574. size_t i;
  1575. unsigned nnew, nother;
  1576. char *args=strdup(form_args);
  1577. char *unread_label;
  1578. char *err_invalid;
  1579. char *err_exists;
  1580. char *err_cantdelete;
  1581. char *msg_hasbeensent;
  1582. char *name_inbox;
  1583. char *name_drafts;
  1584. char *name_sent;
  1585. char *name_trash;
  1586. char *folder_img;
  1587. char *folders_img;
  1588. const char *folderdir;
  1589. if (!args) return;
  1590. unread_label=strtok(args, "|");
  1591. err_invalid=strtok(NULL, "|");
  1592. err_exists=strtok(NULL, "|");
  1593. err_cantdelete=strtok(NULL, "|");
  1594. msg_hasbeensent=strtok(NULL, "|");
  1595. name_inbox=strtok(NULL, "|");
  1596. name_drafts=strtok(NULL, "|");
  1597. name_sent=strtok(NULL, "|");
  1598. name_trash=strtok(NULL, "|");
  1599. folder_img=strtok(NULL, "|");
  1600. folders_img=strtok(NULL, "|");
  1601. if (!unread_label) unread_label="";
  1602. if (!err_invalid) err_invalid="";
  1603. if (!err_exists) err_exists="";
  1604. if (!err_cantdelete) err_cantdelete="";
  1605. if (!name_inbox) name_inbox="";
  1606. if (!name_drafts) name_drafts="";
  1607. if (!name_sent) name_sent="";
  1608. if (!name_trash) name_trash="";
  1609. if (!folder_img) folder_img="";
  1610. if (!folders_img) folders_img="";
  1611. if (folder_err_msg)
  1612. free(folder_err_msg);
  1613. folder_err_msg=0;
  1614. if (strcmp(cgi("foldermsg"), "sent") == 0)
  1615. folder_err_msg=msg_hasbeensent;
  1616. if (strcmp(cgi("cmd"), "newfolder") == 0)
  1617. {
  1618. const char *newfoldername=cgi("foldername");
  1619. const char *newdirname=cgi("dirname");
  1620. const char *folderdir=cgi("folderdir");
  1621. /*
  1622. ** New folder names cannot contain :s, and must be considered
  1623. ** as valid by maildir_folderpath.
  1624. */
  1625. if (!*newfoldername ||
  1626. strchr(newfoldername, '.') ||
  1627. strchr(newdirname, '.'))
  1628. folder_err_msg=err_invalid;
  1629. {
  1630. char *p=malloc(strlen(folderdir)+strlen(newfoldername)
  1631. +strlen(newdirname)+2);
  1632. if (!p) enomem();
  1633. strcpy(p, folderdir);
  1634. if (*newdirname)
  1635. {
  1636. if (*p) strcat(p, ".");
  1637. strcat(p, newdirname);
  1638. }
  1639. if (*p) strcat(p, ".");
  1640. strcat(p, newfoldername);
  1641. if (strchr(p, ':'))
  1642. {
  1643. free(p);
  1644. folder_err_msg=err_invalid;
  1645. }
  1646. else
  1647. {
  1648. char *q=maildir_folderdir(0, p);
  1649. if (!q)
  1650. folder_err_msg=err_invalid;
  1651. else
  1652. {
  1653. free(q);
  1654. if (maildir_create(p))
  1655. folder_err_msg=err_exists;
  1656. }
  1657. free(p);
  1658. }
  1659. }
  1660. }
  1661. if (*cgi("do.delete"))
  1662. {
  1663. const char *p=cgi("DELETE");
  1664. char *pp=strdup(p);
  1665. if (pp && strchr(pp, ':') == 0)
  1666. {
  1667. if (maildir_delete(pp))
  1668. folder_err_msg=err_cantdelete;
  1669. free(pp);
  1670. }
  1671. }
  1672. if (*cgi("do.subunsub"))
  1673. {
  1674. const char *p=cgi("DELETE");
  1675. char *pp=strdup(p);
  1676. char *d;
  1677. if (pp && *pp == ':' &&
  1678. (d=maildir_shareddir(".", pp+1)) != 0)
  1679. {
  1680. if (access(d, 0) == 0)
  1681. maildir_shared_unsubscribe(".", pp+1);
  1682. else
  1683. maildir_shared_subscribe(".", pp+1);
  1684. free(d);
  1685. }
  1686. if (pp)
  1687. free(pp);
  1688. }
  1689. if (*cgi("do.rename"))
  1690. {
  1691. const char *p=cgi("DELETE");
  1692. char *pp=strdup(p);
  1693. if (pp && strchr(pp, ':') == 0)
  1694. {
  1695. const char *q=cgi("renametofolder");
  1696. const char *r=cgi("renametoname");
  1697. char *s=malloc(strlen(q)+strlen(r)+1);
  1698. char *t;
  1699. if (!s) enomem();
  1700. *s=0;
  1701. if (strchr(q, '.'))
  1702. strcpy(s, q);
  1703. strcat(s, r);
  1704. if (strchr(s, ':') || (t=maildir_folderdir(0, s)) == 0)
  1705. folder_err_msg=err_invalid;
  1706. else
  1707. {
  1708. if (access(t, 0) == 0)
  1709. folder_err_msg=err_exists;
  1710. else
  1711. {
  1712. if (maildir_rename(pp, s))
  1713. folder_err_msg=err_cantdelete;
  1714. }
  1715. free(t);
  1716. }
  1717. free(pp);
  1718. free(s);
  1719. }
  1720. }
  1721. if (folder_err_msg)
  1722. {
  1723. char *p=malloc(strlen(folder_err_msg)+1);
  1724. if (!p) enomem();
  1725. strcpy(p, folder_err_msg);
  1726. folder_err_msg=p;
  1727. }
  1728. sqwebmail_folder=0;
  1729. folderdir=cgi("folderdir");
  1730. printf("<TABLE WIDTH="100%%" BORDER=0 CELLPADDING=2 CELLSPACING=0 BGCOLOR="#FFFFC0">n");
  1731. maildir_readfolders(&folders);
  1732. if (*folderdir)
  1733. {
  1734. char *parentfolder=get_parent_folder(folderdir);
  1735. size_t i;
  1736. printf("<TR><TD ALIGN=LEFT COLSPAN=2 BGCOLOR="#EEEE80">%s&lt;&lt;&lt;&nbsp;<A HREF="", folders_img);
  1737. output_scriptptrget();
  1738. printf("&form=folders&folder=INBOX">");
  1739. print_safe(name_inbox);
  1740. printf("</A>");
  1741. i=0;
  1742. while (parentfolder[i])
  1743. {
  1744. char *p=strchr(parentfolder+i, '.');
  1745. int c;
  1746. if (!p) p=parentfolder+strlen(parentfolder);
  1747. c= *p;
  1748. *p=0;
  1749. printf(".<A HREF="");
  1750. output_scriptptrget();
  1751. printf("&form=folders&folder=INBOX&folderdir=");
  1752. output_urlencoded(parentfolder);
  1753. printf("">");
  1754. print_safe(parentfolder+i);
  1755. printf("</A>");
  1756. if ( (*p=c) != 0) ++p;
  1757. i=p-parentfolder;
  1758. }
  1759. printf("</TD></TR>n");
  1760. free(parentfolder);
  1761. }
  1762. for (i=0; folders[i]; i++)
  1763. {
  1764. const char *p;
  1765. const char *shortname=folders[i];
  1766. size_t j;
  1767. const char *pfix=0;
  1768. int isshared=0;
  1769. int isunsubscribed=0;
  1770. char *img=folder_img;
  1771. if (*shortname == ':') /* Shared folders */
  1772. {
  1773. char *dir;
  1774. isshared=1;
  1775. pfix="+++";
  1776. dir=maildir_shareddir(".", shortname+1);
  1777. if (!dir) continue;
  1778. if (access(dir, 0))
  1779. isunsubscribed=1;
  1780. free(dir);
  1781. }
  1782. if (*folderdir)
  1783. {
  1784. unsigned l=strlen(folderdir);
  1785. if (memcmp(shortname, folderdir, l) ||
  1786. shortname[l] != '.') continue;
  1787. shortname += l;
  1788. ++shortname;
  1789. pfix=0;
  1790. }
  1791. if (!pfix)
  1792. {
  1793. pfix="&gt;&gt;&gt;";
  1794. }
  1795. if ((p=strchr(shortname, '.')) != 0)
  1796. {
  1797. char *s=malloc(p+1-folders[i]), *t;
  1798. unsigned tot_nnew, tot_nother;
  1799. if (!s) enomem();
  1800. memcpy(s, folders[i], p-folders[i]);
  1801. s[p-folders[i]]=0;
  1802. img=folders_img;
  1803. printf("<TR BGCOLOR="#EEEE80"><TD ALIGN=LEFT>%s%s&nbsp;<A HREF="", img, pfix);
  1804. output_scriptptrget();
  1805. printf("&form=folders&folder=INBOX&folderdir=");
  1806. output_urlencoded(s);
  1807. printf("">");
  1808. free(s);
  1809. t=malloc(p-shortname+1);
  1810. if (!t) enomem();
  1811. memcpy(t, shortname, p-shortname);
  1812. t[p-shortname]=0;
  1813. print_safe(isshared ? t+1:t);
  1814. free(t);
  1815. printf("</A>");
  1816. tot_nnew=0;
  1817. tot_nother=0;
  1818. j=i;
  1819. while (folders[j] && memcmp(folders[j], folders[i],
  1820. p-folders[i]+1) == 0)
  1821. {
  1822. maildir_count(folders[j], &nnew, &nother);
  1823. ++j;
  1824. tot_nnew += nnew;
  1825. tot_nother += nother;
  1826. }
  1827. i=j-1;
  1828. if (tot_nnew)
  1829. {
  1830. printf(" <FONT COLOR="#800000" SIZE="-1">");
  1831. printf(unread_label, tot_nnew);
  1832. printf(end_font);
  1833. }
  1834. printf("</TD><TD ALIGN=RIGHT VALIGN=TOP>%s%d%s&nbsp;&nbsp;</TD></TR>nn",
  1835. black_color, tot_nnew + tot_nother, end_font);
  1836. continue;
  1837. }
  1838. nnew=0;
  1839. nother=0;
  1840. if (!isunsubscribed)
  1841. maildir_count(folders[i], &nnew, &nother);
  1842. printf("<TR %s><TD ALIGN=LEFT VALIGN=TOP>",
  1843. isunsubscribed ? "BGCOLOR="#DDDD80"":"");
  1844. printf("%s<INPUT BORDER=0 TYPE="radio" NAME="DELETE" VALUE="", img);
  1845. output_attrencoded(folders[i]);
  1846. printf("">&nbsp;");
  1847. if (!isunsubscribed)
  1848. {
  1849. printf("<A HREF="");
  1850. output_scriptptrget();
  1851. printf("&form=folder&folder=");
  1852. output_urlencoded(folders[i]);
  1853. printf("">");
  1854. }
  1855. if (strcmp(folders[i], INBOX) == 0)
  1856. shortname=name_inbox;
  1857. else if (strcmp(folders[i], DRAFTS) == 0)
  1858. shortname=name_drafts;
  1859. else if (strcmp(folders[i], TRASH) == 0)
  1860. shortname=name_trash;
  1861. else if (strcmp(folders[i], SENT) == 0)
  1862. shortname=name_sent;
  1863. print_safe(shortname);
  1864. if (!isunsubscribed)
  1865. printf("</A>");
  1866. if (nnew)
  1867. {
  1868. printf(" <FONT COLOR="#800000" SIZE="-1">");
  1869. printf(unread_label, nnew);
  1870. printf(end_font);
  1871. }
  1872. printf("</TD><TD ALIGN=RIGHT VALIGN=TOP>");
  1873. if (!isunsubscribed)
  1874. {
  1875. printf("%s%d%s&nbsp;&nbsp;",
  1876. black_color, nnew + nother, end_font);
  1877. }
  1878. else
  1879. printf("&nbsp;n");
  1880. printf("</TD></TR>nn");
  1881. }
  1882. maildir_freefolders(&folders);
  1883. printf("</TABLE>n");
  1884. free(args);
  1885. }
  1886. void folder_list2()
  1887. {
  1888. if (folder_err_msg)
  1889. {
  1890. printf("<P><FONT COLOR="FF0000" SIZE="+1">%s%s<BR><BR>n",
  1891. folder_err_msg, end_font);
  1892. }
  1893. }
  1894. void folder_rename_list()
  1895. {
  1896. char **folders;
  1897. int i;
  1898. printf("<select name="renametofolder">n");
  1899. printf("<option value="%s">", INBOX);
  1900. printf("( ... )");
  1901. printf("</option>n");
  1902. maildir_readfolders(&folders);
  1903. for (i=0; folders[i]; i++)
  1904. {
  1905. const char *p=folders[i];
  1906. char *q;
  1907. size_t ql;
  1908. if (*p == ':') continue; /* Omit shared hierarchy */
  1909. p=strrchr(folders[i], '.');
  1910. if (!p) continue;
  1911. q=malloc(p-folders[i]+1);
  1912. if (!q) enomem();
  1913. memcpy(q, folders[i], p-folders[i]);
  1914. q[p-folders[i]]=0;
  1915. printf("<OPTION VALUE="");
  1916. output_attrencoded(q);
  1917. printf("." %s>",
  1918. strcmp(q, cgi("folderdir")) == 0 ? "SELECTED":"");
  1919. output_attrencoded(q);
  1920. printf(".</OPTION>n");
  1921. ql=strlen(q);
  1922. while (folders[++i])
  1923. {
  1924. if (memcmp(folders[i], q, ql) ||
  1925. folders[i][ql] != '.' ||
  1926. strchr(folders[i]+ql+1, '.')) break;
  1927. }
  1928. --i;
  1929. free(q);
  1930. }
  1931. maildir_freefolders(&folders);
  1932. printf("</select>n");
  1933. }
  1934. static int download_func(const char *, size_t, void *);
  1935. void disposition_attachment(FILE *fp, const char *p)
  1936. {
  1937. fprintf(fp, "Content-Disposition: attachment; filename="");
  1938. while (*p)
  1939. {
  1940. if (*p == '"' || *p == '\')
  1941. putc('\', fp);
  1942. if (!ISCTRL(*p))
  1943. putc(*p, fp);
  1944. p++;
  1945. }
  1946. fprintf(fp, ""n");
  1947. }
  1948. void folder_download(const char *folder, size_t pos, const char *mimeid)
  1949. {
  1950. char *filename;
  1951. struct rfc2045 *rfc, *part;
  1952. char buf[BUFSIZ];
  1953. int n,cnt;
  1954. const char *content_type, *dummy, *charset;
  1955. off_t start_pos, end_pos, start_body;
  1956. FILE *fp;
  1957. const char *content_name;
  1958. off_t ldummy;
  1959. const char *disposition_s;
  1960. const char *disposition_name_s;
  1961. const char *disposition_filename_s;
  1962. int fd;
  1963. filename=maildir_posfind(folder, &pos);
  1964. if (!filename) error("Message not found.");
  1965. fp=0;
  1966. fd=maildir_semisafeopen(filename, O_RDONLY, 0);
  1967. if (fd >= 0)
  1968. {
  1969. if ((fp=fdopen(fd, "r")) == 0)
  1970. close(fd);
  1971. }
  1972. if (!fp)
  1973. {
  1974. free(filename);
  1975. error("Message not found.");
  1976. return;
  1977. }
  1978. free(filename);
  1979. rfc=rfc2045_alloc();
  1980. while ((n=fread(buf, 1, sizeof(buf), fp)) > 0)
  1981. rfc2045_parse(rfc, buf, n);
  1982. part=rfc2045_find(rfc, mimeid);
  1983. if (!part) error("Message not found.");
  1984. rfc2045_mimeinfo(part, &content_type, &dummy, &charset);
  1985. rfc2045_dispositioninfo(part, &disposition_s, &disposition_name_s,
  1986. &disposition_filename_s);
  1987. cginocache();
  1988. content_name=rfc2045_contentname(part);
  1989. if (*cgi("download") == '1')
  1990. {
  1991. const char *p=disposition_filename_s;
  1992. if (!p || !*p) p=content_name;
  1993. if (!p || !*p) p="message.dat";
  1994. disposition_attachment(stdout, p);
  1995. content_type="application/octet-stream";
  1996. }
  1997. printf(
  1998. *content_name ?
  1999. "Content-Type: %s; charset="%s"; name="%s"nn":
  2000. "Content-Type: %s; charset="%s"nn",
  2001. content_type, charset, content_name);
  2002. rfc2045_mimepos(part, &start_pos, &end_pos, &start_body,
  2003. &ldummy, &ldummy);
  2004. if (fseek(fp, start_body, SEEK_SET) < 0)
  2005. {
  2006. error("Seek error.");
  2007. return;
  2008. }
  2009. rfc2045_cdecode_start(part, &download_func, 0);
  2010. while (start_body < end_pos)
  2011. {
  2012. cnt=sizeof(buf);
  2013. if (cnt > end_pos-start_body)
  2014. cnt=end_pos-start_body;
  2015. cnt=fread(buf, 1, cnt, fp);
  2016. if (cnt <= 0) break;
  2017. start_body += cnt;
  2018. rfc2045_cdecode(part, buf, cnt);
  2019. }
  2020. rfc2045_cdecode_end(part);
  2021. fclose(fp);
  2022. }
  2023. static int download_func(const char *p, size_t cnt, void *voidptr)
  2024. {
  2025. while (cnt--)
  2026. if (putchar(*p++) == EOF)
  2027. {
  2028. cleanup();
  2029. fake_exit(0);
  2030. }
  2031. return (0);
  2032. }
  2033. void folder_showtransfer()
  2034. {
  2035. char *p;
  2036. char *deletelab, *purgelab, *movelab, *golab;
  2037. p=strdup(form_args);
  2038. if (!p) return;
  2039. (void)strtok(p, "|");
  2040. (void)strtok(0, "|");
  2041. (void)strtok(0, "|");
  2042. (void)strtok(0, "|");
  2043. (void)strtok(0, "|");
  2044. (void)strtok(0, "|");
  2045. deletelab=strtok(0, "|");
  2046. purgelab=strtok(0, "|");
  2047. movelab=strtok(0, "|");
  2048. golab=strtok(0, "|");
  2049. if (!deletelab) deletelab="";
  2050. if (!purgelab) purgelab="";
  2051. if (!movelab) movelab="";
  2052. if (!golab) golab="";
  2053. (void)strtok(0, "|");
  2054. (void)strtok(0, "|");
  2055. (void)strtok(0, "|");
  2056. folder_inbox=strtok(NULL, "|");
  2057. folder_drafts=strtok(NULL, "|");
  2058. folder_trash=strtok(NULL, "|");
  2059. folder_sent=strtok(NULL, "|");
  2060. printf("<INPUT TYPE=HIDDEN NAME=pos VALUE=%s>", cgi("pos"));
  2061. printf("<INPUT TYPE=SUBMIT NAME=cmddel VALUE="%s">%s%s%s<SELECT NAME=moveto>",
  2062. strcmp(sqwebmail_folder, TRASH) == 0
  2063. ? purgelab:deletelab,
  2064. black_color, movelab, end_font);
  2065. show_transfer_dest(sqwebmail_folder);
  2066. printf("</SELECT><INPUT TYPE=SUBMIT NAME=cmdmove VALUE="%s">n",
  2067. golab);
  2068. }
  2069. void
  2070. folder_cleanup()
  2071. {
  2072. msg_purgelab=0;
  2073. msg_folderlab=0;
  2074. folder_drafts=0;
  2075. folder_inbox=0;
  2076. folder_sent=0;
  2077. folder_trash=0;
  2078. msg_badcontenttype=0;
  2079. msg_dispattachment=0;
  2080. msg_downattachment=0;
  2081. msg_forwardattlab=0;
  2082. msg_forwardlab=0;
  2083. msg_fullheaderlab=0;
  2084. msg_golab=0;
  2085. msg_movetolab=0;
  2086. msg_nextlab=0;
  2087. msg_prevlab=0;
  2088. msg_deletelab=0;
  2089. msg_posfile=0;
  2090. msg_replyalllab=0;
  2091. msg_replylab=0;
  2092. folder_err_msg=0;
  2093. msg_msglab=0;
  2094. msg_type=0;
  2095. initnextprevcnt=0;
  2096. msg_hasprev=0;
  2097. msg_hasnext=0;
  2098. msg_pos=0;
  2099. msg_count=0;
  2100. }