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