NeoMutt  2021-02-05-89-gabe350
Teaching an old dog new tricks
DOXYGEN
util.c
Go to the documentation of this file.
1 
32 #include "config.h"
33 #include <ctype.h>
34 #include <errno.h>
35 #include <netdb.h>
36 #include <netinet/in.h>
37 #include <signal.h>
38 #include <stdbool.h>
39 #include <stdint.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <sys/wait.h>
43 #include <time.h>
44 #include <unistd.h>
45 #include "private.h"
46 #include "mutt/lib.h"
47 #include "config/lib.h"
48 #include "email/lib.h"
49 #include "core/lib.h"
50 #include "conn/lib.h"
51 #include "gui/lib.h"
52 #include "bcache/lib.h"
53 #include "imap/lib.h"
54 #include "adata.h"
55 #include "edata.h"
56 #include "mdata.h"
57 #include "msn.h"
58 #include "mutt_account.h"
59 #include "mutt_globals.h"
60 #include "options.h"
61 #ifdef USE_HCACHE
62 #include "hcache/lib.h"
63 #include "message.h"
64 #endif
65 
74 int imap_adata_find(const char *path, struct ImapAccountData **adata,
75  struct ImapMboxData **mdata)
76 {
77  struct ConnAccount cac = { { 0 } };
78  struct ImapAccountData *tmp_adata = NULL;
79  char tmp[1024];
80 
81  if (imap_parse_path(path, &cac, tmp, sizeof(tmp)) < 0)
82  return -1;
83 
84  struct Account *np = NULL;
85  TAILQ_FOREACH(np, &NeoMutt->accounts, entries)
86  {
87  if (np->type != MUTT_IMAP)
88  continue;
89 
90  tmp_adata = np->adata;
91  if (!tmp_adata)
92  continue;
93  if (imap_account_match(&tmp_adata->conn->account, &cac))
94  {
95  *mdata = imap_mdata_new(tmp_adata, tmp);
96  *adata = tmp_adata;
97  return 0;
98  }
99  }
100  mutt_debug(LL_DEBUG3, "no ImapAccountData found\n");
101  return -1;
102 }
103 
109 {
110  mutt_hash_free(&mdata->uid_hash);
111  imap_msn_free(&mdata->msn);
112  mutt_bcache_close(&mdata->bcache);
113 }
114 
122 void imap_get_parent(const char *mbox, char delim, char *buf, size_t buflen)
123 {
124  /* Make a copy of the mailbox name, but only if the pointers are different */
125  if (mbox != buf)
126  mutt_str_copy(buf, mbox, buflen);
127 
128  int n = mutt_str_len(buf);
129 
130  /* Let's go backwards until the next delimiter
131  *
132  * If buf[n] is a '/', the first n-- will allow us
133  * to ignore it. If it isn't, then buf looks like
134  * "/aaaaa/bbbb". There is at least one "b", so we can't skip
135  * the "/" after the 'a's.
136  *
137  * If buf == '/', then n-- => n == 0, so the loop ends
138  * immediately */
139  for (n--; (n >= 0) && (buf[n] != delim); n--)
140  ; // do nothing
141 
142  /* We stopped before the beginning. There is a trailing slash. */
143  if (n > 0)
144  {
145  /* Strip the trailing delimiter. */
146  buf[n] = '\0';
147  }
148  else
149  {
150  buf[0] = (n == 0) ? delim : '\0';
151  }
152 }
153 
163 void imap_get_parent_path(const char *path, char *buf, size_t buflen)
164 {
165  struct ImapAccountData *adata = NULL;
166  struct ImapMboxData *mdata = NULL;
167  char mbox[1024];
168 
169  if (imap_adata_find(path, &adata, &mdata) < 0)
170  {
171  mutt_str_copy(buf, path, buflen);
172  return;
173  }
174 
175  /* Gets the parent mbox in mbox */
176  imap_get_parent(mdata->name, adata->delim, mbox, sizeof(mbox));
177 
178  /* Returns a fully qualified IMAP url */
179  imap_qualify_path(buf, buflen, &adata->conn->account, mbox);
180  imap_mdata_free((void *) &mdata);
181 }
182 
190 void imap_clean_path(char *path, size_t plen)
191 {
192  struct ImapAccountData *adata = NULL;
193  struct ImapMboxData *mdata = NULL;
194 
195  if (imap_adata_find(path, &adata, &mdata) < 0)
196  return;
197 
198  /* Returns a fully qualified IMAP url */
199  imap_qualify_path(path, plen, &adata->conn->account, mdata->name);
200  imap_mdata_free((void *) &mdata);
201 }
202 
206 static const char *imap_get_field(enum ConnAccountField field, void *gf_data)
207 {
208  switch (field)
209  {
210  case MUTT_CA_LOGIN:
211  return C_ImapLogin;
212  case MUTT_CA_USER:
213  return C_ImapUser;
214  case MUTT_CA_PASS:
215  return C_ImapPass;
216  case MUTT_CA_OAUTH_CMD:
218  case MUTT_CA_HOST:
219  default:
220  return NULL;
221  }
222 }
223 
224 #ifdef USE_HCACHE
225 
233 static void imap_msn_index_to_uid_seqset(struct Buffer *buf, struct ImapMboxData *mdata)
234 {
235  int first = 1, state = 0;
236  unsigned int cur_uid = 0, last_uid = 0;
237  unsigned int range_begin = 0, range_end = 0;
238  const size_t max_msn = imap_msn_highest(&mdata->msn);
239 
240  for (unsigned int msn = 1; msn <= max_msn + 1; msn++)
241  {
242  bool match = false;
243  if (msn <= max_msn)
244  {
245  struct Email *e_cur = imap_msn_get(&mdata->msn, msn - 1);
246  cur_uid = e_cur ? imap_edata_get(e_cur)->uid : 0;
247  if (!state || (cur_uid && ((cur_uid - 1) == last_uid)))
248  match = true;
249  last_uid = cur_uid;
250  }
251 
252  if (match)
253  {
254  switch (state)
255  {
256  case 1: /* single: convert to a range */
257  state = 2;
258  /* fall through */
259  case 2: /* extend range ending */
260  range_end = cur_uid;
261  break;
262  default:
263  state = 1;
264  range_begin = cur_uid;
265  break;
266  }
267  }
268  else if (state)
269  {
270  if (first)
271  first = 0;
272  else
273  mutt_buffer_addch(buf, ',');
274 
275  if (state == 1)
276  mutt_buffer_add_printf(buf, "%u", range_begin);
277  else if (state == 2)
278  mutt_buffer_add_printf(buf, "%u:%u", range_begin, range_end);
279 
280  state = 1;
281  range_begin = cur_uid;
282  }
283  }
284 }
285 
289 static void imap_hcache_namer(const char *path, struct Buffer *dest)
290 {
291  mutt_buffer_printf(dest, "%s.hcache", path);
292 }
293 
299 void imap_hcache_open(struct ImapAccountData *adata, struct ImapMboxData *mdata)
300 {
301  if (!adata || !mdata)
302  return;
303 
304  if (mdata->hcache)
305  return;
306 
307  struct HeaderCache *hc = NULL;
308  struct Buffer *mbox = mutt_buffer_pool_get();
309  struct Buffer *cachepath = mutt_buffer_pool_get();
310 
311  imap_cachepath(adata->delim, mdata->name, mbox);
312 
313  if (strstr(mutt_buffer_string(mbox), "/../") ||
314  mutt_str_equal(mutt_buffer_string(mbox), "..") ||
315  mutt_strn_equal(mutt_buffer_string(mbox), "../", 3))
316  {
317  goto cleanup;
318  }
319  size_t len = mutt_buffer_len(mbox);
320  if ((len > 3) && (strcmp(mutt_buffer_string(mbox) + len - 3, "/..") == 0))
321  goto cleanup;
322 
323  struct Url url = { 0 };
324  mutt_account_tourl(&adata->conn->account, &url);
325  url.path = mbox->data;
326  url_tobuffer(&url, cachepath, U_PATH);
327 
329 
330 cleanup:
332  mutt_buffer_pool_release(&cachepath);
333  mdata->hcache = hc;
334 }
335 
340 void imap_hcache_close(struct ImapMboxData *mdata)
341 {
342  if (!mdata->hcache)
343  return;
344 
345  mutt_hcache_close(mdata->hcache);
346  mdata->hcache = NULL;
347 }
348 
356 struct Email *imap_hcache_get(struct ImapMboxData *mdata, unsigned int uid)
357 {
358  if (!mdata->hcache)
359  return NULL;
360 
361  char key[16];
362 
363  sprintf(key, "/%u", uid);
364  struct HCacheEntry hce =
365  mutt_hcache_fetch(mdata->hcache, key, mutt_str_len(key), mdata->uidvalidity);
366  if (!hce.email && hce.uidvalidity)
367  {
368  mutt_debug(LL_DEBUG3, "hcache uidvalidity mismatch: %u\n", hce.uidvalidity);
369  }
370 
371  return hce.email;
372 }
373 
381 int imap_hcache_put(struct ImapMboxData *mdata, struct Email *e)
382 {
383  if (!mdata->hcache)
384  return -1;
385 
386  char key[16];
387 
388  sprintf(key, "/%u", imap_edata_get(e)->uid);
389  return mutt_hcache_store(mdata->hcache, key, mutt_str_len(key), e, mdata->uidvalidity);
390 }
391 
399 int imap_hcache_del(struct ImapMboxData *mdata, unsigned int uid)
400 {
401  if (!mdata->hcache)
402  return -1;
403 
404  char key[16];
405 
406  sprintf(key, "/%u", uid);
407  return mutt_hcache_delete_record(mdata->hcache, key, mutt_str_len(key));
408 }
409 
417 {
418  if (!mdata->hcache)
419  return -1;
420 
421  /* The seqset is likely large. Preallocate to reduce reallocs */
422  struct Buffer buf = mutt_buffer_make(8192);
423  imap_msn_index_to_uid_seqset(&buf, mdata);
424 
425  int rc = mutt_hcache_store_raw(mdata->hcache, "/UIDSEQSET", 10, buf.data,
426  mutt_buffer_len(&buf) + 1);
427  mutt_debug(LL_DEBUG3, "Stored /UIDSEQSET %s\n", buf.data);
428  mutt_buffer_dealloc(&buf);
429  return rc;
430 }
431 
439 {
440  if (!mdata->hcache)
441  return -1;
442 
443  return mutt_hcache_delete_record(mdata->hcache, "/UIDSEQSET", 10);
444 }
445 
453 {
454  if (!mdata->hcache)
455  return NULL;
456 
457  char *seqset = NULL;
458  size_t dlen = 0;
459  char *hc_seqset = mutt_hcache_fetch_raw(mdata->hcache, "/UIDSEQSET", 10, &dlen);
460  if (hc_seqset)
461  {
462  seqset = mutt_strn_dup(hc_seqset, dlen);
463  mutt_hcache_free_raw(mdata->hcache, (void **) &hc_seqset);
464  }
465  mutt_debug(LL_DEBUG3, "Retrieved /UIDSEQSET %s\n", NONULL(seqset));
466 
467  return seqset;
468 }
469 #endif
470 
483 int imap_parse_path(const char *path, struct ConnAccount *cac, char *mailbox, size_t mailboxlen)
484 {
485  static unsigned short ImapPort = 0;
486  static unsigned short ImapsPort = 0;
487 
488  if (ImapPort == 0)
489  {
490  struct servent *service = getservbyname("imap", "tcp");
491  if (service)
492  ImapPort = ntohs(service->s_port);
493  else
494  ImapPort = IMAP_PORT;
495  mutt_debug(LL_DEBUG3, "Using default IMAP port %d\n", ImapPort);
496  }
497 
498  if (ImapsPort == 0)
499  {
500  struct servent *service = getservbyname("imaps", "tcp");
501  if (service)
502  ImapsPort = ntohs(service->s_port);
503  else
504  ImapsPort = IMAP_SSL_PORT;
505  mutt_debug(LL_DEBUG3, "Using default IMAPS port %d\n", ImapsPort);
506  }
507 
508  /* Defaults */
509  cac->port = ImapPort;
510  cac->type = MUTT_ACCT_TYPE_IMAP;
511  cac->service = "imap";
512  cac->get_field = imap_get_field;
513 
514  struct Url *url = url_parse(path);
515  if (!url)
516  return -1;
517 
518  if ((url->scheme != U_IMAP) && (url->scheme != U_IMAPS))
519  {
520  url_free(&url);
521  return -1;
522  }
523 
524  if ((mutt_account_fromurl(cac, url) < 0) || (cac->host[0] == '\0'))
525  {
526  url_free(&url);
527  return -1;
528  }
529 
530  if (url->scheme == U_IMAPS)
531  cac->flags |= MUTT_ACCT_SSL;
532 
533  mutt_str_copy(mailbox, url->path, mailboxlen);
534 
535  url_free(&url);
536 
537  if ((cac->flags & MUTT_ACCT_SSL) && !(cac->flags & MUTT_ACCT_PORT))
538  cac->port = ImapsPort;
539 
540  return 0;
541 }
542 
554 int imap_mxcmp(const char *mx1, const char *mx2)
555 {
556  char *b1 = NULL;
557  char *b2 = NULL;
558  int rc;
559 
560  if (!mx1 || (*mx1 == '\0'))
561  mx1 = "INBOX";
562  if (!mx2 || (*mx2 == '\0'))
563  mx2 = "INBOX";
564  if (mutt_istr_equal(mx1, "INBOX") && mutt_istr_equal(mx2, "INBOX"))
565  {
566  return 0;
567  }
568 
569  b1 = mutt_mem_malloc(strlen(mx1) + 1);
570  b2 = mutt_mem_malloc(strlen(mx2) + 1);
571 
572  imap_fix_path('\0', mx1, b1, strlen(mx1) + 1);
573  imap_fix_path('\0', mx2, b2, strlen(mx2) + 1);
574 
575  rc = mutt_str_cmp(b1, b2);
576  FREE(&b1);
577  FREE(&b2);
578 
579  return rc;
580 }
581 
590 void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder)
591 {
592  struct ConnAccount cac_target = { { 0 } };
593  struct ConnAccount cac_home = { { 0 } };
594  struct Url url = { 0 };
595  char *delim = NULL;
596  int tlen;
597  int hlen = 0;
598  bool home_match = false;
599  char target_mailbox[1024];
600  char home_mailbox[1024];
601 
602  if (imap_parse_path(path, &cac_target, target_mailbox, sizeof(target_mailbox)) < 0)
603  return;
604 
605  if (imap_path_probe(folder, NULL) != MUTT_IMAP)
606  goto fallback;
607 
608  if (imap_parse_path(folder, &cac_home, home_mailbox, sizeof(home_mailbox)) < 0)
609  goto fallback;
610 
611  tlen = mutt_str_len(target_mailbox);
612  hlen = mutt_str_len(home_mailbox);
613 
614  /* check whether we can do '+' substitution */
615  if (tlen && imap_account_match(&cac_home, &cac_target) &&
616  mutt_strn_equal(home_mailbox, target_mailbox, hlen))
617  {
618  if (hlen == 0)
619  home_match = true;
620  else if (C_ImapDelimChars)
621  {
622  for (delim = C_ImapDelimChars; *delim != '\0'; delim++)
623  if (target_mailbox[hlen] == *delim)
624  home_match = true;
625  }
626  }
627 
628  /* do the '+' substitution */
629  if (home_match)
630  {
631  *path++ = '+';
632  /* copy remaining path, skipping delimiter */
633  if (hlen == 0)
634  hlen = -1;
635  memcpy(path, target_mailbox + hlen + 1, tlen - hlen - 1);
636  path[tlen - hlen - 1] = '\0';
637  return;
638  }
639 
640 fallback:
641  mutt_account_tourl(&cac_target, &url);
642  url.path = target_mailbox;
643  url_tostring(&url, path, pathlen, U_NO_FLAGS);
644 }
645 
652 enum QuadOption imap_continue(const char *msg, const char *resp)
653 {
654  imap_error(msg, resp);
655  return mutt_yesorno(_("Continue?"), MUTT_NO);
656 }
657 
663 void imap_error(const char *where, const char *msg)
664 {
665  mutt_error("%s [%s]", where, msg);
666 }
667 
685 char *imap_fix_path(char delim, const char *mailbox, char *path, size_t plen)
686 {
687  int i = 0;
688  for (; mailbox && *mailbox && (i < plen - 1); i++)
689  {
690  if (*mailbox == delim || (!delim && strchr(NONULL(C_ImapDelimChars), *mailbox)))
691  {
692  delim = *mailbox;
693  /* Skip multiple occurrences of delim */
694  while (*mailbox && *(mailbox + 1) == delim)
695  mailbox++;
696  }
697  path[i] = *mailbox++;
698  }
699 
700  /* Do not terminate with a delimiter */
701  if (i && path[i - 1] == delim)
702  i--;
703 
704  /* Ensure null termination */
705  path[i] = '\0';
706  return path;
707 }
708 
715 void imap_cachepath(char delim, const char *mailbox, struct Buffer *dest)
716 {
717  const char *p = mailbox;
718  mutt_buffer_reset(dest);
719  if (!p)
720  return;
721 
722  while (*p)
723  {
724  if (p[0] == delim)
725  {
726  mutt_buffer_addch(dest, '/');
727  /* simple way to avoid collisions with UIDs */
728  if ((p[1] >= '0') && (p[1] <= '9'))
729  mutt_buffer_addch(dest, '_');
730  }
731  else
732  mutt_buffer_addch(dest, *p);
733  p++;
734  }
735 }
736 
744 int imap_get_literal_count(const char *buf, unsigned int *bytes)
745 {
746  char *pc = NULL;
747  char *pn = NULL;
748 
749  if (!buf || !(pc = strchr(buf, '{')))
750  return -1;
751 
752  pc++;
753  pn = pc;
754  while (isdigit((unsigned char) *pc))
755  pc++;
756  *pc = '\0';
757  if (mutt_str_atoui(pn, bytes) < 0)
758  return -1;
759 
760  return 0;
761 }
762 
771 char *imap_get_qualifier(char *buf)
772 {
773  char *s = buf;
774 
775  /* skip tag */
776  s = imap_next_word(s);
777  /* skip OK/NO/BAD response */
778  s = imap_next_word(s);
779 
780  return s;
781 }
782 
788 char *imap_next_word(char *s)
789 {
790  bool quoted = false;
791 
792  while (*s)
793  {
794  if (*s == '\\')
795  {
796  s++;
797  if (*s)
798  s++;
799  continue;
800  }
801  if (*s == '\"')
802  quoted = !quoted;
803  if (!quoted && IS_SPACE(*s))
804  break;
805  s++;
806  }
807 
808  SKIPWS(s);
809  return s;
810 }
811 
819 void imap_qualify_path(char *buf, size_t buflen, struct ConnAccount *cac, char *path)
820 {
821  struct Url url = { 0 };
822  mutt_account_tourl(cac, &url);
823  url.path = path;
824  url_tostring(&url, buf, buflen, U_NO_FLAGS);
825 }
826 
836 void imap_quote_string(char *dest, size_t dlen, const char *src, bool quote_backtick)
837 {
838  const char *quote = "`\"\\";
839  if (!quote_backtick)
840  quote++;
841 
842  char *pt = dest;
843  const char *s = src;
844 
845  *pt++ = '"';
846  /* save room for quote-chars */
847  dlen -= 3;
848 
849  for (; *s && dlen; s++)
850  {
851  if (strchr(quote, *s))
852  {
853  if (dlen < 2)
854  break;
855  dlen -= 2;
856  *pt++ = '\\';
857  *pt++ = *s;
858  }
859  else
860  {
861  *pt++ = *s;
862  dlen--;
863  }
864  }
865  *pt++ = '"';
866  *pt = '\0';
867 }
868 
873 void imap_unquote_string(char *s)
874 {
875  char *d = s;
876 
877  if (*s == '\"')
878  s++;
879  else
880  return;
881 
882  while (*s)
883  {
884  if (*s == '\"')
885  {
886  *d = '\0';
887  return;
888  }
889  if (*s == '\\')
890  {
891  s++;
892  }
893  if (*s)
894  {
895  *d = *s;
896  d++;
897  s++;
898  }
899  }
900  *d = '\0';
901 }
902 
910 void imap_munge_mbox_name(bool unicode, char *dest, size_t dlen, const char *src)
911 {
912  char *buf = mutt_str_dup(src);
913  imap_utf_encode(unicode, &buf);
914 
915  imap_quote_string(dest, dlen, buf, false);
916 
917  FREE(&buf);
918 }
919 
927 void imap_unmunge_mbox_name(bool unicode, char *s)
928 {
930 
931  char *buf = mutt_str_dup(s);
932  if (buf)
933  {
934  imap_utf_decode(unicode, &buf);
935  strncpy(s, buf, strlen(s));
936  }
937 
938  FREE(&buf);
939 }
940 
944 void imap_keepalive(void)
945 {
946  time_t now = mutt_date_epoch();
947  struct Account *np = NULL;
948  TAILQ_FOREACH(np, &NeoMutt->accounts, entries)
949  {
950  if (np->type != MUTT_IMAP)
951  continue;
952 
953  struct ImapAccountData *adata = np->adata;
954  if (!adata || !adata->mailbox)
955  continue;
956 
957  if ((adata->state >= IMAP_AUTHENTICATED) && (now >= (adata->lastread + C_ImapKeepalive)))
958  imap_check_mailbox(adata->mailbox, true);
959  }
960 }
961 
967 int imap_wait_keepalive(pid_t pid)
968 {
969  struct sigaction oldalrm;
970  struct sigaction act;
971  sigset_t oldmask;
972  int rc;
973 
974  bool imap_passive = C_ImapPassive;
975 
976  C_ImapPassive = true;
977  OptKeepQuiet = true;
978 
979  sigprocmask(SIG_SETMASK, NULL, &oldmask);
980 
981  sigemptyset(&act.sa_mask);
982  act.sa_handler = mutt_sig_empty_handler;
983 #ifdef SA_INTERRUPT
984  act.sa_flags = SA_INTERRUPT;
985 #else
986  act.sa_flags = 0;
987 #endif
988 
989  sigaction(SIGALRM, &act, &oldalrm);
990 
991  alarm(C_ImapKeepalive);
992  while ((waitpid(pid, &rc, 0) < 0) && (errno == EINTR))
993  {
994  alarm(0); /* cancel a possibly pending alarm */
995  imap_keepalive();
996  alarm(C_ImapKeepalive);
997  }
998 
999  alarm(0); /* cancel a possibly pending alarm */
1000 
1001  sigaction(SIGALRM, &oldalrm, NULL);
1002  sigprocmask(SIG_SETMASK, &oldmask, NULL);
1003 
1004  OptKeepQuiet = false;
1005  if (!imap_passive)
1006  C_ImapPassive = false;
1007 
1008  return rc;
1009 }
1010 
1016 {
1017  struct ImapAccountData *adata = imap_adata_get(m);
1018  struct ImapMboxData *mdata = imap_mdata_get(m);
1019  if (!adata || !adata->mailbox || (adata->mailbox != m) || !mdata)
1020  return;
1021  mdata->reopen |= IMAP_REOPEN_ALLOW;
1022 }
1023 
1029 {
1030  struct ImapAccountData *adata = imap_adata_get(m);
1031  struct ImapMboxData *mdata = imap_mdata_get(m);
1032  if (!adata || !adata->mailbox || (adata->mailbox != m) || !mdata)
1033  return;
1034  mdata->reopen &= ~IMAP_REOPEN_ALLOW;
1035 }
1036 
1043 bool imap_account_match(const struct ConnAccount *a1, const struct ConnAccount *a2)
1044 {
1045  if (!a1 || !a2)
1046  return false;
1047  if (a1->type != a2->type)
1048  return false;
1049  if (!mutt_istr_equal(a1->host, a2->host))
1050  return false;
1051  if ((a1->port != 0) && (a2->port != 0) && (a1->port != a2->port))
1052  return false;
1053  if (a1->flags & a2->flags & MUTT_ACCT_USER)
1054  return strcmp(a1->user, a2->user) == 0;
1055 
1056  const char *user = NONULL(Username);
1057 
1058  if ((a1->type == MUTT_ACCT_TYPE_IMAP) && C_ImapUser)
1059  user = C_ImapUser;
1060 
1061  if (a1->flags & MUTT_ACCT_USER)
1062  return strcmp(a1->user, user) == 0;
1063  if (a2->flags & MUTT_ACCT_USER)
1064  return strcmp(a2->user, user) == 0;
1065 
1066  return true;
1067 }
1068 
1074 struct SeqsetIterator *mutt_seqset_iterator_new(const char *seqset)
1075 {
1076  if (!seqset || (*seqset == '\0'))
1077  return NULL;
1078 
1079  struct SeqsetIterator *iter = mutt_mem_calloc(1, sizeof(struct SeqsetIterator));
1080  iter->full_seqset = mutt_str_dup(seqset);
1081  iter->eostr = strchr(iter->full_seqset, '\0');
1082  iter->substr_cur = iter->substr_end = iter->full_seqset;
1083 
1084  return iter;
1085 }
1086 
1095 int mutt_seqset_iterator_next(struct SeqsetIterator *iter, unsigned int *next)
1096 {
1097  if (!iter || !next)
1098  return -1;
1099 
1100  if (iter->in_range)
1101  {
1102  if ((iter->down && (iter->range_cur == (iter->range_end - 1))) ||
1103  (!iter->down && (iter->range_cur == (iter->range_end + 1))))
1104  {
1105  iter->in_range = 0;
1106  }
1107  }
1108 
1109  if (!iter->in_range)
1110  {
1111  iter->substr_cur = iter->substr_end;
1112  if (iter->substr_cur == iter->eostr)
1113  return 1;
1114 
1115  while (!*(iter->substr_cur))
1116  iter->substr_cur++;
1117  iter->substr_end = strchr(iter->substr_cur, ',');
1118  if (!iter->substr_end)
1119  iter->substr_end = iter->eostr;
1120  else
1121  *(iter->substr_end) = '\0';
1122 
1123  char *range_sep = strchr(iter->substr_cur, ':');
1124  if (range_sep)
1125  *range_sep++ = '\0';
1126 
1127  if (mutt_str_atoui(iter->substr_cur, &iter->range_cur) != 0)
1128  return -1;
1129  if (range_sep)
1130  {
1131  if (mutt_str_atoui(range_sep, &iter->range_end) != 0)
1132  return -1;
1133  }
1134  else
1135  iter->range_end = iter->range_cur;
1136 
1137  iter->down = (iter->range_end < iter->range_cur);
1138  iter->in_range = 1;
1139  }
1140 
1141  *next = iter->range_cur;
1142  if (iter->down)
1143  iter->range_cur--;
1144  else
1145  iter->range_cur++;
1146 
1147  return 0;
1148 }
1149 
1155 {
1156  if (!ptr || !*ptr)
1157  return;
1158 
1159  struct SeqsetIterator *iter = *ptr;
1160  FREE(&iter->full_seqset);
1161  FREE(ptr);
1162 }
Url::src
char * src
Raw URL string.
Definition: url.h:76
ImapMboxData::hcache
struct HeaderCache * hcache
Definition: mdata.h:62
SeqsetIterator::range_cur
unsigned int range_cur
Definition: private.h:176
imap_utf_decode
void imap_utf_decode(bool unicode, char **s)
Decode email from UTF-8 to local charset.
Definition: utf7.c:345
SeqsetIterator::range_end
unsigned int range_end
Definition: private.h:177
C_ImapDelimChars
char * C_ImapDelimChars
Config: (imap) Characters that denote separators in IMAP folders.
Definition: config.c:45
ConnAccount
Login details for a remote server.
Definition: connaccount.h:51
imap_hcache_get_uid_seqset
char * imap_hcache_get_uid_seqset(struct ImapMboxData *mdata)
Get a UID Sequence Set from the header cache.
Definition: util.c:452
C_ImapKeepalive
short C_ImapKeepalive
Config: (imap) Time to wait before polling an open IMAP connection.
Definition: config.c:49
mutt_hcache_open
struct HeaderCache * mutt_hcache_open(const char *path, const char *folder, hcache_namer_t namer)
Multiplexor for StoreOps::open.
Definition: hcache.c:322
imap_mdata_cache_reset
void imap_mdata_cache_reset(struct ImapMboxData *mdata)
Release and clear cache data of ImapMboxData structure.
Definition: util.c:108
imap_unmunge_mbox_name
void imap_unmunge_mbox_name(bool unicode, char *s)
Remove quoting from a mailbox name.
Definition: util.c:927
QuadOption
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
msn.h
ConnAccount::host
char host[128]
Server to login to.
Definition: connaccount.h:53
U_IMAP
@ U_IMAP
Url is imap://.
Definition: url.h:38
mutt_mem_calloc
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
NeoMutt::accounts
struct AccountList accounts
List of all Accounts.
Definition: neomutt.h:40
mutt_account_fromurl
int mutt_account_fromurl(struct ConnAccount *cac, const struct Url *url)
Fill ConnAccount with information from url.
Definition: mutt_account.c:43
_
#define _(a)
Definition: message.h:28
NONULL
#define NONULL(x)
Definition: string2.h:37
adata.h
Mailbox
A mailbox.
Definition: mailbox.h:81
mutt_hcache_store_raw
int mutt_hcache_store_raw(struct HeaderCache *hc, const char *key, size_t keylen, void *data, size_t dlen)
store a key / data pair
Definition: hcache.c:584
mutt_strn_equal
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:593
imap_hcache_open
void imap_hcache_open(struct ImapAccountData *adata, struct ImapMboxData *mdata)
Open a header cache.
Definition: util.c:299
imap_hcache_del
int imap_hcache_del(struct ImapMboxData *mdata, unsigned int uid)
Delete an item from the header cache.
Definition: util.c:399
MUTT_ACCT_PORT
#define MUTT_ACCT_PORT
Port field has been set.
Definition: connaccount.h:42
imap_mdata_free
void imap_mdata_free(void **ptr)
Free the private Mailbox data - Implements Mailbox::mdata_free()
Definition: mdata.c:36
ImapMboxData::uid_hash
struct HashTable * uid_hash
Definition: mdata.h:58
Buffer
String manipulation buffer.
Definition: buffer.h:33
Account::type
enum MailboxType type
Type of Mailboxes this Account contains.
Definition: account.h:38
LL_DEBUG3
@ LL_DEBUG3
Log at debug level 3.
Definition: logging.h:42
Connection::account
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:36
ConnAccount::get_field
const char *(* get_field)(enum ConnAccountField field, void *gf_data)
Function to get some login credentials.
Definition: connaccount.h:67
imap_continue
enum QuadOption imap_continue(const char *msg, const char *resp)
display a message and ask the user if they want to go on
Definition: util.c:652
mutt_buffer_dealloc
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
imap_msn_index_to_uid_seqset
static void imap_msn_index_to_uid_seqset(struct Buffer *buf, struct ImapMboxData *mdata)
Convert MSN index of UIDs to Seqset.
Definition: util.c:233
imap_hcache_clear_uid_seqset
int imap_hcache_clear_uid_seqset(struct ImapMboxData *mdata)
Delete a UID Sequence Set from the header cache.
Definition: util.c:438
IMAP_SSL_PORT
#define IMAP_SSL_PORT
Port for IMAP over SSL/TLS.
Definition: private.h:48
mutt_buffer_add_printf
int mutt_buffer_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:203
imap_wait_keepalive
int imap_wait_keepalive(pid_t pid)
Wait for a process to change state.
Definition: util.c:967
mutt_account_tourl
void mutt_account_tourl(struct ConnAccount *cac, struct Url *url)
Fill URL with info from account.
Definition: mutt_account.c:79
imap_mdata_new
struct ImapMboxData * imap_mdata_new(struct ImapAccountData *adata, const char *name)
Allocate and initialise a new ImapMboxData structure.
Definition: mdata.c:68
U_NO_FLAGS
#define U_NO_FLAGS
Definition: url.h:48
IMAP_PORT
#define IMAP_PORT
Default port for IMAP.
Definition: private.h:47
mutt_account.h
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
Url::scheme
enum UrlScheme scheme
Scheme, e.g. U_SMTPS.
Definition: url.h:69
lib.h
mutt_str_dup
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
imap_allow_reopen
void imap_allow_reopen(struct Mailbox *m)
Allow re-opening a folder upon expunge.
Definition: util.c:1015
mutt_globals.h
imap_disallow_reopen
void imap_disallow_reopen(struct Mailbox *m)
Disallow re-opening a folder upon expunge.
Definition: util.c:1028
FREE
#define FREE(x)
Definition: memory.h:40
options.h
imap_next_word
char * imap_next_word(char *s)
Find where the next IMAP word begins.
Definition: util.c:788
SeqsetIterator::substr_cur
char * substr_cur
Definition: private.h:178
Email::path
char * path
Path of Email (for local Mailboxes)
Definition: email.h:92
mdata.h
C_ImapPass
char * C_ImapPass
Config: (imap) Password for the IMAP server.
Definition: config.c:53
private.h
mutt_buffer_reset
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
mutt_buffer_pool_release
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
Username
WHERE char * Username
User's login name.
Definition: mutt_globals.h:52
imap_adata_get
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:86
mutt_sig_empty_handler
void mutt_sig_empty_handler(int sig)
Dummy signal handler.
Definition: signal.c:57
C_ImapLogin
char * C_ImapLogin
Config: (imap) Login name for the IMAP server (defaults to $imap_user)
Definition: config.c:51
lib.h
url_parse
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:234
ImapAccountData::conn
struct Connection * conn
Definition: adata.h:38
SeqsetIterator::in_range
int in_range
Definition: private.h:174
SKIPWS
#define SKIPWS(ch)
Definition: string2.h:46
mutt_istr_equal
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
mutt_str_equal
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
lib.h
SeqsetIterator::full_seqset
char * full_seqset
Definition: private.h:172
mutt_seqset_iterator_new
struct SeqsetIterator * mutt_seqset_iterator_new(const char *seqset)
Create a new Sequence Set Iterator.
Definition: util.c:1074
SeqsetIterator::down
int down
Definition: private.h:175
mutt_buffer_addch
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
imap_hcache_get
struct Email * imap_hcache_get(struct ImapMboxData *mdata, unsigned int uid)
Get a header cache entry by its UID.
Definition: util.c:356
mutt_buffer_pool_get
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
imap_adata_find
int imap_adata_find(const char *path, struct ImapAccountData **adata, struct ImapMboxData **mdata)
Find the Account data for this path.
Definition: util.c:74
Mailbox::mdata
void * mdata
Driver specific data.
Definition: mailbox.h:136
url_tostring
int url_tostring(struct Url *url, char *dest, size_t len, uint8_t flags)
Output the URL string for a given Url object.
Definition: url.c:418
U_PATH
#define U_PATH
Definition: url.h:49
imap_msn_get
struct Email * imap_msn_get(const struct MSN *msn, size_t idx)
Return the Email associated with an msn.
Definition: msn.c:80
imap_utf_encode
void imap_utf_encode(bool unicode, char **s)
Encode email from local charset to UTF-8.
Definition: utf7.c:316
MUTT_CA_PASS
@ MUTT_CA_PASS
Password.
Definition: connaccount.h:36
ConnAccountField
ConnAccountField
Login credentials.
Definition: connaccount.h:31
lib.h
Account
A group of associated Mailboxes.
Definition: account.h:36
imap_error
void imap_error(const char *where, const char *msg)
show an error and abort
Definition: util.c:663
imap_get_literal_count
int imap_get_literal_count(const char *buf, unsigned int *bytes)
write number of bytes in an IMAP literal into bytes
Definition: util.c:744
MUTT_CA_HOST
@ MUTT_CA_HOST
Server name.
Definition: connaccount.h:33
Url
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:67
MUTT_ACCT_TYPE_IMAP
@ MUTT_ACCT_TYPE_IMAP
Imap Account.
Definition: mutt_account.h:37
lib.h
url_free
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition: url.c:123
message.h
imap_clean_path
void imap_clean_path(char *path, size_t plen)
Cleans an IMAP path using imap_fix_path.
Definition: util.c:190
ImapEmailData::uid
unsigned int uid
32-bit Message UID
Definition: edata.h:44
ImapMboxData::bcache
struct BodyCache * bcache
Definition: mdata.h:60
U_IMAPS
@ U_IMAPS
Url is imaps://.
Definition: url.h:39
mutt_hcache_free_raw
void mutt_hcache_free_raw(struct HeaderCache *hc, void **data)
Multiplexor for StoreOps::free.
Definition: hcache.c:514
MUTT_IMAP
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:53
url_tobuffer
int url_tobuffer(struct Url *url, struct Buffer *buf, uint8_t flags)
Output the URL string for a given Url object.
Definition: url.c:353
SeqsetIterator::eostr
char * eostr
Definition: private.h:173
HCacheEntry::email
struct Email * email
Retrieved email.
Definition: lib.h:100
ConnAccount::type
unsigned char type
Connection type, e.g. MUTT_ACCT_TYPE_IMAP.
Definition: connaccount.h:58
mutt_debug
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
mutt_bcache_close
void mutt_bcache_close(struct BodyCache **bcache)
Close an Email-Body Cache.
Definition: bcache.c:165
MUTT_NO
@ MUTT_NO
User answered 'No', or assume 'No'.
Definition: quad.h:39
imap_msn_free
void imap_msn_free(struct MSN *msn)
Free the cache.
Definition: msn.c:59
HCacheEntry
Wrapper for Email retrieved from the header cache.
Definition: lib.h:96
C_ImapOauthRefreshCommand
char * C_ImapOauthRefreshCommand
Config: (imap) External command to generate OAUTH refresh token.
Definition: config.c:52
mutt_str_len
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
MUTT_ACCT_USER
#define MUTT_ACCT_USER
User field has been set.
Definition: connaccount.h:43
mutt_buffer_string
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
ConnAccount::flags
MuttAccountFlags flags
Which fields are initialised, e.g. MUTT_ACCT_USER.
Definition: connaccount.h:59
C_ImapUser
char * C_ImapUser
Config: (imap) Username for the IMAP server.
Definition: config.c:61
mutt_date_epoch
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:416
ImapAccountData
IMAP-specific Account data -.
Definition: adata.h:36
imap_get_parent
void imap_get_parent(const char *mbox, char delim, char *buf, size_t buflen)
Get an IMAP folder's parent.
Definition: util.c:122
mutt_seqset_iterator_free
void mutt_seqset_iterator_free(struct SeqsetIterator **ptr)
Free a Sequence Set Iterator.
Definition: util.c:1154
lib.h
ImapMboxData
IMAP-specific Mailbox data -.
Definition: mdata.h:38
lib.h
mutt_hcache_store
int mutt_hcache_store(struct HeaderCache *hc, const char *key, size_t keylen, struct Email *e, uint32_t uidvalidity)
Multiplexor for StoreOps::store.
Definition: hcache.c:527
imap_msn_highest
size_t imap_msn_highest(const struct MSN *msn)
Return the highest MSN in use.
Definition: msn.c:69
mutt_str_cmp
int mutt_str_cmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:567
imap_pretty_mailbox
void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder)
Prettify an IMAP mailbox name.
Definition: util.c:590
MUTT_CA_LOGIN
@ MUTT_CA_LOGIN
Login name.
Definition: connaccount.h:34
MUTT_ACCT_SSL
#define MUTT_ACCT_SSL
Account uses SSL/TLS.
Definition: connaccount.h:46
imap_keepalive
void imap_keepalive(void)
poll the current folder to keep the connection alive
Definition: util.c:944
C_ImapPassive
bool C_ImapPassive
Config: (imap) Reuse an existing IMAP connection to check for new mail.
Definition: config.c:54
HeaderCache
header cache structure
Definition: lib.h:85
mutt_seqset_iterator_next
int mutt_seqset_iterator_next(struct SeqsetIterator *iter, unsigned int *next)
Get the next UID from a Sequence Set.
Definition: util.c:1095
imap_qualify_path
void imap_qualify_path(char *buf, size_t buflen, struct ConnAccount *cac, char *path)
Make an absolute IMAP folder target.
Definition: util.c:819
imap_hcache_store_uid_seqset
int imap_hcache_store_uid_seqset(struct ImapMboxData *mdata)
Store a UID Sequence Set in the header cache.
Definition: util.c:416
ConnAccount::port
unsigned short port
Port to connect to.
Definition: connaccount.h:57
mutt_mem_malloc
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
mutt_strn_dup
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:548
imap_quote_string
void imap_quote_string(char *dest, size_t dlen, const char *src, bool quote_backtick)
quote string according to IMAP rules
Definition: util.c:836
NeoMutt
Container for Accounts, Notifications.
Definition: neomutt.h:36
mutt_hcache_delete_record
int mutt_hcache_delete_record(struct HeaderCache *hc, const char *key, size_t keylen)
Multiplexor for StoreOps::delete_record.
Definition: hcache.c:604
ImapAccountData::mailbox
struct Mailbox * mailbox
Current selected mailbox.
Definition: adata.h:73
imap_unquote_string
void imap_unquote_string(char *s)
equally stupid unquoting routine
Definition: util.c:873
imap_cachepath
void imap_cachepath(char delim, const char *mailbox, struct Buffer *dest)
Generate a cache path for a mailbox.
Definition: util.c:715
C_HeaderCache
char * C_HeaderCache
Config: (hcache) Directory/file for the header cache database.
Definition: config.c:40
imap_path_probe
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2372
imap_mdata_get
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: mdata.c:55
mutt_buffer_len
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:356
Account::adata
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
imap_account_match
bool imap_account_match(const struct ConnAccount *a1, const struct ConnAccount *a2)
Compare two Accounts.
Definition: util.c:1043
plen
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
OptKeepQuiet
WHERE bool OptKeepQuiet
(pseudo) shut up the message and refresh functions while we are executing an external program
Definition: options.h:39
IMAP_AUTHENTICATED
@ IMAP_AUTHENTICATED
Connection is authenticated.
Definition: private.h:111
SeqsetIterator::substr_end
char * substr_end
Definition: private.h:179
ConnAccount::service
const char * service
Name of the service, e.g. "imap".
Definition: connaccount.h:60
Url::path
char * path
Path.
Definition: url.h:74
mutt_hcache_fetch_raw
void * mutt_hcache_fetch_raw(struct HeaderCache *hc, const char *key, size_t keylen, size_t *dlen)
Fetch a message's header from the cache.
Definition: hcache.c:496
HCacheEntry::uidvalidity
uint32_t uidvalidity
IMAP-specific UIDVALIDITY.
Definition: lib.h:98
imap_fix_path
char * imap_fix_path(char delim, const char *mailbox, char *path, size_t plen)
Fix up the imap path.
Definition: util.c:685
lib.h
mutt_str_atoui
int mutt_str_atoui(const char *str, unsigned int *dst)
Convert ASCII string to an unsigned integer.
Definition: string.c:282
imap_hcache_put
int imap_hcache_put(struct ImapMboxData *mdata, struct Email *e)
Add an entry to the header cache.
Definition: util.c:381
mutt_hcache_close
void mutt_hcache_close(struct HeaderCache *hc)
Multiplexor for StoreOps::close.
Definition: hcache.c:419
imap_hcache_close
void imap_hcache_close(struct ImapMboxData *mdata)
Close the header cache.
Definition: util.c:340
MUTT_CA_USER
@ MUTT_CA_USER
User name.
Definition: connaccount.h:35
mutt_yesorno
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:380
Buffer::data
char * data
Pointer to data.
Definition: buffer.h:35
IS_SPACE
#define IS_SPACE(ch)
Definition: string2.h:38
Email
The envelope/body of an email.
Definition: email.h:37
SeqsetIterator
UID Sequence Set Iterator.
Definition: private.h:170
lib.h
edata.h
imap_mxcmp
int imap_mxcmp(const char *mx1, const char *mx2)
Compare mailbox names, giving priority to INBOX.
Definition: util.c:554
mutt_buffer_printf
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
imap_edata_get
struct ImapEmailData * imap_edata_get(struct Email *e)
Get the private data for this Email.
Definition: edata.c:63
imap_hcache_namer
static void imap_hcache_namer(const char *path, struct Buffer *dest)
Generate a filename for the header cache - Implements hcache_namer_t.
Definition: util.c:289
mutt_buffer_make
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
imap_get_qualifier
char * imap_get_qualifier(char *buf)
Get the qualifier from a tagged response.
Definition: util.c:771
ConnAccount::user
char user[128]
Username.
Definition: connaccount.h:55
MUTT_CA_OAUTH_CMD
@ MUTT_CA_OAUTH_CMD
OAuth refresh command.
Definition: connaccount.h:37
mutt_hash_free
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:447
ImapMboxData::uidvalidity
uint32_t uidvalidity
Definition: mdata.h:50
ImapMboxData::name
char * name
Mailbox name.
Definition: mdata.h:40
imap_check_mailbox
enum MxStatus imap_check_mailbox(struct Mailbox *m, bool force)
use the NOOP or IDLE command to poll for new mail
Definition: imap.c:1094
imap_parse_path
int imap_parse_path(const char *path, struct ConnAccount *cac, char *mailbox, size_t mailboxlen)
Parse an IMAP mailbox name into ConnAccount, name.
Definition: util.c:483
imap_get_parent_path
void imap_get_parent_path(const char *path, char *buf, size_t buflen)
Get the path of the parent folder.
Definition: util.c:163
IMAP_REOPEN_ALLOW
#define IMAP_REOPEN_ALLOW
Allow re-opening a folder upon expunge.
Definition: private.h:68
ImapAccountData::delim
char delim
Definition: adata.h:72
mutt_error
#define mutt_error(...)
Definition: logging.h:84
imap_get_field
static const char * imap_get_field(enum ConnAccountField field, void *gf_data)
Get connection login credentials - Implements ConnAccount::get_field()
Definition: util.c:206
mutt_hcache_fetch
struct HCacheEntry mutt_hcache_fetch(struct HeaderCache *hc, const char *key, size_t keylen, uint32_t uidvalidity)
Multiplexor for StoreOps::fetch.
Definition: hcache.c:438
mutt_str_copy
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:716
imap_munge_mbox_name
void imap_munge_mbox_name(bool unicode, char *dest, size_t dlen, const char *src)
Quote awkward characters in a mailbox name.
Definition: util.c:910