1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-05-24 16:43:28 +02:00

common: Add a flag for left anchored substring match to recsel.

* common/recsel.c (struct recsel_expr_s): Add field lefta.
(recsel_parse_expr): Parse it.
(recsel_select): Implement selection.
--

This flags makes it for example easy to select keys last updated from
an ldap server:

  gpg --list-filter 'select=origin=ks && -^ url =~ ldap' \
       -k --with-key-origin
This commit is contained in:
Werner Koch 2025-03-12 11:09:52 +01:00
parent e5555a40e6
commit c12b7d047e
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
3 changed files with 38 additions and 6 deletions

View File

@ -64,6 +64,7 @@ struct recsel_expr_s
unsigned int not:1; /* Negate operators. */ unsigned int not:1; /* Negate operators. */
unsigned int disjun:1;/* Start of a disjunction. */ unsigned int disjun:1;/* Start of a disjunction. */
unsigned int xcase:1; /* String match is case sensitive. */ unsigned int xcase:1; /* String match is case sensitive. */
unsigned int lefta:1; /* String match is left anchored. */
const char *value; /* (Points into NAME.) */ const char *value; /* (Points into NAME.) */
long numvalue; /* strtol of VALUE. */ long numvalue; /* strtol of VALUE. */
char name[1]; /* Name of the property. */ char name[1]; /* Name of the property. */
@ -140,6 +141,7 @@ find_next_lc (char *string)
* Values for <flag> must be space separated and any of: * Values for <flag> must be space separated and any of:
* *
* -- VALUE spans to the end of the expression. * -- VALUE spans to the end of the expression.
* -^ The substring match is left anchored.
* -c The string match in this part is done case-sensitive. * -c The string match in this part is done case-sensitive.
* -t Do not trim leading and trailing spaces from VALUE. * -t Do not trim leading and trailing spaces from VALUE.
* Note that a space after <op> is here required. * Note that a space after <op> is here required.
@ -176,6 +178,7 @@ recsel_parse_expr (recsel_expr_t *selector, const char *expression)
int toend = 0; int toend = 0;
int xcase = 0; int xcase = 0;
int notrim = 0; int notrim = 0;
int lefta = 0;
int disjun = 0; int disjun = 0;
char *next_lc = NULL; char *next_lc = NULL;
@ -206,6 +209,7 @@ recsel_parse_expr (recsel_expr_t *selector, const char *expression)
case '-': toend = 1; break; case '-': toend = 1; break;
case 'c': xcase = 1; break; case 'c': xcase = 1; break;
case 't': notrim = 1; break; case 't': notrim = 1; break;
case '^': lefta = 1; break;
default: default:
log_error ("invalid flag '-%c' in expression\n", *expr); log_error ("invalid flag '-%c' in expression\n", *expr);
recsel_release (se_head); recsel_release (se_head);
@ -235,6 +239,7 @@ recsel_parse_expr (recsel_expr_t *selector, const char *expression)
se->not = 0; se->not = 0;
se->disjun = disjun; se->disjun = disjun;
se->xcase = xcase; se->xcase = xcase;
se->lefta = lefta;
if (!se_head) if (!se_head)
se_head = se; se_head = se;
@ -463,9 +468,10 @@ recsel_dump (recsel_expr_t selector)
log_debug ("--- Begin selectors ---\n"); log_debug ("--- Begin selectors ---\n");
for (se = selector; se; se = se->next) for (se = selector; se; se = se->next)
{ {
log_debug ("%s %s %s %s '%s'\n", log_debug ("%s %s %s %s %s '%s'\n",
se==selector? " ": (se->disjun? "||":"&&"), se==selector? " ": (se->disjun? "||":"&&"),
se->xcase? "-c":" ", se->xcase? "-c":" ",
se->lefta? "-^":" ",
se->name, se->name,
se->op == SELECT_SAME? (se->not? "<>":"= "): se->op == SELECT_SAME? (se->not? "<>":"= "):
se->op == SELECT_SUB? (se->not? "!~":"=~"): se->op == SELECT_SUB? (se->not? "!~":"=~"):
@ -529,9 +535,15 @@ recsel_select (recsel_expr_t selector,
break; break;
case SELECT_SUB: case SELECT_SUB:
if (se->xcase) if (se->xcase)
result = !!gnupg_memstr (value, valuelen, se->value); result = (gnupg_memstr (value, valuelen, se->value)
&& (!se->lefta
|| (selen <= valuelen
&& !memcmp (value, se->value, selen))));
else else
result = !!memistr (value, valuelen, se->value); result = (memistr (value, valuelen, se->value)
&& (!se->lefta
|| (selen <= valuelen
&& !memicmp (value, se->value, selen))));
break; break;
case SELECT_NONEMPTY: case SELECT_NONEMPTY:
result = !!valuelen; result = !!valuelen;

View File

@ -225,9 +225,27 @@ run_test_2 (void)
if (!recsel_select (se, test_2_getval, NULL)) if (!recsel_select (se, test_2_getval, NULL))
fail (0, 0); fail (0, 0);
FREEEXPR(); FREEEXPR();
ADDEXPR ("uid =~ @"); ADDEXPR ("uid !~ @");
if (recsel_select (se, test_2_getval, NULL))
fail (0, 0);
FREEEXPR();
ADDEXPR ("uid =~ foo@");
if (!recsel_select (se, test_2_getval, NULL)) if (!recsel_select (se, test_2_getval, NULL))
fail (0, 0); fail (0, 0);
FREEEXPR();
ADDEXPR ("uid =~ oo@");
if (!recsel_select (se, test_2_getval, NULL))
fail (0, 0);
FREEEXPR();
/* Again but with left anchored substring. */
ADDEXPR ("-^ uid =~ foo@");
if (!recsel_select (se, test_2_getval, NULL))
fail (0, 0);
FREEEXPR();
ADDEXPR ("-^ uid =~ oo@");
if (recsel_select (se, test_2_getval, NULL))
fail (0, 0);
FREEEXPR(); FREEEXPR();
ADDEXPR ("keyid == 0x12345678"); ADDEXPR ("keyid == 0x12345678");

View File

@ -2561,8 +2561,8 @@ gpg can track the origin of a key. Certain origins are implicitly
known (e.g., keyserver, web key directory) and set. For a standard known (e.g., keyserver, web key directory) and set. For a standard
import the origin of the keys imported can be set with this option. import the origin of the keys imported can be set with this option.
To list the possible values use "help" for @var{string}. Some origins To list the possible values use "help" for @var{string}. Some origins
can store an optional @var{url} argument. That URL can appended to can store an optional @var{url} argument; such an URL can be appended to
@var{string} after a comma. @var{string} delimited by a comma.
@item --import-options @var{parameters} @item --import-options @var{parameters}
@opindex import-options @opindex import-options
@ -4389,6 +4389,8 @@ are:
@table @asis @table @asis
@item -- @item --
@var{VALUE} spans to the end of the expression. @var{VALUE} spans to the end of the expression.
@item -^
The substring match is left anchored.
@item -c @item -c
The string match in this part is done case-sensitive. The string match in this part is done case-sensitive.
@item -t @item -t