2 * Copyright (C) 2007 Martin Willi
3 * Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 #include <utils/linked_list.h>
28 typedef struct private_session_t private_session_t
;
31 * private data of the task manager
33 struct private_session_t
{
43 char sid
[COOKIE_LEN
* 2 + 1];
46 * have we sent the session cookie?
51 * list of controller instances controller_t
53 linked_list_t
*controllers
;
56 * list of filter instances filter_t
58 linked_list_t
*filters
;
61 * user defined session context
67 * Implementation of session_t.add_controller.
69 static void add_controller(private_session_t
*this, controller_t
*controller
)
71 this->controllers
->insert_last(this->controllers
, controller
);
75 * Implementation of session_t.add_filter.
77 static void add_filter(private_session_t
*this, filter_t
*filter
)
79 this->filters
->insert_last(this->filters
, filter
);
83 * Create a session ID and a cookie
85 static void create_sid(private_session_t
*this)
90 memset(buf
, 0, sizeof(buf
));
91 memset(this->sid
, 0, sizeof(this->sid
));
92 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
95 rng
->get_bytes(rng
, sizeof(buf
), buf
);
98 chunk_to_hex(chunk_create(buf
, sizeof(buf
)), this->sid
, FALSE
);
102 * run all registered filters
104 static bool run_filter(private_session_t
*this, request_t
*request
, char *p0
,
105 char *p1
, char *p2
, char *p3
, char *p4
, char *p5
)
107 enumerator_t
*enumerator
;
110 enumerator
= this->filters
->create_enumerator(this->filters
);
111 while (enumerator
->enumerate(enumerator
, &filter
))
113 if (!filter
->run(filter
, request
, p0
, p1
, p2
, p3
, p4
, p5
))
115 enumerator
->destroy(enumerator
);
119 enumerator
->destroy(enumerator
);
124 * Implementation of session_t.process.
126 static void process(private_session_t
*this, request_t
*request
)
128 char *pos
, *start
, *param
[6] = {NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
129 enumerator_t
*enumerator
;
130 bool handled
= FALSE
;
131 controller_t
*current
;
134 if (!this->cookie_sent
)
136 request
->add_cookie(request
, "SID", this->sid
);
137 this->cookie_sent
= TRUE
;
140 start
= request
->get_path(request
);
147 while ((pos
= strchr(start
, '/')) != NULL
&& i
< 5)
149 param
[i
++] = strndupa(start
, pos
- start
);
152 param
[i
] = strdupa(start
);
154 if (run_filter(this, request
, param
[0], param
[1], param
[2], param
[3],
157 enumerator
= this->controllers
->create_enumerator(this->controllers
);
158 while (enumerator
->enumerate(enumerator
, ¤t
))
160 if (streq(current
->get_name(current
), param
[0]))
162 current
->handle(current
, request
, param
[1], param
[2],
163 param
[3], param
[4], param
[5]);
168 enumerator
->destroy(enumerator
);
177 if (this->controllers
->get_first(this->controllers
,
178 (void**)¤t
) == SUCCESS
)
180 request
->streamf(request
,
181 "Status: 301 Moved permanently\nLocation: %s/%s\n\n",
182 request
->get_base(request
), current
->get_name(current
));
188 * Implementation of session_t.get_sid.
190 static char* get_sid(private_session_t
*this)
196 * Implementation of session_t.destroy
198 static void destroy(private_session_t
*this)
200 this->controllers
->destroy_offset(this->controllers
, offsetof(controller_t
, destroy
));
201 this->filters
->destroy_offset(this->filters
, offsetof(filter_t
, destroy
));
202 DESTROY_IF(this->context
);
209 session_t
*session_create(context_t
*context
)
211 private_session_t
*this = malloc_thing(private_session_t
);
213 this->public.add_controller
= (void(*)(session_t
*, controller_t
*))add_controller
;
214 this->public.add_filter
= (void(*)(session_t
*, filter_t
*))add_filter
;
215 this->public.process
= (void(*)(session_t
*,request_t
*))process
;
216 this->public.get_sid
= (char*(*)(session_t
*))get_sid
;
217 this->public.destroy
= (void(*)(session_t
*))destroy
;
220 this->cookie_sent
= FALSE
;
221 this->controllers
= linked_list_create();
222 this->filters
= linked_list_create();
223 this->context
= context
;
225 return &this->public;