2020-03-03 23:09:12 +00:00
|
|
|
/* radare - LGPL - Copyright 2009-2020 - pancake, nibble */
|
|
|
|
|
|
|
|
#include <r_cons.h>
|
|
|
|
|
2020-08-17 06:13:20 +00:00
|
|
|
static bool gethtmlrgb(const char *str, char *buf) {
|
2020-03-03 23:09:12 +00:00
|
|
|
ut8 r = 0, g = 0, b = 0;
|
|
|
|
if (r_cons_rgb_parse (str, &r, &g, &b, 0)) {
|
|
|
|
sprintf (buf, "#%02x%02x%02x", r, g, b);
|
2020-08-17 06:13:20 +00:00
|
|
|
return true;
|
2020-03-03 23:09:12 +00:00
|
|
|
}
|
2020-08-17 06:13:20 +00:00
|
|
|
buf[0] = '\0';
|
|
|
|
return false;
|
2020-03-03 23:09:12 +00:00
|
|
|
}
|
|
|
|
|
2020-08-17 06:13:20 +00:00
|
|
|
static const char *gethtmlcolor(const char ptrch) {
|
2020-03-03 23:09:12 +00:00
|
|
|
switch (ptrch) {
|
|
|
|
case '0': return "#000"; // BLACK
|
|
|
|
case '1': return "#f00"; // RED
|
|
|
|
case '2': return "#0f0"; // GREEN
|
|
|
|
case '3': return "#ff0"; // YELLOW
|
|
|
|
case '4': return "#00f"; // BLUE
|
|
|
|
case '5': return "#f0f"; // MAGENTA
|
|
|
|
case '6': return "#aaf"; // TURQOISE
|
|
|
|
case '7': return "#fff"; // WHITE
|
|
|
|
case '8': return "#777"; // GREY
|
2020-08-17 06:13:20 +00:00
|
|
|
case '9': break; // default
|
2020-03-03 23:09:12 +00:00
|
|
|
}
|
2020-08-17 06:13:20 +00:00
|
|
|
return "";
|
2020-03-03 23:09:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: move into r_util/str
|
|
|
|
R_API char *r_cons_html_filter(const char *ptr, int *newlen) {
|
|
|
|
const char *str = ptr;
|
|
|
|
int esc = 0;
|
|
|
|
int len = 0;
|
2020-08-17 06:13:20 +00:00
|
|
|
bool inv = false;
|
|
|
|
char text_color[16] = {0};
|
|
|
|
char background_color[16] = {0};
|
|
|
|
bool has_set = false;
|
|
|
|
bool need_to_set = false;
|
|
|
|
bool need_to_clear = false;
|
|
|
|
bool first_style;
|
2020-03-03 23:09:12 +00:00
|
|
|
int tmp;
|
|
|
|
if (!ptr) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
RStrBuf *res = r_strbuf_new ("");
|
|
|
|
if (!res) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
for (; ptr[0]; ptr = ptr + 1) {
|
2020-08-17 06:13:20 +00:00
|
|
|
if (esc == 0 && ptr[0] != 0x1b && need_to_set) {
|
|
|
|
if (has_set) {
|
|
|
|
r_strbuf_append (res, "</font>");
|
|
|
|
has_set = false;
|
|
|
|
}
|
|
|
|
if (!need_to_clear) {
|
|
|
|
first_style = true;
|
|
|
|
r_strbuf_append (res, "<font");
|
|
|
|
if (text_color[0]) {
|
|
|
|
r_strbuf_appendf (res, " color='%s'", text_color);
|
|
|
|
}
|
|
|
|
if (background_color[0]) {
|
|
|
|
r_strbuf_append (res, first_style? " style='": ";");
|
|
|
|
r_strbuf_appendf (res, "background-color:%s", background_color);
|
|
|
|
first_style = false;
|
|
|
|
}
|
|
|
|
if (inv) {
|
|
|
|
r_strbuf_append (res, first_style? " style='": ";");
|
|
|
|
r_strbuf_append (res, "text-decoration:underline overline");
|
|
|
|
first_style = false;
|
|
|
|
}
|
|
|
|
r_strbuf_append (res, first_style? ">": "'>");
|
|
|
|
has_set = true;
|
|
|
|
}
|
|
|
|
need_to_clear = false;
|
|
|
|
need_to_set = false;
|
|
|
|
}
|
2020-03-03 23:09:12 +00:00
|
|
|
if (ptr[0] == '\n') {
|
|
|
|
tmp = (int) (size_t) (ptr - str);
|
|
|
|
r_strbuf_append_n (res, str, tmp);
|
|
|
|
if (!ptr[1]) {
|
|
|
|
// write new line if it's the end of the output
|
|
|
|
r_strbuf_append (res, "\n");
|
|
|
|
} else {
|
|
|
|
r_strbuf_append (res, "<br />");
|
|
|
|
}
|
|
|
|
str = ptr + 1;
|
|
|
|
continue;
|
|
|
|
} else if (ptr[0] == '<') {
|
2020-08-17 06:13:20 +00:00
|
|
|
tmp = (int)(size_t) (ptr - str);
|
2020-03-03 23:09:12 +00:00
|
|
|
r_strbuf_append_n (res, str, tmp);
|
|
|
|
r_strbuf_append (res, "<");
|
|
|
|
str = ptr + 1;
|
|
|
|
continue;
|
|
|
|
} else if (ptr[0] == '>') {
|
2020-08-17 06:13:20 +00:00
|
|
|
tmp = (int)(size_t) (ptr - str);
|
2020-03-03 23:09:12 +00:00
|
|
|
r_strbuf_append_n (res, str, tmp);
|
|
|
|
r_strbuf_append (res, ">");
|
|
|
|
str = ptr + 1;
|
|
|
|
continue;
|
|
|
|
} else if (ptr[0] == ' ') {
|
|
|
|
tmp = (int) (size_t) (ptr - str);
|
|
|
|
r_strbuf_append_n (res, str, tmp);
|
|
|
|
r_strbuf_append (res, " ");
|
|
|
|
str = ptr + 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (ptr[0] == 0x1b) {
|
|
|
|
esc = 1;
|
2020-08-17 06:13:20 +00:00
|
|
|
tmp = (int)(size_t) (ptr - str);
|
2020-03-03 23:09:12 +00:00
|
|
|
r_strbuf_append_n (res, str, tmp);
|
|
|
|
str = ptr + 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (esc == 1) {
|
|
|
|
// \x1b[2J
|
|
|
|
if (ptr[0] != '[') {
|
2022-06-28 00:49:42 +00:00
|
|
|
R_LOG_ERROR ("Oops invalid escape char");
|
2020-03-03 23:09:12 +00:00
|
|
|
esc = 0;
|
|
|
|
str = ptr + 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
esc = 2;
|
|
|
|
continue;
|
|
|
|
} else if (esc == 2) {
|
|
|
|
// TODO: use dword comparison here
|
|
|
|
if (ptr[0] == '0' && ptr[1] == 'J') { // R_CONS_CLEAR_FROM_CURSOR_TO_END
|
|
|
|
ptr += 2;
|
|
|
|
esc = 0;
|
|
|
|
str = ptr;
|
|
|
|
} else if (!memcmp (ptr, "2K", 2)) {
|
|
|
|
ptr += 2;
|
|
|
|
esc = 0;
|
|
|
|
str = ptr;
|
|
|
|
continue;
|
|
|
|
} else if (ptr[0] == '2' && ptr[1] == 'J') {
|
|
|
|
r_strbuf_append (res, "<hr />");
|
|
|
|
ptr++;
|
|
|
|
esc = 0;
|
|
|
|
str = ptr;
|
|
|
|
continue;
|
2022-05-07 18:53:06 +00:00
|
|
|
} else if (IS_DIGIT (ptr[0]) && ptr[1] == ';' && IS_DIGIT (ptr[2])) {
|
|
|
|
char *m = strchr (ptr, 'm');
|
|
|
|
if (m) {
|
|
|
|
// char *s = r_str_ndup (ptr, m + 1 - ptr);
|
|
|
|
// eprintf ("ONE (%s)\n", s);
|
|
|
|
gethtmlrgb (ptr, background_color);
|
|
|
|
need_to_set = true;
|
|
|
|
ptr = m;
|
|
|
|
str = ptr + 1;
|
|
|
|
esc = 0;
|
|
|
|
}
|
|
|
|
} else if (IS_DIGIT (ptr[0]) && IS_DIGIT (ptr[1]) && ptr[2] == ';') {
|
|
|
|
char *m = strchr (ptr, 'm');
|
|
|
|
if (m) {
|
|
|
|
// char *s = r_str_ndup (ptr, m + 1 - ptr);
|
|
|
|
// eprintf ("TWO (%s)\n", s);
|
|
|
|
gethtmlrgb (ptr, text_color);
|
|
|
|
need_to_set = true;
|
|
|
|
ptr = m;
|
|
|
|
str = ptr + 1;
|
|
|
|
esc = 0;
|
|
|
|
}
|
2020-03-03 23:09:12 +00:00
|
|
|
} else if (!strncmp (ptr, "48;5;", 5) || !strncmp (ptr, "48;2;", 5)) {
|
|
|
|
char *end = strchr (ptr, 'm');
|
2020-08-17 06:13:20 +00:00
|
|
|
gethtmlrgb (ptr, background_color);
|
|
|
|
need_to_set = true;
|
2020-03-03 23:09:12 +00:00
|
|
|
ptr = end;
|
|
|
|
str = ptr + 1;
|
|
|
|
esc = 0;
|
|
|
|
} else if (!strncmp (ptr, "38;5;", 5) || !strncmp (ptr, "38;2;", 5)) {
|
|
|
|
char *end = strchr (ptr, 'm');
|
2020-08-17 06:13:20 +00:00
|
|
|
gethtmlrgb (ptr, text_color);
|
|
|
|
need_to_set = true;
|
2022-05-07 18:53:06 +00:00
|
|
|
if (end) {
|
|
|
|
ptr = end;
|
|
|
|
str = ptr + 1;
|
|
|
|
}
|
2020-03-03 23:09:12 +00:00
|
|
|
esc = 0;
|
2022-05-07 18:53:06 +00:00
|
|
|
} else if ((ptr[0] == '0' || ptr[0] == '1') && ptr[1] == ';' && IS_DIGIT (ptr[2])) {
|
|
|
|
// bg color is kind of ignored, but no glitch so far
|
|
|
|
r_cons_gotoxy (0, 0);
|
|
|
|
ptr += 4;
|
|
|
|
esc = 0;
|
|
|
|
str = ptr;
|
|
|
|
continue;
|
2022-04-19 18:32:11 +00:00
|
|
|
} else if ((ptr[0] == '0' || ptr[0] == '1') && ptr[1] == ';' && ptr[2] == '0') {
|
|
|
|
// bg color is kind of ignored, but no glitch so far
|
2020-03-03 23:09:12 +00:00
|
|
|
r_cons_gotoxy (0, 0);
|
|
|
|
ptr += 4;
|
|
|
|
esc = 0;
|
|
|
|
str = ptr;
|
|
|
|
continue;
|
|
|
|
} else if (ptr[0] == '0' && ptr[1] == 'm') {
|
|
|
|
str = (++ptr) + 1;
|
2020-08-17 06:13:20 +00:00
|
|
|
esc = 0;
|
|
|
|
inv = false;
|
|
|
|
text_color[0] = '\0';
|
|
|
|
background_color[0] = '\0';
|
|
|
|
need_to_set = need_to_clear = true;
|
2020-03-03 23:09:12 +00:00
|
|
|
continue;
|
|
|
|
// reset color
|
2020-08-17 06:13:20 +00:00
|
|
|
} else if (!strncmp (ptr, "27m", 3)) {
|
|
|
|
inv = false;
|
|
|
|
need_to_set = true;
|
|
|
|
ptr = ptr + 2;
|
|
|
|
str = ptr + 1;
|
|
|
|
esc = 0;
|
|
|
|
continue;
|
|
|
|
// reset invert color
|
2020-03-03 23:09:12 +00:00
|
|
|
} else if (ptr[0] == '7' && ptr[1] == 'm') {
|
|
|
|
str = (++ptr) + 1;
|
2020-08-17 06:13:20 +00:00
|
|
|
inv = true;
|
|
|
|
need_to_set = true;
|
2020-03-03 23:09:12 +00:00
|
|
|
esc = 0;
|
|
|
|
continue;
|
2020-08-17 06:13:20 +00:00
|
|
|
// invert color
|
2020-03-03 23:09:12 +00:00
|
|
|
} else if (ptr[0] == '3' && ptr[2] == 'm') {
|
2020-08-17 06:13:20 +00:00
|
|
|
const char *htmlColor = gethtmlcolor (ptr[1]);
|
2020-03-03 23:09:12 +00:00
|
|
|
if (htmlColor) {
|
2020-08-17 06:13:20 +00:00
|
|
|
r_str_ncpy (text_color, htmlColor, sizeof (text_color));
|
2020-03-03 23:09:12 +00:00
|
|
|
}
|
2020-08-17 06:13:20 +00:00
|
|
|
need_to_set = true;
|
|
|
|
ptr = ptr + 2;
|
|
|
|
str = ptr + 1;
|
2020-03-03 23:09:12 +00:00
|
|
|
esc = 0;
|
|
|
|
continue;
|
|
|
|
} else if (ptr[0] == '4' && ptr[2] == 'm') {
|
2020-08-17 06:13:20 +00:00
|
|
|
const char *htmlColor = gethtmlcolor (ptr[1]);
|
2020-03-03 23:09:12 +00:00
|
|
|
if (htmlColor) {
|
2020-08-17 06:13:20 +00:00
|
|
|
r_str_ncpy (background_color, htmlColor, sizeof (background_color));
|
2020-03-03 23:09:12 +00:00
|
|
|
}
|
2020-08-17 06:13:20 +00:00
|
|
|
need_to_set = true;
|
|
|
|
ptr = ptr + 2;
|
|
|
|
str = ptr + 1;
|
2020-03-03 23:09:12 +00:00
|
|
|
esc = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
len++;
|
|
|
|
}
|
2020-08-17 06:13:20 +00:00
|
|
|
r_strbuf_append_n (res, str, ptr - str);
|
|
|
|
if (has_set) {
|
2020-03-03 23:09:12 +00:00
|
|
|
r_strbuf_append (res, "</font>");
|
|
|
|
}
|
|
|
|
if (newlen) {
|
|
|
|
*newlen = res->len;
|
|
|
|
}
|
|
|
|
return r_strbuf_drain (res);
|
|
|
|
}
|
|
|
|
|