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 return ck_calloc(1, sizeof(handler_ctx)); 46 } 47 48 static void handler_ctx_free(handler_ctx *hctx) { 49 free(hctx); 50 } 51 52 #endif 53 54 55 /* init the plugin data */ 56 INIT_FUNC(mod_skeleton_init) { 57 return ck_calloc(1, sizeof(plugin_data)); 58 } 59 60 /* handle plugin config and check values */ 61 62 static void mod_skeleton_merge_config_cpv(plugin_config * const pconf, const config_plugin_value_t * const cpv) { 63 switch (cpv->k_id) { /* index into static config_plugin_keys_t cpk[] */ 64 case 0: /* skeleton.array */ 65 pconf->match = cpv->v.a; 66 break; 67 default:/* should not happen */ 68 return; 69 } 70 } 71 72 static void mod_skeleton_merge_config(plugin_config * const pconf, const config_plugin_value_t *cpv) { 73 do { 74 mod_skeleton_merge_config_cpv(pconf, cpv); 75 } while ((++cpv)->k_id != -1); 76 } 77 78 static void mod_skeleton_patch_config(request_st * const r, plugin_data * const p) { 79 p->conf = p->defaults; /* copy small struct instead of memcpy() */ 80 /*memcpy(&p->conf, &p->defaults, sizeof(plugin_config));*/ 81 for (int i = 1, used = p->nconfig; i < used; ++i) { 82 if (config_check_cond(r, (uint32_t)p->cvlist[i].k_id)) 83 mod_skeleton_merge_config(&p->conf, p->cvlist+p->cvlist[i].v.u2[0]); 84 } 85 } 86 87 SETDEFAULTS_FUNC(mod_skeleton_set_defaults) { 88 static const config_plugin_keys_t cpk[] = { 89 { CONST_STR_LEN("skeleton.array"), 90 T_CONFIG_ARRAY_VLIST, 91 T_CONFIG_SCOPE_CONNECTION } 92 ,{ NULL, 0, 93 T_CONFIG_UNSET, 94 T_CONFIG_SCOPE_UNSET } 95 }; 96 97 plugin_data * const p = p_d; 98 if (!config_plugin_values_init(srv, p, cpk, "mod_skeleton")) 99 return HANDLER_ERROR; 100 101 /* initialize p->defaults from global config context */ 102 if (p->nconfig > 0 && p->cvlist->v.u2[1]) { 103 const config_plugin_value_t *cpv = p->cvlist + p->cvlist->v.u2[0]; 104 if (-1 != cpv->k_id) 105 mod_skeleton_merge_config(&p->defaults, cpv); 106 } 107 108 return HANDLER_GO_ON; 109 } 110 111 URIHANDLER_FUNC(mod_skeleton_uri_handler) { 112 plugin_data * const p = p_d; 113 114 /* determine whether or not module participates in request */ 115 116 if (NULL != r->handler_module) return HANDLER_GO_ON; 117 if (buffer_is_blank(&r->uri.path)) return HANDLER_GO_ON; 118 119 /* get module config for request */ 120 mod_skeleton_patch_config(r, p); 121 122 if (NULL == p->conf.match 123 || NULL == array_match_value_suffix(p->conf.match, &r->uri.path)) { 124 return HANDLER_GO_ON; 125 } 126 127 /* module participates in request; business logic here */ 128 129 r->http_status = 403; /* example: reject request with 403 Forbidden */ 130 return HANDLER_FINISHED; 131 } 132 133 134 /* this function is called at dlopen() time and inits the callbacks */ 135 __attribute_cold__ 136 int mod_skeleton_plugin_init(plugin *p); 137 int mod_skeleton_plugin_init(plugin *p) { 138 p->version = LIGHTTPD_VERSION_ID; 139 p->name = "skeleton"; 140 p->init = mod_skeleton_init; 141 p->set_defaults= mod_skeleton_set_defaults; 142 143 p->handle_uri_clean = mod_skeleton_uri_handler; 144 145 return 0; 146 } 147