+ /* This method finds a valid display name */
+ public bool display_name_is_valid(string name,
+ out string? candidate)
+ {
+ if (&candidate != null)
+ candidate = null;
+ foreach (IdCard id_card in this.store.get_card_list())
+ {
+ if (id_card.display_name == name)
+ {
+ if (&candidate != null)
+ {
+ for (int i = 0; i < 1000; i++)
+ {
+ string tmp = "%s %d".printf(name, i);
+ if (display_name_is_valid(tmp, null))
+ {
+ candidate = tmp;
+ break;
+ }
+ }
+ }
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private bool remove_duplicates(IdCard new_card, out ArrayList<IdCard>? old_duplicates)
+ {
+ ArrayList<IdCard> dups = new ArrayList<IdCard>();
+ var cards = this.store.get_card_list();
+ foreach (IdCard id_card in cards) {
+ if ((new_card != id_card) && (id_card.nai == new_card.nai)) {
+ dups.add(id_card);
+ }
+ }
+
+ foreach (IdCard id_card in dups) {
+ logger.trace("removing duplicate id for '%s'\n".printf(new_card.nai));
+ remove_card_internal(id_card);
+
+ if (new_card.trust_anchor.Compare(id_card.trust_anchor) == 0) {
+ logger.trace("Old and new cards have same trust anchor. Re-using the datetime_added field from the old card.");
+ new_card.trust_anchor.set_datetime_added(id_card.trust_anchor.datetime_added);
+ }
+ }
+
+ if (&old_duplicates != null) {
+ old_duplicates = dups;
+ }
+
+ return (dups.size > 0);
+ }
+
+
+ public bool find_duplicate_nai_sets(out ArrayList<ArrayList<IdCard>> duplicates)
+ {
+ var nais = new HashMap<string, ArrayList<IdCard>>();
+
+ duplicates = new ArrayList<ArrayList<IdCard>>();
+ LinkedList<IdCard> card_list = get_card_list() ;
+ if (card_list == null) {
+ return false;
+ }
+
+ bool found = false;
+ foreach (IdCard id_card in card_list) {
+ logger.trace(@"load_id_cards: Loading card with display name '$(id_card.display_name)'");
+
+ //!!TODO: This uniqueness check really belongs somewhere else -- like where we add
+ // IDs, and/or read them from storage. However, we should never hit this.
+
+ if (nais.has_key(id_card.nai)) {
+ ArrayList<IdCard> list = nais.get(id_card.nai);
+ list.add(id_card);
+ }
+ else {
+ ArrayList<IdCard> list = new ArrayList<IdCard>();
+ list.add(id_card);
+ nais.set(id_card.nai, list);
+ }
+ }
+
+ duplicates = new ArrayList<ArrayList<IdCard>>();
+ foreach (Map.Entry<string, ArrayList<IdCard>> entry in nais.entries) {
+ var list = entry.value;
+ if (list.size > 1) {
+ duplicates.add(list);
+ found = true;
+ }
+ }
+ return found;
+ }
+
+
+ public IdCard? find_id_card(string nai, bool force_flat_file_store) {
+ IdCard? retval = null;
+ IIdentityCardStore.StoreType saved_store_type = get_store_type();
+ if (force_flat_file_store)
+ set_store_type(IIdentityCardStore.StoreType.FLAT_FILE);
+
+ foreach (IdCard id in get_card_list()) {
+ if (id.nai == nai) {
+ retval = id;
+ break;
+ }
+ }
+ set_store_type(saved_store_type);
+ if (force_flat_file_store &&
+ (saved_store_type != IIdentityCardStore.StoreType.FLAT_FILE))
+ card_list_changed();
+ return retval;
+ }
+
+ public void add_card(IdCard card, bool force_flat_file_store, out ArrayList<IdCard>? old_duplicates=null) {
+ if (card.temporary) {
+ logger.trace("add_card: card is temporary; returning.");
+ return;
+ }
+
+ string candidate;
+ IIdentityCardStore.StoreType saved_store_type = get_store_type();
+
+ if (force_flat_file_store)
+ set_store_type(IIdentityCardStore.StoreType.FLAT_FILE);
+
+ remove_duplicates(card, out old_duplicates);
+
+ if (!display_name_is_valid(card.display_name, out candidate))
+ {
+ card.display_name = candidate;
+ }
+
+ if (!card.store_password)
+ password_table.CachePassword(card, store);
+
+ logger.trace("add_card: Adding card '%s' with services: '%s'"
+ .printf(card.display_name, card.get_services_string("; ")));
+