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>
26 typedef struct private_session_t private_session_t
;
29 * private data of the task manager
31 struct private_session_t
{
44 * list of controller instances controller_t
46 linked_list_t
*controllers
;
49 * list of filter instances filter_t
51 linked_list_t
*filters
;
54 * user defined session context
60 * Implementation of session_t.add_controller.
62 static void add_controller(private_session_t
*this, controller_t
*controller
)
64 this->controllers
->insert_last(this->controllers
, controller
);
68 * Implementation of session_t.add_filter.
70 static void add_filter(private_session_t
*this, filter_t
*filter
)
72 this->filters
->insert_last(this->filters
, filter
);
76 * Create a session ID and a cookie
78 static void create_sid(private_session_t
*this, request_t
*request
)
81 chunk_t chunk
= chunk_from_buf(buf
);
84 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
87 rng
->get_bytes(rng
, sizeof(buf
), buf
);
88 this->sid
= chunk_to_hex(chunk
, NULL
, FALSE
).ptr
;
89 request
->add_cookie(request
, "SID", this->sid
);
95 * run all registered filters
97 static bool run_filter(private_session_t
*this, request_t
*request
, char *p0
,
98 char *p1
, char *p2
, char *p3
, char *p4
, char *p5
)
100 enumerator_t
*enumerator
;
103 enumerator
= this->filters
->create_enumerator(this->filters
);
104 while (enumerator
->enumerate(enumerator
, &filter
))
106 if (!filter
->run(filter
, request
, p0
, p1
, p2
, p3
, p4
, p5
))
108 enumerator
->destroy(enumerator
);
112 enumerator
->destroy(enumerator
);
117 * Implementation of session_t.process.
119 static void process(private_session_t
*this, request_t
*request
)
121 char *pos
, *start
, *param
[6] = {NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
122 enumerator_t
*enumerator
;
123 bool handled
= FALSE
;
124 controller_t
*current
;
127 if (this->sid
== NULL
)
129 create_sid(this, request
);
132 start
= request
->get_path(request
);
139 while ((pos
= strchr(start
, '/')) != NULL
&& i
< 5)
141 param
[i
++] = strndupa(start
, pos
- start
);
144 param
[i
] = strdupa(start
);
146 if (run_filter(this, request
, param
[0], param
[1], param
[2], param
[3],
149 enumerator
= this->controllers
->create_enumerator(this->controllers
);
150 while (enumerator
->enumerate(enumerator
, ¤t
))
152 if (streq(current
->get_name(current
), param
[0]))
154 current
->handle(current
, request
, param
[1], param
[2],
155 param
[3], param
[4], param
[5]);
160 enumerator
->destroy(enumerator
);
169 if (this->controllers
->get_first(this->controllers
,
170 (void**)¤t
) == SUCCESS
)
172 request
->redirect(request
, current
->get_name(current
));
178 * Implementation of session_t.get_sid.
180 static char* get_sid(private_session_t
*this)
186 * Implementation of session_t.destroy
188 static void destroy(private_session_t
*this)
190 this->controllers
->destroy_offset(this->controllers
, offsetof(controller_t
, destroy
));
191 this->filters
->destroy_offset(this->filters
, offsetof(filter_t
, destroy
));
192 DESTROY_IF(this->context
);
200 session_t
*session_create(context_t
*context
)
202 private_session_t
*this = malloc_thing(private_session_t
);
204 this->public.add_controller
= (void(*)(session_t
*, controller_t
*))add_controller
;
205 this->public.add_filter
= (void(*)(session_t
*, filter_t
*))add_filter
;
206 this->public.process
= (void(*)(session_t
*,request_t
*))process
;
207 this->public.get_sid
= (char*(*)(session_t
*))get_sid
;
208 this->public.destroy
= (void(*)(session_t
*))destroy
;
211 this->controllers
= linked_list_create();
212 this->filters
= linked_list_create();
213 this->context
= context
;
215 return &this->public;