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