WebCit now detects whether the Citadel server has Sieve support
[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                 case 15:
90                         serv_info.serv_newuser_disabled = atoi(buf);
91                         break;
92                 case 16:
93                         safestrncpy(serv_info.serv_default_cal_zone, buf, sizeof serv_info.serv_default_cal_zone);
94                         break;
95                 case 19:
96                         serv_info.serv_supports_sieve = atoi(buf);
97                         break;
98                 }
99                 ++a;
100         }
101 }
102
103
104
105 /**
106  * \brief Read Citadel variformat text and spit it out as HTML.
107  * \param align html align string
108  */
109 void fmout(char *align)
110 {
111         int intext = 0;
112         int bq = 0;
113         char buf[SIZ];
114
115         wprintf("<div align=%s>\n", align);
116         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
117
118                 if ((intext == 1) && (isspace(buf[0]))) {
119                         wprintf("<br />");
120                 }
121                 intext = 1;
122
123                 /**
124                  * Quoted text should be displayed in italics and in a
125                  * different colour.  This code understands Citadel-style
126                  * " >" quotes and will convert to <BLOCKQUOTE> tags.
127                  */
128                 if ((bq == 0) && (!strncmp(buf, " >", 2))) {
129                         wprintf("<BLOCKQUOTE>");
130                         bq = 1;
131                 } else if ((bq == 1) && (strncmp(buf, " >", 2))) {
132                         wprintf("</BLOCKQUOTE>");
133                         bq = 0;
134                 }
135                 if ((bq == 1) && (!strncmp(buf, " >", 2))) {
136                         strcpy(buf, &buf[2]);
137                 }
138                 /** Activate embedded URL's */
139                 url(buf);
140
141                 escputs(buf);
142                 wprintf("\n");
143         }
144         if (bq == 1) {
145                 wprintf("</I>");
146         }
147         wprintf("</div><br />\n");
148 }
149
150
151
152
153 /**
154  * \brief Read Citadel variformat text and spit it out as HTML in a form
155  * suitable for embedding in another message (forward/quote).
156  * (NO LINEBREAKS ALLOWED HERE!)
157  */
158 void pullquote_fmout(void) {
159         int intext = 0;
160         int bq = 0;
161         char buf[SIZ];
162
163         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
164
165                 if ((intext == 1) && (isspace(buf[0]))) {
166                         wprintf("<br />");
167                 }
168                 intext = 1;
169
170                 /**
171                  * Quoted text should be displayed in italics and in a
172                  * different colour.  This code understands Citadel-style
173                  * " >" quotes and will convert to <BLOCKQUOTE> tags.
174                  */
175                 if ((bq == 0) && (!strncmp(buf, " >", 2))) {
176                         wprintf("<BLOCKQUOTE>");
177                         bq = 1;
178                 } else if ((bq == 1) && (strncmp(buf, " >", 2))) {
179                         wprintf("</BLOCKQUOTE>");
180                         bq = 0;
181                 }
182                 if ((bq == 1) && (!strncmp(buf, " >", 2))) {
183                         strcpy(buf, &buf[2]);
184                 }
185
186                 msgescputs(buf);
187         }
188         if (bq == 1) {
189                 wprintf("</I>");
190         }
191 }
192
193
194
195
196 /**
197  * \brief Transmit message text (in memory) to the server.
198  *
199  * \param ptr Pointer to the message being transmitted
200  */
201 void text_to_server(char *ptr)
202 {
203         char buf[256];
204         int ch, a, pos, len;
205
206         pos = 0;
207         buf[0] = 0;
208
209         while (ptr[pos] != 0) {
210                 ch = ptr[pos++];
211                 if (ch == 10) {
212                         len = strlen(buf);
213                         while ( (isspace(buf[len - 1]))
214                                 && (buf[0] !=  '\0') 
215                                 && (buf[1] !=  '\0') )
216                                 buf[--len] = 0;
217                         serv_puts(buf);
218                         buf[0] = 0;
219                         if (ptr[pos] != 0) strcat(buf, " ");
220                 } else {
221                         a = strlen(buf);
222                         buf[a + 1] = 0;
223                         buf[a] = ch;
224                         if ((ch == 32) && (strlen(buf) > 200)) {
225                                 buf[a] = 0;
226                                 serv_puts(buf);
227                                 buf[0] = 0;
228                         }
229                         if (strlen(buf) > 250) {
230                                 serv_puts(buf);
231                                 buf[0] = 0;
232                         }
233                 }
234         }
235         serv_puts(buf);
236 }
237
238
239 /**
240  * \brief Transmit message text (in memory) to the server,
241  *        converting to Quoted-Printable encoding as we go.
242  *
243  * \param ptr Pointer to the message being transmitted
244  */
245 void text_to_server_qp(char *ptr)
246 {
247         unsigned char ch, buf[256];
248         int pos;
249         int output_len = 0;
250
251         pos = 0;
252         buf[0] = 0;
253         output_len = 0;
254
255         while (ptr[pos] != 0) {
256                 ch = (unsigned char)(ptr[pos++]);
257
258                 if (ch == 13) {
259                         /* ignore carriage returns */
260                 }
261                 else if (ch == 10) {
262                         /* hard line break */
263                         if (output_len > 0) {
264                                 if (isspace(buf[output_len-1])) {
265                                         sprintf((char *)&buf[output_len-1], "=%02X", buf[output_len-1]);
266                                         output_len += 2;
267                                 }
268                         }
269                         buf[output_len++] = 0;
270                         serv_puts((char *)buf);
271                         output_len = 0;
272                 }
273                 else if (ch == 9) {
274                         buf[output_len++] = ch;
275                 }
276                 else if ( (ch >= 32) && (ch <= 60) ) {
277                         buf[output_len++] = ch;
278                 }
279                 else if ( (ch >= 62) && (ch <= 126) ) {
280                         buf[output_len++] = ch;
281                 }
282                 else {
283                         sprintf((char *)&buf[output_len], "=%02X", ch);
284                         output_len += 3;
285                 }
286                 
287                 if (output_len > 72) {
288                         /* soft line break */
289                         if (isspace(buf[output_len-1])) {
290                                 sprintf((char *)&buf[output_len-1], "=%02X", buf[output_len-1]);
291                                 output_len += 2;
292                         }
293                         buf[output_len++] = '=';
294                         buf[output_len++] = 0;
295                         serv_puts((char *)buf);
296                         output_len = 0;
297                 }
298         }
299
300         /* end of data - transmit anything that's left */
301         if (output_len > 0) {
302                 if (isspace(buf[output_len-1])) {
303                         sprintf((char *)&buf[output_len-1], "=%02X", buf[output_len-1]);
304                         output_len += 2;
305                 }
306                 buf[output_len++] = 0;
307                 serv_puts((char *)buf);
308                 output_len = 0;
309         }
310 }
311
312
313
314
315 /**
316  * \brief translate server message output to text
317  * (used for editing room info files and such)
318  */
319 void server_to_text()
320 {
321         char buf[SIZ];
322
323         int count = 0;
324
325         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
326                 if ((buf[0] == 32) && (count > 0)) {
327                         wprintf("\n");
328                 }
329                 wprintf("%s", buf);
330                 ++count;
331         }
332 }
333
334
335
336 /**
337  * Read binary data from server into memory using a series of
338  * server READ commands.
339  * \param buffer the output buffer
340  * \param total_len the maximal length of buffer
341  */
342 void read_server_binary(char *buffer, size_t total_len) {
343         char buf[SIZ];
344         size_t bytes = 0;
345         size_t thisblock = 0;
346
347         memset(buffer, 0, total_len);
348         while (bytes < total_len) {
349                 thisblock = 4095;
350                 if ((total_len - bytes) < thisblock) {
351                         thisblock = total_len - bytes;
352                         if (thisblock == 0) return;
353                 }
354                 serv_printf("READ %d|%d", (int)bytes, (int)thisblock);
355                 serv_getln(buf, sizeof buf);
356                 if (buf[0] == '6') {
357                         thisblock = (size_t)atoi(&buf[4]);
358                         if (!WC->connected) return;
359                         serv_read(&buffer[bytes], thisblock);
360                         bytes += thisblock;
361                 }
362                 else {
363                         lprintf(3, "Error: %s\n", &buf[4]);
364                         return;
365                 }
366         }
367 }
368
369
370 /**
371  * \brief Read text from server, appending to a string buffer until the
372  * usual 000 terminator is found.  Caller is responsible for freeing
373  * the returned pointer.
374  */
375 char *read_server_text(void) {
376         char *text = NULL;
377         size_t bytes_allocated = 0;
378         size_t bytes_read = 0;
379         int linelen;
380         char buf[SIZ];
381
382         text = malloc(SIZ);
383         if (text == NULL) {
384                 return(NULL);
385         }
386         text[0] = 0;
387         bytes_allocated = SIZ;
388
389         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
390                 linelen = strlen(buf);
391                 buf[linelen] = '\n';
392                 buf[linelen+1] = 0;
393                 ++linelen;
394
395                 if ((bytes_read + linelen) >= (bytes_allocated - 2)) {
396                         bytes_allocated = 2 * bytes_allocated;
397                         text = realloc(text, bytes_allocated);
398                 }
399
400                 strcpy(&text[bytes_read], buf);
401                 bytes_read += linelen;
402         }
403
404         return(text);
405 }
406
407
408
409 /*@}*/