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