summaryrefslogtreecommitdiffstats
path: root/web/api/badges/web_buffer_svg.c
diff options
context:
space:
mode:
Diffstat (limited to 'web/api/badges/web_buffer_svg.c')
-rw-r--r--web/api/badges/web_buffer_svg.c130
1 files changed, 92 insertions, 38 deletions
diff --git a/web/api/badges/web_buffer_svg.c b/web/api/badges/web_buffer_svg.c
index ea07c894d..b5a1e03d0 100644
--- a/web/api/badges/web_buffer_svg.c
+++ b/web/api/badges/web_buffer_svg.c
@@ -507,23 +507,23 @@ static struct badge_color {
// colors from:
// https://github.com/badges/shields/blob/master/colorscheme.json
- { "brightgreen", 0, "#4c1" },
- { "green", 0, "#97CA00" },
- { "yellow", 0, "#dfb317" },
- { "yellowgreen", 0, "#a4a61d" },
- { "orange", 0, "#fe7d37" },
- { "red", 0, "#e05d44" },
- { "blue", 0, "#007ec6" },
- { "grey", 0, "#555" },
- { "gray", 0, "#555" },
- { "lightgrey", 0, "#9f9f9f" },
- { "lightgray", 0, "#9f9f9f" },
+ { "brightgreen", 0, "4c1" },
+ { "green", 0, "97CA00" },
+ { "yellow", 0, "dfb317" },
+ { "yellowgreen", 0, "a4a61d" },
+ { "orange", 0, "fe7d37" },
+ { "red", 0, "e05d44" },
+ { "blue", 0, "007ec6" },
+ { "grey", 0, "555" },
+ { "gray", 0, "555" },
+ { "lightgrey", 0, "9f9f9f" },
+ { "lightgray", 0, "9f9f9f" },
// terminator
{ NULL, 0, NULL }
};
-static inline const char *color_map(const char *color) {
+static inline const char *color_map(const char *color, const char *def) {
static int max = -1;
int i;
@@ -543,7 +543,7 @@ static inline const char *color_map(const char *color) {
return ptr->color;
}
- return color;
+ return def;
}
typedef enum color_comparison {
@@ -688,24 +688,66 @@ static inline void calc_colorz(const char *color, char *final, size_t len, calcu
// colors
#define COLOR_STRING_SIZE 100
-void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const char *units, const char *label_color, const char *value_color, int precision, int scale, uint32_t options, int fixed_width_lbl, int fixed_width_val) {
+static inline int allowed_hexa_char(char x) {
+ return ( (x >= '0' && x <= '9') ||
+ (x >= 'a' && x <= 'f') ||
+ (x >= 'A' && x <= 'F')
+ );
+}
+
+static int html_color_check(const char *str) {
+ int i = 0;
+ while(str[i]) {
+ if(!allowed_hexa_char(str[i]))
+ return 0;
+ if(unlikely(i >= 6))
+ return 0;
+ i++;
+ }
+ // want to allow either RGB or RRGGBB
+ return ( i == 6 || i == 3 );
+}
+
+// Will parse color arg as #RRGGBB or #RGB or one of the colors
+// from color_map hash table
+// if parsing fails (argument error) it will return default color
+// given as default parameter (def)
+// in any case it will return either color in "RRGGBB" or "RGB" format as string
+// or whatever is given as def (without checking - caller responsible to give sensible
+// safely escaped default) as default if it fails
+// in any case this function must always return something we can put directly in XML
+// so no escaping is necessary anymore (with excpetion of default where caller is responsible)
+// to give sensible default
+#define BADGE_SVG_COLOR_ARG_MAXLEN 20
+
+static const char *parse_color_argument(const char *arg, const char *def)
+{
+ if( !arg )
+ return def;
+ size_t len = strnlen(arg, BADGE_SVG_COLOR_ARG_MAXLEN);
+ if( len < 2 || len >= BADGE_SVG_COLOR_ARG_MAXLEN )
+ return def;
+ if( html_color_check(arg) )
+ return arg;
+ return color_map(arg, def);
+}
+
+void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const char *units, const char *label_color, const char *value_color, int precision, int scale, uint32_t options, int fixed_width_lbl, int fixed_width_val, const char* text_color_lbl, const char* text_color_val) {
char value_color_buffer[COLOR_STRING_SIZE + 1]
, value_string[VALUE_STRING_SIZE + 1]
, label_escaped[LABEL_STRING_SIZE + 1]
- , value_escaped[VALUE_STRING_SIZE + 1]
- , label_color_escaped[COLOR_STRING_SIZE + 1]
- , value_color_escaped[COLOR_STRING_SIZE + 1];
+ , value_escaped[VALUE_STRING_SIZE + 1];
+
+ const char *label_color_parsed;
+ const char *value_color_parsed;
double label_width = (double)fixed_width_lbl, value_width = (double)fixed_width_val, total_width;
double height = 20.0, font_size = 11.0, text_offset = 5.8, round_corner = 3.0;
if(scale < 100) scale = 100;
- if(unlikely(!label_color || !*label_color))
- label_color = "#555";
-
if(unlikely(!value_color || !*value_color))
- value_color = (isnan(value) || isinf(value))?"#999":"#4c1";
+ value_color = (isnan(value) || isinf(value))?"999":"4c1";
calc_colorz(value_color, value_color_buffer, COLOR_STRING_SIZE, value);
format_value_and_unit(value_string, VALUE_STRING_SIZE, (options & RRDR_OPTION_DISPLAY_ABS)?calculated_number_fabs(value):value, units, precision);
@@ -718,8 +760,9 @@ void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const ch
escape_xmlz(label_escaped, label, LABEL_STRING_SIZE);
escape_xmlz(value_escaped, value_string, VALUE_STRING_SIZE);
- escape_xmlz(label_color_escaped, color_map(label_color), COLOR_STRING_SIZE);
- escape_xmlz(value_color_escaped, color_map(value_color_buffer), COLOR_STRING_SIZE);
+
+ label_color_parsed = parse_color_argument(label_color, "555");
+ value_color_parsed = parse_color_argument(value_color_buffer, "555");
wb->contenttype = CT_IMAGE_SVG_XML;
@@ -743,10 +786,10 @@ void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const ch
"<rect class=\"bdge-ttl-width\" width=\"%0.2f\" height=\"%0.2f\" rx=\"%0.2f\" fill=\"#fff\"/>"
"</mask>"
"<g mask=\"url(#round)\">"
- "<rect class=\"bdge-rect-lbl\" width=\"%0.2f\" height=\"%0.2f\" fill=\"%s\"/>",
+ "<rect class=\"bdge-rect-lbl\" width=\"%0.2f\" height=\"%0.2f\" fill=\"#%s\"/>",
total_width, height,
total_width, height, round_corner,
- label_width, height, label_color_escaped); //<rect class="bdge-rect-lbl"
+ label_width, height, label_color_parsed); //<rect class="bdge-rect-lbl"
if(fixed_width_lbl > 0 && fixed_width_val > 0) {
buffer_sprintf(wb,
@@ -757,8 +800,8 @@ void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const ch
}
buffer_sprintf(wb,
- "<rect class=\"bdge-rect-val\" x=\"%0.2f\" width=\"%0.2f\" height=\"%0.2f\" fill=\"%s\"/>",
- label_width, value_width, height, value_color_escaped);
+ "<rect class=\"bdge-rect-val\" x=\"%0.2f\" width=\"%0.2f\" height=\"%0.2f\" fill=\"#%s\"/>",
+ label_width, value_width, height, value_color_parsed);
if(fixed_width_lbl > 0 && fixed_width_val > 0) {
buffer_sprintf(wb,
@@ -771,18 +814,18 @@ void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const ch
buffer_sprintf(wb,
"<rect class=\"bdge-ttl-width\" width=\"%0.2f\" height=\"%0.2f\" fill=\"url(#smooth)\"/>"
"</g>"
- "<g fill=\"#fff\" text-anchor=\"middle\" font-family=\"DejaVu Sans,Verdana,Geneva,sans-serif\" font-size=\"%0.2f\">"
+ "<g text-anchor=\"middle\" font-family=\"DejaVu Sans,Verdana,Geneva,sans-serif\" font-size=\"%0.2f\">"
"<text class=\"bdge-lbl-lbl\" x=\"%0.2f\" y=\"%0.0f\" fill=\"#010101\" fill-opacity=\".3\" clip-path=\"url(#lbl-rect)\">%s</text>"
- "<text class=\"bdge-lbl-lbl\" x=\"%0.2f\" y=\"%0.0f\" clip-path=\"url(#lbl-rect)\">%s</text>"
+ "<text class=\"bdge-lbl-lbl\" x=\"%0.2f\" y=\"%0.0f\" fill=\"#%s\" clip-path=\"url(#lbl-rect)\">%s</text>"
"<text class=\"bdge-lbl-val\" x=\"%0.2f\" y=\"%0.0f\" fill=\"#010101\" fill-opacity=\".3\" clip-path=\"url(#val-rect)\">%s</text>"
- "<text class=\"bdge-lbl-val\" x=\"%0.2f\" y=\"%0.0f\" clip-path=\"url(#val-rect)\">%s</text>"
+ "<text class=\"bdge-lbl-val\" x=\"%0.2f\" y=\"%0.0f\" fill=\"#%s\" clip-path=\"url(#val-rect)\">%s</text>"
"</g>",
total_width, height,
font_size,
label_width / 2, ceil(height - text_offset), label_escaped,
- label_width / 2, ceil(height - text_offset - 1.0), label_escaped,
+ label_width / 2, ceil(height - text_offset - 1.0), parse_color_argument(text_color_lbl, "fff"), label_escaped,
label_width + value_width / 2 -1, ceil(height - text_offset), value_escaped,
- label_width + value_width / 2 -1, ceil(height - text_offset - 1.0), value_escaped);
+ label_width + value_width / 2 -1, ceil(height - text_offset - 1.0), parse_color_argument(text_color_val, "fff"), value_escaped);
if(fixed_width_lbl <= 0 || fixed_width_val <= 0){
buffer_sprintf(wb,
@@ -815,6 +858,9 @@ void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const ch
buffer_sprintf(wb, "</svg>");
}
+#define BADGE_URL_ARG_LBL_COLOR "text_color_lbl"
+#define BADGE_URL_ARG_VAL_COLOR "text_color_val"
+
int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *url) {
int ret = HTTP_RESP_BAD_REQUEST;
buffer_flush(w->response.data);
@@ -836,7 +882,9 @@ int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *u
, *scale_str = NULL
, *alarm = NULL
, *fixed_width_lbl_str = NULL
- , *fixed_width_val_str = NULL;
+ , *fixed_width_val_str = NULL
+ , *text_color_lbl_str = NULL
+ , *text_color_val_str = NULL;
int group = RRDR_GROUPING_AVERAGE;
uint32_t options = 0x00000000;
@@ -883,6 +931,8 @@ int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *u
else if(!strcmp(name, "fixed_width_lbl")) fixed_width_lbl_str = value;
else if(!strcmp(name, "fixed_width_val")) fixed_width_val_str = value;
else if(!strcmp(name, "alarm")) alarm = value;
+ else if(!strcmp(name, BADGE_URL_ARG_LBL_COLOR)) text_color_lbl_str = value;
+ else if(!strcmp(name, BADGE_URL_ARG_VAL_COLOR)) text_color_val_str = value;
}
int fixed_width_lbl = -1;
@@ -893,7 +943,7 @@ int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *u
fixed_width_lbl = str2i(fixed_width_lbl_str);
fixed_width_val = str2i(fixed_width_val_str);
}
-
+
if(!chart || !*chart) {
buffer_no_cacheable(w->response.data);
buffer_sprintf(w->response.data, "No chart id is given at the request.");
@@ -906,7 +956,7 @@ int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *u
if(!st) st = rrdset_find_byname(host, chart);
if(!st) {
buffer_no_cacheable(w->response.data);
- buffer_svg(w->response.data, "chart not found", NAN, "", NULL, NULL, -1, scale, 0, -1, -1);
+ buffer_svg(w->response.data, "chart not found", NAN, "", NULL, NULL, -1, scale, 0, -1, -1, NULL, NULL);
ret = HTTP_RESP_OK;
goto cleanup;
}
@@ -917,7 +967,7 @@ int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *u
rc = rrdcalc_find(st, alarm);
if (!rc) {
buffer_no_cacheable(w->response.data);
- buffer_svg(w->response.data, "alarm not found", NAN, "", NULL, NULL, -1, scale, 0, -1, -1);
+ buffer_svg(w->response.data, "alarm not found", NAN, "", NULL, NULL, -1, scale, 0, -1, -1, NULL, NULL);
ret = HTTP_RESP_OK;
goto cleanup;
}
@@ -1037,7 +1087,9 @@ int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *u
scale,
options,
fixed_width_lbl,
- fixed_width_val
+ fixed_width_val,
+ text_color_lbl_str,
+ text_color_val_str
);
ret = HTTP_RESP_OK;
}
@@ -1076,7 +1128,9 @@ int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *u
scale,
options,
fixed_width_lbl,
- fixed_width_val
+ fixed_width_val,
+ text_color_lbl_str,
+ text_color_val_str
);
}