mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-23 21:29:49 +00:00
Fix #20760 - Implement native gron via ~{=} ##shell
This commit is contained in:
parent
97c77155f9
commit
ec884e6dfa
@ -2,6 +2,7 @@
|
||||
|
||||
#include <r_cons.h>
|
||||
#include <r_util/r_print.h>
|
||||
#include <r_util/r_json.h>
|
||||
#include <sdb.h>
|
||||
|
||||
#define I(x) r_cons_singleton ()->x
|
||||
@ -46,6 +47,7 @@ static const char *help_detail_tilde[] = {
|
||||
" {}", "", "json indentation",
|
||||
" {}..", "", "less json indentation",
|
||||
" {}...", "", "hud json indentation",
|
||||
" {=}", "", "gron-like output (key=value)",
|
||||
" {path}", "", "json path grep",
|
||||
"endmodifier:", "", "",
|
||||
" $", "", "words must be placed at the end of line",
|
||||
@ -157,6 +159,9 @@ static void parse_grep_expression(const char *str) {
|
||||
} else if (r_str_startswith (ptr, "{:..")) {
|
||||
grep->less = 1;
|
||||
}
|
||||
} else if (ptr[1] == '=' && ptr[2] == '}') {
|
||||
grep->gron = true;
|
||||
ptr += 2;
|
||||
} else if (ptr[1] == '}') {
|
||||
// standard json indentation
|
||||
grep->json = 1;
|
||||
@ -404,17 +409,16 @@ static char *find_next_intgrep(char *cmd, const char *quotes) {
|
||||
* with reshaped grep expression.
|
||||
*/
|
||||
static char *preprocess_filter_expr(char *cmd, const char *quotes) {
|
||||
char *p1, *p2, *ns = NULL;
|
||||
char *p2, *ns = NULL;
|
||||
const char *strsep = "&";
|
||||
int len;
|
||||
int i;
|
||||
|
||||
p1 = find_next_intgrep (cmd, quotes);
|
||||
char *p1 = find_next_intgrep (cmd, quotes);
|
||||
if (!p1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = strlen (p1);
|
||||
int len = strlen (p1);
|
||||
if (len > 4 && r_str_endswith (p1, "~?") && p1[len - 3] != '\\') {
|
||||
p1[len - 2] = '\0';
|
||||
ns = r_str_append (ns, "?");
|
||||
@ -504,10 +508,68 @@ static int cmp(const void *a, const void *b) {
|
||||
return strcmp (a, b);
|
||||
}
|
||||
|
||||
static bool gron(RStrBuf *sb, RJson *node, const char *root) {
|
||||
if (!sb || !node || !root) {
|
||||
return false;
|
||||
}
|
||||
switch (node->type) {
|
||||
case R_JSON_ARRAY:
|
||||
{
|
||||
RJson *cn = node->children.first;
|
||||
int n = 0;
|
||||
r_strbuf_appendf (sb, "%s = [];\n", root);
|
||||
while (cn) {
|
||||
char *newroot = r_str_newf ("%s[%d]", root, n);
|
||||
gron (sb, cn, newroot);
|
||||
free (newroot);
|
||||
cn = cn->next;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case R_JSON_OBJECT:
|
||||
{
|
||||
RJson *cn = node->children.first;
|
||||
r_strbuf_appendf (sb, "%s = {};\n", root);
|
||||
while (cn) {
|
||||
char *newroot = r_str_newf ("%s.%s", root, cn->key);
|
||||
gron (sb, cn, newroot);
|
||||
cn = cn->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case R_JSON_STRING:
|
||||
{
|
||||
size_t l = strlen (node->str_value);
|
||||
char *estr = r_str_encoded_json (node->str_value, l, PJ_ENCODING_STR_DEFAULT);
|
||||
r_strbuf_appendf (sb, "%s = \"%s\";\n", root, estr);
|
||||
free (estr);
|
||||
}
|
||||
break;
|
||||
case R_JSON_BOOLEAN:
|
||||
r_strbuf_appendf (sb, "%s = %s;\n", root, r_str_bool (node->num.u_value));
|
||||
break;
|
||||
case R_JSON_INTEGER:
|
||||
r_strbuf_appendf (sb, "%s = %"PFMT64d";\n", root, node->num.u_value);
|
||||
break;
|
||||
case R_JSON_NULL:
|
||||
r_strbuf_appendf (sb, "%s = null;\n", root);
|
||||
break;
|
||||
case R_JSON_DOUBLE:
|
||||
r_strbuf_appendf (sb, "%s = %lf;\n", root, node->num.dbl_value);
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
eprintf ("unk %s\n", r_json_type (node));
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API void r_cons_grepbuf(void) {
|
||||
RCons *cons = r_cons_singleton ();
|
||||
const char *buf = cons->context->buffer;
|
||||
const int len = cons->context->buffer_len;
|
||||
size_t len = cons->context->buffer_len;
|
||||
RConsGrep *grep = &cons->context->grep;
|
||||
const char *in = buf;
|
||||
int ret, total_lines = 0, l = 0, tl = 0;
|
||||
@ -542,9 +604,9 @@ R_API void r_cons_grepbuf(void) {
|
||||
}
|
||||
|
||||
if ((!len || !buf || !*buf) && (grep->json || grep->less)) {
|
||||
grep->json = 0;
|
||||
grep->json = false;
|
||||
grep->hud = false;
|
||||
grep->less = 0;
|
||||
grep->hud = 0;
|
||||
return;
|
||||
}
|
||||
if (grep->ascart) {
|
||||
@ -573,6 +635,23 @@ R_API void r_cons_grepbuf(void) {
|
||||
free (sin);
|
||||
return;
|
||||
}
|
||||
if (grep->gron) {
|
||||
char *a = strdup (cons->context->buffer);
|
||||
RJson *node = r_json_parse (a);
|
||||
RStrBuf *sb = r_strbuf_new ("");
|
||||
gron (sb, node, "json");
|
||||
char *s = r_strbuf_drain (sb);
|
||||
R_FREE (cons->context->buffer);
|
||||
cons->context->buffer_len = 0;
|
||||
cons->context->buffer_sz = 0;
|
||||
r_cons_print (s);
|
||||
buf = cons->context->buffer;
|
||||
len = cons->context->buffer_len;
|
||||
goto continuation;
|
||||
r_json_free (node);
|
||||
free (a);
|
||||
return;
|
||||
}
|
||||
if (grep->json) {
|
||||
if (grep->json_path) {
|
||||
char *u = sdb_json_get_str (cons->context->buffer, grep->json_path);
|
||||
@ -643,7 +722,9 @@ R_API void r_cons_grepbuf(void) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
RStrBuf *ob = r_strbuf_new ("");
|
||||
RStrBuf *ob = NULL;
|
||||
continuation:
|
||||
ob = r_strbuf_new ("");
|
||||
// if we modify cons->lines we should update I.context->buffer too
|
||||
cons->lines = 0;
|
||||
// used to count lines and change negative grep.line values
|
||||
|
@ -91,7 +91,8 @@ typedef struct r_cons_grep_t {
|
||||
int less;
|
||||
bool hud;
|
||||
bool human;
|
||||
int json;
|
||||
bool gron;
|
||||
bool json;
|
||||
char *json_path;
|
||||
int range_line;
|
||||
int line;
|
||||
|
@ -57,6 +57,7 @@ R_API R_MUSTUSE RJson *r_json_parse(R_BORROW char *text);
|
||||
R_API void r_json_free(RJson *js);
|
||||
R_API const RJson *r_json_get(const RJson *json, const char *key); // get object's property by key
|
||||
R_API const RJson *r_json_item(const RJson *json, size_t idx); // get array element by index
|
||||
R_API const char *r_json_type(const RJson *json);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -398,3 +398,22 @@ R_API const RJson *r_json_item(const RJson *json, size_t idx) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
R_API const char *r_json_type(const RJson *json) {
|
||||
switch (json->type) {
|
||||
case R_JSON_ARRAY:
|
||||
return "array";
|
||||
case R_JSON_OBJECT:
|
||||
return "object";
|
||||
case R_JSON_INTEGER:
|
||||
return "integer";
|
||||
case R_JSON_BOOLEAN:
|
||||
return "boolean";
|
||||
case R_JSON_DOUBLE:
|
||||
return "double";
|
||||
case R_JSON_STRING:
|
||||
return "string";
|
||||
case R_JSON_NULL:
|
||||
return "null";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
@ -543,3 +543,84 @@ EXPECT=<<EOF
|
||||
fd
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=ij.gron
|
||||
FILE=bins/elf/crackme
|
||||
CMDS=<<EOF
|
||||
ij~{=}
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
json = {};
|
||||
json.core = {};
|
||||
json.core.type = "EXEC (Executable file)";
|
||||
json.core.file = "bins/elf/crackme";
|
||||
json.core.fd = 3;
|
||||
json.core.size = 7441;
|
||||
json.core.humansz = "7.3K";
|
||||
json.core.iorw = false;
|
||||
json.core.mode = "r-x";
|
||||
json.core.minopsz = 1;
|
||||
json.core.maxopsz = 16;
|
||||
json.core.invopsz = 1;
|
||||
json.core.block = 256;
|
||||
json.core.format = "elf64";
|
||||
json.bin = {};
|
||||
json.bin.arch = "x86";
|
||||
json.bin.baddr = 4194304;
|
||||
json.bin.binsz = 7441;
|
||||
json.bin.bintype = "elf";
|
||||
json.bin.bits = 64;
|
||||
json.bin.canary = false;
|
||||
json.bin.class = "ELF64";
|
||||
json.bin.compiled = "";
|
||||
json.bin.compiler = "GCC: (Debian 4.4.5-8) 4.4.5";
|
||||
json.bin.crypto = false;
|
||||
json.bin.dbg_file = "";
|
||||
json.bin.endian = "little";
|
||||
json.bin.havecode = true;
|
||||
json.bin.guid = "";
|
||||
json.bin.intrp = "/lib64/ld-linux-x86-64.so.2";
|
||||
json.bin.laddr = 0;
|
||||
json.bin.lang = "c";
|
||||
json.bin.linenum = true;
|
||||
json.bin.lsyms = true;
|
||||
json.bin.machine = "AMD x86-64 architecture";
|
||||
json.bin.nx = true;
|
||||
json.bin.os = "linux";
|
||||
json.bin.cc = "";
|
||||
json.bin.pic = false;
|
||||
json.bin.relocs = true;
|
||||
json.bin.relro = "no";
|
||||
json.bin.rpath = "NONE";
|
||||
json.bin.sanitize = false;
|
||||
json.bin.static = false;
|
||||
json.bin.stripped = false;
|
||||
json.bin.subsys = "linux";
|
||||
json.bin.va = true;
|
||||
json.bin.checksums = {};
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=ij.gron.grep
|
||||
FILE=bins/elf/crackme
|
||||
CMDS=<<EOF
|
||||
ij~{=}opsz
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
json.core.minopsz = 1;
|
||||
json.core.maxopsz = 16;
|
||||
json.core.invopsz = 1;
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=ij.gron.grep.two
|
||||
FILE=bins/elf/crackme
|
||||
CMDS=<<EOF
|
||||
ij~{=}~opsz
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
json.core.minopsz = 1;
|
||||
json.core.maxopsz = 16;
|
||||
json.core.invopsz = 1;
|
||||
EOF
|
||||
RUN
|
||||
|
Loading…
Reference in New Issue
Block a user