* Fixed a multiselect bug in the mailbox view. Ctrl-click was selecting a message...
[citadel.git] / webcit / serv_func.c
blob5fc0996bd1ca00f33585babd08ddb0d96323dc42
1 /*
2 * $Id$
3 */
5 #include "webcit.h"
6 #include "webserver.h"
9 void DeleteServInfo(ServInfo **FreeMe)
11 if (*FreeMe == NULL)
12 return;
13 FreeStrBuf(&(*FreeMe)->serv_nodename);
14 FreeStrBuf(&(*FreeMe)->serv_humannode);
15 FreeStrBuf(&(*FreeMe)->serv_fqdn);
16 FreeStrBuf(&(*FreeMe)->serv_software);
17 FreeStrBuf(&(*FreeMe)->serv_bbs_city);
18 FreeStrBuf(&(*FreeMe)->serv_sysadm);
19 FreeStrBuf(&(*FreeMe)->serv_moreprompt);
20 FreeStrBuf(&(*FreeMe)->serv_default_cal_zone);
21 FreeStrBuf(&(*FreeMe)->serv_svn_revision);
22 free(*FreeMe);
23 *FreeMe = NULL;
27 * get info about the server we've connected to
29 * browser_host the citadell we want to connect to
30 * user_agent which browser uses our client?
32 ServInfo *get_serv_info(StrBuf *browser_host, char *user_agent)
34 ServInfo *info;
35 StrBuf *Buf;
36 char buf[SIZ];
37 int a;
39 /** Tell the server what kind of client is connecting */
40 serv_printf("IDEN %d|%d|%d|%s|%s",
41 DEVELOPER_ID,
42 CLIENT_ID,
43 CLIENT_VERSION,
44 user_agent,
45 ChrPtr(browser_host)
47 serv_getln(buf, sizeof buf);
49 /** Tell the server what kind of richtext we prefer */
50 serv_puts("MSGP text/calendar|text/html|text/plain");
51 serv_getln(buf, sizeof buf);
54 * Tell the server that when we save a calendar event, we
55 * want invitations to be generated by the Citadel server
56 * instead of by the client.
58 serv_puts("ICAL sgi|1");
59 serv_getln(buf, sizeof buf);
61 /** Now ask the server to tell us a little bit about itself... */
62 serv_puts("INFO");
63 serv_getln(buf, sizeof buf);
64 if (buf[0] != '1')
65 return NULL;
67 info = (ServInfo*)malloc(sizeof(ServInfo));
68 memset(info, 0, sizeof(ServInfo));
69 a = 0;
70 Buf = NewStrBuf();
71 while (StrBuf_ServGetln(Buf), (strcmp(ChrPtr(Buf), "000")!= 0)) {
72 /* lprintf (1, "a: %d [%s]", a, ChrPtr(Buf));*/
73 switch (a) {
74 case 0:
75 info->serv_pid = StrToi(Buf);
76 WC->ctdl_pid = info->serv_pid;
77 break;
78 case 1:
79 info->serv_nodename = NewStrBufDup(Buf);
80 break;
81 case 2:
82 info->serv_humannode = NewStrBufDup(Buf);
83 break;
84 case 3:
85 info->serv_fqdn = NewStrBufDup(Buf);
86 break;
87 case 4:
88 info->serv_software = NewStrBufDup(Buf);
89 break;
90 case 5:
91 info->serv_rev_level = StrToi(Buf);
92 break;
93 case 6:
94 info->serv_bbs_city = NewStrBufDup(Buf);
95 break;
96 case 7:
97 info->serv_sysadm = NewStrBufDup(Buf);
98 break;
99 case 9:
100 info->serv_moreprompt = NewStrBufDup(Buf);
101 break;
102 case 14:
103 info->serv_supports_ldap = StrToi(Buf);
104 break;
105 case 15:
106 info->serv_newuser_disabled = StrToi(Buf);
107 break;
108 case 16:
109 info->serv_default_cal_zone = NewStrBufDup(Buf);
110 break;
111 case 20:
112 info->serv_supports_sieve = StrToi(Buf);
113 break;
114 case 21:
115 info->serv_fulltext_enabled = StrToi(Buf);
116 break;
117 case 22:
118 info->serv_svn_revision = NewStrBufDup(Buf);
119 break;
120 case 23:
121 info->serv_supports_openid = StrToi(Buf);
122 break;
124 ++a;
126 FreeStrBuf(&Buf);
127 return info;
133 * Read Citadel variformat text and spit it out as HTML.
134 * align html align string
136 inline void fmout(char *align)
138 _fmout(WC->WBuf, align);
141 void _fmout(StrBuf *Target, char *align)
143 int intext = 0;
144 int bq = 0;
145 char buf[SIZ];
147 StrBufAppendPrintf(Target, "<div align=%s>\n", align);
148 while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
150 if ((intext == 1) && (isspace(buf[0]))) {
151 wprintf("<br />");
153 intext = 1;
156 * Quoted text should be displayed in italics and in a
157 * different colour. This code understands Citadel-style
158 * " >" quotes and will convert to <BLOCKQUOTE> tags.
160 if ((bq == 0) && (!strncmp(buf, " >", 2))) {
161 StrBufAppendBufPlain(Target, HKEY("<BLOCKQUOTE>"), 0);
162 bq = 1;
163 } else if ((bq == 1) && (strncmp(buf, " >", 2))) {
164 StrBufAppendBufPlain(Target, HKEY("</BLOCKQUOTE>"), 0);
165 bq = 0;
167 if ((bq == 1) && (!strncmp(buf, " >", 2))) {
168 strcpy(buf, &buf[2]);
170 /** Activate embedded URL's */
171 url(buf, sizeof(buf));
173 escputs(buf);
174 StrBufAppendBufPlain(Target, HKEY("\n"), 0);
176 if (bq == 1) {
177 wprintf("</I>");
179 wprintf("</div><br />\n");
182 void FmOut(StrBuf *Target, char *align, StrBuf *Source)
184 const char *ptr, *pte;
185 const char *BufPtr = NULL;
186 StrBuf *Line = NewStrBuf();
187 StrBuf *Line1 = NewStrBuf();
188 StrBuf *Line2 = NewStrBuf();
189 int bn = 0;
190 int bq = 0;
191 int i, n, done = 0;
192 long len;
193 int intext = 0;
195 StrBufAppendPrintf(Target, "<div class=\"fmout-%s\">\n", align);
196 while ((n = StrBufSipLine(Line, Source, &BufPtr), n >= 0) && !done)
198 done = n == 0;
199 bq = 0;
200 i = 0;
201 ptr = ChrPtr(Line);
202 len = StrLength(Line);
203 pte = ptr + len;
205 if ((intext == 1) && (isspace(*ptr))) {
206 StrBufAppendBufPlain(Target, HKEY("<br>"), 0);
208 intext = 1;
209 if (isspace(*ptr)) while ((ptr < pte) &&
210 ((*ptr == '>') ||
211 isspace(*ptr)))
213 if (*ptr == '>')
214 bq++;
215 ptr ++;
216 i++;
220 * Quoted text should be displayed in italics and in a
221 * different colour. This code understands Citadel-style
222 * " >" quotes and will convert to <BLOCKQUOTE> tags.
224 if (i > 0) StrBufCutLeft(Line, i);
227 for (i = bn; i < bq; i++)
228 StrBufAppendBufPlain(Target, HKEY("<blockquote>"), 0);
229 for (i = bq; i < bn; i++)
230 StrBufAppendBufPlain(Target, HKEY("</blockquote>"), 0);
231 bn = bq;
233 if (StrLength(Line) == 0)
234 continue;
235 /** Activate embedded URL's */
236 UrlizeText(Line1, Line, Line2);
238 StrEscAppend(Target, Line1, NULL, 0, 0);
240 StrBufAppendBufPlain(Target, HKEY("\n"), 0);
242 for (i = 0; i < bn; i++)
243 StrBufAppendBufPlain(Target, HKEY("</blockquote>"), 0);
244 StrBufAppendBufPlain(Target, HKEY("</div><br>\n"), 0);
245 FreeStrBuf(&Line);
246 FreeStrBuf(&Line1);
247 FreeStrBuf(&Line2);
254 * Read Citadel variformat text and spit it out as HTML in a form
255 * suitable for embedding in another message (forward/quote).
256 * (NO LINEBREAKS ALLOWED HERE!)
258 void pullquote_fmout(void) {
259 int intext = 0;
260 int bq = 0;
261 char buf[SIZ];
263 while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
265 if ((intext == 1) && (isspace(buf[0]))) {
266 wprintf("<br />");
268 intext = 1;
271 * Quoted text should be displayed in italics and in a
272 * different colour. This code understands Citadel-style
273 * " >" quotes and will convert to <BLOCKQUOTE> tags.
275 if ((bq == 0) && (!strncmp(buf, " >", 2))) {
276 wprintf("<BLOCKQUOTE>");
277 bq = 1;
278 } else if ((bq == 1) && (strncmp(buf, " >", 2))) {
279 wprintf("</BLOCKQUOTE>");
280 bq = 0;
282 if ((bq == 1) && (!strncmp(buf, " >", 2))) {
283 strcpy(buf, &buf[2]);
286 msgescputs(buf);
288 if (bq == 1) {
289 wprintf("</I>");
297 * Transmit message text (in memory) to the server.
299 * ptr Pointer to the message being transmitted
301 void text_to_server(char *ptr)
303 char buf[256];
304 int ch, a, pos, len;
306 pos = 0;
307 buf[0] = 0;
309 while (ptr[pos] != 0) {
310 ch = ptr[pos++];
311 if (ch == 10) {
312 len = strlen(buf);
313 while ( (isspace(buf[len - 1]))
314 && (buf[0] != '\0')
315 && (buf[1] != '\0') )
316 buf[--len] = 0;
317 serv_puts(buf);
318 buf[0] = 0;
319 if (ptr[pos] != 0) strcat(buf, " ");
320 } else {
321 a = strlen(buf);
322 buf[a + 1] = 0;
323 buf[a] = ch;
324 if ((ch == 32) && (strlen(buf) > 200)) {
325 buf[a] = 0;
326 serv_puts(buf);
327 buf[0] = 0;
329 if (strlen(buf) > 250) {
330 serv_puts(buf);
331 buf[0] = 0;
335 serv_puts(buf);
340 * Transmit message text (in memory) to the server,
341 * converting to Quoted-Printable encoding as we go.
343 * ptr Pointer to the message being transmitted
345 void text_to_server_qp(char *ptr)
347 unsigned char ch, buf[256];
348 int pos;
349 int output_len = 0;
351 pos = 0;
352 buf[0] = 0;
353 output_len = 0;
355 while (ptr[pos] != 0) {
356 ch = (unsigned char)(ptr[pos++]);
358 if (ch == 13) {
359 /* ignore carriage returns */
361 else if (ch == 10) {
362 /* hard line break */
363 if (output_len > 0) {
364 if (isspace(buf[output_len-1])) {
365 sprintf((char *)&buf[output_len-1], "=%02X", buf[output_len-1]);
366 output_len += 2;
369 buf[output_len++] = 0;
370 serv_puts((char *)buf);
371 output_len = 0;
373 else if (ch == 9) {
374 buf[output_len++] = ch;
376 else if ( (ch >= 32) && (ch <= 60) ) {
377 buf[output_len++] = ch;
379 else if ( (ch >= 62) && (ch <= 126) ) {
380 buf[output_len++] = ch;
382 else {
383 sprintf((char *)&buf[output_len], "=%02X", ch);
384 output_len += 3;
387 if (output_len > 72) {
388 /* soft line break */
389 if (isspace(buf[output_len-1])) {
390 sprintf((char *)&buf[output_len-1], "=%02X", buf[output_len-1]);
391 output_len += 2;
393 buf[output_len++] = '=';
394 buf[output_len++] = 0;
395 serv_puts((char *)buf);
396 output_len = 0;
400 /* end of data - transmit anything that's left */
401 if (output_len > 0) {
402 if (isspace(buf[output_len-1])) {
403 sprintf((char *)&buf[output_len-1], "=%02X", buf[output_len-1]);
404 output_len += 2;
406 buf[output_len++] = 0;
407 serv_puts((char *)buf);
408 output_len = 0;
416 * translate server message output to text
417 * (used for editing room info files and such)
419 void server_to_text()
421 char buf[SIZ];
423 int count = 0;
425 while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
426 if ((buf[0] == 32) && (count > 0)) {
427 wprintf("\n");
429 wprintf("%s", buf);
430 ++count;
437 * Read binary data from server into memory using a series of
438 * server READ commands.
439 * \return the read content as StrBuf
441 int read_server_binary(StrBuf *Ret, size_t total_len)
443 char buf[SIZ];
444 size_t bytes = 0;
445 size_t thisblock = 0;
446 StrBuf *Buf;
448 Buf = NewStrBuf();
449 if (Ret == NULL)
450 return -1;
452 while (bytes < total_len) {
453 thisblock = 4095;
454 if ((total_len - bytes) < thisblock) {
455 thisblock = total_len - bytes;
456 if (thisblock == 0) {
457 FlushStrBuf(Ret);
458 FreeStrBuf(&Buf);
459 return -1;
462 serv_printf("READ %d|%d", (int)bytes, (int)thisblock);
463 if (StrBuf_ServGetln(Buf) > 0)
465 if (GetServerStatus(Buf, NULL) == 6)
467 StrBufCutLeft(Buf, 4); /*/ TODO : thisblock = (size_t)atoi(&buf[4]); */
468 thisblock = StrTol(Buf);
469 if (!WC->connected) {
470 FlushStrBuf(Ret);
471 FreeStrBuf(&Buf);
472 return -1;
474 StrBuf_ServGetBLOB(Ret, thisblock);
475 bytes += thisblock;
477 else {
478 FreeStrBuf(&Buf);
479 lprintf(3, "Error: %s\n", &buf[4]);
480 return -1;
484 FreeStrBuf(&Buf);
485 return StrLength(Ret);
490 * Read text from server, appending to a string buffer until the
491 * usual 000 terminator is found. Caller is responsible for freeing
492 * the returned pointer.
494 int read_server_text(StrBuf *Buf, long *nLines)
496 wcsession *WCC = WC;
497 long nRead;
498 long nTotal = 0;
499 long nlines;
501 nlines = 0;
502 while ((WCC->serv_sock!=-1) &&
503 (nRead = StrBuf_ServGetln(Buf), (nRead >= 0) ))
505 if (strcmp(ChrPtr(Buf) + nTotal, "000") != 0) {
506 StrBufCutRight(Buf, nRead);
507 break;
509 nTotal += nRead;
510 nlines ++;
513 *nLines = nlines;
514 return nTotal;
522 int GetServerStatus(StrBuf *Line, long* FullState)
524 if (FullState != NULL)
525 *FullState = StrTol(Line);
526 return ChrPtr(Line)[0] - 48;
530 void tmplput_serv_ip(StrBuf *Target, WCTemplputParams *TP)
532 StrBufAppendPrintf(Target, "%d", WC->ctdl_pid);
535 void tmplput_serv_nodename(StrBuf *Target, WCTemplputParams *TP)
537 wcsession *WCC = WC;
538 if (WCC->serv_info == NULL)
539 return;
540 StrBufAppendTemplate(Target, TP, WCC->serv_info->serv_nodename, 0);
543 void tmplput_serv_humannode(StrBuf *Target, WCTemplputParams *TP)
545 wcsession *WCC = WC;
546 if (WCC->serv_info == NULL)
547 return;
548 StrBufAppendTemplate(Target, TP, WCC->serv_info->serv_humannode, 0);
551 void tmplput_serv_fqdn(StrBuf *Target, WCTemplputParams *TP)
553 wcsession *WCC = WC;
554 if (WCC->serv_info == NULL)
555 return;
556 StrBufAppendTemplate(Target, TP, WCC->serv_info->serv_fqdn, 0);
559 void tmplput_serv_software(StrBuf *Target, WCTemplputParams *TP)
561 wcsession *WCC = WC;
562 if (WCC->serv_info == NULL)
563 return;
564 StrBufAppendTemplate(Target, TP, WCC->serv_info->serv_software, 0);
567 void tmplput_serv_rev_level(StrBuf *Target, WCTemplputParams *TP)
569 wcsession *WCC = WC;
570 if (WCC->serv_info == NULL)
571 return;
572 StrBufAppendPrintf(Target, "%d.%02d",
573 WCC->serv_info->serv_rev_level / 100,
574 WCC->serv_info->serv_rev_level % 100);
576 int conditional_serv_newuser_disabled(StrBuf *Target, WCTemplputParams *TP)
578 wcsession *WCC = WC;
579 if (WCC->serv_info == NULL)
580 return 0;
581 return WCC->serv_info->serv_newuser_disabled != 0;
583 int conditional_serv_supports_openid(StrBuf *Target, WCTemplputParams *TP)
585 wcsession *WCC = WC;
586 if (WCC->serv_info == NULL)
587 return 0;
588 return WCC->serv_info->serv_supports_openid != 0;
591 void tmplput_serv_bbs_city(StrBuf *Target, WCTemplputParams *TP)
593 wcsession *WCC = WC;
594 if (WCC->serv_info == NULL)
595 return;
596 StrBufAppendTemplate(Target, TP, WC->serv_info->serv_bbs_city, 0);
600 void tmplput_mesg(StrBuf *Target, WCTemplputParams *TP)
602 int n = 0;
603 int Done = 0;
604 StrBuf *Line;
605 StrBuf *Buf;
607 Buf = NewStrBuf();
608 Line = NewStrBuf();
609 serv_printf("MESG %s", TP->Tokens->Params[0]->Start);
610 StrBuf_ServGetln(Line);
611 while (!Done && (StrBuf_ServGetln(Line)>=0)) {
612 if ( (StrLength(Line)==3) &&
613 !strcmp(ChrPtr(Line), "000"))
614 Done = 1;
615 else
617 if (n > 0)
618 StrBufAppendBufPlain(Buf, "\n", 1, 0);
619 StrBufAppendBuf(Buf, Line, 0);
621 n++;
623 FlushStrBuf(Line);
624 FmOut(Line, "center", Buf);
625 StrBufAppendTemplate(Target, TP, Line, 1);
626 FreeStrBuf(&Buf);
627 FreeStrBuf(&Line);
630 void
631 InitModule_SERVFUNC
632 (void)
635 RegisterConditional(HKEY("COND:SERV:OPENID"), 2, conditional_serv_supports_openid, CTX_NONE);
636 RegisterConditional(HKEY("COND:SERV:NEWU"), 2, conditional_serv_newuser_disabled, CTX_NONE);
637 RegisterNamespace("SERV:PID", 0, 0, tmplput_serv_ip, CTX_NONE);
638 RegisterNamespace("SERV:NODENAME", 0, 1, tmplput_serv_nodename, CTX_NONE);
639 RegisterNamespace("SERV:HUMANNODE", 0, 1, tmplput_serv_humannode, CTX_NONE);
640 RegisterNamespace("SERV:FQDN", 0, 1, tmplput_serv_fqdn, CTX_NONE);
641 RegisterNamespace("SERV:SOFTWARE", 0, 1, tmplput_serv_software, CTX_NONE);
642 RegisterNamespace("SERV:REV_LEVEL", 0, 0, tmplput_serv_rev_level, CTX_NONE);
643 RegisterNamespace("SERV:BBS_CITY", 0, 1, tmplput_serv_bbs_city, CTX_NONE);
644 RegisterNamespace("SERV:MESG", 1, 2, tmplput_mesg, CTX_NONE);
645 /*TODO // RegisterNamespace("SERV:LDAP_SUPP", 0, 0, tmplput_serv_ldap_enabled, 0); */
648 /*@}*/