json: New operation "identify" and convenience option --identify.

* src/gpgme-json.c (data_type_to_string): New.
(op_identify): New.
(process_request): Add to command list.
(cmd_identify): New.
(main): Add option --identify.
--
This commit is contained in:
Werner Koch 2023-01-31 09:47:19 +01:00
parent 577562dd4c
commit 359378c5b3
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
2 changed files with 129 additions and 2 deletions

4
NEWS
View File

@ -1,6 +1,8 @@
Noteworthy changes in version 1.19.0 (unreleased)
-------------------------------------------------
* New convenience option --identify for gpgme-json.
* New context flag "no-auto-check-trustdb". [T6261]
* Optionally, build QGpgME for Qt 6
@ -431,7 +433,7 @@ Noteworthy changes in version 1.13.0 (2019-03-26)
* Several fixes to the Common Lisp bindings.
* Fixed minor bugs in gpgme-json. [#4331,#4341,#4342,#4343
* Fixed minor bugs in gpgme-json. [#4331,#4341,#4342,#4343]
* Require trace level 8 to dump all I/O data.

View File

@ -3063,6 +3063,59 @@ leave:
}
static const char *
data_type_to_string (gpgme_data_type_t dt)
{
const char *s = "[?]";
switch (dt)
{
case GPGME_DATA_TYPE_INVALID : s = "invalid"; break;
case GPGME_DATA_TYPE_UNKNOWN : s = "unknown"; break;
case GPGME_DATA_TYPE_PGP_SIGNED : s = "PGP-signed"; break;
case GPGME_DATA_TYPE_PGP_SIGNATURE: s = "PGP-signature"; break;
case GPGME_DATA_TYPE_PGP_ENCRYPTED: s = "PGP-encrypted"; break;
case GPGME_DATA_TYPE_PGP_OTHER : s = "PGP"; break;
case GPGME_DATA_TYPE_PGP_KEY : s = "PGP-key"; break;
case GPGME_DATA_TYPE_CMS_SIGNED : s = "CMS-signed"; break;
case GPGME_DATA_TYPE_CMS_ENCRYPTED: s = "CMS-encrypted"; break;
case GPGME_DATA_TYPE_CMS_OTHER : s = "CMS"; break;
case GPGME_DATA_TYPE_X509_CERT : s = "X.509"; break;
case GPGME_DATA_TYPE_PKCS12 : s = "PKCS12"; break;
}
return s;
}
static const char hlp_identify[] =
"op: \"identify\"\n"
"data: The data to identify.\n"
"\n"
"Optional boolean flags (default is false):\n"
"base64: Input data is base64 encoded.\n"
"\n"
"Response:\n"
"result: A string describing the object.\n";
static gpg_error_t
op_identify (cjson_t request, cjson_t result)
{
gpg_error_t err;
gpgme_data_t input = NULL;
gpgme_data_type_t dt;
if ((err = get_string_data (request, result, "data", &input)))
goto leave;
dt = gpgme_data_identify (input, 0);
xjson_AddStringToObject (result, "result", data_type_to_string (dt));
leave:
gpgme_data_release (input);
return err;
}
static const char hlp_getmore[] =
"op: \"getmore\"\n"
@ -3163,6 +3216,7 @@ static const char hlp_help[] =
" keylist List keys.\n"
" sign Sign data.\n"
" verify Verify data.\n"
" identify Identify the type of the data\n"
" version Get engine information.\n"
" getmore Retrieve remaining data if chunksize was used.\n"
" help Help overview.\n"
@ -3218,6 +3272,7 @@ process_request (const char *request)
{ "createkey", op_createkey, hlp_createkey },
{ "keylist", op_keylist, hlp_keylist },
{ "import", op_import, hlp_import },
{ "identify", op_identify, hlp_identify },
{ "sign", op_sign, hlp_sign },
{ "verify", op_verify, hlp_verify },
{ "version", op_version, hlp_version },
@ -3787,6 +3842,64 @@ native_messaging_repl (void)
}
/* Run the --identify command. */
static gpg_error_t
cmd_identify (const char *fname)
{
gpg_error_t err;
estream_t fp;
gpgme_data_t data;
gpgme_data_type_t dt;
if (fname)
{
fp = es_fopen (fname, "rb");
if (!fp)
{
err = gpg_error_from_syserror ();
log_error ("can't open '%s': %s\n", fname, gpg_strerror (err));
return err;
}
err = gpgme_data_new_from_estream (&data, fp);
}
else
{
char *buffer;
int n;
fp = NULL;
es_set_binary (es_stdin);
/* Urgs: gpgme_data_identify does a seek and that fails for stdin. */
buffer = xmalloc (2048+1);
n = es_fread (buffer, 1, 2048, es_stdin);
if (n < 0 || es_ferror (es_stdin))
{
err = gpg_error_from_syserror ();
log_error ("error reading '%s': %s\n", "[stdin]", gpg_strerror (err));
xfree (buffer);
return err;
}
buffer[n] = 0;
err = gpgme_data_new_from_mem (&data, buffer, n, 1);
xfree (buffer);
}
if (err)
{
log_error ("error creating data object: %s\n", gpg_strerror (err));
return err;
}
dt = gpgme_data_identify (data, 0);
if (dt == GPGME_DATA_TYPE_INVALID)
log_error ("error identifying data\n");
printf ("%s\n", data_type_to_string (dt));
gpgme_data_release (data);
es_fclose (fp);
return 0;
}
static const char *
my_strusage( int level )
@ -3822,6 +3935,7 @@ main (int argc, char *argv[])
CMD_INTERACTIVE = 'i',
CMD_SINGLE = 's',
CMD_LIBVERSION = 501,
CMD_IDENTIFY
} cmd = CMD_DEFAULT;
enum {
OPT_DEBUG = 600
@ -3830,13 +3944,13 @@ main (int argc, char *argv[])
static gpgrt_opt_t opts[] = {
ARGPARSE_c (CMD_INTERACTIVE, "interactive", "Interactive REPL"),
ARGPARSE_c (CMD_SINGLE, "single", "Single request mode"),
ARGPARSE_c (CMD_IDENTIFY, "identify", "Identify the input"),
ARGPARSE_c (CMD_LIBVERSION, "lib-version", "Show library version"),
ARGPARSE_s_n(OPT_DEBUG, "debug", "Flyswatter"),
ARGPARSE_end()
};
gpgrt_argparse_t pargs = { &argc, &argv};
int log_file_set = 0;
gpgrt_set_strusage (my_strusage);
@ -3860,6 +3974,7 @@ main (int argc, char *argv[])
opt_interactive = 1;
/*FALLTHROUGH*/
case CMD_SINGLE:
case CMD_IDENTIFY:
case CMD_LIBVERSION:
cmd = pargs.r_opt;
break;
@ -3922,6 +4037,16 @@ main (int argc, char *argv[])
interactive_repl ();
break;
case CMD_IDENTIFY:
if (argc > 1)
{
log_error ("usage: %s --identify [filename|-]\n",
gpgrt_strusage (11));
exit (1);
}
cmd_identify (argc && strcmp (*argv, "-")? *argv : NULL);
break;
case CMD_LIBVERSION:
printf ("Version from header: %s (0x%06x)\n",
GPGME_VERSION, GPGME_VERSION_NUMBER);