manager can query and list IKE_SA status (no layout yet)
[strongswan.git] / src / manager / lib / request.c
1 /**
2 * @file request.c
3 *
4 * @brief Implementation of request_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2007 Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #define _GNU_SOURCE
24
25 #include "request.h"
26
27 #include <stdlib.h>
28
29 #include <dict.h>
30
31 typedef struct private_request_t private_request_t;
32
33 /**
34 * private data of the task manager
35 */
36 struct private_request_t {
37
38 /**
39 * public functions
40 */
41 request_t public;
42
43 /**
44 * the associated fcgi request
45 */
46 FCGX_Request *req;
47
48 /**
49 * list of cookies
50 */
51 dict_t *cookies;
52
53 /**
54 * list of post data
55 */
56 dict_t *posts;
57 };
58
59 /**
60 * Implementation of request_t.get_cookie.
61 */
62 static char* get_cookie(private_request_t *this, char *name)
63 {
64 return this->cookies->get(this->cookies, name);
65 }
66
67 /**
68 * Implementation of request_t.get_path.
69 */
70 static char* get_path(private_request_t *this)
71 {
72 char * path = FCGX_GetParam("PATH_INFO", this->req->envp);
73 return path ? path : "";
74 }
75
76 /**
77 * Implementation of request_t.get_post_data.
78 */
79 static char* get_post_data(private_request_t *this, char *name)
80 {
81 return this->posts->get(this->posts, name);
82 }
83
84 /**
85 * convert 2 digit hex string to a integer
86 */
87 static char hex2char(char *hex)
88 {
89 static char hexdig[] = "00112233445566778899AaBbCcDdEeFf";
90
91 return (strchr(hexdig, hex[1]) - hexdig)/2 +
92 ((strchr(hexdig, hex[0]) - hexdig)/2 * 16);
93 }
94
95 /**
96 * unescape a string up to the delimiter, and return a clone
97 */
98 static char *unescape(char **pos, char delimiter)
99 {
100 char *ptr, *res, *end, code[3] = {'\0','\0','\0'};
101
102 if (**pos == '\0')
103 {
104 return NULL;
105 }
106 ptr = strchr(*pos, delimiter);
107 if (ptr)
108 {
109 res = strndup(*pos, ptr - *pos);
110 *pos = ptr + 1;
111 }
112 else
113 {
114 res = strdup(*pos);
115 *pos = "";
116 }
117 end = res + strlen(res) + 1;
118 /* replace '+' with ' ' */
119 ptr = res;
120 while ((ptr = strchr(ptr, '+')))
121 {
122 *ptr = ' ';
123 }
124 /* replace %HH with its ascii value */
125 ptr = res;
126 while ((ptr = strchr(ptr, '%')))
127 {
128 if (ptr > end - 2)
129 {
130 break;
131 }
132 strncpy(code, ptr + 1, 2);
133 *ptr = hex2char(code);
134 memmove(ptr + 1, ptr + 3, end - (ptr + 3));
135 }
136 return res;
137 }
138
139 /**
140 * parse the http POST data
141 */
142 static void parse_post(private_request_t *this)
143 {
144 char buf[4096], *pos, *name, *value;
145 int len;
146
147 if (!streq(FCGX_GetParam("REQUEST_METHOD", this->req->envp), "POST") ||
148 !streq(FCGX_GetParam("CONTENT_TYPE", this->req->envp),
149 "application/x-www-form-urlencoded"))
150 {
151 return;
152 }
153
154 len = FCGX_GetStr(buf, sizeof(buf) - 1, this->req->in);
155 if (len != atoi(FCGX_GetParam("CONTENT_LENGTH", this->req->envp)))
156 {
157 return;
158 }
159 buf[len] = 0;
160
161 pos = buf;
162 while (TRUE)
163 {
164 name = unescape(&pos, '=');
165 if (name)
166 {
167 value = unescape(&pos, '&');
168 if (value)
169 {
170 this->posts->set(this->posts, name, value);
171 continue;
172 }
173 else
174 {
175 free(name);
176 }
177 }
178 break;
179 }
180 }
181
182 /**
183 * parse the requests cookies
184 */
185 static void parse_cookies(private_request_t *this)
186 {
187 char *str, *pos;
188 char *name, *value;
189
190 str = FCGX_GetParam("HTTP_COOKIE", this->req->envp);
191 while (str)
192 {
193 if (*str == ' ')
194 {
195 str++;
196 continue;
197 }
198 pos = strchr(str, '=');
199 if (pos == NULL)
200 {
201 break;
202 }
203 name = strndup(str, pos - str);
204 value = NULL;
205 str = pos + 1;
206 if (str)
207 {
208 pos = strchr(str, ';');
209 if (pos)
210 {
211 value = strndup(str, pos - str);
212 }
213 else
214 {
215 value = strdup(str);
216 }
217 }
218 this->cookies->set(this->cookies, name, value);
219 if (pos == NULL)
220 {
221 break;
222 }
223 str = pos + 1;
224 }
225 }
226
227 /**
228 * Implementation of request_t.destroy
229 */
230 static void destroy(private_request_t *this)
231 {
232 this->cookies->destroy(this->cookies);
233 this->posts->destroy(this->posts);
234 free(this);
235 }
236
237 /*
238 * see header file
239 */
240 request_t *request_create(FCGX_Request *request)
241 {
242 private_request_t *this = malloc_thing(private_request_t);
243
244 this->public.get_path = (char*(*)(request_t*))get_path;
245 this->public.get_cookie = (char*(*)(request_t*,char*))get_cookie;
246 this->public.get_post_data = (char*(*)(request_t*, char *name))get_post_data;
247 this->public.destroy = (void(*)(request_t*))destroy;
248
249 this->req = request;
250 this->cookies = dict_create(dict_streq, free, free);
251 this->posts = dict_create(dict_streq, free, free);
252
253 parse_cookies(this);
254 parse_post(this);
255
256 return &this->public;
257 }
258