NeoMutt  2025-12-11-58-g09398d
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
graphviz.c
Go to the documentation of this file.
1
22
28
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 "attach/lib.h"
43#include "compmbox/lib.h"
44#include "expando/lib.h"
45#include "imap/lib.h"
46#include "maildir/lib.h"
47#include "mbox/lib.h"
48#include "ncrypt/lib.h"
49#include "nntp/lib.h"
50#include "pattern/lib.h"
51#include "pop/lib.h"
52#include "imap/adata.h" // IWYU pragma: keep
53#include "imap/mdata.h" // IWYU pragma: keep
54#include "imap/private.h" // IWYU pragma: keep
55#include "maildir/edata.h" // IWYU pragma: keep
56#include "maildir/mdata.h" // IWYU pragma: keep
57#include "mview.h"
58#include "nntp/adata.h" // IWYU pragma: keep
59#include "nntp/mdata.h" // IWYU pragma: keep
60#include "pop/adata.h" // IWYU pragma: keep
61#include "pop/private.h" // IWYU pragma: keep
62#ifdef USE_NOTMUCH
63#include "notmuch/lib.h"
64#include "notmuch/adata.h" // IWYU pragma: keep
65#include "notmuch/mdata.h" // IWYU pragma: keep
66#include "notmuch/private.h" // IWYU pragma: keep
67#endif
68
69// #define GV_HIDE_MVIEW
70#define GV_HIDE_MVIEW_CONTENTS
71// #define GV_HIDE_MBOX
72// #define GV_HIDE_NEOMUTT
73// #define GV_HIDE_CONFIG
74// #define GV_HIDE_ADATA
75// #define GV_HIDE_MDATA
76// #define GV_HIDE_BODY_CONTENT
77// #define GV_HIDE_ENVELOPE
78
79void dot_email(FILE *fp, struct Email *e, struct ListHead *links);
80void dot_envelope(FILE *fp, struct Envelope *env, struct ListHead *links);
81void dot_patternlist(FILE *fp, struct PatternList *pl, struct ListHead *links);
82void dot_expando_node(FILE *fp, struct ExpandoNode *node, struct ListHead *links);
83
84void dot_type_bool(FILE *fp, const char *name, bool val)
85{
86 static const char *values[] = { "false", "true" };
87 fprintf(fp, "\t\t<tr>\n");
88 fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%s</td>\n", name);
89 fprintf(fp, "\t\t\t<td border=\"0\">=</td>\n");
90 fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%s</td>\n", values[val]);
91 fprintf(fp, "\t\t</tr>\n");
92}
93
94#ifndef GV_HIDE_ADATA
95void dot_type_char(FILE *fp, const char *name, char ch)
96{
97 fprintf(fp, "\t\t<tr>\n");
98 fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%s</td>\n", name);
99 fprintf(fp, "\t\t\t<td border=\"0\">=</td>\n");
100 if (ch == '\0')
101 fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">NUL</td>\n");
102 else
103 fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">'%c'</td>\n", ch);
104 fprintf(fp, "\t\t</tr>\n");
105}
106#endif
107
108void dot_type_date(char *buf, size_t buflen, time_t timestamp)
109{
110 mutt_date_localtime_format(buf, buflen, "%Y-%m-%d %H:%M:%S", timestamp);
111}
112
113void dot_type_file(FILE *fp, const char *name, FILE *struct_fp)
114{
115 fprintf(fp, "\t\t<tr>\n");
116 fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%s</td>\n", name);
117 fprintf(fp, "\t\t\t<td border=\"0\">=</td>\n");
118 if (struct_fp)
119 {
120 fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%p (%d)</td>\n",
121 (void *) struct_fp, fileno(struct_fp));
122 }
123 else
124 {
125 fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">NULL</td>\n");
126 }
127 fprintf(fp, "\t\t</tr>\n");
128}
129
130void dot_type_number(FILE *fp, const char *name, int num)
131{
132 fprintf(fp, "\t\t<tr>\n");
133 fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%s</td>\n", name);
134 fprintf(fp, "\t\t\t<td border=\"0\">=</td>\n");
135 fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%d</td>\n", num);
136 fprintf(fp, "\t\t</tr>\n");
137}
138
140{
141 for (int i = buf_len(buf) - 1; i >= 0; i--)
142 {
143 if (buf_at(buf, i) == '<')
144 buf_inline_replace(buf, i, 1, "&lt;");
145 else if (buf_at(buf, i) == '>')
146 buf_inline_replace(buf, i, 1, "&gt;");
147 else if (buf_at(buf, 1) == '&')
148 buf_inline_replace(buf, i, 1, "&amp;");
149 }
150}
151
152void dot_type_string(FILE *fp, const char *name, const char *str, bool force)
153{
154 if ((!str || (str[0] == '\0')) && !force)
155 return;
156
157 struct Buffer *buf = buf_new(str);
158
159 if (!buf_is_empty(buf))
161
162 bool quoted = ((buf_at(buf, 0) != '[') && (buf_at(buf, 0) != '*'));
163
164 fprintf(fp, "\t\t<tr>\n");
165 fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%s</td>\n", name);
166 fprintf(fp, "\t\t\t<td border=\"0\">=</td>\n");
167 if (quoted)
168 fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">\"%s\"</td>\n", buf_string(buf));
169 else
170 fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%s</td>\n", buf_string(buf));
171 fprintf(fp, "\t\t</tr>\n");
172
173 buf_free(&buf);
174}
175
176#ifndef GV_HIDE_MDATA
177void dot_type_umask(char *buf, size_t buflen, int umask)
178{
179 snprintf(buf, buflen, "0%03o", umask);
180}
181#endif
182
183void dot_ptr_name(char *buf, size_t buflen, const void *ptr)
184{
185 snprintf(buf, buflen, "obj_%p", ptr);
186}
187
188void dot_ptr(FILE *fp, const char *name, void *ptr, const char *colour)
189{
190 fprintf(fp, "\t\t<tr>\n");
191 fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%s</td>\n", name);
192 fprintf(fp, "\t\t\t<td border=\"0\">=</td>\n");
193 if (colour && ptr)
194 {
195 fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\" bgcolor=\"%s\">%p</td>\n",
196 colour, ptr);
197 }
198 else
199 {
200 fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%p</td>\n", ptr);
201 }
202 fprintf(fp, "\t\t</tr>\n");
203}
204
205void dot_add_link(struct ListHead *links, void *src, void *dst, const char *label,
206 const char *short_label, bool back, const char *colour)
207{
208 if (!src || !dst)
209 return;
210 if (!colour)
211 colour = "#c0c0c0";
212
213 char obj1[64] = { 0 };
214 char obj2[64] = { 0 };
215 char text[512] = { 0 };
216 char lstr[128] = { 0 };
217 char sstr[128] = { 0 };
218
219 dot_ptr_name(obj1, sizeof(obj1), src);
220 dot_ptr_name(obj2, sizeof(obj2), dst);
221
222 if (label)
223 snprintf(lstr, sizeof(lstr), "edgetooltip=\"%s\"", label);
224
225 if (short_label)
226 snprintf(sstr, sizeof(sstr), "label=\"%s\"", short_label);
227
228 snprintf(text, sizeof(text), "%s -> %s [ %s %s %s color=\"%s\" ]", obj1, obj2,
229 back ? "dir=back" : "", lstr, sstr, colour);
231}
232
233void dot_graph_header(FILE *fp)
234{
235 fprintf(fp, "digraph neomutt\n");
236 fprintf(fp, "{\n\n");
237
238 fprintf(fp, "\tgraph [\n");
239 fprintf(fp, "\t\trankdir=\"TB\"\n");
240 fprintf(fp, "\t\tnodesep=\"0.5\"\n");
241 fprintf(fp, "\t\tranksep=\"0.5\"\n");
242 fprintf(fp, "\t];\n");
243 fprintf(fp, "\n");
244 fprintf(fp, "\tnode [\n");
245 fprintf(fp, "\t\tshape=\"plain\"\n");
246 fprintf(fp, "\t];\n");
247 fprintf(fp, "\n");
248 fprintf(fp, "\tedge [\n");
249 fprintf(fp, "\t\tpenwidth=\"4.5\"\n");
250 fprintf(fp, "\t\tarrowsize=\"1.0\"\n");
251 fprintf(fp, "\t\tcolor=\"#c0c0c0\"\n");
252 fprintf(fp, "\t];\n");
253 fprintf(fp, "\n");
254}
255
256void dot_graph_footer(FILE *fp, struct ListHead *links)
257{
258 fprintf(fp, "\n");
259 struct ListNode *np = NULL;
260 STAILQ_FOREACH(np, links, entries)
261 {
262 fprintf(fp, "\t%s;\n", np->data);
263 }
264 fprintf(fp, "\n}\n");
265}
266
267void dot_object_header(FILE *fp, const void *ptr, const char *name, const char *colour)
268{
269 char obj[64] = { 0 };
270 dot_ptr_name(obj, sizeof(obj), ptr);
271
272 if (!colour)
273 colour = "#ffff80";
274
275 fprintf(fp, "\t%s [\n", obj);
276 fprintf(fp, "\t\tlabel=<<table cellspacing=\"0\" border=\"1\" rows=\"*\" "
277 "color=\"#d0d0d0\">\n");
278 fprintf(fp, "\t\t<tr>\n");
279 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",
280 colour, name, ptr);
281 fprintf(fp, "\t\t</tr>\n");
282}
283
284void dot_object_footer(FILE *fp)
285{
286 fprintf(fp, "\t\t</table>>\n");
287 fprintf(fp, "\t];\n");
288 fprintf(fp, "\n");
289}
290
291void dot_node(FILE *fp, void *ptr, const char *name, const char *colour)
292{
293 char obj[64] = { 0 };
294 dot_ptr_name(obj, sizeof(obj), ptr);
295
296 fprintf(fp, "\t%s [\n", obj);
297 fprintf(fp, "\t\tlabel=<<table cellspacing=\"0\" border=\"1\" rows=\"*\" "
298 "color=\"#d0d0d0\">\n");
299 fprintf(fp, "\t\t<tr>\n");
300 fprintf(fp, "\t\t\t<td border=\"0\" bgcolor=\"%s\" port=\"top\"><font color=\"#000000\" point-size=\"20\"><b>%s</b></font></td>\n",
301 colour, name);
302 fprintf(fp, "\t\t</tr>\n");
304}
305
306void dot_path_fs(char *buf, size_t buflen, const char *path)
307{
308 if (!path)
309 {
310 buf[0] = '\0';
311 return;
312 }
313
314 const char *slash = strrchr(path, '/');
315 if (slash)
316 slash++;
317 else
318 slash = path;
319
320 mutt_str_copy(buf, slash, buflen);
321}
322
323void dot_path_imap(char *buf, size_t buflen, const char *path)
324{
325 char tmp[1024] = { 0 };
326 mutt_str_copy(tmp, path, sizeof(tmp));
327
328 struct Url *u = url_parse(tmp);
329
330 if (u->path && (u->path[0] != '\0'))
331 mutt_str_copy(buf, u->path, buflen);
332 else
333 snprintf(buf, buflen, "%s:%s", u->host, u->user);
334
335 url_free(&u);
336}
337
338#ifndef GV_HIDE_CONFIG
339void dot_config(FILE *fp, const char *name, int type, struct ConfigSubset *sub,
340 struct ListHead *links)
341{
342 if (!sub)
343 return;
344
345 struct Buffer *value = buf_pool_get();
346 dot_object_header(fp, (void *) name, "Config", "#ffff80");
347 dot_type_string(fp, "scope", sub->name, true);
348
349 if (sub->name)
350 {
351 char scope[256];
352 snprintf(scope, sizeof(scope), "%s:", sub->name);
353
354 struct HashElemArray hea = get_elem_list(sub->cs, GEL_ALL_CONFIG);
355 struct HashElem **hep = NULL;
356 ARRAY_FOREACH(hep, &hea)
357 {
358 struct HashElem *item = *hep;
359 if ((item->type & type) == 0)
360 continue;
361
362 const char *iname = item->key.strkey;
363 size_t slen = strlen(scope);
364 if (mutt_str_startswith(iname, scope) != 0)
365 {
366 if (strchr(iname + slen, ':'))
367 continue;
368 if ((CONFIG_TYPE(item->type) == DT_STRING) && (item->type & D_SENSITIVE))
369 {
370 dot_type_string(fp, iname + slen, "***", true);
371 }
372 else
373 {
374 buf_reset(value);
375 cs_subset_he_string_get(sub, item, value);
376 dot_type_string(fp, iname + slen, buf_string(value), true);
377 }
378 }
379 }
380 ARRAY_FREE(&hea);
381 }
382 else
383 {
384 struct HashElemArray hea = get_elem_list(sub->cs, GEL_ALL_CONFIG);
385 dot_type_number(fp, "count", ARRAY_SIZE(&hea));
386 ARRAY_FREE(&hea);
387 }
388
390 buf_pool_release(&value);
391}
392#endif
393
394void dot_comp(FILE *fp, struct CompressInfo *ci, struct ListHead *links)
395{
396 dot_object_header(fp, ci, "CompressInfo", "#c0c060");
397 dot_type_string(fp, "append", ci->cmd_append->string, true);
398 dot_type_string(fp, "close", ci->cmd_close->string, true);
399 dot_type_string(fp, "open", ci->cmd_open->string, true);
401}
402
403void dot_mailbox_type(FILE *fp, const char *name, enum MailboxType type)
404{
405 const char *typestr = NULL;
406
407 switch (type)
408 {
409 case MUTT_MBOX:
410 typestr = "MBOX";
411 break;
412 case MUTT_MMDF:
413 typestr = "MMDF";
414 break;
415 case MUTT_MH:
416 typestr = "MH";
417 break;
418 case MUTT_MAILDIR:
419 typestr = "MAILDIR";
420 break;
421 case MUTT_NNTP:
422 typestr = "NNTP";
423 break;
424 case MUTT_IMAP:
425 typestr = "IMAP";
426 break;
427 case MUTT_NOTMUCH:
428 typestr = "NOTMUCH";
429 break;
430 case MUTT_POP:
431 typestr = "POP";
432 break;
433 case MUTT_COMPRESSED:
434 typestr = "COMPRESSED";
435 break;
436 default:
437 typestr = "UNKNOWN";
438 }
439
440 fprintf(fp, "\t\t<tr>\n");
441 fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%s</td>\n", name);
442 fprintf(fp, "\t\t\t<td border=\"0\">=</td>\n");
443 fprintf(fp, "\t\t\t<td border=\"0\" align=\"left\">%s</td>\n", typestr);
444 fprintf(fp, "\t\t</tr>\n");
445}
446
447#ifndef GV_HIDE_MDATA
448void dot_mailbox_imap(FILE *fp, struct ImapMboxData *mdata, struct ListHead *links)
449{
450 dot_object_header(fp, mdata, "ImapMboxData", "#60c060");
451 dot_type_string(fp, "name", mdata->name, true);
452 dot_type_string(fp, "munge_name", mdata->munge_name, true);
453 dot_type_string(fp, "real_name", mdata->real_name, true);
455}
456
457void dot_mailbox_maildir(FILE *fp, struct MaildirMboxData *mdata, struct ListHead *links)
458{
459 char buf[64] = { 0 };
460
461 dot_object_header(fp, mdata, "MaildirMboxData", "#60c060");
462
463 dot_type_date(buf, sizeof(buf), mdata->mtime_cur.tv_sec);
464 dot_type_string(fp, "mtime_cur", buf, true);
465
466 dot_type_umask(buf, sizeof(buf), mdata->umask);
467 dot_type_string(fp, "umask", buf, true);
469}
470
471void dot_mailbox_mbox(FILE *fp, struct MboxAccountData *mdata, struct ListHead *links)
472{
473 char buf[64] = { 0 };
474
475 dot_object_header(fp, mdata, "MboxAccountData", "#60c060");
476 dot_ptr(fp, "fp", mdata->fp, NULL);
477
478 dot_type_date(buf, sizeof(buf), mdata->atime.tv_sec);
479 dot_type_string(fp, "atime", buf, true);
480
482}
483
484void dot_mailbox_nntp(FILE *fp, struct NntpMboxData *mdata, struct ListHead *links)
485{
486 dot_object_header(fp, mdata, "NntpMboxData", "#60c060");
487 dot_type_string(fp, "group", mdata->group, true);
488 dot_type_string(fp, "desc", mdata->desc, true);
489
490 dot_type_number(fp, "first_message", mdata->first_message);
491 dot_type_number(fp, "last_message", mdata->last_message);
492 dot_type_number(fp, "last_loaded", mdata->last_loaded);
493 dot_type_number(fp, "last_cached", mdata->last_cached);
494 dot_type_number(fp, "unread", mdata->unread);
495
496 dot_type_bool(fp, "subscribed", mdata->subscribed);
497 dot_type_bool(fp, "has_new_mail", mdata->has_new_mail);
498 dot_type_bool(fp, "allowed", mdata->allowed);
499 dot_type_bool(fp, "deleted", mdata->deleted);
500
502}
503
504#ifdef USE_NOTMUCH
505void dot_mailbox_notmuch(FILE *fp, struct NmMboxData *mdata, struct ListHead *links)
506{
507 dot_object_header(fp, mdata, "NmMboxData", "#60c060");
508 dot_type_number(fp, "db_limit", mdata->db_limit);
510}
511#endif
512
513void dot_mailbox_pop(FILE *fp, struct PopAccountData *adata, struct ListHead *links)
514{
515 dot_object_header(fp, adata, "PopAccountData", "#60c060");
516 dot_ptr(fp, "conn", adata->conn, "#ff8080");
518}
519#endif
520
521void dot_mailbox(FILE *fp, struct Mailbox *m, struct ListHead *links)
522{
523 char buf[64] = { 0 };
524
525 dot_object_header(fp, m, "Mailbox", "#80ff80");
526 dot_mailbox_type(fp, "type", m->type);
527 dot_type_string(fp, "name", m->name, false);
528
529 if ((m->type == MUTT_IMAP) || (m->type == MUTT_POP))
530 {
531 dot_path_imap(buf, sizeof(buf), buf_string(&m->pathbuf));
532 dot_type_string(fp, "pathbuf", buf, true);
533 dot_path_imap(buf, sizeof(buf), m->realpath);
534 dot_type_string(fp, "realpath", buf, true);
535 }
536 else
537 {
538 dot_path_fs(buf, sizeof(buf), buf_string(&m->pathbuf));
539 dot_type_string(fp, "pathbuf", buf, true);
540 dot_path_fs(buf, sizeof(buf), m->realpath);
541 dot_type_string(fp, "realpath", buf, true);
542 }
543
544#ifdef GV_HIDE_MDATA
545 dot_ptr(fp, "mdata", m->mdata, NULL);
546#endif
547 dot_ptr(fp, "account", m->account, "#80ffff");
548 dot_type_number(fp, "opened", m->opened);
549
550 dot_type_number(fp, "msg_count", m->msg_count);
551 // dot_type_number(fp, "msg_unread", m->msg_unread);
552 // dot_type_number(fp, "msg_flagged", m->msg_flagged);
553 // dot_type_number(fp, "msg_new", m->msg_new);
554 // dot_type_number(fp, "msg_deleted", m->msg_deleted);
555 // dot_type_number(fp, "msg_tagged", m->msg_tagged);
556
557 dot_ptr(fp, "emails", m->emails, NULL);
558 dot_type_number(fp, "email_max", m->email_max);
559 dot_ptr(fp, "v2r", m->v2r, NULL);
560 dot_type_number(fp, "vcount", m->vcount);
561
563
564 // dot_add_link(links, m, m->mdata, NULL, NULL, false, NULL);
565
566#ifndef GV_HIDE_MDATA
567 if (m->mdata)
568 {
569 if (m->type == MUTT_MAILDIR)
570 dot_mailbox_maildir(fp, m->mdata, links);
571 else if (m->type == MUTT_IMAP)
572 dot_mailbox_imap(fp, m->mdata, links);
573 else if (m->type == MUTT_POP)
574 dot_mailbox_pop(fp, m->mdata, links);
575 else if (m->type == MUTT_MBOX)
576 dot_mailbox_mbox(fp, m->mdata, links);
577 else if (m->type == MUTT_NNTP)
578 dot_mailbox_nntp(fp, m->mdata, links);
579#ifdef USE_NOTMUCH
580 else if (m->type == MUTT_NOTMUCH)
581 dot_mailbox_notmuch(fp, m->mdata, links);
582#endif
583
584 dot_add_link(links, m, m->mdata, "Mailbox->mdata", NULL, false, NULL);
585 }
586#endif
587
588 if (m->compress_info)
589 {
590 dot_comp(fp, m->compress_info, links);
591 dot_add_link(links, m, m->compress_info, "Mailbox->compress_info", NULL, false, NULL);
592 }
593
594#ifndef GV_HIDE_CONFIG
595 if (m->name)
596 {
597 dot_config(fp, m->name, 0, m->sub, links);
598 dot_add_link(links, m, m->name, "Mailbox Config", NULL, false, NULL);
599 }
600#endif
601}
602
603void dot_mailbox_array(FILE *fp, struct MailboxArray *ma, struct ListHead *links)
604{
605 struct Buffer *buf = buf_pool_get();
606
607 char name[256] = { 0 };
608 buf_addstr(buf, "{ rank=same ");
609
610 struct Mailbox *prev = NULL;
611 struct Mailbox **mp = NULL;
612 ARRAY_FOREACH(mp, ma)
613 {
614 struct Mailbox *m = *mp;
615
616 dot_mailbox(fp, m, links);
617 if (prev)
618 dot_add_link(links, prev, m, "MailboxNode->next", NULL, false, NULL);
619
620 dot_ptr_name(name, sizeof(name), m);
621 buf_add_printf(buf, "%s ", name);
622
623 prev = m;
624 }
625
626 buf_addstr(buf, "}");
628 buf_pool_release(&buf);
629}
630
631#ifndef GV_HIDE_ADATA
632void dot_connection(FILE *fp, struct Connection *c, struct ListHead *links)
633{
634 dot_object_header(fp, c, "Connection", "#ff8080");
635 // dot_ptr(fp, "sockdata", c->sockdata, "#60c0c0");
636 dot_type_number(fp, "fd", c->fd);
638
639 dot_object_header(fp, c->inbuf, "ConnAccount", "#ff8080");
640 dot_type_string(fp, "user", c->account.user, true);
641 dot_type_string(fp, "host", c->account.host, true);
642 dot_type_number(fp, "port", c->account.port);
644
645 dot_add_link(links, c, c->inbuf, "Connection.ConnAccount", NULL, false, NULL);
646}
647
648void dot_account_imap(FILE *fp, struct ImapAccountData *adata, struct ListHead *links)
649{
650 dot_object_header(fp, adata, "ImapAccountData", "#60c0c0");
651 // dot_type_string(fp, "mbox_name", adata->mbox_name, true);
652 // dot_type_string(fp, "login", adata->conn->account.login, true);
653 dot_type_string(fp, "user", adata->conn->account.user, true);
654 dot_type_string(fp, "pass", adata->conn->account.pass[0] ? "***" : "", true);
655 dot_type_number(fp, "port", adata->conn->account.port);
656 // dot_ptr(fp, "conn", adata->conn, "#ff8080");
657 dot_type_bool(fp, "unicode", adata->unicode);
658 dot_type_bool(fp, "qresync", adata->qresync);
659 dot_type_char(fp, "seqid", adata->seqid);
660 dot_ptr(fp, "mailbox", adata->mailbox, "#80ff80");
662
663 if (adata->conn)
664 {
665 dot_connection(fp, adata->conn, links);
666 dot_add_link(links, adata, adata->conn, "ImapAccountData->conn", NULL, false, NULL);
667 }
668}
669
670void dot_account_mbox(FILE *fp, struct MboxAccountData *adata, struct ListHead *links)
671{
672 char buf[64] = { 0 };
673
674 dot_object_header(fp, adata, "MboxAccountData", "#60c0c0");
675 dot_ptr(fp, "fp", adata->fp, NULL);
676
677 dot_type_date(buf, sizeof(buf), adata->atime.tv_sec);
678 dot_type_string(fp, "atime", buf, true);
679 dot_type_bool(fp, "locked", adata->locked);
680 dot_type_bool(fp, "append", adata->append);
681
683}
684
685void dot_account_nntp(FILE *fp, struct NntpAccountData *adata, struct ListHead *links)
686{
687 dot_object_header(fp, adata, "NntpAccountData", "#60c0c0");
688 dot_type_number(fp, "groups_num", adata->groups_num);
689
690 dot_type_bool(fp, "hasCAPABILITIES", adata->hasCAPABILITIES);
691 dot_type_bool(fp, "hasSTARTTLS", adata->hasSTARTTLS);
692 dot_type_bool(fp, "hasDATE", adata->hasDATE);
693 dot_type_bool(fp, "hasLIST_NEWSGROUPS", adata->hasLIST_NEWSGROUPS);
694 dot_type_bool(fp, "hasXGTITLE", adata->hasXGTITLE);
695 dot_type_bool(fp, "hasLISTGROUP", adata->hasLISTGROUP);
696 dot_type_bool(fp, "hasLISTGROUPrange", adata->hasLISTGROUPrange);
697 dot_type_bool(fp, "hasOVER", adata->hasOVER);
698 dot_type_bool(fp, "hasXOVER", adata->hasXOVER);
699 dot_type_bool(fp, "cacheable", adata->cacheable);
700 dot_type_bool(fp, "newsrc_modified", adata->newsrc_modified);
701
702 dot_type_string(fp, "authenticators", adata->authenticators, true);
703 dot_type_string(fp, "overview_fmt", adata->overview_fmt, true);
704 dot_type_string(fp, "newsrc_file", adata->newsrc_file, true);
705 dot_type_file(fp, "newsrc_fp", adata->fp_newsrc);
706
707 dot_type_number(fp, "groups_num", adata->groups_num);
708 dot_type_number(fp, "groups_max", adata->groups_max);
709
710 char buf[128];
711 dot_type_date(buf, sizeof(buf), adata->mtime);
712 dot_type_string(fp, "mtime", buf, true);
713 dot_type_date(buf, sizeof(buf), adata->newgroups_time);
714 dot_type_string(fp, "newgroups_time", buf, true);
715 dot_type_date(buf, sizeof(buf), adata->check_time);
716 dot_type_string(fp, "check_time", buf, true);
717
719
720 if (adata->conn)
721 {
722 dot_connection(fp, adata->conn, links);
723 dot_add_link(links, adata, adata->conn, "NntpAccountData->conn", NULL, false, NULL);
724 }
725}
726
727#ifdef USE_NOTMUCH
728void dot_account_notmuch(FILE *fp, struct NmAccountData *adata, struct ListHead *links)
729{
730 dot_object_header(fp, adata, "NmAccountData", "#60c0c0");
731 dot_ptr(fp, "db", adata->db, NULL);
733}
734#endif
735
736void dot_account_pop(FILE *fp, struct PopAccountData *adata, struct ListHead *links)
737{
738 char buf[64] = { 0 };
739
740 dot_object_header(fp, adata, "PopAccountData", "#60c0c0");
741
742 dot_type_date(buf, sizeof(buf), adata->check_time);
743 dot_type_string(fp, "check_time", buf, true);
744
745 dot_type_string(fp, "login", adata->conn->account.login, true);
746 dot_type_string(fp, "user", adata->conn->account.user, true);
747 dot_type_string(fp, "pass", adata->conn->account.pass[0] ? "***" : "", true);
748 dot_type_number(fp, "port", adata->conn->account.port);
749 // dot_ptr(fp, "conn", adata->conn, "#ff8080");
751
752 dot_connection(fp, adata->conn, links);
753 dot_add_link(links, adata, adata->conn, "PopAccountData->conn", NULL, false, NULL);
754}
755#endif
756
757void dot_account(FILE *fp, struct Account *a, struct ListHead *links)
758{
759 dot_object_header(fp, a, "Account", "#80ffff");
760 dot_mailbox_type(fp, "type", a->type);
761 dot_type_string(fp, "name", a->name, true);
762 // dot_ptr(fp, "adata", a->adata, "#60c0c0");
764
765#ifndef GV_HIDE_ADATA
766 if (a->adata)
767 {
768 if (a->type == MUTT_IMAP)
769 dot_account_imap(fp, a->adata, links);
770 else if (a->type == MUTT_POP)
771 dot_account_pop(fp, a->adata, links);
772 else if (a->type == MUTT_MBOX)
773 dot_account_mbox(fp, a->adata, links);
774 else if (a->type == MUTT_NNTP)
775 dot_account_nntp(fp, a->adata, links);
776#ifdef USE_NOTMUCH
777 else if (a->type == MUTT_NOTMUCH)
778 dot_account_notmuch(fp, a->adata, links);
779#endif
780
781 dot_add_link(links, a, a->adata, "Account->adata", NULL, false, NULL);
782 }
783#endif
784
785#ifndef GV_HIDE_CONFIG
786 if (a->name)
787 {
788 dot_config(fp, a->name, 0, a->sub, links);
789 dot_add_link(links, a, a->name, "Config", NULL, false, NULL);
790
791 char name[256] = { 0 };
792 struct Buffer *buf = buf_pool_get();
793
794 buf_addstr(buf, "{ rank=same ");
795
796 dot_ptr_name(name, sizeof(name), a);
797 buf_add_printf(buf, "%s ", name);
798
799 dot_ptr_name(name, sizeof(name), a->name);
800 buf_add_printf(buf, "%s ", name);
801
802 buf_addstr(buf, "}");
804 buf_pool_release(&buf);
805 }
806#endif
807
808 struct Mailbox **mp = ARRAY_FIRST(&a->mailboxes);
809 if (mp && *mp)
810 {
811 dot_add_link(links, a, *mp, "Account->mailboxes", NULL, false, NULL);
812 dot_mailbox_array(fp, &a->mailboxes, links);
813 }
814}
815
816void dot_account_array(FILE *fp, struct AccountArray *aa, struct ListHead *links)
817{
818 struct Account *prev = NULL;
819 struct Account **ap = NULL;
820 ARRAY_FOREACH(ap, aa)
821 {
822 struct Account *a = *ap;
823
824#ifdef GV_HIDE_MBOX
825 if (a->type == MUTT_MBOX)
826 continue;
827#endif
828 dot_account(fp, a, links);
829 if (prev)
830 dot_add_link(links, prev, a, "Account->next", NULL, false, NULL);
831
832 prev = a;
833 }
834}
835
836#ifndef GV_HIDE_MVIEW
837void dot_mview(FILE *fp, struct MailboxView *mv, struct ListHead *links)
838{
839 dot_object_header(fp, mv, "MailboxView", "#ff80ff");
840 dot_ptr(fp, "mailbox", mv->mailbox, "#80ff80");
841#ifdef GV_HIDE_MVIEW_CONTENTS
842 dot_type_number(fp, "vsize", mv->vsize);
843 dot_type_string(fp, "pattern", mv->pattern, true);
844 dot_type_bool(fp, "collapsed", mv->collapsed);
845#endif
847}
848#endif
849
850void dump_graphviz(const char *title, struct MailboxView *mv)
851{
852 char name[256] = { 0 };
853 struct ListHead links = STAILQ_HEAD_INITIALIZER(links);
854
855 time_t now = time(NULL);
856 if (title)
857 {
858 char date[128];
859 mutt_date_localtime_format(date, sizeof(date), "%T", now);
860 snprintf(name, sizeof(name), "%s-%s.gv", date, title);
861 }
862 else
863 {
864 mutt_date_localtime_format(name, sizeof(name), "%T.gv", now);
865 }
866
867 umask(022);
868 FILE *fp = fopen(name, "w");
869 if (!fp)
870 return;
871
873
874#ifndef GV_HIDE_NEOMUTT
875 dot_node(fp, NeoMutt, "NeoMutt", "#ffa500");
876 struct Account **ap = ARRAY_FIRST(&NeoMutt->accounts);
877 if (ap && *ap)
878 {
879 dot_add_link(&links, NeoMutt, *ap, "NeoMutt->accounts", NULL, false, NULL);
880 }
881#ifndef GV_HIDE_CONFIG
882 dot_config(fp, (const char *) NeoMutt->sub, 0, NeoMutt->sub, &links);
883 dot_add_link(&links, NeoMutt, NeoMutt->sub, "NeoMutt Config", NULL, false, NULL);
884 struct Buffer *buf = buf_pool_get();
885 char obj1[64] = { 0 };
886 char obj2[64] = { 0 };
887 dot_ptr_name(obj1, sizeof(obj1), NeoMutt);
888 dot_ptr_name(obj2, sizeof(obj2), NeoMutt->sub);
889 buf_printf(buf, "{ rank=same %s %s }", obj1, obj2);
890 mutt_list_insert_tail(&links, buf_strdup(buf));
891 buf_pool_release(&buf);
892#endif
893#endif
894
895 dot_account_array(fp, &NeoMutt->accounts, &links);
896
897#ifndef GV_HIDE_MVIEW
898 if (mv)
899 dot_mview(fp, mv, &links);
900
901#ifndef GV_HIDE_NEOMUTT
902 /* Globals */
903 fprintf(fp, "\t{ rank=same ");
904 if (mv)
905 {
906 dot_ptr_name(name, sizeof(name), mv);
907 fprintf(fp, "%s ", name);
908 }
909 dot_ptr_name(name, sizeof(name), NeoMutt);
910 fprintf(fp, "%s ", name);
911 fprintf(fp, "}\n");
912#endif
913#endif
914
915 fprintf(fp, "\t{ rank=same ");
917 {
918 struct Account *a = *ap;
919
920#ifdef GV_HIDE_MBOX
921 if (a->type == MUTT_MBOX)
922 continue;
923#endif
924 dot_ptr_name(name, sizeof(name), a);
925 fprintf(fp, "%s ", name);
926 }
927 fprintf(fp, "}\n");
928
929 dot_graph_footer(fp, &links);
930 fclose(fp);
931 mutt_list_free(&links);
932}
933
934#ifndef GV_HIDE_BODY_CONTENT
935void dot_parameter_list(FILE *fp, const char *name, const struct ParameterList *pl)
936{
937 if (!pl)
938 return;
939 if (TAILQ_EMPTY(pl))
940 return;
941
942 dot_object_header(fp, pl, "ParameterList", "#00ff00");
943
944 struct Parameter *np = NULL;
945 TAILQ_FOREACH(np, pl, entries)
946 {
947 dot_type_string(fp, np->attribute, np->value, false);
948 }
949
951}
952
953void dot_content(FILE *fp, struct Content *cont, struct ListHead *links)
954{
955 struct Buffer *buf = buf_pool_get();
956
957 dot_object_header(fp, cont, "Content", "#800080");
958
959 dot_type_number(fp, "hibin", cont->hibin);
960 dot_type_number(fp, "lobin", cont->lobin);
961 dot_type_number(fp, "nulbin", cont->nulbin);
962 dot_type_number(fp, "crlf", cont->crlf);
963 dot_type_number(fp, "ascii", cont->ascii);
964 dot_type_number(fp, "linemax", cont->linemax);
965
966#define ADD_BOOL(F) add_flag(buf, cont->F, #F)
967 ADD_BOOL(space);
968 ADD_BOOL(binary);
969 ADD_BOOL(from);
970 ADD_BOOL(dot);
971 ADD_BOOL(cr);
972#undef ADD_BOOL
973
975
976 buf_pool_release(&buf);
977}
978#endif
979
980void dot_attach_ptr(FILE *fp, struct AttachPtr *aptr, struct ListHead *links)
981{
982 if (!aptr)
983 return;
984
985 dot_object_header(fp, aptr, "AttachPtr", "#ff0000");
986
987 dot_type_file(fp, "fp", aptr->fp);
988
989 dot_type_string(fp, "parent_type", name_content_type(aptr->parent_type), false);
990
991 dot_type_number(fp, "level", aptr->level);
992 dot_type_number(fp, "num", aptr->num);
993
994 dot_type_bool(fp, "unowned", aptr->unowned);
995 dot_type_bool(fp, "collapsed", aptr->collapsed);
996 dot_type_bool(fp, "decrypted", aptr->decrypted);
997
999
1000 dot_add_link(links, aptr->body, aptr, "AttachPtr->body", NULL, true, NULL);
1001}
1002
1003void dot_body(FILE *fp, struct Body *b, struct ListHead *links, bool link_next)
1004{
1005 struct Buffer *buf = buf_pool_get();
1006
1007 dot_object_header(fp, b, "Body", "#2020ff");
1008
1009 char file[256];
1010 dot_path_fs(file, sizeof(file), b->filename);
1011 dot_type_string(fp, "file", file, false);
1012
1013 dot_type_string(fp, "charset", b->charset, false);
1014 dot_type_string(fp, "description", b->description, false);
1015 dot_type_string(fp, "d_filename", b->d_filename, false);
1016 dot_type_string(fp, "form_name", b->form_name, false);
1017 dot_type_string(fp, "language", b->language, false);
1018 dot_type_string(fp, "subtype", b->subtype, false);
1019 dot_type_string(fp, "xtype", b->xtype, false);
1020
1021 dot_type_string(fp, "type", name_content_type(b->type), true);
1022 dot_type_string(fp, "encoding", name_content_encoding(b->encoding), true);
1023 dot_type_string(fp, "disposition", name_content_disposition(b->disposition), true);
1024
1025 if (b->stamp != 0)
1026 {
1027 char arr[64];
1028 dot_type_date(arr, sizeof(arr), b->stamp);
1029 dot_type_string(fp, "stamp", arr, true);
1030 }
1031
1032#define ADD_BOOL(F) add_flag(buf, b->F, #F)
1033 ADD_BOOL(attach_qualifies);
1034 ADD_BOOL(badsig);
1035 ADD_BOOL(deleted);
1036 ADD_BOOL(force_charset);
1037 ADD_BOOL(goodsig);
1038#ifdef USE_AUTOCRYPT
1039 ADD_BOOL(is_autocrypt);
1040#endif
1041 ADD_BOOL(noconv);
1042 ADD_BOOL(tagged);
1043 ADD_BOOL(unlink);
1044 ADD_BOOL(use_disp);
1045 ADD_BOOL(warnsig);
1046#undef ADD_BOOL
1047 dot_type_string(fp, "bools", buf_is_empty(buf) ? "[NONE]" : buf_string(buf), true);
1048
1049 dot_type_number(fp, "attach_count", b->attach_count);
1050 dot_type_number(fp, "hdr_offset", b->hdr_offset);
1051 dot_type_number(fp, "length", b->length);
1052 dot_type_number(fp, "offset", b->offset);
1053
1054 dot_ptr(fp, "aptr", b->aptr, "#3bcbc4");
1055
1056#ifdef GV_HIDE_BODY_CONTENT
1057 if (!TAILQ_EMPTY(&b->parameter))
1058 {
1059 struct Parameter *param = TAILQ_FIRST(&b->parameter);
1060 if (mutt_str_equal(param->attribute, "boundary"))
1061 {
1062 dot_type_string(fp, "boundary", param->value, false);
1063 }
1064 }
1065#endif
1066
1068
1069#ifndef GV_HIDE_BODY_CONTENT
1070 if (!TAILQ_EMPTY(&b->parameter))
1071 {
1072 dot_parameter_list(fp, "parameter", &b->parameter);
1073 dot_add_link(links, b, &b->parameter, "Body->mime_headers", NULL, false, NULL);
1074 }
1075#endif
1076
1077#ifndef GV_HIDE_ENVELOPE
1078 if (b->mime_headers)
1079 {
1080 dot_envelope(fp, b->mime_headers, links);
1081 dot_add_link(links, b, b->mime_headers, "Body->mime_headers", NULL, false, NULL);
1082 }
1083#endif
1084
1085 if (b->email)
1086 {
1087 dot_email(fp, b->email, links);
1088 dot_add_link(links, b, b->email, "Body->email", NULL, false, NULL);
1089 }
1090
1091 if (b->parts)
1092 {
1093 if (!b->email)
1094 dot_body(fp, b->parts, links, true);
1095 dot_add_link(links, b, b->parts, "Body->parts", NULL, false, "#ff0000");
1096 }
1097
1098 if (b->next && link_next)
1099 {
1100 char name[256] = { 0 };
1101 buf_reset(buf);
1102
1103 buf_addstr(buf, "{ rank=same ");
1104
1105 dot_ptr_name(name, sizeof(name), b);
1106 buf_add_printf(buf, "%s ", name);
1107
1108 for (; b->next; b = b->next)
1109 {
1110 dot_body(fp, b->next, links, false);
1111 dot_add_link(links, b, b->next, "Body->next", NULL, false, "#008000");
1112
1113 dot_ptr_name(name, sizeof(name), b->next);
1114 buf_add_printf(buf, "%s ", name);
1115 }
1116
1117 buf_addstr(buf, "}");
1118 mutt_list_insert_tail(links, buf_strdup(buf));
1119 }
1120 else
1121 {
1122#ifndef GV_HIDE_BODY_CONTENT
1123 if (b->content)
1124 {
1125 dot_content(fp, b->content, links);
1126 dot_add_link(links, b, b->content, "Body->content", NULL, false, NULL);
1127 }
1128#endif
1129
1130 // if (b->aptr)
1131 // {
1132 // dot_attach_ptr(fp, b->aptr, links);
1133 // dot_add_link(links, b, b->aptr, "Body->aptr", NULL, false, NULL);
1134 // }
1135 }
1136
1137 buf_pool_release(&buf);
1138}
1139
1140#ifndef GV_HIDE_ENVELOPE
1141void dot_list_head(FILE *fp, const char *name, const struct ListHead *list)
1142{
1143 if (!list || !name)
1144 return;
1145 if (STAILQ_EMPTY(list))
1146 return;
1147
1148 struct Buffer *buf = buf_pool_get();
1149
1150 struct ListNode *np = NULL;
1151 STAILQ_FOREACH(np, list, entries)
1152 {
1153 if (!buf_is_empty(buf))
1154 buf_addch(buf, ',');
1155 buf_addstr(buf, np->data);
1156 }
1157
1158 dot_type_string(fp, name, buf_string(buf), false);
1159 buf_pool_release(&buf);
1160}
1161
1162void dot_addr_list(FILE *fp, const char *name, const struct AddressList *al,
1163 struct ListHead *links)
1164{
1165 if (!al)
1166 return;
1167 if (TAILQ_EMPTY(al))
1168 return;
1169
1170 struct Buffer *buf = buf_pool_get();
1171 mutt_addrlist_write(al, buf, true);
1172 dot_type_string(fp, name, buf_string(buf), false);
1173 buf_pool_release(&buf);
1174}
1175
1176void dot_envelope(FILE *fp, struct Envelope *env, struct ListHead *links)
1177{
1178 struct Buffer *buf = buf_pool_get();
1179
1180 dot_object_header(fp, env, "Envelope", "#ffff00");
1181
1182#define ADD_FLAG(F) add_flag(buf, (env->changed & F), #F)
1187#undef ADD_BOOL
1188 dot_type_string(fp, "changed", buf_is_empty(buf) ? "[NONE]" : buf_string(buf), true);
1189
1190#define ADDR_LIST(AL) dot_addr_list(fp, #AL, &env->AL, links)
1191 ADDR_LIST(return_path);
1192 ADDR_LIST(from);
1193 ADDR_LIST(to);
1194 ADDR_LIST(cc);
1195 ADDR_LIST(bcc);
1196 ADDR_LIST(sender);
1197 ADDR_LIST(reply_to);
1198 ADDR_LIST(mail_followup_to);
1199 ADDR_LIST(x_original_to);
1200#undef ADDR_LIST
1201
1202 dot_type_string(fp, "date", env->date, false);
1203 dot_type_string(fp, "disp_subj", env->disp_subj, false);
1204 dot_type_string(fp, "followup_to", env->followup_to, false);
1205 dot_type_string(fp, "list_post", env->list_post, false);
1206 dot_type_string(fp, "list_subscribe", env->list_subscribe, false);
1207 dot_type_string(fp, "list_unsubscribe", env->list_unsubscribe, false);
1208 dot_type_string(fp, "message_id", env->message_id, false);
1209 dot_type_string(fp, "newsgroups", env->newsgroups, false);
1210 dot_type_string(fp, "organization", env->organization, false);
1211 dot_type_string(fp, "real_subj", env->real_subj, false);
1212 dot_type_string(fp, "spam", buf_string(&env->spam), false);
1213 dot_type_string(fp, "subject", env->subject, false);
1214 dot_type_string(fp, "supersedes", env->supersedes, false);
1215 dot_type_string(fp, "xref", env->xref, false);
1216 dot_type_string(fp, "x_comment_to", env->x_comment_to, false);
1217 dot_type_string(fp, "x_label", env->x_label, false);
1218
1219 if (0)
1220 {
1221 dot_list_head(fp, "references", &env->references);
1222 dot_list_head(fp, "in_reply_to", &env->in_reply_to);
1223 dot_list_head(fp, "userhdrs", &env->userhdrs);
1224 }
1225
1226#ifdef USE_AUTOCRYPT
1227 dot_ptr(fp, "autocrypt", env->autocrypt, NULL);
1228 dot_ptr(fp, "autocrypt_gossip", env->autocrypt_gossip, NULL);
1229#endif
1230
1232
1233 buf_pool_release(&buf);
1234}
1235#endif
1236
1237void dot_email(FILE *fp, struct Email *e, struct ListHead *links)
1238{
1239 struct Buffer *buf = buf_pool_get();
1240 char arr[256];
1241
1242 dot_object_header(fp, e, "Email", "#ff80ff");
1243
1244 dot_type_string(fp, "path", e->path, true);
1245
1246#define ADD_BOOL(F) add_flag(buf, e->F, #F)
1247 ADD_BOOL(active);
1248 ADD_BOOL(attach_del);
1249 ADD_BOOL(attach_valid);
1250 ADD_BOOL(changed);
1251 ADD_BOOL(collapsed);
1252 ADD_BOOL(deleted);
1253 ADD_BOOL(display_subject);
1254 ADD_BOOL(expired);
1255 ADD_BOOL(flagged);
1256 ADD_BOOL(matched);
1257 ADD_BOOL(mime);
1258 ADD_BOOL(old);
1259 ADD_BOOL(purge);
1260 ADD_BOOL(quasi_deleted);
1261 ADD_BOOL(read);
1262 ADD_BOOL(recip_valid);
1263 ADD_BOOL(replied);
1264 ADD_BOOL(searched);
1265 ADD_BOOL(subject_changed);
1266 ADD_BOOL(superseded);
1267 ADD_BOOL(tagged);
1268 ADD_BOOL(threaded);
1269 ADD_BOOL(trash);
1270 ADD_BOOL(visible);
1271#undef ADD_BOOL
1272 dot_type_string(fp, "bools", buf_is_empty(buf) ? "[NONE]" : buf_string(buf), true);
1273
1274 buf_reset(buf);
1275#define ADD_BOOL(F) add_flag(buf, (e->security & F), #F)
1290#undef ADD_BOOL
1291 dot_type_string(fp, "security", buf_is_empty(buf) ? "[NONE]" : buf_string(buf), true);
1292
1293 dot_type_number(fp, "num_hidden", e->num_hidden);
1294 dot_type_number(fp, "offset", e->offset);
1295 dot_type_number(fp, "lines", e->lines);
1296 dot_type_number(fp, "index", e->index);
1297 dot_type_number(fp, "msgno", e->msgno);
1298 dot_type_number(fp, "vnum", e->vnum);
1299 dot_type_number(fp, "score", e->score);
1300 dot_type_number(fp, "attach_total", e->attach_total);
1301
1302 // struct MaildirEmailData *edata = maildir_edata_get(e);
1303 // if (edata)
1304 // dot_type_string(fp, "maildir_flags", edata->maildir_flags, false);
1305
1306 if (e->date_sent != 0)
1307 {
1308 char zone[32];
1309 dot_type_date(arr, sizeof(arr), e->date_sent);
1310 snprintf(zone, sizeof(zone), " (%c%02u%02u)", e->zoccident ? '-' : '+',
1311 e->zhours, e->zminutes);
1312 struct Buffer *date = buf_pool_get();
1313 buf_printf(date, "%s%s", arr, zone);
1314 dot_type_string(fp, "date_sent", buf_string(date), false);
1315 buf_pool_release(&date);
1316 }
1317
1318 if (e->received != 0)
1319 {
1320 dot_type_date(arr, sizeof(arr), e->received);
1321 dot_type_string(fp, "received", arr, false);
1322 }
1323
1325
1326 if (e->body)
1327 {
1328 dot_body(fp, e->body, links, true);
1329 dot_add_link(links, e, e->body, "Email->body", NULL, false, NULL);
1330 }
1331
1332#ifndef GV_HIDE_ENVELOPE
1333 if (e->env)
1334 {
1335 dot_envelope(fp, e->env, links);
1336 dot_add_link(links, e, e->env, "Email->env", NULL, false, NULL);
1337
1338 buf_reset(buf);
1339 buf_addstr(buf, "{ rank=same ");
1340
1341 dot_ptr_name(arr, sizeof(arr), e);
1342 buf_add_printf(buf, "%s ", arr);
1343
1344 dot_ptr_name(arr, sizeof(arr), e->env);
1345 buf_add_printf(buf, "%s ", arr);
1346
1347 buf_addstr(buf, "}");
1348
1349 mutt_list_insert_tail(links, buf_strdup(buf));
1350 }
1351#endif
1352
1353 // struct TagList tags;
1354
1355 buf_pool_release(&buf);
1356}
1357
1359{
1360 char name[256] = { 0 };
1361 struct ListHead links = STAILQ_HEAD_INITIALIZER(links);
1362
1363 time_t now = time(NULL);
1364 mutt_date_localtime_format(name, sizeof(name), "%T-email.gv", now);
1365
1366 umask(022);
1367 FILE *fp = fopen(name, "w");
1368 if (!fp)
1369 return;
1370
1371 dot_graph_header(fp);
1372
1373 dot_body(fp, b, &links, true);
1374
1375 dot_graph_footer(fp, &links);
1376 fclose(fp);
1377 mutt_list_free(&links);
1378}
1379
1380void dump_graphviz_email(struct Email *e, const char *title)
1381{
1382 char name[256] = { 0 };
1383 struct ListHead links = STAILQ_HEAD_INITIALIZER(links);
1384
1385 if (!title)
1386 title = "email";
1387
1388 char format[64];
1389 snprintf(format, sizeof(format), "%%T-%s.gv", title);
1390
1391 time_t now = time(NULL);
1392 mutt_date_localtime_format(name, sizeof(name), format, now);
1393
1394 umask(022);
1395 FILE *fp = fopen(name, "w");
1396 if (!fp)
1397 return;
1398
1399 dot_graph_header(fp);
1400
1401 dot_email(fp, e, &links);
1402
1403 dot_graph_footer(fp, &links);
1404 fclose(fp);
1405 mutt_list_free(&links);
1406}
1407
1408void dot_attach_ptr2(FILE *fp, struct AttachPtr *aptr, struct ListHead *links)
1409{
1410 if (!aptr)
1411 return;
1412
1413 dot_object_header(fp, aptr, "AttachPtr", "#3bcbc4");
1414
1415 dot_ptr(fp, "body", aptr->body, "#2020ff");
1416 dot_type_file(fp, "fp", aptr->fp);
1417
1418 dot_type_string(fp, "parent_type", name_content_type(aptr->parent_type), false);
1419 dot_type_number(fp, "level", aptr->level);
1420 dot_type_number(fp, "num", aptr->num);
1421 dot_type_bool(fp, "unowned", aptr->unowned);
1422 dot_type_bool(fp, "collapsed", aptr->collapsed);
1423 dot_type_bool(fp, "decrypted", aptr->decrypted);
1424
1425 // dot_type_string(fp, "tree", aptr->tree, false);
1426
1428}
1429
1430void dot_array_actx_idx(FILE *fp, struct AttachPtr **idx, short idxlen,
1431 short idxmax, struct ListHead *links)
1432{
1433 dot_object_header(fp, idx, "AttachCtx-&gt;idx", "#9347de");
1434
1435 dot_type_number(fp, "idxlen", idxlen);
1436 dot_type_number(fp, "idxmax", idxmax);
1437
1438 char arr[32];
1439 for (size_t i = 0; i < idxmax; i++)
1440 {
1441 snprintf(arr, sizeof(arr), "idx[%zu]", i);
1442 dot_ptr(fp, arr, idx[i], "#3bcbc4");
1443 }
1444
1446
1447 for (size_t i = 0; i < idxlen; i++)
1448 {
1449 dot_attach_ptr2(fp, idx[i], links);
1450 dot_add_link(links, idx, idx[i], "AttachCtx-&gt;idx", NULL, false, NULL);
1451 }
1452}
1453
1454void dot_array_actx_v2r(FILE *fp, short *v2r, short vcount, struct ListHead *links)
1455{
1456 dot_object_header(fp, v2r, "AttachCtx-&gt;v2r", "#9347de");
1457
1458 dot_type_number(fp, "vcount", vcount);
1459
1460 char arr[32];
1461 for (size_t i = 0; i < vcount; i++)
1462 {
1463 snprintf(arr, sizeof(arr), "v2r[%zu]", i);
1464 dot_type_number(fp, arr, v2r[i]);
1465 }
1466
1468}
1469
1470void dot_array_actx_fp_idx(FILE *fp, FILE **fp_idx, short fp_len, short fp_max,
1471 struct ListHead *links)
1472{
1473 dot_object_header(fp, fp_idx, "AttachCtx-&gt;fp_idx", "#f86e28");
1474
1475 dot_type_number(fp, "fp_len", fp_len);
1476 dot_type_number(fp, "fp_max", fp_max);
1477
1478 char arr[32];
1479 for (size_t i = 0; i < fp_max; i++)
1480 {
1481 snprintf(arr, sizeof(arr), "fp_idx[%zu]", i);
1482 dot_type_file(fp, arr, fp_idx[i]);
1483 }
1484
1486}
1487
1488void dot_array_actx_body_idx(FILE *fp, struct Body **body_idx, short body_len,
1489 short body_max, struct ListHead *links)
1490{
1491 dot_object_header(fp, body_idx, "AttachCtx-&gt;body_idx", "#4ff270");
1492
1493 dot_type_number(fp, "body_len", body_len);
1494 dot_type_number(fp, "body_max", body_max);
1495
1496 char arr[32];
1497 for (size_t i = 0; i < body_max; i++)
1498 {
1499 snprintf(arr, sizeof(arr), "body_idx[%zu]", i);
1500 dot_ptr(fp, arr, body_idx[i], "#2020ff");
1501 }
1502
1504
1505 for (size_t i = 0; i < body_max; i++)
1506 {
1507 if (!body_idx[i])
1508 continue;
1509 dot_body(fp, body_idx[i], links, true);
1510 dot_add_link(links, body_idx, body_idx[i], "AttachCtx->Body", NULL, false, "#008000");
1511 }
1512}
1513
1514void dot_attach_ctx(FILE *fp, struct AttachCtx *actx, struct ListHead *links)
1515{
1516 dot_object_header(fp, actx, "AttachCtx", "#9347de");
1517
1518 dot_ptr(fp, "email", actx->email, "#ff80ff");
1519 dot_type_file(fp, "fp_root", actx->fp_root);
1520
1522
1523 if (actx->idx)
1524 {
1525 dot_array_actx_idx(fp, actx->idx, actx->idxlen, actx->idxmax, links);
1526 dot_add_link(links, actx, actx->idx, "AttachCtx-&gt;idx", NULL, false, NULL);
1527 }
1528
1529 if (actx->v2r)
1530 {
1531 dot_array_actx_v2r(fp, actx->v2r, actx->vcount, links);
1532 dot_add_link(links, actx, actx->v2r, "AttachCtx-&gt;v2r", NULL, false, NULL);
1533 }
1534
1535 if (actx->fp_idx)
1536 {
1537 dot_array_actx_fp_idx(fp, actx->fp_idx, actx->fp_len, actx->fp_max, links);
1538 dot_add_link(links, actx, actx->fp_idx, "AttachCtx-&gt;fp_idx", NULL, false, NULL);
1539 }
1540
1541 if (actx->body_idx)
1542 {
1543 dot_array_actx_body_idx(fp, actx->body_idx, actx->body_len, actx->body_max, links);
1544 dot_add_link(links, actx, actx->body_idx, "AttachCtx-&gt;body_idx", NULL, false, NULL);
1545 }
1546}
1547
1549{
1550 char name[256] = { 0 };
1551 struct ListHead links = STAILQ_HEAD_INITIALIZER(links);
1552
1553 time_t now = time(NULL);
1554 mutt_date_localtime_format(name, sizeof(name), "%T-actx.gv", now);
1555
1556 umask(022);
1557 FILE *fp = fopen(name, "w");
1558 if (!fp)
1559 return;
1560
1561 dot_graph_header(fp);
1562
1563 dot_attach_ctx(fp, actx, &links);
1564
1565 dot_graph_footer(fp, &links);
1566 fclose(fp);
1567 mutt_list_free(&links);
1568}
1569
1570const char *pattern_type_name(int type)
1571{
1572 static struct Mapping PatternNames[] = {
1573 // clang-format off
1574 { "address", MUTT_PAT_ADDRESS },
1575 { "AND", MUTT_PAT_AND },
1576 { "bcc", MUTT_PAT_BCC },
1577 { "body", MUTT_PAT_BODY },
1578 { "broken", MUTT_PAT_BROKEN },
1579 { "cc", MUTT_PAT_CC },
1580 { "children", MUTT_PAT_CHILDREN },
1581 { "collapsed", MUTT_PAT_COLLAPSED },
1582 { "crypt_encrypt", MUTT_PAT_CRYPT_ENCRYPT },
1583 { "crypt_sign", MUTT_PAT_CRYPT_SIGN },
1584 { "crypt_verified", MUTT_PAT_CRYPT_VERIFIED },
1585 { "date", MUTT_PAT_DATE },
1586 { "date_received", MUTT_PAT_DATE_RECEIVED },
1587 { "driver_tags", MUTT_PAT_DRIVER_TAGS },
1588 { "duplicated", MUTT_PAT_DUPLICATED },
1589 { "from", MUTT_PAT_FROM },
1590 { "header", MUTT_PAT_HEADER },
1591 { "hormel", MUTT_PAT_HORMEL },
1592 { "id", MUTT_PAT_ID },
1593 { "id_external", MUTT_PAT_ID_EXTERNAL },
1594 { "list", MUTT_PAT_LIST },
1595 { "message", MUTT_PAT_MESSAGE },
1596 { "mimeattach", MUTT_PAT_MIMEATTACH },
1597 { "mimetype", MUTT_PAT_MIMETYPE },
1598 { "newsgroups", MUTT_PAT_NEWSGROUPS },
1599 { "OR", MUTT_PAT_OR },
1600 { "parent", MUTT_PAT_PARENT },
1601 { "personal_from", MUTT_PAT_PERSONAL_FROM },
1602 { "personal_recip", MUTT_PAT_PERSONAL_RECIP },
1603 { "pgp_key", MUTT_PAT_PGP_KEY },
1604 { "recipient", MUTT_PAT_RECIPIENT },
1605 { "reference", MUTT_PAT_REFERENCE },
1606 { "score", MUTT_PAT_SCORE },
1607 { "sender", MUTT_PAT_SENDER },
1608 { "serversearch", MUTT_PAT_SERVERSEARCH },
1609 { "size", MUTT_PAT_SIZE },
1610 { "subject", MUTT_PAT_SUBJECT },
1611 { "subscribed_list", MUTT_PAT_SUBSCRIBED_LIST },
1612 { "thread", MUTT_PAT_THREAD },
1613 { "to", MUTT_PAT_TO },
1614 { "unreferenced", MUTT_PAT_UNREFERENCED },
1615 { "whole_msg", MUTT_PAT_WHOLE_MSG },
1616 { "xlabel", MUTT_PAT_XLABEL },
1617 { NULL, 0 },
1618 // clang-format on
1619 };
1620
1621 return mutt_map_get_name(type, PatternNames);
1622}
1623
1624void dot_pattern(FILE *fp, struct Pattern *pat, struct ListHead *links)
1625{
1626 struct Buffer *buf = buf_pool_get();
1627 dot_object_header(fp, pat, "Pattern", "#c040c0");
1628
1629 dot_type_string(fp, "op", pattern_type_name(pat->op), true);
1630 if ((pat->min != 0) || (pat->max != 0))
1631 {
1632 dot_type_number(fp, "min", pat->min);
1633 dot_type_number(fp, "max", pat->max);
1634 }
1635
1636#define ADD_BOOL(F) add_flag(buf, pat->F, #F)
1637 ADD_BOOL(pat_not);
1638 ADD_BOOL(all_addr);
1639 ADD_BOOL(string_match);
1641 ADD_BOOL(ign_case);
1642 ADD_BOOL(is_alias);
1643 ADD_BOOL(dynamic);
1644 ADD_BOOL(sendmode);
1645 ADD_BOOL(is_multi);
1646#undef ADD_BOOL
1647 dot_type_string(fp, "flags", buf_is_empty(buf) ? "[NONE]" : buf_string(buf), true);
1648
1649 if (pat->group_match)
1650 {
1651 // struct Group *group; ///< Address group if group_match is set
1652 }
1653 else if (pat->string_match)
1654 {
1655 dot_type_string(fp, "str", pat->p.str, true);
1656 }
1657 else if (pat->is_multi)
1658 {
1659 // struct ListHead multi_cases; ///< Multiple strings for ~I pattern
1660 }
1661 else
1662 {
1663 if (pat->p.regex)
1664 {
1665 dot_ptr(fp, "regex", pat->p.regex, NULL);
1666 dot_type_string(fp, "pattern", pat->raw_pattern, true);
1667 }
1668 }
1669
1671
1672 if (pat->child)
1673 {
1674 dot_patternlist(fp, pat->child, links);
1675 struct Pattern *first = SLIST_FIRST(pat->child);
1676 dot_add_link(links, pat, first, "Pattern->child", NULL, false, "#00ff00");
1677 }
1678 buf_pool_release(&buf);
1679}
1680
1681void dot_patternlist(FILE *fp, struct PatternList *pl, struct ListHead *links)
1682{
1683 struct Buffer *buf = buf_pool_get();
1684
1685 char name[256] = { 0 };
1686 buf_addstr(buf, "{ rank=same ");
1687
1688 struct Pattern *prev = NULL;
1689 struct Pattern *np = NULL;
1690 SLIST_FOREACH(np, pl, entries)
1691 {
1692 dot_pattern(fp, np, links);
1693 if (prev)
1694 dot_add_link(links, prev, np, "PatternList->next", NULL, false, "#ff0000");
1695 prev = np;
1696
1697 dot_ptr_name(name, sizeof(name), np);
1698 buf_add_printf(buf, "%s ", name);
1699 }
1700
1701 buf_addstr(buf, "}");
1702
1703 mutt_list_insert_tail(links, buf_strdup(buf));
1704 buf_pool_release(&buf);
1705}
1706
1707void dump_graphviz_patternlist(struct PatternList *pl)
1708{
1709 char name[256] = { 0 };
1710 struct ListHead links = STAILQ_HEAD_INITIALIZER(links);
1711
1712 time_t now = time(NULL);
1713 mutt_date_localtime_format(name, sizeof(name), "%T-pattern.gv", now);
1714
1715 umask(022);
1716 FILE *fp = fopen(name, "w");
1717 if (!fp)
1718 return;
1719
1720 dot_graph_header(fp);
1721
1722 dot_patternlist(fp, pl, &links);
1723
1724 dot_graph_footer(fp, &links);
1725 fclose(fp);
1726 mutt_list_free(&links);
1727}
1728
1729void dot_format(FILE *fp, struct ExpandoFormat *fmt)
1730{
1731 if (!fmt)
1732 return;
1733
1734 dot_type_number(fp, "min_cols", fmt->min_cols);
1735 dot_type_number(fp, "max_cols", fmt->max_cols);
1736
1737 char *just = "UNKNOWN";
1738 switch (fmt->justification)
1739 {
1740 case JUSTIFY_LEFT:
1741 just = "JUSTIFY_LEFT";
1742 break;
1743 case JUSTIFY_CENTER:
1744 just = "JUSTIFY_CENTER";
1745 break;
1746 case JUSTIFY_RIGHT:
1747 just = "JUSTIFY_RIGHT";
1748 break;
1749 }
1750 dot_type_string(fp, "justification", just, true);
1751 dot_type_char(fp, "leader", fmt->leader);
1752}
1753
1754void dot_expando_node_empty(FILE *fp, struct ExpandoNode *node, struct ListHead *links)
1755{
1756 dot_object_header(fp, node, "Empty", "#ffffff");
1757 // dot_type_string(fp, "type", "ENT_EMPTY", true);
1759}
1760
1761void dot_expando_node_text(FILE *fp, struct ExpandoNode *node, struct ListHead *links)
1762{
1763 struct Buffer *buf = buf_pool_get();
1764 dot_object_header(fp, node, "Text", "#ffff80");
1765 // dot_type_string(fp, "type", "ENT_TEXT", true);
1766 dot_type_string(fp, "text", node->text, false);
1767
1769
1770 buf_pool_release(&buf);
1771}
1772
1773void dot_expando_node_pad(FILE *fp, struct ExpandoNode *node, struct ListHead *links)
1774{
1775 struct Buffer *buf = buf_pool_get();
1776 dot_object_header(fp, node, "Pad", "#80ffff");
1777 // dot_type_string(fp, "type", "ENT_PADDING", true);
1778
1779 struct NodePaddingPrivate *priv = node->ndata;
1780 char *pad = "UNKNOWN";
1781 switch (priv->pad_type)
1782 {
1783 case EPT_FILL_EOL:
1784 pad = "EPT_FILL_EOL";
1785 break;
1786 case EPT_HARD_FILL:
1787 pad = "EPT_HARD_FILL";
1788 break;
1789 case EPT_SOFT_FILL:
1790 pad = "EPT_SOFT_FILL";
1791 break;
1792 }
1793 dot_type_string(fp, "type", pad, true);
1794 dot_type_string(fp, "char", node->text, false);
1795
1797
1798 struct ExpandoNode *left = node_get_child(node, ENP_LEFT);
1799 if (left)
1800 {
1801 dot_expando_node(fp, left, links);
1802 dot_add_link(links, node, left, "Pad->left", "left", false, "#80ff80");
1803 }
1804
1805 struct ExpandoNode *right = node_get_child(node, ENP_RIGHT);
1806 if (right)
1807 {
1808 dot_expando_node(fp, right, links);
1809 dot_add_link(links, node, right, "Pad->right", "right", false, "#ff8080");
1810 }
1811
1812 buf_pool_release(&buf);
1813}
1814
1815void dot_expando_node_condition(FILE *fp, struct ExpandoNode *node, struct ListHead *links)
1816{
1817 struct Buffer *buf = buf_pool_get();
1818 dot_object_header(fp, node, "Condition", "#ff8080");
1819 // dot_type_string(fp, "type", "ENT_CONDITION", true);
1820 dot_type_string(fp, "text", node->text, false);
1821 dot_format(fp, node->format);
1822
1824
1825 struct ExpandoNode *node_cond = node_get_child(node, ENC_CONDITION);
1826 struct ExpandoNode *node_true = node_get_child(node, ENC_TRUE);
1827 struct ExpandoNode *node_false = node_get_child(node, ENC_FALSE);
1828
1829 dot_expando_node(fp, node_cond, links);
1830 dot_add_link(links, node, node_cond, "Condition->condition", "condition", false, "#ff80ff");
1831 if (node_true)
1832 {
1833 dot_expando_node(fp, node_true, links);
1834 dot_add_link(links, node, node_true, "Condition->true", "true", false, "#80ff80");
1835 }
1836 if (node_false)
1837 {
1838 dot_expando_node(fp, node_false, links);
1839 dot_add_link(links, node, node_false, "Condition->false", "false", false, "#ff8080");
1840 }
1841
1842 buf_pool_release(&buf);
1843}
1844
1846 struct ListHead *links)
1847{
1848 struct Buffer *buf = buf_pool_get();
1849 dot_object_header(fp, node, "CondBool", "#c0c0ff");
1850 // dot_type_string(fp, "type", "ENT_CONDBOOL", true);
1851 dot_type_string(fp, "did", name_expando_domain(node->did), true);
1852 dot_type_string(fp, "uid", name_expando_uid(node->did, node->uid), true);
1853 dot_type_string(fp, "text", node->text, false);
1854
1856
1857 buf_pool_release(&buf);
1858}
1859
1861 struct ListHead *links)
1862{
1863 struct Buffer *buf = buf_pool_get();
1864 dot_object_header(fp, node, "CondDate", "#c0c0ff");
1865 // dot_type_string(fp, "type", "ENT_CONDDATE", true);
1866 dot_type_string(fp, "did", name_expando_domain(node->did), true);
1867 dot_type_string(fp, "uid", name_expando_uid(node->did, node->uid), true);
1868 dot_type_string(fp, "text", node->text, false);
1869
1870 struct NodeCondDatePrivate *priv = node->ndata;
1871 if (priv)
1872 {
1873 dot_type_number(fp, "count", priv->count);
1874 dot_type_char(fp, "period", priv->period);
1875 }
1876
1878
1879 buf_pool_release(&buf);
1880}
1881
1882void dot_expando_node_container(FILE *fp, struct ExpandoNode *node, struct ListHead *links)
1883{
1884 dot_object_header(fp, node, "Container", "#80ffff");
1885 // dot_type_string(fp, "type", "ENT_CONTAINER", true);
1886 dot_type_number(fp, "children", ARRAY_SIZE(&node->children));
1887 dot_format(fp, node->format);
1889
1890 struct ExpandoNode **enp = NULL;
1891 enp = ARRAY_FIRST(&node->children);
1892 if (!enp)
1893 return;
1894
1895 struct ExpandoNode *child = *enp;
1896 dot_add_link(links, node, child, "Node->children", "children", false, "#80ff80");
1897
1898 char name[256] = { 0 };
1899 struct Buffer *rank = buf_pool_get();
1900 buf_addstr(rank, "{ rank=same ");
1901
1902 struct ExpandoNode *prev = NULL;
1903 ARRAY_FOREACH(enp, &node->children)
1904 {
1905 child = *enp;
1906
1907 dot_expando_node(fp, child, links);
1908 if (prev)
1909 {
1910 dot_add_link(links, prev, child, "Node->next", "next", false, "#80ff80");
1911 }
1912 prev = child;
1913
1914 dot_ptr_name(name, sizeof(name), child);
1915 buf_add_printf(rank, "%s ", name);
1916 }
1917
1918 buf_addstr(rank, "}");
1919 mutt_list_insert_tail(links, buf_strdup(rank));
1920 buf_pool_release(&rank);
1921}
1922
1923void dot_expando_node_expando(FILE *fp, struct ExpandoNode *node, struct ListHead *links)
1924{
1925 struct Buffer *buf = buf_pool_get();
1926 dot_object_header(fp, node, "Expando", "#80ff80");
1927
1928 // dot_type_number(fp, "type", node->type);
1929 dot_type_string(fp, "did", name_expando_domain(node->did), true);
1930 dot_type_string(fp, "uid", name_expando_uid(node->did, node->uid), true);
1931 dot_type_string(fp, "text", node->text, false);
1932
1933 dot_format(fp, node->format);
1934
1936
1937 buf_pool_release(&buf);
1938}
1939
1940void dot_expando_node_unknown(FILE *fp, struct ExpandoNode *node, struct ListHead *links)
1941{
1942 struct Buffer *buf = buf_pool_get();
1943 dot_object_header(fp, node, "UNKNOWN", "#ff0000");
1944
1945 dot_type_number(fp, "type", node->type);
1946 dot_type_number(fp, "did", node->did);
1947 dot_type_number(fp, "uid", node->uid);
1948 dot_type_string(fp, "text", node->text, false);
1949
1951
1952 buf_pool_release(&buf);
1953}
1954
1955void dot_expando_node(FILE *fp, struct ExpandoNode *node, struct ListHead *links)
1956{
1957 switch (node->type)
1958 {
1959 case ENT_CONDITION:
1960 dot_expando_node_condition(fp, node, links);
1961 break;
1962 case ENT_CONDBOOL:
1963 dot_expando_node_conditional_bool(fp, node, links);
1964 break;
1965 case ENT_CONDDATE:
1966 dot_expando_node_conditional_date(fp, node, links);
1967 break;
1968 case ENT_CONTAINER:
1969 dot_expando_node_container(fp, node, links);
1970 break;
1971 case ENT_EMPTY:
1972 dot_expando_node_empty(fp, node, links);
1973 break;
1974 case ENT_EXPANDO:
1975 dot_expando_node_expando(fp, node, links);
1976 break;
1977 case ENT_PADDING:
1978 dot_expando_node_pad(fp, node, links);
1979 break;
1980 case ENT_TEXT:
1981 dot_expando_node_text(fp, node, links);
1982 break;
1983 default:
1984 dot_expando_node_unknown(fp, node, links);
1985 break;
1986 }
1987}
1988
1990{
1991 char name[256] = { 0 };
1992 struct ListHead links = STAILQ_HEAD_INITIALIZER(links);
1993
1994 time_t now = time(NULL);
1995 mutt_date_localtime_format(name, sizeof(name), "%T-expando.gv", now);
1996
1997 umask(022);
1998 FILE *fp = fopen(name, "w");
1999 if (!fp)
2000 return;
2001
2002 dot_graph_header(fp);
2003
2004 dot_expando_node(fp, node, &links);
2005
2006 dot_graph_footer(fp, &links);
2007 fclose(fp);
2008 mutt_list_free(&links);
2009}
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition address.c:1206
Email Address Handling.
#define ARRAY_FIRST(head)
Convenience method to get the first element.
Definition array.h:135
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:214
#define ARRAY_SIZE(head)
The number of elements stored.
Definition array.h:87
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:204
GUI display the mailboxes in a side panel.
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition buffer.c:204
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition buffer.c:491
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:291
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
Definition buffer.c:668
void buf_free(struct Buffer **ptr)
Deallocates a buffer.
Definition buffer.c:319
void buf_inline_replace(struct Buffer *buf, size_t pos, size_t len, const char *str)
Definition buffer.c:768
struct Buffer * buf_new(const char *str)
Allocate a new Buffer.
Definition buffer.c:304
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition buffer.c:241
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:226
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:571
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
Compressed mbox local mailbox type.
Convenience wrapper for the config headers.
Connection Library.
Convenience wrapper for the core headers.
MailboxType
Supported mailbox formats.
Definition mailbox.h:41
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition mailbox.h:51
@ MUTT_MMDF
'mmdf' Mailbox type
Definition mailbox.h:46
@ MUTT_POP
'POP3' Mailbox type
Definition mailbox.h:52
@ MUTT_MH
'MH' Mailbox type
Definition mailbox.h:47
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
Definition mailbox.h:49
@ MUTT_IMAP
'IMAP' Mailbox type
Definition mailbox.h:50
@ MUTT_MBOX
'mbox' Mailbox type
Definition mailbox.h:45
@ MUTT_COMPRESSED
Compressed file Mailbox type.
Definition mailbox.h:53
@ MUTT_MAILDIR
'Maildir' Mailbox type
Definition mailbox.h:48
Convenience wrapper for the debug headers.
const char * name_content_encoding(enum ContentEncoding enc)
Definition names.c:65
const char * name_content_type(enum ContentType type)
Definition names.c:47
const char * name_content_disposition(enum ContentDisposition disp)
Definition names.c:80
const char * name_expando_uid(enum ExpandoDomain did, int uid)
const char * name_expando_domain(enum ExpandoDomain did)
Structs that make up an email.
#define MUTT_ENV_CHANGED_SUBJECT
Protected header update.
Definition envelope.h:37
#define MUTT_ENV_CHANGED_XLABEL
X-Label edited.
Definition envelope.h:36
#define MUTT_ENV_CHANGED_IRT
In-Reply-To changed to link/break threads.
Definition envelope.h:34
#define MUTT_ENV_CHANGED_REFS
References changed to break thread.
Definition envelope.h:35
Parse Expando string.
@ JUSTIFY_RIGHT
Right justify the text.
Definition format.h:36
@ JUSTIFY_LEFT
Left justify the text.
Definition format.h:34
@ JUSTIFY_CENTER
Centre the text.
Definition format.h:35
void dot_array_actx_idx(FILE *fp, struct AttachPtr **idx, short idxlen, short idxmax, struct ListHead *links)
Definition graphviz.c:1430
void dot_mailbox_pop(FILE *fp, struct PopAccountData *adata, struct ListHead *links)
Definition graphviz.c:513
void dot_ptr_name(char *buf, size_t buflen, const void *ptr)
Definition graphviz.c:183
void dot_parameter_list(FILE *fp, const char *name, const struct ParameterList *pl)
Definition graphviz.c:935
void dot_expando_node_unknown(FILE *fp, struct ExpandoNode *node, struct ListHead *links)
Definition graphviz.c:1940
void dot_graph_header(FILE *fp)
Definition graphviz.c:233
void dot_account_pop(FILE *fp, struct PopAccountData *adata, struct ListHead *links)
Definition graphviz.c:736
void dot_object_footer(FILE *fp)
Definition graphviz.c:284
void dot_path_fs(char *buf, size_t buflen, const char *path)
Definition graphviz.c:306
void dump_graphviz_body(struct Body *b)
Definition graphviz.c:1358
void dot_addr_list(FILE *fp, const char *name, const struct AddressList *al, struct ListHead *links)
Definition graphviz.c:1162
void dot_mailbox_imap(FILE *fp, struct ImapMboxData *mdata, struct ListHead *links)
Definition graphviz.c:448
void dot_comp(FILE *fp, struct CompressInfo *ci, struct ListHead *links)
Definition graphviz.c:394
void dot_expando_node_empty(FILE *fp, struct ExpandoNode *node, struct ListHead *links)
Definition graphviz.c:1754
void dot_mailbox_type(FILE *fp, const char *name, enum MailboxType type)
Definition graphviz.c:403
void dot_attach_ptr2(FILE *fp, struct AttachPtr *aptr, struct ListHead *links)
Definition graphviz.c:1408
void dot_type_date(char *buf, size_t buflen, time_t timestamp)
Definition graphviz.c:108
void dot_array_actx_v2r(FILE *fp, short *v2r, short vcount, struct ListHead *links)
Definition graphviz.c:1454
void dot_type_number(FILE *fp, const char *name, int num)
Definition graphviz.c:130
void dot_expando_node_pad(FILE *fp, struct ExpandoNode *node, struct ListHead *links)
Definition graphviz.c:1773
#define ADDR_LIST(AL)
void dot_email(FILE *fp, struct Email *e, struct ListHead *links)
Definition graphviz.c:1237
void dot_type_char(FILE *fp, const char *name, char ch)
Definition graphviz.c:95
void dot_account_mbox(FILE *fp, struct MboxAccountData *adata, struct ListHead *links)
Definition graphviz.c:670
void dot_type_file(FILE *fp, const char *name, FILE *struct_fp)
Definition graphviz.c:113
void dump_graphviz(const char *title, struct MailboxView *mv)
Definition graphviz.c:850
void dot_format(FILE *fp, struct ExpandoFormat *fmt)
Definition graphviz.c:1729
void dot_type_bool(FILE *fp, const char *name, bool val)
Definition graphviz.c:84
void dot_account_array(FILE *fp, struct AccountArray *aa, struct ListHead *links)
Definition graphviz.c:816
void dot_list_head(FILE *fp, const char *name, const struct ListHead *list)
Definition graphviz.c:1141
void dot_config(FILE *fp, const char *name, int type, struct ConfigSubset *sub, struct ListHead *links)
Definition graphviz.c:339
void dot_array_actx_body_idx(FILE *fp, struct Body **body_idx, short body_len, short body_max, struct ListHead *links)
Definition graphviz.c:1488
void dot_account_imap(FILE *fp, struct ImapAccountData *adata, struct ListHead *links)
Definition graphviz.c:648
void dot_patternlist(FILE *fp, struct PatternList *pl, struct ListHead *links)
Definition graphviz.c:1681
void dot_type_umask(char *buf, size_t buflen, int umask)
Definition graphviz.c:177
void dot_graph_footer(FILE *fp, struct ListHead *links)
Definition graphviz.c:256
void dot_mview(FILE *fp, struct MailboxView *mv, struct ListHead *links)
Definition graphviz.c:837
void dot_account(FILE *fp, struct Account *a, struct ListHead *links)
Definition graphviz.c:757
void dot_connection(FILE *fp, struct Connection *c, struct ListHead *links)
Definition graphviz.c:632
void dot_mailbox_mbox(FILE *fp, struct MboxAccountData *mdata, struct ListHead *links)
Definition graphviz.c:471
void dot_type_string(FILE *fp, const char *name, const char *str, bool force)
Definition graphviz.c:152
void dot_expando_node(FILE *fp, struct ExpandoNode *node, struct ListHead *links)
Definition graphviz.c:1955
void dot_account_notmuch(FILE *fp, struct NmAccountData *adata, struct ListHead *links)
Definition graphviz.c:728
void dump_graphviz_expando_node(struct ExpandoNode *node)
Definition graphviz.c:1989
void dot_array_actx_fp_idx(FILE *fp, FILE **fp_idx, short fp_len, short fp_max, struct ListHead *links)
Definition graphviz.c:1470
void dot_attach_ctx(FILE *fp, struct AttachCtx *actx, struct ListHead *links)
Definition graphviz.c:1514
void dot_path_imap(char *buf, size_t buflen, const char *path)
Definition graphviz.c:323
void dot_node(FILE *fp, void *ptr, const char *name, const char *colour)
Definition graphviz.c:291
void dot_expando_node_container(FILE *fp, struct ExpandoNode *node, struct ListHead *links)
Definition graphviz.c:1882
void dot_mailbox_notmuch(FILE *fp, struct NmMboxData *mdata, struct ListHead *links)
Definition graphviz.c:505
void dot_pattern(FILE *fp, struct Pattern *pat, struct ListHead *links)
Definition graphviz.c:1624
void dot_content(FILE *fp, struct Content *cont, struct ListHead *links)
Definition graphviz.c:953
#define ADD_FLAG(F)
void dot_account_nntp(FILE *fp, struct NntpAccountData *adata, struct ListHead *links)
Definition graphviz.c:685
void dot_attach_ptr(FILE *fp, struct AttachPtr *aptr, struct ListHead *links)
Definition graphviz.c:980
void dot_ptr(FILE *fp, const char *name, void *ptr, const char *colour)
Definition graphviz.c:188
#define ADD_BOOL(F)
void dot_add_link(struct ListHead *links, void *src, void *dst, const char *label, const char *short_label, bool back, const char *colour)
Definition graphviz.c:205
const char * pattern_type_name(int type)
Definition graphviz.c:1570
void dot_object_header(FILE *fp, const void *ptr, const char *name, const char *colour)
Definition graphviz.c:267
void dump_graphviz_patternlist(struct PatternList *pl)
Definition graphviz.c:1707
void dot_envelope(FILE *fp, struct Envelope *env, struct ListHead *links)
Definition graphviz.c:1176
void dot_mailbox_array(FILE *fp, struct MailboxArray *ma, struct ListHead *links)
Definition graphviz.c:603
void dot_expando_node_conditional_date(FILE *fp, struct ExpandoNode *node, struct ListHead *links)
Definition graphviz.c:1860
void dump_graphviz_attach_ctx(struct AttachCtx *actx)
Definition graphviz.c:1548
void dot_expando_node_conditional_bool(FILE *fp, struct ExpandoNode *node, struct ListHead *links)
Definition graphviz.c:1845
void dot_mailbox(FILE *fp, struct Mailbox *m, struct ListHead *links)
Definition graphviz.c:521
void dot_expando_node_text(FILE *fp, struct ExpandoNode *node, struct ListHead *links)
Definition graphviz.c:1761
void dot_type_string_escape(struct Buffer *buf)
Definition graphviz.c:139
void dot_expando_node_condition(FILE *fp, struct ExpandoNode *node, struct ListHead *links)
Definition graphviz.c:1815
void dot_expando_node_expando(FILE *fp, struct ExpandoNode *node, struct ListHead *links)
Definition graphviz.c:1923
void dot_mailbox_maildir(FILE *fp, struct MaildirMboxData *mdata, struct ListHead *links)
Definition graphviz.c:457
void dot_mailbox_nntp(FILE *fp, struct NntpMboxData *mdata, struct ListHead *links)
Definition graphviz.c:484
void dump_graphviz_email(struct Email *e, const char *title)
Definition graphviz.c:1380
void dot_body(FILE *fp, struct Body *b, struct ListHead *links, bool link_next)
Definition graphviz.c:1003
bool group_match(struct Group *g, const char *str)
Does a string match an entry in a Group?
Definition group.c:161
Imap-specific Account data.
IMAP network mailbox.
Imap-specific Mailbox data.
Shared constants/structs that are private to IMAP.
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition list.c:65
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition list.c:123
Maildir-specific Email data.
Maildir local mailbox type.
Maildir-specific Mailbox data.
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
Definition mapping.c:42
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition date.c:950
Convenience wrapper for the library headers.
static const char * timestamp(time_t stamp)
Create a YYYY-MM-DD HH:MM:SS timestamp.
Definition logging.c:78
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:255
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:660
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition string.c:232
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:581
View of a Mailbox.
API for encryption/signing of emails.
#define SEC_INLINE
Email has an inline signature.
Definition lib.h:91
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition lib.h:93
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition lib.h:92
#define PGP_TRADITIONAL_CHECKED
Email has a traditional (inline) signature.
Definition lib.h:98
#define SEC_GOODSIGN
Email has a valid signature.
Definition lib.h:86
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition lib.h:96
#define SEC_SIGNOPAQUE
Email has an opaque signature (encrypted)
Definition lib.h:89
#define SEC_BADSIGN
Email has a bad signature.
Definition lib.h:87
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition lib.h:97
#define SEC_PARTSIGN
Not all parts of the email is signed.
Definition lib.h:88
#define SEC_ENCRYPT
Email is encrypted.
Definition lib.h:84
#define SEC_AUTOCRYPT_OVERRIDE
(Autocrypt) Indicates manual set/unset of encryption
Definition lib.h:94
#define SEC_SIGN
Email is signed.
Definition lib.h:85
#define SEC_KEYBLOCK
Email has a key attached.
Definition lib.h:90
Nntp-specific Account data.
Usenet network mailbox type; talk to an NNTP server.
Nntp-specific Mailbox data.
struct ExpandoNode * node_get_child(const struct ExpandoNode *node, int index)
Get a child of an ExpandoNode.
Definition node.c:91
@ ENT_EXPANDO
Expando, e.g. 'n'.
Definition node.h:39
@ ENT_CONTAINER
Container for other nodes.
Definition node.h:44
@ ENT_CONDITION
True/False condition.
Definition node.h:41
@ ENT_TEXT
Plain text.
Definition node.h:38
@ ENT_CONDDATE
True/False date condition.
Definition node.h:43
@ ENT_EMPTY
Empty.
Definition node.h:37
@ ENT_CONDBOOL
True/False boolean condition.
Definition node.h:42
@ ENT_PADDING
Padding: soft, hard, EOL.
Definition node.h:40
@ ENC_CONDITION
Index of Condition Node.
@ ENC_FALSE
Index of False Node.
@ ENC_TRUE
Index of True Node.
@ ENP_LEFT
Index of Left-Hand Nodes.
@ ENP_RIGHT
Index of Right-Hand Nodes.
@ EPT_FILL_EOL
Fill to the end-of-line.
@ EPT_SOFT_FILL
Soft-fill: right-hand-side will be truncated.
@ EPT_HARD_FILL
Hard-fill: left-hand-side will be truncated.
Notmuch-specific Account data.
Notmuch virtual mailbox type.
Notmuch-specific Mailbox data.
Notmuch private types.
Match patterns to emails.
@ MUTT_PAT_HEADER
Pattern matches email's header.
Definition lib.h:156
@ MUTT_PAT_WHOLE_MSG
Pattern matches raw email text.
Definition lib.h:158
@ MUTT_PAT_BROKEN
Message is part of a broken thread.
Definition lib.h:152
@ MUTT_PAT_ID_EXTERNAL
Message-Id is among results from an external query.
Definition lib.h:154
@ MUTT_PAT_OR
Either pattern can match.
Definition lib.h:138
@ MUTT_PAT_CHILDREN
Pattern matches a child email.
Definition lib.h:141
@ MUTT_PAT_PARENT
Pattern matches parent.
Definition lib.h:140
@ MUTT_PAT_REFERENCE
Pattern matches 'References:' or 'In-Reply-To:' field.
Definition lib.h:163
@ MUTT_PAT_FROM
Pattern matches 'From:' field.
Definition lib.h:147
@ MUTT_PAT_DRIVER_TAGS
Pattern matches message tags.
Definition lib.h:176
@ MUTT_PAT_COLLAPSED
Thread is collapsed.
Definition lib.h:145
@ MUTT_PAT_CRYPT_VERIFIED
Message is crypographically verified.
Definition lib.h:171
@ MUTT_PAT_HORMEL
Pattern matches email's spam score.
Definition lib.h:157
@ MUTT_PAT_SUBJECT
Pattern matches 'Subject:' field.
Definition lib.h:146
@ MUTT_PAT_LIST
Email is on mailing list.
Definition lib.h:165
@ MUTT_PAT_NEWSGROUPS
Pattern matches newsgroup.
Definition lib.h:179
@ MUTT_PAT_PERSONAL_RECIP
Email is addressed to the user.
Definition lib.h:167
@ MUTT_PAT_CC
Pattern matches 'Cc:' field.
Definition lib.h:143
@ MUTT_PAT_SUBSCRIBED_LIST
Email is on subscribed mailing list.
Definition lib.h:166
@ MUTT_PAT_SERVERSEARCH
Server-side pattern matches.
Definition lib.h:175
@ MUTT_PAT_RECIPIENT
User is a recipient of the email.
Definition lib.h:164
@ MUTT_PAT_CRYPT_ENCRYPT
Message is encrypted.
Definition lib.h:172
@ MUTT_PAT_UNREFERENCED
Message is unreferenced in the thread.
Definition lib.h:151
@ MUTT_PAT_CRYPT_SIGN
Message is signed.
Definition lib.h:170
@ MUTT_PAT_MESSAGE
Pattern matches message number.
Definition lib.h:160
@ MUTT_PAT_AND
Both patterns must match.
Definition lib.h:137
@ MUTT_PAT_DATE
Pattern matches 'Date:' field.
Definition lib.h:148
@ MUTT_PAT_XLABEL
Pattern matches keyword/label.
Definition lib.h:174
@ MUTT_PAT_SCORE
Pattern matches email's score.
Definition lib.h:161
@ MUTT_PAT_MIMEATTACH
Pattern matches number of attachments.
Definition lib.h:177
@ MUTT_PAT_DUPLICATED
Duplicate message.
Definition lib.h:150
@ MUTT_PAT_PERSONAL_FROM
Email is from the user.
Definition lib.h:168
@ MUTT_PAT_TO
Pattern matches 'To:' field.
Definition lib.h:142
@ MUTT_PAT_BCC
Pattern matches 'Bcc:' field.
Definition lib.h:144
@ MUTT_PAT_SENDER
Pattern matches sender.
Definition lib.h:159
@ MUTT_PAT_DATE_RECEIVED
Pattern matches date received.
Definition lib.h:149
@ MUTT_PAT_ADDRESS
Pattern matches any address field.
Definition lib.h:169
@ MUTT_PAT_MIMETYPE
Pattern matches MIME type.
Definition lib.h:178
@ MUTT_PAT_PGP_KEY
Message has PGP key.
Definition lib.h:173
@ MUTT_PAT_ID
Pattern matches email's Message-Id.
Definition lib.h:153
@ MUTT_PAT_THREAD
Pattern matches email thread.
Definition lib.h:139
@ MUTT_PAT_SIZE
Pattern matches email's size.
Definition lib.h:162
@ MUTT_PAT_BODY
Pattern matches email's body.
Definition lib.h:155
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:96
Pop-specific Account data.
POP network mailbox.
POP network mailbox.
#define SLIST_FOREACH(var, head, field)
Definition queue.h:229
#define TAILQ_FOREACH(var, head, field)
Definition queue.h:782
#define STAILQ_HEAD_INITIALIZER(head)
Definition queue.h:324
#define STAILQ_FOREACH(var, head, field)
Definition queue.h:390
#define TAILQ_FIRST(head)
Definition queue.h:780
#define STAILQ_EMPTY(head)
Definition queue.h:382
#define SLIST_FIRST(head)
Definition queue.h:227
#define TAILQ_EMPTY(head)
Definition queue.h:778
A group of associated Mailboxes.
Definition account.h:36
enum MailboxType type
Type of Mailboxes this Account contains.
Definition account.h:37
char * name
Name of Account.
Definition account.h:38
struct MailboxArray mailboxes
All Mailboxes.
Definition account.h:40
struct ConfigSubset * sub
Inherited config items.
Definition account.h:39
void * adata
Private data (for Mailbox backends)
Definition account.h:42
A set of attachments.
Definition attach.h:63
short vcount
The number of virtual attachments.
Definition attach.h:72
short body_len
Number of Body parts.
Definition attach.h:79
FILE * fp_root
Used by recvattach for updating.
Definition attach.h:65
short fp_max
Size of FILE array.
Definition attach.h:76
struct Email * email
Used by recvattach for updating.
Definition attach.h:64
struct AttachPtr ** idx
Array of attachments.
Definition attach.h:67
struct Body ** body_idx
Extra struct Body* used for decryption.
Definition attach.h:78
short fp_len
Number of FILE handles.
Definition attach.h:75
short body_max
Size of Body array.
Definition attach.h:80
FILE ** fp_idx
Extra FILE* used for decryption.
Definition attach.h:74
short idxmax
Size of attachment array.
Definition attach.h:69
short idxlen
Number of attachmentes.
Definition attach.h:68
short * v2r
Mapping from virtual to real attachment.
Definition attach.h:71
An email to which things will be attached.
Definition attach.h:35
struct Body * body
Attachment.
Definition attach.h:36
bool collapsed
Group is collapsed.
Definition attach.h:44
int num
Attachment index number.
Definition attach.h:41
int level
Nesting depth of attachment.
Definition attach.h:40
FILE * fp
Used in the recvattach menu.
Definition attach.h:37
bool unowned
Don't unlink on detach.
Definition attach.h:42
bool decrypted
Not part of message as stored in the email->body.
Definition attach.h:43
int parent_type
Type of parent attachment, e.g. TYPE_MULTIPART.
Definition attach.h:38
The body of an email.
Definition body.h:36
char * language
content-language (RFC8255)
Definition body.h:78
char * d_filename
filename to be used for the content-disposition header If NULL, filename is used instead.
Definition body.h:56
struct Body * parts
parts of a multipart or message/rfc822
Definition body.h:73
LOFF_T offset
offset where the actual data begins
Definition body.h:52
signed short attach_count
Number of attachments.
Definition body.h:91
char * xtype
content-type if x-unknown
Definition body.h:62
time_t stamp
Time stamp of last encoding update.
Definition body.h:77
struct Envelope * mime_headers
Memory hole protected headers.
Definition body.h:76
LOFF_T length
length (in bytes) of attachment
Definition body.h:53
char * charset
Send mode: charset of attached file as stored on disk.
Definition body.h:79
struct ParameterList parameter
Parameters of the content-type.
Definition body.h:63
struct AttachPtr * aptr
Menu information, used in recvattach.c.
Definition body.h:75
struct Email * email
header information for message/rfc822
Definition body.h:74
char * description
content-description
Definition body.h:55
unsigned int disposition
content-disposition, ContentDisposition
Definition body.h:42
struct Content * content
Detailed info about the content of the attachment.
Definition body.h:70
struct Body * next
next attachment in the list
Definition body.h:72
char * subtype
content-type subtype
Definition body.h:61
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition body.h:41
long hdr_offset
Offset in stream where the headers begin.
Definition body.h:81
char * form_name
Content-Disposition form-data name param.
Definition body.h:60
unsigned int type
content-type primary type, ContentType
Definition body.h:40
char * filename
When sending a message, this is the file to which this structure refers.
Definition body.h:59
String manipulation buffer.
Definition buffer.h:36
Private data for compress.
Definition lib.h:60
struct Expando * cmd_open
open-hook command
Definition lib.h:63
struct Expando * cmd_append
append-hook command
Definition lib.h:61
struct Expando * cmd_close
close-hook command
Definition lib.h:62
A set of inherited config items.
Definition subset.h:46
const char * name
Scope name of Subset.
Definition subset.h:47
struct ConfigSet * cs
Parent ConfigSet.
Definition subset.h:50
char login[128]
Login name.
Definition connaccount.h:55
char user[128]
Username.
Definition connaccount.h:56
char pass[256]
Password.
Definition connaccount.h:57
char host[128]
Server to login to.
Definition connaccount.h:54
unsigned short port
Port to connect to.
Definition connaccount.h:58
char inbuf[1024]
Buffer for incoming traffic.
Definition connection.h:51
struct ConnAccount account
Account details: username, password, etc.
Definition connection.h:49
int fd
Socket file descriptor.
Definition connection.h:53
Info about an attachment.
Definition content.h:35
long crlf
\r and \n characters
Definition content.h:39
long hibin
8-bit characters
Definition content.h:36
long ascii
Number of ascii chars.
Definition content.h:40
long nulbin
Null characters (0x0)
Definition content.h:38
long linemax
Length of the longest line in the file.
Definition content.h:41
long lobin
Unprintable 7-bit chars (eg., control chars)
Definition content.h:37
The envelope/body of an email.
Definition email.h:39
unsigned int zminutes
Minutes away from UTC.
Definition email.h:57
struct Envelope * env
Envelope information.
Definition email.h:68
int lines
How many lines in the body of this message?
Definition email.h:62
struct Body * body
List of MIME parts.
Definition email.h:69
size_t num_hidden
Number of hidden messages in this view (only valid when collapsed is set)
Definition email.h:123
bool zoccident
True, if west of UTC, False if east.
Definition email.h:58
LOFF_T offset
Where in the stream does this message begin?
Definition email.h:71
short attach_total
Number of qualifying attachments in message, if attach_valid.
Definition email.h:115
unsigned int zhours
Hours away from UTC.
Definition email.h:56
time_t date_sent
Time when the message was sent (UTC)
Definition email.h:60
int vnum
Virtual message number.
Definition email.h:114
int score
Message score.
Definition email.h:113
int msgno
Number displayed to the user.
Definition email.h:111
char * path
Path of Email (for local Mailboxes)
Definition email.h:70
int index
The absolute (unsorted) message number.
Definition email.h:110
time_t received
Time when the message was placed in the mailbox.
Definition email.h:61
The header of an Email.
Definition envelope.h:57
struct ListHead userhdrs
user defined headers
Definition envelope.h:85
char * supersedes
Supersedes header.
Definition envelope.h:74
char * list_subscribe
This stores a mailto URL, or nothing.
Definition envelope.h:68
char *const subject
Email's subject.
Definition envelope.h:70
char * followup_to
List of 'followup-to' fields.
Definition envelope.h:80
char * message_id
Message ID.
Definition envelope.h:73
char * x_comment_to
List of 'X-comment-to' fields.
Definition envelope.h:81
struct AutocryptHeader * autocrypt_gossip
Autocrypt Gossip header.
Definition envelope.h:88
char * newsgroups
List of newsgroups.
Definition envelope.h:78
struct ListHead references
message references (in reverse order)
Definition envelope.h:83
struct AutocryptHeader * autocrypt
Autocrypt header.
Definition envelope.h:87
struct Buffer spam
Spam header.
Definition envelope.h:82
struct ListHead in_reply_to
in-reply-to header content
Definition envelope.h:84
char * xref
List of cross-references.
Definition envelope.h:79
char * organization
Organisation header.
Definition envelope.h:77
char * x_label
X-Label.
Definition envelope.h:76
char * list_post
This stores a mailto URL, or nothing.
Definition envelope.h:67
char *const real_subj
Offset of the real subject.
Definition envelope.h:71
char * date
Sent date.
Definition envelope.h:75
char * disp_subj
Display subject (modified copy of subject)
Definition envelope.h:72
char * list_unsubscribe
This stores a mailto URL, or nothing.
Definition envelope.h:69
Formatting information for an Expando.
Definition node.h:53
char leader
Leader character, 0 or space.
Definition node.h:57
enum FormatJustify justification
Justification: left, centre, right.
Definition node.h:56
int min_cols
Minimum number of screen columns.
Definition node.h:54
int max_cols
Maximum number of screen columns.
Definition node.h:55
Basic Expando Node.
Definition node.h:67
int uid
Unique ID, e.g. ED_EMA_SIZE.
Definition node.h:70
void * ndata
Private node data.
Definition node.h:77
struct ExpandoFormat * format
Formatting info.
Definition node.h:72
int did
Domain ID, e.g. ED_EMAIL.
Definition node.h:69
const char * text
Node-specific text.
Definition node.h:73
enum ExpandoNodeType type
Type of Node, e.g. ENT_EXPANDO.
Definition node.h:68
struct ExpandoNodeArray children
Children nodes.
Definition node.h:75
const char * string
Pointer to the parsed string.
Definition expando.h:42
The item stored in a Hash Table.
Definition hash.h:44
union HashKey key
Key representing the data.
Definition hash.h:46
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition hash.h:45
IMAP-specific Account data -.
Definition adata.h:40
bool qresync
true, if QRESYNC is successfully ENABLE'd
Definition adata.h:63
unsigned char seqid
tag sequence prefix
Definition adata.h:56
bool unicode
If true, we can send UTF-8, and the server will use UTF8 rather than mUTF7.
Definition adata.h:62
struct Mailbox * mailbox
Current selected mailbox.
Definition adata.h:76
struct Connection * conn
Connection to IMAP server.
Definition adata.h:41
IMAP-specific Mailbox data -.
Definition mdata.h:40
char * real_name
Original Mailbox name, e.g.: INBOX can be just \0.
Definition mdata.h:43
char * munge_name
Munged version of the mailbox name.
Definition mdata.h:42
char * name
Mailbox name.
Definition mdata.h:41
A List node for strings.
Definition list.h:37
char * data
String.
Definition list.h:38
View of a Mailbox.
Definition mview.h:40
bool collapsed
Are all threads collapsed?
Definition mview.h:49
off_t vsize
Size (in bytes) of the messages shown.
Definition mview.h:41
struct Mailbox * mailbox
Current Mailbox.
Definition mview.h:51
char * pattern
Limit pattern string.
Definition mview.h:42
A mailbox.
Definition mailbox.h:79
int vcount
The number of virtual messages.
Definition mailbox.h:99
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition mailbox.h:81
int * v2r
Mapping from virtual to real msgno.
Definition mailbox.h:98
int msg_count
Total number of messages.
Definition mailbox.h:88
int email_max
Size of emails array.
Definition mailbox.h:97
enum MailboxType type
Mailbox type.
Definition mailbox.h:102
void * mdata
Driver specific data.
Definition mailbox.h:132
struct Email ** emails
Array of Emails.
Definition mailbox.h:96
char * name
A short name for the Mailbox.
Definition mailbox.h:82
struct Buffer pathbuf
Path of the Mailbox.
Definition mailbox.h:80
struct Account * account
Account that owns this Mailbox.
Definition mailbox.h:127
int opened
Number of times mailbox is opened.
Definition mailbox.h:128
void * compress_info
Compressed mbox module private data.
Definition mailbox.h:121
struct ConfigSubset * sub
Inherited config items.
Definition mailbox.h:83
Maildir-specific Mailbox data -.
Definition mdata.h:35
struct timespec mtime_cur
Timestamp of the 'cur' dir.
Definition mdata.h:37
mode_t umask
umask to use when creating files
Definition mdata.h:38
Mapping between user-readable string and a constant.
Definition mapping.h:33
Mbox-specific Account data -.
Definition lib.h:49
FILE * fp
Mailbox file.
Definition lib.h:50
bool append
mailbox is opened in append mode
Definition lib.h:56
bool locked
is the mailbox locked?
Definition lib.h:55
struct timespec atime
File's last-access time.
Definition lib.h:52
Container for Accounts, Notifications.
Definition neomutt.h:43
struct AccountArray accounts
All Accounts.
Definition neomutt.h:48
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:47
Notmuch-specific Account data -.
Definition adata.h:35
notmuch_database_t * db
Connection to Notmuch database.
Definition adata.h:36
Notmuch-specific Mailbox data -.
Definition mdata.h:35
int db_limit
Maximum number of results to return.
Definition mdata.h:38
NNTP-specific Account data -.
Definition adata.h:36
time_t newgroups_time
Definition adata.h:56
bool newsrc_modified
Definition adata.h:49
bool hasXOVER
Server supports XOVER command.
Definition adata.h:45
struct Connection * conn
Connection to NNTP Server.
Definition adata.h:62
char * authenticators
Definition adata.h:52
char * overview_fmt
Definition adata.h:53
bool hasXGTITLE
Server supports XGTITLE command.
Definition adata.h:41
unsigned int groups_num
Definition adata.h:58
bool hasCAPABILITIES
Server supports CAPABILITIES command.
Definition adata.h:37
bool hasSTARTTLS
Server supports STARTTLS command.
Definition adata.h:38
bool hasLISTGROUPrange
Server supports LISTGROUPrange command.
Definition adata.h:43
time_t check_time
Definition adata.h:57
time_t mtime
Definition adata.h:55
unsigned int groups_max
Definition adata.h:59
bool hasLISTGROUP
Server supports LISTGROUP command.
Definition adata.h:42
FILE * fp_newsrc
Definition adata.h:50
bool cacheable
Definition adata.h:48
bool hasOVER
Server supports OVER command.
Definition adata.h:44
char * newsrc_file
Definition adata.h:51
bool hasDATE
Server supports DATE command.
Definition adata.h:39
bool hasLIST_NEWSGROUPS
Server supports LIST_NEWSGROUPS command.
Definition adata.h:40
NNTP-specific Mailbox data -.
Definition mdata.h:34
anum_t last_cached
Definition mdata.h:40
bool deleted
Definition mdata.h:45
bool allowed
Definition mdata.h:44
anum_t last_message
Definition mdata.h:38
char * group
Name of newsgroup.
Definition mdata.h:35
char * desc
Description of newsgroup.
Definition mdata.h:36
anum_t unread
Definition mdata.h:41
anum_t last_loaded
Definition mdata.h:39
bool has_new_mail
Definition mdata.h:43
anum_t first_message
Definition mdata.h:37
bool subscribed
Definition mdata.h:42
Private data for a Conditional Date -.
int count
Number of 'units' to count.
char period
Units, e.g. 'd' Day or 'm' Month.
Private data for a Padding Node -.
enum ExpandoPadType pad_type
Padding type.
Attribute associated with a MIME part.
Definition parameter.h:33
char * attribute
Parameter name.
Definition parameter.h:34
char * value
Parameter value.
Definition parameter.h:35
A simple (non-regex) pattern.
Definition lib.h:77
bool group_match
Check a group of Addresses.
Definition lib.h:82
union Pattern::@006112053024257132210207314205210350156165326341 p
struct PatternList * child
Arguments to logical operation.
Definition lib.h:90
long min
Minimum for range checks.
Definition lib.h:88
bool string_match
Check a string for a match.
Definition lib.h:81
regex_t * regex
Compiled regex, for non-pattern matching.
Definition lib.h:92
char * str
String, if string_match is set.
Definition lib.h:94
long max
Maximum for range checks.
Definition lib.h:89
short op
Operation, e.g. MUTT_PAT_SCORE.
Definition lib.h:78
bool is_multi
Multiple case (only for ~I pattern now)
Definition lib.h:87
POP-specific Account data -.
Definition adata.h:37
time_t check_time
Definition adata.h:51
struct Connection * conn
Connection to POP server.
Definition adata.h:38
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition url.h:69
char * user
Username.
Definition url.h:71
char * host
Host.
Definition url.h:73
char * path
Path.
Definition url.h:75
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:338
struct HashElemArray get_elem_list(struct ConfigSet *cs, enum GetElemListFlags flags)
Create a sorted list of all config items.
Definition subset.c:81
@ GEL_ALL_CONFIG
All the normal config (no synonyms or deprecated)
Definition subset.h:81
#define CONFIG_TYPE(t)
Definition types.h:49
@ DT_STRING
a string
Definition types.h:44
#define D_SENSITIVE
Contains sensitive value, e.g. password.
Definition types.h:80
const char * strkey
String key.
Definition hash.h:36
struct Url * url_parse(const char *src)
Fill in Url.
Definition url.c:238
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition url.c:123