Back to index

courier  0.68.2
folder.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 2011 Double Precision, Inc.  See COPYING for
00003 ** distribution information.
00004 */
00005 
00006 
00007 /*
00008 */
00009 #include      "config.h"
00010 #include      <stdio.h>
00011 #include      <string.h>
00012 #include      <ctype.h>
00013 #include      <fcntl.h>
00014 #include      <stdlib.h>
00015 #include      "sqwebmail.h"
00016 #include      "maildir/maildirmisc.h"
00017 #include      "maildir/maildircreate.h"
00018 #include      "maildir/maildirnewshared.h"
00019 #include      "maildir/maildirinfo.h"
00020 #include      "maildir/maildiraclt.h"
00021 
00022 #include      "rfc822/rfc822.h"
00023 #include      "rfc822/rfc2047.h"
00024 #include      "rfc2045/rfc2045.h"
00025 #include      "md5/md5.h"
00026 #include      "gpglib/gpglib.h"
00027 #include      "maildir.h"
00028 #include      "mailfilter.h"
00029 #include      "maildir/maildirquota.h"
00030 #include      "maildir/maildirgetquota.h"
00031 #include      "maildir/maildirinfo.h"
00032 #include      "numlib/numlib.h"
00033 #include      "courierauth.h"
00034 #include      "folder.h"
00035 #include      "addressbook.h"
00036 #include      "cgi/cgi.h"
00037 #include      "pref.h"
00038 #include      "token.h"
00039 #include      "filter.h"
00040 #include      "buf.h"
00041 #include      "pref.h"
00042 #include      "newmsg.h"
00043 #include      "htmllibdir.h"
00044 #include      "gpg.h"
00045 #include      "acl.h"
00046 #include      "auth.h"
00047 
00048 #include      "msg2html.h"
00049 
00050 #if    HAVE_LOCALE_H
00051 #if    HAVE_SETLOCALE
00052 #include      <locale.h>
00053 #endif
00054 #endif
00055 
00056 #if    TIME_WITH_SYS_TIME
00057 #include      <sys/time.h>
00058 #include      <time.h>
00059 #else
00060 #if    HAVE_SYS_TIME_H
00061 #include      <sys/time.h>
00062 #else
00063 #include      <time.h>
00064 #endif
00065 #endif
00066 #if    HAVE_SYS_STAT_H
00067 #include      <sys/stat.h>
00068 #endif
00069 #include      <errno.h>
00070 
00071 #include      "unicode/unicode.h"
00072 
00073 #include      <unistd.h>
00074 #if HAVE_WCHAR_H
00075 #include      <wchar.h>
00076 #endif
00077 
00078 #include      "strftime.h"
00079 
00080 extern FILE *open_langform(const char *lang, const char *formname,
00081                         int print_header);
00082 
00083 extern const char *sqwebmail_content_language;
00084 extern char sqwebmail_folder_rights[];
00085 extern const char *sqwebmail_mailboxid;
00086 extern char *get_imageurl();
00087 extern const char *sqwebmail_content_locale;
00088 extern void print_attrencodedlen(const char *, size_t, int, FILE *);
00089 
00090 extern const char *showsize(unsigned long);
00091 extern void maildir_cleanup();
00092 extern const char *nonloginscriptptr();
00093 extern int pref_flagpagesize;
00094 extern int ishttps();
00095 extern const char *sqwebmail_content_charset;
00096 extern int verify_shared_index_file;
00097 
00098 extern time_t rfc822_parsedt(const char *);
00099 static time_t current_time;
00100 
00101 static const char *folder_err_msg=0;
00102 
00103 extern const char *sqwebmail_folder;
00104 
00105 extern void output_scriptptrget();
00106 extern void output_scriptptr();
00107 extern void output_scriptptrpostinfo();
00108 extern void output_attrencoded(const char *);
00109 extern void output_urlencoded(const char *);
00110 extern char *scriptptrget();
00111 
00112 void print_safe_len(const char *p, size_t n, void (*func)(const char *, size_t))
00113 {
00114 char   buf[10];
00115 const  char *q=p;
00116 
00117        while (n)
00118        {
00119               --n;
00120               if (*p == '<')       strcpy(buf, "&lt;");
00121               else if (*p == '>') strcpy(buf, "&gt;");
00122               else if (*p == '&') strcpy(buf, "&amp;");
00123               else if (*p == ' ') strcpy(buf, "&nbsp;");
00124               else if (*p == '\n') strcpy(buf, "<br />");
00125               else if (ISCTRL(*p))
00126                      sprintf(buf, "&#%d;", (int)(unsigned char)*p);
00127               else
00128               {
00129                      p++;
00130                      continue;
00131               }
00132 
00133               (*func)(q, p-q);
00134               (*func)(buf, strlen(buf));
00135               p++;
00136               q=p;
00137        }
00138        (*func)(q, p-q);
00139 }
00140 
00141 static void print_safe_to_stdout(const char *p, size_t cnt)
00142 {
00143        if (cnt == 0)
00144               return;
00145 
00146        if (fwrite(p, cnt, 1, stdout) != 1)
00147               exit(1);
00148 }
00149 
00150 void print_safe(const char *p)
00151 {
00152        print_safe_len(p, strlen(p), print_safe_to_stdout);
00153 }
00154 
00155 void call_print_safe_to_stdout(const char *p, size_t cnt)
00156 {
00157        print_safe_len(p, cnt, print_safe_to_stdout);
00158 }
00159        
00160 void folder_contents_title()
00161 {
00162 const char *lab;
00163 const char *f;
00164 const char *inbox_lab, *drafts_lab, *trash_lab, *sent_lab;
00165 int in_utf8;
00166 
00167        lab=getarg("FOLDERTITLE");
00168 
00169        if (*cgi("search"))
00170               lab=getarg("SEARCHRESULTSTITLE");
00171 
00172        inbox_lab=getarg("INBOX");
00173        drafts_lab=getarg("DRAFTS");
00174        trash_lab=getarg("TRASH");
00175        sent_lab=getarg("SENT");
00176 
00177        f=sqwebmail_folder;
00178        in_utf8=1;
00179 
00180        if (strcmp(f, INBOX) == 0)  f=inbox_lab;
00181        else if (strcmp(f, INBOX "." DRAFTS) == 0)       f=drafts_lab;
00182        else if (strcmp(f, INBOX "." SENT) == 0)  f=sent_lab;
00183        else if (strcmp(f, INBOX "." TRASH) == 0) f=trash_lab;
00184        else in_utf8=0;
00185 
00186        if (lab)
00187        {
00188               char *ff, *origff;
00189 
00190               printf("%s", lab);
00191 
00192               origff=ff=in_utf8 ?
00193                      libmail_u_convert_fromutf8(f,
00194                                              sqwebmail_content_charset,
00195                                              NULL)
00196                      : folder_fromutf7(f);
00197 
00198               if (strcmp(ff, NEWSHAREDSP) == 0 ||
00199                   strncmp(ff, NEWSHAREDSP ".", sizeof(NEWSHAREDSP)) == 0)
00200               {
00201                      printf("%s", getarg("PUBLICFOLDERS"));
00202                      ff=strchr(ff, '.');
00203                      if (!ff)
00204                             ff="";
00205               }
00206               output_attrencoded(ff);
00207               free(origff);
00208        }
00209 }
00210 
00211 static int group_movedel(const char *folder,
00212                      int (*func)(const char *, const char *, size_t))
00213 {
00214 struct cgi_arglist *arg;
00215 
00216        if (*cgi("SELECTALL"))      /* Everything is selected */
00217        {
00218               for (arg=cgi_arglist; arg; arg=arg->next)
00219               {
00220               const  char *f;
00221 
00222                      if (strncmp(arg->argname, "MOVEFILE-", 9)) continue;
00223                      f=cgi(arg->argname);
00224                      CHECKFILENAME(f);
00225                      if ((*func)(folder, f, atol(arg->argname+9)))
00226                             return (-1);
00227               }
00228               return (0);
00229        }
00230 
00231        for (arg=cgi_arglist; arg; arg=arg->next)
00232        {
00233        unsigned long l;
00234        char   movedel[MAXLONGSIZE+10];
00235        const  char *f;
00236 
00237               if (strncmp(arg->argname, "MOVE-", 5))    continue;
00238               l=atol(arg->argname+5);
00239               sprintf(movedel, "MOVEFILE-%lu", l);
00240               f=cgi(movedel);
00241               CHECKFILENAME(f);
00242               if ((*func)(folder, f, l))
00243                      return (-1);
00244        }
00245        return (0);
00246 }
00247 
00248 static int groupdel(const char *folder, const char *file, size_t pos)
00249 {
00250        maildir_msgdeletefile(folder, file, pos);
00251        return (0);
00252 }
00253 
00254 static int groupmove(const char *folder, const char *file, size_t pos)
00255 {
00256        return (maildir_msgmovefile(folder, file, cgi("moveto"), pos));
00257 }
00258 
00259 static const char *do_folder_delmsgs(const char *dir, size_t pos)
00260 {
00261        int    rc=0;
00262        char   buf[2];
00263        char   *cur;
00264 
00265        strcpy(buf, ACL_DELETEMSGS);
00266        acl_computeRightsOnFolder(dir, buf);
00267 
00268 #if 0
00269        {
00270               FILE *fp=fopen("/tmp/pid", "w");
00271 
00272               if (fp)
00273               {
00274                      fprintf(fp, "%d", (int)getpid());
00275                      fclose(fp);
00276                      sleep(10);
00277               }
00278        }
00279 #endif
00280 
00281        if (buf[0] == 0)
00282               return "nodel";
00283 
00284        if (*cgi("cmddel"))
00285        {
00286               rc=group_movedel( dir, &groupdel );
00287               maildir_savefoldermsgs(dir);
00288        } 
00289        else if (*cgi("cmdpurgeall")) 
00290        {
00291            char *deldir;
00292            struct maildir_info minfo;
00293 
00294            if (maildir_info_imap_find(&minfo, dir, login_returnaddr())<0) 
00295                   return "othererror";
00296 
00297            if ((deldir=maildir_name2dir(minfo.homedir, minfo.maildir)) == NULL)
00298            {
00299               maildir_info_destroy(&minfo);
00300               return "othererror";
00301            }
00302            
00303            cur = malloc(strlen(deldir)+5);
00304            strcpy(cur, deldir);
00305            strcat(cur, "/cur");
00306 
00307            rc=maildir_del_content(cur);
00308            maildir_quota_recalculate(".");
00309 
00310            maildir_info_destroy(&minfo);
00311            free(deldir);
00312            free(cur);
00313            
00314        }
00315        else if (*cgi("cmdmove"))
00316        {
00317               const char *p=cgi("moveto");
00318 
00319               CHECKFILENAME(p);
00320               strcpy(buf, ACL_INSERT);
00321               acl_computeRightsOnFolder(p, buf);
00322               if (buf[0] == 0)
00323                      return "noinsert";
00324 
00325               rc=group_movedel( dir, &groupmove );
00326               maildir_savefoldermsgs(dir);
00327        }
00328 
00329        maildir_cleanup();
00330 
00331        return rc ? "quota":"";
00332 }
00333 
00334 void folder_delmsgs(const char *dir, size_t pos)
00335 {
00336        const char *status=do_folder_delmsgs(dir, pos);
00337        
00338        if (*cgi("search"))
00339               http_redirect_argsss("&error=%s&form=folder&pos=%s&search=1&"
00340                                  SEARCHRESFILENAME "=%s", status,
00341                                  cgi("pos"), cgi(SEARCHRESFILENAME));
00342        else
00343               http_redirect_argss("&error=%s&form=folder&pos=%s", status,
00344                                 cgi("pos"));
00345 }
00346 
00347 static void savepath(const char *path, const char *maildir)
00348 {
00349        char buf[BUFSIZ];
00350        FILE *ofp;
00351        FILE *fp;
00352        struct maildir_tmpcreate_info createInfo;
00353 
00354        maildir_tmpcreate_init(&createInfo);
00355 
00356        createInfo.maildir=".";
00357        createInfo.uniq="sharedpath";
00358        createInfo.doordie=1;
00359 
00360        ofp=maildir_tmpcreate_fp(&createInfo);
00361 
00362        fp=fopen(SHAREDPATHCACHE, "r");
00363 
00364        if (fp)
00365        {
00366               int cnt=0;
00367 
00368               while (cnt < 1)
00369               {
00370                      char *p;
00371 
00372                      if (fgets(buf, sizeof(buf), fp) == NULL)
00373                             break;
00374 
00375                      if ((p=strchr(buf, '\n')) != NULL) *p=0;
00376 
00377                      if (strcmp(buf, maildir) == 0)
00378                      {
00379                             if (fgets(buf, sizeof(buf), fp) == NULL)
00380                                    break;
00381                             continue;
00382                      }
00383 
00384                      fprintf(ofp, "%s\n", buf);
00385 
00386                      if (fgets(buf, sizeof(buf), fp) == NULL)
00387                             strcpy(buf, "");
00388                      if ((p=strchr(buf, '\n')) != NULL) *p=0;
00389                      fprintf(ofp, "%s\n", buf);
00390 
00391                      ++cnt;
00392               }
00393               fclose(fp);
00394        }
00395 
00396        fprintf(ofp, "%s\n%s\n", maildir, path);
00397        fclose(ofp);
00398        rename(createInfo.tmpname, SHAREDPATHCACHE);
00399        maildir_tmpcreate_free(&createInfo);
00400 }
00401 
00402 void folder_search(const char *dir, size_t pos)
00403 {
00404        maildir_reload(dir);
00405        maildir_search(dir,
00406                      pos,
00407                      cgi("searchtxt"),
00408                      sqwebmail_content_charset,
00409                      pref_flagpagesize);
00410 
00411        http_redirect_argss("&search=1&form=folder&pos=%s&"
00412                          SEARCHRESFILENAME "=%s", cgi("pos"),
00413                          cgi(SEARCHRESFILENAME));
00414 }
00415 
00416 static void folder_msg_link(const char *, int, size_t, char);
00417 static void folder_msg_unlink(const char *, int, size_t, char);
00418 
00419 static char *truncate_at(const char *, const char *, size_t);
00420 
00421 static void show_msg(const char *dir,
00422                    MSGINFO *msg,
00423                    MATCHEDSTR *matches,
00424                    int row,
00425                    const char *charset);
00426 
00427 void folder_contents(const char *dir, size_t pos)
00428 {
00429 MSGINFO       **contents;
00430 MATCHEDSTR **matches;
00431 int    i, found;
00432 int    morebefore, moreafter;
00433 const char    *nomsg, *selectalllab;
00434  const char   *unselectalllab;
00435 const char    *qerrmsg;
00436 long highend;
00437 unsigned long last_message_searched=0;
00438 unsigned long *last_message_searched_ptr=NULL;
00439 
00440        qerrmsg=getarg("PERMERR");
00441 
00442        if (strcmp(cgi("error"), "quota") == 0)
00443               printf("%s", qerrmsg);
00444 
00445        if (strcmp(cgi("error"), "nodel") == 0)
00446               printf("%s", getarg("NODELPERM"));
00447 
00448        if (strcmp(cgi("error"), "noinsert") == 0)
00449               printf("%s", getarg("NOINSERTPERM"));
00450 
00451        if (strcmp(cgi("error"), "othererror") == 0)
00452               printf("%s", getarg("OTHERERROR"));
00453 
00454        if (strchr(sqwebmail_folder_rights, ACL_READ[0]) == NULL)
00455        {
00456               printf("%s", getarg("ACL"));
00457               return;
00458        }
00459 
00460        maildir_reload(dir);
00461 
00462        if (*cgi("search"))
00463        {
00464 #if 0
00465        {
00466               FILE *fp=fopen("/tmp/pid", "w");
00467 
00468               if (fp)
00469               {
00470                      fprintf(fp, "%d", (int)getpid());
00471                      fclose(fp);
00472                      sleep(10);
00473               }
00474        }
00475 #endif
00476 
00477               morebefore=0;
00478               moreafter=0;
00479               maildir_loadsearch(pref_flagpagesize, &contents, &matches,
00480                                &last_message_searched);
00481 
00482               for (i=0; i<pref_flagpagesize; i++)
00483               {
00484                      if (contents[i] == 0)       continue;
00485 
00486                      last_message_searched_ptr= &last_message_searched;
00487                      break;
00488               }
00489        }
00490        else
00491        {
00492               contents=maildir_read(dir, pref_flagpagesize, &pos,
00493                                   &morebefore, &moreafter);
00494               matches=NULL;
00495        }
00496 
00497        time(&current_time);
00498        nomsg=getarg("NOMESSAGES");
00499        selectalllab=getarg("SELECTALL");
00500        unselectalllab=getarg("UNSELECTALL");
00501 
00502        if (maildir_countof(dir) <= pos + pref_flagpagesize - 1)
00503               highend = (long)(maildir_countof(dir) - 1);
00504        else
00505               highend = (long)(pos + pref_flagpagesize - 1);
00506        if (highend < 0) highend = 0;
00507 
00508        if (!qerrmsg) qerrmsg="";
00509 
00510        folder_navigate(dir, pos, highend, morebefore, moreafter,
00511                      last_message_searched_ptr);
00512 
00513        printf("<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"4\"><tr class=\"folder-index-header\"><th align=\"center\">%s</th><th>&nbsp;</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr>\n",
00514               getarg("NUM"),
00515               getarg("DATE"),
00516               (strncmp(dir, INBOX "." SENT, sizeof(INBOX)+sizeof(SENT)-1) &&
00517                strncmp(dir, INBOX "." DRAFTS, sizeof(INBOX)+sizeof(DRAFTS)-1))
00518                      ? getarg("FROM") : getarg("TO"),
00519               getarg("SUBJECT"),
00520               getarg("SIZE"));
00521 
00522        found=0;
00523        for (i=0; i<pref_flagpagesize; i++)
00524        {
00525               if (contents[i] == 0)       continue;
00526               found=1;
00527 
00528               show_msg(dir, contents[i], matches ? matches[i]:NULL, i,
00529                       sqwebmail_content_charset);
00530        }
00531 
00532        if (found)
00533        {
00534               puts("<tr class=\"folder-index-bg-1\"><td colspan=\"6\"><hr /></td></tr>");
00535               puts("<tr class=\"folder-index-bg-2\"><td>&nbsp;</td>");
00536               puts("<td colspan=\"5\">");
00537 
00538               puts("<script type=\"text/javascript\">");
00539               puts("/* <![CDATA[ */");
00540               puts("function setAll(input, chk) {");
00541               printf("for (i = %ld; i <= %ld; i++) {\n",
00542                      (long)pos, highend);
00543               puts("if (document.getElementById) e = document.getElementById('MOVE-' + i);");
00544               puts("else if (document.all) e = document['MOVE-' + i];");
00545               puts("if (e != null) { e.checked = chk; e.onchange(); }} }");
00546               puts("/* ]]> */");
00547               puts("</script>\n");
00548 
00549               puts("<script type=\"text/javascript\">");
00550               puts("/* <![CDATA[ */");
00551               printf("document.write('<button type=\"button\" onclick=\"setAll(this, true); return false;\">%s<\\/button>\\n&nbsp;');\n",
00552                      selectalllab);
00553               printf("document.write('<button type=\"button\" onclick=\"setAll(this, false); return false;\">%s<\\/button>\\n');\n",
00554                      unselectalllab);
00555               puts("/* ]]> */");
00556               puts("</script>\n");
00557 
00558               printf("<noscript><label><input type=\"checkbox\" name=\"SELECTALL\" />&nbsp;%s</label></noscript>\n",
00559                      selectalllab);
00560               puts("</td></tr>");
00561 
00562               printf("</table>\n");
00563               folder_navigate(dir, pos, highend, morebefore, moreafter,
00564                             last_message_searched_ptr);
00565        }
00566        if (!found && nomsg)
00567        {
00568               puts("<tr class=\"folder-index-bg-1\"><td colspan=\"6\" align=\"left\"><p>");
00569               puts(nomsg);
00570               puts("<br /></p></td></tr>");
00571               printf("</table>\n");
00572        }
00573 
00574        maildir_free(contents, pref_flagpagesize);
00575        if (matches)
00576               matches_free(matches, pref_flagpagesize);
00577 }
00578 
00579 
00580 static int folder_searchlink()
00581 {
00582        if (*cgi("search") == 0)
00583               return 0;
00584 
00585        printf("&amp;search=1&amp;" SEARCHRESFILENAME "=");
00586        output_urlencoded(cgi(SEARCHRESFILENAME));
00587        return 1;
00588 }
00589 
00590 static void show_msg_match_str(const char *prefix,
00591                             const char *utf8match,
00592                             const char *suffix,
00593                             const char *classname);
00594 
00595 static void show_msg(const char *dir,
00596                    MSGINFO *msg,
00597                    MATCHEDSTR *matches,
00598                    int row,
00599                    const char *charset)
00600 {
00601        const char *date, *from, *subj, *size;
00602        char   *froms, *subjs;
00603        const char *p, *q;
00604        size_t l;
00605        char type[8];
00606        char *folder_index_entry_start, *folder_index_entry_end;
00607 
00608        size_t msgnum=msg->msgnum;
00609 
00610        date=MSGINFO_DATE(msg);
00611        from=MSGINFO_FROM(msg);
00612        subj=MSGINFO_SUBJECT(msg);
00613        size=MSGINFO_SIZE(msg);
00614 
00615        type[0]=maildirfile_type(MSGINFO_FILENAME(msg));
00616        type[1]='\0';
00617        if (type[0] == '\0') strcpy(type, "&nbsp;");
00618 
00619        folder_index_entry_start="<span class=\"read-message\">";
00620        folder_index_entry_end="</span>";
00621 
00622        if (type[0] == MSGTYPE_NEW)
00623        {
00624               folder_index_entry_start="<strong class=\"unread-message\">";
00625               folder_index_entry_end="</strong>";
00626        }
00627 
00628        p=MSGINFO_FILENAME(msg);
00629 
00630        if ((q=strrchr(p, '/')) != 0)
00631               p=q+1;
00632 
00633        printf("<tr class=\"folder-index-bg-%d\" id=\"row%d\"><td align=\"right\" class=\"message-number\">%s%ld.%s</td><td class=\"message-status\"><input type=\"checkbox\" name=\"MOVE-%ld\" id=\"MOVE-%ld",
00634               (row & 1)+1,
00635               row,
00636               folder_index_entry_start,
00637               (long)(msgnum+1),
00638               folder_index_entry_end,
00639               (long) (msgnum),
00640               (long) (msgnum));
00641        printf("\" onchange=\"setsel('MOVE-%ld', 'row%d', 'folder-index-bg-%d');\"%s /><input type=\"hidden\" name=\"MOVEFILE-%ld\" value=\"",
00642               (long)(msgnum), row, (row & 1)+1,
00643               (type[0] == MSGTYPE_DELETED ? " disabled=\"disabled\"":""),
00644               (long)(msgnum));
00645        output_attrencoded(p);
00646        printf("\" />&nbsp;%s%s%s</td><td class=\"message-date\">%s",
00647               folder_index_entry_start,
00648               type,
00649               folder_index_entry_end,
00650 
00651               folder_index_entry_start
00652               );
00653        if (!*date)   date=" ";
00654        folder_msg_link(dir, row, msgnum, type[0]);
00655        print_safe(date);
00656        folder_msg_unlink(dir, row, msgnum, type[0]);
00657        printf("%s</td><td class=\"message-from\">%s", folder_index_entry_end,
00658               folder_index_entry_start);
00659        if (!*from)   from=" ";
00660        folder_msg_link(dir, row, msgnum, type[0]);
00661 
00662 
00663        froms=truncate_at(from, charset, 30);
00664 
00665        if (froms == 0)      enomem();
00666 
00667        print_safe(froms);
00668        free(froms);
00669        folder_msg_unlink(dir, row, msgnum, type[0]);
00670        printf("%s<br /></td><td class=\"message-subject\">%s", folder_index_entry_end,
00671               folder_index_entry_start);
00672 
00673        folder_msg_link(dir, row, msgnum, type[0]);
00674 
00675 #if 0
00676        {
00677               static int foo=0; if (foo++ == 0)
00678        {
00679               FILE *fp=fopen("/tmp/pid", "w");
00680 
00681               if (fp)
00682               {
00683                      fprintf(fp, "%d", (int)getpid());
00684                      fclose(fp);
00685                      sleep(10);
00686               }
00687        }
00688        }
00689 #endif
00690 
00691        subjs=truncate_at(subj, charset, 40);
00692 
00693        if (subjs == 0)      enomem();
00694 
00695        print_safe(subjs);
00696        l=strlen(subjs);
00697        while (l++ < 8)
00698               printf("&nbsp;");
00699        free(subjs);
00700 
00701        folder_msg_unlink(dir, row, msgnum, type[0]);
00702        printf("%s</td><td align=\"right\" class=\"message-size\">%s%s&nbsp;%s<br /></td></tr>\n", folder_index_entry_end, folder_index_entry_start, size, folder_index_entry_end);
00703 
00704        while (matches && matches->match)
00705        {
00706               printf("<tr class=\"folder-index-bg-%d\"><td align=\"right\" class=\"message-number\" colspan=\"3\">&nbsp;</td><td class=\"message-searchmatch\" colspan=\"3\">", (row & 1)+1);
00707               show_msg_match_str("...",
00708                                matches->prefix, "", "searchmatch-affix");
00709               show_msg_match_str("", matches->match, "", "searchmatch");
00710               show_msg_match_str("", matches->suffix,
00711                                "...", "searchmatch-affix");
00712               printf("</td></tr>\n");
00713               ++matches;
00714        }
00715 }
00716 
00717 static void show_msg_match_str(const char *prefix,
00718                             const char *utf8match,
00719                             const char *suffix,
00720                             const char *classname)
00721 {
00722        char *p;
00723 
00724        p=libmail_u_convert_fromutf8(utf8match, sqwebmail_content_charset,
00725                                  NULL);
00726 
00727        if (p)
00728        {
00729               printf("<span class=\"%s\">%s", classname, prefix);
00730               output_attrencoded(p);
00731               free(p);
00732               printf("%s</span>", suffix);
00733        }
00734 }
00735 
00736 static void do_folder_navigate(const char *dir, size_t pos, long highend,
00737                             int morebefore, int moreafter)
00738 {
00739        const char    *firstlab, *lastlab;
00740        const char    *beforelab, *afterlab;
00741        const char    *showncountlab, *jumplab, *golab;
00742 
00743        time(&current_time);
00744        showncountlab=getarg("SHOWNCOUNT");
00745        jumplab=getarg("JUMPTO");
00746        golab=getarg("GO");
00747        firstlab=getarg("FIRSTPAGE");
00748        beforelab=getarg("PREVPAGE");
00749        afterlab=getarg("NEXTPAGE");
00750        lastlab=getarg("LASTPAGE");
00751 
00752        printf("<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" class=\"folder-nextprev-buttons\"><tr><td>");
00753 
00754        if (morebefore)
00755        {
00756               printf("<a href=\"");
00757               output_scriptptrget();
00758               printf("&amp;form=folder&amp;pos=0\" style=\"text-decoration: none\">");
00759        }
00760        printf("%s", firstlab);
00761        if (morebefore)
00762               printf("</a>");
00763 
00764        puts("&nbsp;");
00765 
00766        if (morebefore)
00767        {
00768        size_t beforepos;
00769 
00770               if (pos < pref_flagpagesize)       beforepos=0;
00771               else   beforepos=pos-pref_flagpagesize;
00772 
00773               printf("<a href=\"");
00774               output_scriptptrget();
00775               printf("&amp;form=folder&amp;pos=%ld\" style=\"text-decoration: none\">",
00776                      (long)beforepos);
00777        }
00778        printf("%s", beforelab);
00779        if (morebefore)
00780               printf("</a>");
00781 
00782        printf("</td></tr></table>\n");
00783 
00784        if (maildir_countof(dir) > 0) {
00785               puts("</td><td align=\"center\">\n");
00786               puts("<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" class=\"folder-message-count\"><tr><td>\n");
00787               printf(showncountlab, (long)(pos+1), (long)(highend+1), (long)maildir_countof(dir));
00788               puts("</td></tr></table>");
00789 
00790               puts("<script type=\"text/javascript\">");
00791               puts("/* <![CDATA[ */");
00792               puts("document.write('<\\/td><td align=\"center\">' +");
00793 
00794               puts("'<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" class=\"folder-jumpto-field\"><tr><td>' +");
00795               printf("'%s <input type=\"text\" name=\"jumpto\" size=\"3\" value=\"%ld\" onchange=\"this.form.pos.value = this.value - 1;\" />' +\n",
00796                      jumplab, (long)(pos+1));
00797               printf("'<button type=\"button\" onclick=\"this.form.submit();\">%s<\\/button>' +\n",
00798                      golab);
00799               puts("'<\\/td><\\/tr><\\/table>');");
00800               puts("/* ]]> */");
00801               puts("</script>");
00802        }
00803 
00804        printf("</td><td align=\"right\">\n");
00805 
00806        printf("<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" class=\"folder-nextprev-buttons\"><tr><td>");
00807        if (moreafter)
00808        {
00809               printf("<a href=\"");
00810               output_scriptptrget();
00811               printf("&amp;form=folder&amp;pos=%ld\" style=\"text-decoration: none\">",
00812                      (long)(pos+pref_flagpagesize));
00813        }
00814        printf("%s", afterlab);
00815        if (moreafter)
00816               printf("</a>");
00817 
00818        puts("&nbsp;");
00819 
00820        if (moreafter)
00821        {
00822               printf("<a href=\"");
00823               output_scriptptrget();
00824               printf("&amp;form=folder&amp;pos=%ld\" style=\"text-decoration: none\">",
00825                      (long)(maildir_countof(dir)-pref_flagpagesize));
00826        }
00827        printf("%s", lastlab);
00828        if (moreafter)
00829               printf("</a>");
00830 
00831        printf("</td></tr></table>\n");
00832 }
00833 
00834 void folder_navigate(const char *dir, size_t pos, long highend,
00835                    int morebefore, int moreafter,
00836                    unsigned long *last_message_searched_ptr)
00837 {
00838        printf("<table width=\"100%%\" class=\"folder-nextprev-background\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr>");
00839 
00840        if (*cgi("search"))
00841        {
00842               printf("<td class=\"folder-return-link\">");
00843               printf("<a href=\"");
00844               output_scriptptrget();
00845               printf("&amp;form=folder&amp;pos=%ld\">%s</a>",
00846                      (long)pos, getarg("RETURNTOFOLDER"));
00847               printf("</td>");
00848 
00849               printf("<td class=\"folder-last-message-searched\">");
00850               if (last_message_searched_ptr)
00851               {
00852                      printf(getarg("LASTMESSAGESEARCHED"),
00853                             *last_message_searched_ptr+1);
00854               }
00855               else
00856               {
00857                      printf("&nbsp;");
00858               }
00859               printf("</td>");
00860        }
00861        else
00862        {
00863               printf("<td align=\"left\">");
00864               do_folder_navigate(dir, pos, highend, morebefore, moreafter);
00865               printf("</td>");
00866        }
00867 
00868        printf("</tr></table>");
00869 }
00870 
00871 static void folder_msg_link(const char *dir, int row, size_t pos, char t)
00872 {
00873 #if 0
00874        if (t == MSGTYPE_DELETED)
00875        {
00876               printf("<a href=\"");
00877               output_scriptptrget();
00878               printf("&amp;form=folder&amp;pos=%s\">", cgi("pos"));
00879               return;
00880        }
00881 #endif
00882 
00883        printf("<a href=\"");
00884        if (strcmp(dir, INBOX "." DRAFTS))
00885        {
00886               output_scriptptrget();
00887               if (folder_searchlink())
00888                      printf("&amp;searchrow=%d", row);
00889 
00890               printf("&amp;form=readmsg&amp;pos=%ld\">", (long)pos);
00891        }
00892        else
00893        {
00894        size_t mpos=pos;
00895        char   *filename=maildir_posfind(dir, &mpos);
00896        char   *basename=filename ? maildir_basename(filename):NULL;
00897 
00898               output_scriptptrget();
00899               printf("&amp;form=open-draft&amp;draft=");
00900               output_urlencoded(basename);
00901               printf("\">");
00902               if (basename) free(basename);
00903               if (filename) free(filename);
00904        }
00905 }
00906 
00907 static void folder_msg_unlink(const char *dir, int row, size_t pos, char t)
00908 {
00909        printf("</a>");
00910 }
00911 
00912 size_t msg_pos, msg_count;
00913 static char   *msg_posfile;
00914 static int    msg_hasprev, msg_hasnext;
00915 static size_t msg_searchpos;
00916 static long   msg_prevpos, msg_prev_searchpos;
00917 static long   msg_nextpos, msg_next_searchpos;
00918 
00919 static const char    *msg_nextlab=0, *msg_prevlab=0, *msg_deletelab=0,
00920               *msg_purgelab=0, *msg_folderlab=0;
00921 static char   msg_type;
00922 
00923 static const char    *msg_replylab=0;
00924 static const char    *msg_replyalllab=0;
00925 static const char    *msg_replylistlab=0;
00926 static const char    *msg_forwardlab=0;
00927 static const char    *msg_forwardattlab=0;
00928 static const char    *msg_fullheaderlab=0;
00929 static const char    *msg_movetolab=0;
00930 static const char    *msg_print=0;
00931 
00932 static const char    *folder_inbox=0;
00933 static const char    *folder_drafts=0;
00934 static const char    *folder_trash=0;
00935 static const char    *folder_sent=0;
00936 static const char    *msg_golab=0;
00937 
00938 static const char *msg_msglab;
00939 static const char *msg_add=0;
00940 
00941 static int    initnextprevcnt;
00942 
00943 void folder_initnextprev(const char *dir, size_t pos)
00944 {
00945        MSGINFO       **info;
00946        const  char *p;
00947        const  char *msg_numlab, *msg_numnewlab;
00948        static char *filename=0;
00949        int fd;
00950 
00951        MSGINFO *recp;
00952        MSGINFO **search_contents=NULL;
00953        MATCHEDSTR **search_matches=NULL;
00954        unsigned long last_message_searched=0;
00955 
00956        cgi_put(MIMEGPGFILENAME, "");
00957 
00958        if (filename)
00959               free(filename);
00960        filename=0;
00961 
00962 
00963        if (*cgi("mimegpg") && (filename=maildir_posfind(dir, &pos)) != 0)
00964        {
00965               char *tptr;
00966               int nfd;
00967 
00968               fd=maildir_semisafeopen(filename, O_RDONLY, 0);
00969 
00970               if (fd >= 0)
00971               {
00972                      struct maildir_tmpcreate_info createInfo;
00973 
00974                      maildir_purgemimegpg();
00975 
00976                      maildir_tmpcreate_init(&createInfo);
00977 
00978                      createInfo.uniq=":mimegpg:";
00979                      createInfo.doordie=1;
00980 
00981                      if ((nfd=maildir_tmpcreate_fd(&createInfo)) < 0)
00982                      {
00983                             free(filename);
00984                             error("Can't create new file.");
00985                      }
00986 
00987                      tptr=createInfo.tmpname;
00988                      createInfo.tmpname=NULL;
00989                      maildir_tmpcreate_free(&createInfo);
00990 
00991                      chmod(tptr, 0600);
00992 
00993                      /*
00994                      ** Decrypt/check message into a temporary file
00995                      ** that's immediately marked as deleted, so that it
00996                      ** gets purged at the next sweep.
00997                      */
00998 
00999                      if (gpgdecode(fd, nfd) < 0)
01000                      {
01001                             close(nfd);
01002                             unlink(tptr);
01003                             free(tptr);
01004                      }
01005                      else
01006                      {
01007                             close(fd);
01008                             free(filename);
01009                             filename=tptr;
01010                             fd=nfd;
01011 
01012                             cgi_put(MIMEGPGFILENAME,
01013                                    strrchr(filename, '/')+1);
01014                      }
01015                      close(fd);
01016               }
01017        }
01018 
01019        initnextprevcnt=0;
01020        msg_nextlab=getarg("NEXTLAB");
01021        msg_prevlab=getarg("PREVLAB");
01022        msg_deletelab=getarg("DELETELAB");
01023        msg_purgelab=getarg("PURGELAB");
01024 
01025        msg_folderlab=getarg("FOLDERLAB");
01026 
01027        msg_replylab=getarg("REPLY");
01028        msg_replyalllab=getarg("REPLYALL");
01029        msg_replylistlab=getarg("REPLYLIST");
01030 
01031        msg_forwardlab=getarg("FORWARD");
01032        msg_forwardattlab=getarg("FORWARDATT");
01033 
01034        msg_numlab=getarg("MSGNUM");
01035        msg_numnewlab=getarg("MSGNEWNUM");
01036 
01037        msg_fullheaderlab=getarg("FULLHDRS");
01038 
01039        msg_movetolab=getarg("MOVETO");
01040        msg_print=getarg("PRINT");
01041 
01042        folder_inbox=getarg("INBOX");
01043        folder_drafts=getarg("DRAFTS");
01044        folder_trash=getarg("TRASH");
01045        folder_sent=getarg("SENT");
01046 
01047        p=getarg("CREATEFAIL");
01048        if (strcmp(cgi("error"),"quota") == 0)
01049               printf("%s", p);
01050 
01051        msg_golab=getarg("GOLAB");
01052        msg_add=getarg("QUICKADD");
01053 
01054        msg_searchpos=atol(cgi("searchrow"));
01055 
01056        info=maildir_read(dir, 1, &pos, &msg_hasprev, &msg_hasnext);
01057 
01058        recp=info[0];
01059        msg_pos=pos;
01060        msg_prevpos=msg_pos-1;
01061        msg_nextpos=msg_pos+1;
01062        msg_prev_searchpos=msg_prevpos;
01063        msg_next_searchpos=msg_nextpos;
01064 
01065        if (*cgi("search"))
01066               maildir_loadsearch(pref_flagpagesize,
01067                                &search_contents,
01068                                &search_matches,
01069                                &last_message_searched);
01070 
01071 
01072        if (search_contents)
01073        {
01074               if (msg_searchpos < pref_flagpagesize &&
01075                   search_contents[msg_searchpos])
01076               {
01077                      recp=search_contents[msg_searchpos];
01078 
01079                      msg_pos=recp->msgnum;
01080                      if ((msg_hasprev=msg_searchpos > 0 &&
01081                           search_contents[msg_searchpos-1]) != 0)
01082                      {
01083                             msg_prevpos=search_contents
01084                                    [msg_searchpos-1]->msgnum;
01085                             msg_prev_searchpos=msg_searchpos-1;
01086                      }
01087 
01088                      if ((msg_hasnext=msg_searchpos + 1 <
01089                           pref_flagpagesize &&
01090                           search_contents[msg_searchpos+1]) != 0)
01091                      {
01092                             msg_nextpos=search_contents
01093                                    [msg_searchpos+1]->msgnum;
01094                             msg_next_searchpos=msg_searchpos+1;
01095                      }
01096 
01097               }
01098        }
01099 
01100        p=strrchr(MSGINFO_FILENAME(recp), '/');
01101        if (p) p++;
01102        else   p=MSGINFO_FILENAME(recp);
01103        msg_posfile=strdup(p);
01104        if (!msg_posfile)    enomem();
01105 
01106        if ((msg_type=maildirfile_type(MSGINFO_FILENAME(recp)))
01107               == MSGTYPE_NEW) msg_numlab=msg_numnewlab;
01108 
01109        msg_msglab=msg_numlab;
01110        msg_count=maildir_countof(dir);
01111        maildir_free(info, 1);
01112        if (search_contents)
01113               maildir_free(search_contents, pref_flagpagesize);
01114        if (search_matches)
01115               matches_free(search_matches, pref_flagpagesize);
01116 }
01117 
01118 char *get_msgfilename(const char *folder, size_t *pos)
01119 {
01120        char *filename;
01121 
01122        if (*cgi(MIMEGPGFILENAME))
01123        {
01124               const char *p=cgi(MIMEGPGFILENAME);
01125 
01126               CHECKFILENAME(p);
01127 
01128               filename=malloc(sizeof("tmp/")+strlen(p));
01129               if (!filename)
01130                      enomem();
01131               strcat(strcpy(filename, "tmp/"), p);
01132        }
01133        else
01134               filename=maildir_posfind(folder, pos);
01135 
01136        if (!filename)       error("Message not found.");
01137 
01138        return (filename);
01139 }
01140 
01141 void output_mimegpgfilename()
01142 {
01143        if (*cgi(MIMEGPGFILENAME))
01144        {
01145               printf("&amp;" MIMEGPGFILENAME "=");
01146               output_urlencoded(cgi(MIMEGPGFILENAME));
01147        }
01148 }
01149 
01150 void folder_nextprev()
01151 {
01152        printf("<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" class=\"message-menu-background\"><tr valign=\"middle\">");
01153 
01154        printf("<td align=\"left\"><table border=\"0\" cellspacing=\"4\" cellpadding=\"4\"><tr valign=\"top\">");
01155 
01156        /* PREV */
01157 
01158        printf("<td class=\"message-menu-button\">");
01159 
01160        if (msg_hasprev)
01161        {
01162               printf("<a href=\"");
01163               output_scriptptrget();
01164 
01165               if (folder_searchlink())
01166                      printf("&searchrow=%ld", msg_prev_searchpos);
01167 
01168               printf("&amp;form=readmsg&amp;pos=%ld\">",
01169                      msg_prevpos);
01170        }
01171 
01172        printf("%s", msg_prevlab ? msg_prevlab:"");
01173 
01174        if (msg_hasprev)
01175        {
01176               printf("</a>");
01177        }
01178        printf("</td>");
01179 
01180        /* NEXT */
01181 
01182        printf("<td class=\"message-menu-button\">");
01183 
01184        if (msg_hasnext)
01185        {
01186               printf("<a href=\"");
01187               output_scriptptrget();
01188 
01189               if (folder_searchlink())
01190                      printf("&searchrow=%ld", msg_next_searchpos);
01191 
01192               printf("&amp;form=readmsg&amp;pos=%ld\">",
01193                      msg_nextpos);
01194        }
01195 
01196        printf("%s", msg_nextlab ? msg_nextlab:"");
01197 
01198        if (msg_hasnext)
01199        {
01200               printf("</a>");
01201        }
01202        printf("</td>");
01203 
01204        /* DEL */
01205 
01206        printf("<td class=\"message-menu-button\">");
01207        if (msg_type != MSGTYPE_DELETED)
01208        {
01209               printf("<a href=\"");
01210               output_scriptptrget();
01211               tokennewget();
01212               folder_searchlink();
01213               printf("&amp;posfile=");
01214               output_urlencoded(msg_posfile);
01215               printf("&amp;form=delmsg&amp;pos=%ld\">",
01216                      (long)msg_pos);
01217        }
01218        printf("%s", strcmp(sqwebmail_folder, INBOX "." TRASH) == 0
01219               ? msg_purgelab : msg_deletelab);
01220 
01221        if (msg_type != MSGTYPE_DELETED)
01222               printf("</a>");
01223 
01224        printf("</td>\n");
01225 
01226        /* FOLDER */
01227 
01228        printf("<td class=\"message-menu-button\"><a href=\"");
01229        output_scriptptrget();
01230        folder_searchlink();
01231        printf("&amp;pos=%ld&amp;form=folder\">%s</a></td>\n",
01232               (long)( (msg_pos/pref_flagpagesize)*pref_flagpagesize ),
01233               msg_folderlab);
01234 
01235        /* REPLY */
01236 
01237        printf("<td class=\"message-menu-button\"><a href=\"");
01238        output_scriptptrget();
01239        output_mimegpgfilename();
01240        printf("&amp;pos=%ld&amp;reply=1&amp;form=newmsg\">%s</a></td>\n",
01241               (long)msg_pos,
01242               msg_replylab);
01243 
01244        /* REPLY ALL */
01245 
01246        printf("<td class=\"message-menu-button\"><a href=\"");
01247        output_scriptptrget();
01248        output_mimegpgfilename();
01249        printf("&amp;pos=%ld&amp;replyall=1&amp;form=newmsg\">%s</a></td>\n",
01250               (long)msg_pos,
01251               msg_replyalllab);
01252 
01253        /* REPLY LIST */
01254 
01255        printf("<td class=\"message-menu-button\"><a href=\"");
01256        output_scriptptrget();
01257        output_mimegpgfilename();
01258        printf("&amp;pos=%ld&amp;replylist=1&amp;form=newmsg\">%s</a></td>\n",
01259               (long)msg_pos,
01260               msg_replylistlab);
01261 
01262        if (auth_getoptionenvint("wbnoimages"))
01263               printf("<td width=\"100%%\"></td></tr></table><table border=\"0\" cellspacing=\"4\" cellpadding=\"4\"><tr>");
01264 
01265        /* FORWARD */
01266 
01267        printf("<td class=\"message-menu-button\"><a href=\"");
01268        output_scriptptrget();
01269        output_mimegpgfilename();
01270        printf("&amp;pos=%ld&amp;forward=1&amp;form=newmsg\">%s</a></td>\n",
01271               (long)msg_pos,
01272               msg_forwardlab);
01273 
01274        /* FORWARD AS ATTACHMENT*/
01275 
01276        printf("<td class=\"message-menu-button\"><a href=\"");
01277        output_scriptptrget();
01278        output_mimegpgfilename();
01279        printf("&amp;pos=%ld&amp;forwardatt=1&amp;form=newmsg\">%s</a></td>\n",
01280               (long)msg_pos,
01281               msg_forwardattlab);
01282 
01283        /* FULL HEADERS */
01284 
01285        if (!pref_flagfullheaders && !*cgi("fullheaders"))
01286        {
01287               printf("<td class=\"message-menu-button\"><a href=\"");
01288               output_scriptptrget();
01289               folder_searchlink();
01290               output_mimegpgfilename();
01291               printf("&amp;pos=%ld&amp;form=readmsg&amp;fullheaders=1\">%s</a></td>\n",
01292                      (long)msg_pos, msg_fullheaderlab);
01293        }
01294 
01295        /* PRINT MESSAGE */
01296 
01297        printf("<td class=\"message-menu-button\"><a href=\"");
01298        output_scriptptrget();
01299        output_mimegpgfilename();
01300 
01301        printf("&amp;pos=%ld&amp;form=print&amp;setcookie=1%s\" target=\"_blank\">%s</a></td>\n",
01302               (long)msg_pos,
01303               ((pref_flagfullheaders || *cgi("fullheaders")) ? "&amp;fullheaders=1" : ""),
01304               msg_print);
01305 
01306        /* SAVE MESSAGE */
01307 
01308        printf("<td class=\"message-menu-button\"><a href=\"");
01309        output_scriptptrget();
01310        output_mimegpgfilename();
01311 
01312        printf("&amp;pos=%ld&amp;form=fetch&amp;download=1\">%s</a></td>", (long)msg_pos,
01313               getarg("SAVEMESSAGE"));
01314 
01315     printf("<td width=\"100%%\"></td></tr></table></td><td align=\"right\" valign=\"middle\">");
01316 
01317        printf("<table border=\"0\" cellspacing=\"4\"><tr><td class=\"message-x-of-y\">&nbsp;");
01318        printf(msg_msglab, (int)msg_pos+1, (int)msg_count);
01319        printf("&nbsp;</td></tr></table>");
01320     printf("</td></tr></table>\n");
01321 }
01322 
01323 void list_folder(const char *p)
01324 {
01325        char *s=folder_fromutf7(p);
01326        print_safe(s);
01327        free(s);
01328 }
01329 
01330 void list_folder_xlate(const char *p,
01331                      const char *path,
01332                      const char *n_inbox,
01333                      const char *n_drafts,
01334                      const char *n_sent,
01335                      const char *n_trash)
01336 {
01337        if (strcmp(p, INBOX) == 0)
01338               printf("%s", n_inbox);
01339        else if (strcmp(p, INBOX "." DRAFTS) == 0)
01340               printf("%s", n_drafts);
01341        else if (strcmp(p, INBOX "." TRASH) == 0)
01342               printf("%s", n_trash);
01343        else if (strcmp(p, INBOX "." SENT) == 0)
01344               printf("%s", n_sent);
01345        else
01346               list_folder(path);
01347 }
01348 
01349 static void parse_hierarchy(const char *hierarchy,
01350                          void (*maildir_hier_cb)
01351                          (const char *pfix, const char *homedir,
01352                           const char *path, const char *inbox_name),
01353                          void (*sharehier_cb)
01354                          (const char *sharedhier,
01355                           struct maildir_shindex_cache *cache));
01356 
01357 static void show_transfer_dest_real(const char *, const char *,
01358                                 const char *, const char *);
01359 static void show_transfer_dest_fake(const char *,
01360                                 struct maildir_shindex_cache *);
01361                          
01362 static void show_transfer_dest(const char *cur_folder)
01363 {
01364        parse_hierarchy(cur_folder, show_transfer_dest_real,
01365                      show_transfer_dest_fake);
01366 }
01367 
01368 static void show_transfer_dest_fake(const char *dummy1,
01369                                 struct maildir_shindex_cache *dummy2)
01370 {
01371 }
01372 
01373 static void show_transfer_dest_real1(const char *inbox_pfix,
01374                                  const char *homedir,
01375                                  const char *cur_folder,
01376                                  const char *inbox_name);
01377 
01378 static void show_transfer_dest_real(const char *inbox_pfix,
01379                                 const char *homedir,
01380                                 const char *cur_folder,
01381                                 const char *inbox_name)
01382 {
01383        FILE *fp;
01384        char buf1[BUFSIZ];
01385        char buf2[BUFSIZ];
01386 
01387        show_transfer_dest_real1(inbox_pfix, homedir, cur_folder, inbox_name);
01388 
01389        if ((fp=fopen(SHAREDPATHCACHE, "r")) != NULL)
01390        {
01391               while (fgets(buf1, sizeof(buf1), fp) &&
01392                      fgets(buf2, sizeof(buf2), fp))
01393               {
01394                      char *p;
01395 
01396                      p=strchr(buf1, '\n');
01397                      if (p) *p=0;
01398                      p=strchr(buf2, '\n');
01399                      if (p) *p=0;
01400 
01401                      if (homedir == NULL || strcmp(buf1, homedir))
01402                      {
01403                             show_transfer_dest_real1(buf2, buf1,
01404                                                   cur_folder,
01405                                                   inbox_name);
01406                      }
01407               }
01408               fclose(fp);
01409        }
01410 }
01411 
01412 static void show_transfer_dest_real1(const char *inbox_pfix,
01413                                  const char *homedir,
01414                                  const char *cur_folder,
01415                                  const char *inbox_name)
01416 {
01417        char   **folders;
01418        size_t i;
01419        const  char *p;
01420        int    has_shared=0;
01421 
01422        maildir_listfolders(inbox_pfix, homedir, &folders);
01423        for (i=0; folders[i]; i++)
01424        {
01425               char acl_buf[2];
01426 
01427               strcpy(acl_buf, ACL_INSERT);
01428               acl_computeRightsOnFolder(folders[i], acl_buf);
01429 
01430               if (acl_buf[0] == 0)
01431                      continue;
01432 
01433               /* Transferring TO drafts is prohibited */
01434 
01435               if (cur_folder == NULL || strcmp(cur_folder,
01436                                            INBOX "." DRAFTS))
01437               {
01438                      if (strcmp(folders[i], INBOX "." DRAFTS) == 0)
01439                             continue;
01440               }
01441               else
01442               {
01443                      if (strncmp(folders[i], SHARED ".",
01444                                 sizeof(SHARED)) &&
01445                          strcmp(folders[i], INBOX "." TRASH))
01446                             continue;
01447               }
01448 
01449               if (cur_folder && strcmp(cur_folder, folders[i]) == 0)
01450                      continue;
01451 
01452               p=folders[i];
01453 
01454               if (strcmp(p, INBOX) == 0)
01455                      p=folder_inbox;
01456               else if (strcmp(p, INBOX "." DRAFTS) == 0)
01457                      p=folder_drafts;
01458               else if (strcmp(p, INBOX "." TRASH) == 0)
01459                      p=folder_trash;
01460               else if (strcmp(p, INBOX "." SENT) == 0)
01461                      p=folder_sent;
01462               if (!p)       p=folders[i];
01463 
01464               if (strncmp(folders[i], SHARED ".", sizeof(SHARED)) == 0)
01465               {
01466               char   *d=maildir_shareddir(".", strchr(folders[i], '.')+1);
01467               struct stat   stat_buf;
01468 
01469                      if (!d)
01470                      {
01471                             maildir_freefolders(&folders);
01472                             enomem();
01473                      }
01474                      if (stat(d, &stat_buf))     /* Not subscribed */
01475                      {
01476                             free(d);
01477                             continue;
01478                      }
01479                      free(d);
01480 
01481                      if (!has_shared)
01482                      {
01483                             printf("<option value=\"\"></option>\n");
01484                             has_shared=1;
01485                      }
01486               }
01487 
01488               printf("<option value=\"");
01489               output_attrencoded(folders[i]);
01490               printf("\">");
01491 
01492               if (strncmp(folders[i], NEWSHARED, sizeof(NEWSHARED)-1) == 0)
01493               {
01494                      printf("%s.", getarg("PUBLICFOLDERS"));
01495               }
01496 
01497               p=strchr(folders[i], '.');
01498 
01499               list_folder(p ? p+1:folders[i]);
01500               printf("</option>\n");
01501        }
01502        maildir_freefolders(&folders);
01503 }
01504 
01505 void folder_msgmove()
01506 {
01507        ++initnextprevcnt;
01508        printf("<table border=\"0\" class=\"box-small-outer\"><tr><td>\n");
01509        printf("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr><td class=\"folder-move-background\">&nbsp;%s&nbsp;<select name=\"list%d\">\n", msg_movetolab, initnextprevcnt);
01510 
01511        show_transfer_dest(sqwebmail_folder);
01512 
01513        printf("</select><input type=\"submit\"%s name=\"move%d\" value=\"%s\" /></td></tr></table>\n",
01514               (msg_type == MSGTYPE_DELETED ? " disabled":""),
01515               initnextprevcnt,
01516               msg_golab ? msg_golab:"");
01517        printf("<input type=\"hidden\" name=\"pos\" value=\"%s\" />", cgi("pos"));
01518        printf("<input type=\"hidden\" name=\"posfile\" value=\"");
01519        output_attrencoded(msg_posfile ? msg_posfile:"");
01520        printf("\" /></td></tr></table>\n");
01521 }
01522 
01523 void folder_delmsg(size_t pos)
01524 {
01525 MSGINFO       **info;
01526 int    dummy;
01527 const  char *f=cgi("posfile");
01528 size_t newpos;
01529 int    rc=0;
01530 char nbuf[MAXLONGSIZE+10];
01531 
01532        CHECKFILENAME(f);
01533 
01534        if (*cgi("move1"))
01535        {
01536               rc=maildir_msgmovefile(sqwebmail_folder, f, cgi("list1"), pos);
01537               maildir_savefoldermsgs(sqwebmail_folder);
01538        }
01539        else if (*cgi("move2"))
01540        {
01541               rc=maildir_msgmovefile(sqwebmail_folder, f, cgi("list2"), pos);
01542               maildir_savefoldermsgs(sqwebmail_folder);
01543        }
01544        else
01545        {
01546               maildir_msgdeletefile(sqwebmail_folder, f, pos);
01547               maildir_savefoldermsgs(sqwebmail_folder);
01548        }
01549 
01550        if (rc)
01551        {
01552               http_redirect_argu("&form=readmsg&pos=%s&error=quota",
01553                      (unsigned long)pos);
01554               return;
01555        }
01556 
01557        newpos=pos+1;
01558        info=maildir_read(sqwebmail_folder, 1, &newpos, &dummy, &dummy);
01559 
01560        if (info[0] && newpos != pos)
01561        {
01562               sprintf(nbuf, "%lu", (unsigned long)newpos);
01563        }
01564        else
01565        {
01566               sprintf(nbuf, "%lu", (unsigned long)pos);
01567        }
01568 
01569        maildir_free(info, 1);
01570 
01571        if (*cgi("search"))
01572        {
01573               http_redirect_argss("&form=readmsg&pos=%s&search=1&"
01574                                 SEARCHRESFILENAME "=%s", nbuf,
01575                                 cgi(SEARCHRESFILENAME));
01576        }
01577        else
01578        {
01579               http_redirect_argss("&form=readmsg&pos=%s", nbuf, "");
01580        }
01581 }
01582 
01583 static int is_preview_mode()
01584 {
01585        /* We're in new message window, and we're previewing a draft */
01586 
01587        return (*cgi("showdraft"));
01588 }
01589 
01590 static void dokeyimport(FILE *, struct rfc2045 *, int);
01591 
01592 static void charset_warning(const char *mime_charset, void *arg)
01593 {
01594        char charset_buf[32];
01595        char *p;
01596 
01597        charset_buf[0]=0;
01598        strncat(charset_buf, mime_charset, sizeof(charset_buf)-1);
01599 
01600        for (p=charset_buf; *p; p++)
01601               if (*p < ' ' || *p > 0x7f ||
01602                   *p == '<' || *p == '>' || *p == '&')
01603                      *p=' ';
01604 
01605        printf(getarg("CHSET"), charset_buf, sqwebmail_content_charset);
01606 }
01607 
01608 static void html_warning()
01609 {
01610        printf("%s", getarg("HTML"));
01611 }
01612 
01613 static void init_smileys(struct msg2html_info *info)
01614 {
01615        FILE *fp=open_langform(sqwebmail_content_language, "smileys.txt", 0);
01616        char buf[1024];
01617 
01618        char imgbuf[1024];
01619 
01620        if (!fp)
01621               return;
01622 
01623        while (fgets(buf, sizeof(buf), fp) != NULL)
01624        {
01625               char *p=strchr(buf, '#');
01626               char *code;
01627               char *img;
01628               char *attr;
01629 
01630               if (p) *p=0;
01631 
01632               code=buf;
01633 
01634               for (p=buf; *p && !isspace(*p); p++)
01635                      ;
01636 
01637               if (*p)
01638                      *p++=0;
01639 
01640               while (*p && isspace(*p))
01641                      p++;
01642               img=p;
01643 
01644               while (*p && !isspace(*p))
01645                      p++;
01646               if (*p)
01647                      *p++=0;
01648 
01649               while (*p && isspace(*p))
01650                      p++;
01651               attr=p;
01652               p=strchr(p, '\n');
01653               if (p) *p=0;
01654 
01655               if (!*code || !*img)
01656                      continue;
01657 
01658               snprintf(imgbuf, sizeof(imgbuf),
01659                       "<img src=\"%s/%s\" %s />",
01660                       get_imageurl(), img, attr);
01661 
01662               msg2html_add_smiley(info, code, imgbuf);
01663        }
01664        fclose(fp);
01665 }
01666 
01667 static void email_address_start(const char *name, const char *addr)
01668 {
01669        if (is_preview_mode())
01670            return;
01671 
01672        printf("<a href=\"");
01673        output_scriptptrget();
01674        printf("&amp;form=quickadd&amp;pos=%s&amp;newname=",
01675               cgi("pos"));
01676 
01677        if (name)
01678               output_urlencoded(name);
01679 
01680        printf("&amp;newaddr=");
01681        if (addr)
01682               output_urlencoded(addr);
01683 
01684        printf("\" style=\"text-decoration: none\" "
01685               "onmouseover=\"window.status='%s'; return true;\" "
01686               "onmouseout=\"window.status=''; return true;\" >"
01687               "<span class=\"message-rfc822-header-address\">",
01688               msg_add ? msg_add:"");
01689 }
01690 
01691 static void email_address_end()
01692 {
01693        if (is_preview_mode())
01694               return;
01695 
01696        printf("</a></span>");
01697 }
01698 
01699 static void email_header(const char *h,
01700                       void (*cb_func)(const char *))
01701 {
01702        char *hdrname;
01703        char *p;
01704        const char *hdrvalue;
01705 
01706        if ((hdrname=malloc(sizeof("DSPHDR_")+strlen(h))) == NULL)
01707               enomem();
01708 
01709        strcpy (hdrname, "DSPHDR_");
01710        strcat (hdrname, h);
01711 
01712        for (p=hdrname; *p; p++)
01713               *p=toupper((int)(unsigned char)*p);
01714 
01715        hdrvalue = getarg (hdrname);
01716 
01717        (*cb_func)(hdrvalue && *hdrvalue ? hdrvalue:h);
01718 
01719        free(hdrname);
01720 }
01721 
01722 static const char *email_header_date_fmt(const char *def)
01723 {
01724        const char *date_fmt = getarg ("DSPFMT_DATE");
01725 
01726        if (date_fmt && *date_fmt)
01727               def=date_fmt;
01728        return def;
01729 }
01730 
01731 static void buf_cat_esc_amp(struct buf *b, const char *url)
01732 {
01733        for (; *url; ++url)
01734        {
01735               char   c[2];
01736 
01737               if (*url == '&')
01738               {
01739                      buf_cat(b, "&amp;");
01740               }
01741               else if (*url == '<')
01742               {
01743                      buf_cat(b, "&lt;");
01744               }
01745               else if (*url == '>')
01746               {
01747                      buf_cat(b, "&gt;");
01748               }
01749               else if (*url == '"')
01750               {
01751                      buf_cat(b, "&quot;");
01752               }
01753               else
01754               {
01755                      c[0]=*url;
01756                      c[1]=0;
01757                      buf_cat(b, c);
01758               }
01759        }
01760 }
01761 
01762 extern const char *redirect_hash(const char *timestamp);
01763 
01764 static char *get_textlink(const char *s, void *arg)
01765 {
01766 char   *t;
01767 struct buf b;
01768 
01769        buf_init(&b);
01770 
01771        if (strncmp(s, "mailto:", 7) == 0)
01772        {
01773        int    i;
01774 
01775               buf_cat(&b, "<a href=\"");
01776 
01777               {
01778                      char *p=scriptptrget();
01779 
01780                      buf_cat(&b, p);
01781                      free(p);
01782               }
01783 
01784               buf_cat(&b, "&amp;form=newmsg&amp;to=");
01785 
01786               for (i=7; s[i]; i++)
01787               {
01788               char   c[2];
01789 
01790                      c[1]=0;
01791                      if ((c[0]=s[i]) == '?')
01792                             c[0]='&';
01793                      else if (c[0] == '&')
01794                      {
01795                             buf_cat(&b, "&amp;");
01796                      }
01797                      else if (c[0] == '<')
01798                      {
01799                             buf_cat(&b, "&lt;");
01800                      }
01801                      else if (c[0] == '>')
01802                      {
01803                             buf_cat(&b, "&gt;");
01804                      }
01805                      else if (c[0] == '"')
01806                      {
01807                             buf_cat(&b, "&quot;");
01808                      }
01809                      else
01810                      {
01811                             buf_cat(&b, c);
01812                      }
01813               }
01814               buf_cat(&b, "\">"
01815                      "<span class=\"message-text-plain-mailto-link\">");
01816               buf_cat_esc_amp(&b, s);
01817               buf_cat(&b, "</span></a>");
01818        }
01819        else if (strncmp(s, "http:", 5) == 0 || strncmp(s, "https:", 6) == 0)
01820        {
01821               char buffer[NUMBUFSIZE];
01822               time_t now;
01823               char *hash;
01824               const char *n;
01825 
01826               time(&now);
01827               libmail_str_time_t(now, buffer);
01828 
01829               hash=cgiurlencode(redirect_hash(buffer));
01830 
01831               t=cgiurlencode(s);
01832               buf_cat(&b, "<a href=\"");
01833 
01834               n=getenv("SCRIPT_NAME");
01835               if (!n || !*n) n="/";
01836 
01837               buf_cat(&b, n);
01838               buf_cat(&b, "?redirect=");
01839               buf_cat(&b, t);
01840               buf_cat(&b, "&amp;timestamp=");
01841               buf_cat(&b, buffer);
01842               buf_cat(&b, "&amp;md5=");
01843               if (hash)
01844               {
01845                      buf_cat(&b, hash);
01846                      free(hash);
01847               }
01848               buf_cat(&b, "\" target=\"_blank\">"
01849                      "<span class=\"message-text-plain-http-link\">");
01850               buf_cat_esc_amp(&b, s);
01851               buf_cat(&b, "</span></a>");
01852               free(t);
01853        }
01854        t=strdup(b.ptr ? b.ptr:"");
01855        if (!t)       enomem();
01856        buf_free(&b);
01857        return (t);
01858 }
01859 
01860 static void message_rfc822_action(struct rfc2045id *idptr)
01861 {
01862        if (is_preview_mode())
01863               return;
01864 
01865        printf("<tr valign=\"top\"><td>&nbsp;</td><td align=\"left\" valign=\"top\">");
01866 
01867        printf("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr><td><a href=\"");
01868        output_scriptptrget();
01869        output_mimegpgfilename();
01870        msg2html_showmimeid(idptr, NULL);
01871        printf("&amp;pos=%ld&amp;reply=1&amp;form=newmsg\"><font size=\"-1\">%s</font></a>&nbsp;</td><td>&nbsp;<a href=\"",
01872               (long)msg_pos, msg_replylab);
01873 
01874        output_scriptptrget();
01875        output_mimegpgfilename();
01876        msg2html_showmimeid(idptr, NULL);
01877        printf("&amp;pos=%ld&amp;replyall=1&amp;form=newmsg\"><font size=\"-1\">%s</font></a>&nbsp;</td><td>&nbsp;<a href=\"",
01878               (long)msg_pos, msg_replyalllab);
01879        output_scriptptrget();
01880        output_mimegpgfilename();
01881        msg2html_showmimeid(idptr, NULL);
01882        printf("&amp;pos=%ld&amp;forward=1&amp;form=newmsg\"><font size=\"-1\">%s</font></a>&nbsp;</td><td>&nbsp;<a href=\"",
01883               (long)msg_pos, msg_forwardlab);
01884 
01885        output_scriptptrget();
01886        output_mimegpgfilename();
01887        msg2html_showmimeid(idptr, NULL);
01888        printf("&amp;pos=%ld&amp;forwardatt=1&amp;form=newmsg\"><font size=\"-1\">%s</font></a></td></tr></table>\n",
01889               (long)msg_pos, msg_forwardattlab);
01890 
01891        printf("</td></tr>\n");
01892 }
01893 
01894 static void output_mimeurl(struct rfc2045id *id, const char *form)
01895 {
01896        output_scriptptrget();
01897        printf("&amp;form=%s&amp;pos=%ld", form, (long)msg_pos);
01898        msg2html_showmimeid(id, NULL);
01899 
01900        output_mimegpgfilename();
01901 }
01902 
01903 static void inline_image_action(struct rfc2045id *id, const char *content_type,
01904                             void *arg)
01905 {
01906        if (!is_preview_mode())
01907        {
01908               printf("<a href=\"");
01909               output_mimeurl(id, "fetch");
01910               printf("\" target=\"_blank\">");
01911        }
01912        printf("<img src=\"");
01913        output_mimeurl(id, "fetch");
01914        printf("\" alt=\"Inline picture: ");
01915        output_attrencoded(content_type);
01916        printf("\" />%s\n",
01917               is_preview_mode() ? "":"</a>");
01918 }
01919 
01920 
01921 static void showattname(const char *fmt, const char *name,
01922        const char *content_type)
01923 {
01924 char   *t;
01925 
01926        if (!name || !*name) name=content_type;
01927        if (!name)    name="";
01928 
01929        t=malloc(strlen(name)+strlen(fmt)+100);
01930        if (!t)
01931               return;
01932 
01933        sprintf(t, fmt, name);
01934        output_attrencoded(t);
01935        free(t);
01936 }
01937 
01938 static void unknown_attachment_action(struct rfc2045id *id,
01939                                   const char *content_type,
01940                                   const char *content_name,
01941                                   off_t size,
01942                                   void *arg)
01943 {
01944        printf("<table border=\"0\" cellpadding=\"1\" cellspacing=\"0\" class=\"box-small-outer\"><tr><td>");
01945        printf("<table border=\"0\" cellpadding=\"4\" cellspacing=\"0\" class=\"message-download-attachment\"><tr><td>");
01946 
01947        if (strcmp(cgi("form"), "print") == 0)
01948        {
01949               showattname(getarg("ATTSTUB"), content_name, content_type);
01950 
01951               printf("&nbsp;(");
01952               output_attrencoded(content_type);
01953               printf(")");
01954        }
01955        else
01956        {
01957               printf("<div align=\"center\"><span class=\"message-attachment-header\">");
01958               showattname(getarg("ATTACHMENT"), content_name, content_type);
01959 
01960               printf("&nbsp;(");
01961               output_attrencoded(content_type);
01962               printf("; %s)</span></div>",
01963                      showsize(size));
01964               printf("<br /><div align=\"center\">");
01965 
01966               if (!is_preview_mode())
01967               {
01968                      printf("<a href=\"");
01969                      output_mimeurl(id, "fetch");
01970                      printf("\" style=\"text-decoration: none\" target=\"_blank\">");
01971                      printf("%s</a>&nbsp;/&nbsp;", getarg("DISPATT"));
01972                      printf("<a href=\"");
01973                      output_mimeurl(id, "fetch");
01974                      printf("&amp;download=1\" style=\"text-decoration: none\">");
01975                      printf("%s</a>", getarg("DOWNATT"));
01976               }
01977 
01978               printf("</div>\n");
01979        }
01980 
01981        printf("</td></tr></table>\n");
01982        printf("</td></tr></table>\n");
01983 }
01984 
01985 static int is_gpg_enabled()
01986 {
01987        return *cgi(MIMEGPGFILENAME) && !is_preview_mode();
01988 }
01989 
01990 static void application_pgp_keys_action(struct rfc2045id *id)
01991 {
01992        printf("<table border=\"0\" cellpadding=\"8\" cellspacing=\"1\" class=\"box-small-outer\"><tr><td>");
01993        printf("<table border=\"0\" cellpadding=\"4\" cellspacing=\"4\" class=\"message-application-pgpkeys\"><tr><td>");
01994 
01995        if (strcmp(cgi("form"), "print") == 0 || is_preview_mode())
01996        {
01997               printf("%s", getarg("KEY"));
01998        }
01999        else
02000        {
02001               printf("<div align=\"center\"><a href=\"");
02002               output_scriptptrget();
02003               printf("&amp;form=keyimport&amp;pos=%ld", (long)msg_pos);
02004               printf("&amp;pubkeyimport=1");
02005               output_mimegpgfilename();
02006               msg2html_showmimeid(id, "&amp;keymimeid=");
02007               printf("\" style=\"text-decoration: none\" class=\"message-application-pgpkeys\">");
02008               printf("%s", getarg("PUBKEY"));
02009               printf("</a></div>");
02010 
02011               printf("<hr width=\"100%%\" />\n");
02012 
02013               printf("<div align=\"center\"><a href=\"");
02014               output_scriptptrget();
02015               printf("&amp;form=keyimport&amp;pos=%ld", (long)msg_pos);
02016               printf("&amp;privkeyimport=1");
02017               output_mimegpgfilename();
02018               msg2html_showmimeid(id, "&amp;keymimeid=");
02019               printf("\" style=\"text-decoration: none\" class=\"message-application-pgpkeys\">");
02020               printf("%s", getarg("PRIVKEY"));
02021               printf("</a></div>");
02022        }
02023 
02024        printf("</td></tr></table>\n");
02025        printf("</td></tr></table>\n<br />\n");
02026 }
02027 
02028 static void gpg_message_action()
02029 {
02030        printf("<form method=\"post\" action=\"");
02031        output_scriptptr();
02032        printf("\">");
02033        output_scriptptrpostinfo();
02034        printf("<input type=\"hidden\" name=\"form\" value=\"readmsg\" />");
02035        printf("<input type=\"hidden\" name=\"pos\" value=\"%s\" />",
02036               cgi("pos"));
02037        printf("<input type=\"hidden\" name=\"mimegpg\" value=\"1\" />\n");
02038 
02039        printf("<table border=\"0\" cellpadding=\"1\""
02040               " width=\"100%%\" class=\"box-outer\">"
02041               "<tr><td><table width=\"100%%\" border=\"0\" cellspacing=\"0\""
02042               " cellpadding=\"0\" class=\"box-white-outer\"><tr><td>");
02043 
02044        if ( *cgi(MIMEGPGFILENAME))
02045        {
02046               printf("%s", getarg("NOTCOMPACTGPG"));
02047        }
02048        else
02049        {
02050               printf("%s\n", getarg("MIMEGPGNOTICE"));
02051 
02052               if (ishttps())
02053                      printf("%s\n", getarg("PASSPHRASE"));
02054 
02055               printf("%s", getarg("DECRYPT"));
02056        }
02057        printf("</td><tr></table></td></tr></table></form><br />\n");
02058 }
02059 
02060 const char *redirect_hash(const char *timestamp)
02061 {
02062        struct stat stat_buf;
02063 
02064        char buffer[NUMBUFSIZE*2+10];
02065        const char *p=getenv("SQWEBMAIL_RANDSEED");
02066 
02067        if (strlen(timestamp) >= NUMBUFSIZE)
02068               return "";
02069 
02070        strcat(strcpy(buffer, timestamp), " ");
02071 
02072        if (p && *p)
02073               strncat(buffer, p, NUMBUFSIZE);
02074        else
02075        {
02076               if (stat(SENDITSH, &stat_buf) < 0)
02077                      return "";
02078 
02079               libmail_str_ino_t(stat_buf.st_ino, buffer+strlen(buffer));
02080        }
02081 
02082        return md5_hash_courier(buffer);
02083 }
02084 
02085 static char *get_url_to_mime_part(const char *mimeid, void *arg)
02086 {
02087        const char *mimegpgfilename=cgi(MIMEGPGFILENAME);
02088        const char *pos;
02089        char *p, *q;
02090 
02091        p=scriptptrget();
02092        pos=cgi("pos");
02093 
02094        q=malloc(strlen(p)+strlen(pos) +
02095                strlen(mimegpgfilename)+
02096                strlen(mimeid)+
02097                sizeof("&mimeid=&pos=&form=fetch&mimegpgfilename="));
02098        if (!q)       enomem();
02099        strcpy(q, p);
02100        strcat(q, "&form=fetch&pos=");
02101        strcat(q, pos);
02102        strcat(q, "&mimeid=");
02103        strcat(q, mimeid);
02104 
02105        if (*mimegpgfilename)
02106               strcat(strcat(q, "&mimegpgfilename="), mimegpgfilename);
02107 
02108        return (q);
02109 }
02110 
02111 void folder_showmsg(const char *dir, size_t pos)
02112 {
02113        char   *filename;
02114        FILE   *fp;
02115        struct rfc2045 *rfc;
02116        char   buf[BUFSIZ];
02117        int    n;
02118        int    fd;
02119 
02120        struct msg2html_info *info;
02121 
02122        const char *script_name=nonloginscriptptr();
02123 
02124 
02125        if (*cgi("addnick"))
02126        {
02127               const char *name=cgi("newname");
02128               const char *addr=cgi("newaddr");
02129 
02130               const char *nick1=cgi("newnick1");
02131               const char *nick2=cgi("newnick2");
02132 
02133               while (*nick1 && isspace((int)(unsigned char)*nick1))
02134                      ++nick1;
02135 
02136               while (*nick2 && isspace((int)(unsigned char)*nick2))
02137                      ++nick2;
02138 
02139               if (*nick2)
02140                      nick1=nick2;
02141 
02142               if (*nick1)
02143               {
02144                      ab_add(name, addr, nick1);
02145               }
02146        }
02147 
02148        filename=get_msgfilename(dir, &pos);
02149 
02150        fp=0;
02151        fd=maildir_semisafeopen(filename, O_RDONLY, 0);
02152        if (fd >= 0)
02153        {
02154               if ((fp=fdopen(fd, "r")) == 0)
02155                      close(fd);
02156        }
02157 
02158        if (!fp)
02159        {
02160               free(filename);
02161               return;
02162        }
02163 
02164        msg_pos=pos;
02165        rfc=rfc2045_alloc();
02166 
02167        while ((n=fread(buf, 1, sizeof(buf), fp)) > 0)
02168               rfc2045_parse(rfc, buf, n);
02169        rfc2045_parse_partial(rfc);
02170 
02171        info=script_name ? msg2html_alloc(sqwebmail_content_charset):NULL;
02172 
02173        if (info)
02174        {
02175               char nowbuffer[NUMBUFSIZE];
02176               time_t now;
02177               char *hash;
02178               char *washpfix;
02179               char *washpfixmailto;
02180               char *scriptnameget=scriptptrget();
02181               static const char formbuf[]="&form=newmsg&to=";
02182 
02183               info->mimegpgfilename=cgi(MIMEGPGFILENAME);
02184               if (*info->mimegpgfilename)
02185                      CHECKFILENAME(info->mimegpgfilename);
02186 
02187               info->gpgdir=GPGDIR;
02188               info->fullheaders=pref_flagfullheaders || *cgi("fullheaders");
02189               info->noflowedtext=pref_noflowedtext;
02190               info->showhtml=pref_showhtml;
02191 
02192               info->charset_warning=charset_warning;
02193               info->html_content_follows=html_warning;
02194               info->get_url_to_mime_part=get_url_to_mime_part;
02195 
02196               time(&now);
02197               libmail_str_time_t(now, nowbuffer);
02198 
02199               hash=cgiurlencode(redirect_hash(nowbuffer));
02200 
02201               washpfix=malloc(strlen(script_name)
02202                             + strlen(hash ? hash:"") + strlen(nowbuffer)
02203                             + 100);
02204               if (!washpfix)       enomem();
02205 
02206               strcat(strcat(strcat(strcat(strcat(strcpy(washpfix,
02207                                                    script_name),
02208                                              "?timestamp="),
02209                                        nowbuffer),
02210                                  "&md5="),
02211                            (hash ? hash:"")),
02212                      "&redirect=");
02213 
02214               if (hash)
02215                      free(hash);
02216 
02217               washpfixmailto=malloc(strlen(scriptnameget)+sizeof(formbuf));
02218               if (!washpfixmailto) enomem();
02219               strcat(strcpy(washpfixmailto, scriptnameget), formbuf);
02220               free(scriptnameget);
02221 
02222               info->wash_http_prefix=washpfix;
02223               info->wash_mailto_prefix=washpfixmailto;
02224 
02225               init_smileys(info);
02226 
02227               info->email_address_start=email_address_start;
02228               info->email_address_end=email_address_end;
02229               info->email_header=email_header;
02230               info->email_header_date_fmt=email_header_date_fmt;
02231               info->get_textlink=get_textlink;
02232               info->message_rfc822_action=message_rfc822_action;
02233               info->inline_image_action=inline_image_action;
02234               info->unknown_attachment_action=unknown_attachment_action;
02235               info->application_pgp_keys_action=
02236                      application_pgp_keys_action;
02237               info->gpg_message_action=gpg_message_action;
02238 
02239               info->is_gpg_enabled=is_gpg_enabled();
02240               info->is_preview_mode=is_preview_mode();
02241 
02242               msg2html(fp, rfc, info);
02243               msg2html_free(info);
02244 
02245               free(washpfix);
02246               free(washpfixmailto);
02247        }
02248 
02249        rfc2045_free(rfc);
02250        fclose(fp);
02251        if (*cgi(MIMEGPGFILENAME) == 0)
02252               maildir_markread(dir, pos);
02253        free(filename);
02254 }
02255 
02256 void folder_keyimport(const char *dir, size_t pos)
02257 {
02258        char   *filename;
02259        FILE   *fp;
02260        struct rfc2045 *rfc;
02261        int    fd;
02262 
02263        filename=get_msgfilename(dir, &pos);
02264 
02265        fp=0;
02266        fd=maildir_semisafeopen(filename, O_RDONLY, 0);
02267        if (fd >= 0)
02268        {
02269               if ((fp=fdopen(fd, "r")) == 0)
02270                      close(fd);
02271        }
02272 
02273        if (!fp)
02274        {
02275               free(filename);
02276               return;
02277        }
02278 
02279        rfc=rfc2045_fromfp(fp);
02280 
02281 
02282        if (libmail_gpg_has_gpg(GPGDIR) == 0)
02283        {
02284               struct rfc2045 *part;
02285 
02286               if (*cgi("pubkeyimport")
02287                   && (part=rfc2045_find(rfc, cgi("keymimeid"))) != 0)
02288               {
02289                      dokeyimport(fp, part, 0);
02290               }
02291               else if (*cgi("privkeyimport")
02292                   && (part=rfc2045_find(rfc, cgi("keymimeid"))) != 0)
02293               {
02294                      dokeyimport(fp, part, 1);
02295               }
02296        }
02297        rfc2045_free(rfc);
02298        fclose(fp);
02299        free(filename);
02300 
02301        printf("<p><a href=\"");
02302        output_scriptptrget();
02303        printf("&amp;form=readmsg&amp;pos=%s", cgi("pos"));
02304        printf("\">%s</a>", getarg("KEYIMPORT"));
02305 }
02306 
02307 static int importkey_func(const char *p, size_t cnt, void *voidptr);
02308 static int importkeyin_func(const char *p, size_t cnt, void *voidptr);
02309 
02310 static void dokeyimport(FILE *fp, struct rfc2045 *rfcp, int issecret)
02311 {
02312        off_t  start_pos, end_pos, start_body, ldummy;
02313        char buf[BUFSIZ];
02314        int cnt;
02315 
02316        static const char start_str[]=
02317               "<table width=\"100%%\" border=\"0\" class=\"box-outer\"><tr><td>"
02318               "<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"4\""
02319               " class=\"box-white-outer\"><tr><td>%s<pre>\n";
02320 
02321        static const char end_str[]=
02322               "</pre></td></tr></table></td></tr></table><br />\n";
02323 
02324        if (libmail_gpg_import_start(GPGDIR, issecret))
02325               return;
02326 
02327        printf(start_str, getarg("IMPORTHDR"));
02328 
02329        rfc2045_mimepos(rfcp, &start_pos, &end_pos, &start_body,
02330               &ldummy, &ldummy);
02331        if (fseek(fp, start_body, SEEK_SET) < 0)
02332        {
02333               error("Seek error.");
02334               libmail_gpg_import_finish(&importkey_func, NULL);
02335               printf("%s", end_str);
02336               return;
02337        }
02338 
02339        rfc2045_cdecode_start(rfcp, &importkeyin_func, 0);
02340 
02341        while (start_body < end_pos)
02342        {
02343               cnt=sizeof(buf);
02344               if (cnt > end_pos-start_body)
02345                      cnt=end_pos-start_body;
02346               cnt=fread(buf, 1, cnt, fp);
02347               if (cnt <= 0) break;
02348               start_body += cnt;
02349               if (rfc2045_cdecode(rfcp, buf, cnt))
02350               {
02351                      rfc2045_cdecode_end(rfcp);
02352                      printf("%s", end_str);
02353                      return;
02354               }
02355        }
02356 
02357        if (rfc2045_cdecode_end(rfcp) == 0)
02358        {
02359               libmail_gpg_import_finish(&importkey_func, NULL);
02360        }
02361 
02362        printf("%s", end_str);
02363 }
02364 
02365 static int importkeyin_func(const char *p, size_t cnt, void *voidptr)
02366 {
02367        return (libmail_gpg_import_do(p, cnt, &importkey_func, NULL));
02368 }
02369 
02370 static int importkey_func(const char *p, size_t cnt, void *voidptr)
02371 {
02372        print_attrencodedlen(p, cnt, 1, stdout);
02373        return (0);
02374 }
02375 
02376 
02377 /*
02378 ** If we're currently showing (INBOX|shared|#shared).foo.bar hierarchy, return
02379 ** "x.foo".  If we're currently showing (INBOX|shared|#shared).foo, return
02380 ** an empty string.
02381 */
02382 static char *get_parent_folder(const char *p)
02383 {
02384        const char *q;
02385 
02386        q=strrchr(p, '.');
02387 
02388        if (q)
02389        {
02390               char   *s;
02391 
02392               s=malloc(q-p+1);
02393               if (!s)       enomem();
02394               memcpy(s, p, q-p);
02395               s[q-p]=0;
02396               return (s);
02397        }
02398        return (strdup(""));
02399 }
02400 
02401 static int checkrename(const char *origfolder,
02402                      const char *newfolder)
02403 {
02404        char acl_buf[2];
02405        char *p, *q;
02406 
02407        strcpy(acl_buf, ACL_DELETEFOLDER);
02408        acl_computeRightsOnFolder(origfolder, acl_buf);
02409        if (acl_buf[0] == 0)
02410        {
02411               folder_err_msg=getarg("RENAME");
02412               return -1;
02413        }
02414 
02415        strcpy(acl_buf, ACL_CREATE);
02416        p=strdup(newfolder);
02417 
02418        if (!p || !(q=strrchr(p, '.')) ||
02419            (*q=0,
02420             acl_computeRightsOnFolder(p, acl_buf),
02421             acl_buf[0]) == 0)
02422        {
02423               if (p)
02424                      free(p);
02425 
02426               folder_err_msg=getarg("RENAME");
02427               return -1;
02428        }
02429        free(p);
02430 
02431        return 0;
02432 }
02433 
02434 static void dorename(const char *origfolder,
02435                    struct maildir_info *mifrom,
02436                    struct maildir_info *mito,
02437                    const char *err_invalid,
02438                    const char *err_cantdelete,
02439                    const char *err_exists)
02440 {
02441        char *s;
02442        char *t;
02443        char *u;
02444 
02445        const char *p;
02446        struct stat   stat_buf;
02447 
02448        if (mifrom->homedir == NULL ||
02449            mifrom->maildir == NULL ||
02450            mito->homedir == NULL ||
02451            mito->maildir == NULL ||
02452            strcmp(mifrom->homedir, mito->homedir))
02453        {
02454               folder_err_msg=err_invalid;
02455               return;
02456        }
02457 
02458        s=maildir_name2dir(".", mifrom->maildir);
02459        t=maildir_name2dir(".", mito->maildir);
02460 
02461        if (!s || !t)
02462        {
02463               if (s) free(s);
02464               if (t) free(t);
02465               folder_err_msg=err_invalid;
02466               return;
02467        }
02468 
02469        p=s;
02470        if (strncmp(p, "./", 2) == 0) p += 2;
02471 
02472        if (strcmp(p, ".") == 0 ||
02473            strcmp(p, "." SENT) == 0 ||
02474            strcmp(p, "." DRAFTS) == 0 ||
02475            strcmp(p, "." TRASH) == 0)
02476        {
02477               free(s);
02478               free(t);
02479               folder_err_msg=err_invalid;
02480               return;
02481        }
02482 
02483        u=maildir_name2dir(mito->homedir, mito->maildir);
02484        if (!u)
02485        {
02486               free(s);
02487               free(t);
02488               folder_err_msg=err_invalid;
02489               return;
02490        }
02491 
02492        if (stat(u, &stat_buf) == 0)
02493        {
02494               free(s);
02495               free(t);
02496               folder_err_msg=err_exists;
02497               return;
02498        }
02499        free(u);
02500 
02501        if (mailfilter_folderused(origfolder))
02502        {
02503               free(s);
02504               free(t);
02505               folder_err_msg=err_cantdelete;
02506               return;
02507        }
02508 
02509        if (maildir_rename(mifrom->homedir,
02510                         strncmp(s, "./", 2) == 0 ? s+2:s,
02511                         strncmp(t, "./", 2) == 0 ? t+2:t,
02512                         MAILDIR_RENAME_FOLDER, NULL))
02513               folder_err_msg=err_cantdelete;
02514 
02515        free(s);
02516        free(t);
02517 }
02518 
02519 struct publicfolderlist_helper {
02520        char *name;
02521        char *homedir;
02522        char *maildir;
02523 };
02524 
02525 static void freeph(struct publicfolderlist_helper *ph)
02526 {
02527        if (ph->name)
02528               free(ph->name);
02529        if (ph->homedir)
02530               free(ph->homedir);
02531        if (ph->maildir)
02532               free(ph->maildir);
02533        memset(ph, 0, sizeof(*ph));
02534 }
02535 
02536 static void do_folderlist(const char *pfix, const char *homedir,
02537                        const char *path, const char *inbox_name);
02538 static void do_sharedhierlist(const char *sharedhier,
02539                            struct maildir_shindex_cache *cache);
02540 
02541 static int checkcreate(const char *f, int isrec)
02542 {
02543        char *s=strdup(f);
02544        char *q;
02545        char buf[2];
02546        struct maildir_info minfo;
02547 
02548        if (!s)
02549        {
02550               folder_err_msg=getarg("CREATEPERMS");
02551               return -1;
02552        }
02553 
02554        if (isrec)
02555        {
02556               if ((q=strrchr(s, '.')) == NULL ||
02557                   (*q=0, checkcreate(s, 0)) < 0)
02558               {
02559                      free(s);
02560                      folder_err_msg=getarg("CREATEPERMS");
02561                      return -1;
02562               }
02563               *q='.';
02564        }
02565 
02566        if (maildir_info_imap_find(&minfo, s, login_returnaddr()) < 0)
02567        {
02568               free(s);
02569               folder_err_msg=getarg("CREATEPERMS");
02570               return -1;
02571        }
02572 
02573        if (strchr(minfo.maildir, '.') == NULL)
02574        {
02575               free(s);
02576               folder_err_msg=getarg("CREATEPERMS");
02577               return -1;
02578        }
02579 
02580        maildir_acl_delete(minfo.homedir,
02581                         strchr(minfo.maildir, '.'));
02582 
02583        maildir_info_destroy(&minfo);
02584 
02585        strcpy(buf, ACL_CREATE);
02586 
02587        if ((q=strrchr(s, '.')) == NULL ||
02588            (*q=0,
02589             acl_computeRightsOnFolder(s, buf),
02590             buf[0]) == 0)
02591        {
02592               free(s);
02593               folder_err_msg=getarg("CREATEPERMS");
02594               return -1;
02595        }
02596        free(s);
02597        return 0;
02598 }
02599 
02600 void folder_list()
02601 {
02602        const char    *err_invalid;
02603        const char    *err_exists;
02604        const char    *err_cantdelete;
02605        const char    *msg_hasbeensent;
02606 
02607        err_invalid=getarg("INVALID");
02608        err_exists=getarg("EXISTS");
02609        err_cantdelete=getarg("DELETE");
02610        msg_hasbeensent=getarg("WASSENT");
02611 
02612        folder_err_msg=0;
02613 
02614        if (strcmp(cgi("foldermsg"), "sent") == 0)
02615               folder_err_msg=msg_hasbeensent;
02616 
02617        if (*cgi("do.create"))
02618        {
02619               const char    *newfoldername=trim_spaces(cgi("foldername"));
02620               const char    *newdirname=trim_spaces(cgi("dirname"));
02621               const char    *folderdir=cgi("folderdir");
02622               char   *futf7;
02623               char   *dutf7;
02624 
02625               /*
02626               ** New folder names cannot contain .s, and must be considered
02627               ** as valid by maildir_folderpath.
02628               */
02629 
02630               if (!*folderdir)
02631                      folderdir=INBOX;
02632 
02633               futf7=folder_toutf7(newfoldername);
02634               dutf7=folder_toutf7(newdirname);;
02635 
02636               if (!*newfoldername ||
02637                   strchr(futf7, '.') ||
02638                   strchr(dutf7, '.'))
02639               {
02640                      free(futf7);
02641                      free(dutf7);
02642                      folder_err_msg=err_invalid;
02643               }
02644               else
02645               {
02646                      char   *p;
02647                      struct maildir_info minfo;
02648                      char *q;
02649 
02650                      p=malloc(strlen(folderdir)+strlen(futf7)
02651                              +strlen(dutf7)+3);
02652 
02653                      if (!p)       enomem();
02654                      strcpy(p, folderdir);
02655                      if (*dutf7)
02656                      {
02657                             if (*p)       strcat(p, ".");
02658                             strcat(p, dutf7);
02659                      }
02660                      if (*p)       strcat(p, ".");
02661                      strcat(p, futf7);
02662 
02663                      free(futf7);
02664                      free(dutf7);
02665 
02666                      if (maildir_info_imap_find(&minfo, p,
02667                                              login_returnaddr()) < 0)
02668                      {
02669                             folder_err_msg=err_invalid;
02670                      }
02671                      else if (minfo.homedir == NULL ||
02672                              minfo.maildir == NULL ||
02673                              (q=maildir_name2dir(minfo.homedir,
02674                                                minfo.maildir)) == NULL)
02675                      {
02676                             maildir_info_destroy(&minfo);
02677                             folder_err_msg=err_invalid;
02678                      }
02679                      else if (access(q, 0) == 0)
02680                      {
02681                             free(q);
02682                             maildir_info_destroy(&minfo);
02683                             folder_err_msg=err_exists;
02684                      }
02685                      else
02686                      {
02687                             if (checkcreate(p, *newdirname != 0) == 0)
02688                             {
02689                                    if (maildir_make(q, 0700, 0700, 1))
02690                                           folder_err_msg=err_exists;
02691                                    else
02692                                    {
02693                                           char buf[1];
02694 
02695                                           buf[0]=0;
02696                                           acl_computeRightsOnFolder(p,
02697                                                                  buf);
02698                                           /* Initialize ACLs correctly */
02699                                    }
02700                             }
02701                             free(q);
02702                             maildir_info_destroy(&minfo);
02703                      }
02704               }
02705        }
02706 
02707        if (*cgi("do.delete"))
02708        {
02709               const char *p=cgi("DELETE");
02710               char acl_buf[2];
02711 
02712               strcpy(acl_buf, ACL_DELETEFOLDER);
02713               acl_computeRightsOnFolder(p, acl_buf);
02714               if (acl_buf[0] == 0)
02715                      folder_err_msg=getarg("DELETEPERMS");
02716               else if (mailfilter_folderused(p))
02717                      folder_err_msg=err_cantdelete;
02718               else if (maildir_delete(p, *cgi("deletecontent")))
02719                      folder_err_msg=err_cantdelete;
02720               else
02721                      maildir_quota_recalculate(".");
02722        }
02723 
02724        if (*cgi("do.subunsub"))
02725        {
02726               const char *p=cgi("DELETE");
02727               char   *pp=strdup(p);
02728               char *d;
02729 
02730               if (pp && strncmp(pp, SHARED ".", sizeof(SHARED)) == 0 &&
02731                   (d=maildir_shareddir(".", pp+sizeof(SHARED))) != 0)
02732               {
02733               struct stat   stat_buf;
02734 
02735                      if (stat(d, &stat_buf) == 0)
02736                             maildir_shared_unsubscribe(".",
02737                                                     pp+sizeof(SHARED));
02738                      else
02739                             maildir_shared_subscribe(".",
02740                                                   pp+sizeof(SHARED));
02741                      free(d);
02742               }
02743 
02744               if (pp)
02745                      free(pp);
02746        }
02747 
02748        if (*cgi("do.rename"))
02749        {
02750               const char *p=cgi("DELETE");
02751               char   *pp=strdup(p);
02752               struct maildir_info mifrom, mito;
02753               const char *qutf7=cgi("renametofolder");
02754               const char *r=trim_spaces(cgi("renametoname"));
02755               char   *s;
02756               char   *rutf7;
02757 
02758               rutf7=folder_toutf7(r);
02759 
02760               s=malloc(strlen(qutf7)+strlen(rutf7)+1);
02761 
02762               if (!s)       enomem();
02763 
02764               strcat(strcpy(s, qutf7), rutf7);
02765 
02766               if (strchr(r, '.') == NULL
02767                   && maildir_info_imap_find(&mifrom, pp,
02768                                          login_returnaddr()) == 0)
02769               {
02770                      if (maildir_info_imap_find(&mito, s,
02771                                              login_returnaddr()) == 0)
02772                      {
02773                             if (checkrename(pp, s) == 0)
02774                                    dorename(pp, &mifrom, &mito,
02775                                            err_invalid,
02776                                            err_cantdelete,
02777                                            err_exists);
02778                             maildir_info_destroy(&mifrom);
02779                      }
02780                      else
02781                      {
02782                             folder_err_msg=err_invalid;
02783                      }
02784                      maildir_info_destroy(&mito);
02785               }
02786               else
02787               {
02788                      folder_err_msg=err_invalid;
02789               }
02790               free(rutf7);
02791               free(pp);
02792               free(s);
02793               maildir_quota_recalculate(".");
02794        }
02795 
02796        parse_hierarchy(cgi("folderdir"),
02797                          do_folderlist,
02798                          do_sharedhierlist);
02799 }
02800 
02801 static int do_publicfolderlist_cb(struct maildir_newshared_enum_cb *cb)
02802 {
02803        struct publicfolderlist_helper *h=
02804               (struct publicfolderlist_helper *)cb->cb_arg;
02805 
02806        h->name=strdup(cb->name);
02807        if (cb->homedir)
02808               h->homedir=strdup(cb->homedir);
02809        h->maildir=strdup(cb->maildir);
02810        return 0;
02811 }
02812 
02813 static void parse_hierarchy(const char *folderdir,
02814                          void (*maildir_hier_cb)
02815                          (const char *pfix, const char *homedir,
02816                           const char *path, const char *inbox_name),
02817                          void (*sharedhier_cb)
02818                          (const char *sharedhier,
02819                           struct maildir_shindex_cache *cache))
02820 {
02821        struct maildir_shindex_cache *index;
02822        const char *indexfile;
02823        const char *subhierarchy;
02824        const char *p;
02825        const char *q;
02826        size_t l;
02827        size_t n;
02828        struct publicfolderlist_helper ph;
02829        int eof;
02830 
02831        if (strchr(folderdir, '/'))
02832               enomem();
02833               
02834        if (strncmp(folderdir, NEWSHAREDSP, sizeof(NEWSHAREDSP)-1) == 0)
02835               switch (folderdir[sizeof(NEWSHAREDSP)-1]) {
02836               case 0:
02837                      verify_shared_index_file=1;
02838                      /* FALLTHRU */
02839               case '.':
02840                      break;
02841               default:
02842                      (*maildir_hier_cb)(INBOX, NULL, folderdir, INBOX);
02843                      return;
02844               }
02845        else
02846        {
02847               (*maildir_hier_cb)(INBOX, NULL, folderdir, INBOX);
02848               return;
02849        }
02850 
02851        index=NULL;
02852        indexfile=NULL;
02853        subhierarchy=NULL;
02854        p=folderdir;
02855 
02856        memset(&ph, 0, sizeof(ph));
02857 
02858        while ((index=maildir_shared_cache_read(index, indexfile,
02859                                           subhierarchy)) != NULL)
02860        {
02861               q=strchr(p, '.');
02862               if (!q)
02863                      break;
02864 
02865               p=q+1;
02866 
02867               if ((q=strchr(p, '.')) != NULL)
02868                      l=q-p;
02869               else
02870                      l=strlen(p);
02871 
02872               for (n=0; n<index->nrecords; n++)
02873               {
02874                      char *m=maildir_info_imapmunge(index->records[n].name);
02875 
02876                      if (!m)
02877                             continue;
02878 
02879                      if (strlen(m) == l &&
02880                          strncmp(m, p, l) == 0)
02881                      {
02882                             free(m);
02883                             break;
02884                      }
02885                      free(m);
02886               }
02887 
02888               if (n >= index->nrecords)
02889               {
02890                      index=NULL;
02891                      break;
02892               }
02893 
02894               index->indexfile.startingpos=index->records[n].offset;
02895               freeph(&ph);
02896               if (maildir_newshared_nextAt(&index->indexfile, &eof,
02897                                         &do_publicfolderlist_cb, &ph) ||
02898                   eof)
02899               {
02900                      index=NULL;
02901                      break;
02902               }
02903 
02904               if (ph.homedir)
02905               {
02906                      char *loc=maildir_location(ph.homedir,
02907                                              ph.maildir);
02908                      char *m_path;
02909                      char *m_inbox;
02910 
02911                      if (loc)
02912                      {
02913                             while (*p)
02914                             {
02915                                    if (*p == '.')
02916                                           break;
02917                                    ++p;
02918                             }
02919 
02920                             m_path=malloc(p-folderdir+1);
02921                             if (!m_path)
02922                                    enomem();
02923                             memcpy(m_path, folderdir, p-folderdir);
02924                             m_path[p-folderdir]=0;
02925 
02926                             m_inbox=malloc(strlen(m_path)+1+strlen(p));
02927                             if (!m_inbox)
02928                                    enomem();
02929 
02930                             strcat(strcpy(m_inbox, m_path), p);
02931 
02932                             savepath(m_path, loc);
02933                             (*maildir_hier_cb)(m_path, loc, m_inbox,
02934                                             m_path);
02935                             free(loc);
02936                             free(m_path);
02937                             free(m_inbox);
02938                      }
02939                      freeph(&ph);
02940                      return;
02941               }
02942 
02943               indexfile=ph.maildir;
02944               subhierarchy=index->records[n].name;
02945        }
02946 
02947        freeph(&ph);
02948 
02949        (*sharedhier_cb)(folderdir, index);
02950 }
02951 
02952 static void do_sharedhierlist(const char *folderdir,
02953                            struct maildir_shindex_cache *index)
02954 {
02955        const char *p;
02956        const char *q;
02957        size_t n;
02958        struct publicfolderlist_helper ph;
02959        const char *folders_img;
02960        const char *name_inbox;
02961        int eof;
02962        char *url, *url2;
02963 
02964        p=strrchr(folderdir, '.');
02965 
02966        if (p)
02967               ++p;
02968        else p=folderdir;
02969 
02970        folders_img=getarg("FOLDERSICON");
02971        name_inbox=getarg("INBOX");
02972 
02973        memset(&ph, 0, sizeof(ph));
02974 
02975               printf("<table width=\"100%%\" border=\"0\" cellpadding=\"2\" cellspacing=\"0\" class=\"folderlist\">\n"
02976               "<tr><td align=\"left\" "
02977               "class=\"folderparentdir\">%s&lt;&lt;&lt;&nbsp;",
02978               folders_img);
02979 
02980        if (strcmp(folderdir, NEWSHAREDSP) == 0)
02981        {
02982               printf("<a href=\"");
02983               output_scriptptrget();
02984               printf("&amp;form=folders&amp;folder=INBOX\">");
02985               print_safe(name_inbox);
02986               printf("</a>");
02987        }
02988        else
02989        {
02990               printf("<a href=\"");
02991               output_scriptptrget();
02992               printf("&amp;folderdir=");
02993               output_urlencoded(NEWSHAREDSP);
02994               printf("&amp;form=folders&amp;folder=INBOX\">%s</a>",
02995                      getarg("PUBLICFOLDERS"));
02996        }
02997 
02998        for (q=folderdir; q<p; )
02999        {
03000               const char *r;
03001               char *s;
03002 
03003               if (*q == '.')
03004               {
03005                      ++q;
03006                      continue;
03007               }
03008 
03009               for (r=q; *r; r++)
03010                      if (*r == '.')
03011                             break;
03012 
03013               if (q != folderdir)
03014               {
03015                      printf(".<a href=\"");
03016                      output_scriptptrget();
03017                      printf("&amp;form=folders&amp;folder=INBOX&amp;folderdir=");
03018 
03019 
03020                      s=malloc(r-folderdir+1);
03021                      if (!s)
03022                             enomem();
03023 
03024                      memcpy(s, folderdir, r-folderdir);
03025                      s[r-folderdir]=0;
03026 
03027                      output_urlencoded(s);
03028                      printf("\">");
03029                      free(s);
03030 
03031                      s=malloc(r-q+1);
03032                      if (!s)
03033                             enomem();
03034                      memcpy(s, q, r-q);
03035                      s[r-q]=0;
03036                      list_folder(s);
03037                      free(s);
03038                      printf("</a>");
03039               }
03040               q=r;
03041        }
03042 
03043        printf("</td></tr>\n");
03044 
03045 
03046        while (*q && *q != '.')
03047               ++q;
03048 
03049        url=malloc(q-folderdir+1);
03050        if (!url)
03051               enomem();
03052        memcpy(url, folderdir, q-folderdir);
03053        url[q-folderdir]=0;
03054 
03055        for (n=0; index && n<index->nrecords; n++)
03056        {
03057               freeph(&ph);
03058 
03059               if (n == 0)
03060                      index->indexfile.startingpos=0;
03061 
03062               if ((n == 0 ? &maildir_newshared_nextAt:
03063                    &maildir_newshared_next)(&index->indexfile, &eof,
03064                                          &do_publicfolderlist_cb, &ph) ||
03065                   eof)
03066               {
03067                      break;
03068               }
03069 
03070               if (ph.homedir)
03071               {
03072                      char *d=maildir_location(ph.homedir, ph.maildir);
03073 
03074                      if (d)
03075                      {
03076                             if (maildir_info_suppress(d))
03077                             {
03078                                    free(d);
03079                                    continue;
03080                             }
03081                             free(d);
03082                      }
03083               }
03084 
03085               printf("<tr class=\"foldersubdir\"><td align=\"left\">%s"
03086                      "&gt;&gt;&gt;&nbsp;<a href=\"", folders_img);
03087               output_scriptptrget();
03088               printf("&amp;form=folders&amp;folder=INBOX&amp;folderdir=");
03089 
03090               output_urlencoded(url);
03091 
03092               url2=maildir_info_imapmunge(ph.name);
03093 
03094               if (!url2)
03095                      enomem();
03096               printf(".");
03097               output_urlencoded(url2);
03098 
03099               printf("\">");
03100               list_folder(url2);
03101               free(url2);
03102               printf("</a></td></tr>\n");
03103        }
03104        free(url);
03105        freeph(&ph);
03106        printf("</table>\n");
03107 }
03108 
03109 static void do_folderlist(const char *inbox_pfix,
03110                        const char *homedir,
03111                        const char *folderdir,
03112                        const char *inbox_name)
03113 {
03114        const char    *name_inbox;
03115        const char    *name_drafts;
03116        const char    *name_sent;
03117        const char    *name_trash;
03118        const char    *folder_img;
03119        const char    *folders_img;
03120        const char    *unread_label;
03121        const char    *acl_img;
03122        char acl_buf[2];
03123        char   **folders;
03124        size_t i;
03125        unsigned nnew, nother;
03126        size_t folderdir_l;
03127 
03128        name_inbox=getarg("INBOX");
03129        name_drafts=getarg("DRAFTS");
03130        name_sent=getarg("SENT");
03131        name_trash=getarg("TRASH");
03132        folder_img=getarg("FOLDERICON");
03133        folders_img=getarg("FOLDERSICON");
03134        sqwebmail_folder=0;
03135        unread_label=getarg("UNREAD");
03136        acl_img=maildir_newshared_disabled ? NULL : getarg("ACLICON");
03137 
03138               printf("<table width=\"100%%\" border=\"0\" cellpadding=\"2\" cellspacing=\"0\" class=\"folderlist\">\n");
03139 
03140        maildir_listfolders(inbox_pfix, homedir, &folders);
03141 
03142        if (*folderdir && strcmp(folderdir, INBOX))
03143        {
03144               char *parentfolder;
03145               size_t i;
03146               char *q, *r;
03147               const char *c;
03148 
03149               if (strncmp(folderdir, SHARED ".", sizeof(SHARED)) == 0)
03150               {
03151                      for (c=folderdir; *c; c++)
03152                             if (*c == '.')
03153                                    break;
03154 
03155                      r=malloc(strlen(inbox_pfix)+strlen(c)+1);
03156                      if (!r)
03157                             enomem();
03158                      strcat(strcpy(r, inbox_pfix), c);
03159 
03160                      parentfolder=get_parent_folder(r);
03161                      free(r);
03162               }
03163               else
03164                      parentfolder=get_parent_folder(folderdir);
03165 
03166               for (q=parentfolder; *q; q++)
03167                      if (*q == '.')
03168                             break;
03169 
03170               printf("<tr><td align=\"left\" colspan=\"2\" class=\"folderparentdir\">%s", folders_img);
03171               printf("&lt;&lt;&lt;&nbsp;");
03172 
03173 #if 0
03174               printf("<a href=\"");
03175               output_scriptptrget();
03176               printf("&amp;folderdir=");
03177               output_urlencoded(inbox_pfix);
03178               printf("&amp;form=folders&amp;folder=INBOX\">");
03179               print_safe(inbox_name);
03180               printf("</a>");
03181 #endif
03182 
03183               i=0;
03184               while (parentfolder[i])
03185               {
03186               char   *p=strchr(parentfolder+i, '.');
03187               int    c;
03188 
03189                      if (!p)       p=parentfolder+strlen(parentfolder);
03190                      c= *p;
03191                      *p=0;
03192 
03193                      if (strchr(parentfolder, '.'))
03194                             printf(".");
03195                      printf("<a href=\"");
03196                      output_scriptptrget();
03197                      printf("&amp;form=folders&amp;folder=INBOX&amp;folderdir=");
03198                      output_urlencoded(parentfolder);
03199                      printf("\">");
03200                      if (strcmp(parentfolder, NEWSHAREDSP) == 0)
03201                             printf("%s", getarg("PUBLICFOLDERS"));
03202                      else
03203                             list_folder_xlate(parentfolder,
03204                                             parentfolder+i,
03205                                             name_inbox,
03206                                             name_drafts,
03207                                             name_sent,
03208                                             name_trash);
03209                      printf("</a>");
03210                      if ( (*p=c) != 0)    ++p;
03211                      i=p-parentfolder;
03212               }
03213               printf("</td></tr>\n");
03214               free(parentfolder);
03215        }
03216        else if (strcmp(inbox_pfix, INBOX))
03217        {
03218               size_t i;
03219               char *p;
03220               char *q;
03221 
03222               printf("<tr><td align=\"left\" colspan=\"2\" class=\"folderparentdir\">%s&lt;&lt;&lt;&nbsp;", folders_img);
03223 
03224               p=strdup(inbox_pfix);
03225               if (!p)
03226                      enomem();
03227 
03228               if ((q=strrchr(p, '.')) != 0)
03229                      *q=0;
03230 
03231               for (i=0; p[i]; )
03232               {
03233                      size_t j;
03234                      char save_ch;
03235 
03236                      for (j=i; p[j]; j++)
03237                             if (p[j] == '.')
03238                                    break;
03239 
03240 
03241                      save_ch=p[j];
03242                      p[j]=0;
03243 
03244                      if (i)
03245                             printf(".");
03246 
03247                      printf("<a href=\"");
03248                      output_scriptptrget();
03249                      printf("&amp;form=folders&amp;folder=INBOX&amp;folderdir=");
03250                      output_urlencoded(p);
03251                      printf("\">");
03252 
03253                      if (strcmp(p, NEWSHAREDSP) == 0)
03254                             printf("%s", getarg("PUBLICFOLDERS"));
03255                      else
03256                             list_folder(p+i);
03257                      printf("</a>");
03258 
03259                      p[j]=save_ch;
03260 
03261                      if (save_ch)
03262                             ++j;
03263                      i=j;
03264               }
03265               printf("</td></tr>\n");
03266               free(p);
03267        }
03268 
03269 
03270        if (!folderdir || strchr(folderdir, '.') == 0)
03271        {
03272               folderdir=inbox_pfix;
03273        }
03274 
03275        folderdir_l=strlen(folderdir);
03276 
03277        for (i=0; folders[i]; i++)
03278        {
03279               const  char *p;
03280               const  char *shortname=folders[i];
03281 
03282               size_t j;
03283               const char *pfix;
03284               int isunsubscribed=0;
03285               const char    *img=folder_img;
03286 
03287               pfix="&gt;&gt;&gt;";
03288 
03289               if (strncmp(shortname, SHARED ".",
03290                          sizeof(SHARED)) == 0)
03291               {
03292                      char   *dir;
03293                      struct stat   stat_buf;
03294 
03295                      pfix="+++";
03296 
03297                      dir=maildir_shareddir(".",
03298                                          shortname+sizeof(SHARED));
03299                      if (!dir)     continue;
03300                      if (stat(dir, &stat_buf))
03301                             isunsubscribed=1;
03302                      free(dir);
03303               }
03304 
03305               if (strcmp(shortname, inbox_name) == 0 &&
03306                   strcmp(folderdir, inbox_name) == 0)
03307               {
03308                      /* List INBOX at the top level */
03309 
03310                      strcpy(acl_buf, ACL_LOOKUP);
03311                      acl_computeRightsOnFolder(shortname, acl_buf);
03312                      if (acl_buf[0] == 0)
03313                             continue;
03314               }
03315               else
03316               {
03317                      if (strcmp(folderdir, INBOX) == 0 &&
03318                          strncmp(shortname, SHARED ".", sizeof(SHARED)) == 0)
03319                      {
03320                             shortname += sizeof(SHARED);
03321                      }
03322                      else
03323                      {
03324                             if (memcmp(shortname, folderdir, folderdir_l) ||
03325                                 shortname[folderdir_l] != '.')
03326                             {
03327                                    continue;
03328                             }
03329 
03330                             strcpy(acl_buf, ACL_LOOKUP);
03331                             acl_computeRightsOnFolder(shortname, acl_buf);
03332                             if (acl_buf[0] == 0)
03333                                    continue;
03334 
03335                             shortname += folderdir_l;
03336                             ++shortname;
03337                      }
03338 
03339                      if ((p=strchr(shortname, '.')) != 0)
03340                      {
03341                             char *s;
03342                             char   *t;
03343                             unsigned tot_nnew, tot_nother;
03344 
03345                             s=malloc(p-folders[i]+1);
03346                             if (!s)
03347                                    enomem();
03348                             memcpy(s, folders[i], p-folders[i]);
03349                             s[p-folders[i]]=0;
03350 
03351                             printf("<tr class=\"foldersubdir\"><td align=\"left\">");
03352                             if (acl_img)
03353                             {
03354                                    printf("<a href=\"");
03355                                    output_scriptptrget();
03356                                    printf("&amp;form=acl&amp;folder=");
03357                                    output_urlencoded(s);
03358                                    printf("\">%s</a>&nbsp;", acl_img);
03359                             }
03360                             printf("%s%s&nbsp;<a href=\"",
03361                                    folders_img, pfix);
03362 
03363                             output_scriptptrget();
03364                             printf("&amp;form=folders&amp;folder=INBOX&amp;folderdir=");
03365                             output_urlencoded(s);
03366                             printf("\">");
03367                             free(s);
03368 
03369                             t=malloc(p-shortname+1);
03370                             if (!t)       enomem();
03371                             memcpy(t, shortname, p-shortname);
03372                             t[p-shortname]=0;
03373                             list_folder_xlate(folders[i],
03374                                             t,
03375                                             name_inbox,
03376                                             name_drafts,
03377                                             name_sent,
03378                                             name_trash);
03379                             free(t);
03380                             printf("</a>");
03381 
03382                             tot_nnew=0;
03383                             tot_nother=0;
03384 
03385                             j=i;
03386                             while (folders[j] && memcmp(folders[j], folders[i],
03387                                                      p-folders[i]+1) == 0)
03388                             {
03389                                    strcpy(acl_buf, ACL_LOOKUP);
03390                                    acl_computeRightsOnFolder(folders[j],
03391                                                           acl_buf);
03392                                    if (acl_buf[0] == 0)
03393                                           continue;
03394 
03395                                    maildir_count(folders[j], &nnew, &nother);
03396                                    ++j;
03397                                    tot_nnew += nnew;
03398                                    tot_nother += nother;
03399                             }
03400                             i=j-1;
03401                             if (tot_nnew)
03402                             {
03403                                    printf(" <span class=\"subfolderlistunread\">");
03404                                    printf(unread_label, tot_nnew);
03405                                    printf("</span>");
03406                             }
03407                             printf("</td><td align=\"right\" valign=\"top\"><span class=\"subfoldercnt\">%d</span>&nbsp;&nbsp;</td></tr>\n\n",
03408                                    tot_nnew + tot_nother);
03409                             continue;
03410                      }
03411               }
03412 
03413               nnew=0;
03414               nother=0;
03415 
03416               if (!isunsubscribed)
03417                      maildir_count(folders[i], &nnew, &nother);
03418 
03419               printf("<tr%s><td align=\"left\" valign=\"top\">",
03420                      isunsubscribed ? " class=\"folderunsubscribed\"":"");
03421 
03422               if (acl_img)
03423               {
03424                      printf("<a href=\"");
03425                      output_scriptptrget();
03426                      printf("&amp;form=acl&amp;folder=");
03427                      output_urlencoded(folders[i]);
03428                      printf("\">%s</a>&nbsp", acl_img);
03429               }
03430 
03431               printf("%s&nbsp;<input type=\"radio\" name=\"DELETE\" value=\"", img);
03432               output_attrencoded(folders[i]);
03433               printf("\" />&nbsp;");
03434               if (!isunsubscribed)
03435               {
03436                      printf("<a class=\"folderlink\" href=\"");
03437                      output_scriptptrget();
03438                      printf("&amp;form=folder&amp;folder=");
03439                      output_urlencoded(folders[i]);
03440                      printf("\">");
03441               }
03442 
03443               list_folder_xlate(folders[i],
03444                               strcmp(folders[i], inbox_name) == 0
03445                               ? INBOX:shortname,
03446                               name_inbox,
03447                               name_drafts,
03448                               name_sent,
03449                               name_trash);
03450               if (!isunsubscribed)
03451                      printf("</a>");
03452               if (nnew)
03453               {
03454                      printf(" <span class=\"folderlistunread\">");
03455                      printf(unread_label, nnew);
03456                      printf("</span>");
03457               }
03458               printf("</td><td align=\"right\" valign=\"top\">");
03459 
03460               if (!isunsubscribed)
03461               {
03462                      printf("<span class=\"foldercnt\">%d</span>&nbsp;&nbsp;",
03463                             nnew + nother);
03464               }
03465               else
03466               printf("&nbsp;\n");
03467               printf("</td></tr>\n\n");
03468        }
03469        maildir_freefolders(&folders);
03470 
03471        if (strcmp(folderdir, INBOX) == 0 && !maildir_newshared_disabled)
03472        {
03473               char *sp=cgiurlencode(NEWSHAREDSP);
03474 
03475               printf("<tr class=\"foldersubdir\"><td align=\"left\">%s&gt;&gt;&gt;&nbsp;<a href=\"", folders_img);
03476               output_scriptptrget();
03477               printf("&amp;form=folders&amp;folder=INBOX&amp;folderdir="
03478                      "%s\">%s</a>"
03479                      "</td><td>&nbsp;</td></tr>\n\n",
03480                      sp,
03481                      getarg("PUBLICFOLDERS"));
03482               free(sp);
03483        }
03484        printf("</table>\n");
03485 }
03486 
03487 void folder_list2()
03488 {
03489        if (folder_err_msg)
03490        {
03491               printf("%s\n", folder_err_msg);
03492        }
03493 }
03494 
03495 static void folder_rename_dest_fake(const char *dummy1,
03496                                 struct maildir_shindex_cache *dummy2);
03497 static void folder_rename_dest_real(const char *inbox_pfix,
03498                                 const char *homedir,
03499                                 const char *cur_folder,
03500                                 const char *inbox_name);
03501 
03502 void folder_rename_list()
03503 {
03504        parse_hierarchy(cgi("folderdir"), folder_rename_dest_real,
03505                      folder_rename_dest_fake);
03506 }
03507 
03508 static void folder_rename_dest_fake(const char *dummy1,
03509                                 struct maildir_shindex_cache *dummy2)
03510 {
03511 }
03512 
03513 static void folder_rename_dest_real(const char *inbox_pfix,
03514                                 const char *homedir,
03515                                 const char *cur_folder,
03516                                 const char *inbox_name)
03517 {
03518        char   **folders;
03519        int    i;
03520        size_t pl=strlen(inbox_pfix);
03521 
03522        printf("<select name=\"renametofolder\">\n");
03523        printf("<option value=\"%s.\">", inbox_pfix);
03524        printf("( ... )");
03525        printf("</option>\n");
03526 
03527        maildir_listfolders(inbox_pfix, homedir, &folders);
03528        for (i=0; folders[i]; i++)
03529        {
03530               const char *p=folders[i];
03531               char   *q;
03532               size_t ql;
03533               char acl_buf[2];
03534 
03535               if (strncmp(p, inbox_pfix, pl) == 0)
03536                      switch (p[pl]) {
03537                      case '.':
03538                             break;
03539                      default:
03540                             continue;
03541                      }
03542               else
03543                      continue;
03544 
03545               p += pl+1;
03546 
03547               p=strrchr(p, '.');
03548               if (!p)       continue;
03549               q=malloc(p-folders[i]+1);
03550               if (!q)       enomem();
03551               memcpy(q, folders[i], p-folders[i]);
03552               q[p-folders[i]]=0;
03553               strcpy(acl_buf, ACL_CREATE);
03554               acl_computeRightsOnFolder(q, acl_buf);
03555               if (acl_buf[0])
03556               {
03557                      printf("<option value=\"");
03558                      output_attrencoded(q);
03559                      printf(".\"%s>",
03560                             strcmp(q, cgi("folderdir")) == 0
03561                             ? " selected='selected'":"");
03562                      list_folder(strchr(q, '.')+1);
03563                      printf(".</option>\n");
03564               }
03565               ql=strlen(q);
03566               while (folders[++i])
03567               {
03568                      if (memcmp(folders[i], q, ql) ||
03569                             folders[i][ql] != '.' ||
03570                             strchr(folders[i]+ql+1, '.'))      break;
03571               }
03572               --i;
03573               free(q);
03574        }
03575        maildir_freefolders(&folders);
03576        printf("</select>\n");
03577 }
03578 
03579 void folder_download(const char *folder, size_t pos, const char *mimeid)
03580 {
03581        char   *filename;
03582        FILE *fp=NULL;
03583        int    fd;
03584 
03585        filename=get_msgfilename(folder, &pos);
03586 
03587        fd=maildir_semisafeopen(filename, O_RDONLY, 0);
03588        if (fd >= 0)
03589        {
03590               if ((fp=fdopen(fd, "r")) == 0)
03591                      close(fd);
03592        }
03593 
03594        if (!fp)
03595        {
03596               free(filename);
03597               error("Message not found.");
03598               return;
03599        }
03600        free(filename);
03601 
03602        cginocache();
03603        msg2html_download(fp, mimeid, *cgi("download") == '1',
03604                        sqwebmail_content_charset);
03605 
03606        fclose(fp);
03607 }
03608 
03609 void folder_showtransfer()
03610 {
03611        const char    *deletelab, *purgelab, *movelab, *golab;
03612 
03613        deletelab=getarg("DELETE");
03614        purgelab=getarg("PURGE");
03615        movelab=getarg("ORMOVETO");
03616        golab=getarg("GO");
03617        folder_inbox=getarg("INBOX");
03618        folder_drafts=getarg("DRAFTS");
03619        folder_trash=getarg("TRASH");
03620        folder_sent=getarg("SENT");
03621 
03622        printf("<input type=\"hidden\" name=\"pos\" value=\"%s\" />", cgi("pos"));
03623 
03624        if (*cgi("search"))
03625        {
03626               printf("<input type=\"hidden\" name=\"search\" value=\"1\" />"
03627                      "<input type=\"hidden\" name=\"" SEARCHRESFILENAME
03628                      "\" value=\"");
03629               output_attrencoded(cgi(SEARCHRESFILENAME));
03630               printf("\" />");
03631        }
03632 
03633        if ((strcmp(sqwebmail_folder, INBOX "." TRASH) == 0) && (strlen(getarg("PURGEALL"))))
03634            printf("<input type=\"submit\" name=\"cmdpurgeall\" value=\"%s\" onclick=\"javascript: return deleteAll();\" />", 
03635               getarg("PURGEALL"));
03636        printf("<input type=\"submit\" name=\"cmddel\" value=\"%s\" />%s<select name=\"moveto\">",
03637               strcmp(sqwebmail_folder, INBOX "." TRASH) == 0
03638               ? purgelab:deletelab,
03639               movelab);
03640 
03641        show_transfer_dest(sqwebmail_folder);
03642        printf("</select><input type=\"submit\" name=\"cmdmove\" value=\"%s\" />\n",
03643               golab);
03644 }
03645 
03646 void folder_showquota()
03647 {
03648        const char    *quotamsg;
03649        struct maildirsize quotainfo;
03650 
03651        quotamsg=getarg("QUOTAUSAGE");
03652 
03653        if (maildir_openquotafile(&quotainfo, "."))
03654               return;
03655 
03656        if (quotainfo.quota.nmessages != 0 ||
03657            quotainfo.quota.nbytes != 0)
03658               printf(quotamsg, maildir_readquota(&quotainfo));
03659 
03660        maildir_closequotafile(&quotainfo);
03661 }
03662 
03663 void
03664 folder_cleanup()
03665 {
03666        msg_purgelab=0;
03667        msg_folderlab=0;
03668        folder_drafts=0;
03669        folder_inbox=0;
03670        folder_sent=0;
03671        folder_trash=0;
03672        msg_forwardattlab=0;
03673        msg_forwardlab=0;
03674        msg_fullheaderlab=0;
03675        msg_golab=0;
03676        msg_movetolab=0;
03677        msg_nextlab=0;
03678        msg_prevlab=0;
03679        msg_deletelab=0;
03680        msg_posfile=0;
03681        msg_replyalllab=0;
03682        msg_replylistlab=0;
03683        msg_replylab=0;
03684        folder_err_msg=0;
03685        msg_msglab=0;
03686        msg_add=0;
03687 
03688        msg_type=0;
03689        initnextprevcnt=0;
03690        msg_hasprev=0;
03691        msg_hasnext=0;
03692        msg_pos=0;
03693        msg_count=0;
03694 }
03695 
03696 
03697 /*
03698 ** Unicode-aware truncation of text at a specified column, if text length
03699 ** exceeds the given # of characters.
03700 */
03701 
03702 static char *truncate_at(const char *str,
03703                       const char *charset,
03704                       size_t ncols)
03705 {
03706        unicode_char *uc;
03707        size_t n;
03708        size_t cols, tp=0;
03709        char *retbuf;
03710        libmail_u_convert_handle_t h;
03711        int chopped=0;
03712 
03713        if (!str)
03714               return NULL;
03715 
03716        h=libmail_u_convert_tou_init("utf-8", &uc, &n, 1);
03717 
03718        if (h)
03719        {
03720               libmail_u_convert(h, str, strlen(str));
03721               libmail_u_convert_deinit(h, NULL);
03722        }
03723        else
03724        {
03725               uc=NULL;
03726        }
03727 
03728        if (!uc)
03729               return NULL;
03730 
03731        for (cols=0, n=0; uc[n]; n++) {
03732 
03733               cols += unicode_wcwidth(uc[n]);
03734 
03735               tp = n;
03736               if (cols > ncols-3 && n > 0 &&
03737                   unicode_grapheme_break(uc[n-1], uc[n]))
03738               {
03739                      chopped=1;
03740                      break;
03741               }
03742               ++tp;
03743        }
03744 
03745        if (chopped)
03746        {
03747               uc = realloc(uc, sizeof(unicode_char) * (tp+4));
03748               if (uc == 0) enomem();
03749               uc[tp]='.';
03750               uc[tp+1]='.';
03751               uc[tp+2]='.';
03752               tp += 3;
03753        }
03754 
03755        h=libmail_u_convert_fromu_init(charset, &retbuf, &cols, 1);
03756 
03757        if (h)
03758        {
03759               libmail_u_convert_uc(h, uc, tp);
03760               libmail_u_convert_deinit(h, NULL);
03761        }
03762        else
03763        {
03764               retbuf=NULL;
03765        }
03766 
03767        free(uc);
03768        return retbuf;
03769 }