From 27cb58901ead4e6632e8fbf97d8c2053e5b7ff59 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Sat, 17 Feb 2018 19:18:15 -0500 Subject: [PATCH] html render replaced by json render in the C server. next needs to be the json-to-html in the client side... --- libcitadel/lib/json.c | 15 +++++- libcitadel/lib/libcitadel.h | 8 +++- libcitadel/lib/wildfire.c | 41 +++++----------- webcit-ng/forum_view.c | 92 +++++++++++++++++++++++++++++++++++- webcit-ng/room_functions.c | 4 -- webcit-ng/static/js/views.js | 2 +- webcit-ng/webcit.h | 3 -- 7 files changed, 122 insertions(+), 43 deletions(-) diff --git a/libcitadel/lib/json.c b/libcitadel/lib/json.c index b16674589..7f611818f 100644 --- a/libcitadel/lib/json.c +++ b/libcitadel/lib/json.c @@ -121,7 +121,7 @@ JsonValue *NewJsonBigNumber(const char *Key, long keylen, double Number) } -JsonValue *NewJsonString(const char *Key, long keylen, StrBuf *CopyMe) +JsonValue *NewJsonString(const char *Key, long keylen, StrBuf *CopyMe, int copy_or_smash) { JsonValue *Ret; @@ -132,7 +132,18 @@ JsonValue *NewJsonString(const char *Key, long keylen, StrBuf *CopyMe) { Ret->Name = NewStrBufPlain(Key, keylen); } - Ret->Value = NewStrBufDup(CopyMe); + if (copy_or_smash == NEWJSONSTRING_COPYBUF) + { + Ret->Value = NewStrBufDup(CopyMe); + } + else if (copy_or_smash == NEWJSONSTRING_SMASHBUF) + { + Ret->Value = CopyMe; + } + else + { + Ret->Value = NULL; // error condition + } return Ret; } diff --git a/libcitadel/lib/libcitadel.h b/libcitadel/lib/libcitadel.h index a6d66c5ec..3e86d07f5 100644 --- a/libcitadel/lib/libcitadel.h +++ b/libcitadel/lib/libcitadel.h @@ -28,7 +28,7 @@ #include #include -#define LIBCITADEL_VERSION_NUMBER 917 +#define LIBCITADEL_VERSION_NUMBER 918 /* * Here's a bunch of stupid magic to make the MIME parser portable. @@ -613,7 +613,11 @@ JsonValue *NewJsonNumber(const char *Key, long keylen, long Number); JsonValue *NewJsonBigNumber(const char *Key, long keylen, double Number); -JsonValue *NewJsonString(const char *Key, long keylen, StrBuf *CopyMe); +enum { + NEWJSONSTRING_COPYBUF, // make a copy of the StrBuf, source is left alone + NEWJSONSTRING_SMASHBUF // smash the source StrBuf, the json object now owns that memory +}; +JsonValue *NewJsonString(const char *Key, long keylen, StrBuf *CopyMe, int copy_or_smash); JsonValue *NewJsonPlainString(const char *Key, long keylen, const char *CopyMe, long len); diff --git a/libcitadel/lib/wildfire.c b/libcitadel/lib/wildfire.c index 1958f5920..c1fd2e3cc 100644 --- a/libcitadel/lib/wildfire.c +++ b/libcitadel/lib/wildfire.c @@ -58,8 +58,7 @@ JsonValue *WildFireMessage(const char *Filename, long fnlen, JsonArrayAppend(Ret, WFInfo(Filename, fnlen, LineNo, Type)); - JsonArrayAppend(Ret, - NewJsonString(NULL, 0, Msg)); + JsonArrayAppend(Ret, NewJsonString(NULL, 0, Msg, NEWJSONSTRING_COPYBUF)); return Ret; } @@ -275,28 +274,16 @@ JsonValue *WildFireException(const char *Filename, long FileLen, JsonValue *Val; Val = NewJsonArray(NULL, 0); - JsonArrayAppend(Val, WFInfo(Filename, FileLen, - LineNo, eEXCEPTION)); - - ExcClass = NewJsonObject(WF_MsgStrs[eTRACE].Key, - WF_MsgStrs[eTRACE].len); - + JsonArrayAppend(Val, WFInfo(Filename, FileLen, LineNo, eEXCEPTION)); + ExcClass = NewJsonObject(WF_MsgStrs[eTRACE].Key, WF_MsgStrs[eTRACE].len); JsonArrayAppend(Val, ExcClass); - JsonObjectAppend(ExcClass, - NewJsonPlainString(HKEY("Class"), - HKEY("Exception"))); - JsonObjectAppend(ExcClass, - NewJsonString(HKEY("Message"), Message)); - JsonObjectAppend(ExcClass, - NewJsonPlainString(HKEY("File"), - Filename, FileLen)); + JsonObjectAppend(ExcClass, NewJsonPlainString(HKEY("Class"), HKEY("Exception"))); + JsonObjectAppend(ExcClass, NewJsonString(HKEY("Message"), Message, NEWJSONSTRING_COPYBUF)); + JsonObjectAppend(ExcClass, NewJsonPlainString(HKEY("File"), Filename, FileLen)); /* - JsonObjectAppend(ExcClass, - NewJsonPlainString(HKEY("Type"), - HKEY("throw"))); + JsonObjectAppend(ExcClass, NewJsonPlainString(HKEY("Type"), HKEY("throw"))); */ - JsonObjectAppend(ExcClass, - NewJsonNumber(HKEY("Line"), LineNo)); + JsonObjectAppend(ExcClass, NewJsonNumber(HKEY("Line"), LineNo)); #ifdef HAVE_BACKTRACE { @@ -338,14 +325,10 @@ JsonValue *WildFireException(const char *Filename, long FileLen, Frame = NewJsonObject(NULL, 0); JsonArrayAppend(Trace, Frame); - JsonObjectAppend(Frame, - NewJsonString(HKEY("function"), Function)); - JsonObjectAppend(Frame, - NewJsonString(HKEY("file"), FileName)); - JsonObjectAppend(Frame, - NewJsonNumber(HKEY("line"), FunctionLine)); - JsonObjectAppend(Frame, - NewJsonArray(HKEY("args")));/* not supportet... */ + JsonObjectAppend(Frame, NewJsonString(HKEY("function"), Function, NEWJSONSTRING_COPYBUF)); + JsonObjectAppend(Frame, NewJsonString(HKEY("file"), FileName, NEWJSONSTRING_COPYBUF)); + JsonObjectAppend(Frame, NewJsonNumber(HKEY("line"), FunctionLine)); + JsonObjectAppend(Frame, NewJsonArray(HKEY("args"))); // not supported FunctionLine = 0; FlushStrBuf(FileName); diff --git a/webcit-ng/forum_view.c b/webcit-ng/forum_view.c index 016b8116d..6d8a8a3de 100644 --- a/webcit-ng/forum_view.c +++ b/webcit-ng/forum_view.c @@ -295,7 +295,6 @@ void flat_view(struct http_transaction *h, struct ctdlsession *c, char *which) return; } -#endif // render one message (entire transaction) FIXME EXTERMINATE // @@ -314,12 +313,101 @@ void html_render_one_message(struct http_transaction *h, struct ctdlsession *c, return; } +#endif // Fetch a single message and return it in JSON format for client-side rendering // void json_render_one_message(struct http_transaction *h, struct ctdlsession *c, long msgnum) { - JsonValue *j = NULL; // FIXME do something useful + StrBuf *raw_msg = NULL; + StrBuf *sanitized_msg = NULL; + char buf[1024]; + char content_transfer_encoding[1024] = { 0 }; + char content_type[1024] = { 0 }; + char author[128] = { 0 }; + char datetime[128] = { 0 } ; + + setup_for_forum_view(c); + + ctdl_printf(c, "MSG4 %ld", msgnum); + ctdl_readline(c, buf, sizeof(buf)); + if (buf[0] != '1') { + do_404(h); + return; + } + + JsonValue *j = NewJsonObject(HKEY("message")); + + while ( (ctdl_readline(c, buf, sizeof(buf)) >= 0) && (strcmp(buf, "text")) && (strcmp(buf, "000")) ) { + // citadel header parsing here + if (!strncasecmp(buf, "from=", 5)) { + JsonObjectAppend(j, NewJsonPlainString( HKEY("from"), &buf[5], -1)); + } + if (!strncasecmp(buf, "rfca=", 5)) { + JsonObjectAppend(j, NewJsonPlainString( HKEY("from"), &buf[5], -1)); + } + if (!strncasecmp(buf, "time=", 5)) { + time_t tt; + struct tm tm; + tt = atol(&buf[5]); + localtime_r(&tt, &tm); + strftime(datetime, sizeof datetime, "%c", &tm); + JsonObjectAppend(j, NewJsonPlainString( HKEY("time"), datetime, -1)); + } + } + + if (!strcmp(buf, "text")) { + while ( (ctdl_readline(c, buf, sizeof(buf)) >= 0) && (strcmp(buf, "")) && (strcmp(buf, "000")) ) { + // rfc822 header parsing here + if (!strncasecmp(buf, "Content-transfer-encoding:", 26)) { + strcpy(content_transfer_encoding, &buf[26]); + striplt(content_transfer_encoding); + } + if (!strncasecmp(buf, "Content-type:", 13)) { + strcpy(content_type, &buf[13]); + striplt(content_type); + } + } + raw_msg = ctdl_readtextmsg(c); + } + else { + raw_msg = NULL; + } + + if (raw_msg) { + + // These are the encodings we know how to handle. Decode in-place. + + if (!strcasecmp(content_transfer_encoding, "base64")) { + StrBufDecodeBase64(raw_msg); + } + if (!strcasecmp(content_transfer_encoding, "quoted-printable")) { + StrBufDecodeQP(raw_msg); + } + + // At this point, raw_msg contains the decoded message. + // Now run through the renderers we have available. + + if (!strncasecmp(content_type, "text/html", 9)) { + sanitized_msg = html2html("UTF-8", 0, c->room, msgnum, raw_msg); + } + else if (!strncasecmp(content_type, "text/plain", 10)) { + sanitized_msg = text2html("UTF-8", 0, c->room, msgnum, raw_msg); + } + else if (!strncasecmp(content_type, "text/x-citadel-variformat", 25)) { + sanitized_msg = variformat2html(raw_msg); + } + else { + sanitized_msg = NewStrBufPlain(HKEY("No renderer for this content type
")); + } + FreeStrBuf(&raw_msg); + + // If sanitized_msg is not NULL, we have rendered the message and can output it. + + if (sanitized_msg) { + JsonObjectAppend(j, NewJsonString(HKEY("text"), sanitized_msg, NEWJSONSTRING_SMASHBUF)); + } + } StrBuf *sj = NewStrBuf(); SerializeJson(sj, j, 1); // '1' == free the source object diff --git a/webcit-ng/room_functions.c b/webcit-ng/room_functions.c index 8136ced9e..a2dfc7b90 100644 --- a/webcit-ng/room_functions.c +++ b/webcit-ng/room_functions.c @@ -193,10 +193,6 @@ void object_in_room(struct http_transaction *h, struct ctdlsession *c) { json_render_one_message(h, c, msgnum); } - else if (!strcasecmp(buf, "html")) // FIXME exterminate this, we don't want any server-side rendering - { - html_render_one_message(h, c, msgnum); - } else { download_mime_component(h, c, msgnum, buf); diff --git a/webcit-ng/static/js/views.js b/webcit-ng/static/js/views.js index 5b3c47881..bfa45f5a6 100644 --- a/webcit-ng/static/js/views.js +++ b/webcit-ng/static/js/views.js @@ -155,7 +155,7 @@ function render_messages(msgs, prefix, view) function render_one(div, msgnum, view) { var request = new XMLHttpRequest(); - request.open("GET", "/ctdl/r/" + escapeHTMLURI(current_room) + "/" + msgs[i] + "/html", true); + request.open("GET", "/ctdl/r/" + escapeHTMLURI(current_room) + "/" + msgs[i] + "/json", true); request.onreadystatechange = function() { if (this.readyState === 4) diff --git a/webcit-ng/webcit.h b/webcit-ng/webcit.h index 5321c9b99..69a6bc071 100644 --- a/webcit-ng/webcit.h +++ b/webcit-ng/webcit.h @@ -147,8 +147,6 @@ void dav_get_message(struct http_transaction *h, struct ctdlsession *c, long msg void dav_put_message(struct http_transaction *h, struct ctdlsession *c, char *euid, long old_msgnum); ssize_t ctdl_write(struct ctdlsession *ctdl, const void *buf, size_t count); int login_to_citadel(struct ctdlsession *c, char *auth, char *resultbuf); -void threaded_view(struct http_transaction *h, struct ctdlsession *c, char *which); -void flat_view(struct http_transaction *h, struct ctdlsession *c, char *which); StrBuf *ctdl_readtextmsg(struct ctdlsession *ctdl); StrBuf *html2html(const char *supplied_charset, int treat_as_wiki, char *roomname, long msgnum, StrBuf *Source); void download_mime_component(struct http_transaction *h, struct ctdlsession *c, long msgnum, char *partnum); @@ -164,4 +162,3 @@ void do_404(struct http_transaction *h); void do_412(struct http_transaction *h); void UrlizeText(StrBuf* Target, StrBuf *Source, StrBuf *WrkBuf); void json_render_one_message(struct http_transaction *h, struct ctdlsession *c, long msgnum); -void html_render_one_message(struct http_transaction *h, struct ctdlsession *c, long msgnum); -- 2.30.2