9 #include "stat_cache.h"
11 #include "http_chunk.h"
20 * this is a staticfile for a lighttpd plugin
26 /* plugin config for all request/connections */
30 unsigned short etags_used
;
31 unsigned short disable_pathinfo
;
37 plugin_config
**config_storage
;
42 /* init the plugin data */
43 INIT_FUNC(mod_staticfile_init
) {
46 p
= calloc(1, sizeof(*p
));
51 /* detroy the plugin data */
52 FREE_FUNC(mod_staticfile_free
) {
57 if (!p
) return HANDLER_GO_ON
;
59 if (p
->config_storage
) {
61 for (i
= 0; i
< srv
->config_context
->used
; i
++) {
62 plugin_config
*s
= p
->config_storage
[i
];
64 if (NULL
== s
) continue;
66 array_free(s
->exclude_ext
);
70 free(p
->config_storage
);
78 /* handle plugin config and check values */
80 SETDEFAULTS_FUNC(mod_staticfile_set_defaults
) {
84 config_values_t cv
[] = {
85 { "static-file.exclude-extensions", NULL
, T_CONFIG_ARRAY
, T_CONFIG_SCOPE_CONNECTION
}, /* 0 */
86 { "static-file.etags", NULL
, T_CONFIG_BOOLEAN
, T_CONFIG_SCOPE_CONNECTION
}, /* 1 */
87 { "static-file.disable-pathinfo", NULL
, T_CONFIG_BOOLEAN
, T_CONFIG_SCOPE_CONNECTION
}, /* 2 */
88 { NULL
, NULL
, T_CONFIG_UNSET
, T_CONFIG_SCOPE_UNSET
}
91 if (!p
) return HANDLER_ERROR
;
93 p
->config_storage
= calloc(1, srv
->config_context
->used
* sizeof(plugin_config
*));
95 for (i
= 0; i
< srv
->config_context
->used
; i
++) {
96 data_config
const* config
= (data_config
const*)srv
->config_context
->data
[i
];
99 s
= calloc(1, sizeof(plugin_config
));
100 s
->exclude_ext
= array_init();
102 s
->disable_pathinfo
= 0;
104 cv
[0].destination
= s
->exclude_ext
;
105 cv
[1].destination
= &(s
->etags_used
);
106 cv
[2].destination
= &(s
->disable_pathinfo
);
108 p
->config_storage
[i
] = s
;
110 if (0 != config_insert_values_global(srv
, config
->value
, cv
, i
== 0 ? T_CONFIG_SCOPE_SERVER
: T_CONFIG_SCOPE_CONNECTION
)) {
111 return HANDLER_ERROR
;
115 return HANDLER_GO_ON
;
120 static int mod_staticfile_patch_connection(server
*srv
, connection
*con
, plugin_data
*p
) {
122 plugin_config
*s
= p
->config_storage
[0];
126 PATCH(disable_pathinfo
);
128 /* skip the first, the global context */
129 for (i
= 1; i
< srv
->config_context
->used
; i
++) {
130 data_config
*dc
= (data_config
*)srv
->config_context
->data
[i
];
131 s
= p
->config_storage
[i
];
133 /* condition didn't match */
134 if (!config_check_cond(srv
, con
, dc
)) continue;
137 for (j
= 0; j
< dc
->value
->used
; j
++) {
138 data_unset
*du
= dc
->value
->data
[j
];
140 if (buffer_is_equal_string(du
->key
, CONST_STR_LEN("static-file.exclude-extensions"))) {
142 } else if (buffer_is_equal_string(du
->key
, CONST_STR_LEN("static-file.etags"))) {
144 } else if (buffer_is_equal_string(du
->key
, CONST_STR_LEN("static-file.disable-pathinfo"))) {
145 PATCH(disable_pathinfo
);
154 URIHANDLER_FUNC(mod_staticfile_subrequest
) {
155 plugin_data
*p
= p_d
;
159 /* someone else has done a decision for us */
160 if (con
->http_status
!= 0) return HANDLER_GO_ON
;
161 if (buffer_is_empty(con
->uri
.path
)) return HANDLER_GO_ON
;
162 if (buffer_is_empty(con
->physical
.path
)) return HANDLER_GO_ON
;
164 /* someone else has handled this request */
165 if (con
->mode
!= DIRECT
) return HANDLER_GO_ON
;
167 /* we only handle GET, POST and HEAD */
168 switch(con
->request
.http_method
) {
169 case HTTP_METHOD_GET
:
170 case HTTP_METHOD_POST
:
171 case HTTP_METHOD_HEAD
:
174 return HANDLER_GO_ON
;
177 mod_staticfile_patch_connection(srv
, con
, p
);
179 if (p
->conf
.disable_pathinfo
&& !buffer_string_is_empty(con
->request
.pathinfo
)) {
180 if (con
->conf
.log_request_handling
) {
181 log_error_write(srv
, __FILE__
, __LINE__
, "s", "-- NOT handling file as static file, pathinfo forbidden");
183 return HANDLER_GO_ON
;
186 /* ignore certain extensions */
187 for (k
= 0; k
< p
->conf
.exclude_ext
->used
; k
++) {
188 ds
= (data_string
*)p
->conf
.exclude_ext
->data
[k
];
190 if (buffer_is_empty(ds
->value
)) continue;
192 if (buffer_is_equal_right_len(con
->physical
.path
, ds
->value
, buffer_string_length(ds
->value
))) {
193 if (con
->conf
.log_request_handling
) {
194 log_error_write(srv
, __FILE__
, __LINE__
, "s", "-- NOT handling file as static file, extension forbidden");
196 return HANDLER_GO_ON
;
201 if (con
->conf
.log_request_handling
) {
202 log_error_write(srv
, __FILE__
, __LINE__
, "s", "-- handling file as static file");
205 if (!p
->conf
.etags_used
) con
->etag_flags
= 0;
206 http_response_send_file(srv
, con
, con
->physical
.path
);
208 return HANDLER_FINISHED
;
211 /* this function is called at dlopen() time and inits the callbacks */
213 int mod_staticfile_plugin_init(plugin
*p
);
214 int mod_staticfile_plugin_init(plugin
*p
) {
215 p
->version
= LIGHTTPD_VERSION_ID
;
216 p
->name
= buffer_init_string("staticfile");
218 p
->init
= mod_staticfile_init
;
219 p
->handle_subrequest_start
= mod_staticfile_subrequest
;
220 p
->set_defaults
= mod_staticfile_set_defaults
;
221 p
->cleanup
= mod_staticfile_free
;