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