* move some more vars from the session context to strbuf (the use of StrBufAppendTemp...
[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 /*
10  * get info about the server we've connected to
11  *
12  * browser_host         the citadell we want to connect to
13  * user_agent           which browser uses our client?
14  */
15 void get_serv_info(char *browser_host, char *user_agent)
16 {
17         StrBuf *Buf;
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         Buf = NewStrBuf();
51         while (StrBuf_ServGetln(Buf), (strcmp(ChrPtr(Buf), "000")!= 0)) {
52 /*              lprintf (1, "a: %d [%s]", a, ChrPtr(Buf));*/
53                 switch (a) {
54                 case 0:
55                         serv_info.serv_pid = StrToi(Buf);
56                         WC->ctdl_pid = serv_info.serv_pid;
57                         break;
58                 case 1:
59                         serv_info.serv_nodename = NewStrBufDup(Buf);
60                         break;
61                 case 2:
62                         serv_info.serv_humannode = NewStrBufDup(Buf);
63                         break;
64                 case 3:
65                         serv_info.serv_fqdn = NewStrBufDup(Buf);
66                         break;
67                 case 4:
68                         serv_info.serv_software = NewStrBufDup(Buf);
69                         break;
70                 case 5:
71                         serv_info.serv_rev_level = StrToi(Buf);
72                         break;
73                 case 6:
74                         serv_info.serv_bbs_city = NewStrBufDup(Buf);
75                         break;
76                 case 7:
77                         serv_info.serv_sysadm = NewStrBufDup(Buf);
78                         break;
79                 case 9:
80                         serv_info.serv_moreprompt = NewStrBufDup(Buf);
81                         break;
82                 case 14:
83                         serv_info.serv_supports_ldap = StrToi(Buf);
84                         break;
85                 case 15:
86                         serv_info.serv_newuser_disabled = StrToi(Buf);
87                         break;
88                 case 16:
89                         serv_info.serv_default_cal_zone = NewStrBufDup(Buf);
90                         break;
91                 case 20:
92                         serv_info.serv_supports_sieve = StrToi(Buf);
93                         break;
94                 case 21:
95                         serv_info.serv_fulltext_enabled = StrToi(Buf);
96                         break;
97                 case 22:
98                         serv_info.serv_svn_revision = NewStrBufDup(Buf);
99                         break;
100                 case 23:
101                         serv_info.serv_supports_openid = StrToi(Buf);
102                         break;
103                 }
104                 ++a;
105         }
106 }
107
108
109
110 /**
111  *  Read Citadel variformat text and spit it out as HTML.
112  *  align html align string
113  */
114 inline void fmout(char *align)
115 {
116         _fmout(WC->WBuf, align);
117 }
118
119 void _fmout(StrBuf *Target, char *align)
120 {
121         int intext = 0;
122         int bq = 0;
123         char buf[SIZ];
124
125         StrBufAppendPrintf(Target, "<div align=%s>\n", align);
126         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
127
128                 if ((intext == 1) && (isspace(buf[0]))) {
129                         wprintf("<br />");
130                 }
131                 intext = 1;
132
133                 /**
134                  * Quoted text should be displayed in italics and in a
135                  * different colour.  This code understands Citadel-style
136                  * " >" quotes and will convert to <BLOCKQUOTE> tags.
137                  */
138                 if ((bq == 0) && (!strncmp(buf, " >", 2))) {
139                         StrBufAppendBufPlain(Target, HKEY("<BLOCKQUOTE>"), 0);
140                         bq = 1;
141                 } else if ((bq == 1) && (strncmp(buf, " >", 2))) {
142                         StrBufAppendBufPlain(Target, HKEY("</BLOCKQUOTE>"), 0);
143                         bq = 0;
144                 }
145                 if ((bq == 1) && (!strncmp(buf, " >", 2))) {
146                         strcpy(buf, &buf[2]);
147                 }
148                 /** Activate embedded URL's */
149                 url(buf, sizeof(buf));
150
151                 escputs(buf);/*/ TODO: Target */
152                 StrBufAppendBufPlain(Target, HKEY("\n"), 0);
153         }
154         if (bq == 1) {
155                 wprintf("</I>");
156         }
157         wprintf("</div><br />\n");
158 }
159
160 void FmOut(StrBuf *Target, char *align, StrBuf *Source)
161 {
162         const char *ptr, *pte;
163         const char *BufPtr = NULL;
164         StrBuf *Line = NewStrBuf();
165         StrBuf *Line1 = NewStrBuf();
166         StrBuf *Line2 = NewStrBuf();
167         int bn = 0;
168         int bq = 0;
169         int i, n, done = 0;
170         long len;
171         int intext = 0;
172
173         StrBufAppendPrintf(Target, "<div align=\"%s\">\n", align);
174         while ((n = StrBufSipLine(Line, Source, &BufPtr), n >= 0) && !done)
175         {
176                 done = n == 0;
177                 bq = 0;
178                 i = 0;
179                 ptr = ChrPtr(Line);
180                 len = StrLength(Line);
181                 pte = ptr + len;
182
183                 if ((intext == 1) && (isspace(*ptr))) {
184                         StrBufAppendBufPlain(Target, HKEY("<br />"), 0);
185                 }
186                 intext = 1;
187                 if (isspace(*ptr)) while ((ptr < pte) &&
188                        ((*ptr == '>') ||
189                         isspace(*ptr)))
190                 {
191                         if (*ptr == '>')
192                                 bq++;
193                         ptr ++;
194                         i++;
195                 }
196
197                 /**
198                  * Quoted text should be displayed in italics and in a
199                  * different colour.  This code understands Citadel-style
200                  * " >" quotes and will convert to <BLOCKQUOTE> tags.
201                  */
202                 if (i > 0) StrBufCutLeft(Line, i);
203                 
204
205                 for (i = bn; i < bq; i++)                               
206                         StrBufAppendBufPlain(Target, HKEY("<blockquote>"), 0);
207                 for (i = bq; i < bn; i++)                               
208                         StrBufAppendBufPlain(Target, HKEY("</blockquote>"), 0);
209                 bn = bq;
210
211                 if (StrLength(Line) == 0)
212                         continue;
213                 /** Activate embedded URL's */
214                 UrlizeText(Line1, Line, Line2);
215
216                 StrEscAppend(Target, Line1, NULL, 0, 0);
217
218                 StrBufAppendBufPlain(Target, HKEY("\n"), 0);
219         }
220         for (i = 0; i < bn; i++)                                
221                 StrBufAppendBufPlain(Target, HKEY("</blockquote>"), 0);
222         StrBufAppendBufPlain(Target, HKEY("</div><br />\n"), 0);
223         FreeStrBuf(&Line);
224         FreeStrBuf(&Line1);
225         FreeStrBuf(&Line2);
226 }
227
228
229
230
231 /**
232  *  Read Citadel variformat text and spit it out as HTML in a form
233  * suitable for embedding in another message (forward/quote).
234  * (NO LINEBREAKS ALLOWED HERE!)
235  */
236 void pullquote_fmout(void) {
237         int intext = 0;
238         int bq = 0;
239         char buf[SIZ];
240
241         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
242
243                 if ((intext == 1) && (isspace(buf[0]))) {
244                         wprintf("<br />");
245                 }
246                 intext = 1;
247
248                 /**
249                  * Quoted text should be displayed in italics and in a
250                  * different colour.  This code understands Citadel-style
251                  * " >" quotes and will convert to <BLOCKQUOTE> tags.
252                  */
253                 if ((bq == 0) && (!strncmp(buf, " >", 2))) {
254                         wprintf("<BLOCKQUOTE>");
255                         bq = 1;
256                 } else if ((bq == 1) && (strncmp(buf, " >", 2))) {
257                         wprintf("</BLOCKQUOTE>");
258                         bq = 0;
259                 }
260                 if ((bq == 1) && (!strncmp(buf, " >", 2))) {
261                         strcpy(buf, &buf[2]);
262                 }
263
264                 msgescputs(buf);
265         }
266         if (bq == 1) {
267                 wprintf("</I>");
268         }
269 }
270
271
272
273
274 /**
275  *  Transmit message text (in memory) to the server.
276  *
277  *  ptr Pointer to the message being transmitted
278  */
279 void text_to_server(char *ptr)
280 {
281         char buf[256];
282         int ch, a, pos, len;
283
284         pos = 0;
285         buf[0] = 0;
286
287         while (ptr[pos] != 0) {
288                 ch = ptr[pos++];
289                 if (ch == 10) {
290                         len = strlen(buf);
291                         while ( (isspace(buf[len - 1]))
292                                 && (buf[0] !=  '\0') 
293                                 && (buf[1] !=  '\0') )
294                                 buf[--len] = 0;
295                         serv_puts(buf);
296                         buf[0] = 0;
297                         if (ptr[pos] != 0) strcat(buf, " ");
298                 } else {
299                         a = strlen(buf);
300                         buf[a + 1] = 0;
301                         buf[a] = ch;
302                         if ((ch == 32) && (strlen(buf) > 200)) {
303                                 buf[a] = 0;
304                                 serv_puts(buf);
305                                 buf[0] = 0;
306                         }
307                         if (strlen(buf) > 250) {
308                                 serv_puts(buf);
309                                 buf[0] = 0;
310                         }
311                 }
312         }
313         serv_puts(buf);
314 }
315
316
317 /**
318  *  Transmit message text (in memory) to the server,
319  *        converting to Quoted-Printable encoding as we go.
320  *
321  *  ptr Pointer to the message being transmitted
322  */
323 void text_to_server_qp(char *ptr)
324 {
325         unsigned char ch, buf[256];
326         int pos;
327         int output_len = 0;
328
329         pos = 0;
330         buf[0] = 0;
331         output_len = 0;
332
333         while (ptr[pos] != 0) {
334                 ch = (unsigned char)(ptr[pos++]);
335
336                 if (ch == 13) {
337                         /* ignore carriage returns */
338                 }
339                 else if (ch == 10) {
340                         /* hard line break */
341                         if (output_len > 0) {
342                                 if (isspace(buf[output_len-1])) {
343                                         sprintf((char *)&buf[output_len-1], "=%02X", buf[output_len-1]);
344                                         output_len += 2;
345                                 }
346                         }
347                         buf[output_len++] = 0;
348                         serv_puts((char *)buf);
349                         output_len = 0;
350                 }
351                 else if (ch == 9) {
352                         buf[output_len++] = ch;
353                 }
354                 else if ( (ch >= 32) && (ch <= 60) ) {
355                         buf[output_len++] = ch;
356                 }
357                 else if ( (ch >= 62) && (ch <= 126) ) {
358                         buf[output_len++] = ch;
359                 }
360                 else {
361                         sprintf((char *)&buf[output_len], "=%02X", ch);
362                         output_len += 3;
363                 }
364                 
365                 if (output_len > 72) {
366                         /* soft line break */
367                         if (isspace(buf[output_len-1])) {
368                                 sprintf((char *)&buf[output_len-1], "=%02X", buf[output_len-1]);
369                                 output_len += 2;
370                         }
371                         buf[output_len++] = '=';
372                         buf[output_len++] = 0;
373                         serv_puts((char *)buf);
374                         output_len = 0;
375                 }
376         }
377
378         /* end of data - transmit anything that's left */
379         if (output_len > 0) {
380                 if (isspace(buf[output_len-1])) {
381                         sprintf((char *)&buf[output_len-1], "=%02X", buf[output_len-1]);
382                         output_len += 2;
383                 }
384                 buf[output_len++] = 0;
385                 serv_puts((char *)buf);
386                 output_len = 0;
387         }
388 }
389
390
391
392
393 /**
394  *  translate server message output to text
395  * (used for editing room info files and such)
396  */
397 void server_to_text()
398 {
399         char buf[SIZ];
400
401         int count = 0;
402
403         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
404                 if ((buf[0] == 32) && (count > 0)) {
405                         wprintf("\n");
406                 }
407                 wprintf("%s", buf);
408                 ++count;
409         }
410 }
411
412
413
414 /**
415  * Read binary data from server into memory using a series of
416  * server READ commands.
417  * \return the read content as StrBuf
418  */
419 int read_server_binary(StrBuf *Ret, size_t total_len) 
420 {
421         char buf[SIZ];
422         size_t bytes = 0;
423         size_t thisblock = 0;
424         StrBuf *Buf;
425         
426         Buf = NewStrBuf();
427         if (Ret == NULL)
428             return -1;
429
430         while (bytes < total_len) {
431                 thisblock = 4095;
432                 if ((total_len - bytes) < thisblock) {
433                         thisblock = total_len - bytes;
434                         if (thisblock == 0) {
435                                 FlushStrBuf(Ret); 
436                                 FreeStrBuf(&Buf);
437                                 return -1; 
438                         }
439                 }
440                 serv_printf("READ %d|%d", (int)bytes, (int)thisblock);
441                 if (StrBuf_ServGetln(Buf) > 0)
442                 {
443                         if (GetServerStatus(Buf, NULL) == 6)
444                         {
445                             StrBufCutLeft(Buf, 4); /*/ TODO : thisblock = (size_t)atoi(&buf[4]); */
446                             thisblock = StrTol(Buf);
447                             if (!WC->connected) {
448                                     FlushStrBuf(Ret); 
449                                     FreeStrBuf(&Buf); 
450                                     return -1; 
451                             }
452                             StrBuf_ServGetBLOB(Ret, thisblock);
453                             bytes += thisblock;
454                     }
455                     else {
456                             FreeStrBuf(&Buf);
457                             lprintf(3, "Error: %s\n", &buf[4]);
458                             return -1;
459                     }
460                 }
461         }
462         FreeStrBuf(&Buf);
463         return StrLength(Ret);
464 }
465
466
467 /**
468  *  Read text from server, appending to a string buffer until the
469  * usual 000 terminator is found.  Caller is responsible for freeing
470  * the returned pointer.
471  */
472 int read_server_text(StrBuf *Buf, long *nLines)
473 {
474         wcsession *WCC = WC;
475         long nRead;
476         long nTotal = 0;
477         long nlines;
478         
479         nlines = 0;
480         while ((WCC->serv_sock!=-1) &&
481                (nRead = StrBuf_ServGetln(Buf), (nRead >= 0) ))
482         {
483                 if (strcmp(ChrPtr(Buf) + nTotal, "000") != 0) {
484                         StrBufCutRight(Buf, nRead);
485                         break;
486                 }
487                 nTotal += nRead;
488                 nlines ++;
489         }
490
491         *nLines = nlines;
492         return nTotal;
493 }
494
495
496
497
498
499
500 int GetServerStatus(StrBuf *Line, long* FullState)
501 {
502         if (FullState != NULL)
503                 *FullState = StrTol(Line);
504         return ChrPtr(Line)[0] - 48;
505 }
506
507
508 void tmplput_serv_ip(StrBuf *Target, WCTemplputParams *TP)
509 {
510         StrBufAppendPrintf(Target, "%d", WC->ctdl_pid);
511 }
512
513 void tmplput_serv_nodename(StrBuf *Target, WCTemplputParams *TP)
514 {
515         StrBufAppendTemplate(Target, TP, serv_info.serv_nodename, 0);
516 }
517
518 void tmplput_serv_humannode(StrBuf *Target, WCTemplputParams *TP)
519 {
520         StrBufAppendTemplate(Target, TP, serv_info.serv_humannode, 0);
521 }
522
523 void tmplput_serv_fqdn(StrBuf *Target, WCTemplputParams *TP)
524 {
525         StrBufAppendTemplate(Target, TP, serv_info.serv_fqdn, 0);
526 }
527
528 void tmplput_serv_software(StrBuf *Target, WCTemplputParams *TP)
529 {
530         StrBufAppendTemplate(Target, TP, serv_info.serv_software, 0);
531 }
532
533 void tmplput_serv_rev_level(StrBuf *Target, WCTemplputParams *TP)
534 {
535         StrBufAppendPrintf(Target, "%d.%02d",
536                             serv_info.serv_rev_level / 100,
537                             serv_info.serv_rev_level % 100);
538 }
539 int conditional_serv_newuser_disabled(StrBuf *Target, WCTemplputParams *TP)
540 {
541         return serv_info.serv_newuser_disabled != 0;
542 }
543 int conditional_serv_supports_openid(StrBuf *Target, WCTemplputParams *TP)
544 {
545         return serv_info.serv_supports_openid != 0;
546 }
547
548 void tmplput_serv_bbs_city(StrBuf *Target, WCTemplputParams *TP)
549 {
550         StrBufAppendTemplate(Target, TP, serv_info.serv_bbs_city, 0);
551 }
552
553
554 void tmplput_mesg(StrBuf *Target, WCTemplputParams *TP)
555 {
556         int n = 0;
557         int Done = 0;
558         StrBuf *Line;
559         StrBuf *Buf;
560
561         Buf = NewStrBuf();
562         Line = NewStrBuf();
563         serv_printf("MESG %s", TP->Tokens->Params[0]->Start);
564         StrBuf_ServGetln(Line);
565         while (!Done &&  (StrBuf_ServGetln(Line)>=0)) {
566                 if ( (StrLength(Line)==3) && 
567                     !strcmp(ChrPtr(Line), "000")) 
568                         Done = 1;
569                 else
570                 {
571                         if (n > 0)
572                                 StrBufAppendBufPlain(Buf, "\n", 1, 0);
573                         StrBufAppendBuf(Buf, Line, 0);
574                 }
575                 n++;
576         }
577         FlushStrBuf(Line);
578         FmOut(Line, "center", Buf);
579         StrBufAppendTemplate(Target, TP, Line, 1);
580         FreeStrBuf(&Buf);
581         FreeStrBuf(&Line);
582 }
583
584 void 
585 InitModule_SERVFUNC
586 (void)
587 {
588
589         RegisterConditional(HKEY("COND:SERV:OPENID"), 2, conditional_serv_supports_openid, CTX_NONE);
590         RegisterConditional(HKEY("COND:SERV:NEWU"), 2, conditional_serv_newuser_disabled, CTX_NONE);
591         RegisterNamespace("SERV:PID", 0, 0, tmplput_serv_ip, CTX_NONE);
592         RegisterNamespace("SERV:NODENAME", 0, 1, tmplput_serv_nodename, CTX_NONE);
593         RegisterNamespace("SERV:HUMANNODE", 0, 1, tmplput_serv_humannode, CTX_NONE);
594         RegisterNamespace("SERV:FQDN", 0, 1, tmplput_serv_fqdn, CTX_NONE);
595         RegisterNamespace("SERV:SOFTWARE", 0, 1, tmplput_serv_software, CTX_NONE);
596         RegisterNamespace("SERV:REV_LEVEL", 0, 0, tmplput_serv_rev_level, CTX_NONE);
597         RegisterNamespace("SERV:BBS_CITY", 0, 1, tmplput_serv_bbs_city, CTX_NONE);
598         RegisterNamespace("SERV:MESG", 1, 2, tmplput_mesg, CTX_NONE);
599 /*TODO //       RegisterNamespace("SERV:LDAP_SUPP", 0, 0, tmplput_serv_ldap_enabled, 0); */
600 }
601
602 /*@}*/