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