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