1#include "base.h" 2#include "log.h" 3#include "buffer.h" 4 5#include "plugin.h" 6 7#include <ctype.h> 8#include <stdlib.h> 9#include <string.h> 10 11/** 12 * this is a skeleton for a lighttpd plugin 13 * 14 * just replaces every occurance of 'skeleton' by your plugin name 15 * 16 * e.g. in vim: 17 * 18 * :%s/skeleton/myhandler/ 19 * 20 */ 21 22 23 24/* plugin config for all request/connections */ 25 26typedef struct { 27 array *match; 28} plugin_config; 29 30typedef struct { 31 PLUGIN_DATA; 32 33 buffer *match_buf; 34 35 plugin_config **config_storage; 36 37 plugin_config conf; 38} plugin_data; 39 40typedef struct { 41 size_t foo; 42} handler_ctx; 43 44static handler_ctx * handler_ctx_init() { 45 handler_ctx * hctx; 46 47 hctx = calloc(1, sizeof(*hctx)); 48 49 return hctx; 50} 51 52static void handler_ctx_free(handler_ctx *hctx) { 53 54 free(hctx); 55} 56 57/* init the plugin data */ 58INIT_FUNC(mod_skeleton_init) { 59 plugin_data *p; 60 61 p = calloc(1, sizeof(*p)); 62 63 p->match_buf = buffer_init(); 64 65 return p; 66} 67 68/* destroy the plugin data */ 69FREE_FUNC(mod_skeleton_free) { 70 plugin_data *p = p_d; 71 72 UNUSED(srv); 73 74 if (!p) return HANDLER_GO_ON; 75 76 if (p->config_storage) { 77 size_t i; 78 79 for (i = 0; i < srv->config_context->used; i++) { 80 plugin_config *s = p->config_storage[i]; 81 82 if (NULL == s) continue; 83 84 array_free(s->match); 85 86 free(s); 87 } 88 free(p->config_storage); 89 } 90 91 buffer_free(p->match_buf); 92 93 free(p); 94 95 return HANDLER_GO_ON; 96} 97 98/* handle plugin config and check values */ 99 100SETDEFAULTS_FUNC(mod_skeleton_set_defaults) { 101 plugin_data *p = p_d; 102 size_t i = 0; 103 104 config_values_t cv[] = { 105 { "skeleton.array", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ 106 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } 107 }; 108 109 if (!p) return HANDLER_ERROR; 110 111 p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *)); 112 113 for (i = 0; i < srv->config_context->used; i++) { 114 data_config const* config = (data_config const*)srv->config_context->data[i]; 115 plugin_config *s; 116 117 s = calloc(1, sizeof(plugin_config)); 118 s->match = array_init(); 119 120 cv[0].destination = s->match; 121 122 p->config_storage[i] = s; 123 124 if (0 != config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) { 125 return HANDLER_ERROR; 126 } 127 } 128 129 return HANDLER_GO_ON; 130} 131 132#define PATCH(x) \ 133 p->conf.x = s->x; 134static int mod_skeleton_patch_connection(server *srv, connection *con, plugin_data *p) { 135 size_t i, j; 136 plugin_config *s = p->config_storage[0]; 137 138 PATCH(match); 139 140 /* skip the first, the global context */ 141 for (i = 1; i < srv->config_context->used; i++) { 142 data_config *dc = (data_config *)srv->config_context->data[i]; 143 s = p->config_storage[i]; 144 145 /* condition didn't match */ 146 if (!config_check_cond(srv, con, dc)) continue; 147 148 /* merge config */ 149 for (j = 0; j < dc->value->used; j++) { 150 data_unset *du = dc->value->data[j]; 151 152 if (buffer_is_equal_string(du->key, CONST_STR_LEN("skeleton.array"))) { 153 PATCH(match); 154 } 155 } 156 } 157 158 return 0; 159} 160#undef PATCH 161 162URIHANDLER_FUNC(mod_skeleton_uri_handler) { 163 plugin_data *p = p_d; 164 int s_len; 165 size_t k, i; 166 167 UNUSED(srv); 168 169 if (con->mode != DIRECT) return HANDLER_GO_ON; 170 171 if (con->uri.path->used == 0) return HANDLER_GO_ON; 172 173 mod_skeleton_patch_connection(srv, con, p); 174 175 s_len = con->uri.path->used - 1; 176 177 for (k = 0; k < p->conf.match->used; k++) { 178 data_string *ds = (data_string *)p->conf.match->data[k]; 179 int ct_len = ds->value->used - 1; 180 181 if (ct_len > s_len) continue; 182 if (ds->value->used == 0) continue; 183 184 if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) { 185 con->http_status = 403; 186 187 return HANDLER_FINISHED; 188 } 189 } 190 191 /* not found */ 192 return HANDLER_GO_ON; 193} 194 195/* this function is called at dlopen() time and inits the callbacks */ 196 197int mod_skeleton_plugin_init(plugin *p) { 198 p->version = LIGHTTPD_VERSION_ID; 199 p->name = buffer_init_string("skeleton"); 200 201 p->init = mod_skeleton_init; 202 p->handle_uri_clean = mod_skeleton_uri_handler; 203 p->set_defaults = mod_skeleton_set_defaults; 204 p->cleanup = mod_skeleton_free; 205 206 p->data = NULL; 207 208 return 0; 209} 210