X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fmessages.c;h=73527505384ec86eda880fa09ac2ad4fed7e116a;hb=716bbef62d0958b2211fda68e2f133514faade9b;hp=ac29cd5d7c4ec47015e9956527cedbea031c080b;hpb=4d0a622d2d3ae20770258981c6062f58c9fc01a3;p=citadel.git diff --git a/webcit/messages.c b/webcit/messages.c index ac29cd5d7..735275053 100644 --- a/webcit/messages.c +++ b/webcit/messages.c @@ -1,10 +1,12 @@ /* * Functions which deal with the fetching and displaying of messages. * - * Copyright (c) 1996-2012 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); @@ -932,22 +919,12 @@ void post_mime_to_server(void) { serv_printf("\n--%s", alt_boundary); } - if (havebstr("markdown")) - { - serv_puts("Content-type: text/x-markdown; charset=utf-8"); - serv_puts("Content-Transfer-Encoding: quoted-printable"); - serv_puts(""); - text_to_server_qp(sbstr("msgtext")); /* Transmit message in quoted-printable encoding */ - } - else - { - serv_puts("Content-type: text/html; charset=utf-8"); - serv_puts("Content-Transfer-Encoding: quoted-printable"); - serv_puts(""); - serv_puts("\r\n"); - text_to_server_qp(sbstr("msgtext")); /* Transmit message in quoted-printable encoding */ - serv_puts("\r\n"); - } + serv_puts("Content-type: text/html; charset=utf-8"); + serv_puts("Content-Transfer-Encoding: quoted-printable"); + serv_puts(""); + serv_puts("\r\n"); + text_to_server_qp(sbstr("msgtext")); /* Transmit message in quoted-printable encoding */ + serv_puts("\r\n"); if (include_text_alt) { serv_printf("--%s--", alt_boundary); @@ -999,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; @@ -1035,7 +1011,7 @@ void post_message(void) StrBuf *Recp = NULL; StrBuf *Cc = NULL; StrBuf *Bcc = NULL; - char *wikipage = NULL; + StrBuf *wikipage = NULL; const StrBuf *my_email_addr = NULL; StrBuf *CmdBuf = NULL; StrBuf *references = NULL; @@ -1090,7 +1066,7 @@ void post_message(void) FreeStrBuf(&EmailAddress); FreeStrBuf(&EncBuf); - wikipage = strdup(bstr("page")); + wikipage = NewStrBufDup(sbstr("page")); str_wiki_index(wikipage); my_email_addr = sbstr("my_email_addr"); @@ -1098,7 +1074,7 @@ void post_message(void) StrLength(encoded_subject) + StrLength(Cc) + StrLength(Bcc) + - strlen(wikipage) + + StrLength(wikipage) + StrLength(my_email_addr) + StrLength(references); CmdBuf = NewStrBufPlain(NULL, sizeof (CMD) + HeaderLen); @@ -1110,7 +1086,7 @@ void post_message(void) ChrPtr(display_name), saving_to_drafts?"":ChrPtr(Cc), saving_to_drafts?"":ChrPtr(Bcc), - wikipage, + ChrPtr(wikipage), ChrPtr(my_email_addr), ChrPtr(references)); FreeStrBuf(&references); @@ -1345,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; @@ -1364,10 +1340,6 @@ void display_enter(void) int i = 0; long replying_to; - int prefer_md; - - get_pref_yesno("markdown", &prefer_md, 0); - if (havebstr("force_room")) { gotoroom(sbstr("force_room")); } @@ -1432,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 @@ -1462,16 +1434,9 @@ void display_enter(void) 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; @@ -1601,8 +1566,7 @@ 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(); @@ -1631,22 +1595,22 @@ 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); + } } FreeStrBuf(&wefw); FreeStrBuf(&msgn); @@ -1657,23 +1621,23 @@ void display_enter(void) 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; const StrBuf *Bcc = NULL; - char *wikipage = NULL; + StrBuf *wikipage = NULL; StrBuf *CmdBuf = NULL; const char CMD[] = "ENT0 0|%s|%d|0||%s||%s|%s|%s"; Recp = sbstr("recp"); Cc = sbstr("cc"); Bcc = sbstr("bcc"); - wikipage = strdup(bstr("page")); + wikipage = NewStrBufDup(sbstr("page")); str_wiki_index(wikipage); CmdBuf = NewStrBufPlain(NULL, @@ -1682,7 +1646,7 @@ void display_enter(void) StrLength(display_name) + StrLength(Cc) + StrLength(Bcc) + - strlen(wikipage)); + StrLength(wikipage)); StrBufPrintf(CmdBuf, CMD, @@ -1691,7 +1655,7 @@ void display_enter(void) ChrPtr(display_name), ChrPtr(Cc), ChrPtr(Bcc), - wikipage + ChrPtr(wikipage) ); serv_puts(ChrPtr(CmdBuf)); StrBuf_ServGetln(CmdBuf); @@ -1720,20 +1684,17 @@ void display_enter(void) begin_burst(); output_headers(1, 0, 0, 0, 1, 0); - if ((WCC->CurRoom.defview == VIEW_WIKIMD) || prefer_md) - DoTemplate(HKEY("edit_markdown_epic"), NULL, &NoCtx); - else - DoTemplate(HKEY("edit_message"), NULL, &NoCtx); + DoTemplate(HKEY("edit_message"), NULL, &NoCtx); end_burst(); return; } + /* * delete a message */ -void delete_msg(void) -{ +void delete_msg(void) { long msgid; StrBuf *Line; @@ -1758,8 +1719,7 @@ void delete_msg(void) /* * move a message to another room */ -void move_msg(void) -{ +void move_msg(void) { long msgid; msgid = lbstr("msgid"); @@ -1780,7 +1740,6 @@ void move_msg(void) } - /* * Generic function to output an arbitrary MIME attachment from * message being composed @@ -1789,8 +1748,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; @@ -1825,98 +1783,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; - - att = Buf = NewStrBuf(); - msgnum = StrBufExtract_long(WCC->Hdr->HR.ReqLine, 0, '/'); - StrBufExtract_token(att, WCC->Hdr->HR.ReqLine, 1, '/'); + StrBuf *Buf; + StrBuf *ContentType; + StrBuf *PartNum; - 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); + PartNum = NewStrBuf(); - 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; @@ -1937,15 +1863,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(); @@ -1957,26 +1882,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(); @@ -1990,6 +1917,7 @@ void view_postpart(void) { FreeStrBuf(&partnum); } + void download_postpart(void) { StrBuf *filename = NewStrBuf(); StrBuf *partnum = NewStrBuf(); @@ -2004,7 +1932,6 @@ void download_postpart(void) { } - void show_num_attachments(void) { wc_printf("%d", GetCount(WC->attachments)); } @@ -2019,7 +1946,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(); @@ -2031,6 +1957,7 @@ void jsonMessageList(void) { readloop(oper, eUseDefault); } + void FreeReadLoopHandlerSet(void *v) { RoomRenderer *Handler = (RoomRenderer *) v; FreeStrBuf(&Handler->FetchMessageList); @@ -2040,6 +1967,7 @@ void FreeReadLoopHandlerSet(void *v) { free(Handler); } + void RegisterReadLoopHandlerset( int RoomType, GetParamsGetServerCall_func GetParamsGetServerCall, @@ -2116,8 +2044,6 @@ InitModule_MSG PRF_STRING, NULL); RegisterPreference("mailbox",_("Mailbox view mode"), PRF_STRING, NULL); - RegisterPreference("markdown",_("Prefer markdown editing"), PRF_YESNO, NULL); - WebcitAddUrlHandler(HKEY("readnew"), "", 0, h_readnew, ANONYMOUS|NEED_URL); WebcitAddUrlHandler(HKEY("readold"), "", 0, h_readold, ANONYMOUS|NEED_URL);