Updated.
[gnupg.git] / g10 / keyedit.c
index bf5ab77..56e30e5 100644 (file)
@@ -1,6 +1,6 @@
 /* keyedit.c - keyedit stuff
 /* keyedit.c - keyedit stuff
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- *               2005 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+ *               2006 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
  *
  * This file is part of GnuPG.
  *
@@ -16,7 +16,8 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
  */
 
 #include <config.h>
  */
 
 #include <config.h>
 #include "keyserver-internal.h"
 
 static void show_prefs( PKT_user_id *uid, PKT_signature *selfsig, int verbose);
 #include "keyserver-internal.h"
 
 static void show_prefs( PKT_user_id *uid, PKT_signature *selfsig, int verbose);
+static void show_names(KBNODE keyblock,PKT_public_key *pk,
+                      unsigned int flag,int with_prefs);
 static void show_key_with_all_names( KBNODE keyblock, int only_marked,
            int with_revoker, int with_fpr, int with_subkeys, int with_prefs );
 static void show_key_and_fingerprint( KBNODE keyblock );
 static void show_key_with_all_names( KBNODE keyblock, int only_marked,
            int with_revoker, int with_fpr, int with_subkeys, int with_prefs );
 static void show_key_and_fingerprint( KBNODE keyblock );
-static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock, int photo );
+static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock,
+                       int photo, const char *photo_name );
 static void menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock );
 static void menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock );
-static int  menu_delsig( KBNODE pub_keyblock );
+static int menu_delsig( KBNODE pub_keyblock );
+static int menu_clean(KBNODE keyblock,int self_only);
 static void menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock );
 static int menu_addrevoker( KBNODE pub_keyblock,
                            KBNODE sec_keyblock, int sensitive );
 static int menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock );
 static void menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock );
 static int menu_addrevoker( KBNODE pub_keyblock,
                            KBNODE sec_keyblock, int sensitive );
 static int menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock );
+static int menu_backsign(KBNODE pub_keyblock,KBNODE sec_keyblock);
 static int menu_set_primary_uid( KBNODE pub_keyblock, KBNODE sec_keyblock );
 static int menu_set_preferences( KBNODE pub_keyblock, KBNODE sec_keyblock );
 static int menu_set_keyserver_url (const char *url,
                                   KBNODE pub_keyblock, KBNODE sec_keyblock );
 static int menu_set_primary_uid( KBNODE pub_keyblock, KBNODE sec_keyblock );
 static int menu_set_preferences( KBNODE pub_keyblock, KBNODE sec_keyblock );
 static int menu_set_keyserver_url (const char *url,
                                   KBNODE pub_keyblock, KBNODE sec_keyblock );
+static int menu_set_notation(const char *string,
+                            KBNODE pub_keyblock,KBNODE sec_keyblock);
 static int menu_select_uid( KBNODE keyblock, int idx );
 static int menu_select_uid( KBNODE keyblock, int idx );
+static int menu_select_uid_namehash( KBNODE keyblock, const char *namehash );
 static int menu_select_key( KBNODE keyblock, int idx );
 static int count_uids( KBNODE keyblock );
 static int count_uids_with_flag( KBNODE keyblock, unsigned flag );
 static int menu_select_key( KBNODE keyblock, int idx );
 static int count_uids( KBNODE keyblock );
 static int count_uids_with_flag( KBNODE keyblock, unsigned flag );
@@ -263,7 +272,7 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node,
            char *p = get_user_id( sig->keyid, &n );
            tty_print_utf8_string2(p, n, opt.screen_columns-keystrlen()-26-
                               ((opt.list_options&LIST_SHOW_SIG_EXPIRE)?11:0));
            char *p = get_user_id( sig->keyid, &n );
            tty_print_utf8_string2(p, n, opt.screen_columns-keystrlen()-26-
                               ((opt.list_options&LIST_SHOW_SIG_EXPIRE)?11:0));
-           m_free(p);
+           xfree(p);
          }
        tty_printf("\n");
 
          }
        tty_printf("\n");
 
@@ -421,7 +430,7 @@ trustsig_prompt(byte *trust_value,byte *trust_depth,char **regexp)
        *trust_value=60;
       else if(p[0]=='2' && !p[1])
        *trust_value=120;
        *trust_value=60;
       else if(p[0]=='2' && !p[1])
        *trust_value=120;
-      m_free(p);
+      xfree(p);
     }
 
   tty_printf("\n");
     }
 
   tty_printf("\n");
@@ -438,7 +447,7 @@ trustsig_prompt(byte *trust_value,byte *trust_depth,char **regexp)
       trim_spaces(p);
       cpr_kill_prompt();
       *trust_depth=atoi(p);
       trim_spaces(p);
       cpr_kill_prompt();
       *trust_depth=atoi(p);
-      m_free(p);
+      xfree(p);
     }
 
   tty_printf("\n");
     }
 
   tty_printf("\n");
@@ -457,7 +466,7 @@ trustsig_prompt(byte *trust_value,byte *trust_depth,char **regexp)
       char *q=p;
       int regexplen=100,ind;
 
       char *q=p;
       int regexplen=100,ind;
 
-      *regexp=m_alloc(regexplen);
+      *regexp=xmalloc(regexplen);
 
       /* Now mangle the domain the user entered into a regexp.  To do
         this, \-escape everything that isn't alphanumeric, and attach
 
       /* Now mangle the domain the user entered into a regexp.  To do
         this, \-escape everything that isn't alphanumeric, and attach
@@ -477,7 +486,7 @@ trustsig_prompt(byte *trust_value,byte *trust_depth,char **regexp)
          if((regexplen-ind)<3)
            {
              regexplen+=100;
          if((regexplen-ind)<3)
            {
              regexplen+=100;
-             *regexp=m_realloc(*regexp,regexplen);
+             *regexp=xrealloc(*regexp,regexplen);
            }
 
          q++;
            }
 
          q++;
@@ -487,7 +496,7 @@ trustsig_prompt(byte *trust_value,byte *trust_depth,char **regexp)
       strcat(*regexp,">$");
     }
 
       strcat(*regexp,">$");
     }
 
-  m_free(p);
+  xfree(p);
   tty_printf("\n");
 }
 
   tty_printf("\n");
 }
 
@@ -498,7 +507,7 @@ trustsig_prompt(byte *trust_value,byte *trust_depth,char **regexp)
  */
 static int
 sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
  */
 static int
 sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
-          int local, int nonrevocable, int trust )
+          int local, int nonrevocable, int trust, int interactive )
 {
     int rc = 0;
     SK_LIST sk_list = NULL;
 {
     int rc = 0;
     SK_LIST sk_list = NULL;
@@ -506,7 +515,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
     PKT_secret_key *sk = NULL;
     KBNODE node, uidnode;
     PKT_public_key *primary_pk=NULL;
     PKT_secret_key *sk = NULL;
     KBNODE node, uidnode;
     PKT_public_key *primary_pk=NULL;
-    int select_all = !count_selected_uids(keyblock);
+    int select_all = !count_selected_uids(keyblock) || interactive;
     int all_v3=1;
 
     /* Are there any non-v3 sigs on this key already? */
     int all_v3=1;
 
     /* Are there any non-v3 sigs on this key already? */
@@ -525,8 +534,8 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
      * be one which is capable of signing keys.  I can't see a reason
      * why to sign keys using a subkey.  Implementation of USAGE_CERT
      * is just a hack in getkey.c and does not mean that a subkey
      * be one which is capable of signing keys.  I can't see a reason
      * why to sign keys using a subkey.  Implementation of USAGE_CERT
      * is just a hack in getkey.c and does not mean that a subkey
-     * marked as certification capable will be used */
-    rc=build_sk_list( locusr, &sk_list, 0, PUBKEY_USAGE_SIG|PUBKEY_USAGE_CERT);
+     * marked as certification capable will be used. */
+    rc=build_sk_list( locusr, &sk_list, 0, PUBKEY_USAGE_CERT);
     if( rc )
        goto leave;
 
     if( rc )
        goto leave;
 
@@ -539,7 +548,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
        byte trust_depth=0,trust_value=0;
 
        if(local || nonrevocable || trust ||
        byte trust_depth=0,trust_value=0;
 
        if(local || nonrevocable || trust ||
-          opt.cert_policy_url || opt.cert_notation_data)
+          opt.cert_policy_url || opt.cert_notations)
          force_v4=1;
 
        /* we have to use a copy of the sk, because make_keysig_packet
          force_v4=1;
 
        /* we have to use a copy of the sk, because make_keysig_packet
@@ -575,10 +584,12 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
                    force_v4=0;
                  }
            }
                    force_v4=0;
                  }
            }
-           else if( node->pkt->pkttype == PKT_USER_ID ) {
+           else if( node->pkt->pkttype == PKT_USER_ID )
+             {
                uidnode = (node->flag & NODFLG_MARK_A)? node : NULL;
                if(uidnode)
                  {
                uidnode = (node->flag & NODFLG_MARK_A)? node : NULL;
                if(uidnode)
                  {
+                   int yesreally=0;
                    char *user=utf8_to_native(uidnode->pkt->pkt.user_id->name,
                                              uidnode->pkt->pkt.user_id->len,
                                              0);
                    char *user=utf8_to_native(uidnode->pkt->pkt.user_id->name,
                                              uidnode->pkt->pkt.user_id->len,
                                              0);
@@ -601,6 +612,8 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
                                uidnode->flag &= ~NODFLG_MARK_A;
                                uidnode=NULL;
                              }
                                uidnode->flag &= ~NODFLG_MARK_A;
                                uidnode=NULL;
                              }
+                           else if(interactive)
+                             yesreally=1;
                          }
                        else
                          {
                          }
                        else
                          {
@@ -627,6 +640,8 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
                                uidnode->flag &= ~NODFLG_MARK_A;
                                uidnode=NULL;
                              }
                                uidnode->flag &= ~NODFLG_MARK_A;
                                uidnode=NULL;
                              }
+                           else if(interactive)
+                             yesreally=1;
                          }
                        else
                          {
                          }
                        else
                          {
@@ -652,6 +667,8 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
                                uidnode->flag &= ~NODFLG_MARK_A;
                                uidnode=NULL;
                              }
                                uidnode->flag &= ~NODFLG_MARK_A;
                                uidnode=NULL;
                              }
+                           else if(interactive)
+                             yesreally=1;
                          }
                        else
                          {
                          }
                        else
                          {
@@ -661,9 +678,20 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
                          }
                      }
 
                          }
                      }
 
-                   m_free(user);
+                   if(uidnode && interactive && !yesreally)
+                     {
+                       tty_printf(_("User ID \"%s\" is signable.  "),user);
+                       if(!cpr_get_answer_is_yes("sign_uid.sign_okay",
+                                                 _("Sign it? (y/N) ")))
+                         {
+                           uidnode->flag &= ~NODFLG_MARK_A;
+                           uidnode=NULL;
+                         }
+                     }
+
+                   xfree(user);
                  }
                  }
-           }
+             }
            else if( uidnode && node->pkt->pkttype == PKT_SIGNATURE
                && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
                if( sk_keyid[0] == node->pkt->pkt.signature->keyid[0]
            else if( uidnode && node->pkt->pkttype == PKT_SIGNATURE
                && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
                if( sk_keyid[0] == node->pkt->pkt.signature->keyid[0]
@@ -691,7 +719,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
                            {
                              force_v4=1;
                              node->flag|=NODFLG_DELSIG;
                            {
                              force_v4=1;
                              node->flag|=NODFLG_DELSIG;
-                             m_free(user);
+                             xfree(user);
                              continue;
                            }
                      }
                              continue;
                            }
                      }
@@ -715,7 +743,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
                                in place. */
 
                            node->flag|=NODFLG_DELSIG;
                                in place. */
 
                            node->flag|=NODFLG_DELSIG;
-                           m_free(user);
+                           xfree(user);
                            continue;
                          }
                      }
                            continue;
                          }
                      }
@@ -740,7 +768,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
                                in place. */
 
                            node->flag|=NODFLG_DELSIG;
                                in place. */
 
                            node->flag|=NODFLG_DELSIG;
-                           m_free(user);
+                           xfree(user);
                            continue;
                          }
                      }
                            continue;
                          }
                      }
@@ -762,7 +790,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
                      {
                        /* Don't delete the old sig here since this is
                           an --expert thing. */
                      {
                        /* Don't delete the old sig here since this is
                           an --expert thing. */
-                       m_free(user);
+                       xfree(user);
                        continue;
                      }
 
                        continue;
                      }
 
@@ -771,7 +799,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
                     write_status_text (STATUS_ALREADY_SIGNED, buf);
                    uidnode->flag &= ~NODFLG_MARK_A; /* remove mark */
 
                     write_status_text (STATUS_ALREADY_SIGNED, buf);
                    uidnode->flag &= ~NODFLG_MARK_A; /* remove mark */
 
-                   m_free(user);
+                   xfree(user);
                }
            }
        }
                }
            }
        }
@@ -812,35 +840,42 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
              }
            else
              {
              }
            else
              {
-               char *answer;
-
                tty_printf(_("This key is due to expire on %s.\n"),
                           expirestr_from_pk(primary_pk));
 
                tty_printf(_("This key is due to expire on %s.\n"),
                           expirestr_from_pk(primary_pk));
 
-               answer=cpr_get("sign_uid.expire",
-                              _("Do you want your signature to "
-                                "expire at the same time? (Y/n) "));
-               if(answer_is_yes_no_default(answer,1))
+               if(opt.ask_cert_expire)
                  {
                  {
-                   /* This fixes the signature timestamp we're going
-                      to make as now.  This is so the expiration date
-                      is exactly correct, and not a few seconds off
-                      (due to the time it takes to answer the
-                      questions, enter the passphrase, etc). */
-                   timestamp=now;
-                   duration=primary_pk->expiredate-now;
-                   force_v4=1;
-                 }
+                   char *answer=cpr_get("sign_uid.expire",
+                                        _("Do you want your signature to "
+                                          "expire at the same time? (Y/n) "));
+                   if(answer_is_yes_no_default(answer,1))
+                     {
+                       /* This fixes the signature timestamp we're
+                          going to make as now.  This is so the
+                          expiration date is exactly correct, and not
+                          a few seconds off (due to the time it takes
+                          to answer the questions, enter the
+                          passphrase, etc). */
+                       timestamp=now;
+                       duration=primary_pk->expiredate-now;
+                       force_v4=1;
+                     }
 
 
-               cpr_kill_prompt();
-               m_free(answer);
+                   cpr_kill_prompt();
+                   xfree(answer);
+                 }
              }
          }
 
        /* Only ask for duration if we haven't already set it to match
            the expiration of the pk */
              }
          }
 
        /* Only ask for duration if we haven't already set it to match
            the expiration of the pk */
-       if(opt.ask_cert_expire && !duration && !selfsig)
-         duration=ask_expire_interval(1);
+       if(!duration && !selfsig)
+         {
+           if(opt.ask_cert_expire)
+             duration=ask_expire_interval(1,opt.def_cert_expire);
+           else
+             duration=parse_expire_string(opt.def_cert_expire);
+         }
 
        if(duration)
          force_v4=1;
 
        if(duration)
          force_v4=1;
@@ -910,7 +945,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
                    else
                      tty_printf(_("Invalid selection.\n"));
 
                    else
                      tty_printf(_("Invalid selection.\n"));
 
-                   m_free(answer);
+                   xfree(answer);
                  }
              }
 
                  }
              }
 
@@ -921,7 +956,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
        p=get_user_id_native(sk_keyid);
        tty_printf(_("Are you sure that you want to sign this key with your\n"
                     "key \"%s\" (%s)\n"),p,keystr_from_sk(sk));
        p=get_user_id_native(sk_keyid);
        tty_printf(_("Are you sure that you want to sign this key with your\n"
                     "key \"%s\" (%s)\n"),p,keystr_from_sk(sk));
-       m_free(p);
+       xfree(p);
 
        if(selfsig)
          {
 
        if(selfsig)
          {
@@ -1036,7 +1071,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
                *ret_modified = 1; /* we changed the keyblock */
                update_trust = 1;
 
                *ret_modified = 1; /* we changed the keyblock */
                update_trust = 1;
 
-               pkt = m_alloc_clear( sizeof *pkt );
+               pkt = xmalloc_clear( sizeof *pkt );
                pkt->pkttype = PKT_SIGNATURE;
                pkt->pkt.signature = sig;
                insert_kbnode( node, new_kbnode(pkt), PKT_SIGNATURE );
                pkt->pkttype = PKT_SIGNATURE;
                pkt->pkt.signature = sig;
                insert_kbnode( node, new_kbnode(pkt), PKT_SIGNATURE );
@@ -1144,7 +1179,7 @@ change_passphrase( KBNODE keyblock )
        tty_printf(_("Can't edit this key: %s\n"), g10_errstr(rc));
     else {
        DEK *dek = NULL;
        tty_printf(_("Can't edit this key: %s\n"), g10_errstr(rc));
     else {
        DEK *dek = NULL;
-       STRING2KEY *s2k = m_alloc_secure( sizeof *s2k );
+       STRING2KEY *s2k = xmalloc_secure( sizeof *s2k );
         const char *errtext = NULL;
 
        tty_printf(_("Enter the new passphrase for this secret key.\n\n") );
         const char *errtext = NULL;
 
        tty_printf(_("Enter the new passphrase for this secret key.\n\n") );
@@ -1197,12 +1232,12 @@ change_passphrase( KBNODE keyblock )
                break;
            }
        }
                break;
            }
        }
-       m_free(s2k);
-       m_free(dek);
+       xfree(s2k);
+       xfree(dek);
     }
 
   leave:
     }
 
   leave:
-    m_free( passphrase );
+    xfree( passphrase );
     set_next_passphrase( NULL );
     return changed && !rc;
 }
     set_next_passphrase( NULL );
     return changed && !rc;
 }
@@ -1305,9 +1340,10 @@ enum cmdids
     cmdREVSIG, cmdREVKEY, cmdREVUID, cmdDELSIG, cmdPRIMARY, cmdDEBUG,
     cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY,
     cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF,
     cmdREVSIG, cmdREVKEY, cmdREVUID, cmdDELSIG, cmdPRIMARY, cmdDEBUG,
     cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY,
     cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF,
-    cmdEXPIRE, cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF,
-    cmdPREFKS, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST,
-    cmdADDCARDKEY, cmdKEYTOCARD, cmdBKUPTOCARD, cmdNOP
+    cmdEXPIRE, cmdBACKSIGN, cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF,
+    cmdSETPREF, cmdPREFKS, cmdNOTATION, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST,
+    cmdCHKTRUST, cmdADDCARDKEY, cmdKEYTOCARD, cmdBKUPTOCARD, cmdCLEAN,
+    cmdMINIMIZE, cmdNOP
   };
 
 static struct
   };
 
 static struct
@@ -1330,6 +1366,8 @@ static struct
     { "key"     , cmdSELKEY    , 0, N_("select subkey N") },
     { "check"   , cmdCHECK     , 0, N_("check signatures") },
     { "c"       , cmdCHECK     , 0, NULL },
     { "key"     , cmdSELKEY    , 0, N_("select subkey N") },
     { "check"   , cmdCHECK     , 0, N_("check signatures") },
     { "c"       , cmdCHECK     , 0, NULL },
+    { "cross-certify", cmdBACKSIGN  , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL },
+    { "backsign", cmdBACKSIGN  , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL },
     { "sign"    , cmdSIGN      , KEYEDIT_NOT_SK|KEYEDIT_TAIL_MATCH,
       N_("sign selected user IDs [* see below for related commands]") },
     { "s"       , cmdSIGN      , KEYEDIT_NOT_SK, NULL },
     { "sign"    , cmdSIGN      , KEYEDIT_NOT_SK|KEYEDIT_TAIL_MATCH,
       N_("sign selected user IDs [* see below for related commands]") },
     { "s"       , cmdSIGN      , KEYEDIT_NOT_SK, NULL },
@@ -1387,7 +1425,9 @@ static struct
     { "updpref" , cmdSETPREF   , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL },
 
     { "keyserver",cmdPREFKS    , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
     { "updpref" , cmdSETPREF   , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL },
 
     { "keyserver",cmdPREFKS    , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
-      N_("set preferred keyserver URL for the selected user IDs")},
+      N_("set the preferred keyserver URL for the selected user IDs")},
+    { "notation", cmdNOTATION  , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
+      N_("set a notation for the selected user IDs")},
     { "passwd"  , cmdPASSWD    , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
       N_("change the passphrase") },
     /* Alias */
     { "passwd"  , cmdPASSWD    , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
       N_("change the passphrase") },
     /* Alias */
@@ -1406,10 +1446,13 @@ static struct
     { "enable"  , cmdENABLEKEY , KEYEDIT_NOT_SK, N_("enable key") },
     { "disable" , cmdDISABLEKEY, KEYEDIT_NOT_SK, N_("disable key") },
     { "showphoto",cmdSHOWPHOTO , 0, N_("show selected photo IDs") },
     { "enable"  , cmdENABLEKEY , KEYEDIT_NOT_SK, N_("enable key") },
     { "disable" , cmdDISABLEKEY, KEYEDIT_NOT_SK, N_("disable key") },
     { "showphoto",cmdSHOWPHOTO , 0, N_("show selected photo IDs") },
+    { "clean",    cmdCLEAN     , KEYEDIT_NOT_SK,
+      N_("compact unusable user IDs and remove unusable signatures from key")},
+    { "minimize", cmdMINIMIZE  , KEYEDIT_NOT_SK,
+      N_("compact unusable user IDs and remove all signatures from key") },
     { NULL, cmdNONE, 0, NULL }
   };
 
     { NULL, cmdNONE, 0, NULL }
   };
 
-
 #ifdef HAVE_LIBREADLINE
 
 /* These two functions are used by readline for command completion. */
 #ifdef HAVE_LIBREADLINE
 
 /* These two functions are used by readline for command completion. */
@@ -1554,6 +1597,7 @@ keyedit_menu( const char *username, STRLIST locusr,
        PKT_public_key *pk=keyblock->pkt->pkt.public_key;
 
        tty_printf("\n");
        PKT_public_key *pk=keyblock->pkt->pkt.public_key;
 
        tty_printf("\n");
+
        if( redisplay && !quiet )
          {
            show_key_with_all_names( cur_keyblock, 0, 1, 0, 1, 0 );
        if( redisplay && !quiet )
          {
            show_key_with_all_names( cur_keyblock, 0, 1, 0, 1, 0 );
@@ -1561,14 +1605,14 @@ keyedit_menu( const char *username, STRLIST locusr,
            redisplay = 0;
          }
        do {
            redisplay = 0;
          }
        do {
-           m_free(answer);
+           xfree(answer);
            if( have_commands ) {
                if( commands ) {
            if( have_commands ) {
                if( commands ) {
-                   answer = m_strdup( commands->d );
+                   answer = xstrdup( commands->d );
                    commands = commands->next;
                }
                else if( opt.batch ) {
                    commands = commands->next;
                }
                else if( opt.batch ) {
-                   answer = m_strdup("quit");
+                   answer = xstrdup("quit");
                }
                else
                    have_commands = 0;
                }
                else
                    have_commands = 0;
@@ -1665,8 +1709,10 @@ keyedit_menu( const char *username, STRLIST locusr,
            break;
 
          case cmdSELUID:
            break;
 
          case cmdSELUID:
-           if( menu_select_uid( cur_keyblock, arg_number ) )
-               redisplay = 1;
+           if(strlen(arg_string)==NAMEHASH_LEN*2)
+             redisplay=menu_select_uid_namehash(cur_keyblock,arg_string);
+           else
+             redisplay=menu_select_uid(cur_keyblock,arg_number);
            break;
 
          case cmdSELKEY:
            break;
 
          case cmdSELKEY:
@@ -1683,7 +1729,7 @@ keyedit_menu( const char *username, STRLIST locusr,
 
          case cmdSIGN: /* sign (only the public key) */
            {
 
          case cmdSIGN: /* sign (only the public key) */
            {
-             int localsig=0,nonrevokesig=0,trustsig=0;
+             int localsig=0,nonrevokesig=0,trustsig=0,interactive=0;
 
              if( pk->is_revoked )
                {
 
              if( pk->is_revoked )
                {
@@ -1704,18 +1750,21 @@ keyedit_menu( const char *username, STRLIST locusr,
                    }
                }
 
                    }
                }
 
-             if( count_uids(keyblock) > 1 && !count_selected_uids(keyblock)
-                 && !have_commands )
-               {
-                 if( !cpr_get_answer_is_yes("keyedit.sign_all.okay",
-                                            _("Really sign all user IDs?"
-                                              " (y/N) ")))
-                   {
+             if(count_uids(keyblock) > 1 && !count_selected_uids(keyblock)
+                && !cpr_get_answer_is_yes("keyedit.sign_all.okay",
+                                          _("Really sign all user IDs?"
+                                            " (y/N) ")))
+                {
+                  if(opt.interactive)
+                   interactive=1;
+                 else
+                    {
                      tty_printf(_("Hint: Select the user IDs to sign\n"));
                      tty_printf(_("Hint: Select the user IDs to sign\n"));
-                     break;
-                   }
-               }
+                      have_commands = 0;
+                      break;
+                    }
 
 
+                }
              /* What sort of signing are we doing? */
              if(!parse_sign_type(answer,&localsig,&nonrevokesig,&trustsig))
                {
              /* What sort of signing are we doing? */
              if(!parse_sign_type(answer,&localsig,&nonrevokesig,&trustsig))
                {
@@ -1724,7 +1773,7 @@ keyedit_menu( const char *username, STRLIST locusr,
                }
 
              sign_uids(keyblock, locusr, &modified,
                }
 
              sign_uids(keyblock, locusr, &modified,
-                       localsig, nonrevokesig, trustsig);
+                       localsig, nonrevokesig, trustsig, interactive);
            }
            break;
 
            }
            break;
 
@@ -1750,7 +1799,7 @@ keyedit_menu( const char *username, STRLIST locusr,
            /* fall through */
 
          case cmdADDUID:
            /* fall through */
 
          case cmdADDUID:
-           if( menu_adduid( keyblock, sec_keyblock, photo ) )
+           if( menu_adduid( keyblock, sec_keyblock, photo, arg_string ) )
              {
                update_trust = 1;
                redisplay = 1;
              {
                update_trust = 1;
                redisplay = 1;
@@ -1935,7 +1984,7 @@ keyedit_menu( const char *username, STRLIST locusr,
            {
              int sensitive=0;
 
            {
              int sensitive=0;
 
-             if(arg_string && ascii_strcasecmp(arg_string,"sensitive")==0)
+             if(ascii_strcasecmp(arg_string,"sensitive")==0)
                sensitive=1;
              if( menu_addrevoker( keyblock, sec_keyblock, sensitive ) ) {
                redisplay = 1;
                sensitive=1;
              if( menu_addrevoker( keyblock, sec_keyblock, sensitive ) ) {
                redisplay = 1;
@@ -2010,6 +2059,15 @@ keyedit_menu( const char *username, STRLIST locusr,
              }
            break;
 
              }
            break;
 
+         case cmdBACKSIGN:
+           if(menu_backsign(keyblock,sec_keyblock))
+             {
+               sec_modified = 1;
+               modified = 1;
+               redisplay = 1;
+             }
+           break;
+
          case cmdPRIMARY:
            if( menu_set_primary_uid ( keyblock, sec_keyblock ) ) {
                merge_keys_and_selfsig( keyblock );
          case cmdPRIMARY:
            if( menu_set_primary_uid ( keyblock, sec_keyblock ) ) {
                merge_keys_and_selfsig( keyblock );
@@ -2044,11 +2102,21 @@ keyedit_menu( const char *username, STRLIST locusr,
            break;
 
          case cmdPREF:
            break;
 
          case cmdPREF:
-           show_key_with_all_names( keyblock, 0, 0, 0, 0, 1 );
+           {
+             int count=count_selected_uids(keyblock);
+             assert(keyblock->pkt->pkttype==PKT_PUBLIC_KEY);
+             show_names(keyblock,keyblock->pkt->pkt.public_key,
+                        count?NODFLG_SELUID:0,1);
+           }
            break;
 
          case cmdSHOWPREF:
            break;
 
          case cmdSHOWPREF:
-           show_key_with_all_names( keyblock, 0, 0, 0, 0, 2 );
+           {
+             int count=count_selected_uids(keyblock);
+             assert(keyblock->pkt->pkttype==PKT_PUBLIC_KEY);
+             show_names(keyblock,keyblock->pkt->pkt.public_key,
+                        count?NODFLG_SELUID:0,2);
+           }
            break;
 
           case cmdSETPREF:
            break;
 
           case cmdSETPREF:
@@ -2088,6 +2156,16 @@ keyedit_menu( const char *username, STRLIST locusr,
              }
            break;
 
              }
            break;
 
+         case cmdNOTATION:
+           if( menu_set_notation ( *arg_string?arg_string:NULL,
+                                   keyblock, sec_keyblock ) )
+             {
+               merge_keys_and_selfsig( keyblock );
+               modified = 1;
+               redisplay = 1;
+             }
+           break;
+
          case cmdNOP:
            break;
 
          case cmdNOP:
            break;
 
@@ -2106,9 +2184,17 @@ keyedit_menu( const char *username, STRLIST locusr,
            }
            break;
 
            }
            break;
 
-         case cmdSHOWPHOTO:
-           menu_showphoto(keyblock);
-           break;
+         case cmdSHOWPHOTO:
+           menu_showphoto(keyblock);
+           break;
+
+         case cmdCLEAN:
+           redisplay=modified=menu_clean(keyblock,0);
+           break;
+
+         case cmdMINIMIZE:
+           redisplay=modified=menu_clean(keyblock,1);
+           break;
 
          case cmdQUIT:
            if( have_commands )
 
          case cmdQUIT:
            if( have_commands )
@@ -2164,11 +2250,39 @@ keyedit_menu( const char *username, STRLIST locusr,
     release_kbnode( keyblock );
     release_kbnode( sec_keyblock );
     keydb_release (kdbhd);
     release_kbnode( keyblock );
     release_kbnode( sec_keyblock );
     keydb_release (kdbhd);
-    m_free(answer);
+    xfree(answer);
 }
 
 }
 
+static void
+tty_print_notations(int indent,PKT_signature *sig)
+{
+  int first=1;
+  struct notation *notation,*nd;
+
+  if(indent<0)
+    {
+      first=0;
+      indent=-indent;
+    }
+
+  notation=sig_to_notation(sig);
+
+  for(nd=notation;nd;nd=nd->next)
+    {
+      if(!first)
+       tty_printf("%*s",indent,"");
+      else
+       first=0;
+
+      tty_print_utf8_string(nd->name,strlen(nd->name));
+      tty_printf("=");
+      tty_print_utf8_string(nd->value,strlen(nd->value));
+      tty_printf("\n");
+    }
+
+  free_notation(notation);
+}
 
 
-\f
 /****************
  * show preferences of a public keyblock.
  */
 /****************
  * show preferences of a public keyblock.
  */
@@ -2265,17 +2379,17 @@ show_prefs (PKT_user_id *uid, PKT_signature *selfsig, int verbose)
            }
            tty_printf ("%s",compress_algo_to_string(COMPRESS_ALGO_NONE));
         }
            }
            tty_printf ("%s",compress_algo_to_string(COMPRESS_ALGO_NONE));
         }
-       if(uid->mdc_feature || !uid->ks_modify)
+       if(uid->flags.mdc || !uid->flags.ks_modify)
          {
            tty_printf ("\n     ");
            tty_printf (_("Features: "));
            any=0;
          {
            tty_printf ("\n     ");
            tty_printf (_("Features: "));
            any=0;
-           if(uid->mdc_feature)
+           if(uid->flags.mdc)
              {
                tty_printf ("MDC");
                any=1;
              }
              {
                tty_printf ("MDC");
                any=1;
              }
-           if(!uid->ks_modify)
+           if(!uid->flags.ks_modify)
              {
                if(any)
                  tty_printf (", ");
              {
                if(any)
                  tty_printf (", ");
@@ -2298,6 +2412,13 @@ show_prefs (PKT_user_id *uid, PKT_signature *selfsig, int verbose)
                tty_print_utf8_string(pref_ks,pref_ks_len);
                tty_printf("\n");
              }
                tty_print_utf8_string(pref_ks,pref_ks_len);
                tty_printf("\n");
              }
+
+           if(selfsig->flags.notation)
+             {
+               tty_printf ("     ");
+               tty_printf(_("Notations: "));
+               tty_print_notations(5+strlen(_("Notations: ")),selfsig);
+             }
          }
     }
     else {
          }
     }
     else {
@@ -2308,15 +2429,14 @@ show_prefs (PKT_user_id *uid, PKT_signature *selfsig, int verbose)
                                  prefs[i].type == PREFTYPE_ZIP ? 'Z':'?',
                                  prefs[i].value);
         }
                                  prefs[i].type == PREFTYPE_ZIP ? 'Z':'?',
                                  prefs[i].value);
         }
-        if (uid->mdc_feature)
+        if (uid->flags.mdc)
             tty_printf (" [mdc]");
             tty_printf (" [mdc]");
-        if (!uid->ks_modify)
+        if (!uid->flags.ks_modify)
             tty_printf (" [no-ks-modify]");
         tty_printf("\n");
     }
 }
 
             tty_printf (" [no-ks-modify]");
         tty_printf("\n");
     }
 }
 
-
 /* This is the version of show_key_with_all_names used when
    opt.with_colons is used.  It prints all available data in a easy to
    parse format and does not translate utf8 */
 /* This is the version of show_key_with_all_names used when
    opt.with_colons is used.  It prints all available data in a easy to
    parse format and does not translate utf8 */
@@ -2373,24 +2493,7 @@ show_key_with_all_names_colon (KBNODE keyblock)
           putchar('\n');
           
           print_fingerprint (pk, NULL, 0);
           putchar('\n');
           
           print_fingerprint (pk, NULL, 0);
-
-          /* print the revoker record */
-          if( !pk->revkey && pk->numrevkeys )
-            BUG();
-          else
-            {
-              for (i=0; i < pk->numrevkeys; i++)
-                {
-                  byte *p;
-
-                  printf ("rvk:::%d::::::", pk->revkey[i].algid);
-                  p = pk->revkey[i].fpr;
-                  for (j=0; j < 20; j++, p++ )
-                    printf ("%02X", *p);
-                  printf (":%02x%s:\n", pk->revkey[i].class,
-                          (pk->revkey[i].class&0x40)?"s":"");
-                }
-            }
+         print_revokers(pk);
         }
     }
   
         }
     }
   
@@ -2450,9 +2553,9 @@ show_key_with_all_names_colon (KBNODE keyblock)
                             prefs[j].type == PREFTYPE_ZIP ? 'Z':'?',
                             prefs[j].value);
                   } 
                             prefs[j].type == PREFTYPE_ZIP ? 'Z':'?',
                             prefs[j].value);
                   } 
-                if (uid->mdc_feature)
+                if (uid->flags.mdc)
                   printf (",mdc");
                   printf (",mdc");
-                if (!uid->ks_modify)
+                if (!uid->flags.ks_modify)
                   printf (",no-ks-modify");
               } 
             putchar (':');
                   printf (",no-ks-modify");
               } 
             putchar (':');
@@ -2474,6 +2577,63 @@ show_key_with_all_names_colon (KBNODE keyblock)
       }
 }
 
       }
 }
 
+static void
+show_names(KBNODE keyblock,PKT_public_key *pk,unsigned int flag,int with_prefs)
+{
+  KBNODE node;
+  int i=0;
+
+  for( node = keyblock; node; node = node->next )
+    {
+      if( node->pkt->pkttype == PKT_USER_ID
+         && !is_deleted_kbnode(node))
+       {
+         PKT_user_id *uid = node->pkt->pkt.user_id;
+         ++i;
+         if(!flag || (flag && (node->flag & flag)))
+           {
+             if(!(flag&NODFLG_MARK_A) && pk)
+               tty_printf("%s ",uid_trust_string_fixed(pk,uid));
+
+             if( flag & NODFLG_MARK_A )
+               tty_printf("     ");
+             else if( node->flag & NODFLG_SELUID )
+               tty_printf("(%d)* ", i);
+             else if( uid->is_primary )
+               tty_printf("(%d). ", i);
+             else
+               tty_printf("(%d)  ", i);
+             tty_print_utf8_string( uid->name, uid->len );
+             tty_printf("\n");
+             if(with_prefs && pk)
+               {
+                 if(pk->version>3 || uid->selfsigversion>3)
+                   {
+                     PKT_signature *selfsig=NULL;
+                     KBNODE signode;
+
+                     for(signode=node->next;
+                         signode && signode->pkt->pkttype==PKT_SIGNATURE;
+                         signode=signode->next)
+                       {
+                         if(signode->pkt->pkt.signature->
+                            flags.chosen_selfsig)
+                           {
+                             selfsig=signode->pkt->pkt.signature;
+                             break;
+                           }
+                       }
+
+                     show_prefs (uid, selfsig, with_prefs == 2);
+                   }
+                 else
+                   tty_printf(_("There are no preferences on a"
+                                " PGP 2.x-style user ID.\n"));
+               }
+           }
+       }
+    }
+}
 
 /****************
  * Display the key a the user ids, if only_marked is true, do only
 
 /****************
  * Display the key a the user ids, if only_marked is true, do only
@@ -2498,7 +2658,8 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker,
     /* the keys */
     for( node = keyblock; node; node = node->next ) {
        if( node->pkt->pkttype == PKT_PUBLIC_KEY
     /* the keys */
     for( node = keyblock; node; node = node->next ) {
        if( node->pkt->pkttype == PKT_PUBLIC_KEY
-           || (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) {
+           || (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+               && !is_deleted_kbnode(node)) ) {
            PKT_public_key *pk = node->pkt->pkt.public_key;
            const char *otrust="err",*trust="err";
 
            PKT_public_key *pk = node->pkt->pkt.public_key;
            const char *otrust="err",*trust="err";
 
@@ -2527,7 +2688,7 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker,
                const char *algo=pubkey_algo_to_string(pk->revoked.algo);
                tty_printf(_("This key was revoked on %s by %s key %s\n"),
                           revokestr_from_pk(pk),algo?algo:"?",user);
                const char *algo=pubkey_algo_to_string(pk->revoked.algo);
                tty_printf(_("This key was revoked on %s by %s key %s\n"),
                           revokestr_from_pk(pk),algo?algo:"?",user);
-               m_free(user);
+               xfree(user);
              }
 
            if(with_revoker)
              }
 
            if(with_revoker)
@@ -2556,7 +2717,7 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker,
                        }
 
                      tty_printf ("\n");
                        }
 
                      tty_printf ("\n");
-                     m_free(user);
+                     xfree(user);
                    }
              }
 
                    }
              }
 
@@ -2651,59 +2812,8 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker,
               }
          }
     }
               }
          }
     }
-    
-    /* the user ids */
 
 
-    i = 0;
-    for( node = keyblock; node; node = node->next )
-      {
-       if( node->pkt->pkttype == PKT_USER_ID )
-         {
-           PKT_user_id *uid = node->pkt->pkt.user_id;
-           ++i;
-           if( !only_marked || (only_marked && (node->flag & NODFLG_MARK_A)))
-             {
-               if(!only_marked && primary)
-                 tty_printf("%s ",uid_trust_string_fixed(primary,uid));
-
-               if( only_marked )
-                 tty_printf("     ");
-               else if( node->flag & NODFLG_SELUID )
-                 tty_printf("(%d)* ", i);
-               else if( uid->is_primary )
-                 tty_printf("(%d). ", i);
-               else
-                 tty_printf("(%d)  ", i);
-               tty_print_utf8_string( uid->name, uid->len );
-               tty_printf("\n");
-               if( with_prefs )
-                 {
-                   if(pk_version>3 || uid->selfsigversion>3)
-                     {
-                       PKT_signature *selfsig=NULL;
-                       KBNODE signode;
-
-                       for(signode=node->next;
-                           signode && signode->pkt->pkttype==PKT_SIGNATURE;
-                           signode=signode->next)
-                         {
-                           if(signode->pkt->pkt.signature->
-                              flags.chosen_selfsig)
-                             {
-                               selfsig=signode->pkt->pkt.signature;
-                               break;
-                             }
-                         }
-
-                       show_prefs (uid, selfsig, with_prefs == 2);
-                     }
-                   else
-                     tty_printf(_("There are no preferences on a"
-                                  " PGP 2.x-style user ID.\n"));
-                 }
-             }
-         }
-      }
+    show_names(keyblock,primary,only_marked?NODFLG_MARK_A:0,with_prefs);
 
     if (do_warn)
         tty_printf (_("Please note that the shown key validity"
 
     if (do_warn)
         tty_printf (_("Please note that the shown key validity"
@@ -2712,7 +2822,7 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker,
 }
 
 
 }
 
 
-/* Display basic key information.  This fucntion is suitable to show
+/* Display basic key information.  This function is suitable to show
    information on the key without any dependencies on the trustdb or
    any other internal GnuPG stuff.  KEYBLOCK may either be a public or
    a secret key.*/
    information on the key without any dependencies on the trustdb or
    any other internal GnuPG stuff.  KEYBLOCK may either be a public or
    a secret key.*/
@@ -2848,7 +2958,8 @@ no_primary_warning(KBNODE keyblock)
  * Return true if there is a new user id
  */
 static int
  * Return true if there is a new user id
  */
 static int
-menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo)
+menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock,
+            int photo, const char *photo_name)
 {
     PKT_user_id *uid;
     PKT_public_key *pk=NULL;
 {
     PKT_user_id *uid;
     PKT_public_key *pk=NULL;
@@ -2914,7 +3025,7 @@ menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo)
            }
        }
 
            }
        }
 
-      uid = generate_photo_id(pk);
+      uid = generate_photo_id(pk,photo_name);
     } else
       uid = generate_user_id();
     if( !uid )
     } else
       uid = generate_user_id();
     if( !uid )
@@ -2930,7 +3041,7 @@ menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo)
     }
 
     /* insert/append to secret keyblock */
     }
 
     /* insert/append to secret keyblock */
-    pkt = m_alloc_clear( sizeof *pkt );
+    pkt = xmalloc_clear( sizeof *pkt );
     pkt->pkttype = PKT_USER_ID;
     pkt->pkt.user_id = scopy_user_id(uid);
     node = new_kbnode(pkt);
     pkt->pkttype = PKT_USER_ID;
     pkt->pkt.user_id = scopy_user_id(uid);
     node = new_kbnode(pkt);
@@ -2938,7 +3049,7 @@ menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo)
        insert_kbnode( sec_where, node, 0 );
     else
        add_kbnode( sec_keyblock, node );
        insert_kbnode( sec_where, node, 0 );
     else
        add_kbnode( sec_keyblock, node );
-    pkt = m_alloc_clear( sizeof *pkt );
+    pkt = xmalloc_clear( sizeof *pkt );
     pkt->pkttype = PKT_SIGNATURE;
     pkt->pkt.signature = copy_signature(NULL, sig);
     if( sec_where )
     pkt->pkttype = PKT_SIGNATURE;
     pkt->pkt.signature = copy_signature(NULL, sig);
     if( sec_where )
@@ -2946,7 +3057,7 @@ menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo)
     else
        add_kbnode( sec_keyblock, new_kbnode(pkt) );
     /* insert/append to public keyblock */
     else
        add_kbnode( sec_keyblock, new_kbnode(pkt) );
     /* insert/append to public keyblock */
-    pkt = m_alloc_clear( sizeof *pkt );
+    pkt = xmalloc_clear( sizeof *pkt );
     pkt->pkttype = PKT_USER_ID;
     pkt->pkt.user_id = uid;
     node = new_kbnode(pkt);
     pkt->pkttype = PKT_USER_ID;
     pkt->pkt.user_id = uid;
     node = new_kbnode(pkt);
@@ -2954,7 +3065,7 @@ menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo)
        insert_kbnode( pub_where, node, 0 );
     else
        add_kbnode( pub_keyblock, node );
        insert_kbnode( pub_where, node, 0 );
     else
        add_kbnode( pub_keyblock, node );
-    pkt = m_alloc_clear( sizeof *pkt );
+    pkt = xmalloc_clear( sizeof *pkt );
     pkt->pkttype = PKT_SIGNATURE;
     pkt->pkt.signature = copy_signature(NULL, sig);
     if( pub_where )
     pkt->pkttype = PKT_SIGNATURE;
     pkt->pkt.signature = copy_signature(NULL, sig);
     if( pub_where )
@@ -3091,6 +3202,58 @@ menu_delsig( KBNODE pub_keyblock )
     return changed;
 }
 
     return changed;
 }
 
+static int
+menu_clean(KBNODE keyblock,int self_only)
+{
+  KBNODE uidnode;
+  int modified=0,select_all=!count_selected_uids(keyblock);
+
+  for(uidnode=keyblock->next;
+      uidnode && uidnode->pkt->pkttype!=PKT_PUBLIC_SUBKEY;
+      uidnode=uidnode->next)
+    {
+      if(uidnode->pkt->pkttype==PKT_USER_ID
+        && (uidnode->flag&NODFLG_SELUID || select_all))
+       {
+         int uids=0,sigs=0;
+         char *user=utf8_to_native(uidnode->pkt->pkt.user_id->name,
+                                   uidnode->pkt->pkt.user_id->len,
+                                   0);
+
+         clean_one_uid(keyblock,uidnode,opt.verbose,self_only,&uids,&sigs);
+         if(uids)
+           {
+             const char *reason;
+
+             if(uidnode->pkt->pkt.user_id->is_revoked)
+               reason=_("revoked");
+             else if(uidnode->pkt->pkt.user_id->is_expired)
+               reason=_("expired");
+             else
+               reason=_("invalid");
+
+             tty_printf("User ID \"%s\" compacted: %s\n",user,reason);
+
+             modified=1;
+           }
+         else if(sigs)
+           {
+             tty_printf(sigs==1?
+                        "User ID \"%s\": %d signature removed\n":
+                        "User ID \"%s\": %d signatures removed\n",
+                        user,sigs);
+
+             modified=1;
+           }
+         else
+           tty_printf(_("User ID \"%s\": already clean\n"),user);
+
+         xfree(user);
+       }
+    }
+
+  return modified;
+}
 
 /****************
  * Remove some of the secondary keys
 
 /****************
  * Remove some of the secondary keys
@@ -3201,7 +3364,7 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive )
       if(revoker_pk)
        free_public_key(revoker_pk);
 
       if(revoker_pk)
        free_public_key(revoker_pk);
 
-      revoker_pk=m_alloc_clear(sizeof(*revoker_pk));
+      revoker_pk=xmalloc_clear(sizeof(*revoker_pk));
 
       tty_printf("\n");
 
 
       tty_printf("\n");
 
@@ -3209,22 +3372,24 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive )
                          _("Enter the user ID of the designated revoker: "));
       if(answer[0]=='\0' || answer[0]=='\004')
        {
                          _("Enter the user ID of the designated revoker: "));
       if(answer[0]=='\0' || answer[0]=='\004')
        {
-         m_free(answer);
+         xfree(answer);
          goto fail;
        }
 
          goto fail;
        }
 
-      /* Note that I'm requesting SIG here and not CERT.  We're making
-        a certification, but it is okay to be a subkey. */
-      revoker_pk->req_usage=PUBKEY_USAGE_SIG;
+      /* Note that I'm requesting CERT here, which usually implies
+        primary keys only, but some casual testing shows that PGP and
+        GnuPG both can handle a designated revokation from a
+        subkey. */
+      revoker_pk->req_usage=PUBKEY_USAGE_CERT;
       rc=get_pubkey_byname(revoker_pk,answer,NULL,NULL,1);
       if(rc)
        {
          log_error (_("key \"%s\" not found: %s\n"),answer,g10_errstr(rc));
       rc=get_pubkey_byname(revoker_pk,answer,NULL,NULL,1);
       if(rc)
        {
          log_error (_("key \"%s\" not found: %s\n"),answer,g10_errstr(rc));
-         m_free(answer);
+         xfree(answer);
          continue;
        }
 
          continue;
        }
 
-      m_free(answer);
+      xfree(answer);
 
       fingerprint_from_pk(revoker_pk,revkey.fpr,&fprlen);
       if(fprlen!=20)
 
       fingerprint_from_pk(revoker_pk,revkey.fpr,&fprlen);
       if(fprlen!=20)
@@ -3314,13 +3479,13 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive )
   sk=NULL;
 
   /* insert into secret keyblock */
   sk=NULL;
 
   /* insert into secret keyblock */
-  pkt = m_alloc_clear( sizeof *pkt );
+  pkt = xmalloc_clear( sizeof *pkt );
   pkt->pkttype = PKT_SIGNATURE;
   pkt->pkt.signature = copy_signature(NULL, sig);
   insert_kbnode( sec_keyblock, new_kbnode(pkt), PKT_SIGNATURE );
 
   /* insert into public keyblock */
   pkt->pkttype = PKT_SIGNATURE;
   pkt->pkt.signature = copy_signature(NULL, sig);
   insert_kbnode( sec_keyblock, new_kbnode(pkt), PKT_SIGNATURE );
 
   /* insert into public keyblock */
-  pkt = m_alloc_clear( sizeof *pkt );
+  pkt = xmalloc_clear( sizeof *pkt );
   pkt->pkttype = PKT_SIGNATURE;
   pkt->pkt.signature = sig;
   insert_kbnode( pub_keyblock, new_kbnode(pkt), PKT_SIGNATURE );
   pkt->pkttype = PKT_SIGNATURE;
   pkt->pkt.signature = sig;
   insert_kbnode( pub_keyblock, new_kbnode(pkt), PKT_SIGNATURE );
@@ -3442,18 +3607,18 @@ menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock )
                    return 0;
                }
                /* replace the packet */
                    return 0;
                }
                /* replace the packet */
-               newpkt = m_alloc_clear( sizeof *newpkt );
+               newpkt = xmalloc_clear( sizeof *newpkt );
                newpkt->pkttype = PKT_SIGNATURE;
                newpkt->pkt.signature = newsig;
                free_packet( node->pkt );
                newpkt->pkttype = PKT_SIGNATURE;
                newpkt->pkt.signature = newsig;
                free_packet( node->pkt );
-               m_free( node->pkt );
+               xfree( node->pkt );
                node->pkt = newpkt;
                if( sn ) {
                node->pkt = newpkt;
                if( sn ) {
-                   newpkt = m_alloc_clear( sizeof *newpkt );
+                   newpkt = xmalloc_clear( sizeof *newpkt );
                    newpkt->pkttype = PKT_SIGNATURE;
                    newpkt->pkt.signature = copy_signature( NULL, newsig );
                    free_packet( sn->pkt );
                    newpkt->pkttype = PKT_SIGNATURE;
                    newpkt->pkt.signature = copy_signature( NULL, newsig );
                    free_packet( sn->pkt );
-                   m_free( sn->pkt );
+                   xfree( sn->pkt );
                    sn->pkt = newpkt;
                }
                sub_pk = NULL;
                    sn->pkt = newpkt;
                }
                sub_pk = NULL;
@@ -3467,6 +3632,167 @@ menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock )
 }
 
 static int
 }
 
 static int
+menu_backsign(KBNODE pub_keyblock,KBNODE sec_keyblock)
+{
+  int rc,modified=0;
+  PKT_public_key *main_pk;
+  PKT_secret_key *main_sk,*sub_sk=NULL;
+  KBNODE node;
+
+  assert(pub_keyblock->pkt->pkttype==PKT_PUBLIC_KEY);
+  assert(sec_keyblock->pkt->pkttype==PKT_SECRET_KEY);
+
+  merge_keys_and_selfsig(pub_keyblock);
+  main_pk=pub_keyblock->pkt->pkt.public_key;
+  main_sk=copy_secret_key(NULL,sec_keyblock->pkt->pkt.secret_key);
+  keyid_from_pk(main_pk,NULL);
+
+  for(node=pub_keyblock;node;node=node->next)
+    {
+      PKT_public_key *sub_pk=NULL;
+      KBNODE node2,sig_pk=NULL,sig_sk=NULL;
+      char *passphrase;
+
+      if(sub_sk)
+       {
+         free_secret_key(sub_sk);
+         sub_sk=NULL;
+       }
+
+      /* Find a signing subkey with no backsig */
+      if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY)
+       {
+         if(node->pkt->pkt.public_key->pubkey_usage&PUBKEY_USAGE_SIG)
+           {
+             if(node->pkt->pkt.public_key->backsig)
+               tty_printf(_("signing subkey %s is already cross-certified\n"),
+                          keystr_from_pk(node->pkt->pkt.public_key));
+             else
+               sub_pk=node->pkt->pkt.public_key;
+           }
+         else
+           tty_printf(_("subkey %s does not sign and so does"
+                        " not need to be cross-certified\n"),
+                      keystr_from_pk(node->pkt->pkt.public_key));
+       }
+
+      if(!sub_pk)
+       continue;
+
+      /* Find the selected selfsig on this subkey */
+      for(node2=node->next;
+         node2 && node2->pkt->pkttype==PKT_SIGNATURE;
+         node2=node2->next)
+       if(node2->pkt->pkt.signature->version>=4
+          && node2->pkt->pkt.signature->flags.chosen_selfsig)
+         {
+           sig_pk=node2;
+           break;
+         }
+
+      if(!sig_pk)
+       continue;
+
+      /* Find the secret subkey that matches the public subkey */
+      for(node2=sec_keyblock;node2;node2=node2->next)
+       if(node2->pkt->pkttype==PKT_SECRET_SUBKEY
+          && !cmp_public_secret_key(sub_pk,node2->pkt->pkt.secret_key))
+         {
+           sub_sk=copy_secret_key(NULL,node2->pkt->pkt.secret_key);
+           break;
+         }
+
+      if(!sub_sk)
+       {
+         tty_printf(_("no secret subkey for public subkey %s - ignoring\n"),
+                    keystr_from_pk(sub_pk));
+         continue;
+       }
+
+      /* Now finally find the matching selfsig on the secret subkey.
+        We can't use chosen_selfsig here (it's not set for secret
+        keys), so we just pick the selfsig with the right class.
+        This is what menu_expire does as well. */
+      for(node2=node2->next;
+         node2 && node2->pkt->pkttype!=PKT_SECRET_SUBKEY;
+         node2=node2->next)
+       if(node2->pkt->pkttype==PKT_SIGNATURE
+          && node2->pkt->pkt.signature->version>=4
+          && node2->pkt->pkt.signature->keyid[0]==sig_pk->pkt->pkt.signature->keyid[0]
+          && node2->pkt->pkt.signature->keyid[1]==sig_pk->pkt->pkt.signature->keyid[1]
+          && node2->pkt->pkt.signature->sig_class==sig_pk->pkt->pkt.signature->sig_class)
+         {
+           sig_sk=node2;
+           break;
+         }
+
+      /* Now we can get to work.  We have a main key and secret part,
+        a signing subkey with signature and secret part possibly with
+        signature. */
+
+      passphrase=get_last_passphrase();
+      set_next_passphrase(passphrase);
+      xfree(passphrase);
+
+      rc=make_backsig(sig_pk->pkt->pkt.signature,main_pk,sub_pk,sub_sk);
+      if(rc==0)
+       {
+         PKT_signature *newsig;
+         PACKET *newpkt;
+
+         passphrase=get_last_passphrase();
+         set_next_passphrase(passphrase);
+         xfree(passphrase);
+
+         rc=update_keysig_packet(&newsig,sig_pk->pkt->pkt.signature,main_pk,
+                                 NULL,sub_pk,main_sk,NULL,NULL);
+         if(rc==0)
+           {
+             /* Put the new sig into place on the pubkey */
+             newpkt=xmalloc_clear(sizeof(*newpkt));
+             newpkt->pkttype=PKT_SIGNATURE;
+             newpkt->pkt.signature=newsig;
+             free_packet(sig_pk->pkt);
+             xfree(sig_pk->pkt);
+             sig_pk->pkt=newpkt;
+
+             if(sig_sk)
+               {
+                 /* Put the new sig into place on the seckey */
+                 newpkt=xmalloc_clear(sizeof(*newpkt));
+                 newpkt->pkttype=PKT_SIGNATURE;
+                 newpkt->pkt.signature=copy_signature(NULL,newsig);
+                 free_packet(sig_sk->pkt);
+                 xfree(sig_sk->pkt);
+                 sig_sk->pkt=newpkt;
+               }
+
+             modified=1;
+           }
+         else
+           {
+             log_error("update_keysig_packet failed: %s\n",g10_errstr(rc));
+             break;
+           }
+       }
+      else
+       {
+         log_error("make_backsig failed: %s\n",g10_errstr(rc));
+         break;
+       }
+    }
+
+  set_next_passphrase(NULL);
+
+  free_secret_key(main_sk);
+  if(sub_sk)
+    free_secret_key(sub_sk);
+
+  return modified;
+}
+
+
+static int
 change_primary_uid_cb ( PKT_signature *sig, void *opaque )
 {
     byte buf[1];
 change_primary_uid_cb ( PKT_signature *sig, void *opaque )
 {
     byte buf[1];
@@ -3548,7 +3874,7 @@ menu_set_primary_uid ( KBNODE pub_keyblock, KBNODE sec_keyblock )
 
                log_info(_("skipping v3 self-signature on user ID \"%s\"\n"),
                         user);
 
                log_info(_("skipping v3 self-signature on user ID \"%s\"\n"),
                         user);
-               m_free(user);
+               xfree(user);
              }
              else {
                /* This is a selfsignature which is to be replaced.
              }
              else {
                /* This is a selfsignature which is to be replaced.
@@ -3592,11 +3918,11 @@ menu_set_primary_uid ( KBNODE pub_keyblock, KBNODE sec_keyblock )
                         return 0;
                     }
                     /* replace the packet */
                         return 0;
                     }
                     /* replace the packet */
-                    newpkt = m_alloc_clear( sizeof *newpkt );
+                    newpkt = xmalloc_clear( sizeof *newpkt );
                     newpkt->pkttype = PKT_SIGNATURE;
                     newpkt->pkt.signature = newsig;
                     free_packet( node->pkt );
                     newpkt->pkttype = PKT_SIGNATURE;
                     newpkt->pkt.signature = newsig;
                     free_packet( node->pkt );
-                    m_free( node->pkt );
+                    xfree( node->pkt );
                     node->pkt = newpkt;
                     modified = 1;
                }
                     node->pkt = newpkt;
                     modified = 1;
                }
@@ -3658,7 +3984,7 @@ menu_set_preferences (KBNODE pub_keyblock, KBNODE sec_keyblock )
 
                log_info(_("skipping v3 self-signature on user ID \"%s\"\n"),
                         user);
 
                log_info(_("skipping v3 self-signature on user ID \"%s\"\n"),
                         user);
-               m_free(user);
+               xfree(user);
              }
              else {
                /* This is a selfsignature which is to be replaced 
              }
              else {
                /* This is a selfsignature which is to be replaced 
@@ -3680,11 +4006,11 @@ menu_set_preferences (KBNODE pub_keyblock, KBNODE sec_keyblock )
                     return 0;
                 }
                 /* replace the packet */
                     return 0;
                 }
                 /* replace the packet */
-                newpkt = m_alloc_clear( sizeof *newpkt );
+                newpkt = xmalloc_clear( sizeof *newpkt );
                 newpkt->pkttype = PKT_SIGNATURE;
                 newpkt->pkt.signature = newsig;
                 free_packet( node->pkt );
                 newpkt->pkttype = PKT_SIGNATURE;
                 newpkt->pkt.signature = newsig;
                 free_packet( node->pkt );
-                m_free( node->pkt );
+                xfree( node->pkt );
                 node->pkt = newpkt;
                 modified = 1;
              }
                 node->pkt = newpkt;
                 modified = 1;
              }
@@ -3713,14 +4039,14 @@ menu_set_keyserver_url (const char *url,
   no_primary_warning(pub_keyblock);
 
   if(url)
   no_primary_warning(pub_keyblock);
 
   if(url)
-    answer=m_strdup(url);
+    answer=xstrdup(url);
   else
     {
       answer=cpr_get_utf8("keyedit.add_keyserver",
                          _("Enter your preferred keyserver URL: "));
       if(answer[0]=='\0' || answer[0]=='\004')
        {
   else
     {
       answer=cpr_get_utf8("keyedit.add_keyserver",
                          _("Enter your preferred keyserver URL: "));
       if(answer[0]=='\0' || answer[0]=='\004')
        {
-         m_free(answer);
+         xfree(answer);
          return 0;
        }
     }
          return 0;
        }
     }
@@ -3732,13 +4058,13 @@ menu_set_keyserver_url (const char *url,
       struct keyserver_spec *keyserver=NULL;
       /* Sanity check the format */
       keyserver=parse_keyserver_uri(answer,1,NULL,0);
       struct keyserver_spec *keyserver=NULL;
       /* Sanity check the format */
       keyserver=parse_keyserver_uri(answer,1,NULL,0);
-      m_free(answer);
+      xfree(answer);
       if(!keyserver)
        {
          log_info(_("could not parse keyserver URL\n"));
          return 0;
        }
       if(!keyserver)
        {
          log_info(_("could not parse keyserver URL\n"));
          return 0;
        }
-      uri=m_strdup(keyserver->uri);
+      uri=xstrdup(keyserver->uri);
       free_keyserver_spec(keyserver);
     }
 
       free_keyserver_spec(keyserver);
     }
 
@@ -3817,25 +4143,238 @@ menu_set_keyserver_url (const char *url,
                      log_error ("update_keysig_packet failed: %s\n",
                                 g10_errstr(rc));
                      free_secret_key( sk );
                      log_error ("update_keysig_packet failed: %s\n",
                                 g10_errstr(rc));
                      free_secret_key( sk );
-                     m_free(uri);
+                     xfree(uri);
                      return 0;
                    }
                  /* replace the packet */
                      return 0;
                    }
                  /* replace the packet */
-                 newpkt = m_alloc_clear( sizeof *newpkt );
+                 newpkt = xmalloc_clear( sizeof *newpkt );
                  newpkt->pkttype = PKT_SIGNATURE;
                  newpkt->pkt.signature = newsig;
                  free_packet( node->pkt );
                  newpkt->pkttype = PKT_SIGNATURE;
                  newpkt->pkt.signature = newsig;
                  free_packet( node->pkt );
-                 m_free( node->pkt );
+                 xfree( node->pkt );
                  node->pkt = newpkt;
                  modified = 1;
                }
 
                  node->pkt = newpkt;
                  modified = 1;
                }
 
-             m_free(user);
+             xfree(user);
+           }
+       }
+    }
+
+  xfree(uri);
+  free_secret_key( sk );
+  return modified;
+}
+
+static int
+menu_set_notation(const char *string,KBNODE pub_keyblock,KBNODE sec_keyblock)
+{
+  PKT_secret_key *sk;    /* copy of the main sk */
+  PKT_public_key *main_pk;
+  PKT_user_id *uid;
+  KBNODE node;
+  u32 keyid[2];
+  int selected, select_all;
+  int modified = 0;
+  char *answer;
+  struct notation *notation;
+
+  no_primary_warning(pub_keyblock);
+
+  if(string)
+    answer=xstrdup(string);
+  else
+    {
+      answer=cpr_get_utf8("keyedit.add_notation",
+                         _("Enter the notation: "));
+      if(answer[0]=='\0' || answer[0]=='\004')
+       {
+         xfree(answer);
+         return 0;
+       }
+    }
+
+  if(ascii_strcasecmp(answer,"none")==0
+     || ascii_strcasecmp(answer,"-")==0)
+    notation=NULL; /* delete them all */
+  else
+    {
+      notation=string_to_notation(answer,0);
+      if(!notation)
+       {
+         xfree(answer);
+         return 0;
+       }
+    }
+
+  xfree(answer);
+
+  select_all = !count_selected_uids (pub_keyblock);
+
+  node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
+  sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
+
+  /* Now we can actually change the self signature(s) */
+  main_pk = NULL;
+  uid = NULL;
+  selected = 0;
+  for ( node=pub_keyblock; node; node = node->next )
+    {
+      if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
+       break; /* ready */
+
+      if ( node->pkt->pkttype == PKT_PUBLIC_KEY )
+       {
+         main_pk = node->pkt->pkt.public_key;
+         keyid_from_pk( main_pk, keyid );
+       }
+      else if ( node->pkt->pkttype == PKT_USER_ID )
+       {
+         uid = node->pkt->pkt.user_id;
+         selected = select_all || (node->flag & NODFLG_SELUID);
+       }
+      else if ( main_pk && uid && selected
+               && node->pkt->pkttype == PKT_SIGNATURE )
+       {
+         PKT_signature *sig = node->pkt->pkt.signature;
+         if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
+              && (uid && (sig->sig_class&~3) == 0x10)
+              && sig->flags.chosen_selfsig)
+           {
+             char *user=utf8_to_native(uid->name,strlen(uid->name),0);
+             if( sig->version < 4 )
+               log_info(_("skipping v3 self-signature on user ID \"%s\"\n"),
+                        user);
+             else
+               {
+                 PKT_signature *newsig;
+                 PACKET *newpkt;
+                 int rc,skip=0,addonly=1;
+
+                 if(sig->flags.notation)
+                   {
+                     tty_printf("Current notations for user ID \"%s\":\n",
+                                user);
+                     tty_print_notations(-9,sig);
+                   }
+                 else
+                   {
+                     tty_printf("No notations on user ID \"%s\"\n",user);
+                     if(notation==NULL)
+                       {
+                         /* There are no current notations, so there
+                            is no point in trying to un-set them. */
+                         continue;
+                       }
+                   }
+
+                 if(notation)
+                   {
+                     struct notation *n;
+                     int deleting=0;
+
+                     notation->next=sig_to_notation(sig);
+
+                     for(n=notation->next;n;n=n->next)
+                       if(strcmp(n->name,notation->name)==0)
+                         {
+                           if(notation->value)
+                             {
+                               if(strcmp(n->value,notation->value)==0)
+                                 {
+                                   if(notation->flags.ignore)
+                                     {
+                                       /* Value match with a delete
+                                          flag. */
+                                       n->flags.ignore=1;
+                                       deleting=1;
+                                     }
+                                   else
+                                     {
+                                       /* Adding the same notation
+                                          twice, so don't add it at
+                                          all. */
+                                       skip=1;
+                                       tty_printf("Skipping notation:"
+                                                  " %s=%s\n",
+                                                  notation->name,
+                                                  notation->value);
+                                       break;
+                                     }
+                                 }
+                             }
+                           else
+                             {
+                               /* No value, so it means delete. */
+                               n->flags.ignore=1;
+                               deleting=1;
+                             }
+
+                           if(n->flags.ignore)
+                             {
+                               tty_printf("Removing notation: %s=%s\n",
+                                          n->name,n->value);
+                               addonly=0;
+                             }
+                         }
+
+                     if(!notation->flags.ignore && !skip)
+                       tty_printf("Adding notation: %s=%s\n",
+                                  notation->name,notation->value);
+
+                     /* We tried to delete, but had no matches */
+                     if(notation->flags.ignore && !deleting)
+                       continue;
+                   }
+                 else
+                   {
+                     tty_printf("Removing all notations\n");
+                     addonly=0;
+                   }
+
+                 if(skip
+                    || (!addonly
+                        && !cpr_get_answer_is_yes("keyedit.confirm_notation",
+                                                  _("Proceed? (y/N) "))))
+                   continue;
+
+                 rc = update_keysig_packet (&newsig, sig,
+                                            main_pk, uid, NULL,
+                                            sk,
+                                            keygen_add_notations, notation );
+                 if( rc )
+                   {
+                     log_error ("update_keysig_packet failed: %s\n",
+                                g10_errstr(rc));
+                     free_secret_key( sk );
+                     free_notation(notation);
+                     xfree(user);
+                     return 0;
+                   }
+
+                 /* replace the packet */
+                 newpkt = xmalloc_clear( sizeof *newpkt );
+                 newpkt->pkttype = PKT_SIGNATURE;
+                 newpkt->pkt.signature = newsig;
+                 free_packet( node->pkt );
+                 xfree( node->pkt );
+                 node->pkt = newpkt;
+                 modified = 1;
+
+                 if(notation)
+                   {
+                     /* Snip off the notation list from the sig */
+                     free_notation(notation->next);
+                     notation->next=NULL;
+                   }
+
+                 xfree(user);
+               }
            }
        }
     }
 
            }
        }
     }
 
-  m_free(uri);
+  free_notation(notation);
   free_secret_key( sk );
   return modified;
 }
   free_secret_key( sk );
   return modified;
 }
@@ -3886,6 +4425,45 @@ menu_select_uid( KBNODE keyblock, int idx )
     return 1;
 }
 
     return 1;
 }
 
+/* Search in the keyblock for a uid that matches namehash */
+static int
+menu_select_uid_namehash( KBNODE keyblock, const char *namehash )
+{
+  byte hash[NAMEHASH_LEN];
+  KBNODE node;
+  int i;
+
+  assert(strlen(namehash)==NAMEHASH_LEN*2);
+
+  for(i=0;i<NAMEHASH_LEN;i++)
+    hash[i]=hextobyte(&namehash[i*2]);
+
+  for(node=keyblock->next;node;node=node->next)
+    {
+      if(node->pkt->pkttype==PKT_USER_ID)
+       {
+         namehash_from_uid(node->pkt->pkt.user_id);
+         if(memcmp(node->pkt->pkt.user_id->namehash,hash,NAMEHASH_LEN)==0)
+           {
+             if(node->flag&NODFLG_SELUID)
+               node->flag &= ~NODFLG_SELUID;
+             else
+               node->flag |= NODFLG_SELUID;
+
+             break;
+           }
+       }
+    }
+
+    if(!node)
+      {
+       tty_printf(_("No user ID with hash %s\n"),namehash);
+       return 0;
+      }
+
+  return 1;
+}
+
 /****************
  * Select secondary keys
  * Returns: True if the selection changed;
 /****************
  * Select secondary keys
  * Returns: True if the selection changed;
@@ -4012,7 +4590,7 @@ static void
 ask_revoke_sig( KBNODE keyblock, KBNODE node )
 {
     int doit=0;
 ask_revoke_sig( KBNODE keyblock, KBNODE node )
 {
     int doit=0;
-    char *p;
+    PKT_user_id *uid;
     PKT_signature *sig = node->pkt->pkt.signature;
     KBNODE unode = find_prev_kbnode( keyblock, node, PKT_USER_ID );
 
     PKT_signature *sig = node->pkt->pkt.signature;
     KBNODE unode = find_prev_kbnode( keyblock, node, PKT_USER_ID );
 
@@ -4021,15 +4599,33 @@ ask_revoke_sig( KBNODE keyblock, KBNODE node )
        return;
     }
 
        return;
     }
 
-    p=utf8_to_native(unode->pkt->pkt.user_id->name,
-                    unode->pkt->pkt.user_id->len,0);
-    tty_printf(_("user ID: \"%s\"\n"),p);
-    m_free(p);
+    uid=unode->pkt->pkt.user_id;
+
+    if(opt.with_colons)
+      {
+       if(uid->attrib_data)
+         printf("uat:::::::::%u %lu",uid->numattribs,uid->attrib_len);
+       else
+         {
+           printf("uid:::::::::");
+           print_string (stdout, uid->name, uid->len, ':');
+         }
 
 
-    tty_printf(_("signed by your key %s on %s%s%s\n"),
-              keystr(sig->keyid),datestr_from_sig(sig),
-              sig->flags.exportable?"":_(" (non-exportable)"),"");
+       printf("\n");
 
 
+       print_and_check_one_sig_colon(keyblock,node,NULL,NULL,NULL,NULL,1);
+      }
+    else
+      {
+       char *p=utf8_to_native(unode->pkt->pkt.user_id->name,
+                        unode->pkt->pkt.user_id->len,0);
+       tty_printf(_("user ID: \"%s\"\n"),p);
+       xfree(p);
+
+       tty_printf(_("signed by your key %s on %s%s%s\n"),
+                  keystr(sig->keyid),datestr_from_sig(sig),
+                  sig->flags.exportable?"":_(" (non-exportable)"),"");
+      }
     if(sig->flags.expired)
       {
        tty_printf(_("This signature expired on %s.\n"),
     if(sig->flags.expired)
       {
        tty_printf(_("This signature expired on %s.\n"),
@@ -4170,7 +4766,7 @@ menu_revsig( KBNODE keyblock )
        attrib.non_exportable=!node->pkt->pkt.signature->flags.exportable;
 
        node->flag &= ~NODFLG_MARK_A;
        attrib.non_exportable=!node->pkt->pkt.signature->flags.exportable;
 
        node->flag &= ~NODFLG_MARK_A;
-       sk = m_alloc_secure_clear( sizeof *sk );
+       sk = xmalloc_secure_clear( sizeof *sk );
        if( get_seckey( sk, node->pkt->pkt.signature->keyid ) ) {
            log_info(_("no secret key\n"));
            continue;
        if( get_seckey( sk, node->pkt->pkt.signature->keyid ) ) {
            log_info(_("no secret key\n"));
            continue;
@@ -4194,7 +4790,7 @@ menu_revsig( KBNODE keyblock )
        if(primary_pk->keyid[0]==sig->keyid[0] &&
           primary_pk->keyid[1]==sig->keyid[1])
          unode->pkt->pkt.user_id->is_revoked=1;
        if(primary_pk->keyid[0]==sig->keyid[0] &&
           primary_pk->keyid[1]==sig->keyid[1])
          unode->pkt->pkt.user_id->is_revoked=1;
-       pkt = m_alloc_clear( sizeof *pkt );
+       pkt = xmalloc_clear( sizeof *pkt );
        pkt->pkttype = PKT_SIGNATURE;
        pkt->pkt.signature = sig;
        insert_kbnode( unode, new_kbnode(pkt), 0 );
        pkt->pkttype = PKT_SIGNATURE;
        pkt->pkt.signature = sig;
        insert_kbnode( unode, new_kbnode(pkt), 0 );
@@ -4243,7 +4839,7 @@ menu_revuid( KBNODE pub_keyblock, KBNODE sec_keyblock )
          {
            char *user=utf8_to_native(uid->name,uid->len,0);
            log_info(_("user ID \"%s\" is already revoked\n"),user);
          {
            char *user=utf8_to_native(uid->name,uid->len,0);
            log_info(_("user ID \"%s\" is already revoked\n"),user);
-           m_free(user);
+           xfree(user);
          }
        else
          {
          }
        else
          {
@@ -4280,7 +4876,7 @@ menu_revuid( KBNODE pub_keyblock, KBNODE sec_keyblock )
              }
            else
              {
              }
            else
              {
-               pkt = m_alloc_clear( sizeof *pkt );
+               pkt = xmalloc_clear( sizeof *pkt );
                pkt->pkttype = PKT_SIGNATURE;
                pkt->pkt.signature = sig;
                insert_kbnode( node, new_kbnode(pkt), 0 );
                pkt->pkttype = PKT_SIGNATURE;
                pkt->pkt.signature = sig;
                insert_kbnode( node, new_kbnode(pkt), 0 );
@@ -4345,7 +4941,7 @@ menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
 
   changed = 1; /* we changed the keyblock */
 
 
   changed = 1; /* we changed the keyblock */
 
-  pkt = m_alloc_clear( sizeof *pkt );
+  pkt = xmalloc_clear( sizeof *pkt );
   pkt->pkttype = PKT_SIGNATURE;
   pkt->pkt.signature = sig;
   insert_kbnode( pub_keyblock, new_kbnode(pkt), 0 );
   pkt->pkttype = PKT_SIGNATURE;
   pkt->pkt.signature = sig;
   insert_kbnode( pub_keyblock, new_kbnode(pkt), 0 );
@@ -4406,7 +5002,7 @@ menu_revsubkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
            }
            changed = 1; /* we changed the keyblock */
 
            }
            changed = 1; /* we changed the keyblock */
 
-           pkt = m_alloc_clear( sizeof *pkt );
+           pkt = xmalloc_clear( sizeof *pkt );
            pkt->pkttype = PKT_SIGNATURE;
            pkt->pkt.signature = sig;
            insert_kbnode( node, new_kbnode(pkt), 0 );
            pkt->pkttype = PKT_SIGNATURE;
            pkt->pkt.signature = sig;
            insert_kbnode( node, new_kbnode(pkt), 0 );