/* GNU Mailutils -- a suite of utilities for electronic mail Copyright (C) 2011-2019 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include struct list_closure { int error_code; mu_list_t retlist; const char *command; }; static int count_level (const char *name, int delim) { int level = 0; while (*name) if (*name++ == delim) level++; return level; } static int list_attr_conv (void *item, void *data) { struct imap_list_element *elt = item; struct mu_list_response *rp = data; if (elt->type != imap_eltype_string) return 0; if (mu_c_strcasecmp (elt->v.string, "\\Noinferiors")) rp->type |= MU_FOLDER_ATTRIBUTE_DIRECTORY; if (mu_c_strcasecmp (elt->v.string, "\\Noselect")) rp->type |= MU_FOLDER_ATTRIBUTE_FILE; /* FIXME: \Marked nad \Unmarked have no correspondence in flags. */ return 0; } static void list_untagged_handler (mu_imap_t imap, mu_list_t resp, void *data) { struct list_closure *clos = data; struct imap_list_element *elt; size_t count; if (clos->error_code) return; mu_list_count (resp, &count); if (count == 4 && _mu_imap_list_nth_element_is_string (resp, 0, clos->command)) { struct mu_list_response *rp; rp = calloc (1, sizeof (*rp)); if (!rp) { clos->error_code = ENOMEM; return; } elt = _mu_imap_list_at (resp, 1); if (!(elt && elt->type == imap_eltype_list)) return; rp->type = 0; mu_list_foreach (elt->v.list, list_attr_conv, rp); elt = _mu_imap_list_at (resp, 3); if (!(elt && elt->type == imap_eltype_string)) return; rp->name = strdup (elt->v.string); if (!rp->name) { free (rp); clos->error_code = ENOMEM; return; } elt = _mu_imap_list_at (resp, 2); if (!elt) return; if (_mu_imap_list_element_is_nil (elt)) { rp->separator = 0; rp->level = 0; } else if (elt->type != imap_eltype_string) return; else { rp->separator = elt->v.string[0]; rp->level = count_level (rp->name, rp->separator); } if ((clos->error_code = mu_list_append (clos->retlist, rp))) mu_list_response_free (rp); } } int mu_imap_genlist (mu_imap_t imap, int lsub, const char *refname, const char *mboxname, mu_list_t retlist) { char const *argv[3]; static struct imap_command com; struct list_closure clos; int rc; if (!refname || !mboxname) return EINVAL; argv[0] = lsub ? "LSUB" : "LIST"; argv[1] = refname; argv[2] = mboxname; clos.error_code = 0; clos.retlist = retlist; clos.command = argv[0]; com.session_state = MU_IMAP_SESSION_AUTH; com.capa = NULL; com.rx_state = lsub ? MU_IMAP_CLIENT_LSUB_RX : MU_IMAP_CLIENT_LIST_RX; com.argc = 3; com.argv = argv; com.extra = NULL; com.msgset = NULL; com.tagged_handler = NULL; com.untagged_handler = list_untagged_handler; com.untagged_handler_data = &clos; rc = mu_imap_gencom (imap, &com); if (rc == 0) rc = clos.error_code; return rc; } int mu_imap_genlist_new (mu_imap_t imap, int lsub, const char *refname, const char *mboxname, mu_list_t *plist) { mu_list_t list; int rc = mu_list_create (&list); if (rc == 0) { mu_list_set_destroy_item (list, mu_list_response_free); rc = mu_imap_genlist (imap, lsub, refname, mboxname, list); if (rc) mu_list_destroy (&list); else *plist = list; } return rc; }