* get_serv_info(): evaluate server replies
[citadel.git] / webcit / serv_func.c
1 /*
2  * $Id$
3  */
4
5 #include "webcit.h"
6 #include "webserver.h"
7
8 int is_uds = 0;
9 char serv_sock_name[PATH_MAX] = "";
10
11 HashList *EmbeddableMimes = NULL;
12 StrBuf *EmbeddableMimeStrs = NULL;
13
14
15 void SetInlinMimeRenderers(void)
16 {
17         StrBuf *Buf;
18
19         Buf = NewStrBuf();
20         /** Tell the server what kind of richtext we prefer */
21         serv_putbuf(EmbeddableMimeStrs);
22         StrBuf_ServGetln(Buf);
23
24         FreeStrBuf(&Buf);
25 }
26
27
28 void DeleteServInfo(ServInfo **FreeMe)
29 {
30         if (*FreeMe == NULL)
31                 return;
32         FreeStrBuf(&(*FreeMe)->serv_nodename);
33         FreeStrBuf(&(*FreeMe)->serv_humannode);
34         FreeStrBuf(&(*FreeMe)->serv_fqdn);
35         FreeStrBuf(&(*FreeMe)->serv_software);
36         FreeStrBuf(&(*FreeMe)->serv_bbs_city);
37         FreeStrBuf(&(*FreeMe)->serv_sysadm);
38         FreeStrBuf(&(*FreeMe)->serv_moreprompt);
39         FreeStrBuf(&(*FreeMe)->serv_default_cal_zone);
40         FreeStrBuf(&(*FreeMe)->serv_svn_revision);
41         free(*FreeMe);
42         *FreeMe = NULL;
43 }
44
45 /*
46  * get info about the server we've connected to
47  *
48  * browser_host         the citadel we want to connect to
49  * user_agent           which browser uses our client?
50  */
51 ServInfo *get_serv_info(StrBuf *browser_host, StrBuf *user_agent)
52 {
53         ServInfo *info;
54         StrBuf *Buf;
55         int a;
56
57         Buf = NewStrBuf();
58         /** Tell the server what kind of client is connecting */
59         serv_printf("IDEN %d|%d|%d|%s|%s",
60                     DEVELOPER_ID,
61                     CLIENT_ID,
62                     CLIENT_VERSION,
63                     ChrPtr(user_agent),
64                     ChrPtr(browser_host)
65         );
66         StrBuf_ServGetln(Buf);
67         if (GetServerStatus(Buf, NULL) != 2) {
68                 lprintf(0, "get_serv_info(IDEN): unexpected answer [%s]\n",
69                         ChrPtr(Buf));
70                 FreeStrBuf(&Buf);
71                 return NULL;
72         }
73
74         /*
75          * Tell the server that when we save a calendar event, we
76          * want invitations to be generated by the Citadel server
77          * instead of by the client.
78          */
79         serv_puts("ICAL sgi|1");
80         StrBuf_ServGetln(Buf);
81         if (GetServerStatus(Buf, NULL) != 2) {
82                 lprintf(0, "get_serv_info(ICAL sgi|1): unexpected answer [%s]\n",
83                         ChrPtr(Buf));
84                 FreeStrBuf(&Buf);
85                 return NULL;
86         }
87
88         /** Now ask the server to tell us a little bit about itself... */
89         serv_puts("INFO");
90         StrBuf_ServGetln(Buf);
91         if (GetServerStatus(Buf, NULL) != 1) {
92                 lprintf(0, "get_serv_info(INFO sgi|1): unexpected answer [%s]\n",
93                         ChrPtr(Buf));
94                 FreeStrBuf(&Buf);
95                 return NULL;
96         }
97
98         info = (ServInfo*)malloc(sizeof(ServInfo));
99         memset(info, 0, sizeof(ServInfo));
100         a = 0;
101         while (StrBuf_ServGetln(Buf), (strcmp(ChrPtr(Buf), "000")!= 0)) {
102 /*              lprintf (1, "a: %d [%s]", a, ChrPtr(Buf));*/
103                 switch (a) {
104                 case 0:
105                         info->serv_pid = StrToi(Buf);
106                         WC->ctdl_pid = info->serv_pid;
107                         break;
108                 case 1:
109                         info->serv_nodename = NewStrBufDup(Buf);
110                         break;
111                 case 2:
112                         info->serv_humannode = NewStrBufDup(Buf);
113                         break;
114                 case 3:
115                         info->serv_fqdn = NewStrBufDup(Buf);
116                         break;
117                 case 4:
118                         info->serv_software = NewStrBufDup(Buf);
119                         break;
120                 case 5:
121                         info->serv_rev_level = StrToi(Buf);
122                         break;
123                 case 6:
124                         info->serv_bbs_city = NewStrBufDup(Buf);
125                         break;
126                 case 7:
127                         info->serv_sysadm = NewStrBufDup(Buf);
128                         break;
129                 case 9:
130                         info->serv_moreprompt = NewStrBufDup(Buf);
131                         break;
132                 case 14:
133                         info->serv_supports_ldap = StrToi(Buf);
134                         break;
135                 case 15:
136                         info->serv_newuser_disabled = StrToi(Buf);
137                         break;
138                 case 16:
139                         info->serv_default_cal_zone = NewStrBufDup(Buf);
140                         break;
141                 case 20:
142                         info->serv_supports_sieve = StrToi(Buf);
143                         break;
144                 case 21:
145                         info->serv_fulltext_enabled = StrToi(Buf);
146                         break;
147                 case 22:
148                         info->serv_svn_revision = NewStrBufDup(Buf);
149                         break;
150                 case 23:
151                         info->serv_supports_openid = StrToi(Buf);
152                         break;
153                 }
154                 ++a;
155         }
156         FreeStrBuf(&Buf);
157         return info;
158 }
159
160 int GetConnected (void)
161 {
162         StrBuf *Buf;
163         wcsession *WCC = WC;
164
165         if (WCC->ReadBuf == NULL)
166                 WCC->ReadBuf = NewStrBufPlain(NULL, SIZ * 4);
167         if (is_uds) /* unix domain socket */
168                 WCC->serv_sock = uds_connectsock(serv_sock_name);
169         else        /* tcp socket */
170                 WCC->serv_sock = tcp_connectsock(ctdlhost, ctdlport);
171         
172         if (WCC->serv_sock < 0) {
173                 do_logout();
174                 FreeStrBuf(&WCC->ReadBuf);
175                 return 1;
176         }
177         else {
178                 long Status;
179                 Buf = NewStrBuf();
180                 WCC->connected = 1;
181                 StrBuf_ServGetln(Buf);  /* get the server greeting */
182                 GetServerStatus(Buf, &Status);
183                 FreeStrBuf(&Buf);
184
185                 /* Are there too many users already logged in? */
186                 if (Status == 571) {
187                         wc_printf(_("This server is already serving its maximum number of users and cannot accept any additional logins at this time.  Please try again later or contact your system administrator."));
188                         end_burst();
189                         end_webcit_session();
190                         return 1;
191                 }
192
193                 /*
194                  * From what host is our user connecting?  Go with
195                  * the host at the other end of the HTTP socket,
196                  * unless we are following X-Forwarded-For: headers
197                  * and such a header has already turned up something.
198                  */
199                 if ( (!follow_xff) || (StrLength(WCC->Hdr->HR.browser_host) == 0) ) {
200                         if (WCC->Hdr->HR.browser_host == NULL) {
201                                 WCC->Hdr->HR.browser_host = NewStrBuf();
202                                 Put(WCC->Hdr->HTTPHeaders, HKEY("FreeMeWithTheOtherHeaders"), 
203                                     WCC->Hdr->HR.browser_host, HFreeStrBuf);
204                         }
205                         locate_host(WCC->Hdr->HR.browser_host, WCC->Hdr->http_sock);
206                 }
207                 if (WCC->serv_info == NULL)
208                         WCC->serv_info = get_serv_info(WCC->Hdr->HR.browser_host, WCC->Hdr->HR.user_agent);
209                 if (WCC->serv_info == NULL){
210                         begin_burst();
211                         wc_printf(_("Received unexpected answer from Citadel "
212                                   "server; bailing out."));
213                         hprintf("HTTP/1.1 200 OK\r\n");
214                         hprintf("Content-type: text/plain; charset=utf-8\r\n");
215                         end_burst();
216                         end_webcit_session();
217                         return 1;
218                 }
219                 if (WCC->serv_info->serv_rev_level < MINIMUM_CIT_VERSION) {
220                         begin_burst();
221                         wc_printf(_("You are connected to a Citadel "
222                                   "server running Citadel %d.%02d. \n"
223                                   "In order to run this version of WebCit "
224                                   "you must also have Citadel %d.%02d or"
225                                   " newer.\n\n\n"),
226                                 WCC->serv_info->serv_rev_level / 100,
227                                 WCC->serv_info->serv_rev_level % 100,
228                                 MINIMUM_CIT_VERSION / 100,
229                                 MINIMUM_CIT_VERSION % 100
230                                 );
231                         hprintf("HTTP/1.1 200 OK\r\n");
232                         hprintf("Content-type: text/plain; charset=utf-8\r\n");
233                         end_burst();
234                         end_webcit_session();
235                         return 1;
236                 }
237                 SetInlinMimeRenderers();
238         }
239         return 0;
240 }
241
242 /*
243  *  Read Citadel variformat text and spit it out as HTML.
244  *  align html align string
245  */
246 inline void fmout(char *align)
247 {
248         _fmout(WC->WBuf, align);
249 }
250
251 void _fmout(StrBuf *Target, char *align)
252 {
253         int intext = 0;
254         int bq = 0;
255         char buf[SIZ];
256
257         StrBufAppendPrintf(Target, "<div align=%s>\n", align);
258         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
259
260                 if ((intext == 1) && (isspace(buf[0]))) {
261                         wc_printf("<br />");
262                 }
263                 intext = 1;
264
265                 /*
266                  * Quoted text should be displayed in italics and in a
267                  * different colour.  This code understands Citadel-style
268                  * " >" quotes and will convert to <BLOCKQUOTE> tags.
269                  */
270                 if ((bq == 0) && (!strncmp(buf, " >", 2))) {
271                         StrBufAppendBufPlain(Target, HKEY("<BLOCKQUOTE>"), 0);
272                         bq = 1;
273                 } else if ((bq == 1) && (strncmp(buf, " >", 2))) {
274                         StrBufAppendBufPlain(Target, HKEY("</BLOCKQUOTE>"), 0);
275                         bq = 0;
276                 }
277                 if ((bq == 1) && (!strncmp(buf, " >", 2))) {
278                         strcpy(buf, &buf[2]);
279                 }
280                 /* Activate embedded URL's */
281                 url(buf, sizeof(buf));
282
283                 escputs(buf);
284                 StrBufAppendBufPlain(Target, HKEY("\n"), 0);
285         }
286         if (bq == 1) {
287                 wc_printf("</I>");
288         }
289         wc_printf("</div><br />\n");
290 }
291
292 void FmOut(StrBuf *Target, char *align, StrBuf *Source)
293 {
294         const char *ptr, *pte;
295         const char *BufPtr = NULL;
296         StrBuf *Line = NewStrBufPlain(NULL, SIZ);
297         StrBuf *Line1 = NewStrBufPlain(NULL, SIZ);
298         StrBuf *Line2 = NewStrBufPlain(NULL, SIZ);
299         int bn = 0;
300         int bq = 0;
301         int i;
302         long len;
303         int intext = 0;
304
305         StrBufAppendPrintf(Target, "<div class=\"fmout-%s\">\n", align);
306
307         if (StrLength(Source) > 0) 
308                 do 
309                 {
310                         StrBufSipLine(Line, Source, &BufPtr);
311                         bq = 0;
312                         i = 0;
313                         ptr = ChrPtr(Line);
314                         len = StrLength(Line);
315                         pte = ptr + len;
316
317                         if ((intext == 1) && (isspace(*ptr))) {
318                                 StrBufAppendBufPlain(Target, HKEY("<br>"), 0);
319                         }
320                         intext = 1;
321                         if (isspace(*ptr)) while ((ptr < pte) &&
322                                                   ((*ptr == '>') ||
323                                                    isspace(*ptr)))
324                                            {
325                                                    if (*ptr == '>')
326                                                            bq++;
327                                                    ptr ++;
328                                                    i++;
329                                            }
330
331                         /**
332                          * Quoted text should be displayed in italics and in a
333                          * different colour.  This code understands Citadel-style
334                          * " >" quotes and will convert to <BLOCKQUOTE> tags.
335                          */
336                         if (i > 0) StrBufCutLeft(Line, i);
337                 
338
339                         for (i = bn; i < bq; i++)                               
340                                 StrBufAppendBufPlain(Target, HKEY("<blockquote>"), 0);
341                         for (i = bq; i < bn; i++)                               
342                                 StrBufAppendBufPlain(Target, HKEY("</blockquote>"), 0);
343                         bn = bq;
344
345                         if (StrLength(Line) == 0)
346                                 continue;
347                         /** Activate embedded URL's */
348                         UrlizeText(Line1, Line, Line2);
349
350                         StrEscAppend(Target, Line1, NULL, 0, 0);
351
352                         StrBufAppendBufPlain(Target, HKEY("\n"), 0);
353                 }
354                 while ((BufPtr != StrBufNOTNULL) &&
355                        (BufPtr != NULL));
356
357         for (i = 0; i < bn; i++) {
358                 StrBufAppendBufPlain(Target, HKEY("</blockquote>"), 0);
359         }
360         StrBufAppendBufPlain(Target, HKEY("</div><br>\n"), 0);
361         FreeStrBuf(&Line);
362         FreeStrBuf(&Line1);
363         FreeStrBuf(&Line2);
364 }
365
366
367 /*
368  * Read Citadel variformat text and spit it out as HTML in a form
369  * suitable for embedding in another message (forward/quote).
370  * (NO LINEBREAKS ALLOWED HERE!)
371  */
372 void pullquote_fmout(void) {
373         int intext = 0;
374         int bq = 0;
375         char buf[SIZ];
376
377         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
378
379                 if ((intext == 1) && (isspace(buf[0]))) {
380                         wc_printf("<br />");
381                 }
382                 intext = 1;
383
384                 /**
385                  * Quoted text should be displayed in italics and in a
386                  * different colour.  This code understands Citadel-style
387                  * " >" quotes and will convert to <BLOCKQUOTE> tags.
388                  */
389                 if ((bq == 0) && (!strncmp(buf, " >", 2))) {
390                         wc_printf("<BLOCKQUOTE>");
391                         bq = 1;
392                 } else if ((bq == 1) && (strncmp(buf, " >", 2))) {
393                         wc_printf("</BLOCKQUOTE>");
394                         bq = 0;
395                 }
396                 if ((bq == 1) && (!strncmp(buf, " >", 2))) {
397                         strcpy(buf, &buf[2]);
398                 }
399
400                 msgescputs(buf);
401         }
402         if (bq == 1) {
403                 wc_printf("</I>");
404         }
405 }
406
407
408
409
410 /*
411  *  Transmit message text (in memory) to the server.
412  */
413 void text_to_server(char *ptr)
414 {
415         char buf[256];
416         int ch, a, pos, len;
417
418         pos = 0;
419         buf[0] = 0;
420
421         while (ptr[pos] != 0) {
422                 ch = ptr[pos++];
423                 if (ch == 10) {
424                         len = strlen(buf);
425                         while ( (isspace(buf[len - 1]))
426                                 && (buf[0] !=  '\0') 
427                                 && (buf[1] !=  '\0') )
428                                 buf[--len] = 0;
429                         serv_puts(buf);
430                         buf[0] = 0;
431                         if (ptr[pos] != 0) strcat(buf, " ");
432                 } else {
433                         a = strlen(buf);
434                         buf[a + 1] = 0;
435                         buf[a] = ch;
436                         if ((ch == 32) && (strlen(buf) > 200)) {
437                                 buf[a] = 0;
438                                 serv_puts(buf);
439                                 buf[0] = 0;
440                         }
441                         if (strlen(buf) > 250) {
442                                 serv_puts(buf);
443                                 buf[0] = 0;
444                         }
445                 }
446         }
447         serv_puts(buf);
448 }
449
450
451 /*
452  * Transmit message text (in memory) to the server, converting to Quoted-Printable encoding as we go.
453  */
454 void text_to_server_qp(char *ptr)
455 {
456         unsigned char ch, buf[256];
457         int pos;
458         int output_len = 0;
459
460         pos = 0;
461         buf[0] = 0;
462         output_len = 0;
463
464         while (ptr[pos] != 0) {
465                 ch = (unsigned char)(ptr[pos++]);
466
467                 if (ch == 13) {
468                         /* ignore carriage returns */
469                 }
470                 else if (ch == 10) {
471                         /* hard line break */
472                         if (output_len > 0) {
473                                 if (isspace(buf[output_len-1])) {
474                                         sprintf((char *)&buf[output_len-1], "=%02X", buf[output_len-1]);
475                                         output_len += 2;
476                                 }
477                         }
478                         buf[output_len++] = 0;
479                         serv_puts((char *)buf);
480                         output_len = 0;
481                 }
482                 else if (ch == 9) {
483                         buf[output_len++] = ch;
484                 }
485                 else if ( (ch >= 32) && (ch <= 60) ) {
486                         buf[output_len++] = ch;
487                 }
488                 else if ( (ch >= 62) && (ch <= 126) ) {
489                         buf[output_len++] = ch;
490                 }
491                 else {
492                         sprintf((char *)&buf[output_len], "=%02X", ch);
493                         output_len += 3;
494                 }
495                 
496                 if (output_len > 72) {
497                         /* soft line break */
498                         if (isspace(buf[output_len-1])) {
499                                 sprintf((char *)&buf[output_len-1], "=%02X", buf[output_len-1]);
500                                 output_len += 2;
501                         }
502                         buf[output_len++] = '=';
503                         buf[output_len++] = 0;
504                         serv_puts((char *)buf);
505                         output_len = 0;
506                 }
507         }
508
509         /* end of data - transmit anything that's left */
510         if (output_len > 0) {
511                 if (isspace(buf[output_len-1])) {
512                         sprintf((char *)&buf[output_len-1], "=%02X", buf[output_len-1]);
513                         output_len += 2;
514                 }
515                 buf[output_len++] = 0;
516                 serv_puts((char *)buf);
517                 output_len = 0;
518         }
519 }
520
521
522
523
524 /*
525  * translate server message output to text (used for editing room info files and such)
526  */
527 void server_to_text()
528 {
529         char buf[SIZ];
530
531         int count = 0;
532
533         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
534                 if ((buf[0] == 32) && (count > 0)) {
535                         wc_printf("\n");
536                 }
537                 wc_printf("%s", buf);
538                 ++count;
539         }
540 }
541
542
543
544
545 /*
546  * Read text from server, appending to a string buffer until the
547  * usual 000 terminator is found.  Caller is responsible for freeing
548  * the returned pointer.
549  */
550 int read_server_text(StrBuf *Buf, long *nLines)
551 {
552         wcsession *WCC = WC;
553         long nRead;
554         long nTotal = 0;
555         long nlines;
556         
557         nlines = 0;
558         while ((WCC->serv_sock!=-1) &&
559                (nRead = StrBuf_ServGetln(Buf), (nRead >= 0) ))
560         {
561                 if (strcmp(ChrPtr(Buf) + nTotal, "000") != 0) {
562                         StrBufCutRight(Buf, nRead);
563                         break;
564                 }
565                 nTotal += nRead;
566                 nlines ++;
567         }
568
569         *nLines = nlines;
570         return nTotal;
571 }
572
573
574 int GetServerStatus(StrBuf *Line, long* FullState)
575 {
576         if (FullState != NULL)
577                 *FullState = StrTol(Line);
578         return ChrPtr(Line)[0] - 48;
579 }
580
581
582 void tmplput_serv_ip(StrBuf *Target, WCTemplputParams *TP)
583 {
584         StrBufAppendPrintf(Target, "%d", WC->ctdl_pid);
585 }
586
587 void tmplput_serv_nodename(StrBuf *Target, WCTemplputParams *TP)
588 {
589         wcsession *WCC = WC;
590         if (WCC->serv_info == NULL)
591                 return;
592         StrBufAppendTemplate(Target, TP, WCC->serv_info->serv_nodename, 0);
593 }
594
595 void tmplput_serv_humannode(StrBuf *Target, WCTemplputParams *TP)
596 {
597         wcsession *WCC = WC;
598         if (WCC->serv_info == NULL)
599                 return;
600         StrBufAppendTemplate(Target, TP, WCC->serv_info->serv_humannode, 0);
601 }
602
603 void tmplput_serv_fqdn(StrBuf *Target, WCTemplputParams *TP)
604 {
605         wcsession *WCC = WC;
606         if (WCC->serv_info == NULL)
607                 return;
608         StrBufAppendTemplate(Target, TP, WCC->serv_info->serv_fqdn, 0);
609 }
610
611 void tmplput_serv_software(StrBuf *Target, WCTemplputParams *TP)
612 {
613         wcsession *WCC = WC;
614         if (WCC->serv_info == NULL)
615                 return;
616         StrBufAppendTemplate(Target, TP, WCC->serv_info->serv_software, 0);
617 }
618
619 void tmplput_serv_rev_level(StrBuf *Target, WCTemplputParams *TP)
620 {
621         wcsession *WCC = WC;
622         if (WCC->serv_info == NULL)
623                 return;
624         StrBufAppendPrintf(Target, "%d.%02d",
625                             WCC->serv_info->serv_rev_level / 100,
626                             WCC->serv_info->serv_rev_level % 100);
627 }
628 int conditional_serv_newuser_disabled(StrBuf *Target, WCTemplputParams *TP)
629 {
630         wcsession *WCC = WC;
631         if (WCC->serv_info == NULL)
632                 return 0;
633         return WCC->serv_info->serv_newuser_disabled != 0;
634 }
635
636 int conditional_serv_supports_openid(StrBuf *Target, WCTemplputParams *TP)
637 {
638         wcsession *WCC = WC;
639         if (WCC->serv_info == NULL)
640                 return 0;
641         return WCC->serv_info->serv_supports_openid != 0;
642 }
643
644 int conditional_serv_fulltext_enabled(StrBuf *Target, WCTemplputParams *TP)
645 {
646         wcsession *WCC = WC;
647         if (WCC->serv_info == NULL)
648                 return 0;
649         return WCC->serv_info->serv_fulltext_enabled != 0;
650 }
651
652 void tmplput_serv_bbs_city(StrBuf *Target, WCTemplputParams *TP)
653 {
654         wcsession *WCC = WC;
655         if (WCC->serv_info == NULL)
656                 return;
657         StrBufAppendTemplate(Target, TP, WC->serv_info->serv_bbs_city, 0);
658 }
659
660 void tmplput_mesg(StrBuf *Target, WCTemplputParams *TP)
661 {
662         int n = 0;
663         int Done = 0;
664         StrBuf *Line;
665         StrBuf *Buf;
666
667         Buf = NewStrBuf();
668         Line = NewStrBuf();
669         serv_printf("MESG %s", TP->Tokens->Params[0]->Start);
670
671         StrBuf_ServGetln(Line);
672         if (GetServerStatus(Line, NULL) == 1) {
673                 while (!Done &&  (StrBuf_ServGetln(Line)>=0)) {
674                         if ( (StrLength(Line)==3) && 
675                              !strcmp(ChrPtr(Line), "000")) 
676                                 Done = 1;
677                         else
678                         {
679                                 if (n > 0)
680                                         StrBufAppendBufPlain(Buf, "\n", 1, 0);
681                                 StrBufAppendBuf(Buf, Line, 0);
682                         }
683                         n++;
684                 }
685         
686                 FlushStrBuf(Line);
687                 FmOut(Line, "center", Buf);
688                 StrBufAppendTemplate(Target, TP, Line, 1);
689         }
690         FreeStrBuf(&Buf);
691         FreeStrBuf(&Line);
692 }
693
694
695 void RegisterEmbeddableMimeType(const char *MimeType, long MTLen, int Priority)
696 {
697         StrBuf *MT;
698         MT = NewStrBufPlain(MimeType, MTLen);
699         Put(EmbeddableMimes, IKEY(Priority), MT, HFreeStrBuf);
700 }
701
702 void CreateMimeStr(void)
703 {
704         HashPos  *it;
705         void *vMime;
706         long len = 0;
707         const char *Key;
708
709         it = GetNewHashPos(EmbeddableMimes, 0);
710         while (GetNextHashPos(EmbeddableMimes, it, &len, &Key, &vMime) &&
711                (vMime != NULL)) {
712                 if (StrLength(EmbeddableMimeStrs) > 0)
713                         StrBufAppendBufPlain(EmbeddableMimeStrs, HKEY("|"), 0);
714                 else 
715                         StrBufAppendBufPlain(EmbeddableMimeStrs, HKEY("MSGP "), 0);
716                 StrBufAppendBuf(EmbeddableMimeStrs, (StrBuf*) vMime, 0);
717         }
718         DeleteHashPos(&it);
719 }
720
721 void
722 ServerStartModule_SERV_FUNC
723 (void)
724 {
725         EmbeddableMimes = NewHash(1, Flathash);
726         EmbeddableMimeStrs = NewStrBuf();
727 }
728
729
730 void
731 ServerShutdownModule_SERV_FUNC
732 (void)
733 {
734         FreeStrBuf(&EmbeddableMimeStrs);
735         DeleteHash(&EmbeddableMimes);
736 }
737
738 void 
739 InitModule_SERVFUNC
740 (void)
741 {
742         is_uds = strcasecmp(ctdlhost, "uds") == 0;
743         if (is_uds)
744                 snprintf(serv_sock_name, PATH_MAX, "%s/citadel.socket", ctdlport);
745
746         RegisterConditional(HKEY("COND:SERV:OPENID"), 2, conditional_serv_supports_openid, CTX_NONE);
747         RegisterConditional(HKEY("COND:SERV:NEWU"), 2, conditional_serv_newuser_disabled, CTX_NONE);
748         RegisterConditional(HKEY("COND:SERV:HAVEFULLTEXT"), 2, conditional_serv_fulltext_enabled, CTX_NONE);
749         RegisterNamespace("SERV:PID", 0, 0, tmplput_serv_ip, NULL, CTX_NONE);
750         RegisterNamespace("SERV:NODENAME", 0, 1, tmplput_serv_nodename, NULL, CTX_NONE);
751         RegisterNamespace("SERV:HUMANNODE", 0, 1, tmplput_serv_humannode, NULL, CTX_NONE);
752         RegisterNamespace("SERV:FQDN", 0, 1, tmplput_serv_fqdn, NULL, CTX_NONE);
753         RegisterNamespace("SERV:SOFTWARE", 0, 1, tmplput_serv_software, NULL, CTX_NONE);
754         RegisterNamespace("SERV:REV_LEVEL", 0, 0, tmplput_serv_rev_level, NULL, CTX_NONE);
755         RegisterNamespace("SERV:BBS_CITY", 0, 1, tmplput_serv_bbs_city, NULL, CTX_NONE);
756         RegisterNamespace("SERV:MESG", 1, 2, tmplput_mesg, NULL, CTX_NONE);
757 /*TODO //       RegisterNamespace("SERV:LDAP_SUPP", 0, 0, tmplput_serv_ldap_enabled, 0); */
758 }
759
760
761
762 void 
763 SessionDestroyModule_SERVFUNC
764 (wcsession *sess)
765 {
766         DeleteServInfo(&sess->serv_info);
767 }