Index: libabac/abac_xml.c
===================================================================
--- libabac/abac_xml.c	(revision b7e77dfa7e38d121dc6bbbab89456e4af6479d04)
+++ libabac/abac_xml.c	(revision d2b198c77ec345f4a2f4f7c24f7d28230cb6faad)
@@ -153,6 +153,6 @@
 xmlChar *encode_rt0_xml_v10(abac_attribute_t *);
 xmlChar *encode_rt0_xml_v11(abac_attribute_t *);
-xmlChar **parse_rt0_xml_v10(xmlNodePtr);
-xmlChar **parse_rt0_xml_v11(xmlNodePtr);
+xmlChar **parse_rt0_xml_v10(xmlNodePtr, abac_keyid_map_t *);
+xmlChar **parse_rt0_xml_v11(xmlNodePtr, abac_keyid_map_t *);
 
 /* Structure that specializes XML parsing */
@@ -163,5 +163,5 @@
     xmlChar *(*rt0_to_xml)(abac_attribute_t *);
     /* Convert an rt0 element into a list of RT0 strings */
-    xmlChar **(*xml_to_rt0)(xmlNodePtr);
+    xmlChar **(*xml_to_rt0)(xmlNodePtr, abac_keyid_map_t *);
     /* The overall template to generate this version of credential */
     char *out_template;
@@ -590,5 +590,6 @@
  * return value is an array of strings, zero-terminated (like argv) that holds
  * the RT0 strings.  It is NULL on failure. */
-static xmlChar **parse_privilege(xmlDocPtr doc, void *ctxt_id_certs) {
+static xmlChar **parse_privilege(xmlDocPtr doc, void *ctxt_id_certs, 
+	abac_keyid_map_t *km) {
     xmlNodePtr root = NULL;	/* XML root node */
     xmlNodePtr node = NULL;	/* XML scratch node */
@@ -737,5 +738,5 @@
  * has no structure.
  */
-xmlChar **parse_rt0_xml_v10(xmlNodePtr n) {
+xmlChar **parse_rt0_xml_v10(xmlNodePtr n, abac_keyid_map_t *km) {
     xmlChar *txt;
     xmlChar **rv = NULL;
@@ -816,11 +817,26 @@
  * </tail>
  * becomes P.r1.r2.
+ * In addition, if there is a mnemonic in the ABACPrincipal field, add it to
+ * the keyid_map (if there is a map).
  */
-static xmlChar *term_copy(xmlNodePtr n, xmlChar *dest) {
+static xmlChar *term_copy(xmlNodePtr n, xmlChar *dest, abac_keyid_map_t *km) {
     xmlNodePtr p = get_direct_child(n, "ABACprincipal");
+    xmlNodePtr k = NULL;
+    xmlNodePtr m = NULL;
+    char *ks = NULL;
+    char *ms = NULL;
 
     if ( !p ) return NULL;
-    if ( !(p = get_direct_child(p, "keyid"))) return NULL;
-    if ( !(dest = role_copy(get_element_content(p), dest))) return NULL;
+    if ( !(k = get_direct_child(p, "keyid"))) return NULL;
+    if ( !(ks = get_element_content(k))) return NULL;
+    if ( !(dest = role_copy(ks, dest))) return NULL;
+    /* If there's a mnemonic string, add the mapping from keyid to mnemonic to
+     * the keymap */
+    if ( (m = get_direct_child(p, "mnemonic"))) {
+	if ( (ms = get_element_content(m))) {
+	    abac_keyid_map_remove_keyid(km, ks);
+	    abac_keyid_map_add_nickname(km, ks, ms);
+	}
+    }
     if ( (p = get_direct_child(n, "linking_role"))) {
 	*dest++ = '.';
@@ -870,5 +886,5 @@
  * Converts to A.r<-B.r1.r2 & C.r2
  */
-xmlChar **parse_rt0_xml_v11(xmlNodePtr n) {
+xmlChar **parse_rt0_xml_v11(xmlNodePtr n, abac_keyid_map_t *km) {
     int len = 3;    /* Length of the RT0 string we're building. Initially 3 for
 		       the <- and end-of-string */
@@ -909,5 +925,5 @@
     d = rv[0];
     if ( !( c = get_direct_child(n, "head"))) goto fail;
-    if ( !(d = term_copy(c, d))) goto fail;
+    if ( !(d = term_copy(c, d, km))) goto fail;
     d = append_and_move(d, "<-", 2);
     tails = 0;
@@ -919,5 +935,5 @@
 	    if ( tails++) 
 		d = append_and_move(d, " & ", 3);
-	    if ( !(d = term_copy(c, d))) goto fail;
+	    if ( !(d = term_copy(c, d, km))) goto fail;
 	}
     }
@@ -939,5 +955,5 @@
  * which the new certificate is added.
  */
-xmlChar **parse_abac(xmlDocPtr doc, void *ctxt_id_certs) {
+xmlChar **parse_abac(xmlDocPtr doc, void *ctxt_id_certs, abac_keyid_map_t *km) {
     xmlNodePtr root = NULL;	/* XML root node */
     xmlNodePtr node = NULL;	/* XML credential node */
@@ -991,5 +1007,5 @@
 
     /* read the RT0 and return it */
-    if ( !(rv = proc->xml_to_rt0(rt0)) ) goto fail;
+    if ( !(rv = proc->xml_to_rt0(rt0, km)) ) goto fail;
     ncred=1;
 
@@ -1020,5 +1036,5 @@
  * the ABAC context. */
 char **read_credential(void *ctxt_id_certs, char *infile, 
-	char **in_xml) {
+	char **in_xml, abac_keyid_map_t *km) {
     xmlChar **xml = (xmlChar **) in_xml;    /* Cast */
     xmlDocPtr doc = xmlParseFile(infile);   /* Parse the document */
@@ -1042,7 +1058,7 @@
     /* Demux on type */
     if ( !strcmp((char *) text, "privilege")) {
-	rv = parse_privilege(doc, ctxt_id_certs);
+	rv = parse_privilege(doc, ctxt_id_certs, km);
     } else if ( !strcmp((char *) text, "abac")) {
-	rv = parse_abac(doc, ctxt_id_certs);
+	rv = parse_abac(doc, ctxt_id_certs, km);
     } else { 
 	goto fail;
@@ -1469,5 +1485,5 @@
 
 /* parse xml structure and extract the attribute rules */
-char **get_rt0_from_xml(void *ctxt_id_certs,char *xml) {
+char **get_rt0_from_xml(void *ctxt_id_certs,char *xml, abac_keyid_map_t *km) {
     xmlDocPtr doc=xmlParseMemory(xml,strlen(xml));
     xmlNodePtr node = NULL;                 /* XML scratch node */
@@ -1490,7 +1506,7 @@
     /* Demux on type */
     if ( !strcmp((char *) text, "privilege")) {
-        rv = parse_privilege(doc,ctxt_id_certs);
+        rv = parse_privilege(doc, ctxt_id_certs, km);
     } else if ( !strcmp((char *) text, "abac")) {
-        rv = parse_abac(doc, ctxt_id_certs);
+        rv = parse_abac(doc, ctxt_id_certs, km);
     } else {
         goto fail;
