core: Prepare for new key listing data send by gpg.
authorWerner Koch <wk@gnupg.org>
Tue, 28 Mar 2017 09:40:44 +0000 (11:40 +0200)
committerWerner Koch <wk@gnupg.org>
Tue, 28 Mar 2017 09:41:30 +0000 (11:41 +0200)
* src/gpgme.h.in (gpgme_user_id_t): New fields 'origin' and
'last_update'.
(gpgme_key_t): New fields 'origin' and 'last_update'.
* src/conversion.c (_gpgme_parse_timestamp_ul): New.
* src/keylist.c (keylist_colon_handler): Parse fields 19 and 20.

* tests/run-keylist.c (main): Print new fields.

Signed-off-by: Werner Koch <wk@gnupg.org>
NEWS
doc/gpgme.texi
src/conversion.c
src/gpgme.h.in
src/keylist.c
src/util.h
tests/run-keylist.c

diff --git a/NEWS b/NEWS
index e119b9a..0005abe 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -10,7 +10,11 @@ Noteworthy changes in version 1.8.1 (unreleased)
  gpgme_op_createkey          CHANGED: Meaning of 'expire' parameter.
  gpgme_op_createsubkey       CHANGED: Meaning of 'expire' parameter.
  GPGME_CREATE_NOEXPIRE       NEW.
+ gpgme_key_t                 EXTENDED: New field 'origin'.
+ gpgme_key_t                 EXTENDED: New field 'last_update'.
  gpgme_subkey_t              EXTENDED: New field 'is_de_vs'.
+ gpgme_user_id_t             EXTENDED: New field 'origin'.
+ gpgme_user_id_t             EXTENDED: New field 'last_update'.
  gpgme_op_keylist_from_data_start NEW.
  gpgme_op_set_uid_flag_start      NEW.
  gpgme_op_set_uid_flag            NEW.
index d5969b7..62004ae 100644 (file)
@@ -3078,6 +3078,9 @@ be true even if the corresponding subkey flag may be false
 (offline/stub keys).  This is only set if a listing of secret keys has
 been requested or if @code{GPGME_KEYLIST_MODE_WITH_SECRET} is active.
 
+@item unsigned int origin : 5
+Reserved for the origin of this key.
+
 @item gpgme_protocol_t protocol
 This is the protocol supported by this key.
 
@@ -3111,6 +3114,9 @@ this is a copy of the fingerprint of the first subkey.  For an
 incomplete key (for example from a verification result) a subkey may
 be missing but this field may be set nevertheless.
 
+@item unsigned long last_update
+Reserved for the time of the last update of this key.
+
 @end table
 @end deftp
 
@@ -3255,6 +3261,13 @@ this user id.
 
 @item gpgme_key_sig_t signatures
 This is a linked list with the signatures on this user ID.
+
+@item unsigned int origin : 5
+Reserved for the origin of this user ID.
+
+@item unsigned long last_update
+Reserved for the time of the last update of this user ID.
+
 @end table
 @end deftp
 
index 6dfabe7..92dd214 100644 (file)
@@ -536,6 +536,25 @@ _gpgme_parse_timestamp (const char *timestamp, char **endp)
 }
 
 
+/* This function is similar to _gpgme_parse_timestamp but returns an
+ * unsigned long and 0 on error.  */
+unsigned long
+_gpgme_parse_timestamp_ul (const char *timestamp)
+{
+  time_t tim;
+  char *tail;
+
+  if (!*timestamp)
+    return 0; /* Shortcut empty strings.  */
+
+  tim = _gpgme_parse_timestamp (timestamp, &tail);
+  if (tim == -1 || timestamp == tail || (*tail && *tail != ' '))
+    tim = 0; /* No time given or invalid engine.  */
+
+  return (unsigned long)tim;
+}
+
+
 /* The GPG backend uses OpenPGP algorithm numbers which we need to map
    to our algorithm numbers.  This function MUST not change ERRNO. */
 int
index b6c1406..24b21e7 100644 (file)
@@ -662,7 +662,10 @@ struct _gpgme_user_id
   unsigned int invalid : 1;
 
   /* Internal to GPGME, do not use.  */
-  unsigned int _unused : 30;
+  unsigned int _unused : 25;
+
+  /* Origin of this user ID.  */
+  unsigned int origin : 5;
 
   /* The validity of the user ID.  */
   gpgme_validity_t validity;
@@ -693,6 +696,9 @@ struct _gpgme_user_id
 
   /* The malloced TOFU information or NULL.  */
   gpgme_tofu_info_t tofu;
+
+  /* Time of the last refresh of thsi user id.  0 if unknown.  */
+  unsigned long last_update;
 };
 typedef struct _gpgme_user_id *gpgme_user_id_t;
 
@@ -736,7 +742,10 @@ struct _gpgme_key
   unsigned int is_qualified : 1;
 
   /* Internal to GPGME, do not use.  */
-  unsigned int _unused : 22;
+  unsigned int _unused : 17;
+
+  /* Origin of this key.  */
+  unsigned int origin : 5;
 
   /* This is the protocol supported by this key.  */
   gpgme_protocol_t protocol;
@@ -776,6 +785,9 @@ struct _gpgme_key
    * this is a copy of the FPR of the first subkey.  We need it here
    * to allow for an incomplete key object.  */
   char *fpr;
+
+  /* Time of the last refresh of the entire key.  0 if unknown.  */
+  unsigned long last_update;
 };
 typedef struct _gpgme_key *gpgme_key_t;
 
index c88a7ca..e16ba4d 100644 (file)
@@ -552,7 +552,7 @@ keylist_colon_handler (void *priv, char *line)
       RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV, RT_SPK
     }
   rectype = RT_NONE;
-#define NR_FIELDS 18
+#define NR_FIELDS 20
   char *field[NR_FIELDS];
   int fields = 0;
   void *hook;
@@ -733,6 +733,12 @@ keylist_colon_handler (void *priv, char *line)
       if (fields >= 17 && *field[17])
         parse_pub_field18 (subkey, field[17]);
 
+      if (fields >= 20)
+        {
+          key->last_update = _gpgme_parse_timestamp_ul (field[18]);
+          key->origin = 0; /* Fixme: Not yet defined in gpg.  */
+        }
+
       break;
 
     case RT_SUB:
@@ -818,12 +824,15 @@ keylist_colon_handler (void *priv, char *line)
        {
          if (_gpgme_key_append_name (key, field[9], 1))
            return gpg_error (GPG_ERR_ENOMEM);  /* FIXME */
-         else
-           {
-             if (field[1])
-               set_userid_flags (key, field[1]);
-             opd->tmp_uid = key->_last_uid;
-           }
+
+          if (field[1])
+            set_userid_flags (key, field[1]);
+          opd->tmp_uid = key->_last_uid;
+          if (fields >= 20)
+            {
+              opd->tmp_uid->last_update = _gpgme_parse_timestamp_ul (field[18]);
+              opd->tmp_uid->origin = 0; /* Fixme: Not yet defined in gpg.  */
+            }
        }
       break;
 
index b27c583..7b7924c 100644 (file)
@@ -165,6 +165,9 @@ gpgme_off_t _gpgme_string_to_off (const char *string);
    point to the next non-parsed character in TIMESTRING. */
 time_t _gpgme_parse_timestamp (const char *timestamp, char **endp);
 
+/* Variant of _gpgme_parse_timestamp to return an unsigned long or 0
+ * on error or missing timestamp.  */
+unsigned long _gpgme_parse_timestamp_ul (const char *timestamp);
 
 gpgme_error_t _gpgme_map_gnupg_error (char *err);
 
index aab4bb6..dd310e5 100644 (file)
@@ -251,6 +251,7 @@ main (int argc, char **argv)
               key->is_qualified? " qualified":"",
               key->subkeys && key->subkeys->is_de_vs? " de-vs":"",
               key->subkeys && key->subkeys->is_cardkey? " cardkey":"");
+      printf ("upd     : %lu (%u)\n", key->last_update, key->origin);
 
       subkey = key->subkeys;
       if (subkey)
@@ -289,6 +290,7 @@ main (int argc, char **argv)
             printf ("    name: %s\n", uid->name);
           if (uid->comment)
             printf ("   cmmnt: %s\n", uid->comment);
+          printf ("     upd: %lu (%u)\n", uid->last_update, uid->origin);
           printf ("   valid: %s\n",
                   uid->validity == GPGME_VALIDITY_UNKNOWN? "unknown":
                   uid->validity == GPGME_VALIDITY_UNDEFINED? "undefined":