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