more sorting out of the headers
[citadel.git] / webcit / messages.c
index db7638b51a254bf399b463e6def3ee8809a7685b..a98d702572aa500b1d83ccdd64776d52d31db557 100644 (file)
@@ -1,10 +1,12 @@
 /*
  * Functions which deal with the fetching and displaying of messages.
  *
- * Copyright (c) 1996-2018 by the citadel.org team
+ * Copyright (c) 1996-2020 by the citadel.org team
  *
- * This program is open source software.  You can redistribute it and/or
- * modify it under the terms of the GNU General Public License, version 3.
+ * This program is open source software.  We call it open source, not
+ * free software, because Richard Stallman is a communist and an asshole.
+ *
+ * The program is licensed under the General Public License, version 3.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -25,12 +27,7 @@ int dbg_analyze_msg = 0;
 #define SENDER_COL_WIDTH_PCT           30      /* Mailbox view column width */
 #define DATE_PLUS_BUTTONS_WIDTH_PCT    20      /* Mailbox view column width */
 
-void jsonMessageListHdr(void);
-
-void display_enter(void);
-
-void fixview()
-{
+void fixview() {
        /* workaround for json listview; its not useable directly */
        if (WC->CurRoom.view == VIEW_JSON_LIST) {
                StrBuf *View = NewStrBuf();
@@ -38,10 +35,9 @@ void fixview()
                putbstr("view", View);;
        }
 }
-int load_message(message_summary *Msg, 
-                StrBuf *FoundCharset,
-                StrBuf **Error)
-{
+
+
+int load_message(message_summary *Msg, StrBuf *FoundCharset, StrBuf **Error) {
        StrBuf *Buf;
        StrBuf *HdrToken;
        char buf[SIZ];
@@ -155,16 +151,14 @@ int load_message(message_summary *Msg,
 }
 
 
-
 /*
- * I wanna SEE that message!
+ * Display a message to the user
  *
  * msgnum              Message number to display
  * printable_view      Nonzero to display a printable view
  * section             Optional for encapsulated message/rfc822 submessage
  */
-int read_message(StrBuf *Target, const char *tmpl, long tmpllen, long msgnum, const StrBuf *PartNum, const StrBuf **OutMime, WCTemplputParams *TP) 
-{
+int read_message(StrBuf *Target, const char *tmpl, long tmpllen, long msgnum, const StrBuf *PartNum, const StrBuf **OutMime, WCTemplputParams *TP) {
        StrBuf *Buf;
        StrBuf *FoundCharset;
        HashPos  *it;
@@ -248,9 +242,7 @@ int read_message(StrBuf *Target, const char *tmpl, long tmpllen, long msgnum, co
 }
 
 
-long
-HttpStatus(long CitadelStatus)
-{
+long HttpStatus(long CitadelStatus) {
        long httpstatus = 502;
        
        switch (MAJORCODE(CitadelStatus))
@@ -316,12 +308,12 @@ HttpStatus(long CitadelStatus)
        return httpstatus;
 }
 
+
 /*
  * Unadorned HTML output of an individual message, suitable
  * for placing in a hidden iframe, for printing, or whatever
  */
-void handle_one_message(void) 
-{
+void handle_one_message(void) {
        long CitStatus = ERROR + NOT_HERE;
        int CopyMessage = 0;
        const StrBuf *Destination;
@@ -333,7 +325,6 @@ void handle_one_message(void)
        StrBuf *CmdBuf = NULL;
        const char *pMsg;
 
-
        pMsg = strchr(ChrPtr(WCC->Hdr->HR.ReqLine), '/');
        if (pMsg == NULL) {
                HttpStatus(CitStatus);
@@ -452,6 +443,7 @@ void print_message(void) {
        wDumpContent(0);
 }
 
+
 /*
  * Display a message's headers
  */
@@ -480,7 +472,6 @@ void display_headers(void) {
 }
 
 
-
 /*
  * load message pointers from the server for a "read messages" operation
  *
@@ -602,15 +593,13 @@ int load_msg_ptrs(const char *servcmd,
 }
 
 
-
-/**
- * \brief sets FlagToSet for each of ScanMe that appears in MatchMSet
- * \param ScanMe List of BasicMsgStruct to be searched it MatchSet
- * \param MatchMSet MSet we want to flag
- * \param FlagToSet Flag to set on each BasicMsgStruct->Flags if in MSet
+/*
+ * sets FlagToSet for each of ScanMe that appears in MatchMSet
+ * ScanMe:      List of BasicMsgStruct to be searched it MatchSet
+ * MatchMSet:   MSet we want to flag
+ * FlagToSet:   Flag to set on each BasicMsgStruct->Flags if in MSet
  */
-long SetFlagsFromMSet(HashList *ScanMe, MSet *MatchMSet, int FlagToSet, int Reverse)
-{
+long SetFlagsFromMSet(HashList *ScanMe, MSet *MatchMSet, int FlagToSet, int Reverse) {
        const char *HashKey;
        long HKLen;
        long count = 0;
@@ -636,8 +625,7 @@ long SetFlagsFromMSet(HashList *ScanMe, MSet *MatchMSet, int FlagToSet, int Reve
 }
 
 
-long load_seen_flags(void)
-{
+long load_seen_flags(void) {
        long count = 0;
        StrBuf *OldMsg;
        wcsession *WCC = WC;
@@ -687,8 +675,7 @@ typedef struct _RoomRenderer{
  *
  * Set oper to "readnew" or "readold" or "readfwd" or "headers" or "readgt" or "readlt" or "do_search"
  */
-void readloop(long oper, eCustomRoomRenderer ForceRenderer)
-{
+void readloop(long oper, eCustomRoomRenderer ForceRenderer) {
        RoomRenderer *ViewMsg;
        void *vViewMsg;
        void *vMsg;
@@ -923,7 +910,7 @@ void post_mime_to_server(void) {
                serv_puts("Content-type: text/plain; charset=utf-8");
                serv_puts("Content-Transfer-Encoding: quoted-printable");
                serv_puts("");
-               txtmail = html_to_ascii(bstr("msgtext"), 0, 80, 0);
+               txtmail = html_to_ascii(bstr("msgtext"), 0, 80);
                Buf = NewStrBufPlain(txtmail, -1);
                free(txtmail);
 
@@ -989,8 +976,7 @@ void post_mime_to_server(void) {
  * discarded.  This prevents the accidental double-saving of the same message
  * if the user happens to click the browser "back" button.
  */
-void post_message(void)
-{
+void post_message(void) {
        StrBuf *UserName;
        StrBuf *EmailAddress;
        StrBuf *EncBuf;
@@ -1335,12 +1321,12 @@ typedef enum _eReplyToNodes {
        eReplyAll,
        eForward
 }eReplyToNodes;
-       
+
+
 /*
  * display the message entry screen
  */
-void display_enter(void)
-{
+void display_enter(void) {
        const char *ReplyingModeStr;
        eReplyToNodes ReplyMode = eReply;
        StrBuf *Line;
@@ -1418,15 +1404,15 @@ void display_enter(void)
                return;
        }
 
-
        ReplyingModeStr = bstr("replying_mode");
-       if (ReplyingModeStr != NULL) for (i = 0; i < 3; i++) {
+       if (ReplyingModeStr != NULL) {
+               for (i = 0; i < 3; i++) {
                        if (strcmp(ReplyingModeStr, ReplyToModeStrings[i]) == 0) {
                                ReplyMode = (eReplyToNodes) i;
                                break;
                        }
                }
-               
+       }
 
        /*
         * If the "replying_to" variable is set, it refers to a message
@@ -1438,26 +1424,19 @@ void display_enter(void)
                StrBuf *wefw = NULL;
                StrBuf *msgn = NULL;
                StrBuf *from = NULL;
-               StrBuf *node = NULL;
                StrBuf *rfca = NULL;
                StrBuf *rcpt = NULL;
                StrBuf *cccc = NULL;
                StrBuf *replyto = NULL;
                StrBuf *nvto = NULL;
+               int message_originated_locally = 0;
                serv_printf("MSG0 %ld|1", replying_to); 
 
                StrBuf_ServGetln(Line);
                if (GetServerStatusMsg(Line, NULL, 0, 0) == 1)
-                       while (len = StrBuf_ServGetln(Line),
-                              (len >= 0) && 
-                              ((len != 3)  ||
-                               strcmp(ChrPtr(Line), "000")))
-                       {
+                       while (len = StrBuf_ServGetln(Line), (len >= 0) && ((len != 3) || strcmp(ChrPtr(Line), "000"))) {
                                eMessageField which;
-                               if ((StrLength(Line) > 4) && 
-                                   (ChrPtr(Line)[4] == '=') &&
-                                   GetFieldFromMnemonic(&which, ChrPtr(Line)))
-                                       switch (which) {
+                               if ((StrLength(Line) > 4) && (ChrPtr(Line)[4] == '=') && GetFieldFromMnemonic(&which, ChrPtr(Line))) switch (which) {
                                        case eMsgSubject: {
                                                StrBuf *subj = NewStrBuf();
                                                StrBuf *FlatSubject;
@@ -1482,6 +1461,11 @@ void display_enter(void)
                                        }
                                                break;
 
+                                       case eIsLocal: {
+                                               message_originated_locally = 1;
+                                               break;
+                                       }
+
                                        case eWeferences:
                                        {
                                                int rrtok;
@@ -1517,20 +1501,12 @@ void display_enter(void)
                                                }
                                                break;
                                        }
-                               
                                        case eRecipient:
                                                rcpt = NewStrBufPlain(ChrPtr(Line) + 5, StrLength(Line) - 5);
                                                break;
-                       
-                               
                                        case eCarbonCopY:
                                                cccc = NewStrBufPlain(ChrPtr(Line) + 5, StrLength(Line) - 5);
                                                break;
-
-                               
-                                       case eNodeName:
-                                               node = NewStrBufPlain(ChrPtr(Line) + 5, StrLength(Line) - 5);
-                                               break;
                                        case eReplyTo:
                                                replyto = NewStrBufPlain(ChrPtr(Line) + 5, StrLength(Line) - 5);
                                                break;
@@ -1548,11 +1524,9 @@ void display_enter(void)
                                                putbstr("nvto", nvto);
                                                break;
                                        case eXclusivID:
-                                       case eHumanNode:
                                        case eJournal:
                                        case eListID:
                                        case eMesageText:
-                                       case eOriginalRoom:
                                        case eMessagePath:
                                        case eSpecialField:
                                        case eTimestamp:
@@ -1560,7 +1534,6 @@ void display_enter(void)
                                        case eFormatType:
                                        case eMessagePart:
                                        case eSubFolder:
-                                       case ePevious:
                                        case eLastHeader:
                                                break;
 
@@ -1587,13 +1560,14 @@ void display_enter(void)
                /*
                 * If this is a Reply or a ReplyAll, copy the sender's email into the To: field
                 */
-               if ((ReplyMode == eReply) || (ReplyMode == eReplyAll))
-               {
+               if ((ReplyMode == eReply) || (ReplyMode == eReplyAll)) {
                        StrBuf *to_rcpt;
+
                        if ((StrLength(replyto) > 0) && (ReplyMode == eReplyAll)) {
                                to_rcpt = NewStrBuf();
                                StrBufAppendBuf(to_rcpt, replyto, 0);
                        }
+
                        else if (StrLength(rfca) > 0) {
                                to_rcpt = NewStrBuf();
                                StrBufAppendBuf(to_rcpt, from, 0);
@@ -1601,15 +1575,10 @@ void display_enter(void)
                                StrBufAppendBuf(to_rcpt, rfca, 0);
                                StrBufAppendBufPlain(to_rcpt, HKEY(">"), 0);
                        }
+
                        else {
                                to_rcpt =  from;
                                from = NULL;
-                               if (    (StrLength(node) > 0)
-                                       && (strcasecmp(ChrPtr(node), ChrPtr(WCC->serv_info->serv_nodename)))
-                               ) {
-                                       StrBufAppendBufPlain(to_rcpt, HKEY(" @ "), 0);
-                                       StrBufAppendBuf(to_rcpt, node, 0);
-                               }
                        }
                        PutBstr(HKEY("recp"), to_rcpt);
                }
@@ -1617,37 +1586,48 @@ void display_enter(void)
                /*
                 * Only if this is a ReplyAll, copy all recipients into the Cc: field
                 */
-               if (ReplyMode == eReplyAll)
-               {
+               if (ReplyMode == eReplyAll) {
                        StrBuf *cc_rcpt = rcpt;
                        rcpt = NULL;
-                       if ((StrLength(cccc) > 0) && (StrLength(replyto) == 0))
-                       {
+                       if ((StrLength(cccc) > 0) && (StrLength(replyto) == 0)) {
                                if (cc_rcpt != NULL)  {
                                        StrBufAppendPrintf(cc_rcpt, ", ");
                                        StrBufAppendBuf(cc_rcpt, cccc, 0);
-                               } else {
+                               }
+                               else {
                                        cc_rcpt = cccc;
                                        cccc = NULL;
                                }
                        }
-                       if (cc_rcpt != NULL)
+                       if (cc_rcpt != NULL) {
                                PutBstr(HKEY("cc"), cc_rcpt);
+                       }
                }
+
+               // FOOFOO
+               syslog(LOG_DEBUG, "wefw = %s", ChrPtr(wefw));
+               syslog(LOG_DEBUG, "msgn = %s", ChrPtr(msgn));
+               syslog(LOG_DEBUG, "from = %s", ChrPtr(from));
+               syslog(LOG_DEBUG, "rfca = %s", ChrPtr(rfca));
+               syslog(LOG_DEBUG, "rcpt = %s", ChrPtr(rcpt));
+               syslog(LOG_DEBUG, "cccc = %s", ChrPtr(cccc));
+               syslog(LOG_DEBUG, "replyto = %s", ChrPtr(replyto));
+               syslog(LOG_DEBUG, "nvto = %s", ChrPtr(nvto));
+               syslog(LOG_DEBUG, "local = %d" , message_originated_locally);
+
                FreeStrBuf(&wefw);
                FreeStrBuf(&msgn);
                FreeStrBuf(&from);
-               FreeStrBuf(&node);
                FreeStrBuf(&rfca);
                FreeStrBuf(&rcpt);
                FreeStrBuf(&cccc);
        }
        FreeStrBuf(&Line);
+
        /*
         * Otherwise proceed normally.
         * Do a custom room banner with no navbar...
         */
-
        if (recipient_required) {
                const StrBuf *Recp = NULL; 
                const StrBuf *Cc = NULL;
@@ -1712,11 +1692,11 @@ void display_enter(void)
        return;
 }
 
+
 /*
  * delete a message
  */
-void delete_msg(void)
-{
+void delete_msg(void) {
        long msgid;
        StrBuf *Line;
        
@@ -1741,8 +1721,7 @@ void delete_msg(void)
 /*
  * move a message to another room
  */
-void move_msg(void)
-{
+void move_msg(void) {
        long msgid;
 
        msgid = lbstr("msgid");
@@ -1763,7 +1742,6 @@ void move_msg(void)
 }
 
 
-
 /*
  * Generic function to output an arbitrary MIME attachment from
  * message being composed
@@ -1772,8 +1750,7 @@ void move_msg(void)
  * filename            Fake filename to give
  * force_download      Nonzero to force set the Content-Type: header to "application/octet-stream"
  */
-void postpart(StrBuf *partnum, StrBuf *filename, int force_download)
-{
+void postpart(StrBuf *partnum, StrBuf *filename, int force_download) {
        void *vPart;
        StrBuf *content_type;
        wc_mime_attachment *part;
@@ -1808,98 +1785,66 @@ void postpart(StrBuf *partnum, StrBuf *filename, int force_download)
  * Generic function to output an arbitrary MIME part from an arbitrary
  * message number on the server.
  *
- * msgnum              Number of the item on the citadel server
- * partnum             The MIME part to be output
+ * msgnum              message number on the citadel server
+ * partnum             MIME part number to be output
  * force_download      Nonzero to force set the Content-Type: header to "application/octet-stream"
  */
-void mimepart(int force_download)
-{
-       int detect_mime = 0;
+void view_or_download_mimepart(int force_download) {
        long msgnum;
-       long ErrorDetail;
-       StrBuf *att;
-       wcsession *WCC = WC;
-       StrBuf *Buf;
        off_t bytes;
-       StrBuf *ContentType = NewStrBufPlain(HKEY("application/octet-stream"));
-       const char *CT;
+       StrBuf *Buf;
+       StrBuf *ContentType;
+       StrBuf *PartNum;
 
-       att = Buf = NewStrBuf();
-       msgnum = StrBufExtract_long(WCC->Hdr->HR.ReqLine, 0, '/');
-       StrBufExtract_token(att, WCC->Hdr->HR.ReqLine, 1, '/');
+       PartNum = NewStrBuf();
 
-       serv_printf("OPNA %ld|%s", msgnum, ChrPtr(att));
-       StrBuf_ServGetln(Buf);
-       if (GetServerStatus(Buf, &ErrorDetail) == 2) {
-               StrBufCutLeft(Buf, 4);
-               bytes = StrBufExtract_long(Buf, 0, '|');
-               StrBufExtract_token(ContentType, Buf, 3, '|');
-               CheckGZipCompressionAllowed (SKEY(ContentType));
-               if (force_download)
-               {
-                       FlushStrBuf(ContentType);
-                       detect_mime = 0;
-               }
-               else
-               {
-                       if (!strcasecmp(ChrPtr(ContentType), "application/octet-stream"))
-                       {
-                               StrBufExtract_token(Buf, WCC->Hdr->HR.ReqLine, 2, '/');
-                               CT = GuessMimeByFilename(SKEY(Buf));
-                               StrBufPlain(ContentType, CT, -1);
-                       }
-                       if (!strcasecmp(ChrPtr(ContentType), "application/octet-stream"))
-                       {
-                               detect_mime = 1;
-                       }
-               }
-               serv_read_binary_to_http(ContentType, bytes, 0, detect_mime);
-
-               serv_read_binary(WCC->WBuf, bytes, Buf);
-               serv_puts("CLOS");
-               StrBuf_ServGetln(Buf);
-               CT = ChrPtr(ContentType);
-       } else {
-               StrBufCutLeft(Buf, 4);
-               switch (ErrorDetail) {
-               default:
-               case ERROR + MESSAGE_NOT_FOUND:
-                       hprintf("HTTP/1.1 404 %s\n", ChrPtr(Buf));
-                       break;
-               case ERROR + NOT_LOGGED_IN:
-                       hprintf("HTTP/1.1 401 %s\n", ChrPtr(Buf));
-                       break;
+       msgnum = StrBufExtract_long(WC->Hdr->HR.ReqLine, 0, '/');
+       StrBufExtract_token(PartNum, WC->Hdr->HR.ReqLine, 1, '/');
 
-               case ERROR + HIGHER_ACCESS_REQUIRED:
-                       hprintf("HTTP/1.1 403 %s\n", ChrPtr(Buf));
-                       break;
-               case ERROR + INTERNAL_ERROR:
-               case ERROR + TOO_BIG:
-                       hprintf("HTTP/1.1 500 %s\n", ChrPtr(Buf));
-                       break;
-               }
+       Buf = NewStrBuf();
+       serv_printf("DLAT %ld|%s", msgnum, ChrPtr(PartNum));    // DLAT will return: 6XX length|-1|filename|cbtype|cbcharset
+       StrBuf_ServGetln(Buf);
+       FreeStrBuf(&PartNum);
 
-               hprintf("Pragma: no-cache\r\n"
+       if (GetServerStatus(Buf, NULL) != 6) {
+               FreeStrBuf(&Buf);
+               hprintf("HTTP/1.1 500 error\r\n"
+                       "Pragma: no-cache\r\n"
                        "Cache-Control: no-store\r\n"
                        "Expires: -1\r\n"
+                       "Content-Type: text/plain\r\n"
                );
-
-               hprintf("Content-Type: text/plain\r\n");
                begin_burst();
-               wc_printf(_("An error occurred while retrieving this part: %s\n"), 
-                       ChrPtr(Buf));
-               end_burst();
+               wc_printf(_("An error occurred while retrieving this part: %s\n"), "--");
+               return;
        }
-       FreeStrBuf(&ContentType);
+
+       StrBufCutLeft(Buf, 4);
+       bytes = StrBufExtract_long(Buf, 0, '|');
+
+       if (force_download) {
+               ContentType = NewStrBufPlain(HKEY("application/octet-stream"));
+       }
+       else {
+               ContentType = NewStrBuf();
+               StrBufExtract_token(ContentType, Buf, 3, '|');
+       }
+
        FreeStrBuf(&Buf);
+       Buf = NewStrBuf();
+       StrBuf_ServGetBLOBBuffered(Buf, bytes);
+
+       WC->WBuf = Buf;
+       Buf = NULL;
+       http_transmit_thing(ChrPtr(ContentType), 0);
+       FreeStrBuf(&ContentType);
 }
 
 
 /*
  * Read any MIME part of a message, from the server, into memory.
  */
-StrBuf *load_mimepart(long msgnum, char *partnum)
-{
+StrBuf *load_mimepart(long msgnum, char *partnum) {
        off_t bytes;
        StrBuf *Buf;
        
@@ -1920,15 +1865,14 @@ StrBuf *load_mimepart(long msgnum, char *partnum)
        }
 }
 
+
 /*
  * Read any MIME part of a message, from the server, into memory.
  */
-void MimeLoadData(wc_mime_attachment *Mime)
-{
+void MimeLoadData(wc_mime_attachment *Mime) {
        StrBuf *Buf;
        const char *Ptr;
        off_t bytes;
-       /* TODO: is there a chance the content type is different from the one we know? */
 
        serv_printf("DLAT %ld|%s", Mime->msgnum, ChrPtr(Mime->PartNum));
        Buf = NewStrBuf();
@@ -1940,26 +1884,28 @@ void MimeLoadData(wc_mime_attachment *Mime)
                if (Mime->Charset == NULL) Mime->Charset = NewStrBuf();
                StrBufExtract_NextToken(Mime->Charset, Buf, &Ptr, '|');
                
-               if (Mime->Data == NULL)
+               if (Mime->Data == NULL) {
                        Mime->Data = NewStrBufPlain(NULL, bytes);
+               }
                StrBuf_ServGetBLOBBuffered(Mime->Data, bytes);
        }
        else {
                FlushStrBuf(Mime->Data);
-               /* TODO XImportant message */
        }
        FreeStrBuf(&Buf);
 }
 
 
 void view_mimepart(void) {
-       mimepart(0);
+       view_or_download_mimepart(0);
 }
 
+
 void download_mimepart(void) {
-       mimepart(1);
+       view_or_download_mimepart(1);
 }
 
+
 void view_postpart(void) {
        StrBuf *filename = NewStrBuf();
        StrBuf *partnum = NewStrBuf();
@@ -1973,6 +1919,7 @@ void view_postpart(void) {
        FreeStrBuf(&partnum);
 }
 
+
 void download_postpart(void) {
        StrBuf *filename = NewStrBuf();
        StrBuf *partnum = NewStrBuf();
@@ -1987,7 +1934,6 @@ void download_postpart(void) {
 }
 
 
-
 void show_num_attachments(void) {
        wc_printf("%d", GetCount(WC->attachments));
 }
@@ -2002,7 +1948,6 @@ void h_readgt(void) { readloop(readgt, eUseDefault);}
 void h_readlt(void) { readloop(readlt, eUseDefault);}
 
 
-
 /* Output message list in JSON format */
 void jsonMessageList(void) {
        StrBuf *View = NewStrBuf();
@@ -2014,6 +1959,7 @@ void jsonMessageList(void) {
        readloop(oper, eUseDefault);
 }
 
+
 void FreeReadLoopHandlerSet(void *v) {
        RoomRenderer *Handler = (RoomRenderer *) v;
        FreeStrBuf(&Handler->FetchMessageList);
@@ -2023,6 +1969,7 @@ void FreeReadLoopHandlerSet(void *v) {
        free(Handler);
 }
 
+
 void RegisterReadLoopHandlerset(
        int RoomType,
        GetParamsGetServerCall_func GetParamsGetServerCall,