1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

gpg: New option --export-filter

* g10/gpg.c (oExportFilter): New.
(opts): Add --export-filter.
(main): Handle option.
* g10/export.c: Include recsel.h, init.h, and mbox-util.h.
(export_keep_uid): New global var.
(cleanup_export_globals): New.
(parse_and_set_export_filter): New.
(filter_getval): New.
(apply_keep_uid_filter): New.
(do_export_stream): Apply filter if set.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2016-07-01 16:50:12 +02:00
parent 5137bf73cc
commit 7bfc86c938
No known key found for this signature in database
GPG key ID: E3FDFF218E45B72B
4 changed files with 141 additions and 5 deletions

View file

@ -35,6 +35,9 @@
#include "i18n.h"
#include "membuf.h"
#include "host2net.h"
#include "recsel.h"
#include "mbox-util.h"
#include "init.h"
#include "trustdb.h"
#include "call-agent.h"
@ -56,6 +59,16 @@ struct export_stats_s
};
/* A global variable to store the selector created from
* --export-filter keep-uid=EXPR.
*
* FIXME: We should put this into the CTRL object but that requires a
* lot more changes right now.
*/
static recsel_expr_t export_keep_uid;
/* Local prototypes. */
static int do_export (ctrl_t ctrl, strlist_t users, int secret,
unsigned int options, export_stats_t stats);
@ -65,6 +78,12 @@ static int do_export_stream (ctrl_t ctrl, iobuf_t out,
export_stats_t stats, int *any);
static void
cleanup_export_globals (void)
{
recsel_release (export_keep_uid);
export_keep_uid = NULL;
}
/* Option parser for export options. See parse_options fro
@ -100,6 +119,38 @@ parse_export_options(char *str,unsigned int *options,int noisy)
}
/* Parse and set an export filter from string. STRING has the format
* "NAME=EXPR" with NAME being the name of the filter. Spaces before
* and after NAME are not allowed. If this function is called several
* times all expressions for the same NAME are concatenated.
* Supported filter names are:
*
* - keep-uid :: If the expression evaluates to true for a certain
* user ID packet, that packet and all it dependencies
* will be exported. The expression may use these
* variables:
*
* - uid :: The entire user ID.
* - mbox :: The mail box part of the user ID.
* - primary :: Evaluate to true for the primary user ID.
*/
gpg_error_t
parse_and_set_export_filter (const char *string)
{
gpg_error_t err;
/* Auto register the cleanup function. */
register_mem_cleanup_func (cleanup_export_globals);
if (!strncmp (string, "keep-uid=", 9))
err = recsel_parse_expr (&export_keep_uid, string+9);
else
err = gpg_error (GPG_ERR_INV_NAME);
return err;
}
/* Create a new export stats object initialized to zero. On error
returns NULL and sets ERRNO. */
export_stats_t
@ -1147,6 +1198,74 @@ receive_seckey_from_agent (ctrl_t ctrl, gcry_cipher_hd_t cipherhd,
}
/* Helper for apply_keep_uid_filter. */
static const char *
filter_getval (void *cookie, const char *propname)
{
kbnode_t node = cookie;
const char *result;
if (node->pkt->pkttype == PKT_USER_ID)
{
if (!strcmp (propname, "uid"))
result = node->pkt->pkt.user_id->name;
else if (!strcmp (propname, "mbox"))
{
if (!node->pkt->pkt.user_id->mbox)
{
node->pkt->pkt.user_id->mbox
= mailbox_from_userid (node->pkt->pkt.user_id->name);
}
return node->pkt->pkt.user_id->mbox;
}
else if (!strcmp (propname, "primary"))
result = node->pkt->pkt.user_id->is_primary? "1":"0";
else
result = NULL;
}
else
result = NULL;
return result;
}
/*
* Apply the keep-uid filter to the keyblock. The deleted nodes are
* marked and thus the caller should call commit_kbnode afterwards.
* KEYBLOCK must not have any blocks marked as deleted.
*/
static void
apply_keep_uid_filter (kbnode_t keyblock, recsel_expr_t selector)
{
kbnode_t node;
for (node = keyblock->next; node; node = node->next )
{
if (node->pkt->pkttype == PKT_USER_ID)
{
if (!recsel_select (selector, filter_getval, node))
{
log_debug ("keep-uid: deleting '%s'\n",
node->pkt->pkt.user_id->name);
/* The UID packet and all following packets up to the
* next UID or a subkey. */
delete_kbnode (node);
for (; node->next
&& node->next->pkt->pkttype != PKT_USER_ID
&& node->next->pkt->pkttype != PKT_PUBLIC_SUBKEY
&& node->next->pkt->pkttype != PKT_SECRET_SUBKEY ;
node = node->next)
delete_kbnode (node->next);
}
else
log_debug ("keep-uid: keeping '%s'\n",
node->pkt->pkt.user_id->name);
}
}
}
/* Export the keys identified by the list of strings in USERS to the
stream OUT. If Secret is false public keys will be exported. With
secret true secret keys will be exported; in this case 1 means the
@ -1326,6 +1445,13 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
if ((options & EXPORT_CLEAN))
clean_key (keyblock, opt.verbose, (options&EXPORT_MINIMAL), NULL, NULL);
if (export_keep_uid)
{
commit_kbnode (&keyblock);
apply_keep_uid_filter (keyblock, export_keep_uid);
commit_kbnode (&keyblock);
}
/* And write it. */
xfree (cache_nonce);
cache_nonce = NULL;