xref: /lighttpd1.4/src/mod_staticfile.c (revision e11f72b1)
1 #include "first.h"
2 
3 #include "base.h"
4 #include "log.h"
5 #include "buffer.h"
6 
7 #include "plugin.h"
8 
9 #include "response.h"
10 
11 #include <stdlib.h>
12 #include <string.h>
13 
14 /**
15  * this is a staticfile for a lighttpd plugin
16  *
17  */
18 
19 
20 typedef struct {
21 	const array *exclude_ext;
22 	unsigned short etags_used;
23 	unsigned short disable_pathinfo;
24 } plugin_config;
25 
26 typedef struct {
27     PLUGIN_DATA;
28     plugin_config defaults;
29     plugin_config conf;
30 } plugin_data;
31 
32 INIT_FUNC(mod_staticfile_init) {
33     return calloc(1, sizeof(plugin_data));
34 }
35 
36 static void mod_staticfile_merge_config_cpv(plugin_config * const pconf, const config_plugin_value_t * const cpv) {
37     switch (cpv->k_id) { /* index into static config_plugin_keys_t cpk[] */
38       case 0: /* static-file.exclude-extensions */
39         pconf->exclude_ext = cpv->v.a;
40         break;
41       case 1: /* static-file.etags */
42         pconf->etags_used = cpv->v.u;
43         break;
44       case 2: /* static-file.disable-pathinfo */
45         pconf->disable_pathinfo = cpv->v.u;
46         break;
47       default:/* should not happen */
48         return;
49     }
50 }
51 
52 static void mod_staticfile_merge_config(plugin_config * const pconf, const config_plugin_value_t *cpv) {
53     do {
54         mod_staticfile_merge_config_cpv(pconf, cpv);
55     } while ((++cpv)->k_id != -1);
56 }
57 
58 static void mod_staticfile_patch_config(request_st * const r, plugin_data * const p) {
59     p->conf = p->defaults; /* copy small struct instead of memcpy() */
60     /*memcpy(&p->conf, &p->defaults, sizeof(plugin_config));*/
61     for (int i = 1, used = p->nconfig; i < used; ++i) {
62         if (config_check_cond(r, (uint32_t)p->cvlist[i].k_id))
63             mod_staticfile_merge_config(&p->conf,
64                                         p->cvlist + p->cvlist[i].v.u2[0]);
65     }
66 }
67 
68 SETDEFAULTS_FUNC(mod_staticfile_set_defaults) {
69     static const config_plugin_keys_t cpk[] = {
70       { CONST_STR_LEN("static-file.exclude-extensions"),
71         T_CONFIG_ARRAY_VLIST,
72         T_CONFIG_SCOPE_CONNECTION }
73      ,{ CONST_STR_LEN("static-file.etags"),
74         T_CONFIG_BOOL,
75         T_CONFIG_SCOPE_CONNECTION }
76      ,{ CONST_STR_LEN("static-file.disable-pathinfo"),
77         T_CONFIG_BOOL,
78         T_CONFIG_SCOPE_CONNECTION }
79      ,{ NULL, 0,
80         T_CONFIG_UNSET,
81         T_CONFIG_SCOPE_UNSET }
82     };
83 
84     plugin_data * const p = p_d;
85     if (!config_plugin_values_init(srv, p, cpk, "mod_staticfile"))
86         return HANDLER_ERROR;
87 
88     /* initialize p->defaults from global config context */
89     p->defaults.etags_used = 1; /* etags enabled */
90     if (p->nconfig > 0 && p->cvlist->v.u2[1]) {
91         const config_plugin_value_t *cpv = p->cvlist + p->cvlist->v.u2[0];
92         if (-1 != cpv->k_id)
93             mod_staticfile_merge_config(&p->defaults, cpv);
94     }
95 
96     return HANDLER_GO_ON;
97 }
98 
99 URIHANDLER_FUNC(mod_staticfile_subrequest) {
100     plugin_data * const p = p_d;
101 
102     if (r->http_status != 0) return HANDLER_GO_ON;
103     if (buffer_is_empty(&r->physical.path)) return HANDLER_GO_ON;
104     if (NULL != r->handler_module) return HANDLER_GO_ON;
105     if (!http_method_get_head_post(r->http_method)) return HANDLER_GO_ON;
106 
107     mod_staticfile_patch_config(r, p);
108 
109     if (p->conf.disable_pathinfo && !buffer_string_is_empty(&r->pathinfo)) {
110         if (r->conf.log_request_handling)
111             log_error(r->conf.errh, __FILE__, __LINE__,
112               "-- NOT handling file as static file, pathinfo forbidden");
113         return HANDLER_GO_ON;
114     }
115 
116     if (p->conf.exclude_ext
117         && array_match_value_suffix(p->conf.exclude_ext, &r->physical.path)) {
118         if (r->conf.log_request_handling)
119             log_error(r->conf.errh, __FILE__, __LINE__,
120               "-- NOT handling file as static file, extension forbidden");
121         return HANDLER_GO_ON;
122     }
123 
124     if (r->conf.log_request_handling) {
125         log_error(r->conf.errh, __FILE__, __LINE__,
126           "-- handling file as static file");
127     }
128 
129     if (!p->conf.etags_used) r->conf.etag_flags = 0;
130     http_response_send_file(r, &r->physical.path);
131 
132     return HANDLER_FINISHED;
133 }
134 
135 
136 int mod_staticfile_plugin_init(plugin *p);
137 int mod_staticfile_plugin_init(plugin *p) {
138 	p->version     = LIGHTTPD_VERSION_ID;
139 	p->name        = "staticfile";
140 
141 	p->init        = mod_staticfile_init;
142 	p->handle_subrequest_start = mod_staticfile_subrequest;
143 	p->set_defaults  = mod_staticfile_set_defaults;
144 
145 	return 0;
146 }
147