1 #include "first.h" 2 3 #include <stdlib.h> 4 #include <string.h> 5 6 #include "plugin.h" 7 8 #include "log.h" 9 #include "buffer.h" 10 #include "array.h" 11 #include "request.h" 12 13 /** 14 * this is a skeleton for a lighttpd plugin 15 * 16 * just replaces every occurrence of 'skeleton' by your plugin name 17 * 18 * e.g. in vim: 19 * 20 * :%s/skeleton/myhandler/ 21 * 22 */ 23 24 25 /* plugin config for all request/connections */ 26 27 typedef struct { 28 const array *match; 29 } plugin_config; 30 31 typedef struct { 32 PLUGIN_DATA; 33 plugin_config defaults; 34 plugin_config conf; 35 } plugin_data; 36 37 38 #if 0 /* (needed if module keeps state for request) */ 39 40 typedef struct { 41 size_t foo; 42 } handler_ctx; 43 44 static handler_ctx * handler_ctx_init() { 45 handler_ctx * hctx = calloc(1, sizeof(*hctx)); 46 force_assert(hctx); 47 return hctx; 48 } 49 50 static void handler_ctx_free(handler_ctx *hctx) { 51 free(hctx); 52 } 53 54 #endif 55 56 57 /* init the plugin data */ 58 INIT_FUNC(mod_skeleton_init) { 59 return calloc(1, sizeof(plugin_data)); 60 } 61 62 /* handle plugin config and check values */ 63 64 static void mod_skeleton_merge_config_cpv(plugin_config * const pconf, const config_plugin_value_t * const cpv) { 65 switch (cpv->k_id) { /* index into static config_plugin_keys_t cpk[] */ 66 case 0: /* skeleton.array */ 67 pconf->match = cpv->v.a; 68 break; 69 default:/* should not happen */ 70 return; 71 } 72 } 73 74 static void mod_skeleton_merge_config(plugin_config * const pconf, const config_plugin_value_t *cpv) { 75 do { 76 mod_skeleton_merge_config_cpv(pconf, cpv); 77 } while ((++cpv)->k_id != -1); 78 } 79 80 static void mod_skeleton_patch_config(request_st * const r, plugin_data * const p) { 81 p->conf = p->defaults; /* copy small struct instead of memcpy() */ 82 /*memcpy(&p->conf, &p->defaults, sizeof(plugin_config));*/ 83 for (int i = 1, used = p->nconfig; i < used; ++i) { 84 if (config_check_cond(r, (uint32_t)p->cvlist[i].k_id)) 85 mod_skeleton_merge_config(&p->conf, p->cvlist+p->cvlist[i].v.u2[0]); 86 } 87 } 88 89 SETDEFAULTS_FUNC(mod_skeleton_set_defaults) { 90 static const config_plugin_keys_t cpk[] = { 91 { CONST_STR_LEN("skeleton.array"), 92 T_CONFIG_ARRAY_VLIST, 93 T_CONFIG_SCOPE_CONNECTION } 94 ,{ NULL, 0, 95 T_CONFIG_UNSET, 96 T_CONFIG_SCOPE_UNSET } 97 }; 98 99 plugin_data * const p = p_d; 100 if (!config_plugin_values_init(srv, p, cpk, "mod_skeleton")) 101 return HANDLER_ERROR; 102 103 /* initialize p->defaults from global config context */ 104 if (p->nconfig > 0 && p->cvlist->v.u2[1]) { 105 const config_plugin_value_t *cpv = p->cvlist + p->cvlist->v.u2[0]; 106 if (-1 != cpv->k_id) 107 mod_skeleton_merge_config(&p->defaults, cpv); 108 } 109 110 return HANDLER_GO_ON; 111 } 112 113 URIHANDLER_FUNC(mod_skeleton_uri_handler) { 114 plugin_data * const p = p_d; 115 116 /* determine whether or not module participates in request */ 117 118 if (NULL != r->handler_module) return HANDLER_GO_ON; 119 if (buffer_is_blank(&r->uri.path)) return HANDLER_GO_ON; 120 121 /* get module config for request */ 122 mod_skeleton_patch_config(r, p); 123 124 if (NULL == p->conf.match 125 || NULL == array_match_value_suffix(p->conf.match, &r->uri.path)) { 126 return HANDLER_GO_ON; 127 } 128 129 /* module participates in request; business logic here */ 130 131 r->http_status = 403; /* example: reject request with 403 Forbidden */ 132 return HANDLER_FINISHED; 133 } 134 135 136 /* this function is called at dlopen() time and inits the callbacks */ 137 __attribute_cold__ 138 int mod_skeleton_plugin_init(plugin *p); 139 int mod_skeleton_plugin_init(plugin *p) { 140 p->version = LIGHTTPD_VERSION_ID; 141 p->name = "skeleton"; 142 p->init = mod_skeleton_init; 143 p->set_defaults= mod_skeleton_set_defaults; 144 145 p->handle_uri_clean = mod_skeleton_uri_handler; 146 147 return 0; 148 } 149