xref: /lighttpd1.4/src/mod_skeleton.c (revision 6516c5a2)
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(void) {
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 */
INIT_FUNC(mod_skeleton_init)56 INIT_FUNC(mod_skeleton_init) {
57     return ck_calloc(1, sizeof(plugin_data));
58 }
59 
60 /* handle plugin config and check values */
61 
mod_skeleton_merge_config_cpv(plugin_config * const pconf,const config_plugin_value_t * const cpv)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 
mod_skeleton_merge_config(plugin_config * const pconf,const config_plugin_value_t * cpv)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 
mod_skeleton_patch_config(request_st * const r,plugin_data * const p)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 
SETDEFAULTS_FUNC(mod_skeleton_set_defaults)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 
URIHANDLER_FUNC(mod_skeleton_uri_handler)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);
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