NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
graphviz.c
Go to the documentation of this file.
1 
29 #include "config.h"
30 #include <stdbool.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <sys/stat.h>
34 #include <time.h>
35 #include "mutt/lib.h"
36 #include "address/lib.h"
37 #include "config/lib.h"
38 #include "email/lib.h"
39 #include "core/lib.h"
40 #include "conn/lib.h"
41 #include "lib.h"
42 #include "compmbox/lib.h"
43 #include "imap/lib.h"
44 #include "maildir/lib.h"
45 #include "mbox/lib.h"
46 #include "ncrypt/lib.h"
47 #include "nntp/lib.h"
48 #include "notmuch/lib.h"
49 #include "pop/lib.h"
50 #include "context.h"
51 #include "imap/adata.h" // IWYU pragma: keep
52 #include "imap/mdata.h" // IWYU pragma: keep
53 #include "imap/private.h" // IWYU pragma: keep
54 #include "maildir/edata.h" // IWYU pragma: keep
55 #include "maildir/mdata.h" // IWYU pragma: keep
56 #include "maildir/private.h" // IWYU pragma: keep
57 #include "nntp/adata.h" // IWYU pragma: keep
58 #include "nntp/mdata.h" // IWYU pragma: keep
59 #include "notmuch/adata.h" // IWYU pragma: keep
60 #include "notmuch/mdata.h" // IWYU pragma: keep
61 #include "notmuch/private.h" // IWYU pragma: keep
62 #include "pop/adata.h" // IWYU pragma: keep
63 #include "pop/private.h" // IWYU pragma: keep
64 
65 // #define GV_HIDE_CONTEXT
66 #define GV_HIDE_CONTEXT_CONTENTS
67 // #define GV_HIDE_MBOX
68 // #define GV_HIDE_NEOMUTT
69 // #define GV_HIDE_CONFIG
70 // #define GV_HIDE_MDATA
71 
72 static void dot_email(FILE *fp, struct Email *e, struct ListHead *links);
73 static void dot_envelope(FILE *fp, struct Envelope *env, struct ListHead *links);
74 
75 const char *get_content_type(enum ContentType type)
76 {
77  switch (type)
78  {
79  case TYPE_OTHER:
80  return "TYPE_OTHER";
81  case TYPE_AUDIO:
82  return "TYPE_AUDIO";
83  case TYPE_APPLICATION:
84  return "TYPE_APPLICATION";
85  case TYPE_IMAGE:
86  return "TYPE_IMAGE";
87  case TYPE_MESSAGE:
88  return "TYPE_MESSAGE";
89  case TYPE_MODEL:
90  return "TYPE_MODEL";
91  case TYPE_MULTIPART:
92  return "TYPE_MULTIPART";
93  case TYPE_TEXT:
94  return "TYPE_TEXT";
95  case TYPE_VIDEO:
96  return "TYPE_VIDEO";
97  case TYPE_ANY:
98  return "TYPE_ANY";
99  default:
100  return "UNKNOWN";
101  }
102 }
103 
105 {
106  switch (enc)
107  {
108  case ENC_OTHER:
109  return "ENC_OTHER";
110  case ENC_7BIT:
111  return "ENC_7BIT";
112  case ENC_8BIT:
113  return "ENC_8BIT";
115  return "ENC_QUOTED_PRINTABLE";
116  case ENC_BASE64:
117  return "ENC_BASE64";
118  case ENC_BINARY:
119  return "ENC_BINARY";
120  case ENC_UUENCODED:
121  return "ENC_UUENCODED";
122  default:
123  return "UNKNOWN";
124  }
125 }
126 
128 {
129  switch (disp)
130  {
131  case DISP_INLINE:
132  return "DISP_INLINE";
133  case DISP_ATTACH:
134  return "DISP_ATTACH";
135  case DISP_FORM_DATA:
136  return "DISP_FORM_DATA";
137  case DISP_NONE:
138  return "DISP_NONE";
139  default:
140  return "UNKNOWN";
141  }
142 }
143 
144 void add_flag(struct Buffer *buf, bool is_set, const char *name)
145 {
146  if (!buf || !name)
147  return;
148 
149  if (is_set)
150  {
151  if (!mutt_buffer_is_empty(buf))
152  mutt_buffer_addch(buf, ',');
153  mutt_buffer_addstr(buf, name);
154  }
155 }
156 
157 static void dot_type_bool(FILE *fp, const char *name, bool val)
158 {
159  static const char *values[] = { "false", "true" };
160  fprintf(fp, "\t\t<tr>\n");
161  fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%s</td>\n", name);
162  fprintf(fp, "\t\t\t<td border=\"0\">=</td>\n");
163  fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%s</td>\n", values[val]);
164  fprintf(fp, "\t\t</tr>\n");
165 }
166 
167 static void dot_type_char(FILE *fp, const char *name, char ch)
168 {
169  fprintf(fp, "\t\t<tr>\n");
170  fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%s</td>\n", name);
171  fprintf(fp, "\t\t\t<td border=\"0\">=</td>\n");
172  fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%c</td>\n", ch);
173  fprintf(fp, "\t\t</tr>\n");
174 }
175 
176 static void dot_type_date(char *buf, size_t buflen, time_t timestamp)
177 {
178  mutt_date_localtime_format(buf, buflen, "%Y-%m-%d %H:%M:%S", timestamp);
179 }
180 
181 static void dot_type_file(FILE *fp, const char *name, FILE *struct_fp)
182 {
183  fprintf(fp, "\t\t<tr>\n");
184  fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%s</td>\n", name);
185  fprintf(fp, "\t\t\t<td border=\"0\">=</td>\n");
186  if (struct_fp)
187  {
188  fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%p (%d)</td>\n",
189  (void *) struct_fp, fileno(struct_fp));
190  }
191  else
192  {
193  fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">NULL</td>\n");
194  }
195  fprintf(fp, "\t\t</tr>\n");
196 }
197 
198 static void dot_type_number(FILE *fp, const char *name, int num)
199 {
200  fprintf(fp, "\t\t<tr>\n");
201  fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%s</td>\n", name);
202  fprintf(fp, "\t\t\t<td border=\"0\">=</td>\n");
203  fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%d</td>\n", num);
204  fprintf(fp, "\t\t</tr>\n");
205 }
206 
207 static void dot_type_string_escape(char *buf, size_t buflen)
208 {
209  for (; buf[0]; buf++)
210  {
211  if (buf[0] == '<')
212  mutt_str_inline_replace(buf, buflen, 1, "&lt;");
213  else if (buf[0] == '>')
214  mutt_str_inline_replace(buf, buflen, 1, "&gt;");
215  else if (buf[0] == '&')
216  mutt_str_inline_replace(buf, buflen, 1, "&amp;");
217  }
218 }
219 
220 static void dot_type_string(FILE *fp, const char *name, const char *str, bool force)
221 {
222  if ((!str || (str[0] == '\0')) && !force)
223  return;
224 
225  char buf[1024] = "[NULL]";
226 
227  if (str)
228  {
229  mutt_str_copy(buf, str, sizeof(buf));
230  dot_type_string_escape(buf, sizeof(buf));
231  }
232 
233  bool quoted = ((buf[0] != '[') && (buf[0] != '*'));
234 
235  fprintf(fp, "\t\t<tr>\n");
236  fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%s</td>\n", name);
237  fprintf(fp, "\t\t\t<td border=\"0\">=</td>\n");
238  if (quoted)
239  fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">\"%s\"</td>\n", buf);
240  else
241  fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%s</td>\n", buf);
242  fprintf(fp, "\t\t</tr>\n");
243 }
244 
245 static void dot_type_umask(char *buf, size_t buflen, int umask)
246 {
247  snprintf(buf, buflen, "0%03o", umask);
248 }
249 
250 static void dot_ptr_name(char *buf, size_t buflen, const void *ptr)
251 {
252  snprintf(buf, buflen, "obj_%p", ptr);
253 }
254 
255 static void dot_ptr(FILE *fp, const char *name, void *ptr, const char *colour)
256 {
257  fprintf(fp, "\t\t<tr>\n");
258  fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%s</td>\n", name);
259  fprintf(fp, "\t\t\t<td border=\"0\">=</td>\n");
260  if (colour && ptr)
261  {
262  fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\" bgcolor=\"%s\">%p</td>\n",
263  colour, ptr);
264  }
265  else
266  {
267  fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%p</td>\n", ptr);
268  }
269  fprintf(fp, "\t\t</tr>\n");
270 }
271 
272 static void dot_add_link(struct ListHead *links, void *src, void *dst,
273  const char *label, bool back, const char *colour)
274 {
275  if (!src || !dst)
276  return;
277  if (!colour)
278  colour = "#c0c0c0";
279 
280  char obj1[16] = { 0 };
281  char obj2[16] = { 0 };
282  char text[256] = { 0 };
283  char lstr[128] = { 0 };
284 
285  dot_ptr_name(obj1, sizeof(obj1), src);
286  dot_ptr_name(obj2, sizeof(obj2), dst);
287 
288  if (label)
289  snprintf(lstr, sizeof(lstr), "edgetooltip=\"%s\"", label);
290 
291  snprintf(text, sizeof(text), "%s -> %s [ %s %s color=\"%s\" ]", obj1, obj2,
292  back ? "dir=back" : "", lstr, colour);
293  mutt_list_insert_tail(links, mutt_str_dup(text));
294 }
295 
296 static void dot_graph_header(FILE *fp)
297 {
298  fprintf(fp, "digraph neomutt\n");
299  fprintf(fp, "{\n\n");
300 
301  fprintf(fp, "\tgraph [\n");
302  fprintf(fp, "\t\trankdir=\"TB\"\n");
303  fprintf(fp, "\t\tnodesep=\"0.5\"\n");
304  fprintf(fp, "\t\tranksep=\"0.5\"\n");
305  fprintf(fp, "\t];\n");
306  fprintf(fp, "\n");
307  fprintf(fp, "\tnode [\n");
308  fprintf(fp, "\t\tshape=\"plain\"\n");
309  fprintf(fp, "\t];\n");
310  fprintf(fp, "\n");
311  fprintf(fp, "\tedge [\n");
312  fprintf(fp, "\t\tpenwidth=\"4.5\"\n");
313  fprintf(fp, "\t\tarrowsize=\"1.0\"\n");
314  fprintf(fp, "\t\tcolor=\"#c0c0c0\"\n");
315  fprintf(fp, "\t];\n");
316  fprintf(fp, "\n");
317 }
318 
319 static void dot_graph_footer(FILE *fp, struct ListHead *links)
320 {
321  fprintf(fp, "\n");
322  struct ListNode *np = NULL;
323  STAILQ_FOREACH(np, links, entries)
324  {
325  fprintf(fp, "\t%s;\n", np->data);
326  }
327  fprintf(fp, "\n}\n");
328 }
329 
330 static void dot_object_header(FILE *fp, const void *ptr, const char *name, const char *colour)
331 {
332  char obj[16] = { 0 };
333  dot_ptr_name(obj, sizeof(obj), ptr);
334 
335  if (!colour)
336  colour = "#ffff80";
337 
338  fprintf(fp, "\t%s [\n", obj);
339  fprintf(fp, "\t\tlabel=<<table cellspacing=\"0\" border=\"1\" rows=\"*\" "
340  "color=\"#d0d0d0\">\n");
341  fprintf(fp, "\t\t<tr>\n");
342  fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\" bgcolor=\"%s\" port=\"top\" colspan=\"3\"><font color=\"#000000\" point-size=\"20\"><b>%s</b></font> <font point-size=\"12\">(%p)</font></td>\n",
343  colour, name, ptr);
344  fprintf(fp, "\t\t</tr>\n");
345 }
346 
347 static void dot_object_footer(FILE *fp)
348 {
349  fprintf(fp, "\t\t</table>>\n");
350  fprintf(fp, "\t];\n");
351  fprintf(fp, "\n");
352 }
353 
354 static void dot_node(FILE *fp, void *ptr, const char *name, const char *colour)
355 {
356  char obj[16] = { 0 };
357  dot_ptr_name(obj, sizeof(obj), ptr);
358 
359  fprintf(fp, "\t%s [\n", obj);
360  fprintf(fp, "\t\tlabel=<<table cellspacing=\"0\" border=\"1\" rows=\"*\" "
361  "color=\"#d0d0d0\">\n");
362  fprintf(fp, "\t\t<tr>\n");
363  fprintf(fp, "\t\t\t<td border=\"0\" bgcolor=\"%s\" port=\"top\"><font color=\"#000000\" point-size=\"20\"><b>%s</b></font></td>\n",
364  colour, name);
365  fprintf(fp, "\t\t</tr>\n");
366  dot_object_footer(fp);
367 }
368 
369 static void dot_node_link(FILE *fp, void *ptr, const char *name, void *link, const char *colour)
370 {
371  char obj[16] = { 0 };
372  dot_ptr_name(obj, sizeof(obj), ptr);
373 
374  fprintf(fp, "\t%s [\n", obj);
375  fprintf(fp, "\t\tlabel=<<table cellspacing=\"0\" border=\"1\" rows=\"*\" "
376  "color=\"#d0d0d0\">\n");
377  fprintf(fp, "\t\t<tr>\n");
378  fprintf(fp, "\t\t\t<td border=\"0\" bgcolor=\"%s\" port=\"top\"><font color=\"#000000\" point-size=\"20\"><b>%s</b></font></td>\n",
379  colour, name);
380  fprintf(fp, "\t\t</tr>\n");
381 
382  fprintf(fp, "\t\t<tr>\n");
383  fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\" bgcolor=\"%s\">%p</td>\n", colour, link);
384  fprintf(fp, "\t\t</tr>\n");
385 
386  dot_object_footer(fp);
387 }
388 
389 static void dot_path_fs(char *buf, size_t buflen, const char *path)
390 {
391  if (!path)
392  {
393  buf[0] = '\0';
394  return;
395  }
396 
397  const char *slash = strrchr(path, '/');
398  if (slash)
399  slash++;
400  else
401  slash = path;
402 
403  mutt_str_copy(buf, slash, buflen);
404 }
405 
406 static void dot_path_imap(char *buf, size_t buflen, const char *path)
407 {
408  char tmp[1024] = { 0 };
409  mutt_str_copy(tmp, path, sizeof(tmp));
410 
411  struct Url *u = url_parse(tmp);
412 
413  if (u->path && (u->path[0] != '\0'))
414  mutt_str_copy(buf, u->path, buflen);
415  else
416  snprintf(buf, buflen, "%s:%s", u->host, u->user);
417 
418  url_free(&u);
419 }
420 
421 static void dot_config(FILE *fp, const char *name, int type,
422  struct ConfigSubset *sub, struct ListHead *links)
423 {
424  if (!sub)
425  return;
426 
427  struct Buffer value = mutt_buffer_make(256);
428  dot_object_header(fp, (void *) name, "Config", "#ffff80");
429  dot_type_string(fp, "scope", sub->name, true);
430 
431  if (sub->name)
432  {
433  char scope[256];
434  snprintf(scope, sizeof(scope), "%s:", sub->name);
435 
436  struct HashElem **list = get_elem_list(sub->cs);
437  for (size_t i = 0; list[i]; i++)
438  {
439  struct HashElem *item = list[i];
440  if ((item->type & type) == 0)
441  continue;
442 
443  const char *iname = item->key.strkey;
444  size_t slen = strlen(scope);
445  if (mutt_str_startswith(iname, scope) != 0)
446  {
447  if (strchr(iname + slen, ':'))
448  continue;
449  if ((DTYPE(item->type) == DT_STRING) && (item->type & DT_SENSITIVE))
450  {
451  dot_type_string(fp, iname + slen, "***", true);
452  }
453  else
454  {
455  mutt_buffer_reset(&value);
456  cs_subset_he_string_get(sub, item, &value);
457  dot_type_string(fp, iname + slen, value.data, true);
458  }
459  }
460  }
461  }
462  else
463  {
464  struct HashElem **list = get_elem_list(sub->cs);
465  int i = 0;
466  for (; list[i]; i++)
467  ; // do nothing
468 
469  dot_type_number(fp, "count", i);
470  FREE(&list);
471  }
472 
473  dot_object_footer(fp);
474  mutt_buffer_dealloc(&value);
475 }
476 
477 static void dot_comp(FILE *fp, struct CompressInfo *ci, struct ListHead *links)
478 {
479  dot_object_header(fp, ci, "CompressInfo", "#c0c060");
480  dot_type_string(fp, "append", ci->cmd_append, true);
481  dot_type_string(fp, "close", ci->cmd_close, true);
482  dot_type_string(fp, "open", ci->cmd_open, true);
483  dot_object_footer(fp);
484 }
485 
486 static void dot_mailbox_type(FILE *fp, const char *name, enum MailboxType type)
487 {
488  const char *typestr = NULL;
489 
490  switch (type)
491  {
492  case MUTT_MBOX:
493  typestr = "MBOX";
494  break;
495  case MUTT_MMDF:
496  typestr = "MMDF";
497  break;
498  case MUTT_MH:
499  typestr = "MH";
500  break;
501  case MUTT_MAILDIR:
502  typestr = "MAILDIR";
503  break;
504  case MUTT_NNTP:
505  typestr = "NNTP";
506  break;
507  case MUTT_IMAP:
508  typestr = "IMAP";
509  break;
510  case MUTT_NOTMUCH:
511  typestr = "NOTMUCH";
512  break;
513  case MUTT_POP:
514  typestr = "POP";
515  break;
516  case MUTT_COMPRESSED:
517  typestr = "COMPRESSED";
518  break;
519  default:
520  typestr = "UNKNOWN";
521  }
522 
523  fprintf(fp, "\t\t<tr>\n");
524  fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%s</td>\n", name);
525  fprintf(fp, "\t\t\t<td border=\"0\">=</td>\n");
526  fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%s</td>\n", typestr);
527  fprintf(fp, "\t\t</tr>\n");
528 }
529 
530 static void dot_mailbox_imap(FILE *fp, struct ImapMboxData *mdata, struct ListHead *links)
531 {
532  dot_object_header(fp, mdata, "ImapMboxData", "#60c060");
533  dot_type_string(fp, "name", mdata->name, true);
534  dot_type_string(fp, "munge_name", mdata->munge_name, true);
535  dot_type_string(fp, "real_name", mdata->real_name, true);
536  dot_object_footer(fp);
537 }
538 
539 static void dot_mailbox_maildir(FILE *fp, struct MaildirMboxData *mdata, struct ListHead *links)
540 {
541  char buf[64] = { 0 };
542 
543  dot_object_header(fp, mdata, "MaildirMboxData", "#60c060");
544 
545  dot_type_date(buf, sizeof(buf), mdata->mtime_cur.tv_sec);
546  dot_type_string(fp, "mtime_cur", buf, true);
547 
548  dot_type_umask(buf, sizeof(buf), mdata->mh_umask);
549  dot_type_string(fp, "mh_umask", buf, true);
550  dot_object_footer(fp);
551 }
552 
553 static void dot_mailbox_mbox(FILE *fp, struct MboxAccountData *mdata, struct ListHead *links)
554 {
555  char buf[64] = { 0 };
556 
557  dot_object_header(fp, mdata, "MboxAccountData", "#60c060");
558  dot_ptr(fp, "fp", mdata->fp, NULL);
559 
560  dot_type_date(buf, sizeof(buf), mdata->atime.tv_sec);
561  dot_type_string(fp, "atime", buf, true);
562 
563  dot_object_footer(fp);
564 }
565 
566 static void dot_mailbox_nntp(FILE *fp, struct NntpMboxData *mdata, struct ListHead *links)
567 {
568  dot_object_header(fp, mdata, "NntpMboxData", "#60c060");
569  dot_type_string(fp, "group", mdata->group, true);
570  dot_type_string(fp, "desc", mdata->desc, true);
571 
572  dot_type_number(fp, "first_message", mdata->first_message);
573  dot_type_number(fp, "last_message", mdata->last_message);
574  dot_type_number(fp, "last_loaded", mdata->last_loaded);
575  dot_type_number(fp, "last_cached", mdata->last_cached);
576  dot_type_number(fp, "unread", mdata->unread);
577 
578  dot_type_bool(fp, "subscribed", mdata->subscribed);
579  dot_type_bool(fp, "has_new_mail", mdata->has_new_mail);
580  dot_type_bool(fp, "allowed", mdata->allowed);
581  dot_type_bool(fp, "deleted", mdata->deleted);
582 
583  dot_object_footer(fp);
584 }
585 
586 static void dot_mailbox_notmuch(FILE *fp, struct NmMboxData *mdata, struct ListHead *links)
587 {
588  dot_object_header(fp, mdata, "NmMboxData", "#60c060");
589  dot_type_number(fp, "db_limit", mdata->db_limit);
590  dot_object_footer(fp);
591 }
592 
593 static void dot_mailbox_pop(FILE *fp, struct PopAccountData *adata, struct ListHead *links)
594 {
595  dot_object_header(fp, adata, "PopAccountData", "#60c060");
596  dot_ptr(fp, "conn", adata->conn, "#ff8080");
597  dot_object_footer(fp);
598 }
599 
600 static void dot_mailbox(FILE *fp, struct Mailbox *m, struct ListHead *links)
601 {
602  char buf[64] = { 0 };
603 
604  dot_object_header(fp, m, "Mailbox", "#80ff80");
605  dot_mailbox_type(fp, "type", m->type);
606  dot_type_string(fp, "name", m->name, false);
607 
608  if ((m->type == MUTT_IMAP) || (m->type == MUTT_POP))
609  {
610  dot_path_imap(buf, sizeof(buf), mutt_buffer_string(&m->pathbuf));
611  dot_type_string(fp, "pathbuf", buf, true);
612  dot_path_imap(buf, sizeof(buf), m->realpath);
613  dot_type_string(fp, "realpath", buf, true);
614  }
615  else
616  {
617  dot_path_fs(buf, sizeof(buf), mutt_buffer_string(&m->pathbuf));
618  dot_type_string(fp, "pathbuf", buf, true);
619  dot_path_fs(buf, sizeof(buf), m->realpath);
620  dot_type_string(fp, "realpath", buf, true);
621  }
622 
623 #ifdef GV_HIDE_MDATA
624  dot_ptr(fp, "mdata", m->mdata, NULL);
625 #endif
626  dot_ptr(fp, "account", m->account, "#80ffff");
627 
628  dot_type_number(fp, "msg_count", m->msg_count);
629  // dot_type_number(fp, "msg_unread", m->msg_unread);
630  // dot_type_number(fp, "msg_flagged", m->msg_flagged);
631  // dot_type_number(fp, "msg_new", m->msg_new);
632  // dot_type_number(fp, "msg_deleted", m->msg_deleted);
633  // dot_type_number(fp, "msg_tagged", m->msg_tagged);
634 
635  dot_ptr(fp, "emails", m->emails, NULL);
636  dot_type_number(fp, "email_max", m->email_max);
637  dot_ptr(fp, "v2r", m->v2r, NULL);
638  dot_type_number(fp, "vcount", m->vcount);
639 
640  dot_object_footer(fp);
641 
642  // dot_add_link(links, m, m->mdata, false, NULL);
643 
644 #ifndef GV_HIDE_MDATA
645  if (m->mdata)
646  {
647  if (m->type == MUTT_MAILDIR)
648  dot_mailbox_maildir(fp, m->mdata, links);
649  else if (m->type == MUTT_IMAP)
650  dot_mailbox_imap(fp, m->mdata, links);
651  else if (m->type == MUTT_POP)
652  dot_mailbox_pop(fp, m->mdata, links);
653  else if (m->type == MUTT_MBOX)
654  dot_mailbox_mbox(fp, m->mdata, links);
655  else if (m->type == MUTT_NNTP)
656  dot_mailbox_nntp(fp, m->mdata, links);
657  else if (m->type == MUTT_NOTMUCH)
658  dot_mailbox_notmuch(fp, m->mdata, links);
659 
660  dot_add_link(links, m, m->mdata, "Mailbox->mdata", false, NULL);
661  }
662 #endif
663 
664  if (m->compress_info)
665  {
666  dot_comp(fp, m->compress_info, links);
667  dot_add_link(links, m, m->compress_info, "Mailbox->compress_info", false, NULL);
668  }
669 
670 #ifndef GV_HIDE_CONFIG
671  if (m->name)
672  {
673  dot_config(fp, m->name, DT_INHERIT_MBOX, m->sub, links);
674  dot_add_link(links, m, m->name, "Mailbox Config", false, NULL);
675  }
676 #endif
677 }
678 
679 static void dot_mailbox_node(FILE *fp, struct MailboxNode *mn, struct ListHead *links)
680 {
681  dot_node(fp, mn, "MN", "#80ff80");
682 
683  dot_mailbox(fp, mn->mailbox, links);
684 
685  dot_add_link(links, mn, mn->mailbox, "MailboxNode->mailbox", false, NULL);
686 
687  struct Buffer buf;
688  mutt_buffer_init(&buf);
689 
690  char name[256] = { 0 };
691  mutt_buffer_addstr(&buf, "{ rank=same ");
692 
693  dot_ptr_name(name, sizeof(name), mn);
694  mutt_buffer_add_printf(&buf, "%s ", name);
695 
696  dot_ptr_name(name, sizeof(name), mn->mailbox);
697  mutt_buffer_add_printf(&buf, "%s ", name);
698 
699 #ifndef GV_HIDE_MDATA
700  if (mn->mailbox->mdata)
701  {
702  dot_ptr_name(name, sizeof(name), mn->mailbox->mdata);
703  mutt_buffer_add_printf(&buf, "%s ", name);
704  }
705 #endif
706 
707 #ifndef GV_HIDE_CONFIG
708  if (mn->mailbox->name)
709  {
710  dot_ptr_name(name, sizeof(name), mn->mailbox->name);
711  mutt_buffer_add_printf(&buf, "%s ", name);
712  }
713 #endif
714 
715  mutt_buffer_addstr(&buf, "}");
716 
718  mutt_buffer_dealloc(&buf);
719 }
720 
721 static void dot_mailbox_list(FILE *fp, struct MailboxList *ml, struct ListHead *links, bool abbr)
722 {
723  struct MailboxNode *prev = NULL;
724  struct MailboxNode *np = NULL;
725  STAILQ_FOREACH(np, ml, entries)
726  {
727  if (abbr)
728  dot_node_link(fp, np, "MN", np->mailbox, "#80ff80");
729  else
730  dot_mailbox_node(fp, np, links);
731  if (prev)
732  dot_add_link(links, prev, np, "MailboxNode->next", false, NULL);
733  prev = np;
734  }
735 }
736 
737 static void dot_connection(FILE *fp, struct Connection *c, struct ListHead *links)
738 {
739  dot_object_header(fp, c, "Connection", "#ff8080");
740  // dot_ptr(fp, "sockdata", c->sockdata, "#60c0c0");
741  dot_type_number(fp, "fd", c->fd);
742  dot_object_footer(fp);
743 
744  dot_object_header(fp, c->inbuf, "ConnAccount", "#ff8080");
745  dot_type_string(fp, "user", c->account.user, true);
746  dot_type_string(fp, "host", c->account.host, true);
747  dot_type_number(fp, "port", c->account.port);
748  dot_object_footer(fp);
749 
750  dot_add_link(links, c, c->inbuf, "Connection.ConnAccount", false, NULL);
751 }
752 
753 static void dot_account_imap(FILE *fp, struct ImapAccountData *adata, struct ListHead *links)
754 {
755  dot_object_header(fp, adata, "ImapAccountData", "#60c0c0");
756  // dot_type_string(fp, "mbox_name", adata->mbox_name, true);
757  // dot_type_string(fp, "login", adata->conn->account.login, true);
758  dot_type_string(fp, "user", adata->conn->account.user, true);
759  dot_type_string(fp, "pass", adata->conn->account.pass[0] ? "***" : "", true);
760  dot_type_number(fp, "port", adata->conn->account.port);
761  // dot_ptr(fp, "conn", adata->conn, "#ff8080");
762  dot_type_bool(fp, "unicode", adata->unicode);
763  dot_type_bool(fp, "qresync", adata->qresync);
764  dot_type_char(fp, "seqid", adata->seqid);
765  dot_ptr(fp, "mailbox", adata->mailbox, "#80ff80");
766  dot_object_footer(fp);
767 
768  if (adata->conn)
769  {
770  dot_connection(fp, adata->conn, links);
771  dot_add_link(links, adata, adata->conn, "ImapAccountData->conn", false, NULL);
772  }
773 }
774 
775 static void dot_account_mbox(FILE *fp, struct MboxAccountData *adata, struct ListHead *links)
776 {
777  char buf[64] = { 0 };
778 
779  dot_object_header(fp, adata, "MboxAccountData", "#60c0c0");
780  dot_ptr(fp, "fp", adata->fp, NULL);
781 
782  dot_type_date(buf, sizeof(buf), adata->atime.tv_sec);
783  dot_type_string(fp, "atime", buf, true);
784  dot_type_bool(fp, "locked", adata->locked);
785  dot_type_bool(fp, "append", adata->append);
786 
787  dot_object_footer(fp);
788 }
789 
790 static void dot_account_nntp(FILE *fp, struct NntpAccountData *adata, struct ListHead *links)
791 {
792  dot_object_header(fp, adata, "NntpAccountData", "#60c0c0");
793  dot_type_number(fp, "groups_num", adata->groups_num);
794 
795  dot_type_bool(fp, "hasCAPABILITIES", adata->hasCAPABILITIES);
796  dot_type_bool(fp, "hasSTARTTLS", adata->hasSTARTTLS);
797  dot_type_bool(fp, "hasDATE", adata->hasDATE);
798  dot_type_bool(fp, "hasLIST_NEWSGROUPS", adata->hasLIST_NEWSGROUPS);
799  dot_type_bool(fp, "hasXGTITLE", adata->hasXGTITLE);
800  dot_type_bool(fp, "hasLISTGROUP", adata->hasLISTGROUP);
801  dot_type_bool(fp, "hasLISTGROUPrange", adata->hasLISTGROUPrange);
802  dot_type_bool(fp, "hasOVER", adata->hasOVER);
803  dot_type_bool(fp, "hasXOVER", adata->hasXOVER);
804  dot_type_bool(fp, "cacheable", adata->cacheable);
805  dot_type_bool(fp, "newsrc_modified", adata->newsrc_modified);
806 
807  dot_type_string(fp, "authenticators", adata->authenticators, true);
808  dot_type_string(fp, "overview_fmt", adata->overview_fmt, true);
809  dot_type_string(fp, "newsrc_file", adata->newsrc_file, true);
810  dot_type_file(fp, "newsrc_fp", adata->fp_newsrc);
811 
812  dot_type_number(fp, "groups_num", adata->groups_num);
813  dot_type_number(fp, "groups_max", adata->groups_max);
814 
815  char buf[128];
816  dot_type_date(buf, sizeof(buf), adata->mtime);
817  dot_type_string(fp, "mtime", buf, true);
818  dot_type_date(buf, sizeof(buf), adata->newgroups_time);
819  dot_type_string(fp, "newgroups_time", buf, true);
820  dot_type_date(buf, sizeof(buf), adata->check_time);
821  dot_type_string(fp, "check_time", buf, true);
822 
823  dot_object_footer(fp);
824 
825  if (adata->conn)
826  {
827  dot_connection(fp, adata->conn, links);
828  dot_add_link(links, adata, adata->conn, "NntpAccountData->conn", false, NULL);
829  }
830 }
831 
832 static void dot_account_notmuch(FILE *fp, struct NmAccountData *adata, struct ListHead *links)
833 {
834  dot_object_header(fp, adata, "NmAccountData", "#60c0c0");
835  dot_ptr(fp, "db", adata->db, NULL);
836  dot_object_footer(fp);
837 }
838 
839 static void dot_account_pop(FILE *fp, struct PopAccountData *adata, struct ListHead *links)
840 {
841  char buf[64] = { 0 };
842 
843  dot_object_header(fp, adata, "PopAccountData", "#60c0c0");
844 
845  dot_type_date(buf, sizeof(buf), adata->check_time);
846  dot_type_string(fp, "check_time", buf, true);
847 
848  dot_type_string(fp, "login", adata->conn->account.login, true);
849  dot_type_string(fp, "user", adata->conn->account.user, true);
850  dot_type_string(fp, "pass", adata->conn->account.pass[0] ? "***" : "", true);
851  dot_type_number(fp, "port", adata->conn->account.port);
852  // dot_ptr(fp, "conn", adata->conn, "#ff8080");
853  dot_object_footer(fp);
854 
855  if (adata->conn)
856  {
857  dot_connection(fp, adata->conn, links);
858  dot_add_link(links, adata, adata->conn, "PopAccountData->conn", false, NULL);
859  }
860 }
861 
862 static void dot_account(FILE *fp, struct Account *a, struct ListHead *links)
863 {
864  dot_object_header(fp, a, "Account", "#80ffff");
865  dot_mailbox_type(fp, "type", a->type);
866  dot_type_string(fp, "name", a->name, true);
867  // dot_ptr(fp, "adata", a->adata, "#60c0c0");
868  dot_object_footer(fp);
869 
870  if (a->adata)
871  {
872  if (a->type == MUTT_IMAP)
873  dot_account_imap(fp, a->adata, links);
874  else if (a->type == MUTT_POP)
875  dot_account_pop(fp, a->adata, links);
876  else if (a->type == MUTT_MBOX)
877  dot_account_mbox(fp, a->adata, links);
878  else if (a->type == MUTT_NNTP)
879  dot_account_nntp(fp, a->adata, links);
880  else if (a->type == MUTT_NOTMUCH)
881  dot_account_notmuch(fp, a->adata, links);
882 
883  dot_add_link(links, a, a->adata, "Account->adata", false, NULL);
884  }
885 
886 #ifndef GV_HIDE_CONFIG
887  if (a->name)
888  {
889  dot_config(fp, a->name, DT_INHERIT_ACC, a->sub, links);
890  dot_add_link(links, a, a->name, "Config", false, NULL);
891 
892  char name[256] = { 0 };
893  struct Buffer buf;
894  mutt_buffer_init(&buf);
895 
896  mutt_buffer_addstr(&buf, "{ rank=same ");
897 
898  dot_ptr_name(name, sizeof(name), a);
899  mutt_buffer_add_printf(&buf, "%s ", name);
900 
901  dot_ptr_name(name, sizeof(name), a->name);
902  mutt_buffer_add_printf(&buf, "%s ", name);
903 
904  mutt_buffer_addstr(&buf, "}");
906  mutt_buffer_dealloc(&buf);
907  }
908 #endif
909 
910  struct MailboxNode *first = STAILQ_FIRST(&a->mailboxes);
911  dot_add_link(links, a, first, "Account->mailboxes", false, NULL);
912  dot_mailbox_list(fp, &a->mailboxes, links, false);
913 }
914 
915 static void dot_account_list(FILE *fp, struct AccountList *al, struct ListHead *links)
916 {
917  struct Account *prev = NULL;
918  struct Account *np = NULL;
919  TAILQ_FOREACH(np, al, entries)
920  {
921 #ifdef GV_HIDE_MBOX
922  if (np->type == MUTT_MBOX)
923  continue;
924 #endif
925  dot_account(fp, np, links);
926  if (prev)
927  dot_add_link(links, prev, np, "Account->next", false, NULL);
928 
929  prev = np;
930  }
931 }
932 
933 static void dot_context(FILE *fp, struct Context *ctx, struct ListHead *links)
934 {
935  dot_object_header(fp, ctx, "Context", "#ff80ff");
936  dot_ptr(fp, "mailbox", ctx->mailbox, "#80ff80");
937 #ifdef GV_HIDE_CONTEXT_CONTENTS
938  dot_type_number(fp, "vsize", ctx->vsize);
939  dot_type_string(fp, "pattern", ctx->pattern, true);
940  dot_type_bool(fp, "collapsed", ctx->collapsed);
941 #endif
942  dot_object_footer(fp);
943 }
944 
945 void dump_graphviz(const char *title, struct Context *ctx)
946 {
947  char name[256] = { 0 };
948  struct ListHead links = STAILQ_HEAD_INITIALIZER(links);
949 
950  time_t now = time(NULL);
951  if (title)
952  {
953  char date[128];
954  mutt_date_localtime_format(date, sizeof(date), "%R", now);
955  snprintf(name, sizeof(name), "%s-%s.gv", date, title);
956  }
957  else
958  {
959  mutt_date_localtime_format(name, sizeof(name), "%R.gv", now);
960  }
961 
962  umask(022);
963  FILE *fp = fopen(name, "w");
964  if (!fp)
965  return;
966 
967  dot_graph_header(fp);
968 
969 #ifndef GV_HIDE_NEOMUTT
970  dot_node(fp, NeoMutt, "NeoMutt", "#ffa500");
972  "NeoMutt->accounts", false, NULL);
973 #ifndef GV_HIDE_CONFIG
974  dot_config(fp, (const char *) NeoMutt->sub, 0, NeoMutt->sub, &links);
975  dot_add_link(&links, NeoMutt, NeoMutt->sub, "NeoMutt Config", false, NULL);
976  struct Buffer buf = mutt_buffer_make(256);
977  char obj1[16] = { 0 };
978  char obj2[16] = { 0 };
979  dot_ptr_name(obj1, sizeof(obj1), NeoMutt);
980  dot_ptr_name(obj2, sizeof(obj2), NeoMutt->sub);
981  mutt_buffer_printf(&buf, "{ rank=same %s %s }", obj1, obj2);
983  mutt_buffer_dealloc(&buf);
984 #endif
985 #endif
986 
987  dot_account_list(fp, &NeoMutt->accounts, &links);
988 
989 #ifndef GV_HIDE_CONTEXT
990  if (ctx)
991  dot_context(fp, ctx, &links);
992 
993 #ifndef GV_HIDE_NEOMUTT
994  /* Globals */
995  fprintf(fp, "\t{ rank=same ");
996  if (ctx)
997  {
998  dot_ptr_name(name, sizeof(name), ctx);
999  fprintf(fp, "%s ", name);
1000  }
1001  dot_ptr_name(name, sizeof(name), NeoMutt);
1002  fprintf(fp, "%s ", name);
1003  fprintf(fp, "}\n");
1004 #endif
1005 #endif
1006 
1007  fprintf(fp, "\t{ rank=same ");
1008  struct Account *np = NULL;
1009  TAILQ_FOREACH(np, &NeoMutt->accounts, entries)
1010  {
1011 #ifdef GV_HIDE_MBOX
1012  if (np->type == MUTT_MBOX)
1013  continue;
1014 #endif
1015  dot_ptr_name(name, sizeof(name), np);
1016  fprintf(fp, "%s ", name);
1017  }
1018  fprintf(fp, "}\n");
1019 
1020  dot_graph_footer(fp, &links);
1021  fclose(fp);
1022  mutt_list_free(&links);
1023 }
1024 
1025 static void dot_parameter_list(FILE *fp, const char *name, const struct ParameterList *pl)
1026 {
1027  if (!pl)
1028  return;
1029  if (TAILQ_EMPTY(pl))
1030  return;
1031 
1032  dot_object_header(fp, pl, "ParameterList", "#00ff00");
1033 
1034  struct Parameter *np = NULL;
1035  TAILQ_FOREACH(np, pl, entries)
1036  {
1037  dot_type_string(fp, np->attribute, np->value, false);
1038  }
1039 
1040  dot_object_footer(fp);
1041 }
1042 
1043 static void dot_content(FILE *fp, struct Content *cont, struct ListHead *links)
1044 {
1045  struct Buffer buf = mutt_buffer_make(256);
1046 
1047  dot_object_header(fp, cont, "Content", "#800080");
1048 
1049  dot_type_number(fp, "hibin", cont->hibin);
1050  dot_type_number(fp, "lobin", cont->lobin);
1051  dot_type_number(fp, "nulbin", cont->nulbin);
1052  dot_type_number(fp, "crlf", cont->crlf);
1053  dot_type_number(fp, "ascii", cont->ascii);
1054  dot_type_number(fp, "linemax", cont->linemax);
1055 
1056 #define ADD_BOOL(F) add_flag(&buf, cont->F, #F)
1057  ADD_BOOL(space);
1058  ADD_BOOL(binary);
1059  ADD_BOOL(from);
1060  ADD_BOOL(dot);
1061  ADD_BOOL(cr);
1062 #undef ADD_BOOL
1063 
1064  dot_object_footer(fp);
1065 
1066  mutt_buffer_dealloc(&buf);
1067 }
1068 
1069 void dot_attach_ptr(FILE *fp, struct AttachPtr *aptr, struct ListHead *links)
1070 {
1071  if (!aptr)
1072  return;
1073 
1074  struct Buffer buf = mutt_buffer_make(256);
1075 
1076  dot_object_header(fp, aptr, "AttachPtr", "#ff0000");
1077 
1078  dot_type_file(fp, "fp", aptr->fp);
1079 
1080  dot_type_string(fp, "parent_type", get_content_type(aptr->parent_type), false);
1081 
1082  dot_type_number(fp, "level", aptr->level);
1083  dot_type_number(fp, "num", aptr->num);
1084 
1085  dot_type_bool(fp, "unowned", aptr->unowned);
1086  dot_type_bool(fp, "decrypted", aptr->decrypted);
1087 
1088  dot_object_footer(fp);
1089 
1090  dot_add_link(links, aptr->body, aptr, "AttachPtr->body", true, NULL);
1091 
1092  mutt_buffer_dealloc(&buf);
1093 }
1094 
1095 static void dot_body(FILE *fp, struct Body *b, struct ListHead *links, bool link_next)
1096 {
1097  struct Buffer buf = mutt_buffer_make(256);
1098 
1099  dot_object_header(fp, b, "Body", "#2020ff");
1100 
1101  char file[256];
1102  dot_path_fs(file, sizeof(file), b->filename);
1103  dot_type_string(fp, "file", file, false);
1104 
1105  dot_type_string(fp, "charset", b->charset, false);
1106  dot_type_string(fp, "description", b->description, false);
1107  dot_type_string(fp, "d_filename", b->d_filename, false);
1108  dot_type_string(fp, "form_name", b->form_name, false);
1109  dot_type_string(fp, "language", b->language, false);
1110  dot_type_string(fp, "subtype", b->subtype, false);
1111  dot_type_string(fp, "xtype", b->xtype, false);
1112 
1113  dot_type_string(fp, "type", get_content_type(b->type), true);
1114  dot_type_string(fp, "encoding", get_content_encoding(b->encoding), true);
1115  dot_type_string(fp, "disposition", get_content_disposition(b->disposition), true);
1116 
1117  if (b->stamp != 0)
1118  {
1119  char arr[64];
1120  dot_type_date(arr, sizeof(arr), b->stamp);
1121  dot_type_string(fp, "stamp", arr, true);
1122  }
1123 
1124 #define ADD_BOOL(F) add_flag(&buf, b->F, #F)
1125  ADD_BOOL(attach_qualifies);
1126  ADD_BOOL(badsig);
1127  ADD_BOOL(collapsed);
1128  ADD_BOOL(deleted);
1129  ADD_BOOL(force_charset);
1130  ADD_BOOL(goodsig);
1131 #ifdef USE_AUTOCRYPT
1132  ADD_BOOL(is_autocrypt);
1133 #endif
1134  ADD_BOOL(noconv);
1135  ADD_BOOL(tagged);
1136  ADD_BOOL(unlink);
1137  ADD_BOOL(use_disp);
1138  ADD_BOOL(warnsig);
1139 #undef ADD_BOOL
1140  dot_type_string(fp, "bools",
1141  mutt_buffer_is_empty(&buf) ? "[NONE]" : mutt_buffer_string(&buf), true);
1142 
1143  dot_type_number(fp, "attach_count", b->attach_count);
1144  dot_type_number(fp, "hdr_offset", b->hdr_offset);
1145  dot_type_number(fp, "length", b->length);
1146  dot_type_number(fp, "offset", b->offset);
1147 
1148  dot_ptr(fp, "aptr", b->aptr, "#3bcbc4");
1149  dot_object_footer(fp);
1150 
1151  if (!TAILQ_EMPTY(&b->parameter))
1152  {
1153  dot_parameter_list(fp, "parameter", &b->parameter);
1154  dot_add_link(links, b, &b->parameter, "Body->mime_headers", false, NULL);
1155  }
1156 
1157  if (b->mime_headers)
1158  {
1159  dot_envelope(fp, b->mime_headers, links);
1160  dot_add_link(links, b, b->mime_headers, "Body->mime_headers", false, NULL);
1161  }
1162 
1163  if (b->email)
1164  {
1165  dot_email(fp, b->email, links);
1166  dot_add_link(links, b, b->email, "Body->email", false, NULL);
1167  }
1168 
1169  if (b->parts)
1170  {
1171  if (!b->email)
1172  dot_body(fp, b->parts, links, true);
1173  dot_add_link(links, b, b->parts, "Body->parts", false, "#ff0000");
1174  }
1175 
1176  if (b->next && link_next)
1177  {
1178  char name[256] = { 0 };
1179  mutt_buffer_reset(&buf);
1180 
1181  mutt_buffer_addstr(&buf, "{ rank=same ");
1182 
1183  dot_ptr_name(name, sizeof(name), b);
1184  mutt_buffer_add_printf(&buf, "%s ", name);
1185 
1186  for (; b->next; b = b->next)
1187  {
1188  dot_body(fp, b->next, links, false);
1189  dot_add_link(links, b, b->next, "Body->next", false, "#008000");
1190 
1191  dot_ptr_name(name, sizeof(name), b->next);
1192  mutt_buffer_add_printf(&buf, "%s ", name);
1193  }
1194 
1195  mutt_buffer_addstr(&buf, "}");
1197  }
1198  else
1199  {
1200  if (b->content)
1201  {
1202  dot_content(fp, b->content, links);
1203  dot_add_link(links, b, b->content, "Body->content", false, NULL);
1204  }
1205 
1206  // if (b->aptr)
1207  // {
1208  // dot_attach_ptr(fp, b->aptr, links);
1209  // dot_add_link(links, b, b->aptr, "Body->aptr", false, NULL);
1210  // }
1211  }
1212 
1213  mutt_buffer_dealloc(&buf);
1214 }
1215 
1216 static void dot_list_head(FILE *fp, const char *name, const struct ListHead *list)
1217 {
1218  if (!list || !name)
1219  return;
1220  if (STAILQ_EMPTY(list))
1221  return;
1222 
1223  struct Buffer buf = mutt_buffer_make(256);
1224 
1225  struct ListNode *np = NULL;
1226  STAILQ_FOREACH(np, list, entries)
1227  {
1228  if (!mutt_buffer_is_empty(&buf))
1229  mutt_buffer_addch(&buf, ',');
1230  mutt_buffer_addstr(&buf, np->data);
1231  }
1232 
1233  dot_type_string(fp, name, mutt_buffer_string(&buf), false);
1234 }
1235 
1236 static void dot_addr_list(FILE *fp, const char *name,
1237  const struct AddressList *al, struct ListHead *links)
1238 {
1239  if (!al)
1240  return;
1241  if (TAILQ_EMPTY(al))
1242  return;
1243 
1244  char buf[1024] = { 0 };
1245 
1246  mutt_addrlist_write(al, buf, sizeof(buf), true);
1247  dot_type_string(fp, name, buf, false);
1248 }
1249 
1250 static void dot_envelope(FILE *fp, struct Envelope *env, struct ListHead *links)
1251 {
1252  struct Buffer buf = mutt_buffer_make(256);
1253 
1254  dot_object_header(fp, env, "Envelope", "#ffff00");
1255 
1256 #define ADD_FLAG(F) add_flag(&buf, (env->changed & F), #F)
1261 #undef ADD_BOOL
1262  dot_type_string(fp, "changed",
1263  mutt_buffer_is_empty(&buf) ? "[NONE]" : mutt_buffer_string(&buf), true);
1264 
1265 #define ADDR_LIST(AL) dot_addr_list(fp, #AL, &env->AL, links)
1266  ADDR_LIST(return_path);
1267  ADDR_LIST(from);
1268  ADDR_LIST(to);
1269  ADDR_LIST(cc);
1270  ADDR_LIST(bcc);
1271  ADDR_LIST(sender);
1272  ADDR_LIST(reply_to);
1273  ADDR_LIST(mail_followup_to);
1274  ADDR_LIST(x_original_to);
1275 #undef ADDR_LIST
1276 
1277  dot_type_string(fp, "date", env->date, false);
1278  dot_type_string(fp, "disp_subj", env->disp_subj, false);
1279  dot_type_string(fp, "followup_to", env->followup_to, false);
1280  dot_type_string(fp, "list_post", env->list_post, false);
1281  dot_type_string(fp, "message_id", env->message_id, false);
1282  dot_type_string(fp, "newsgroups", env->newsgroups, false);
1283  dot_type_string(fp, "organization", env->organization, false);
1284  dot_type_string(fp, "real_subj", env->real_subj, false);
1285  dot_type_string(fp, "spam", mutt_buffer_string(&env->spam), false);
1286  dot_type_string(fp, "subject", env->subject, false);
1287  dot_type_string(fp, "supersedes", env->supersedes, false);
1288  dot_type_string(fp, "xref", env->xref, false);
1289  dot_type_string(fp, "x_comment_to", env->x_comment_to, false);
1290  dot_type_string(fp, "x_label", env->x_label, false);
1291 
1292  if (0)
1293  {
1294  dot_list_head(fp, "references", &env->references);
1295  dot_list_head(fp, "in_reply_to", &env->in_reply_to);
1296  dot_list_head(fp, "userhdrs", &env->userhdrs);
1297  }
1298 
1299 #ifdef USE_AUTOCRYPT
1300  dot_ptr(fp, "autocrypt", env->autocrypt, NULL);
1301  dot_ptr(fp, "autocrypt_gossip", env->autocrypt_gossip, NULL);
1302 #endif
1303 
1304  dot_object_footer(fp);
1305 
1306  mutt_buffer_dealloc(&buf);
1307 }
1308 
1309 static void dot_email(FILE *fp, struct Email *e, struct ListHead *links)
1310 {
1311  struct Buffer buf = mutt_buffer_make(256);
1312  char arr[256];
1313 
1314  dot_object_header(fp, e, "Email", "#ff80ff");
1315 
1316  dot_type_string(fp, "path", e->path, true);
1317 
1318 #define ADD_BOOL(F) add_flag(&buf, e->F, #F)
1319  ADD_BOOL(active);
1320  ADD_BOOL(attach_del);
1321  ADD_BOOL(attach_valid);
1322  ADD_BOOL(changed);
1323  ADD_BOOL(collapsed);
1324  ADD_BOOL(deleted);
1325  ADD_BOOL(display_subject);
1326  ADD_BOOL(expired);
1327  ADD_BOOL(flagged);
1328  ADD_BOOL(matched);
1329  ADD_BOOL(mime);
1330  ADD_BOOL(old);
1331  ADD_BOOL(purge);
1332  ADD_BOOL(quasi_deleted);
1333  ADD_BOOL(read);
1334  ADD_BOOL(recip_valid);
1335  ADD_BOOL(replied);
1336  ADD_BOOL(searched);
1337  ADD_BOOL(subject_changed);
1338  ADD_BOOL(superseded);
1339  ADD_BOOL(tagged);
1340  ADD_BOOL(threaded);
1341  ADD_BOOL(trash);
1342  ADD_BOOL(visible);
1343 #undef ADD_BOOL
1344  dot_type_string(fp, "bools",
1345  mutt_buffer_is_empty(&buf) ? "[NONE]" : mutt_buffer_string(&buf), true);
1346 
1347  mutt_buffer_reset(&buf);
1348 #define ADD_BOOL(F) add_flag(&buf, (e->security & F), #F)
1350  ADD_BOOL(SEC_SIGN);
1363 #undef ADD_BOOL
1364  dot_type_string(fp, "security",
1365  mutt_buffer_is_empty(&buf) ? "[NONE]" : mutt_buffer_string(&buf), true);
1366 
1367  dot_type_number(fp, "num_hidden", e->num_hidden);
1368  dot_type_number(fp, "offset", e->offset);
1369  dot_type_number(fp, "lines", e->lines);
1370  dot_type_number(fp, "index", e->index);
1371  dot_type_number(fp, "msgno", e->msgno);
1372  dot_type_number(fp, "vnum", e->vnum);
1373  dot_type_number(fp, "score", e->score);
1374  dot_type_number(fp, "attach_total", e->attach_total);
1375 
1376  // struct MaildirEmailData *edata = maildir_edata_get(e);
1377  // if (edata)
1378  // dot_type_string(fp, "maildir_flags", edata->maildir_flags, false);
1379 
1380  if (e->date_sent != 0)
1381  {
1382  char zone[32];
1383  dot_type_date(arr, sizeof(arr), e->date_sent);
1384  snprintf(zone, sizeof(zone), " (%c%02u%02u)", e->zoccident ? '-' : '+',
1385  e->zhours, e->zminutes);
1386  mutt_str_cat(arr, sizeof(arr), zone);
1387  dot_type_string(fp, "date_sent", arr, false);
1388  }
1389 
1390  if (e->received != 0)
1391  {
1392  dot_type_date(arr, sizeof(arr), e->received);
1393  dot_type_string(fp, "received", arr, false);
1394  }
1395 
1396  dot_object_footer(fp);
1397 
1398  if (e->body)
1399  {
1400  dot_body(fp, e->body, links, true);
1401  dot_add_link(links, e, e->body, "Email->body", false, NULL);
1402  }
1403 
1404  if (e->env)
1405  {
1406  dot_envelope(fp, e->env, links);
1407  dot_add_link(links, e, e->env, "Email->env", false, NULL);
1408 
1409  mutt_buffer_reset(&buf);
1410  mutt_buffer_addstr(&buf, "{ rank=same ");
1411 
1412  dot_ptr_name(arr, sizeof(arr), e);
1413  mutt_buffer_add_printf(&buf, "%s ", arr);
1414 
1415  dot_ptr_name(arr, sizeof(arr), e->env);
1416  mutt_buffer_add_printf(&buf, "%s ", arr);
1417 
1418  mutt_buffer_addstr(&buf, "}");
1419 
1421  }
1422 
1423  // struct TagList tags;
1424 
1425  mutt_buffer_dealloc(&buf);
1426 }
1427 
1429 {
1430  char name[256] = { 0 };
1431  struct ListHead links = STAILQ_HEAD_INITIALIZER(links);
1432 
1433  time_t now = time(NULL);
1434  mutt_date_localtime_format(name, sizeof(name), "%R-email.gv", now);
1435 
1436  umask(022);
1437  FILE *fp = fopen(name, "w");
1438  if (!fp)
1439  return;
1440 
1441  dot_graph_header(fp);
1442 
1443  dot_email(fp, e, &links);
1444 
1445  dot_graph_footer(fp, &links);
1446  fclose(fp);
1447  mutt_list_free(&links);
1448 }
1449 
1450 static void dot_attach_ptr2(FILE *fp, struct AttachPtr *aptr, struct ListHead *links)
1451 {
1452  if (!aptr)
1453  return;
1454 
1455  struct Buffer buf = mutt_buffer_make(256);
1456 
1457  dot_object_header(fp, aptr, "AttachPtr", "#3bcbc4");
1458 
1459  dot_ptr(fp, "body", aptr->body, "#2020ff");
1460  dot_type_file(fp, "fp", aptr->fp);
1461 
1462  dot_type_string(fp, "parent_type", get_content_type(aptr->parent_type), false);
1463  dot_type_number(fp, "level", aptr->level);
1464  dot_type_number(fp, "num", aptr->num);
1465  dot_type_bool(fp, "unowned", aptr->unowned);
1466  dot_type_bool(fp, "decrypted", aptr->decrypted);
1467 
1468  // dot_type_string(fp, "tree", aptr->tree, false);
1469 
1470  dot_object_footer(fp);
1471 
1472  mutt_buffer_dealloc(&buf);
1473 }
1474 
1475 static void dot_array_actx_idx(FILE *fp, struct AttachPtr **idx, short idxlen,
1476  short idxmax, struct ListHead *links)
1477 {
1478  dot_object_header(fp, idx, "AttachCtx-&gt;idx", "#9347de");
1479 
1480  dot_type_number(fp, "idxlen", idxlen);
1481  dot_type_number(fp, "idxmax", idxmax);
1482 
1483  char arr[32];
1484  for (size_t i = 0; i < idxmax; i++)
1485  {
1486  snprintf(arr, sizeof(arr), "idx[%ld]", i);
1487  dot_ptr(fp, arr, idx[i], "#3bcbc4");
1488  }
1489 
1490  dot_object_footer(fp);
1491 
1492  for (size_t i = 0; i < idxlen; i++)
1493  {
1494  dot_attach_ptr2(fp, idx[i], links);
1495  dot_add_link(links, idx, idx[i], "AttachCtx-&gt;idx", false, NULL);
1496  }
1497 }
1498 
1499 static void dot_array_actx_v2r(FILE *fp, short *v2r, short vcount, struct ListHead *links)
1500 {
1501  dot_object_header(fp, v2r, "AttachCtx-&gt;v2r", "#9347de");
1502 
1503  dot_type_number(fp, "vcount", vcount);
1504 
1505  char arr[32];
1506  for (size_t i = 0; i < vcount; i++)
1507  {
1508  snprintf(arr, sizeof(arr), "v2r[%ld]", i);
1509  dot_type_number(fp, arr, v2r[i]);
1510  }
1511 
1512  dot_object_footer(fp);
1513 }
1514 
1515 static void dot_array_actx_fp_idx(FILE *fp, FILE **fp_idx, short fp_len,
1516  short fp_max, struct ListHead *links)
1517 {
1518  dot_object_header(fp, fp_idx, "AttachCtx-&gt;fp_idx", "#f86e28");
1519 
1520  dot_type_number(fp, "fp_len", fp_len);
1521  dot_type_number(fp, "fp_max", fp_max);
1522 
1523  char arr[32];
1524  for (size_t i = 0; i < fp_max; i++)
1525  {
1526  snprintf(arr, sizeof(arr), "fp_idx[%ld]", i);
1527  dot_type_file(fp, arr, fp_idx[i]);
1528  }
1529 
1530  dot_object_footer(fp);
1531 }
1532 
1533 static void dot_array_actx_body_idx(FILE *fp, struct Body **body_idx, short body_len,
1534  short body_max, struct ListHead *links)
1535 {
1536  dot_object_header(fp, body_idx, "AttachCtx-&gt;body_idx", "#4ff270");
1537 
1538  dot_type_number(fp, "body_len", body_len);
1539  dot_type_number(fp, "body_max", body_max);
1540 
1541  char arr[32];
1542  for (size_t i = 0; i < body_max; i++)
1543  {
1544  snprintf(arr, sizeof(arr), "body_idx[%ld]", i);
1545  dot_ptr(fp, arr, body_idx[i], "#2020ff");
1546  }
1547 
1548  dot_object_footer(fp);
1549 }
1550 
1551 static void dot_attach_ctx(FILE *fp, struct AttachCtx *actx, struct ListHead *links)
1552 {
1553  struct Buffer buf = mutt_buffer_make(256);
1554  // char arr[256];
1555 
1556  dot_object_header(fp, actx, "AttachCtx", "#9347de");
1557 
1558  dot_ptr(fp, "email", actx->email, "#ff80ff");
1559  dot_type_file(fp, "fp_root", actx->fp_root);
1560 
1561  dot_object_footer(fp);
1562 
1563  if (actx->idx)
1564  {
1565  dot_array_actx_idx(fp, actx->idx, actx->idxlen, actx->idxmax, links);
1566  dot_add_link(links, actx, actx->idx, "AttachCtx-&gt;idx", false, NULL);
1567  }
1568 
1569  if (actx->v2r)
1570  {
1571  dot_array_actx_v2r(fp, actx->v2r, actx->vcount, links);
1572  dot_add_link(links, actx, actx->v2r, "AttachCtx-&gt;v2r", false, NULL);
1573  }
1574 
1575  if (actx->fp_idx)
1576  {
1577  dot_array_actx_fp_idx(fp, actx->fp_idx, actx->fp_len, actx->fp_max, links);
1578  dot_add_link(links, actx, actx->fp_idx, "AttachCtx-&gt;fp_idx", false, NULL);
1579  }
1580 
1581  if (actx->body_idx)
1582  {
1583  dot_array_actx_body_idx(fp, actx->body_idx, actx->body_len, actx->body_max, links);
1584  dot_add_link(links, actx, actx->body_idx, "AttachCtx-&gt;body_idx", false, NULL);
1585  }
1586 
1587  mutt_buffer_dealloc(&buf);
1588 }
1589 
1591 {
1592  char name[256] = { 0 };
1593  struct ListHead links = STAILQ_HEAD_INITIALIZER(links);
1594 
1595  time_t now = time(NULL);
1596  mutt_date_localtime_format(name, sizeof(name), "%R-actx.gv", now);
1597 
1598  umask(022);
1599  FILE *fp = fopen(name, "w");
1600  if (!fp)
1601  return;
1602 
1603  dot_graph_header(fp);
1604 
1605  dot_attach_ctx(fp, actx, &links);
1606 
1607  dot_graph_footer(fp, &links);
1608  fclose(fp);
1609  mutt_list_free(&links);
1610 }
static void dot_array_actx_body_idx(FILE *fp, struct Body **body_idx, short body_len, short body_max, struct ListHead *links)
Definition: graphviz.c:1533
char * attribute
Parameter name.
Definition: parameter.h:34
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
ContentDisposition
Content-Disposition values.
Definition: mime.h:60
bool has_new_mail
Definition: mdata.h:42
static void dot_mailbox(FILE *fp, struct Mailbox *m, struct ListHead *links)
Definition: graphviz.c:600
The "current" mailbox.
Definition: context.h:37
union HashKey key
Key representing the data.
Definition: hash.h:46
static void dot_type_string(FILE *fp, const char *name, const char *str, bool force)
Definition: graphviz.c:220
const char * get_content_type(enum ContentType type)
Definition: graphviz.c:75
static void dot_envelope(FILE *fp, struct Envelope *env, struct ListHead *links)
Definition: graphviz.c:1250
Unknown Content-Type.
Definition: mime.h:31
static void dot_mailbox_node(FILE *fp, struct MailboxNode *mn, struct ListHead *links)
Definition: graphviz.c:679
int lines
How many lines in the body of this message?
Definition: email.h:85
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
char * newsrc_file
Definition: adata.h:52
static void dot_addr_list(FILE *fp, const char *name, const struct AddressList *al, struct ListHead *links)
Definition: graphviz.c:1236
An email to which things will be attached.
Definition: attach.h:34
char login[128]
Login name.
Definition: connaccount.h:54
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
int msg_count
Total number of messages.
Definition: mailbox.h:91
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
char * name
Name of Account.
Definition: account.h:39
const char * cmd_append
append-hook command
Definition: lib.h:48
static void dot_account_notmuch(FILE *fp, struct NmAccountData *adata, struct ListHead *links)
Definition: graphviz.c:832
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:691
IMAP network mailbox.
The envelope/body of an email.
Definition: email.h:37
FILE ** fp_idx
Extra FILE* used for decryption.
Definition: attach.h:61
#define TAILQ_FIRST(head)
Definition: queue.h:723
struct Content * content
Detailed info about the content of the attachment.
Definition: body.h:51
static void dot_type_number(FILE *fp, const char *name, int num)
Definition: graphviz.c:198
static void dot_array_actx_v2r(FILE *fp, short *v2r, short vcount, struct ListHead *links)
Definition: graphviz.c:1499
long linemax
Length of the longest line in the file.
Definition: content.h:40
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:40
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
struct Body * body
List of MIME parts.
Definition: email.h:91
struct AutocryptHeader * autocrypt_gossip
Definition: envelope.h:86
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: mailbox.h:52
short body_len
Number of Body parts.
Definition: attach.h:66
Structs that make up an email.
bool locked
is the mailbox locked?
Definition: lib.h:53
The "currently-open" mailbox.
bool append
mailbox is opened in append mode
Definition: lib.h:54
char * supersedes
Supersedes header.
Definition: envelope.h:70
7-bit text
Definition: mime.h:49
#define ADD_FLAG(F)
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:68
struct AccountList accounts
List of all Accounts.
Definition: neomutt.h:40
Maildir-specific Mailbox data.
struct Email * email
Used by recvattach for updating.
Definition: attach.h:51
short idxmax
Size of attachment array.
Definition: attach.h:56
char * xref
List of cross-references.
Definition: envelope.h:76
bool newsrc_modified
Definition: adata.h:50
static void dot_mailbox_maildir(FILE *fp, struct MaildirMboxData *mdata, struct ListHead *links)
Definition: graphviz.c:539
static void dot_content(FILE *fp, struct Content *cont, struct ListHead *links)
Definition: graphviz.c:1043
char * disp_subj
Display subject (modified copy of subject)
Definition: envelope.h:68
Notmuch-specific Account data.
Mbox-specific Account data -.
Definition: lib.h:48
char * date
Sent date.
Definition: envelope.h:71
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:75
static void dot_object_header(FILE *fp, const void *ptr, const char *name, const char *colour)
Definition: graphviz.c:330
const char * name
Scope name of Subset.
Definition: subset.h:48
Pop-specific Account data.
size_t idx
Definition: mailbox.c:257
static void dot_mailbox_nntp(FILE *fp, struct NntpMboxData *mdata, struct ListHead *links)
Definition: graphviz.c:566
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
struct Email * arr[10]
Definition: mailbox.c:256
struct MailboxList mailboxes
List of Mailboxes.
Definition: account.h:41
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
A group of associated Mailboxes.
Definition: account.h:36
struct timespec atime
File&#39;s last-access time.
Definition: lib.h:51
time_t mtime
Definition: adata.h:56
static void dot_connection(FILE *fp, struct Connection *c, struct ListHead *links)
Definition: graphviz.c:737
FILE * fp_root
Used by recvattach for updating.
Definition: attach.h:52
String manipulation buffer.
Definition: buffer.h:33
Type: &#39;audio/*&#39;.
Definition: mime.h:32
char user[128]
Username.
Definition: connaccount.h:55
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
struct ListHead userhdrs
user defined headers
Definition: envelope.h:83
struct Connection * conn
Definition: adata.h:38
static const char * timestamp(time_t stamp)
Create a YYYY-MM-DD HH:MM:SS timestamp.
Definition: logging.c:77
struct Mailbox * mailbox
Current selected mailbox.
Definition: adata.h:76
char * real_subj
Offset of the real subject.
Definition: envelope.h:67
static void dot_mailbox_type(FILE *fp, const char *name, enum MailboxType type)
Definition: graphviz.c:486
struct Body * next
next attachment in the list
Definition: body.h:53
short idxlen
Number of attachmentes.
Definition: attach.h:55
8-bit text
Definition: mime.h:50
struct AutocryptHeader * autocrypt
Definition: envelope.h:85
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:84
long hibin
8-bit characters
Definition: content.h:35
bool hasSTARTTLS
Definition: adata.h:39
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition: url.c:123
Imap-specific Account data.
enum MailboxType type
Type of Mailboxes this Account contains.
Definition: account.h:38
Type: &#39;*&#39; or &#39;.*&#39;.
Definition: mime.h:40
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
bool zoccident
True, if west of UTC, False if east.
Definition: email.h:65
char * form_name
Content-Disposition form-data name param.
Definition: body.h:41
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define DTYPE(x)
Mask for the Data Type.
Definition: types.h:44
NNTP-specific Account data -.
Definition: adata.h:36
#define MUTT_ENV_CHANGED_SUBJECT
Protected header update.
Definition: envelope.h:35
struct HashElem ** get_elem_list(struct ConfigSet *cs)
Create a sorted list of all config items.
Definition: subset.c:75
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
bool subscribed
Definition: mdata.h:41
int vcount
The number of virtual messages.
Definition: mailbox.h:102
The body of an email.
Definition: body.h:34
#define DT_SENSITIVE
Contains sensitive value, e.g. password.
Definition: types.h:49
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:67
Convenience wrapper for the config headers.
anum_t last_cached
Definition: mdata.h:39
unsigned char seqid
tag sequence prefix
Definition: adata.h:56
time_t tv_sec
Definition: file.h:50
Email Address Handling.
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:82
char host[128]
Server to login to.
Definition: connaccount.h:53
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
static void dot_comp(FILE *fp, struct CompressInfo *ci, struct ListHead *links)
Definition: graphviz.c:477
struct Body ** body_idx
Extra struct Body* used for decryption.
Definition: attach.h:65
char inbuf[1024]
Buffer for incoming traffic.
Definition: connection.h:42
static void dot_add_link(struct ListHead *links, void *src, void *dst, const char *label, bool back, const char *colour)
Definition: graphviz.c:272
notmuch_database_t * db
Definition: adata.h:36
const char * cmd_close
close-hook command
Definition: lib.h:49
Imap-specific Mailbox data.
#define ADDR_LIST(AL)
bool cacheable
Definition: adata.h:49
static void dot_graph_footer(FILE *fp, struct ListHead *links)
Definition: graphviz.c:319
char * name
A short name for the Mailbox.
Definition: mailbox.h:85
struct ConfigSet * cs
Parent ConfigSet.
Definition: subset.h:51
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:82
char * message_id
Message ID.
Definition: envelope.h:69
static void dot_node_link(FILE *fp, void *ptr, const char *name, void *link, const char *colour)
Definition: graphviz.c:369
Content is form-data.
Definition: mime.h:64
static void dot_path_fs(char *buf, size_t buflen, const char *path)
Definition: graphviz.c:389
static void dot_account_pop(FILE *fp, struct PopAccountData *adata, struct ListHead *links)
Definition: graphviz.c:839
struct Mailbox * mailbox
Definition: context.h:49
Type: &#39;video/*&#39;.
Definition: mime.h:39
Notmuch-specific Mailbox data -.
Definition: mdata.h:33
static void dot_config(FILE *fp, const char *name, int type, struct ConfigSubset *sub, struct ListHead *links)
Definition: graphviz.c:421
time_t newgroups_time
Definition: adata.h:57
static void dot_type_umask(char *buf, size_t buflen, int umask)
Definition: graphviz.c:245
static void dot_array_actx_idx(FILE *fp, struct AttachPtr **idx, short idxlen, short idxmax, struct ListHead *links)
Definition: graphviz.c:1475
const char * get_content_encoding(enum ContentEncoding enc)
Definition: graphviz.c:104
static void dot_account_imap(FILE *fp, struct ImapAccountData *adata, struct ListHead *links)
Definition: graphviz.c:753
anum_t last_loaded
Definition: mdata.h:38
static void dot_account_list(FILE *fp, struct AccountList *al, struct ListHead *links)
Definition: graphviz.c:915
int parent_type
Type of parent attachment, e.g. TYPE_MULTIPART.
Definition: attach.h:38
int cs_subset_he_string_get(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *result)
Get a config item as a string.
Definition: subset.c:354
struct Envelope * env
Envelope information.
Definition: email.h:90
bool hasLIST_NEWSGROUPS
Definition: adata.h:41
char * overview_fmt
Definition: adata.h:54
Convenience wrapper for the core headers.
char pass[256]
Password.
Definition: connaccount.h:56
char * group
Definition: mdata.h:34
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
Content is attached.
Definition: mime.h:63
signed short attach_count
Number of attachments.
Definition: body.h:59
short attach_total
Number of qualifying attachments in message, if attach_valid.
Definition: email.h:97
int mutt_buffer_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:203
static void dot_body(FILE *fp, struct Body *b, struct ListHead *links, bool link_next)
Definition: graphviz.c:1095
static void dot_type_string_escape(char *buf, size_t buflen)
Definition: graphviz.c:207
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
Compressed mbox local mailbox type.
Shared constants/structs that are private to IMAP.
const char * get_content_disposition(enum ContentDisposition disp)
Definition: graphviz.c:127
void * mdata
Driver specific data.
Definition: mailbox.h:136
Base-64 encoded text.
Definition: mime.h:52
mode_t mh_umask
Definition: mdata.h:37
&#39;Maildir&#39; Mailbox type
Definition: mailbox.h:51
Usenet network mailbox type; talk to an NNTP server.
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
bool unowned
Don&#39;t unlink on detach.
Definition: attach.h:42
short body_max
Size of Body array.
Definition: attach.h:67
int score
Message score.
Definition: email.h:89
char * subtype
content-type subtype
Definition: body.h:37
time_t date_sent
Time when the message was sent (UTC)
Definition: email.h:82
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
time_t check_time
Definition: adata.h:51
off_t vsize
Size (in bytes) of the messages shown.
Definition: context.h:39
Info about an attachment.
Definition: content.h:33
Maildir/MH private types.
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:88
#define DT_STRING
a string
Definition: types.h:41
bool decrypted
Not part of message as stored in the email->body.
Definition: attach.h:43
unsigned short port
Port to connect to.
Definition: connaccount.h:57
static void dot_mailbox_pop(FILE *fp, struct PopAccountData *adata, struct ListHead *links)
Definition: graphviz.c:593
char * x_comment_to
List of &#39;X-comment-to&#39; fields.
Definition: envelope.h:78
#define MUTT_ENV_CHANGED_XLABEL
X-Label edited.
Definition: envelope.h:34
A set of inherited config items.
Definition: subset.h:46
Notmuch virtual mailbox type.
static void dot_type_date(char *buf, size_t buflen, time_t timestamp)
Definition: graphviz.c:176
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:87
&#39;POP3&#39; Mailbox type
Definition: mailbox.h:55
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
int email_max
Number of pointers in emails.
Definition: mailbox.h:100
static void dot_path_imap(char *buf, size_t buflen, const char *path)
Definition: graphviz.c:406
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
A mailbox.
Definition: mailbox.h:81
bool hasXGTITLE
Definition: adata.h:42
struct ConfigSubset * sub
Inherited config items.
Definition: mailbox.h:86
char * user
Username.
Definition: url.h:71
static void dot_mailbox_list(FILE *fp, struct MailboxList *ml, struct ListHead *links, bool abbr)
Definition: graphviz.c:721
bool allowed
Definition: mdata.h:43
int num
Attachment index number.
Definition: attach.h:41
unsigned int groups_max
Definition: adata.h:60
int fd
Socket file descriptor.
Definition: connection.h:44
static void dot_account(FILE *fp, struct Account *a, struct ListHead *links)
Definition: graphviz.c:862
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
long ascii
Number of ascii chars.
Definition: content.h:39
size_t num_hidden
Number of hidden messages in this view (only valid when collapsed is set)
Definition: email.h:75
bool hasLISTGROUP
Definition: adata.h:43
#define SEC_AUTOCRYPT_OVERRIDE
(Autocrypt) Indicates manual set/unset of encryption
Definition: lib.h:85
struct AttachPtr * aptr
Menu information, used in recvattach.c.
Definition: body.h:57
Type: &#39;text/*&#39;.
Definition: mime.h:38
char * data
Pointer to data.
Definition: buffer.h:35
char * xtype
content-type if x-unknown
Definition: body.h:36
unsigned int groups_num
Definition: adata.h:59
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
Nntp-specific Mailbox data.
#define SEC_KEYBLOCK
Email has a key attached.
Definition: lib.h:81
&#39;mmdf&#39; Mailbox type
Definition: mailbox.h:49
#define DT_INHERIT_MBOX
Config item can be Mailbox-specific.
Definition: types.h:52
static void dot_object_footer(FILE *fp)
Definition: graphviz.c:347
bool qresync
true, if QRESYNC is successfully ENABLE&#39;d
Definition: adata.h:63
POP network mailbox.
char * charset
Send mode: charset of attached file as stored on disk.
Definition: body.h:49
FILE * fp
Used in the recvattach menu.
Definition: attach.h:37
static void dot_attach_ctx(FILE *fp, struct AttachCtx *actx, struct ListHead *links)
Definition: graphviz.c:1551
char * name
Mailbox name.
Definition: mdata.h:40
Compressed file Mailbox type.
Definition: mailbox.h:56
API for encryption/signing of emails.
&#39;MH&#39; Mailbox type
Definition: mailbox.h:50
char * host
Host.
Definition: url.h:73
void add_flag(struct Buffer *buf, bool is_set, const char *name)
Definition: graphviz.c:144
static void dot_array_actx_fp_idx(FILE *fp, FILE **fp_idx, short fp_len, short fp_max, struct ListHead *links)
Definition: graphviz.c:1515
int vnum
Virtual message number.
Definition: email.h:88
static void dot_account_nntp(FILE *fp, struct NntpAccountData *adata, struct ListHead *links)
Definition: graphviz.c:790
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
unsigned int zhours
Hours away from UTC.
Definition: email.h:63
char * description
content-description
Definition: body.h:40
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
#define DT_INHERIT_ACC
Config item can be Account-specific.
Definition: types.h:51
bool hasOVER
Definition: adata.h:45
Private data for compress.
Definition: lib.h:46
NNTP-specific Mailbox data -.
Definition: mdata.h:32
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:83
Maildir local mailbox type.
#define SEC_BADSIGN
Email has a bad signature.
Definition: lib.h:78
char * path
Path.
Definition: url.h:75
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
char * real_name
Original Mailbox name, e.g.: INBOX can be just \0.
Definition: mdata.h:42
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:54
static void dot_node(FILE *fp, void *ptr, const char *name, const char *colour)
Definition: graphviz.c:354
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:84
&#39;mbox&#39; Mailbox type
Definition: mailbox.h:48
char * list_post
This stores a mailto URL, or nothing.
Definition: envelope.h:65
static void dot_email(FILE *fp, struct Email *e, struct ListHead *links)
Definition: graphviz.c:1309
Type: &#39;message/*&#39;.
Definition: mime.h:35
static void dot_type_bool(FILE *fp, const char *name, bool val)
Definition: graphviz.c:157
char * mutt_str_cat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
Definition: string.c:385
#define SEC_SIGN
Email is signed.
Definition: lib.h:76
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:101
struct Connection * conn
Definition: adata.h:63
static void dot_mailbox_mbox(FILE *fp, struct MboxAccountData *mdata, struct ListHead *links)
Definition: graphviz.c:553
char * authenticators
Definition: adata.h:53
IMAP-specific Account data -.
Definition: adata.h:39
long lobin
Unprintable 7-bit chars (eg., control chars)
Definition: content.h:36
char * data
String.
Definition: list.h:36
char * subject
Email&#39;s subject.
Definition: envelope.h:66
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
char * value
Parameter value.
Definition: parameter.h:35
time_t check_time
Definition: adata.h:58
MailboxType
Supported mailbox formats.
Definition: mailbox.h:43
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:131
Maildir-specific Email data.
bool deleted
Definition: mdata.h:44
static void dot_list_head(FILE *fp, const char *name, const struct ListHead *list)
Definition: graphviz.c:1216
char * newsgroups
List of newsgroups.
Definition: envelope.h:75
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:749
No preferred disposition.
Definition: mime.h:65
IMAP-specific Mailbox data -.
Definition: mdata.h:38
bool hasLISTGROUPrange
Definition: adata.h:44
short * v2r
Mapping from virtual to real attachment.
Definition: attach.h:58
short fp_max
Size of FILE array.
Definition: attach.h:63
void dump_graphviz(const char *title, struct Context *ctx)
Definition: graphviz.c:945
bool collapsed
Are all threads collapsed?
Definition: context.h:47
anum_t first_message
Definition: mdata.h:36
time_t stamp
Time stamp of last encoding update.
Definition: body.h:61
anum_t unread
Definition: mdata.h:40
static void dot_ptr(FILE *fp, const char *name, void *ptr, const char *colour)
Definition: graphviz.c:255
const char * strkey
String key.
Definition: hash.h:36
static void dot_context(FILE *fp, struct Context *ctx, struct ListHead *links)
Definition: graphviz.c:933
void dot_attach_ptr(FILE *fp, struct AttachPtr *aptr, struct ListHead *links)
Definition: graphviz.c:1069
Binary.
Definition: mime.h:53
static void dot_ptr_name(char *buf, size_t buflen, const void *ptr)
Definition: graphviz.c:250
struct timespec mtime_cur
Definition: mdata.h:36
char * followup_to
List of &#39;followup-to&#39; fields.
Definition: envelope.h:77
Quoted-printable text.
Definition: mime.h:51
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:124
Type: &#39;model/*&#39;.
Definition: mime.h:36
Connection Library.
char * path
Path of Email (for local Mailboxes)
Definition: email.h:92
void dump_graphviz_attach_ctx(struct AttachCtx *actx)
Definition: graphviz.c:1590
#define ADD_BOOL(F)
long crlf
\r and \n characters
Definition: content.h:38
Attribute associated with a MIME part.
Definition: parameter.h:32
static void dot_account_mbox(FILE *fp, struct MboxAccountData *adata, struct ListHead *links)
Definition: graphviz.c:775
FILE * fp_newsrc
Definition: adata.h:51
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition: hash.h:45
int index
The absolute (unsorted) message number.
Definition: email.h:86
#define FREE(x)
Definition: memory.h:40
struct ConfigSubset * sub
Inherited config items.
Definition: account.h:40
static void dot_attach_ptr2(FILE *fp, struct AttachPtr *aptr, struct ListHead *links)
Definition: graphviz.c:1450
char * organization
Organisation header.
Definition: envelope.h:73
char * language
content-language (RFC8255)
Definition: body.h:38
#define STAILQ_EMPTY(head)
Definition: queue.h:348
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
bool hasXOVER
Definition: adata.h:46
static void dot_parameter_list(FILE *fp, const char *name, const struct ParameterList *pl)
Definition: graphviz.c:1025
The item stored in a Hash Table.
Definition: hash.h:43
Type: &#39;image/*&#39;.
Definition: mime.h:34
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
List of Mailboxes.
Definition: mailbox.h:156
#define PGP_TRADITIONAL_CHECKED
Email has a traditional (inline) signature.
Definition: lib.h:89
#define MUTT_ENV_CHANGED_REFS
References changed to break thread.
Definition: envelope.h:33
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
bool mutt_str_inline_replace(char *buf, size_t buflen, size_t xlen, const char *rstr)
Replace the beginning of a string.
Definition: string.c:1046
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:42
POP-specific Account data -.
Definition: adata.h:36
#define MUTT_ENV_CHANGED_IRT
In-Reply-To changed to link/break threads.
Definition: envelope.h:32
#define TAILQ_EMPTY(head)
Definition: queue.h:721
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:46
bool hasDATE
Definition: adata.h:40
bool hasCAPABILITIES
Definition: adata.h:38
Nntp-specific Account data.
struct Buffer pathbuf
Definition: mailbox.h:83
Convenience wrapper for the library headers.
struct ListHead references
message references (in reverse order)
Definition: envelope.h:81
A List node for strings.
Definition: list.h:34
static void dot_type_char(FILE *fp, const char *name, char ch)
Definition: graphviz.c:167
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
Notmuch private types.
char * munge_name
Munged version of the mailbox name.
Definition: mdata.h:41
Content is inline.
Definition: mime.h:62
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
char * pattern
Limit pattern string.
Definition: context.h:40
static void dot_graph_header(FILE *fp)
Definition: graphviz.c:296
char * x_label
X-Label.
Definition: envelope.h:72
struct Email * email
header information for message/rfc822
Definition: body.h:55
void dump_graphviz_email(struct Email *e)
Definition: graphviz.c:1428
FILE * fp
Mailbox file.
Definition: lib.h:50
static void dot_mailbox_notmuch(FILE *fp, struct NmMboxData *mdata, struct ListHead *links)
Definition: graphviz.c:586
#define STAILQ_FIRST(head)
Definition: queue.h:350
A set of attachments.
Definition: attach.h:49
int level
Nesting depth of attachment.
Definition: attach.h:40
Encoding unknown.
Definition: mime.h:48
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
#define SEC_GOODSIGN
Email has a valid signature.
Definition: lib.h:77
const char * cmd_open
open-hook command
Definition: lib.h:50
int db_limit
Maximum number of results to return.
Definition: mdata.h:37
long nulbin
Null characters (0x0)
Definition: content.h:37
size_t mutt_addrlist_write(const struct AddressList *al, char *buf, size_t buflen, bool display)
Write an Address to a buffer.
Definition: address.c:1150
unsigned int zminutes
Minutes away from UTC.
Definition: email.h:64
short fp_len
Number of FILE handles.
Definition: attach.h:62
#define SEC_PARTSIGN
Not all parts of the email is signed.
Definition: lib.h:79
Maildir-specific Mailbox data -.
Definition: mdata.h:34
Type: &#39;application/*&#39;.
Definition: mime.h:33
UUEncoded text.
Definition: mime.h:54
ContentEncoding
Content-Transfer-Encoding.
Definition: mime.h:46
Notmuch-specific Mailbox data.
static void dot_mailbox_imap(FILE *fp, struct ImapMboxData *mdata, struct ListHead *links)
Definition: graphviz.c:530
time_t received
Time when the message was placed in the mailbox.
Definition: email.h:83
bool unicode
If true, we can send UTF-8, and the server will use UTF8 rather than mUTF7.
Definition: adata.h:62
static void dot_type_file(FILE *fp, const char *name, FILE *struct_fp)
Definition: graphviz.c:181
The header of an Email.
Definition: envelope.h:54
struct Buffer spam
Spam header.
Definition: envelope.h:80
short vcount
The number of virtual attachments.
Definition: attach.h:59
int msgno
Number displayed to the user.
Definition: email.h:87
ContentType
Content-Type.
Definition: mime.h:29
#define SEC_SIGNOPAQUE
Email has an opaque signature (encrypted)
Definition: lib.h:80
Notmuch-specific Account data -.
Definition: adata.h:34
struct Connection * conn
Definition: adata.h:41
char * desc
Definition: mdata.h:35
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:158
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:234
anum_t last_message
Definition: mdata.h:37
POP network mailbox.
struct Body * body
Attachment.
Definition: attach.h:36