2024-06-07 10:14:13 +00:00
|
|
|
/* radare - LGPL - Copyright 2009-2024 - pancake, nibble */
|
2020-03-03 23:09:12 +00:00
|
|
|
|
|
|
|
#include <r_cons.h>
|
|
|
|
|
2023-02-20 21:05:38 +00:00
|
|
|
static bool gethtmlrgb(const char *str, char *buf, size_t buf_size) {
|
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)) {
|
2023-02-20 21:05:38 +00:00
|
|
|
snprintf (buf, buf_size, "#%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;
|
2020-08-17 06:13:20 +00:00
|
|
|
bool inv = false;
|
|
|
|
char text_color[16] = {0};
|
|
|
|
char background_color[16] = {0};
|
2023-07-31 23:54:55 +00:00
|
|
|
bool has_bold = false;
|
2020-08-17 06:13:20 +00:00
|
|
|
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;
|
|
|
|
}
|
2024-06-07 10:14:13 +00:00
|
|
|
for (; ptr[0]; ptr++) {
|
2020-08-17 06:13:20 +00:00
|
|
|
if (esc == 0 && ptr[0] != 0x1b && need_to_set) {
|
|
|
|
if (has_set) {
|
2024-09-24 09:35:46 +00:00
|
|
|
r_strbuf_append (res, "</span>");
|
2020-08-17 06:13:20 +00:00
|
|
|
has_set = false;
|
|
|
|
}
|
|
|
|
if (!need_to_clear) {
|
|
|
|
first_style = true;
|
2024-09-24 09:35:46 +00:00
|
|
|
r_strbuf_append (res, "<span");
|
2020-08-17 06:13:20 +00:00
|
|
|
if (text_color[0]) {
|
2024-09-24 09:35:46 +00:00
|
|
|
r_strbuf_append (res, first_style? " style='": ";");
|
|
|
|
r_strbuf_appendf (res, "color:%s", text_color);
|
|
|
|
first_style = false;
|
2020-08-17 06:13:20 +00:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
2023-07-31 23:54:55 +00:00
|
|
|
if (has_bold) {
|
|
|
|
r_strbuf_append (res, first_style? " style='": ";");
|
|
|
|
r_strbuf_append (res, "font-weight:bold");
|
|
|
|
first_style = false;
|
|
|
|
}
|
2020-08-17 06:13:20 +00:00
|
|
|
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') {
|
2024-06-07 10:14:13 +00:00
|
|
|
if (ptr > str) {
|
|
|
|
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;
|
2020-03-03 23:09:12 +00:00
|
|
|
} else {
|
2024-06-07 10:14:13 +00:00
|
|
|
r_strbuf_append (res, "<br />\n");
|
2020-03-03 23:09:12 +00:00
|
|
|
}
|
|
|
|
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);
|
2024-06-07 10:14:13 +00:00
|
|
|
if (tmp > 0) {
|
|
|
|
r_strbuf_append_n (res, str, tmp);
|
|
|
|
str = ptr + 1;
|
|
|
|
} else {
|
|
|
|
str++;
|
|
|
|
}
|
2020-03-03 23:09:12 +00:00
|
|
|
r_strbuf_append (res, " ");
|
|
|
|
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;
|
2023-03-10 21:51:41 +00:00
|
|
|
}
|
|
|
|
if (esc == 2) {
|
2020-03-03 23:09:12 +00:00
|
|
|
// 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;
|
2023-07-31 23:54:55 +00:00
|
|
|
} else if (ptr[0] == '1') {
|
|
|
|
// ignore bold
|
|
|
|
has_bold = true;
|
2020-03-03 23:09:12 +00:00
|
|
|
} 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;
|
2024-09-17 15:05:59 +00:00
|
|
|
} else if (isdigit (ptr[0]) && ptr[1] == ';' && isdigit (ptr[2])) {
|
2022-05-07 18:53:06 +00:00
|
|
|
char *m = strchr (ptr, 'm');
|
|
|
|
if (m) {
|
2023-02-20 21:05:38 +00:00
|
|
|
gethtmlrgb (ptr, background_color, sizeof (background_color));
|
2022-05-07 18:53:06 +00:00
|
|
|
need_to_set = true;
|
|
|
|
ptr = m;
|
|
|
|
str = ptr + 1;
|
|
|
|
esc = 0;
|
|
|
|
}
|
2024-09-17 15:05:59 +00:00
|
|
|
} else if (isdigit (ptr[0]) && isdigit (ptr[1]) && ptr[2] == ';') {
|
2022-05-07 18:53:06 +00:00
|
|
|
char *m = strchr (ptr, 'm');
|
|
|
|
if (m) {
|
2023-02-20 21:05:38 +00:00
|
|
|
gethtmlrgb (ptr, text_color, sizeof (text_color));
|
2022-05-07 18:53:06 +00:00
|
|
|
need_to_set = true;
|
|
|
|
ptr = m;
|
|
|
|
str = ptr + 1;
|
|
|
|
esc = 0;
|
|
|
|
}
|
2022-06-28 12:32:12 +00:00
|
|
|
} else if (r_str_startswith (ptr, "48;5;") || r_str_startswith (ptr, "48;2;")) {
|
2020-03-03 23:09:12 +00:00
|
|
|
char *end = strchr (ptr, 'm');
|
2023-02-20 21:05:38 +00:00
|
|
|
gethtmlrgb (ptr, background_color, sizeof (background_color));
|
2020-08-17 06:13:20 +00:00
|
|
|
need_to_set = true;
|
2020-03-03 23:09:12 +00:00
|
|
|
ptr = end;
|
|
|
|
str = ptr + 1;
|
|
|
|
esc = 0;
|
2022-06-28 12:32:12 +00:00
|
|
|
} else if (r_str_startswith (ptr, "38;5;") || r_str_startswith (ptr, "38;2;")) {
|
2020-03-03 23:09:12 +00:00
|
|
|
char *end = strchr (ptr, 'm');
|
2023-02-20 21:05:38 +00:00
|
|
|
gethtmlrgb (ptr, text_color, sizeof (text_color));
|
2020-08-17 06:13:20 +00:00
|
|
|
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;
|
2024-09-17 15:05:59 +00:00
|
|
|
} else if ((ptr[0] == '0' || ptr[0] == '1') && ptr[1] == ';' && isdigit (ptr[2])) {
|
2022-05-07 18:53:06 +00:00
|
|
|
// bg color is kind of ignored, but no glitch so far
|
|
|
|
r_cons_gotoxy (0, 0);
|
|
|
|
ptr += 4;
|
|
|
|
esc = 0;
|
|
|
|
str = ptr;
|
|
|
|
continue;
|
2020-03-03 23:09:12 +00:00
|
|
|
} else if (ptr[0] == '0' && ptr[1] == 'm') {
|
2022-11-30 16:13:32 +00:00
|
|
|
ptr++;
|
|
|
|
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
|
2022-06-28 12:32:12 +00:00
|
|
|
} else if (r_str_startswith (ptr, "27m")) {
|
2020-08-17 06:13:20 +00:00
|
|
|
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') {
|
2022-11-30 16:13:32 +00:00
|
|
|
ptr++;
|
|
|
|
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;
|
2023-03-10 21:51:41 +00:00
|
|
|
} else if ((ptr[0] == '4' || ptr[0] == '9') && 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-06-07 10:14:13 +00:00
|
|
|
if (ptr > str) {
|
|
|
|
r_strbuf_append_n (res, str, ptr - str);
|
|
|
|
}
|
2020-08-17 06:13:20 +00:00
|
|
|
if (has_set) {
|
2024-09-24 09:35:46 +00:00
|
|
|
r_strbuf_append (res, "</span>");
|
2020-03-03 23:09:12 +00:00
|
|
|
}
|
|
|
|
if (newlen) {
|
|
|
|
*newlen = res->len;
|
|
|
|
}
|
|
|
|
return r_strbuf_drain (res);
|
|
|
|
}
|
|
|
|
|