2 MiddleMan filtering proxy server
3 Copyright (C) 2002 Jason McLaughlin
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <sys/types.h>
29 parse <templates> section from xml config file
31 TEMPLATES *templates_load(TEMPLATES * templates, XML_LIST * xml_list)
33 TEMPLATES *templates_tmp = templates;
34 struct TEMPLATE_LIST *template_list = NULL;
36 if (templates_tmp == NULL) {
37 templates_tmp = xmalloc(sizeof(TEMPLATES));
38 templates_tmp->template_list = NULL;
39 templates_tmp->path = NULL;
40 templates_tmp->id = 0;
42 templates = templates_tmp;
44 pthread_rwlock_init(&templates_tmp->lock, NULL);
46 template_list = templates_tmp->template_list;
48 while ((xml_list = xml_section(xml_list, "<templates>"))) {
49 XML_LIST_LOOP(xml_list, "<templates>") {
50 XML_LIST_CMP(xml_list, "<template>") {
51 template_list = template_list_new(template_list);
52 template_list->id = templates->id++;
54 if (templates_tmp->template_list == NULL)
55 templates_tmp->template_list = template_list;
56 XML_LIST_LOOP(xml_list, "<template>") {
57 XML_LIST_CMP(xml_list, "<enabled>") {
58 xml_list = xml_list->next;
59 if (xml_list->type == XML_VALUE) {
60 if (!strcasecmp(xml_list->item, "false"))
61 template_list->enabled = FALSE;
63 template_list->enabled = TRUE;
66 XML_LIST_CMP(xml_list, "<comment>") {
67 xml_list = xml_list->next;
68 if (xml_list->type == XML_VALUE)
69 template_list_insert(template_list, xml_list->item, NULL, NULL, NULL, NULL, NULL);
71 XML_LIST_CMP(xml_list, "<name>") {
72 xml_list = xml_list->next;
73 if (xml_list->type == XML_VALUE)
74 template_list_insert(template_list, NULL, xml_list->item, NULL, NULL, NULL, NULL);
76 XML_LIST_CMP(xml_list, "<file>") {
77 xml_list = xml_list->next;
78 if (xml_list->type == XML_VALUE)
79 template_list_insert(template_list, NULL, NULL, xml_list->item, NULL, NULL, NULL);
81 XML_LIST_CMP(xml_list, "<type>") {
82 xml_list = xml_list->next;
83 if (xml_list->type == XML_VALUE)
84 template_list_insert(template_list, NULL, NULL, NULL, xml_list->item, NULL, NULL);
86 XML_LIST_CMP(xml_list, "<mime>") {
87 xml_list = xml_list->next;
88 if (xml_list->type == XML_VALUE)
89 template_list_insert(template_list, NULL, NULL, NULL, NULL, xml_list->item, NULL);
91 XML_LIST_CMP(xml_list, "<code>") {
92 xml_list = xml_list->next;
93 if (xml_list->type == XML_VALUE)
94 template_list_insert(template_list, NULL, NULL, NULL, NULL, NULL, xml_list->item);
98 XML_LIST_CMP(xml_list, "<path>") {
99 xml_list = xml_list->next;
100 if (xml_list->type == XML_VALUE) {
101 FREE_AND_NULL(templates_tmp->path);
102 templates_tmp->path = xstrdup(xml_list->item);
111 XML_LIST *templates_xml(TEMPLATES * templates, XML_LIST * xml_list)
114 struct TEMPLATE_LIST *tl;
116 if (templates == NULL)
119 pthread_rwlock_rdlock(&templates->lock);
121 xml_list = xml_list_add(xml_list, "<templates>", XML_TAG);
123 if (templates->path != NULL) {
124 xml_list = xml_list_add(xml_list, "<path>", XML_TAG);
125 ptr = string_to_xml(templates->path);
126 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
128 xml_list = xml_list_add(xml_list, "</path>", XML_TAG);
131 for (tl = templates->template_list; tl; tl = tl->next) {
132 xml_list = xml_list_add(xml_list, "<template>", XML_TAG);
134 xml_list = xml_list_add(xml_list, "<enabled>", XML_TAG);
135 xml_list = xml_list_add(xml_list, (tl->enabled == TRUE) ? "true" : "false", XML_VALUE);
136 xml_list = xml_list_add(xml_list, "</enabled>", XML_TAG);
138 if (tl->comment != NULL) {
139 xml_list = xml_list_add(xml_list, "<comment>", XML_TAG);
140 ptr = string_to_xml(tl->comment);
141 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
143 xml_list = xml_list_add(xml_list, "</comment>", XML_TAG);
146 if (tl->name != NULL) {
147 xml_list = xml_list_add(xml_list, "<name>", XML_TAG);
148 ptr = string_to_xml(tl->name);
149 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
151 xml_list = xml_list_add(xml_list, "</name>", XML_TAG);
154 if (tl->file != NULL) {
155 xml_list = xml_list_add(xml_list, "<file>", XML_TAG);
156 ptr = string_to_xml(tl->file);
157 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
159 xml_list = xml_list_add(xml_list, "</file>", XML_TAG);
162 if (tl->mime != NULL) {
163 xml_list = xml_list_add(xml_list, "<mime>", XML_TAG);
164 ptr = string_to_xml(tl->mime);
165 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
167 xml_list = xml_list_add(xml_list, "</mime>", XML_TAG);
170 if (tl->code != -1) {
171 xml_list = xml_list_add(xml_list, "<code>", XML_TAG);
172 snprintf(buf, sizeof(buf), "%d", tl->code);
173 xml_list = xml_list_add(xml_list, buf, XML_VALUE);
174 xml_list = xml_list_add(xml_list, "</code>", XML_TAG);
177 xml_list = xml_list_add(xml_list, "<type>", XML_TAG);
178 xml_list = xml_list_add(xml_list, (tl->type == TEMPLATE_FILE) ? "file" : "executable", XML_VALUE);
179 xml_list = xml_list_add(xml_list, "</type>", XML_TAG);
181 xml_list = xml_list_add(xml_list, "</template>", XML_TAG);
185 xml_list = xml_list_add(xml_list, "</templates>", XML_TAG);
187 pthread_rwlock_unlock(&templates->lock);
192 void template_list_insert(struct TEMPLATE_LIST *x, char *a, char *b, char *c, char *d, char *e, char *f)
195 FREE_AND_NULL(x->comment);
198 x->comment = xstrdup(a);
201 FREE_AND_NULL(x->name);
204 x->name = xstrdup(b);
207 FREE_AND_NULL(x->file);
210 x->file = xstrdup(c);
213 if (!strcasecmp(d, "file"))
214 x->type = TEMPLATE_FILE;
215 else if (!strcasecmp(d, "executable"))
216 x->type = TEMPLATE_EXECUTABLE;
219 FREE_AND_NULL(x->mime);
222 x->mime = xstrdup(e);
232 struct TEMPLATE_LIST *template_list_new(struct TEMPLATE_LIST *x)
235 x = xmalloc(sizeof(struct TEMPLATE_LIST));
238 while (x->next != NULL)
240 x->next = xmalloc(sizeof(struct TEMPLATE_LIST));
250 x->type = TEMPLATE_FILE;
256 struct TEMPLATE_LIST *template_list_delete(struct TEMPLATE_LIST *x)
258 struct TEMPLATE_LIST *start = x;
260 while (start->prev != NULL)
264 x->next->prev = x->prev;
266 x->prev->next = x->next;
270 FREE_AND_NULL(x->comment);
271 FREE_AND_NULL(x->name);
272 FREE_AND_NULL(x->file);
273 FREE_AND_NULL(x->mime);
281 free templates structure
283 void templates_free(TEMPLATES * templates)
288 templates_list_free(templates->template_list);
290 if (templates->path != NULL)
291 xfree(templates->path);
293 pthread_rwlock_destroy(&templates->lock);
298 void templates_list_free(struct TEMPLATE_LIST *tl)
300 struct TEMPLATE_LIST *tmp;
305 FREE_AND_NULL(tl->comment);
306 FREE_AND_NULL(tl->name);
307 FREE_AND_NULL(tl->file);
308 FREE_AND_NULL(tl->mime);
316 load a template from a file, and place in a buffer
318 FILEBUF *template_get(TEMPLATES * templates, CONNECTION * connection, char *name)
322 struct TEMPLATE_LIST *template_list = NULL;
325 pthread_rwlock_rdlock(&templates->lock);
326 template_list = templates->template_list;
328 while (template_list != NULL) {
329 /* search through templates from config file first */
330 if (template_list->name != NULL) {
331 if (template_list->enabled == TRUE && !strcasecmp(template_list->name, name))
335 template_list = template_list->next;
338 if (template_list == NULL || template_list->file == NULL) {
339 /* no matching template in config file, search through compiled-in templates */
340 while (PAGES[i].name != NULL) {
341 if (!strcasecmp(PAGES[i].name, name)) {
348 /* nope, nothing... oh well */
352 i = (PAGES[x].len != -1) ? PAGES[x].len : strlen(PAGES[x].content);
356 ret->data = xmalloc(i);
357 memcpy(ret->data, PAGES[x].content, i);
358 ret->type = xstrdup(PAGES[x].mime);
359 } else if (template_list->type == TEMPLATE_FILE) {
360 if (template_list->file[0] != '/' && templates->path != NULL)
361 snprintf(buf, sizeof(buf), "%s/%s", templates->path, template_list->file);
363 snprintf(buf, sizeof(buf), "%s", template_list->file);
367 filebuf_read(ret, buf);
369 if (template_list->mime != NULL)
370 ret->type = xstrdup(template_list->mime);
371 } else if (template_list->type == TEMPLATE_EXECUTABLE) {
372 ret = external_exec(connection, template_list->file, NULL, EXTERNAL_PIPE);
373 if (template_list->mime != NULL && ret != NULL) {
374 if (!strcasecmp(template_list->mime, "STDIN"))
375 ret->type = external_getmime(ret);
377 ret->type = xstrdup(template_list->mime);
381 if (ret != NULL && (ret->type == NULL || !strncasecmp(ret->type, "text/", 5))) {
382 /* replace variables with actual value, or just remove if value is unknown */
383 /* note: these can't be escaped... I should fix that */
384 string_replace(ret, "$HTTP_METHOD", (connection->header != NULL) ? connection->header->method : NULL);
385 string_replace(ret, "$HTTP_HOST", (connection->header != NULL) ? connection->header->host : NULL);
386 string_replace(ret, "$HTTP_FILE", (connection->header != NULL) ? connection->header->file : NULL);
387 snprintf(buf, sizeof(buf), "%d", (connection->header != NULL) ? connection->header->port : 0);
388 string_replace(ret, "$HTTP_PORT", buf);
390 string_replace(ret, "$IP", connection->ip);
393 if (template_list != NULL && ret != NULL)
394 ret->code = template_list->code;
397 pthread_rwlock_unlock(&templates->lock);
403 send a template with http headers and proper mime type to web browser
405 int template_send(TEMPLATES * templates, char *template, CONNECTION * connection, int error)
407 FILEBUF *filebuf = NULL;
410 filebuf = template_get(templates, connection, template);
415 header = header_new();
416 header->type = HTTP_RESP;
417 header->code = (filebuf->code != -1) ? filebuf->code : error;
418 header->content_length = filebuf->size;
419 header->content_type = (filebuf->type != NULL) ? xstrdup(filebuf->type) : xstrdup("text/plain");
421 header_send(header, connection, CLIENT, HEADER_RESP);
422 http_header_free(header);
424 /* don't actually send anything if this is a HEAD request */
425 if (connection->header == NULL || strcasecmp(connection->header->method, "HEAD"))
426 net_filebuf_send(filebuf, connection, CLIENT);
428 putlog(MMLOG_TEMPLATE, "sent %s", template);
430 filebuf_free(filebuf);