mod_rrd.c (mod_rrd-1.0.0.tar.bz2) | : | mod_rrd.c (mod_rrd-1.0.1.tar.bz2) | ||
---|---|---|---|---|
skipping to change at line 32 | skipping to change at line 32 | |||
* | * | |||
* <IfModule mod_rrd.c> | * <IfModule mod_rrd.c> | |||
* <Directory "/var/lib/collectd/rrd"> | * <Directory "/var/lib/collectd/rrd"> | |||
* Require all granted | * Require all granted | |||
* </Directory> | * </Directory> | |||
* Alias /rrd /var/lib/collectd/rrd | * Alias /rrd /var/lib/collectd/rrd | |||
* <Location /rrd> | * <Location /rrd> | |||
* RRDGraph on | * RRDGraph on | |||
* RRDGraphOption title %{SERVER_NAME} | * RRDGraphOption title %{SERVER_NAME} | |||
* RRDGraphEnv METHODS %{REQUEST_METHOD} | * RRDGraphEnv METHODS %{REQUEST_METHOD} | |||
* RRDGraphElement DEF:xifOutOctets=monitor*.rrd:ifOutOctets:AVERAGE | * RRDGraphElement DEF:xifOutOctets=monitor*.rrd:ifOutOctets:AVERAGE "option al/expression/monitor*.rrd" "/optional/path/prefix/" | |||
* RRDGraphElement VDEF:xifOutOctetsmax=xifOutOctets+,MAXIMUM | * RRDGraphElement VDEF:xifOutOctetsmax=xifOutOctets+,MAXIMUM | |||
* RRDGraphElement CDEF:xcombined=xifOutOctets,1,+ | * RRDGraphElement CDEF:xcombined=xifOutOctets,1,+ | |||
* RRDGraphElement LINE1:xifOutOctets#00ff00:Out+Octets :%{SERVER_NAME} | * RRDGraphElement LINE1:xifOutOctets#00ff00:Out+Octets :%{SERVER_NAME} | |||
* RRDGraphElement AREA:xifOutOctets#00ff00:Out+Octets :%{SERVER_NAME} | * RRDGraphElement AREA:xifOutOctets#00ff00:Out+Octets :%{SERVER_NAME} | |||
* RRDGraphElement TICK:xifOutOctets#00ff00:1.0:Failures :%{SERVER_NAME} | * RRDGraphElement TICK:xifOutOctets#00ff00:1.0:Failures :%{SERVER_NAME} | |||
* RRDGraphElement "VRULE:0#FF0000:dashed line:dashes" :%{SERVER_NAME} | * RRDGraphElement "VRULE:0#FF0000:dashed line:dashes" :%{SERVER_NAME} | |||
* RRDGraphElement "HRULE:0#FF0000:dashed line:dashes" :%{SERVER_NAME} | * RRDGraphElement "HRULE:0#FF0000:dashed line:dashes" :%{SERVER_NAME} | |||
* RRDGraphElement "COMMENT:Foo" %{env:METHODS} | * RRDGraphElement "COMMENT:Foo" %{env:METHODS} | |||
* </Location> | * </Location> | |||
* </IfModule> | * </IfModule> | |||
skipping to change at line 133 | skipping to change at line 133 | |||
static apr_thread_mutex_t *rrd_mutex = NULL; | static apr_thread_mutex_t *rrd_mutex = NULL; | |||
#endif | #endif | |||
module AP_MODULE_DECLARE_DATA rrd_module; | module AP_MODULE_DECLARE_DATA rrd_module; | |||
typedef struct rrd_conf { | typedef struct rrd_conf { | |||
const char *location; | const char *location; | |||
apr_array_header_t *options; | apr_array_header_t *options; | |||
apr_array_header_t *elements; | apr_array_header_t *elements; | |||
apr_hash_t *env; | apr_hash_t *env; | |||
const char *format; | ||||
int graph; | int graph; | |||
unsigned int location_set:1; | unsigned int location_set:1; | |||
unsigned int format_set:1; | ||||
unsigned int graph_set:1; | unsigned int graph_set:1; | |||
} rrd_conf; | } rrd_conf; | |||
typedef struct rrd_ctx { | typedef struct rrd_ctx { | |||
apr_file_t *file; | apr_file_t *file; | |||
apr_bucket_brigade *bb; | apr_bucket_brigade *bb; | |||
} rrd_ctx; | } rrd_ctx; | |||
typedef enum rrd_conf_e { | typedef enum rrd_conf_e { | |||
RRD_CONF_DEF, | RRD_CONF_DEF, | |||
skipping to change at line 168 | skipping to change at line 170 | |||
typedef struct rrd_cmd_t rrd_cmd_t; | typedef struct rrd_cmd_t rrd_cmd_t; | |||
typedef struct rrd_def_t { | typedef struct rrd_def_t { | |||
const char *vname; | const char *vname; | |||
const char *path; | const char *path; | |||
const char *dsname; | const char *dsname; | |||
const char *cf; | const char *cf; | |||
apr_pool_t *pool; | apr_pool_t *pool; | |||
apr_array_header_t *requests; | apr_array_header_t *requests; | |||
ap_expr_info_t *epath; | ||||
ap_expr_info_t *edirpath; | ||||
} rrd_def_t; | } rrd_def_t; | |||
typedef struct rrd_vdef_t { | typedef struct rrd_vdef_t { | |||
const char *vname; | const char *vname; | |||
const char *dsname; | const char *dsname; | |||
const char *rpn; | const char *rpn; | |||
rrd_cmd_t *ref; | rrd_cmd_t *ref; | |||
} rrd_vdef_t; | } rrd_vdef_t; | |||
typedef struct rrd_cdef_t { | typedef struct rrd_cdef_t { | |||
skipping to change at line 463 | skipping to change at line 467 | |||
" </wadl:resource>\n" | " </wadl:resource>\n" | |||
" </wadl:resources>\n" | " </wadl:resources>\n" | |||
"</wadl:application>\n", | "</wadl:application>\n", | |||
conf->location ? conf->location : | conf->location ? conf->location : | |||
apr_pstrcat(r->pool, ap_http_scheme(r), "://", | apr_pstrcat(r->pool, ap_http_scheme(r), "://", | |||
r->server->server_hostname, r->uri, NULL)); | r->server->server_hostname, r->uri, NULL)); | |||
return OK; | return OK; | |||
} | } | |||
static const char *lookup_content_type(const char *format) | ||||
{ | ||||
switch(format[0]) { | ||||
case 'p': | ||||
case 'P': | ||||
if (strcasecmp(format, "PNG") == 0) { | ||||
return "image/png"; | ||||
} | ||||
if (strcasecmp(format, "PDF") == 0) { | ||||
return "application/pdf"; | ||||
} | ||||
break; | ||||
case 's': | ||||
case 'S': | ||||
if (strcasecmp(format, "SVG") == 0) { | ||||
return "image/svg+xml"; | ||||
} | ||||
if (strcasecmp(format, "SSV") == 0) { | ||||
return "text/plain"; | ||||
} | ||||
break; | ||||
case 'e': | ||||
case 'E': | ||||
if (strcasecmp(format, "EPS") == 0) { | ||||
return "application/eps"; | ||||
} | ||||
break; | ||||
case 'x': | ||||
case 'X': | ||||
if (strcasecmp(format, "XML") == 0) { | ||||
return "application/xml"; | ||||
} | ||||
if (strcasecmp(format, "XMLENUM") == 0) { | ||||
return "application/xml"; | ||||
} | ||||
break; | ||||
case 'j': | ||||
case 'J': | ||||
if (strcasecmp(format, "JSON") == 0) { | ||||
return "application/json"; | ||||
} | ||||
if (strcasecmp(format, "JSONTIME") == 0) { | ||||
return "application/json"; | ||||
} | ||||
break; | ||||
case 'c': | ||||
case 'C': | ||||
if (strcasecmp(format, "CSV") == 0) { | ||||
return "text/csv"; | ||||
} | ||||
break; | ||||
case 't': | ||||
case 'T': | ||||
if (strcasecmp(format, "TSV") == 0) { | ||||
return "text/tab-separated-values"; | ||||
} | ||||
break; | ||||
} | ||||
return NULL; | ||||
} | ||||
static const char *parse_rrdgraph_suffix(request_rec *r) | static const char *parse_rrdgraph_suffix(request_rec *r) | |||
{ | { | |||
const char *fname = ap_strrchr_c(r->filename, '/'); | const char *fname = ap_strrchr_c(r->filename, '/'); | |||
if (fname) { | if (fname) { | |||
/* PNG|SVG|EPS|PDF|XML|XMLENUM|JSON|JSONTIME|CSV|TSV|SSV */ | /* PNG|SVG|EPS|PDF|XML|XMLENUM|JSON|JSONTIME|CSV|TSV|SSV */ | |||
const char *suffix = ap_strrchr_c(fname, '.'); | const char *suffix = ap_strrchr_c(fname, '.'); | |||
if (suffix) { | if (suffix) { | |||
switch (suffix[1]) { | switch (suffix[1]) { | |||
case 'p': | case 'p': | |||
case 'P': | case 'P': | |||
if (strcasecmp(suffix, ".png") == 0) { | if (strcasecmp(suffix, ".png") == 0) { | |||
return "PNG"; | return "PNG"; | |||
} | } | |||
if (strcasecmp(suffix, "pdf") == 0) { | if (strcasecmp(suffix, ".pdf") == 0) { | |||
return "PDF"; | return "PDF"; | |||
} | } | |||
break; | break; | |||
case 's': | case 's': | |||
case 'S': | case 'S': | |||
if (strcasecmp(suffix, ".svg") == 0) { | if (strcasecmp(suffix, ".svg") == 0) { | |||
return "SVG"; | return "SVG"; | |||
} | } | |||
if (strcasecmp(suffix, "ssv") == 0) { | if (strcasecmp(suffix, ".ssv") == 0) { | |||
return "SSV"; | return "SSV"; | |||
} | } | |||
break; | break; | |||
case 'e': | case 'e': | |||
case 'E': | case 'E': | |||
if (strcasecmp(suffix, ".eps") == 0) { | if (strcasecmp(suffix, ".eps") == 0) { | |||
return "EPS"; | return "EPS"; | |||
} | } | |||
break; | break; | |||
case 'x': | case 'x': | |||
skipping to change at line 532 | skipping to change at line 597 | |||
if (strcasecmp(suffix, ".tsv") == 0) { | if (strcasecmp(suffix, ".tsv") == 0) { | |||
return "TSV"; | return "TSV"; | |||
} | } | |||
break; | break; | |||
} | } | |||
} | } | |||
} | } | |||
return NULL; | return NULL; | |||
} | } | |||
static int parse_element(apr_pool_t *p, const char *element, ap_expr_info_t *ele | static int parse_element(apr_pool_t *p, const char *element, ap_expr_info_t *exp | |||
gend, | r1, | |||
apr_array_header_t *cmds) | ap_expr_info_t *expr2, apr_array_header_t *cmds) | |||
{ | { | |||
switch (element[0]) { | switch (element[0]) { | |||
case 'A': | case 'A': | |||
/* handle AREA sections */ | /* handle AREA sections */ | |||
if (strncmp(element, "AREA:", 5) == 0) { | if (strncmp(element, "AREA:", 5) == 0) { | |||
char *vncol; | char *vncol; | |||
rrd_cmd_t *cmd = apr_array_push(cmds); | rrd_cmd_t *cmd = apr_array_push(cmds); | |||
cmd->type = RRD_CONF_AREA; | cmd->type = RRD_CONF_AREA; | |||
element += 5; | element += 5; | |||
vncol = ap_getword(p, &element, ':'); | vncol = ap_getword(p, &element, ':'); | |||
cmd->a.legend = getword_quote(p, &element, ':'); | cmd->a.legend = getword_quote(p, &element, ':'); | |||
cmd->a.elegend = elegend; | cmd->a.elegend = expr1; | |||
cmd->a.args = element; | cmd->a.args = element; | |||
cmd->a.vname = apr_cstr_tokenize("#", &vncol); | cmd->a.vname = apr_cstr_tokenize("#", &vncol); | |||
cmd->a.colour = vncol; | cmd->a.colour = vncol; | |||
return 1; | return 1; | |||
} | } | |||
break; | break; | |||
case 'C': | case 'C': | |||
/* handle CDEF sections */ | /* handle CDEF sections */ | |||
if (strncmp(element, "CDEF:", 5) == 0) { | if (strncmp(element, "CDEF:", 5) == 0) { | |||
char *rpn, *rpns; | char *rpn, *rpns; | |||
skipping to change at line 575 | skipping to change at line 640 | |||
rp->rpn = rpn; | rp->rpn = rpn; | |||
} | } | |||
return 1; | return 1; | |||
} | } | |||
/* handle COMMENT sections */ | /* handle COMMENT sections */ | |||
if (strncmp(element, "COMMENT:", 7) == 0) { | if (strncmp(element, "COMMENT:", 7) == 0) { | |||
rrd_cmd_t *cmd = apr_array_push(cmds); | rrd_cmd_t *cmd = apr_array_push(cmds); | |||
cmd->type = RRD_CONF_COMMENT; | cmd->type = RRD_CONF_COMMENT; | |||
cmd->e.element = ap_getword(p, &element, ':'); | cmd->e.element = ap_getword(p, &element, ':'); | |||
cmd->a.legend = getword_quote(p, &element, ':'); | cmd->a.legend = getword_quote(p, &element, ':'); | |||
cmd->e.elegend = elegend; | cmd->e.elegend = expr1; | |||
return 1; | return 1; | |||
} | } | |||
break; | break; | |||
case 'D': | case 'D': | |||
/* handle DEF sections */ | /* handle DEF sections */ | |||
if (strncmp(element, "DEF:", 4) == 0) { | if (strncmp(element, "DEF:", 4) == 0) { | |||
rrd_cmd_t *cmd = apr_array_push(cmds); | rrd_cmd_t *cmd = apr_array_push(cmds); | |||
cmd->type = RRD_CONF_DEF; | cmd->type = RRD_CONF_DEF; | |||
element += 4; | element += 4; | |||
cmd->d.vname = ap_getword(p, &element, '='); | cmd->d.vname = ap_getword(p, &element, '='); | |||
cmd->d.path = ap_getword(p, &element, ':'); | cmd->d.path = ap_getword(p, &element, ':'); | |||
cmd->d.dsname = ap_getword(p, &element, ':'); | cmd->d.dsname = ap_getword(p, &element, ':'); | |||
cmd->d.cf = element; | cmd->d.cf = element; | |||
cmd->d.pool = p; | cmd->d.pool = p; | |||
cmd->d.requests = apr_array_make(p, 10, sizeof(request_rec *)); | cmd->d.requests = apr_array_make(p, 10, sizeof(request_rec *)); | |||
cmd->d.epath = expr1; | ||||
cmd->d.edirpath = expr2; | ||||
return 1; | return 1; | |||
} | } | |||
break; | break; | |||
case 'G': | case 'G': | |||
/* handle GPRINT sections */ | /* handle GPRINT sections */ | |||
if (strncmp(element, "GPRINT:", 7) == 0) { | if (strncmp(element, "GPRINT:", 7) == 0) { | |||
rrd_cmd_t *cmd = apr_array_push(cmds); | rrd_cmd_t *cmd = apr_array_push(cmds); | |||
cmd->type = RRD_CONF_GPRINT; | cmd->type = RRD_CONF_GPRINT; | |||
element += 7; | element += 7; | |||
cmd->p.vname = ap_getword(p, &element, ':'); | cmd->p.vname = ap_getword(p, &element, ':'); | |||
skipping to change at line 614 | skipping to change at line 681 | |||
break; | break; | |||
case 'H': | case 'H': | |||
/* handle HRULE sections */ | /* handle HRULE sections */ | |||
if (strncmp(element, "HRULE:", 6) == 0) { | if (strncmp(element, "HRULE:", 6) == 0) { | |||
char *vncol; | char *vncol; | |||
rrd_cmd_t *cmd = apr_array_push(cmds); | rrd_cmd_t *cmd = apr_array_push(cmds); | |||
cmd->type = RRD_CONF_HRULE; | cmd->type = RRD_CONF_HRULE; | |||
element += 6; | element += 6; | |||
vncol = ap_getword(p, &element, ':'); | vncol = ap_getword(p, &element, ':'); | |||
cmd->r.legend = getword_quote(p, &element, ':'); | cmd->r.legend = getword_quote(p, &element, ':'); | |||
cmd->r.elegend = elegend; | cmd->r.elegend = expr1; | |||
cmd->r.args = element; | cmd->r.args = element; | |||
cmd->r.val = apr_cstr_tokenize("#", &vncol); | cmd->r.val = apr_cstr_tokenize("#", &vncol); | |||
cmd->r.colour = vncol; | cmd->r.colour = vncol; | |||
return 1; | return 1; | |||
} | } | |||
break; | break; | |||
case 'L': | case 'L': | |||
/* handle LINE sections */ | /* handle LINE sections */ | |||
if (strncmp(element, "LINE", 4) == 0) { | if (strncmp(element, "LINE", 4) == 0) { | |||
char *vncol; | char *vncol; | |||
rrd_cmd_t *cmd = apr_array_push(cmds); | rrd_cmd_t *cmd = apr_array_push(cmds); | |||
cmd->type = RRD_CONF_LINE; | cmd->type = RRD_CONF_LINE; | |||
cmd->l.line = ap_getword(p, &element, ':'); | cmd->l.line = ap_getword(p, &element, ':'); | |||
vncol = ap_getword(p, &element, ':'); | vncol = ap_getword(p, &element, ':'); | |||
cmd->l.legend = getword_quote(p, &element, ':'); | cmd->l.legend = getword_quote(p, &element, ':'); | |||
cmd->l.elegend = elegend; | cmd->l.elegend = expr1; | |||
cmd->l.args = element; | cmd->l.args = element; | |||
cmd->l.vname = apr_cstr_tokenize("#", &vncol); | cmd->l.vname = apr_cstr_tokenize("#", &vncol); | |||
cmd->l.colour = vncol; | cmd->l.colour = vncol; | |||
cmd->l.elegend = elegend; | cmd->l.elegend = expr1; | |||
return 1; | return 1; | |||
} | } | |||
break; | break; | |||
case 'P': | case 'P': | |||
/* handle PRINT sections */ | /* handle PRINT sections */ | |||
if (strncmp(element, "PRINT:", 6) == 0) { | if (strncmp(element, "PRINT:", 6) == 0) { | |||
rrd_cmd_t *cmd = apr_array_push(cmds); | rrd_cmd_t *cmd = apr_array_push(cmds); | |||
cmd->type = RRD_CONF_PRINT; | cmd->type = RRD_CONF_PRINT; | |||
element += 6; | element += 6; | |||
cmd->p.vname = ap_getword(p, &element, ':'); | cmd->p.vname = ap_getword(p, &element, ':'); | |||
skipping to change at line 670 | skipping to change at line 737 | |||
case 'T': | case 'T': | |||
/* handle TICK sections */ | /* handle TICK sections */ | |||
if (strncmp(element, "TICK:", 5) == 0) { | if (strncmp(element, "TICK:", 5) == 0) { | |||
char *vncol; | char *vncol; | |||
rrd_cmd_t *cmd = apr_array_push(cmds); | rrd_cmd_t *cmd = apr_array_push(cmds); | |||
cmd->type = RRD_CONF_TICK; | cmd->type = RRD_CONF_TICK; | |||
element += 5; | element += 5; | |||
vncol = ap_getword(p, &element, ':'); | vncol = ap_getword(p, &element, ':'); | |||
cmd->t.fraction = ap_getword(p, &element, ':'); | cmd->t.fraction = ap_getword(p, &element, ':'); | |||
cmd->t.legend = getword_quote(p, &element, ':'); | cmd->t.legend = getword_quote(p, &element, ':'); | |||
cmd->t.elegend = elegend; | cmd->t.elegend = expr1; | |||
cmd->t.args = element; | cmd->t.args = element; | |||
cmd->t.vname = apr_cstr_tokenize("#", &vncol); | cmd->t.vname = apr_cstr_tokenize("#", &vncol); | |||
cmd->t.colour = vncol; | cmd->t.colour = vncol; | |||
return 1; | return 1; | |||
} | } | |||
/* handle TEXTALIGN sections */ | /* handle TEXTALIGN sections */ | |||
else if (strncmp(element, "TEXTALIGN:", 10) == 0) { | else if (strncmp(element, "TEXTALIGN:", 10) == 0) { | |||
rrd_cmd_t *cmd = apr_array_push(cmds); | rrd_cmd_t *cmd = apr_array_push(cmds); | |||
cmd->type = RRD_CONF_TEXTALIGN; | cmd->type = RRD_CONF_TEXTALIGN; | |||
cmd->e.element = ap_getword(p, &element, ':'); | cmd->e.element = ap_getword(p, &element, ':'); | |||
cmd->a.legend = getword_quote(p, &element, ':'); | cmd->a.legend = getword_quote(p, &element, ':'); | |||
cmd->e.elegend = elegend; | cmd->e.elegend = expr1; | |||
return 1; | return 1; | |||
} | } | |||
break; | break; | |||
case 'V': | case 'V': | |||
/* handle VDEF sections */ | /* handle VDEF sections */ | |||
if (strncmp(element, "VDEF:", 5) == 0) { | if (strncmp(element, "VDEF:", 5) == 0) { | |||
rrd_cmd_t *cmd = apr_array_push(cmds); | rrd_cmd_t *cmd = apr_array_push(cmds); | |||
cmd->type = RRD_CONF_VDEF; | cmd->type = RRD_CONF_VDEF; | |||
element += 5; | element += 5; | |||
cmd->v.vname = ap_getword(p, &element, '='); | cmd->v.vname = ap_getword(p, &element, '='); | |||
skipping to change at line 705 | skipping to change at line 772 | |||
return 1; | return 1; | |||
} | } | |||
/* handle VRULE sections */ | /* handle VRULE sections */ | |||
if (strncmp(element, "VRULE:", 6) == 0) { | if (strncmp(element, "VRULE:", 6) == 0) { | |||
char *vncol; | char *vncol; | |||
rrd_cmd_t *cmd = apr_array_push(cmds); | rrd_cmd_t *cmd = apr_array_push(cmds); | |||
cmd->type = RRD_CONF_VRULE; | cmd->type = RRD_CONF_VRULE; | |||
element += 6; | element += 6; | |||
vncol = ap_getword(p, &element, ':'); | vncol = ap_getword(p, &element, ':'); | |||
cmd->r.legend = getword_quote(p, &element, ':'); | cmd->r.legend = getword_quote(p, &element, ':'); | |||
cmd->r.elegend = elegend; | cmd->r.elegend = expr1; | |||
cmd->r.args = element; | cmd->r.args = element; | |||
cmd->r.val = apr_cstr_tokenize("#", &vncol); | cmd->r.val = apr_cstr_tokenize("#", &vncol); | |||
cmd->r.colour = vncol; | cmd->r.colour = vncol; | |||
return 1; | return 1; | |||
} | } | |||
break; | break; | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
skipping to change at line 1103 | skipping to change at line 1170 | |||
} | } | |||
element = apr_pstrdup(r->pool, apr_punescape_url(r->pool, arg, NULL, NUL L, 0)); | element = apr_pstrdup(r->pool, apr_punescape_url(r->pool, arg, NULL, NUL L, 0)); | |||
if (!element) { | if (!element) { | |||
log_message(r, APR_SUCCESS, | log_message(r, APR_SUCCESS, | |||
apr_psprintf(r->pool, | apr_psprintf(r->pool, | |||
"The following element could not be unescaped: %s", arg) , NULL); | "The following element could not be unescaped: %s", arg) , NULL); | |||
return HTTP_BAD_REQUEST; | return HTTP_BAD_REQUEST; | |||
} | } | |||
if (parse_element(r->pool, element, NULL, cmds->cmds)) { | if (parse_element(r->pool, element, NULL, NULL, cmds->cmds)) { | |||
continue; | continue; | |||
} | } | |||
/* try parse options that take the form of name value pairs */ | /* try parse options that take the form of name value pairs */ | |||
key = apr_cstr_tokenize("=", &element); | key = apr_cstr_tokenize("=", &element); | |||
val = element; | val = element; | |||
if (parse_option(r->pool, key, val, NULL, cmds->opts)) { | if (parse_option(r->pool, key, val, NULL, cmds->opts)) { | |||
continue; | continue; | |||
} | } | |||
skipping to change at line 1150 | skipping to change at line 1217 | |||
} | } | |||
return NULL; | return NULL; | |||
} | } | |||
static int resolve_def(request_rec *r, rrd_cmd_t *cmd, rrd_cmds_t *cmds) | static int resolve_def(request_rec *r, rrd_cmd_t *cmd, rrd_cmds_t *cmds) | |||
{ | { | |||
ap_dir_match_t w; | ap_dir_match_t w; | |||
rrd_cb_t ctx; | rrd_cb_t ctx; | |||
apr_pool_t *ptemp; | apr_pool_t *ptemp; | |||
const char *last, *dirpath = r->filename; | const char *last, *path, *dirpath = r->filename; | |||
apr_hash_index_t *hi, *hi2; | apr_hash_index_t *hi, *hi2; | |||
apr_hash_t *set; | apr_hash_t *set; | |||
rrd_conf *conf = ap_get_module_config(r->per_dir_config, | rrd_conf *conf = ap_get_module_config(r->per_dir_config, | |||
&rrd_module); | &rrd_module); | |||
apr_pool_create(&ptemp, r->pool); | apr_pool_create(&ptemp, r->pool); | |||
/* process the wildcards */ | /* process the wildcards */ | |||
ctx.r = r; | ctx.r = r; | |||
ctx.cmd = cmd; | ctx.cmd = cmd; | |||
w.prefix = "rrd path: "; | w.prefix = "rrd path: "; | |||
w.p = r->pool; | w.p = r->pool; | |||
w.ptemp = ptemp; | w.ptemp = ptemp; | |||
w.flags = AP_DIR_FLAG_OPTIONAL | AP_DIR_FLAG_RECURSIVE; | w.flags = AP_DIR_FLAG_OPTIONAL | AP_DIR_FLAG_RECURSIVE; | |||
w.cb = resolve_def_cb; | w.cb = resolve_def_cb; | |||
w.ctx = &ctx; | w.ctx = &ctx; | |||
w.depth = 0; | w.depth = 0; | |||
last = strrchr(r->filename, '/'); | path = cmd->d.path; | |||
if (last) { | if (cmd->d.epath) { | |||
dirpath = apr_pstrndup(ptemp, r->filename, last - r->filename); | const char *err = NULL; | |||
path = ap_expr_str_exec(r, cmd->d.epath, &err); | ||||
if (err) { | ||||
log_message(r, APR_SUCCESS, | ||||
apr_psprintf(r->pool, | ||||
"While evaluating an element expression: %s", err), NULL | ||||
); | ||||
return HTTP_INTERNAL_SERVER_ERROR; | ||||
} | ||||
} | } | |||
const char *err = ap_dir_fnmatch(&w, dirpath, cmd->d.path); | if (cmd->d.edirpath) { | |||
const char *err = NULL; | ||||
dirpath = ap_expr_str_exec(r, cmd->d.edirpath, &err); | ||||
if (err) { | ||||
log_message(r, APR_SUCCESS, | ||||
apr_psprintf(r->pool, | ||||
"While evaluating an element expression: %s", err), NULL | ||||
); | ||||
return HTTP_INTERNAL_SERVER_ERROR; | ||||
} | ||||
} | ||||
else { | ||||
last = strrchr(r->filename, '/'); | ||||
if (last) { | ||||
dirpath = apr_pstrndup(ptemp, r->filename, last - r->filename); | ||||
} | ||||
} | ||||
ap_log_rerror( | ||||
APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, | ||||
"mod_rrd: Attempting to match wildcard RRD path '%s' against base '% | ||||
s'", | ||||
path, dirpath); | ||||
const char *err = ap_dir_fnmatch(&w, dirpath, path); | ||||
if (err) { | if (err) { | |||
log_message(r, APR_SUCCESS, | log_message(r, APR_SUCCESS, | |||
apr_psprintf(r->pool, | apr_psprintf(r->pool, | |||
"While parsing DEF '%s': %s", cmd->d.path, err), NULL); | "While parsing DEF path '%s': %s", path, err), NULL); | |||
return HTTP_BAD_REQUEST; | return HTTP_BAD_REQUEST; | |||
} | } | |||
/* process the environment lookup */ | /* process the environment lookup */ | |||
set = apr_hash_make(ptemp); | set = apr_hash_make(ptemp); | |||
for (hi = apr_hash_first(NULL, conf->env); hi; hi = apr_hash_next(hi)) { | for (hi = apr_hash_first(NULL, conf->env); hi; hi = apr_hash_next(hi)) { | |||
const char *err = NULL, *key, *val; | const char *err = NULL, *key, *val; | |||
ap_expr_info_t *eval; | ap_expr_info_t *eval; | |||
void *v; | void *v; | |||
const void *k; | const void *k; | |||
skipping to change at line 2143 | skipping to change at line 2239 | |||
/* no results */ | /* no results */ | |||
if (cmd->d.requests->nelts == 0) { | if (cmd->d.requests->nelts == 0) { | |||
/* output nothing */ | /* output nothing */ | |||
} | } | |||
/* one result */ | /* one result */ | |||
else if (cmd->d.requests->nelts == 1) { | else if (cmd->d.requests->nelts == 1) { | |||
request_rec *rr = APR_ARRAY_IDX(cmd->d.requests, 0, request_rec *); | request_rec *rr = APR_ARRAY_IDX(cmd->d.requests, 0, request_rec *); | |||
const char *arg = apr_psprintf(r->pool, "DEF:%s=%s:%s:%s", cmd->d.vname, | const char *arg = apr_psprintf(r->pool, "DEF:%s=%s:%s:%s", cmd->d.vname, | |||
rr->filename, cmd->d.dsname, cmd->d.cf); | pescape_colon(r->pool, rr->filename), cmd->d.dsname, cmd- >d.cf); | |||
APR_ARRAY_PUSH(args, const char *) = arg; | APR_ARRAY_PUSH(args, const char *) = arg; | |||
} | } | |||
/* more than one result */ | /* more than one result */ | |||
else { | else { | |||
char *cdef; | char *cdef; | |||
int len = apr_snprintf(NULL, 0, "CDEF:%s=", cmd->d.vname); | int len = apr_snprintf(NULL, 0, "CDEF:%s=", cmd->d.vname); | |||
/* handle each DEF: line */ | /* handle each DEF: line */ | |||
for (j = 0; j < cmd->d.requests->nelts; ++j) { | for (j = 0; j < cmd->d.requests->nelts; ++j) { | |||
request_rec *rr = APR_ARRAY_IDX(cmd->d.requests, j, request_rec *); | request_rec *rr = APR_ARRAY_IDX(cmd->d.requests, j, request_rec *); | |||
const char *arg = apr_psprintf(r->pool, "DEF:%sw%d=%s:%s:%s", cmd->d .vname, | const char *arg = apr_psprintf(r->pool, "DEF:%sw%d=%s:%s:%s", cmd->d .vname, | |||
j, rr->filename, cmd->d.dsname, cmd->d.cf); | j, pescape_colon(r->pool, rr->filename), cmd->d.dsname, cmd->d.c f); | |||
APR_ARRAY_PUSH(args, const char *) = arg; | APR_ARRAY_PUSH(args, const char *) = arg; | |||
len += apr_snprintf(NULL, 0, "%s%sw%d%s", j ? "," : "", cmd->d.vname , j, j ? ",+" : ""); | len += apr_snprintf(NULL, 0, "%s%sw%d%s", j ? "," : "", cmd->d.vname , j, j ? ",+" : ""); | |||
} | } | |||
/* calculate the CDEF summary line */ | /* calculate the CDEF summary line */ | |||
cdef = apr_palloc(r->pool, len + 1); | cdef = apr_palloc(r->pool, len + 1); | |||
APR_ARRAY_PUSH(args, const char *) = cdef; | APR_ARRAY_PUSH(args, const char *) = cdef; | |||
cdef += apr_snprintf(cdef, len, "CDEF:%s=", cmd->d.vname); | cdef += apr_snprintf(cdef, len, "CDEF:%s=", cmd->d.vname); | |||
for (j = 0; j < cmd->d.requests->nelts; ++j) { | for (j = 0; j < cmd->d.requests->nelts; ++j) { | |||
cdef += apr_snprintf(cdef, len, "%s%sw%d%s", j ? "," : "", cmd->d.vn ame, j, j ? ",+" : ""); | cdef += apr_snprintf(cdef, len, "%s%sw%d%s", j ? "," : "", cmd->d.vn ame, j, j ? ",+" : ""); | |||
skipping to change at line 2179 | skipping to change at line 2275 | |||
} | } | |||
return OK; | return OK; | |||
} | } | |||
static int generate_args(request_rec *r, rrd_cmds_t *cmds, apr_array_header_t ** pargs) | static int generate_args(request_rec *r, rrd_cmds_t *cmds, apr_array_header_t ** pargs) | |||
{ | { | |||
apr_array_header_t *args; | apr_array_header_t *args; | |||
rrd_cmd_t *cmd; | rrd_cmd_t *cmd; | |||
rrd_opt_t *opt; | rrd_opt_t *opt; | |||
const char *format; | ||||
int i, num = 4, ret = OK; | int i, num = 4, ret = OK; | |||
rrd_conf *conf = ap_get_module_config(r->per_dir_config, | ||||
&rrd_module); | ||||
/* count the options */ | /* count the options */ | |||
for (i = 0; i < cmds->opts->nelts; ++i) { | for (i = 0; i < cmds->opts->nelts; ++i) { | |||
opt = &((rrd_opt_t *)cmds->opts->elts)[i]; | opt = &((rrd_opt_t *)cmds->opts->elts)[i]; | |||
if (opt->val) { | if (opt->val) { | |||
num++; | num++; | |||
} | } | |||
num++; | num++; | |||
skipping to change at line 2204 | skipping to change at line 2304 | |||
cmd = &APR_ARRAY_IDX(cmds->cmds, i, rrd_cmd_t); | cmd = &APR_ARRAY_IDX(cmds->cmds, i, rrd_cmd_t); | |||
if (cmd->def) { | if (cmd->def) { | |||
num += cmd->def->d.requests->nelts; | num += cmd->def->d.requests->nelts; | |||
} | } | |||
num++; | num++; | |||
} | } | |||
/* work out the format */ | ||||
format = conf->format ? conf->format : parse_rrdgraph_suffix(r); | ||||
/* set the content type */ | ||||
ap_set_content_type(r, lookup_content_type(format)); | ||||
/* create arguments of the correct size */ | /* create arguments of the correct size */ | |||
args = *pargs = apr_array_make(r->pool, num, sizeof(const char *)); | args = *pargs = apr_array_make(r->pool, num, sizeof(const char *)); | |||
/* the argv array */ | /* the argv array */ | |||
APR_ARRAY_PUSH(args, const char *) = "rrdgraph"; | APR_ARRAY_PUSH(args, const char *) = "rrdgraph"; | |||
APR_ARRAY_PUSH(args, const char *) = "-"; | APR_ARRAY_PUSH(args, const char *) = "-"; | |||
APR_ARRAY_PUSH(args, const char *) = "--imgformat"; | APR_ARRAY_PUSH(args, const char *) = "--imgformat"; | |||
APR_ARRAY_PUSH(args, const char *) = parse_rrdgraph_suffix(r); | APR_ARRAY_PUSH(args, const char *) = format; | |||
/* first create the options */ | /* first create the options */ | |||
for (i = 0; i < cmds->opts->nelts; ++i) { | for (i = 0; i < cmds->opts->nelts; ++i) { | |||
opt = &((rrd_opt_t *)cmds->opts->elts)[i]; | opt = &((rrd_opt_t *)cmds->opts->elts)[i]; | |||
APR_ARRAY_PUSH(args, const char *) = | APR_ARRAY_PUSH(args, const char *) = | |||
apr_pstrcat(r->pool, "--", opt->key, NULL); | apr_pstrcat(r->pool, "--", opt->key, NULL); | |||
if (opt->eval) { | if (opt->eval) { | |||
const char *err = NULL; | const char *err = NULL; | |||
skipping to change at line 2391 | skipping to change at line 2497 | |||
if (grinfo == NULL) { | if (grinfo == NULL) { | |||
log_message(r, APR_SUCCESS, "Call to rrd_graph_v failed", rrd_get_error( )); | log_message(r, APR_SUCCESS, "Call to rrd_graph_v failed", rrd_get_error( )); | |||
ret = HTTP_INTERNAL_SERVER_ERROR; | ret = HTTP_INTERNAL_SERVER_ERROR; | |||
} | } | |||
else { | else { | |||
/* grab the image data from the results */ | /* grab the image data from the results */ | |||
while (grinfo) { | while (grinfo) { | |||
if (strcmp(grinfo->key, "image") == 0) { | if (strcmp(grinfo->key, "image") == 0) { | |||
apr_brigade_write(bb, NULL, NULL, (const char *)grinfo->value.u_ blo.ptr, | apr_brigade_write(bb, NULL, NULL, (const char *)grinfo->value.u_ blo.ptr, | |||
grinfo->value.u_blo.size); | grinfo->value.u_blo.size); | |||
ap_set_content_length(r, grinfo->value.u_blo.size); | ||||
break; | break; | |||
} | } | |||
/* skip anything else */ | /* skip anything else */ | |||
grinfo = grinfo->next; | grinfo = grinfo->next; | |||
} | } | |||
rrd_info_free(grinfo); | rrd_info_free(grinfo); | |||
} | } | |||
rrd_clear_error(); | rrd_clear_error(); | |||
#if APR_HAS_THREADS | #if APR_HAS_THREADS | |||
skipping to change at line 2432 | skipping to change at line 2539 | |||
APLOG_MARK, APLOG_DEBUG, rv, r, "rrd_handler: ap_pass_brigad e returned %i", rv); | APLOG_MARK, APLOG_DEBUG, rv, r, "rrd_handler: ap_pass_brigad e returned %i", rv); | |||
return HTTP_INTERNAL_SERVER_ERROR; | return HTTP_INTERNAL_SERVER_ERROR; | |||
} | } | |||
} | } | |||
return ret; | return ret; | |||
} | } | |||
static int get_rrd(request_rec *r) | static int get_rrd(request_rec *r) | |||
{ | { | |||
rrd_conf *conf = ap_get_module_config(r->per_dir_config, | ||||
&rrd_module); | ||||
/* | /* | |||
* if a file does not exist, assume it is a request for a graph, otherwise | * if a file does not exist, assume it is a request for a graph, otherwise | |||
* go with the original file. | * go with the original file. | |||
*/ | */ | |||
if (r->filename && r->finfo.filetype == APR_NOFILE && parse_rrdgraph_suffix( | if ((conf->format) || | |||
r)) { | (r->filename && r->finfo.filetype == APR_NOFILE && parse_rrdgraph | |||
_suffix(r))) { | ||||
return get_rrdgraph(r); | return get_rrdgraph(r); | |||
} | } | |||
return DECLINED; | return DECLINED; | |||
} | } | |||
static int rrd_fixups(request_rec *r) | ||||
{ | ||||
rrd_conf *conf = ap_get_module_config(r->per_dir_config, | ||||
&rrd_module); | ||||
if (!conf) { | ||||
return DECLINED; | ||||
} | ||||
if (conf->graph) { | ||||
r->handler = "rrdgraph"; | ||||
return OK; | ||||
} | ||||
return DECLINED; | ||||
} | ||||
static int rrd_handler(request_rec *r) | static int rrd_handler(request_rec *r) | |||
{ | { | |||
rrd_conf *conf = ap_get_module_config(r->per_dir_config, | rrd_conf *conf = ap_get_module_config(r->per_dir_config, | |||
&rrd_module); | &rrd_module); | |||
if (!conf || !conf->graph) { | if (!conf || !conf->graph) { | |||
return DECLINED; | return DECLINED; | |||
} | } | |||
skipping to change at line 2503 | skipping to change at line 2630 | |||
rrd_conf *add = (rrd_conf *) addv; | rrd_conf *add = (rrd_conf *) addv; | |||
rrd_conf *base = (rrd_conf *) basev; | rrd_conf *base = (rrd_conf *) basev; | |||
new->options = apr_array_append(p, add->options, base->options); | new->options = apr_array_append(p, add->options, base->options); | |||
new->elements = apr_array_append(p, add->elements, base->elements); | new->elements = apr_array_append(p, add->elements, base->elements); | |||
new->env = apr_hash_overlay(p, add->env, base->env); | new->env = apr_hash_overlay(p, add->env, base->env); | |||
new->location = (add->location_set == 0) ? base->location : add->location; | new->location = (add->location_set == 0) ? base->location : add->location; | |||
new->location_set = add->location_set || base->location_set; | new->location_set = add->location_set || base->location_set; | |||
new->format = (add->format_set == 0) ? base->format : add->format; | ||||
new->format_set = add->format_set || base->format_set; | ||||
new->graph = (add->graph_set == 0) ? base->graph : add->graph; | new->graph = (add->graph_set == 0) ? base->graph : add->graph; | |||
new->graph_set = add->graph_set || base->graph_set; | new->graph_set = add->graph_set || base->graph_set; | |||
return new; | return new; | |||
} | } | |||
static const char *set_rrd_graph_format(cmd_parms *cmd, void *dconf, const char | ||||
*format) | ||||
{ | ||||
rrd_conf *conf = dconf; | ||||
conf->format = format; | ||||
conf->format_set = 1; | ||||
return NULL; | ||||
} | ||||
static const char *set_rrd_graph_option(cmd_parms *cmd, void *dconf, const char *key, const char *val) | static const char *set_rrd_graph_option(cmd_parms *cmd, void *dconf, const char *key, const char *val) | |||
{ | { | |||
rrd_conf *conf = dconf; | rrd_conf *conf = dconf; | |||
ap_expr_info_t *eval = NULL; | ap_expr_info_t *eval = NULL; | |||
const char *expr_err = NULL; | const char *expr_err = NULL; | |||
if (val) { | if (val) { | |||
eval = ap_expr_parse_cmd(cmd, val, AP_EXPR_FLAG_STRING_RESULT, | eval = ap_expr_parse_cmd(cmd, val, AP_EXPR_FLAG_STRING_RESULT, | |||
&expr_err, NULL); | &expr_err, NULL); | |||
skipping to change at line 2536 | skipping to change at line 2676 | |||
} | } | |||
if (!parse_option(cmd->pool, key, val, eval, conf->options)) { | if (!parse_option(cmd->pool, key, val, eval, conf->options)) { | |||
return apr_pstrcat(cmd->pool, "Could not recognise option: ", key, NULL) ; | return apr_pstrcat(cmd->pool, "Could not recognise option: ", key, NULL) ; | |||
} | } | |||
return NULL; | return NULL; | |||
} | } | |||
static const char *set_rrd_graph_element(cmd_parms *cmd, void *dconf, | static const char *set_rrd_graph_element(cmd_parms *cmd, void *dconf, | |||
const char *element, const char *legend) | const char *element, const char *val1, const char *val2) | |||
{ | { | |||
rrd_conf *conf = dconf; | rrd_conf *conf = dconf; | |||
ap_expr_info_t *elegend = NULL; | ap_expr_info_t *eval1 = NULL, *eval2 = NULL; | |||
const char *expr_err = NULL; | const char *expr_err = NULL; | |||
if (legend) { | if (val1) { | |||
eval1 = ap_expr_parse_cmd(cmd, val1, AP_EXPR_FLAG_STRING_RESULT, | ||||
&expr_err, NULL); | ||||
if (expr_err) { | ||||
return apr_pstrcat(cmd->temp_pool, | ||||
"Cannot parse expression '", val1, "': ", | ||||
expr_err, NULL); | ||||
} | ||||
} | ||||
if (val2) { | ||||
elegend = ap_expr_parse_cmd(cmd, legend, AP_EXPR_FLAG_STRING_RESULT, | eval2 = ap_expr_parse_cmd(cmd, val2, AP_EXPR_FLAG_STRING_RESULT, | |||
&expr_err, NULL); | &expr_err, NULL); | |||
if (expr_err) { | if (expr_err) { | |||
return apr_pstrcat(cmd->temp_pool, | return apr_pstrcat(cmd->temp_pool, | |||
"Cannot parse expression '", legend, "': ", | "Cannot parse expression '", val2, "': ", | |||
expr_err, NULL); | expr_err, NULL); | |||
} | } | |||
} | } | |||
if (!parse_element(cmd->pool, element, elegend, conf->elements)) { | if (!parse_element(cmd->pool, element, eval1, eval2, conf->elements)) { | |||
return apr_psprintf(cmd->pool, | return apr_psprintf(cmd->pool, | |||
"RRDGraphElement was not recognised: %s", element); | "RRDGraphElement was not recognised: %s", element); | |||
} | } | |||
return NULL; | return NULL; | |||
} | } | |||
static const char *set_rrd_graph_env(cmd_parms *cmd, void *dconf, | static const char *set_rrd_graph_env(cmd_parms *cmd, void *dconf, | |||
const char *key, const char *val) | const char *key, const char *val) | |||
{ | { | |||
skipping to change at line 2597 | skipping to change at line 2750 | |||
conf->graph = flag; | conf->graph = flag; | |||
conf->graph_set = 1; | conf->graph_set = 1; | |||
return NULL; | return NULL; | |||
} | } | |||
static const command_rec rrd_cmds[] = { | static const command_rec rrd_cmds[] = { | |||
AP_INIT_FLAG("RRDGraph", set_rrd_graph, NULL, RSRC_CONF | ACCESS_CONF, | AP_INIT_FLAG("RRDGraph", set_rrd_graph, NULL, RSRC_CONF | ACCESS_CONF, | |||
"Enable the rrdgraph image generator."), | "Enable the rrdgraph image generator."), | |||
AP_INIT_TAKE1("RRDGraphFormat", set_rrd_graph_format, NULL, RSRC_CONF | ACCE | ||||
SS_CONF, | ||||
"Explicitly set the image format. Takes any valid --imgformat value."), | ||||
AP_INIT_TAKE12("RRDGraphOption", set_rrd_graph_option, NULL, RSRC_CONF | ACC ESS_CONF, | AP_INIT_TAKE12("RRDGraphOption", set_rrd_graph_option, NULL, RSRC_CONF | ACC ESS_CONF, | |||
"Options for the rrdgraph image generator."), | "Options for the rrdgraph image generator."), | |||
AP_INIT_TAKE12("RRDGraphElement", set_rrd_graph_element, NULL, RSRC_CONF | A CCESS_CONF, | AP_INIT_TAKE123("RRDGraphElement", set_rrd_graph_element, NULL, RSRC_CONF | ACCESS_CONF, | |||
"Elements for the rrdgraph image generator. If specified, an optional ex pression can be set for the legend where appropriate."), | "Elements for the rrdgraph image generator. If specified, an optional ex pression can be set for the legend where appropriate."), | |||
AP_INIT_TAKE2("RRDGraphEnv", set_rrd_graph_env, NULL, RSRC_CONF | ACCESS_CON F, | AP_INIT_TAKE2("RRDGraphEnv", set_rrd_graph_env, NULL, RSRC_CONF | ACCESS_CON F, | |||
"Summarise environment variables from the RRD file requests."), { NULL } | "Summarise environment variables from the RRD file requests."), { NULL } | |||
}; | }; | |||
static void register_hooks(apr_pool_t *p) | static void register_hooks(apr_pool_t *p) | |||
{ | { | |||
ap_hook_child_init(rrd_child_init,NULL,NULL,APR_HOOK_MIDDLE); | ap_hook_child_init(rrd_child_init,NULL,NULL,APR_HOOK_MIDDLE); | |||
ap_hook_handler(rrd_handler, NULL, NULL, APR_HOOK_MIDDLE); | ap_hook_fixups(rrd_fixups, NULL, NULL, APR_HOOK_MIDDLE); | |||
ap_hook_handler(rrd_handler, NULL, NULL, APR_HOOK_FIRST); | ||||
} | } | |||
AP_DECLARE_MODULE(rrd) = { | AP_DECLARE_MODULE(rrd) = { | |||
STANDARD20_MODULE_STUFF, | STANDARD20_MODULE_STUFF, | |||
create_rrd_config, /* create per-directory config structure */ | create_rrd_config, /* create per-directory config structure */ | |||
merge_rrd_config, /* merge per-directory config structures */ | merge_rrd_config, /* merge per-directory config structures */ | |||
NULL, /* create per-server config structure */ | NULL, /* create per-server config structure */ | |||
NULL, /* merge per-server config structures */ | NULL, /* merge per-server config structures */ | |||
rrd_cmds, /* command apr_table_t */ | rrd_cmds, /* command apr_table_t */ | |||
register_hooks /* register hooks */ | register_hooks /* register hooks */ | |||
End of changes. 43 change blocks. | ||||
34 lines changed or deleted | 195 lines changed or added |