}
-JsonValue *NewJsonString(const char *Key, long keylen, StrBuf *CopyMe)
+JsonValue *NewJsonString(const char *Key, long keylen, StrBuf *CopyMe, int copy_or_smash)
{
JsonValue *Ret;
{
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;
}
#include <sys/types.h>
#include <netinet/in.h>
-#define LIBCITADEL_VERSION_NUMBER 917
+#define LIBCITADEL_VERSION_NUMBER 918
/*
* Here's a bunch of stupid magic to make the MIME parser portable.
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);
JsonArrayAppend(Ret, WFInfo(Filename, fnlen,
LineNo, Type));
- JsonArrayAppend(Ret,
- NewJsonString(NULL, 0, Msg));
+ JsonArrayAppend(Ret, NewJsonString(NULL, 0, Msg, NEWJSONSTRING_COPYBUF));
return Ret;
}
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
{
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);
return;
}
-#endif
// render one message (entire transaction) FIXME EXTERMINATE
//
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("<i>No renderer for this content type</i><br>"));
+ }
+ 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
{
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);
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)
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);
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);