+/* Returns TRUE iff name and/or addr is considered duplicite. */
+static notmuch_bool_t
+check_duplicite (const search_options_t *opt, GHashTable *addrs, const char *name, const char *addr)
+{
+ notmuch_bool_t duplicite;
+ char *key;
+
+ if (opt->filter_by == FILTER_BY_ADDRFOLD ||
+ opt->filter_by == FILTER_BY_NAMEADDRFOLD) {
+ gchar *folded = g_utf8_casefold (addr, -1);
+ addr = talloc_strdup (opt->format, folded);
+ g_free (folded);
+ }
+ switch (opt->filter_by) {
+ case FILTER_BY_NAMEADDR:
+ case FILTER_BY_NAMEADDRFOLD:
+ key = talloc_asprintf (opt->format, "%s <%s>", name, addr);
+ break;
+ case FILTER_BY_NAME:
+ key = talloc_strdup (opt->format, name); /* !name results in !key */
+ break;
+ case FILTER_BY_ADDR:
+ case FILTER_BY_ADDRFOLD:
+ key = talloc_strdup (opt->format, addr);
+ break;
+ default:
+ INTERNAL_ERROR("invalid --filter-by flags");
+ }
+
+ if (opt->filter_by == FILTER_BY_ADDRFOLD ||
+ opt->filter_by == FILTER_BY_NAMEADDRFOLD)
+ talloc_free ((char*)addr);
+
+ if (! key)
+ return FALSE;
+
+ duplicite = g_hash_table_lookup_extended (addrs, key, NULL, NULL);
+
+ if (! duplicite)
+ g_hash_table_insert (addrs, key, NULL);
+ else
+ talloc_free (key);
+
+ return duplicite;
+}
+
+static void
+print_mailbox (const search_options_t *opt, const mailbox_t *mailbox)
+{
+ const char *name = mailbox->name;
+ const char *addr = mailbox->addr;
+
+ if (opt->format->is_text_printer) {
+ char *mailbox_str;
+
+ if (name && *name)
+ mailbox_str = talloc_asprintf (opt->format, "%s <%s>", name, addr);
+ else
+ mailbox_str = talloc_strdup (opt->format, addr);
+
+ if (! mailbox_str) {
+ fprintf (stderr, "Error: out of memory\n");
+ return;
+ }
+ opt->format->string (opt->format, mailbox_str);
+ opt->format->separator (opt->format);
+
+ talloc_free (mailbox_str);
+ } else {
+ opt->format->begin_map (opt->format);
+ opt->format->map_key (opt->format, "name");
+ opt->format->string (opt->format, name);
+ opt->format->map_key (opt->format, "address");
+ opt->format->string (opt->format, addr);
+ opt->format->end (opt->format);
+ opt->format->separator (opt->format);
+ }
+}
+
+static void
+process_address_list (const search_options_t *opt, GHashTable *addrs,
+ InternetAddressList *list)
+{
+ InternetAddress *address;
+ int i;
+
+ for (i = 0; i < internet_address_list_length (list); i++) {
+ address = internet_address_list_get_address (list, i);
+ if (INTERNET_ADDRESS_IS_GROUP (address)) {
+ InternetAddressGroup *group;
+ InternetAddressList *group_list;
+
+ group = INTERNET_ADDRESS_GROUP (address);
+ group_list = internet_address_group_get_members (group);
+ if (group_list == NULL)
+ continue;
+
+ process_address_list (opt, addrs, group_list);
+ } else {
+ InternetAddressMailbox *mailbox = INTERNET_ADDRESS_MAILBOX (address);
+ mailbox_t mbx = {
+ .name = internet_address_get_name (address),
+ .addr = internet_address_mailbox_get_addr (mailbox),
+ };
+
+ if (check_duplicite (opt, addrs, mbx.name, mbx.addr))
+ continue;
+
+ print_mailbox (opt, &mbx);
+ }
+ }
+}
+
+static void
+process_address_header (const search_options_t *opt, GHashTable *addrs, const char *value)
+{
+ InternetAddressList *list;
+
+ if (value == NULL)
+ return;
+
+ list = internet_address_list_parse_string (value);
+ if (list == NULL)
+ return;
+
+ process_address_list (opt, addrs, list);
+}
+
+static void
+_my_talloc_free_for_g_hash (void *ptr)
+{
+ talloc_free (ptr);
+}
+