* All OS-level includes are now included from webcit.h instead of from
[citadel.git] / webcit / serv_func.c
1 /*
2  * $Id$
3  *
4  * Handles various types of data transfer operations with the Citadel service.
5  *
6  */
7
8 #include "webcit.h"
9 #include "webserver.h"
10
11 struct serv_info serv_info;
12
13 /*
14  * get info about the server we've connected to
15  */
16 void get_serv_info(char *browser_host, char *user_agent)
17 {
18         char buf[SIZ];
19         int a;
20
21         /* Tell the server what kind of client is connecting */
22         serv_printf("IDEN %d|%d|%d|%s|%s",
23                 DEVELOPER_ID,
24                 CLIENT_ID,
25                 CLIENT_VERSION,
26                 user_agent,
27                 browser_host
28         );
29         serv_getln(buf, sizeof buf);
30
31         /* Tell the server what kind of richtext we prefer */
32         serv_puts("MSGP text/html|text/plain");
33         serv_getln(buf, sizeof buf);
34
35 #ifdef WEBCIT_WITH_CALENDAR_SERVICE
36         /* Tell the server that when we save a calendar event, we
37          * want invitations to be generated by the Citadel server
38          * instead of by the client.
39          */
40         serv_puts("ICAL sgi|1");
41         serv_getln(buf, sizeof buf);
42 #endif
43
44         /* Now ask the server to tell us a little bit about itself... */
45         serv_puts("INFO");
46         serv_getln(buf, sizeof buf);
47         if (buf[0] != '1')
48                 return;
49
50         a = 0;
51         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
52                 switch (a) {
53                 case 0:
54                         serv_info.serv_pid = atoi(buf);
55                         WC->ctdl_pid = serv_info.serv_pid;
56                         break;
57                 case 1:
58                         safestrncpy(serv_info.serv_nodename, buf, sizeof serv_info.serv_nodename);
59                         break;
60                 case 2:
61                         safestrncpy(serv_info.serv_humannode, buf, sizeof serv_info.serv_humannode);
62                         break;
63                 case 3:
64                         safestrncpy(serv_info.serv_fqdn, buf, sizeof serv_info.serv_fqdn);
65                         break;
66                 case 4:
67                         safestrncpy(serv_info.serv_software, buf, sizeof serv_info.serv_software);
68                         break;
69                 case 5:
70                         serv_info.serv_rev_level = atoi(buf);
71                         break;
72                 case 6:
73                         safestrncpy(serv_info.serv_bbs_city, buf, sizeof serv_info.serv_bbs_city);
74                         break;
75                 case 7:
76                         safestrncpy(serv_info.serv_sysadm, buf, sizeof serv_info.serv_sysadm);
77                         break;
78                 case 9:
79                         safestrncpy(serv_info.serv_moreprompt, buf, sizeof serv_info.serv_moreprompt);
80                         break;
81                 case 14:
82                         serv_info.serv_supports_ldap = atoi(buf);
83                         break;
84                 }
85                 ++a;
86         }
87 }
88
89
90
91 /* 
92  * Function to spit out Citadel variformat text in HTML
93  * If fp is non-null, it is considered to be the file handle to read the
94  * text from.  Otherwise, text is read from the server.
95  */
96 void fmout(FILE *fp, char *align)
97 {
98
99         int intext = 0;
100         int bq = 0;
101         char buf[SIZ];
102
103         wprintf("<div align=%s>\n", align);
104         while (1) {
105                 if (fp == NULL)
106                         serv_getln(buf, sizeof buf);
107                 if (fp != NULL) {
108                         if (fgets(buf, SIZ, fp) == NULL)
109                                 safestrncpy(buf, "000", sizeof buf);
110                         buf[strlen(buf) - 1] = 0;
111                 }
112                 if (!strcmp(buf, "000")) {
113                         if (bq == 1)
114                                 wprintf("</I>");
115                         wprintf("</div><br />\n");
116                         return;
117                 }
118                 if ((intext == 1) && (isspace(buf[0]))) {
119                         wprintf("<br />");
120                 }
121                 intext = 1;
122
123                 /* Quoted text should be displayed in italics and in a
124                  * different colour.  This code understands Citadel-style
125                  * " >" quotes and will convert to <BLOCKQUOTE> tags.
126                  */
127                 if ((bq == 0) && (!strncmp(buf, " >", 2))) {
128                         wprintf("<BLOCKQUOTE>");
129                         bq = 1;
130                 } else if ((bq == 1) && (strncmp(buf, " >", 2))) {
131                         wprintf("</BLOCKQUOTE>");
132                         bq = 0;
133                 }
134                 if ((bq == 1) && (!strncmp(buf, " >", 2))) {
135                         strcpy(buf, &buf[2]);
136                 }
137                 /* Activate embedded URL's */
138                 url(buf);
139
140                 escputs(buf);
141                 wprintf("\n");
142         }
143 }
144
145
146
147
148 /*
149  * Transmit message text (in memory) to the server.
150  * If convert_to_html is set to 1, the message is converted into something
151  * which kind of resembles HTML.
152  */
153 void text_to_server(char *ptr, int convert_to_html)
154 {
155         char buf[SIZ];
156         char conv[4];
157         int ch, a, pos;
158
159         pos = 0;
160         buf[0] = 0;
161
162         while (ptr[pos] != 0) {
163                 ch = ptr[pos++];
164                 if (ch == 10) {
165                         while ( (isspace(buf[strlen(buf) - 1]))
166                           && (strlen(buf) > 1) )
167                                 buf[strlen(buf) - 1] = 0;
168                         serv_puts(buf);
169                         buf[0] = 0;
170                         if (convert_to_html) {
171                                 strcat(buf, "<br />");
172                         }
173                         else {
174                                 if (ptr[pos] != 0) strcat(buf, " ");
175                         }
176                 } else if ((convert_to_html)&&(strchr("#&;`'|*?-~<>^()[]{}$\\", ch) != NULL)) {
177                         sprintf(conv, "%c", ch);
178                         stresc(&buf[strlen(buf)], conv, 0, 0);
179                 } else {
180                         a = strlen(buf);
181                         buf[a + 1] = 0;
182                         buf[a] = ch;
183                         if ((ch == 32) && (strlen(buf) > 200)) {
184                                 buf[a] = 0;
185                                 serv_puts(buf);
186                                 buf[0] = 0;
187                         }
188                         if (strlen(buf) > 250) {
189                                 serv_puts(buf);
190                                 buf[0] = 0;
191                         }
192                 }
193         }
194         serv_puts(buf);
195
196 }
197
198
199
200 /*
201  * translate server message output to text
202  * (used for editing room info files and such)
203  */
204 void server_to_text()
205 {
206         char buf[SIZ];
207
208         int count = 0;
209
210         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
211                 if ((buf[0] == 32) && (count > 0)) {
212                         wprintf("\n");
213                 }
214                 wprintf("%s", buf);
215                 ++count;
216         }
217 }
218
219
220
221 /*
222  * Read binary data from server into memory using a series of
223  * server READ commands.
224  */
225 void read_server_binary(char *buffer, size_t total_len) {
226         char buf[SIZ];
227         size_t bytes = 0;
228         size_t thisblock = 0;
229
230         memset(buffer, 0, total_len);
231         while (bytes < total_len) {
232                 thisblock = 4095;
233                 if ((total_len - bytes) < thisblock) {
234                         thisblock = total_len - bytes;
235                         if (thisblock == 0) return;
236                 }
237                 serv_printf("READ %d|%d", (int)bytes, (int)thisblock);
238                 serv_getln(buf, sizeof buf);
239                 if (buf[0] == '6') {
240                         thisblock = (size_t)atoi(&buf[4]);
241                         if (!WC->connected) return;
242                         serv_read(&buffer[bytes], thisblock);
243                         bytes += thisblock;
244                 }
245                 else {
246                         lprintf(3, "Error: %s\n", &buf[4]);
247                         return;
248                 }
249         }
250 }
251
252
253 /*
254  * Read text from server, appending to a string buffer until the
255  * usual 000 terminator is found.  Caller is responsible for freeing
256  * the returned pointer.
257  */
258 char *read_server_text(void) {
259         char *text = NULL;
260         size_t bytes_allocated = 0;
261         size_t bytes_read = 0;
262         int linelen;
263         char buf[SIZ];
264
265         text = malloc(SIZ);
266         if (text == NULL) {
267                 return(NULL);
268         }
269         text[0] = 0;
270         bytes_allocated = SIZ;
271
272         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
273                 linelen = strlen(buf);
274                 buf[linelen] = '\n';
275                 buf[linelen+1] = 0;
276                 ++linelen;
277
278                 if ((bytes_read + linelen) >= (bytes_allocated - 2)) {
279                         bytes_allocated = 2 * bytes_allocated;
280                         text = realloc(text, bytes_allocated);
281                 }
282
283                 strcpy(&text[bytes_read], buf);
284                 bytes_read += linelen;
285         }
286
287         return(text);
288 }