strongswan/src/manager/lib/response.c

224 lines
5.0 KiB
C

/**
* @file response.c
*
* @brief Implementation of response_t.
*
*/
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "response.h"
#include <stdlib.h>
#include <stdarg.h>
#include <utils/linked_list.h>
typedef struct {
char *name;
char *value;
} name_value_t;
/**
* create name value pair
*/
static name_value_t *name_value_create(char *name, char *value)
{
name_value_t *this = malloc_thing(name_value_t);
this->name = strdup(name);
this->value = strdup(value);
return this;
}
/**
* destroy a name value pair
*/
static void name_value_destroy(name_value_t *this)
{
free(this->name);
free(this->value);
free(this);
}
typedef struct private_response_t private_response_t;
/**
* private data of the task manager
*/
struct private_response_t {
/**
* public functions
*/
response_t public;
/**
* the associated fcgi request
*/
FCGX_Request *req;
/**
* Content type
*/
char *content_type;
/**
* list of cookies (name_value_t)
*/
linked_list_t *cookies;
/**
* list of custom headers (name_value_t)
*/
linked_list_t *headers;
/**
* headers already written?
*/
bool started;
};
/**
* write the headers, if not already written
*/
static void write_headers(private_response_t *this)
{
iterator_t *iterator;
name_value_t *current;
FCGX_FPrintF(this->req->out, "Content-type: %s\n", this->content_type);
iterator = this->cookies->create_iterator(this->cookies, TRUE);
while (iterator->iterate(iterator, (void**)&current))
{
FCGX_FPrintF(this->req->out, "Set-Cookie: %s=%s; path=%s\n",
current->name, current->value,
FCGX_GetParam("SCRIPT_NAME", this->req->envp));
}
iterator->destroy(iterator);
iterator = this->cookies->create_iterator(this->headers, TRUE);
while (iterator->iterate(iterator, (void**)&current))
{
FCGX_FPrintF(this->req->out, "%s: %s\n",
current->name, current->value);
}
iterator->destroy(iterator);
FCGX_PutChar('\n', this->req->out);
this->started = TRUE;
}
/**
* Implementation of response_t.print.
*/
static void print_(private_response_t *this, char *str)
{
if (!this->started)
{
write_headers(this);
}
FCGX_PutS(str, this->req->out);
}
/**
* Implementation of response_t.printf.
*/
static void printf_(private_response_t *this, char *format, ...)
{
va_list args;
if (!this->started)
{
write_headers(this);
}
va_start(args, format);
FCGX_VFPrintF(this->req->out, format, args);
va_end(args);
}
/**
* Implementation of response_t.add_header.
*/
static void add_header(private_response_t *this, char *name, char *value)
{
this->headers->insert_last(this->headers, name_value_create(name, value));
}
/**
* Implementation of response_t.set_content_type.
*/
static void set_content_type(private_response_t *this, char *type)
{
free(this->content_type);
this->content_type = strdup(type);
}
/**
* Implementation of response_t.add_cookie.
*/
static void add_cookie(private_response_t *this, char *name, char *value)
{
this->cookies->insert_last(this->cookies, name_value_create(name, value));
}
/**
* Implementation of response_t.redirect.
*/
static void redirect(private_response_t *this, char *location)
{
FCGX_FPrintF(this->req->out, "Status: 303 See Other\n");
FCGX_FPrintF(this->req->out, "Location: %s%s%s\n\n",
FCGX_GetParam("SCRIPT_NAME", this->req->envp),
*location == '/' ? "" : "/", location);
}
/**
* Implementation of response_t.destroy
*/
static void destroy(private_response_t *this)
{
this->headers->destroy_function(this->headers, (void*)name_value_destroy);
this->cookies->destroy_function(this->cookies, (void*)name_value_destroy);
free(this->content_type);
free(this);
}
/*
* see header file
*/
response_t *response_create(FCGX_Request *request)
{
private_response_t *this = malloc_thing(private_response_t);
this->public.print = (void(*)(response_t*, char *str))print_;
this->public.printf = (void(*)(response_t*, char *format, ...))printf_;
this->public.add_header = (void(*)(response_t*, char *name, char *value))add_header;
this->public.set_content_type = (void(*)(response_t*, char *type))set_content_type;
this->public.add_cookie = (void(*)(response_t*, char *name, char *value))add_cookie;
this->public.redirect = (void(*)(response_t*, char *location))redirect;
this->public.destroy = (void(*)(response_t*))destroy;
this->req = request;
this->headers = linked_list_create();
this->cookies = linked_list_create();
this->content_type = strdup("text/html");
this->started = FALSE;
return &this->public;
}