mirror of
git://git.gnupg.org/gnupg.git
synced 2025-02-01 16:33:02 +01: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:
parent
5137bf73cc
commit
7bfc86c938
12
doc/gpg.texi
12
doc/gpg.texi
@ -2219,12 +2219,14 @@ opposite meaning. The options are:
|
||||
@end table
|
||||
|
||||
@item --import-filter @code{@var{name}=@var{expr}}
|
||||
@itemx --export-filter @code{@var{name}=@var{expr}}
|
||||
@opindex import-filter
|
||||
This option defines an import filter which is implied to the imported
|
||||
keyblock right before it will be stored. @var{name} defines the type
|
||||
of filter to use, @var{expr} the expression to evaluate. The option
|
||||
can be used several times which then appends more expression to the
|
||||
same @var{name}.
|
||||
@opindex export-filter
|
||||
These options define an import/export filter which are applied to the
|
||||
imported/exported keyblock right before it will be stored/written.
|
||||
@var{name} defines the type of filter to use, @var{expr} the
|
||||
expression to evaluate. The option can be used several times which
|
||||
then appends more expression to the same @var{name}.
|
||||
|
||||
@noindent
|
||||
The available filter types are:
|
||||
|
126
g10/export.c
126
g10/export.c
@ -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;
|
||||
|
@ -302,6 +302,7 @@ enum cmd_and_opt_values
|
||||
oImportOptions,
|
||||
oImportFilter,
|
||||
oExportOptions,
|
||||
oExportFilter,
|
||||
oListOptions,
|
||||
oVerifyOptions,
|
||||
oTempDir,
|
||||
@ -575,6 +576,7 @@ static ARGPARSE_OPTS opts[] = {
|
||||
ARGPARSE_s_s (oImportOptions, "import-options", "@"),
|
||||
ARGPARSE_s_s (oImportFilter, "import-filter", "@"),
|
||||
ARGPARSE_s_s (oExportOptions, "export-options", "@"),
|
||||
ARGPARSE_s_s (oExportFilter, "export-filter", "@"),
|
||||
ARGPARSE_s_s (oListOptions, "list-options", "@"),
|
||||
ARGPARSE_s_s (oVerifyOptions, "verify-options", "@"),
|
||||
|
||||
@ -3049,6 +3051,11 @@ main (int argc, char **argv)
|
||||
log_error(_("invalid export options\n"));
|
||||
}
|
||||
break;
|
||||
case oExportFilter:
|
||||
rc = parse_and_set_export_filter (pargs.r.ret_str);
|
||||
if (rc)
|
||||
log_error (_("invalid filter option: %s\n"), gpg_strerror (rc));
|
||||
break;
|
||||
case oListOptions:
|
||||
if(!parse_list_options(pargs.r.ret_str))
|
||||
{
|
||||
|
@ -379,6 +379,7 @@ void export_release_stats (export_stats_t stats);
|
||||
void export_print_stats (export_stats_t stats);
|
||||
|
||||
int parse_export_options(char *str,unsigned int *options,int noisy);
|
||||
gpg_error_t parse_and_set_export_filter (const char *string);
|
||||
|
||||
int export_pubkeys (ctrl_t ctrl, strlist_t users, unsigned int options,
|
||||
export_stats_t stats);
|
||||
|
Loading…
x
Reference in New Issue
Block a user