Imported Upstream version 1.12.0
[platform/upstream/gpgme.git] / src / op-support.c
index 2bcb3a3..9414e61 100644 (file)
@@ -14,7 +14,7 @@
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with this program; if not, see <http://www.gnu.org/licenses/>.
+   License along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #if HAVE_CONFIG_H
 #include "util.h"
 #include "debug.h"
 
+#if GPG_ERROR_VERSION_NUMBER < 0x011700  /* 1.23 */
+# define GPG_ERR_SUBKEYS_EXP_OR_REV 217
+#endif
+
+
 \f
 gpgme_error_t
 _gpgme_op_data_lookup (gpgme_ctx_t ctx, ctx_op_data_id_t type, void **hook,
@@ -89,6 +94,7 @@ _gpgme_op_reset (gpgme_ctx_t ctx, int type)
   _gpgme_release_result (ctx);
   LOCK (ctx->lock);
   ctx->canceled = 0;
+  ctx->redraw_suggested = 0;
   UNLOCK (ctx->lock);
 
   if (ctx->engine && no_reset)
@@ -135,6 +141,8 @@ _gpgme_op_reset (gpgme_ctx_t ctx, int type)
       if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
        err = 0;
 
+      _gpgme_engine_set_engine_flags (ctx->engine, ctx);
+
       if (!err)
         {
           err = _gpgme_engine_set_pinentry_mode (ctx->engine,
@@ -143,6 +151,12 @@ _gpgme_op_reset (gpgme_ctx_t ctx, int type)
             err = 0;
         }
 
+      if (!err && ctx->status_cb && ctx->full_status)
+        {
+          _gpgme_engine_set_status_cb (ctx->engine,
+                                       ctx->status_cb, ctx->status_cb_value);
+        }
+
       if (err)
         {
           _gpgme_engine_release (ctx->engine);
@@ -190,16 +204,21 @@ _gpgme_op_reset (gpgme_ctx_t ctx, int type)
 }
 
 \f
-/* Parse the INV_RECP or INV-SNDR status line in ARGS and return the
-   result in KEY.  */
+/* Parse the INV_RECP or INV_SNDR status line in ARGS and return the
+   result in KEY.  If KC_FPR (from the KEY_CONSIDERED status line) is
+   not NULL take the KC_FLAGS in account. */
 gpgme_error_t
-_gpgme_parse_inv_recp (char *args, gpgme_invalid_key_t *key)
+_gpgme_parse_inv_recp (char *args, int for_signing,
+                       const char *kc_fpr, unsigned int kc_flags,
+                       gpgme_invalid_key_t *key)
 {
   gpgme_invalid_key_t inv_key;
   char *tail;
   long int reason;
 
-  inv_key = malloc (sizeof (*inv_key));
+  (void)for_signing;
+
+  inv_key = calloc (1, sizeof (*inv_key));
   if (!inv_key)
     return gpg_error_from_syserror ();
   inv_key->next = NULL;
@@ -214,9 +233,11 @@ _gpgme_parse_inv_recp (char *args, gpgme_invalid_key_t *key)
 
   switch (reason)
     {
-    default:
     case 0:
-      inv_key->reason = gpg_error (GPG_ERR_GENERAL);
+      if (kc_fpr && (kc_flags & 2))
+        inv_key->reason = gpg_error (GPG_ERR_SUBKEYS_EXP_OR_REV);
+      else
+        inv_key->reason = gpg_error (GPG_ERR_GENERAL);
       break;
 
     case 1:
@@ -274,6 +295,10 @@ _gpgme_parse_inv_recp (char *args, gpgme_invalid_key_t *key)
     case 14:
       inv_key->reason = gpg_error (GPG_ERR_INV_USER_ID);
       break;
+
+    default:
+      inv_key->reason = gpg_error (GPG_ERR_GENERAL);
+      break;
     }
 
   while (*tail && *tail == ' ')
@@ -287,18 +312,53 @@ _gpgme_parse_inv_recp (char *args, gpgme_invalid_key_t *key)
          return gpg_error_from_syserror ();
        }
     }
-  else
-    inv_key->fpr = NULL;
 
   *key = inv_key;
   return 0;
 }
 
 
+\f
+/* Parse a KEY_CONSIDERED status line in ARGS and store the
+ * fingerprint and the flags at R_FPR and R_FLAGS.  The caller must
+ * free the value at R_FPR on success.  */
+gpgme_error_t
+_gpgme_parse_key_considered (const char *args,
+                             char **r_fpr, unsigned int *r_flags)
+{
+  char *pend;
+  size_t n;
+
+  *r_fpr = NULL;
+
+  pend = strchr (args, ' ');
+  if (!pend || pend == args)
+    return trace_gpg_error (GPG_ERR_INV_ENGINE);  /* Bogus status line.  */
+  n = pend - args;
+  *r_fpr = malloc (n + 1);
+  if (!*r_fpr)
+    return gpg_error_from_syserror ();
+  memcpy (*r_fpr, args, n);
+  (*r_fpr)[n] = 0;
+  args = pend + 1;
+
+  gpg_err_set_errno (0);
+  *r_flags = strtoul (args, &pend, 0);
+  if (errno || args == pend || (*pend && *pend != ' '))
+    {
+      free (*r_fpr);
+      *r_fpr = NULL;
+      return trace_gpg_error (GPG_ERR_INV_ENGINE);
+    }
+
+  return 0;
+}
+
+
 /* Parse the PLAINTEXT status line in ARGS and return the result in
    FILENAMEP.  */
 gpgme_error_t
-_gpgme_parse_plaintext (char *args, char **filenamep)
+_gpgme_parse_plaintext (char *args, char **filenamep, int *r_mime)
 {
   char *tail;
 
@@ -307,7 +367,9 @@ _gpgme_parse_plaintext (char *args, char **filenamep)
   if (*args == '\0')
     return 0;
 
-  /* First argument is file type.  */
+  /* First argument is file type (a one byte uppercase hex value).  */
+  if (args[0] == '6' && args[1] == 'D')
+    *r_mime = 1;
   while (*args != ' ' && *args != '\0')
     args++;
   while (*args == ' ')
@@ -337,3 +399,34 @@ _gpgme_parse_plaintext (char *args, char **filenamep)
     }
   return 0;
 }
+
+
+/* Parse a FAILURE status line and return the error code.  ARGS is
+ * modified to contain the location part.  Note that for now we ignore
+ * failure codes with a location of gpg-exit; they are too trouble
+ * some.  Instead we should eventually record that error in the
+ * context and provide a function to return a fuller error
+ * description; this could then also show the location of the error
+ * (e.g. "option- parser") to make it easier for the user to detect
+ * the actual error. */
+gpgme_error_t
+_gpgme_parse_failure (char *args)
+{
+  char *where, *which;
+
+  if (!strncmp (args, "gpg-exit", 8))
+    return 0;
+
+  where = strchr (args, ' ');
+  if (!where)
+    return trace_gpg_error (GPG_ERR_INV_ENGINE);
+
+  *where = '\0';
+  which = where + 1;
+
+  where = strchr (which, ' ');
+  if (where)
+    *where = '\0';
+
+  return atoi (which);
+}