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