4 #include "http_vhostdb.h"
6 #include "stat_cache.h"
17 buffer
*vhostdb_backend_conf
;
20 const http_vhostdb_backend_t
*vhostdb_backend
;
25 plugin_config
**config_storage
;
31 INIT_FUNC(mod_vhostdb_init
) {
32 plugin_data
*p
= calloc(1, sizeof(*p
));
33 p
->tmp_buf
= buffer_init();
37 FREE_FUNC(mod_vhostdb_free
) {
39 if (!p
) return HANDLER_GO_ON
;
41 if (p
->config_storage
) {
43 for (i
= 0; i
< srv
->config_context
->used
; i
++) {
44 plugin_config
*s
= p
->config_storage
[i
];
45 if (NULL
== s
) continue;
46 buffer_free(s
->vhostdb_backend_conf
);
49 free(p
->config_storage
);
59 SETDEFAULTS_FUNC(mod_vhostdb_set_defaults
) {
61 config_values_t cv
[] = {
62 { "vhostdb.backend", NULL
, T_CONFIG_STRING
, T_CONFIG_SCOPE_CONNECTION
}, /* 0 */
64 { NULL
, NULL
, T_CONFIG_UNSET
, T_CONFIG_SCOPE_UNSET
}
67 p
->config_storage
= calloc(1, srv
->config_context
->used
* sizeof(plugin_config
*));
69 for (size_t i
= 0; i
< srv
->config_context
->used
; ++i
) {
70 data_config
const *config
= (data_config
const*)srv
->config_context
->data
[i
];
71 plugin_config
*s
= calloc(1, sizeof(plugin_config
));
72 s
->vhostdb_backend_conf
= buffer_init();
74 cv
[0].destination
= s
->vhostdb_backend_conf
;
76 p
->config_storage
[i
] = s
;
78 if (0 != config_insert_values_global(srv
, config
->value
, cv
, i
== 0 ? T_CONFIG_SCOPE_SERVER
: T_CONFIG_SCOPE_CONNECTION
)) {
82 if (!buffer_string_is_empty(s
->vhostdb_backend_conf
)) {
84 http_vhostdb_backend_get(s
->vhostdb_backend_conf
);
85 if (NULL
== s
->vhostdb_backend
) {
86 log_error_write(srv
, __FILE__
, __LINE__
, "sb",
87 "vhostdb.backend not supported:",
88 s
->vhostdb_backend_conf
);
99 static int mod_vhostdb_patch_connection(server
*srv
, connection
*con
, plugin_data
*p
) {
100 plugin_config
*s
= p
->config_storage
[0];
101 PATCH(vhostdb_backend
);
103 /* skip the first, the global context */
104 for (size_t i
= 1; i
< srv
->config_context
->used
; ++i
) {
105 data_config
*dc
= (data_config
*)srv
->config_context
->data
[i
];
106 s
= p
->config_storage
[i
];
108 /* condition didn't match */
109 if (!config_check_cond(srv
, con
, dc
)) continue;
112 for (size_t j
= 0; j
< dc
->value
->used
; ++j
) {
113 data_unset
*du
= dc
->value
->data
[j
];
115 if (buffer_is_equal_string(du
->key
, CONST_STR_LEN("vhostdb.backend"))) {
116 PATCH(vhostdb_backend
);
127 buffer
*document_root
;
130 static vhostdb_entry
* vhostdb_entry_init (void)
132 vhostdb_entry
*ve
= calloc(1, sizeof(*ve
));
133 ve
->server_name
= buffer_init();
134 ve
->document_root
= buffer_init();
138 static void vhostdb_entry_free (vhostdb_entry
*ve
)
140 buffer_free(ve
->server_name
);
141 buffer_free(ve
->document_root
);
145 CONNECTION_FUNC(mod_vhostdb_handle_connection_close
) {
146 plugin_data
*p
= p_d
;
149 if ((ve
= con
->plugin_ctx
[p
->id
])) {
150 con
->plugin_ctx
[p
->id
] = NULL
;
151 vhostdb_entry_free(ve
);
155 return HANDLER_GO_ON
;
158 static handler_t
mod_vhostdb_error_500 (connection
*con
)
160 con
->http_status
= 500; /* Internal Server Error */
162 return HANDLER_FINISHED
;
165 static handler_t
mod_vhostdb_found (connection
*con
, vhostdb_entry
*ve
)
167 /* fix virtual server and docroot */
168 buffer_copy_buffer(con
->server_name
, ve
->server_name
);
169 buffer_copy_buffer(con
->physical
.doc_root
, ve
->document_root
);
170 return HANDLER_GO_ON
;
173 CONNECTION_FUNC(mod_vhostdb_handle_docroot
) {
174 plugin_data
*p
= p_d
;
176 const http_vhostdb_backend_t
*backend
;
178 stat_cache_entry
*sce
;
180 /* no host specified? */
181 if (buffer_string_is_empty(con
->uri
.authority
)) return HANDLER_GO_ON
;
183 /* XXX: future: implement larger, managed cache
184 * of database responses (positive and negative) */
186 /* check if cached this connection */
187 ve
= con
->plugin_ctx
[p
->id
];
188 if (ve
&& buffer_is_equal(ve
->server_name
, con
->uri
.authority
)) {
189 return mod_vhostdb_found(con
, ve
); /* HANDLER_GO_ON */
192 mod_vhostdb_patch_connection(srv
, con
, p
);
193 if (!p
->conf
.vhostdb_backend
) return HANDLER_GO_ON
;
196 backend
= p
->conf
.vhostdb_backend
;
197 if (0 != backend
->query(srv
, con
, backend
->p_d
, b
)) {
198 return mod_vhostdb_error_500(con
); /* HANDLER_FINISHED */
201 if (buffer_string_is_empty(b
)) {
202 /* no such virtual host */
203 return HANDLER_GO_ON
;
206 /* sanity check that really is a directory */
207 buffer_append_slash(b
);
208 if (HANDLER_ERROR
== stat_cache_get_entry(srv
, con
, b
, &sce
)) {
209 log_error_write(srv
, __FILE__
, __LINE__
, "sb", strerror(errno
), b
);
210 return mod_vhostdb_error_500(con
); /* HANDLER_FINISHED */
212 if (!S_ISDIR(sce
->st
.st_mode
)) {
213 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "Not a directory", b
);
214 return mod_vhostdb_error_500(con
); /* HANDLER_FINISHED */
218 if (!ve
) con
->plugin_ctx
[p
->id
] = ve
= vhostdb_entry_init();
219 buffer_copy_buffer(ve
->server_name
, con
->uri
.authority
);
220 buffer_copy_buffer(ve
->document_root
, b
);
222 return mod_vhostdb_found(con
, ve
); /* HANDLER_GO_ON */
225 int mod_vhostdb_plugin_init(plugin
*p
);
226 int mod_vhostdb_plugin_init(plugin
*p
) {
227 p
->version
= LIGHTTPD_VERSION_ID
;
228 p
->name
= buffer_init_string("vhostdb");
229 p
->init
= mod_vhostdb_init
;
230 p
->cleanup
= mod_vhostdb_free
;
231 p
->set_defaults
= mod_vhostdb_set_defaults
;
232 p
->handle_docroot
= mod_vhostdb_handle_docroot
;
233 p
->connection_reset
= mod_vhostdb_handle_connection_close
;