1 /*****************************************************************************
2 * httpd.c: HTTPd wrapper
3 *****************************************************************************
4 * Copyright (C) 2007 the VideoLAN team
7 * Authors: Antoine Cellerier <dionoea at videolan tod org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
35 #include <vlc_common.h>
36 #include <vlc_httpd.h>
38 #include <lua.h> /* Low level lua C API */
39 #include <lauxlib.h> /* Higher level C API */
40 #include <lualib.h> /* Lua libs */
44 /*****************************************************************************
46 *****************************************************************************/
47 static uint8_t *vlclua_todata( lua_State *L, int narg, int *i_data );
49 /*****************************************************************************
51 *****************************************************************************/
53 /* This is kind of a useless function since TLS with the 4 last args
54 * unset does the same thing as far as I know. */
55 int vlclua_httpd_host_new( lua_State *L )
57 vlc_object_t *p_this = vlclua_get_this( L );
58 const char *psz_host = luaL_checkstring( L, 1 );
59 int i_port = luaL_checkint( L, 2 );
60 httpd_host_t *p_httpd_host = httpd_HostNew( p_this, psz_host, i_port );
62 return luaL_error( L, "Failed to create HTTP host \"%s:%d\".",
64 vlclua_push_vlc_object( L, p_httpd_host, vlclua_httpd_host_delete );
69 int vlclua_httpd_tls_host_new( lua_State *L )
71 vlc_object_t *p_this = vlclua_get_this( L );
72 const char *psz_host = luaL_checkstring( L, 1 );
73 int i_port = luaL_checkint( L, 2 );
74 const char *psz_cert = luaL_optstring( L, 3, NULL );
75 const char *psz_key = luaL_optstring( L, 4, NULL );
76 const char *psz_ca = luaL_optstring( L, 5, NULL );
77 const char *psz_crl = luaL_optstring( L, 6, NULL );
78 httpd_host_t *p_httpd_host = httpd_TLSHostNew( p_this, psz_host, i_port,
82 return luaL_error( L, "Failed to create HTTP TLS host \"%s:%d\" "
83 "(cert: \"%s\", key: \"%s\", ca: \"%s\", "
84 "crl: \"%s\").", psz_host, i_port,
85 psz_cert, psz_key, psz_ca, psz_crl );
86 vlclua_push_vlc_object( L, (vlc_object_t*)p_httpd_host, vlclua_httpd_host_delete );
90 #define ARG_1_IS_HTTPD_HOST httpd_host_t *p_httpd_host = \
91 (httpd_host_t*)vlclua_checkobject( L, 1, VLC_OBJECT_HTTPD_HOST );
92 int vlclua_httpd_host_delete( lua_State *L )
95 httpd_HostDelete( p_httpd_host );
99 /*****************************************************************************
101 *****************************************************************************/
102 struct httpd_handler_sys_t
108 static int vlclua_httpd_handler_callback(
109 httpd_handler_sys_t *p_sys, httpd_handler_t *p_handler, char *psz_url,
110 uint8_t *psz_request, int i_type, uint8_t *p_in, int i_in,
111 char *psz_remote_addr, char *psz_remote_host,
112 uint8_t **pp_data, int *pi_data )
114 VLC_UNUSED(p_handler);
115 lua_State *L = p_sys->L;
118 lua_pushvalue( L, 1 );
119 lua_pushvalue( L, 2 );
120 /* function data function data */
121 lua_pushstring( L, psz_url );
122 /* function data function data url */
123 lua_pushstring( L, (const char *)psz_request );
124 /* function data function data url request */
125 lua_pushinteger( L, i_type ); /* Q: what does i_type stand for? */
126 /* function data function data url request type */
127 lua_pushlstring( L, (const char *)p_in, i_in ); /* Q: what do p_in contain? */
128 /* function data function data url request type in */
129 lua_pushstring( L, psz_remote_addr );
130 /* function data function data url request type in addr */
131 lua_pushstring( L, psz_remote_host );
132 /* function data function data url request type in addr host */
133 if( lua_pcall( L, 7, 1, 0 ) )
135 /* function data err */
136 vlc_object_t *p_this = vlclua_get_this( L );
137 const char *psz_err = lua_tostring( L, -1 );
138 msg_Err( p_this, "Error while runing the lua HTTPd handler "
139 "callback: %s", psz_err );
144 /* function data outdata */
145 *pp_data = vlclua_todata( L, -1, pi_data );
151 int vlclua_httpd_handler_new( lua_State * L )
154 const char *psz_url = luaL_checkstring( L, 2 );
155 const char *psz_user = luaL_nilorcheckstring( L, 3 );
156 const char *psz_password = luaL_nilorcheckstring( L, 4 );
157 const vlc_acl_t *p_acl = NULL; /* FIXME 5 */
158 /* Stack item 6 is the callback function */
159 luaL_argcheck( L, lua_isfunction( L, 6 ), 6, "Should be a function" );
160 /* Stack item 7 is the callback data */
162 httpd_handler_sys_t *p_sys = (httpd_handler_sys_t*)
163 malloc( sizeof( httpd_handler_sys_t ) );
165 return luaL_error( L, "Failed to allocate private buffer." );
166 p_sys->L = lua_newthread( L );
167 p_sys->ref = luaL_ref( L, LUA_REGISTRYINDEX ); /* pops the object too */
168 /* use lua_xmove to move the lua callback function and data to
169 * the callback's stack. */
170 lua_xmove( L, p_sys->L, 2 );
171 httpd_handler_t *p_handler = httpd_HandlerNew(
172 p_httpd_host, psz_url, psz_user, psz_password,
173 p_acl, vlclua_httpd_handler_callback, p_sys );
175 return luaL_error( L, "Failed to create HTTPd handler." );
176 lua_pushlightuserdata( L, p_handler ); /* FIXME */
180 int vlclua_httpd_handler_delete( lua_State *L )
182 httpd_handler_t *p_handler = (httpd_handler_t*)luaL_checklightuserdata( L, 1 ); /* FIXME */
183 httpd_handler_sys_t *p_sys = httpd_HandlerDelete( p_handler );
184 luaL_unref( p_sys->L, LUA_REGISTRYINDEX, p_sys->ref );
189 /*****************************************************************************
191 *****************************************************************************/
192 struct httpd_file_sys_t
198 static int vlclua_httpd_file_callback(
199 httpd_file_sys_t *p_sys, httpd_file_t *p_file, uint8_t *psz_request,
200 uint8_t **pp_data, int *pi_data )
203 lua_State *L = p_sys->L;
206 lua_pushvalue( L, 1 );
207 lua_pushvalue( L, 2 );
208 /* function data function data */
209 lua_pushstring( L, (const char *)psz_request );
210 /* function data function data request */
211 if( lua_pcall( L, 2, 1, 0 ) )
213 /* function data err */
214 vlc_object_t *p_this = vlclua_get_this( L );
215 const char *psz_err = lua_tostring( L, -1 );
216 msg_Err( p_this, "Error while runing the lua HTTPd file callback: %s",
222 /* function data outdata */
223 *pp_data = vlclua_todata( L, -1, pi_data );
229 int vlclua_httpd_file_new( lua_State *L )
232 const char *psz_url = luaL_checkstring( L, 2 );
233 const char *psz_mime = luaL_nilorcheckstring( L, 3 );
234 const char *psz_user = luaL_nilorcheckstring( L, 4 );
235 const char *psz_password = luaL_nilorcheckstring( L, 5 );
236 const vlc_acl_t *p_acl = lua_isnil( L, 6 ) ? NULL : luaL_checklightuserdata( L, 6 );
237 /* Stack item 7 is the callback function */
238 luaL_argcheck( L, lua_isfunction( L, 7 ), 7, "Should be a function" );
239 /* Stack item 8 is the callback data */
240 httpd_file_sys_t *p_sys = (httpd_file_sys_t *)
241 malloc( sizeof( httpd_file_sys_t ) );
243 return luaL_error( L, "Failed to allocate private buffer." );
244 p_sys->L = lua_newthread( L );
245 p_sys->ref = luaL_ref( L, LUA_REGISTRYINDEX ); /* pops the object too */
246 lua_xmove( L, p_sys->L, 2 );
247 httpd_file_t *p_file = httpd_FileNew( p_httpd_host, psz_url, psz_mime,
248 psz_user, psz_password, p_acl,
249 vlclua_httpd_file_callback, p_sys );
251 return luaL_error( L, "Failed to create HTTPd file." );
252 lua_pushlightuserdata( L, p_file ); /* FIXME */
256 int vlclua_httpd_file_delete( lua_State *L )
258 httpd_file_t *p_file = (httpd_file_t*)luaL_checklightuserdata( L, 1 ); /* FIXME */
259 /* FIXME: How do we delete p_sys ? the struct is hidden in the VLC core */
260 httpd_file_sys_t *p_sys = httpd_FileDelete( p_file );
261 luaL_unref( p_sys->L, LUA_REGISTRYINDEX, p_sys->ref );
266 /*****************************************************************************
268 *****************************************************************************/
269 int vlclua_httpd_redirect_new( lua_State *L )
272 const char *psz_url_dst = luaL_checkstring( L, 2 );
273 const char *psz_url_src = luaL_checkstring( L, 3 );
274 httpd_redirect_t *p_redirect = httpd_RedirectNew( p_httpd_host,
278 return luaL_error( L, "Failed to create HTTPd redirect." );
279 lua_pushlightuserdata( L, p_redirect ); /* FIXME */
283 int vlclua_httpd_redirect_delete( lua_State *L )
285 httpd_redirect_t *p_redirect = (httpd_redirect_t*)luaL_checklightuserdata( L, 1 ); /* FIXME */
286 httpd_RedirectDelete( p_redirect );
290 /*****************************************************************************
292 *****************************************************************************/
293 static uint8_t *vlclua_todata( lua_State *L, int narg, int *pi_data )
296 const char *psz_data = lua_tolstring( L, narg, &i_data );
297 uint8_t *p_data = (uint8_t*)malloc( i_data * sizeof(uint8_t) );
298 *pi_data = (int)i_data;
301 luaL_error( L, "Error while allocating buffer." );
302 return NULL; /* To please gcc even though luaL_error longjmp-ed out of here */
304 memcpy( p_data, psz_data, i_data );