HTML messages are now encoded as "Quoted-Printable" before being
[citadel.git] / webcit / serv_func.c
1 /*
2  * $Id$
3  */
4 /**
5  * \defgroup ServFuncs Handles various types of data transfer operations with the Citadel service.
6  * \ingroup CitadelCommunitacion
7  */
8
9 /*@{*/ 
10 #include "webcit.h"
11 #include "webserver.h"
12
13 struct serv_info serv_info; /**< our connection data to the server */
14
15 /**
16  * \brief get info about the server we've connected to
17  * \param browser_host the citadell we want to connect to
18  * \param user_agent which browser uses our client?
19  */
20 void get_serv_info(char *browser_host, char *user_agent)
21 {
22         char buf[SIZ];
23         int a;
24
25         /** Tell the server what kind of client is connecting */
26         serv_printf("IDEN %d|%d|%d|%s|%s",
27                 DEVELOPER_ID,
28                 CLIENT_ID,
29                 CLIENT_VERSION,
30                 user_agent,
31                 browser_host
32         );
33         serv_getln(buf, sizeof buf);
34
35         /** Tell the server what kind of richtext we prefer */
36         serv_puts("MSGP text/html|text/plain");
37         serv_getln(buf, sizeof buf);
38
39 #ifdef WEBCIT_WITH_CALENDAR_SERVICE
40         /**
41          * Tell the server that when we save a calendar event, we
42          * want invitations to be generated by the Citadel server
43          * instead of by the client.
44          */
45         serv_puts("ICAL sgi|1");
46         serv_getln(buf, sizeof buf);
47 #endif
48
49         /** Now ask the server to tell us a little bit about itself... */
50         serv_puts("INFO");
51         serv_getln(buf, sizeof buf);
52         if (buf[0] != '1')
53                 return;
54
55         a = 0;
56         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
57                 switch (a) {
58                 case 0:
59                         serv_info.serv_pid = atoi(buf);
60                         WC->ctdl_pid = serv_info.serv_pid;
61                         break;
62                 case 1:
63                         safestrncpy(serv_info.serv_nodename, buf, sizeof serv_info.serv_nodename);
64                         break;
65                 case 2:
66                         safestrncpy(serv_info.serv_humannode, buf, sizeof serv_info.serv_humannode);
67                         break;
68                 case 3:
69                         safestrncpy(serv_info.serv_fqdn, buf, sizeof serv_info.serv_fqdn);
70                         break;
71                 case 4:
72                         safestrncpy(serv_info.serv_software, buf, sizeof serv_info.serv_software);
73                         break;
74                 case 5:
75                         serv_info.serv_rev_level = atoi(buf);
76                         break;
77                 case 6:
78                         safestrncpy(serv_info.serv_bbs_city, buf, sizeof serv_info.serv_bbs_city);
79                         break;
80                 case 7:
81                         safestrncpy(serv_info.serv_sysadm, buf, sizeof serv_info.serv_sysadm);
82                         break;
83                 case 9:
84                         safestrncpy(serv_info.serv_moreprompt, buf, sizeof serv_info.serv_moreprompt);
85                         break;
86                 case 14:
87                         serv_info.serv_supports_ldap = atoi(buf);
88                         break;
89                 }
90                 ++a;
91         }
92 }
93
94
95
96 /**
97  * \brief Read Citadel variformat text and spit it out as HTML.
98  * \param align html align string
99  */
100 void fmout(char *align)
101 {
102         int intext = 0;
103         int bq = 0;
104         char buf[SIZ];
105
106         wprintf("<div align=%s>\n", align);
107         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
108
109                 if ((intext == 1) && (isspace(buf[0]))) {
110                         wprintf("<br />");
111                 }
112                 intext = 1;
113
114                 /**
115                  * Quoted text should be displayed in italics and in a
116                  * different colour.  This code understands Citadel-style
117                  * " >" quotes and will convert to <BLOCKQUOTE> tags.
118                  */
119                 if ((bq == 0) && (!strncmp(buf, " >", 2))) {
120                         wprintf("<BLOCKQUOTE>");
121                         bq = 1;
122                 } else if ((bq == 1) && (strncmp(buf, " >", 2))) {
123                         wprintf("</BLOCKQUOTE>");
124                         bq = 0;
125                 }
126                 if ((bq == 1) && (!strncmp(buf, " >", 2))) {
127                         strcpy(buf, &buf[2]);
128                 }
129                 /** Activate embedded URL's */
130                 url(buf);
131
132                 escputs(buf);
133                 wprintf("\n");
134         }
135         if (bq == 1) {
136                 wprintf("</I>");
137         }
138         wprintf("</div><br />\n");
139 }
140
141
142
143
144 /**
145  * \brief Read Citadel variformat text and spit it out as HTML in a form
146  * suitable for embedding in another message (forward/quote).
147  * (NO LINEBREAKS ALLOWED HERE!)
148  */
149 void pullquote_fmout(void) {
150         int intext = 0;
151         int bq = 0;
152         char buf[SIZ];
153
154         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
155
156                 if ((intext == 1) && (isspace(buf[0]))) {
157                         wprintf("<br />");
158                 }
159                 intext = 1;
160
161                 /**
162                  * Quoted text should be displayed in italics and in a
163                  * different colour.  This code understands Citadel-style
164                  * " >" quotes and will convert to <BLOCKQUOTE> tags.
165                  */
166                 if ((bq == 0) && (!strncmp(buf, " >", 2))) {
167                         wprintf("<BLOCKQUOTE>");
168                         bq = 1;
169                 } else if ((bq == 1) && (strncmp(buf, " >", 2))) {
170                         wprintf("</BLOCKQUOTE>");
171                         bq = 0;
172                 }
173                 if ((bq == 1) && (!strncmp(buf, " >", 2))) {
174                         strcpy(buf, &buf[2]);
175                 }
176
177                 msgescputs(buf);
178         }
179         if (bq == 1) {
180                 wprintf("</I>");
181         }
182 }
183
184
185
186
187 /**
188  * \brief Transmit message text (in memory) to the server.
189  *
190  * \param ptr Pointer to the message being transmitted
191  */
192 void text_to_server(char *ptr)
193 {
194         char buf[256];
195         int ch, a, pos;
196
197         pos = 0;
198         buf[0] = 0;
199
200         while (ptr[pos] != 0) {
201                 ch = ptr[pos++];
202                 if (ch == 10) {
203                         while ( (isspace(buf[strlen(buf) - 1]))
204                           && (strlen(buf) > 1) )
205                                 buf[strlen(buf) - 1] = 0;
206                         serv_puts(buf);
207                         buf[0] = 0;
208                         if (ptr[pos] != 0) strcat(buf, " ");
209                 } else {
210                         a = strlen(buf);
211                         buf[a + 1] = 0;
212                         buf[a] = ch;
213                         if ((ch == 32) && (strlen(buf) > 200)) {
214                                 buf[a] = 0;
215                                 serv_puts(buf);
216                                 buf[0] = 0;
217                         }
218                         if (strlen(buf) > 250) {
219                                 serv_puts(buf);
220                                 buf[0] = 0;
221                         }
222                 }
223         }
224         serv_puts(buf);
225 }
226
227
228 /**
229  * \brief Transmit message text (in memory) to the server,
230  *        converting to Quoted-Printable encoding as we go.
231  *
232  * \param ptr Pointer to the message being transmitted
233  */
234 void text_to_server_qp(char *ptr)
235 {
236         char buf[256];
237         int ch, pos;
238         int output_len = 0;
239
240         pos = 0;
241         buf[0] = 0;
242         output_len = 0;
243
244         while (ptr[pos] != 0) {
245                 ch = ptr[pos++];
246
247                 if (ch == 13) {
248                         /* ignore carriage returns */
249                 }
250                 else if (ch == 10) {
251                         /* hard line break */
252                         if (output_len > 0) {
253                                 if (isspace(buf[output_len-1])) {
254                                         sprintf(&buf[output_len-1], "=%02X", buf[output_len-1]);
255                                         output_len += 2;
256                                 }
257                         }
258                         buf[output_len++] = 0;
259                         serv_puts(buf);
260                         output_len = 0;
261                 }
262                 else if (ch == 9) {
263                         buf[output_len++] = ch;
264                 }
265                 else if ( (ch >= 32) && (ch <= 60) ) {
266                         buf[output_len++] = ch;
267                 }
268                 else if ( (ch >= 62) && (ch <= 126) ) {
269                         buf[output_len++] = ch;
270                 }
271                 else {
272                         sprintf(&buf[output_len], "=%02X", ch);
273                         output_len += 3;
274                 }
275                 
276                 if (output_len > 72) {
277                         /* soft line break */
278                         if (isspace(buf[output_len-1])) {
279                                 sprintf(&buf[output_len-1], "=%02X", buf[output_len-1]);
280                                 output_len += 2;
281                         }
282                         buf[output_len++] = '=';
283                         buf[output_len++] = 0;
284                         serv_puts(buf);
285                         output_len = 0;
286                 }
287         }
288
289         /* end of data - transmit anything that's left */
290         if (output_len > 0) {
291                 if (isspace(buf[output_len-1])) {
292                         sprintf(&buf[output_len-1], "=%02X", buf[output_len-1]);
293                         output_len += 2;
294                 }
295                 buf[output_len++] = 0;
296                 serv_puts(buf);
297                 output_len = 0;
298         }
299 }
300
301
302
303
304 /**
305  * \brief translate server message output to text
306  * (used for editing room info files and such)
307  */
308 void server_to_text()
309 {
310         char buf[SIZ];
311
312         int count = 0;
313
314         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
315                 if ((buf[0] == 32) && (count > 0)) {
316                         wprintf("\n");
317                 }
318                 wprintf("%s", buf);
319                 ++count;
320         }
321 }
322
323
324
325 /**
326  * Read binary data from server into memory using a series of
327  * server READ commands.
328  * \param buffer the output buffer
329  * \param total_len the maximal length of buffer
330  */
331 void read_server_binary(char *buffer, size_t total_len) {
332         char buf[SIZ];
333         size_t bytes = 0;
334         size_t thisblock = 0;
335
336         memset(buffer, 0, total_len);
337         while (bytes < total_len) {
338                 thisblock = 4095;
339                 if ((total_len - bytes) < thisblock) {
340                         thisblock = total_len - bytes;
341                         if (thisblock == 0) return;
342                 }
343                 serv_printf("READ %d|%d", (int)bytes, (int)thisblock);
344                 serv_getln(buf, sizeof buf);
345                 if (buf[0] == '6') {
346                         thisblock = (size_t)atoi(&buf[4]);
347                         if (!WC->connected) return;
348                         serv_read(&buffer[bytes], thisblock);
349                         bytes += thisblock;
350                 }
351                 else {
352                         lprintf(3, "Error: %s\n", &buf[4]);
353                         return;
354                 }
355         }
356 }
357
358
359 /**
360  * \brief Read text from server, appending to a string buffer until the
361  * usual 000 terminator is found.  Caller is responsible for freeing
362  * the returned pointer.
363  */
364 char *read_server_text(void) {
365         char *text = NULL;
366         size_t bytes_allocated = 0;
367         size_t bytes_read = 0;
368         int linelen;
369         char buf[SIZ];
370
371         text = malloc(SIZ);
372         if (text == NULL) {
373                 return(NULL);
374         }
375         text[0] = 0;
376         bytes_allocated = SIZ;
377
378         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
379                 linelen = strlen(buf);
380                 buf[linelen] = '\n';
381                 buf[linelen+1] = 0;
382                 ++linelen;
383
384                 if ((bytes_read + linelen) >= (bytes_allocated - 2)) {
385                         bytes_allocated = 2 * bytes_allocated;
386                         text = realloc(text, bytes_allocated);
387                 }
388
389                 strcpy(&text[bytes_read], buf);
390                 bytes_read += linelen;
391         }
392
393         return(text);
394 }
395
396
397
398 /*@}*/