diff --git a/libr/lang/p/qjs.c b/libr/lang/p/qjs.c index 09d7349f0b..540e5c203a 100644 --- a/libr/lang/p/qjs.c +++ b/libr/lang/p/qjs.c @@ -9,6 +9,9 @@ #include "../js_require.c" #include "../js_r2papi.c" +static R_TH_LOCAL JSContext *Gctx = NULL; +static R_TH_LOCAL JSValue Gfunc; + typedef struct { JSContext *ctx; JSRuntime *r; @@ -88,6 +91,85 @@ static JSValue b64(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst free (ret); return v; } + +static int r2plugin_core_call(void *_core, const char *input) { + // RCore *core = _core; + JSValueConst args[1] = { + JS_NewString (Gctx, input) + }; + JSValue res = JS_Call (Gctx, Gfunc, JS_UNDEFINED, countof (args), args); + return JS_ToBool (Gctx, res) == 1; +} + +static JSValue r2plugin_core(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { + JSRuntime *rt = JS_GetRuntime (ctx); + QjsContext *k = JS_GetRuntimeOpaque (rt); + RCore *core = k->core; + if (argc != 2) { + return JS_ThrowRangeError(ctx, "r2plugin expects two arguments"); + } + + JSValueConst args[1] = { + JS_NewString (ctx, "POP"), + }; + JSValue res = JS_Call (ctx, argv[1], JS_UNDEFINED, countof (args), args); + + // check if res is an object + if (!JS_IsObject (res)) { + return JS_ThrowRangeError(ctx, "r2plugin function must return an object"); + } + + RCorePlugin *ap = R_NEW0 (RCorePlugin); + JSValue name = JS_GetPropertyStr (ctx, res, "name"); + size_t namelen; + const char *nameptr = JS_ToCStringLen2 (ctx, &namelen, name, false); + if (nameptr) { + ap->name = strdup (nameptr); + } + JSValue desc = JS_GetPropertyStr (ctx, res, "desc"); + const char *descptr = JS_ToCStringLen2 (ctx, &namelen, desc, false); + if (descptr) { + ap->desc = strdup (descptr); + } + JSValue license = JS_GetPropertyStr (ctx, res, "license"); + const char *licenseptr = JS_ToCStringLen2 (ctx, &namelen, license, false); + if (licenseptr) { + ap->license = strdup (licenseptr); + } + JSValue func = JS_GetPropertyStr (ctx, res, "call"); + Gctx = ctx; // XXX dont do globals + Gfunc = func; + + ap->call = r2plugin_core_call; + + RLibStruct *lib = R_NEW0 (RLibStruct); + lib->type = R_LIB_TYPE_CORE; + lib->data = ap; + lib->version = R2_VERSION; + + r_lib_open_ptr (core->lib, "qjs", NULL, lib); + + // ret = k->core->pluginAdd (k->core, n); +// r_core_plugin_add (core, ap); + return JS_NewBool (ctx, true); +} + +static JSValue r2plugin(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { + size_t plen; + const char *n = JS_ToCStringLen2 (ctx, &plen, argv[0], false); + if (R_STR_ISNOTEMPTY (n)) { + if (!strcmp (n, "core")) { + // { name: string, call: function, license: string, desc: string } + // JSValue val = + return r2plugin_core (ctx, this_val, argc, argv); + } else { + // invalid throw exception here + return JS_ThrowRangeError(ctx, "invalid r2plugin type"); + } + } + return JS_NewBool (ctx, false); +} + static JSValue r2cmd(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { JSRuntime *rt = JS_GetRuntime (ctx); QjsContext *k = JS_GetRuntimeOpaque (rt); @@ -218,6 +300,8 @@ static void register_helpers(JSContext *ctx) { JS_NewCFunction (ctx, b64, "b64", 1)); JS_SetPropertyStr (ctx, global_obj, "r2cmd", JS_NewCFunction (ctx, r2cmd, "r2cmd", 1)); + JS_SetPropertyStr (ctx, global_obj, "r2plugin", + JS_NewCFunction (ctx, r2plugin, "r2plugin", 1)); JS_SetPropertyStr (ctx, global_obj, "r2log", JS_NewCFunction (ctx, r2log, "r2log", 1)); JS_SetPropertyStr (ctx, global_obj, "write", diff --git a/libr/lang/t/coreplug.qjs b/libr/lang/t/coreplug.qjs new file mode 100644 index 0000000000..65228b7e44 --- /dev/null +++ b/libr/lang/t/coreplug.qjs @@ -0,0 +1,24 @@ + + +const { log } = console; + +function examplePlugin() { + function coreCall(input) { + if (input.startsWith("test")) { + log("This is a QJS test"); + return true; + } + return false; + } + return { + name: "qjs-example", + desc: "Example QJS plugin (type 'test') in the r2 shell", + call: coreCall, + }; +} + +log("Installing the `qjs-example` core plugin"); +log("Type 'test' to confirm it works"); +r2plugin("core", examplePlugin); +log(r2cmd("Lc")); + diff --git a/libr/util/file.c b/libr/util/file.c index 77335823f1..f810b8c8f3 100644 --- a/libr/util/file.c +++ b/libr/util/file.c @@ -1569,11 +1569,9 @@ R_API const char *r_file_extension(const char *str) { R_API bool r_file_is_newer(const char *f1, const char *f2) { struct stat a1, a2; if (stat (f1, &a1) == -1) { - eprintf ("no\n"); return false; } if (stat (f2, &a2) == -1) { - eprintf ("no 2\n"); return false; } long a = a1.st_mtime;