json: Make native messaging work.
* src/gpgme-json.c (opt_debug): New. (process_request): Add optional arg nm_mode. In this mode take the request from a "message" object. (native_messaging_repl): Add debug output and call process_request in NM_MODE. (main): Add option --debug. Parse envvar GPGME_JSON_DEBUG as an alternative way to enable this. Use a default log file. -- Note that the default log file is ~/.gnupg/S.gpgme-json.log . Thus to debug a javascript application you should start watchgnupg --time-only --force ~/.gnupg/S.gpgme-json.log in a separate tty and then use GPGME_JSON_DEBUG=1 firefox & to run firefox. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
7c220e387d
commit
4b2fa657d1
@ -56,7 +56,8 @@ static char *error_object_string (const char *message,
|
|||||||
|
|
||||||
/* True if interactive mode is active. */
|
/* True if interactive mode is active. */
|
||||||
static int opt_interactive;
|
static int opt_interactive;
|
||||||
|
/* True is debug mode is active. */
|
||||||
|
static int opt_debug;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -754,9 +755,10 @@ op_help (cjson_t request, cjson_t result)
|
|||||||
|
|
||||||
|
|
||||||
/* Process a request and return the response. The response is a newly
|
/* Process a request and return the response. The response is a newly
|
||||||
* allocated staring or NULL in case of an error. */
|
* allocated staring or NULL in case of an error. With NM_MODE set
|
||||||
|
* the actual request is taken from a "message" object. */
|
||||||
static char *
|
static char *
|
||||||
process_request (const char *request)
|
process_request (const char *request, int nm_mode)
|
||||||
{
|
{
|
||||||
static struct {
|
static struct {
|
||||||
const char *op;
|
const char *op;
|
||||||
@ -770,6 +772,7 @@ process_request (const char *request)
|
|||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
size_t erroff;
|
size_t erroff;
|
||||||
|
cjson_t json_orig;
|
||||||
cjson_t json;
|
cjson_t json;
|
||||||
cjson_t j_tmp, j_op;
|
cjson_t j_tmp, j_op;
|
||||||
cjson_t response;
|
cjson_t response;
|
||||||
@ -780,7 +783,7 @@ process_request (const char *request)
|
|||||||
|
|
||||||
response = xjson_CreateObject ();
|
response = xjson_CreateObject ();
|
||||||
|
|
||||||
json = cJSON_Parse (request, &erroff);
|
json = json_orig = cJSON_Parse (request, &erroff);
|
||||||
if (!json)
|
if (!json)
|
||||||
{
|
{
|
||||||
log_string (GPGRT_LOGLVL_INFO, request);
|
log_string (GPGRT_LOGLVL_INFO, request);
|
||||||
@ -788,6 +791,16 @@ process_request (const char *request)
|
|||||||
error_object (response, "invalid JSON object at offset %zu\n", erroff);
|
error_object (response, "invalid JSON object at offset %zu\n", erroff);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
if (nm_mode)
|
||||||
|
{
|
||||||
|
json = cJSON_GetObjectItem (json, "message");
|
||||||
|
if (!json)
|
||||||
|
{
|
||||||
|
log_info ("no \"message\" object in request\n");
|
||||||
|
error_object (response, "no \"message\" object in request\n");
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
j_tmp = cJSON_GetObjectItem (json, "help");
|
j_tmp = cJSON_GetObjectItem (json, "help");
|
||||||
helpmode = (j_tmp && cjson_is_true (j_tmp));
|
helpmode = (j_tmp && cjson_is_true (j_tmp));
|
||||||
@ -844,8 +857,7 @@ process_request (const char *request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
cJSON_Delete (json);
|
cJSON_Delete (json_orig);
|
||||||
json = NULL;
|
|
||||||
if (opt_interactive)
|
if (opt_interactive)
|
||||||
res = cJSON_Print (response);
|
res = cJSON_Print (response);
|
||||||
else
|
else
|
||||||
@ -930,7 +942,7 @@ process_meta_commands (const char *request)
|
|||||||
"\"\\nMeta commands:\\n"
|
"\"\\nMeta commands:\\n"
|
||||||
" ,help This help\\n"
|
" ,help This help\\n"
|
||||||
" ,quit Terminate process\""
|
" ,quit Terminate process\""
|
||||||
"}");
|
"}", 0);
|
||||||
else if (!strncmp (request, "quit", 4) && (spacep (request+4) || !request[4]))
|
else if (!strncmp (request, "quit", 4) && (spacep (request+4) || !request[4]))
|
||||||
exit (0);
|
exit (0);
|
||||||
else
|
else
|
||||||
@ -1029,7 +1041,7 @@ interactive_repl (void)
|
|||||||
}
|
}
|
||||||
else if (request)
|
else if (request)
|
||||||
{
|
{
|
||||||
response = process_request (request);
|
response = process_request (request, 0);
|
||||||
}
|
}
|
||||||
xfree (request);
|
xfree (request);
|
||||||
request = NULL;
|
request = NULL;
|
||||||
@ -1072,7 +1084,7 @@ interactive_repl (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Read and process asingle request. */
|
/* Read and process a single request. */
|
||||||
static void
|
static void
|
||||||
read_and_process_single_request (void)
|
read_and_process_single_request (void)
|
||||||
{
|
{
|
||||||
@ -1093,7 +1105,7 @@ read_and_process_single_request (void)
|
|||||||
if (request)
|
if (request)
|
||||||
{
|
{
|
||||||
xfree (response);
|
xfree (response);
|
||||||
response = process_request (request);
|
response = process_request (request, 0);
|
||||||
if (response)
|
if (response)
|
||||||
{
|
{
|
||||||
es_fputs (response, es_stdout);
|
es_fputs (response, es_stdout);
|
||||||
@ -1126,6 +1138,7 @@ native_messaging_repl (void)
|
|||||||
* binary mode. */
|
* binary mode. */
|
||||||
es_set_binary (es_stdin);
|
es_set_binary (es_stdin);
|
||||||
es_set_binary (es_stdout);
|
es_set_binary (es_stdout);
|
||||||
|
es_setbuf (es_stdin, NULL);
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
@ -1149,7 +1162,7 @@ native_messaging_repl (void)
|
|||||||
{
|
{
|
||||||
log_error ("error reading request: request too long (%zu MiB)\n",
|
log_error ("error reading request: request too long (%zu MiB)\n",
|
||||||
(size_t)nrequest / (1024*1024));
|
(size_t)nrequest / (1024*1024));
|
||||||
/* Fixme: Shall we read the request t the bit bucket and
|
/* Fixme: Shall we read the request to the bit bucket and
|
||||||
* return an error reponse or just return an error reponse
|
* return an error reponse or just return an error reponse
|
||||||
* and terminate? Needs some testing. */
|
* and terminate? Needs some testing. */
|
||||||
break;
|
break;
|
||||||
@ -1181,8 +1194,12 @@ native_messaging_repl (void)
|
|||||||
}
|
}
|
||||||
else /* Process request */
|
else /* Process request */
|
||||||
{
|
{
|
||||||
|
if (opt_debug)
|
||||||
|
log_debug ("request='%s'\n", request);
|
||||||
xfree (response);
|
xfree (response);
|
||||||
response = process_request (request);
|
response = process_request (request, 1);
|
||||||
|
if (opt_debug)
|
||||||
|
log_debug ("response='%s'\n", response);
|
||||||
}
|
}
|
||||||
nresponse = strlen (response);
|
nresponse = strlen (response);
|
||||||
|
|
||||||
@ -1263,12 +1280,18 @@ main (int argc, char *argv[])
|
|||||||
enum { CMD_DEFAULT = 0,
|
enum { CMD_DEFAULT = 0,
|
||||||
CMD_INTERACTIVE = 'i',
|
CMD_INTERACTIVE = 'i',
|
||||||
CMD_SINGLE = 's',
|
CMD_SINGLE = 's',
|
||||||
CMD_LIBVERSION = 501
|
CMD_LIBVERSION = 501,
|
||||||
} cmd = CMD_DEFAULT;
|
} cmd = CMD_DEFAULT;
|
||||||
|
enum {
|
||||||
|
OPT_DEBUG = 600
|
||||||
|
};
|
||||||
|
|
||||||
static gpgrt_opt_t opts[] = {
|
static gpgrt_opt_t opts[] = {
|
||||||
ARGPARSE_c (CMD_INTERACTIVE, "interactive", "Interactive REPL"),
|
ARGPARSE_c (CMD_INTERACTIVE, "interactive", "Interactive REPL"),
|
||||||
ARGPARSE_c (CMD_SINGLE, "single", "Single request mode"),
|
ARGPARSE_c (CMD_SINGLE, "single", "Single request mode"),
|
||||||
ARGPARSE_c (CMD_LIBVERSION, "lib-version", "Show library version"),
|
ARGPARSE_c (CMD_LIBVERSION, "lib-version", "Show library version"),
|
||||||
|
ARGPARSE_s_n(OPT_DEBUG, "debug", "Flyswatter"),
|
||||||
|
|
||||||
ARGPARSE_end()
|
ARGPARSE_end()
|
||||||
};
|
};
|
||||||
gpgrt_argparse_t pargs = { &argc, &argv};
|
gpgrt_argparse_t pargs = { &argc, &argv};
|
||||||
@ -1298,6 +1321,8 @@ main (int argc, char *argv[])
|
|||||||
cmd = pargs.r_opt;
|
cmd = pargs.r_opt;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OPT_DEBUG: opt_debug = 1; break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
pargs.err = ARGPARSE_PRINT_WARNING;
|
pargs.err = ARGPARSE_PRINT_WARNING;
|
||||||
break;
|
break;
|
||||||
@ -1305,6 +1330,29 @@ main (int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
gpgrt_argparse (NULL, &pargs, NULL);
|
gpgrt_argparse (NULL, &pargs, NULL);
|
||||||
|
|
||||||
|
if (!opt_debug)
|
||||||
|
{
|
||||||
|
const char *s = getenv ("GPGME_JSON_DEBUG");
|
||||||
|
if (s && atoi (s) > 0)
|
||||||
|
opt_debug = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt_debug)
|
||||||
|
{
|
||||||
|
const char *home = getenv ("HOME");
|
||||||
|
char *file = xstrconcat ("socket://",
|
||||||
|
home? home:"/tmp",
|
||||||
|
"/.gnupg/S.gpgme-json.log", NULL);
|
||||||
|
log_set_file (file);
|
||||||
|
xfree (file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt_debug)
|
||||||
|
{ int i;
|
||||||
|
for (i=0; argv[i]; i++)
|
||||||
|
log_debug ("argv[%d]='%s'\n", i, argv[i]);
|
||||||
|
}
|
||||||
|
|
||||||
switch (cmd)
|
switch (cmd)
|
||||||
{
|
{
|
||||||
case CMD_DEFAULT:
|
case CMD_DEFAULT:
|
||||||
@ -1327,6 +1375,9 @@ main (int argc, char *argv[])
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opt_debug)
|
||||||
|
log_debug ("ready");
|
||||||
|
|
||||||
#endif /* This is a modern libgp-error. */
|
#endif /* This is a modern libgp-error. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user