* Replaced serv_gets() with serv_getln() - which now requires the caller
[citadel.git] / webcit / subst.c
1 /*
2  * $Id$
3  *
4  * Variable substitution type stuff
5  *
6  */
7
8
9
10 #include <ctype.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <stdio.h>
14 #include <fcntl.h>
15 #include <signal.h>
16 #include <sys/types.h>
17 #include <sys/wait.h>
18 #include <sys/socket.h>
19 #include <sys/time.h>
20 #include <sys/stat.h>
21 #include <limits.h>
22 #include <netinet/in.h>
23 #include <netdb.h>
24 #include <string.h>
25 #include <pwd.h>
26 #include <errno.h>
27 #include <stdarg.h>
28 #include <pthread.h>
29 #include <signal.h>
30 #include "webcit.h"
31
32
33 /*
34  * Clear out the list of substitution variables local to this session
35  */
36 void clear_local_substs(void) {
37         struct wcsubst *ptr;
38
39         while (WC->vars != NULL) {
40                 ptr = WC->vars->next;
41
42                 if ((WC->vars->wcs_type == WCS_STRING)
43                    || (WC->vars->wcs_type == WCS_SERVCMD)) {
44                         free(WC->vars->wcs_value);
45                 }
46
47                 free(WC->vars);
48                 WC->vars = ptr;
49         }
50
51         WC->vars = NULL;
52 }
53
54
55 /*
56  * Add a substitution variable (local to this session)
57  */
58 void svprintf(char *keyname, int keytype, const char *format,...)
59 {
60         va_list arg_ptr;
61         char wbuf[SIZ];
62         struct wcsubst *ptr = NULL;
63         struct wcsubst *scan;
64
65         /* First scan through to see if we're doing a replacement of
66          * an existing key
67          */
68         for (scan=WC->vars; scan!=NULL; scan=scan->next) {
69                 if (!strcasecmp(scan->wcs_key, keyname)) {
70                         ptr = scan;
71                         free(ptr->wcs_value);
72                 }
73         }
74
75         /* Otherwise allocate a new one */
76         if (ptr == NULL) {
77                 ptr = (struct wcsubst *) malloc(sizeof(struct wcsubst));
78                 ptr->next = WC->vars;
79                 safestrncpy(ptr->wcs_key, keyname, sizeof ptr->wcs_key);
80                 WC->vars = ptr;
81         }
82
83         /* Format the string and save it */
84
85         va_start(arg_ptr, format);
86         vsnprintf(wbuf, sizeof wbuf, format, arg_ptr);
87         va_end(arg_ptr);
88
89         ptr->wcs_type = keytype;
90         ptr->wcs_value = strdup(wbuf);
91 }
92
93 /*
94  * Add a substitution variable (local to this session) that does a callback
95  */
96 void svcallback(char *keyname, void (*fcn_ptr)() )
97 {
98         struct wcsubst *ptr;
99
100         ptr = (struct wcsubst *) malloc(sizeof(struct wcsubst));
101         ptr->next = WC->vars;
102         ptr->wcs_type = WCS_FUNCTION;
103         strcpy(ptr->wcs_key, keyname);
104         ptr->wcs_function = fcn_ptr;
105         WC->vars = ptr;
106 }
107
108
109
110 /*
111  * back end for print_value_of() ... does a server command
112  */
113 void pvo_do_cmd(char *servcmd) {
114         char buf[SIZ];
115
116         serv_puts(servcmd);
117         serv_getln(buf, sizeof buf);
118
119         switch(buf[0]) {
120                 case '2':
121                 case '3':
122                 case '5':
123                         wprintf("%s\n", &buf[4]);
124                         break;
125                 case '1':
126                         fmout(NULL, "CENTER");
127                         break;
128                 case '4':
129                         wprintf("%s\n", &buf[4]);
130                         serv_puts("000");
131                         break;
132         }
133 }
134
135
136
137 /*
138  * Print the value of a variable
139  */
140 void print_value_of(char *keyname) {
141         struct wcsubst *ptr;
142         void *fcn();
143
144         if (keyname[0] == '=') {
145                 do_template(&keyname[1]);
146         }
147
148         if (!strcasecmp(keyname, "SERV_PID")) {
149                 wprintf("%d", WC->ctdl_pid);
150         }
151
152         else if (!strcasecmp(keyname, "SERV_NODENAME")) {
153                 escputs(serv_info.serv_nodename);
154         }
155
156         else if (!strcasecmp(keyname, "SERV_HUMANNODE")) {
157                 escputs(serv_info.serv_humannode);
158         }
159
160         else if (!strcasecmp(keyname, "SERV_FQDN")) {
161                 escputs(serv_info.serv_fqdn);
162         }
163
164         else if (!strcasecmp(keyname, "SERV_SOFTWARE")) {
165                 escputs(serv_info.serv_software);
166         }
167
168         else if (!strcasecmp(keyname, "SERV_REV_LEVEL")) {
169                 wprintf("%d.%02d",
170                         serv_info.serv_rev_level / 100,
171                         serv_info.serv_rev_level % 100
172                 );
173         }
174
175         else if (!strcasecmp(keyname, "SERV_BBS_CITY")) {
176                 escputs(serv_info.serv_bbs_city);
177         }
178
179         else if (!strcasecmp(keyname, "CURRENT_USER")) {
180                 escputs(WC->wc_username);
181         }
182
183         else if (!strcasecmp(keyname, "CURRENT_ROOM")) {
184                 escputs(WC->wc_roomname);
185         }
186
187         /* Page-local variables */
188         else for (ptr = WC->vars; ptr != NULL; ptr = ptr->next) {
189                 if (!strcasecmp(ptr->wcs_key, keyname)) {
190                         if (ptr->wcs_type == WCS_STRING) {
191                                 wprintf("%s", ptr->wcs_value);
192                         }
193                         else if (ptr->wcs_type == WCS_SERVCMD) {
194                                 pvo_do_cmd(ptr->wcs_value);
195                         }
196                         else if (ptr->wcs_type == WCS_FUNCTION) {
197                                 (*ptr->wcs_function) ();
198                         }
199                 }
200         }
201 }
202
203
204
205 /*
206  * Display a variable-substituted template
207  */
208 void do_template(void *templatename) {
209         char filename[PATH_MAX];
210         FILE *fp;
211         char inbuf[1024];
212         char outbuf[sizeof inbuf];
213         char key[sizeof inbuf];
214         int i, pos;
215
216         strcpy(filename, "static/");
217         strcat(filename, templatename);
218         if (WC->is_wap)
219                 strcat(filename, ".wml");
220         else
221                 strcat(filename, ".html");
222         
223         fp = fopen(filename, "r");
224         if (fp == NULL) {
225                 wprintf("<BLINK>ERROR</BLINK> - could not open template ");
226                 wprintf("'%s' - %s<br />\n",
227                         templatename, strerror(errno));
228                 return;
229         }
230
231         strcpy(inbuf, "");
232
233         while (fgets(inbuf, sizeof inbuf, fp) != NULL) {
234                 strcpy(outbuf, "");
235
236                 while (strlen(inbuf) > 0) {
237                         pos = (-1);
238                         for (i=strlen(inbuf); i>=0; --i) {
239                                 if ((inbuf[i]=='<')&&(inbuf[i+1]=='?')) pos = i;
240                         }
241                         if (pos < 0) {
242                                 wprintf("%s", inbuf);
243                                 strcpy(inbuf, "");
244                         }
245                         else {
246                                 strncpy(outbuf, inbuf, pos);
247                                 outbuf[pos] = 0;
248                                 wprintf("%s", outbuf);
249                                 strcpy(inbuf, &inbuf[pos]);
250                                 pos = 1;
251                                 for (i=strlen(inbuf); i>=0; --i) {
252                                         if (inbuf[i]=='>') pos = i;
253                                 }
254                                 strncpy(key, &inbuf[2], pos-2);
255                                 key[pos-2] = 0;
256                                 print_value_of(key);
257                                 strcpy(inbuf, &inbuf[pos+1]);
258                         }
259                 }
260         }
261
262         fclose(fp);
263 }