03f7a1f7ef526e15c09024e8e6c5f552d25a1647
[citadel.git] / webcit-ng / old_threaded_view_save_for_reference.c
1 /*
2  * This is some older code for the forum view that does server-side rendering.
3  * We're keeping it around as a reference.
4  *
5  * Copyright (c) 1996-2018 by the citadel.org team
6  *
7  * This program is open source software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 3.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
15
16
17 #if 0
18 // Renderer for one message in the threaded view
19 // (This will probably work for the flat view too.)
20 //
21 void forum_render_one_message(struct ctdlsession *c, StrBuf * sj, long msgnum)
22 {
23         StrBuf *raw_msg = NULL;
24         StrBuf *sanitized_msg = NULL;
25         char buf[1024];
26         char content_transfer_encoding[1024] = { 0 };
27         char content_type[1024] = { 0 };
28         char author[128] = { 0 };
29         char datetime[128] = { 0 };
30
31         ctdl_printf(c, "MSG4 %ld", msgnum);
32         ctdl_readline(c, buf, sizeof(buf));
33         if (buf[0] != '1') {
34                 StrBufAppendPrintf(sj, "<div>ERROR CONDITION FIXME WRITE A BOX</div>");
35                 return;
36         }
37
38         while ((ctdl_readline(c, buf, sizeof(buf)) >= 0) && (strcmp(buf, "text")) && (strcmp(buf, "000"))) {
39                 // citadel header parsing here
40                 if (!strncasecmp(buf, "from=", 5)) {
41                         safestrncpy(author, &buf[5], sizeof author);
42                 }
43                 if (!strncasecmp(buf, "time=", 5)) {
44                         time_t tt;
45                         struct tm tm;
46                         tt = atol(&buf[5]);
47                         localtime_r(&tt, &tm);
48                         strftime(datetime, sizeof datetime, "%c", &tm);
49                 }
50         }
51
52         if (!strcmp(buf, "text")) {
53                 while ((ctdl_readline(c, buf, sizeof(buf)) >= 0) && (strcmp(buf, "")) && (strcmp(buf, "000"))) {
54                         // rfc822 header parsing here
55                         if (!strncasecmp(buf, "Content-transfer-encoding:", 26)) {
56                                 strcpy(content_transfer_encoding, &buf[26]);
57                                 striplt(content_transfer_encoding);
58                         }
59                         if (!strncasecmp(buf, "Content-type:", 13)) {
60                                 strcpy(content_type, &buf[13]);
61                                 striplt(content_type);
62                         }
63                 }
64                 raw_msg = ctdl_readtextmsg(c);
65         } else {
66                 raw_msg = NULL;
67         }
68
69         // begin output
70
71         StrBufAppendPrintf(sj, "<div>");        // begin message wrapper
72         StrBufAppendPrintf(sj, "<div style=\"float:left;padding-right:2px\">"); // begin avatar FIXME move the style to a stylesheet
73         StrBufAppendPrintf(sj, "<i class=\"fa fa-user-circle fa-2x\"></i> ");   // FIXME temporary avatar
74         StrBufAppendPrintf(sj, "</div>");       // end avatar
75         StrBufAppendPrintf(sj, "<div>");        // begin content
76         StrBufAppendPrintf(sj, "<div>");        // begin header
77         StrBufAppendPrintf(sj, "<span class=\"ctdl-username\"><a href=\"#\">%s</a></span> ", author);   // FIXME link to user profile or whatever
78         StrBufAppendPrintf(sj, "<span class=\"ctdl-msgdate\">%s</span> ", datetime);
79         StrBufAppendPrintf(sj, "</div>");       // end header
80         StrBufAppendPrintf(sj, "<div>");        // begin body
81
82         if (raw_msg) {
83
84                 // These are the encodings we know how to handle.  Decode in-place.
85
86                 if (!strcasecmp(content_transfer_encoding, "base64")) {
87                         StrBufDecodeBase64(raw_msg);
88                 }
89                 if (!strcasecmp(content_transfer_encoding, "quoted-printable")) {
90                         StrBufDecodeQP(raw_msg);
91                 }
92                 // At this point, raw_msg contains the decoded message.
93                 // Now run through the renderers we have available.
94
95                 if (!strncasecmp(content_type, "text/html", 9)) {
96                         sanitized_msg = html2html("UTF-8", 0, c->room, msgnum, raw_msg);
97                 } else if (!strncasecmp(content_type, "text/plain", 10)) {
98                         sanitized_msg = text2html("UTF-8", 0, c->room, msgnum, raw_msg);
99                 } else if (!strncasecmp(content_type, "text/x-citadel-variformat", 25)) {
100                         sanitized_msg = variformat2html(raw_msg);
101                 } else {
102                         sanitized_msg = NewStrBufPlain(HKEY("<i>No renderer for this content type</i><br>"));
103                 }
104                 FreeStrBuf(&raw_msg);
105
106                 // If sanitized_msg is not NULL, we have rendered the message and can output it.
107
108                 if (sanitized_msg) {
109                         StrBufAppendBuf(sj, sanitized_msg, 0);
110                         FreeStrBuf(&sanitized_msg);
111                 }
112         }
113
114         StrBufAppendPrintf(sj, "</div>");       // end body
115         StrBufAppendPrintf(sj, "</div>");       // end content
116         StrBufAppendPrintf(sj, "</div>");       // end wrapper
117 }
118
119
120 // This code implements the thread display code.  The thread sorting algorithm is working nicely but we're trying
121 // not to do rendering in the C server of webcit.  Maybe move it into the server as "MSGS threaded" or something like that?
122
123 // Threaded view (recursive section)
124 //
125 void thread_o_print(struct ctdlsession *c, StrBuf * sj, struct mthread *m, int num_msgs, int where_parent_is, int nesting_level)
126 {
127         int i = 0;
128         int j = 0;
129         int num_printed = 0;
130
131         for (i = 0; i < num_msgs; ++i) {
132                 if (m[i].parent == where_parent_is) {
133
134                         if (++num_printed == 1) {
135                                 StrBufAppendPrintf(sj, "<ul style=\"list-style-type: none;\">");
136                         }
137
138                         StrBufAppendPrintf(sj, "<li class=\"post\" id=\"post-%ld\">", m[i].msgnum);
139                         forum_render_one_message(c, sj, m[i].msgnum);
140                         StrBufAppendPrintf(sj, "</li>\r\n");
141                         if (i != 0) {
142                                 thread_o_print(c, sj, m, num_msgs, i, nesting_level + 1);
143                         }
144                 }
145         }
146
147         if (num_printed > 0) {
148                 StrBufAppendPrintf(sj, "</ul>");
149         }
150 }
151
152
153 // Threaded view (entry point)
154 //
155 void threaded_view(struct http_transaction *h, struct ctdlsession *c, char *which)
156 {
157         int num_msgs = 0;
158         int num_alloc = 0;
159         struct mthread *m;
160         char buf[1024];
161         char refs[1024];
162         int i, j, k;
163
164         ctdl_printf(c, "MSGS ALL|||9"); // 9 == headers + thread references
165         ctdl_readline(c, buf, sizeof(buf));
166         if (buf[0] != '1') {
167                 do_404(h);
168                 return;
169         }
170
171         StrBuf *sj = NewStrBuf();
172         StrBufAppendPrintf(sj, "<html><body>\r\n");
173
174         while (ctdl_readline(c, buf, sizeof buf), strcmp(buf, "000")) {
175
176                 ++num_msgs;
177                 if (num_msgs > num_alloc) {
178                         if (num_alloc == 0) {
179                                 num_alloc = 100;
180                                 m = malloc(num_alloc * sizeof(struct mthread));
181                         } else {
182                                 num_alloc *= 2;
183                                 m = realloc(m, (num_alloc * sizeof(struct mthread)));
184                         }
185                 }
186
187                 memset(&m[num_msgs - 1], 0, sizeof(struct mthread));
188                 m[num_msgs - 1].msgnum = extract_long(buf, 0);
189                 m[num_msgs - 1].datetime = extract_long(buf, 1);
190                 extract_token(m[num_msgs - 1].from, buf, 2, '|', sizeof m[num_msgs - 1].from);
191                 m[num_msgs - 1].threadhash = extract_int(buf, 6);
192                 extract_token(refs, buf, 7, '|', sizeof refs);
193
194                 char *t;
195                 char *r = refs;
196                 i = 0;
197                 while ((t = strtok_r(r, ",", &r))) {
198                         if (i == 0) {
199                                 m[num_msgs - 1].refhashes[0] = atoi(t); // always keep the first one
200                         } else {
201                                 memcpy(&m[num_msgs - 1].refhashes[1], &m[num_msgs - 1].refhashes[2], sizeof(int) * 8);  // shift the rest
202                                 m[num_msgs - 1].refhashes[9] = atoi(t);
203                         }
204                         ++i;
205                 }
206
207         }
208
209         // Sort by thread.  I did read jwz's sorting algorithm and it looks pretty good, but jwz is a self-righteous asshole so we do it our way.
210         for (i = 0; i < num_msgs; ++i) {
211                 for (j = 9; (j >= 0) && (m[i].parent == 0); --j) {
212                         for (k = 0; (k < num_msgs) && (m[i].parent == 0); ++k) {
213                                 if (m[i].refhashes[j] == m[k].threadhash) {
214                                         m[i].parent = k;
215                                 }
216                         }
217                 }
218         }
219
220         // Now render it
221         setup_for_forum_view(c);
222         thread_o_print(c, sj, m, num_msgs, 0, 0);       // Render threads recursively and recursively
223
224         // Garbage collection is for people who aren't smart enough to manage their own memory.
225         if (num_msgs > 0) {
226                 free(m);
227         }
228
229         StrBufAppendPrintf(sj, "</body></html>\r\n");
230
231         add_response_header(h, strdup("Content-type"), strdup("text/html; charset=utf-8"));
232         h->response_code = 200;
233         h->response_string = strdup("OK");
234         h->response_body_length = StrLength(sj);
235         h->response_body = SmashStrBuf(&sj);
236         return;
237 }
238
239
240 // flat view (entry point)
241 //
242 void flat_view(struct http_transaction *h, struct ctdlsession *c, char *which)
243 {
244         StrBuf *sj = NewStrBuf();
245         StrBufAppendPrintf(sj, "<html><body>\r\n");
246
247         setup_for_forum_view(c);
248         long *msglist = get_msglist(c, "ALL");
249         if (msglist) {
250                 int i;
251                 for (i = 0; (msglist[i] > 0); ++i) {
252                         forum_render_one_message(c, sj, msglist[i]);
253                 }
254                 free(msglist);
255         }
256
257         StrBufAppendPrintf(sj, "</body></html>\r\n");
258
259         add_response_header(h, strdup("Content-type"), strdup("text/html; charset=utf-8"));
260         h->response_code = 200;
261         h->response_string = strdup("OK");
262         h->response_body_length = StrLength(sj);
263         h->response_body = SmashStrBuf(&sj);
264         return;
265 }
266
267
268 // render one message (entire transaction)      FIXME EXTERMINATE
269 //
270 void html_render_one_message(struct http_transaction *h, struct ctdlsession *c, long msgnum)
271 {
272         StrBuf *sj = NewStrBuf();
273         StrBufAppendPrintf(sj, "<html><body>\r\n");
274         setup_for_forum_view(c);        // FIXME way too inefficient to do this for every message !!!!!!!!!!!!!
275         forum_render_one_message(c, sj, msgnum);
276         StrBufAppendPrintf(sj, "</body></html>\r\n");
277         add_response_header(h, strdup("Content-type"), strdup("text/html; charset=utf-8"));
278         h->response_code = 200;
279         h->response_string = strdup("OK");
280         h->response_body_length = StrLength(sj);
281         h->response_body = SmashStrBuf(&sj);
282         return;
283 }
284
285 #endif