aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2025-03-12 10:09:52 +0000
committerWerner Koch <[email protected]>2025-03-12 10:09:52 +0000
commitc12b7d047e75808dfc8918f42962b4c8d1dead91 (patch)
tree887db74e0d613a9f3152b561343c2db7923ec953
parentUpdate autogen.sh from upstream to version 2025-03-10 (diff)
downloadgnupg-c12b7d047e75808dfc8918f42962b4c8d1dead91.tar.gz
gnupg-c12b7d047e75808dfc8918f42962b4c8d1dead91.zip
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
-rw-r--r--common/recsel.c18
-rw-r--r--common/t-recsel.c20
-rw-r--r--doc/gpg.texi6
3 files changed, 38 insertions, 6 deletions
diff --git a/common/recsel.c b/common/recsel.c
index fa3debaaf..c2c98ed06 100644
--- a/common/recsel.c
+++ b/common/recsel.c
@@ -64,6 +64,7 @@ struct recsel_expr_s
unsigned int not:1; /* Negate operators. */
unsigned int disjun:1;/* Start of a disjunction. */
unsigned int xcase:1; /* String match is case sensitive. */
+ unsigned int lefta:1; /* String match is left anchored. */
const char *value; /* (Points into NAME.) */
long numvalue; /* strtol of VALUE. */
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:
*
* -- 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.
* -t Do not trim leading and trailing spaces from VALUE.
* 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 xcase = 0;
int notrim = 0;
+ int lefta = 0;
int disjun = 0;
char *next_lc = NULL;
@@ -206,6 +209,7 @@ recsel_parse_expr (recsel_expr_t *selector, const char *expression)
case '-': toend = 1; break;
case 'c': xcase = 1; break;
case 't': notrim = 1; break;
+ case '^': lefta = 1; break;
default:
log_error ("invalid flag '-%c' in expression\n", *expr);
recsel_release (se_head);
@@ -235,6 +239,7 @@ recsel_parse_expr (recsel_expr_t *selector, const char *expression)
se->not = 0;
se->disjun = disjun;
se->xcase = xcase;
+ se->lefta = lefta;
if (!se_head)
se_head = se;
@@ -463,9 +468,10 @@ recsel_dump (recsel_expr_t selector)
log_debug ("--- Begin selectors ---\n");
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->xcase? "-c":" ",
+ se->lefta? "-^":" ",
se->name,
se->op == SELECT_SAME? (se->not? "<>":"= "):
se->op == SELECT_SUB? (se->not? "!~":"=~"):
@@ -529,9 +535,15 @@ recsel_select (recsel_expr_t selector,
break;
case SELECT_SUB:
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
- result = !!memistr (value, valuelen, se->value);
+ result = (memistr (value, valuelen, se->value)
+ && (!se->lefta
+ || (selen <= valuelen
+ && !memicmp (value, se->value, selen))));
break;
case SELECT_NONEMPTY:
result = !!valuelen;
diff --git a/common/t-recsel.c b/common/t-recsel.c
index 2d5a95d25..ff68e54c3 100644
--- a/common/t-recsel.c
+++ b/common/t-recsel.c
@@ -225,9 +225,27 @@ run_test_2 (void)
if (!recsel_select (se, test_2_getval, NULL))
fail (0, 0);
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))
+ 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();
ADDEXPR ("keyid == 0x12345678");
diff --git a/doc/gpg.texi b/doc/gpg.texi
index 5f93e9f8c..cd979b2a5 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -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
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
-can store an optional @var{url} argument. That URL can appended to
-@var{string} after a comma.
+can store an optional @var{url} argument; such an URL can be appended to
+@var{string} delimited by a comma.
@item --import-options @var{parameters}
@opindex import-options
@@ -4389,6 +4389,8 @@ are:
@table @asis
@item --
@var{VALUE} spans to the end of the expression.
+ @item -^
+ The substring match is left anchored.
@item -c
The string match in this part is done case-sensitive.
@item -t