NeoMutt  2021-10-29-220-g2b1eec
Teaching an old dog new tricks
DOXYGEN
compress.c
Go to the documentation of this file.
1 
37 #include "config.h"
38 #include <stdbool.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <sys/stat.h>
42 #include <unistd.h>
43 #include "mutt/lib.h"
44 #include "config/lib.h"
45 #include "core/lib.h"
46 #include "gui/lib.h"
47 #include "lib.h"
48 #include "format_flags.h"
49 #include "hook.h"
50 #include "mutt_commands.h"
51 #include "mutt_globals.h"
52 #include "muttlib.h"
53 #include "mx.h"
54 #include "protos.h"
55 
56 struct Email;
57 
58 static const struct Command comp_commands[] = {
59  // clang-format off
60  { "append-hook", mutt_parse_hook, MUTT_APPEND_HOOK },
61  { "close-hook", mutt_parse_hook, MUTT_CLOSE_HOOK },
62  { "open-hook", mutt_parse_hook, MUTT_OPEN_HOOK },
63  // clang-format on
64 };
65 
69 void mutt_comp_init(void)
70 {
72 }
73 
85 static bool lock_realpath(struct Mailbox *m, bool excl)
86 {
87  if (!m || !m->compress_info)
88  return false;
89 
90  struct CompressInfo *ci = m->compress_info;
91 
92  if (ci->locked)
93  return true;
94 
95  if (excl)
96  ci->fp_lock = fopen(m->realpath, "a");
97  else
98  ci->fp_lock = fopen(m->realpath, "r");
99  if (!ci->fp_lock)
100  {
101  mutt_perror(m->realpath);
102  return false;
103  }
104 
105  int r = mutt_file_lock(fileno(ci->fp_lock), excl, true);
106  if (r == 0)
107  ci->locked = true;
108  else if (excl)
109  {
111  m->readonly = true;
112  return true;
113  }
114 
115  return r == 0;
116 }
117 
124 static void unlock_realpath(struct Mailbox *m)
125 {
126  if (!m || !m->compress_info)
127  return;
128 
129  struct CompressInfo *ci = m->compress_info;
130 
131  if (!ci->locked)
132  return;
133 
134  mutt_file_unlock(fileno(ci->fp_lock));
135 
136  ci->locked = false;
138 }
139 
150 static int setup_paths(struct Mailbox *m)
151 {
152  if (!m)
153  return -1;
154 
155  /* Setup the right paths */
157 
158  /* We will uncompress to TMPDIR */
159  struct Buffer *buf = mutt_buffer_pool_get();
160  mutt_buffer_mktemp(buf);
161  mutt_buffer_copy(&m->pathbuf, buf);
163 
164  FILE *fp = mutt_file_fopen(mailbox_path(m), "w");
165  if (!fp)
166  return -1;
167 
168  mutt_file_fclose(&fp);
169  return 0;
170 }
171 
178 static void store_size(const struct Mailbox *m)
179 {
180  if (!m || !m->compress_info)
181  return;
182 
183  struct CompressInfo *ci = m->compress_info;
184 
185  ci->size = mutt_file_get_size(m->realpath);
186 }
187 
196 static struct CompressInfo *set_compress_info(struct Mailbox *m)
197 {
198  if (!m)
199  return NULL;
200 
201  if (m->compress_info)
202  return m->compress_info;
203 
204  /* Open is compulsory */
205  const char *o = mutt_find_hook(MUTT_OPEN_HOOK, mailbox_path(m));
206  if (!o)
207  return NULL;
208 
209  const char *c = mutt_find_hook(MUTT_CLOSE_HOOK, mailbox_path(m));
210  const char *a = mutt_find_hook(MUTT_APPEND_HOOK, mailbox_path(m));
211 
212  struct CompressInfo *ci = mutt_mem_calloc(1, sizeof(struct CompressInfo));
213  m->compress_info = ci;
214 
215  ci->cmd_open = mutt_str_dup(o);
216  ci->cmd_close = mutt_str_dup(c);
217  ci->cmd_append = mutt_str_dup(a);
218 
219  return ci;
220 }
221 
226 static void compress_info_free(struct Mailbox *m)
227 {
228  if (!m || !m->compress_info)
229  return;
230 
231  struct CompressInfo *ci = m->compress_info;
232  FREE(&ci->cmd_open);
233  FREE(&ci->cmd_close);
234  FREE(&ci->cmd_append);
235 
236  unlock_realpath(m);
237 
238  FREE(&m->compress_info);
239 }
240 
249 static const char *compress_format_str(char *buf, size_t buflen, size_t col, int cols,
250  char op, const char *src, const char *prec,
251  const char *if_str, const char *else_str,
252  intptr_t data, MuttFormatFlags flags)
253 {
254  if (!buf || (data == 0))
255  return src;
256 
257  struct Mailbox *m = (struct Mailbox *) data;
258 
259  /* NOTE the compressed file config vars expect %f and %t to be
260  * surrounded by '' (unlike other NeoMutt config vars, which add the
261  * outer quotes for the user). This is why we use the
262  * mutt_buffer_quote_filename() form with add_outer of false. */
263  struct Buffer *quoted = mutt_buffer_pool_get();
264  switch (op)
265  {
266  case 'f':
267  /* Compressed file */
268  mutt_buffer_quote_filename(quoted, m->realpath, false);
269  snprintf(buf, buflen, "%s", mutt_buffer_string(quoted));
270  break;
271  case 't':
272  /* Plaintext, temporary file */
273  mutt_buffer_quote_filename(quoted, mailbox_path(m), false);
274  snprintf(buf, buflen, "%s", mutt_buffer_string(quoted));
275  break;
276  }
277 
278  mutt_buffer_pool_release(&quoted);
279  return src;
280 }
281 
299 static void expand_command_str(const struct Mailbox *m, const char *cmd, char *buf, int buflen)
300 {
301  if (!m || !cmd || !buf)
302  return;
303 
304  mutt_expando_format(buf, buflen, 0, buflen, cmd, compress_format_str,
305  (intptr_t) m, MUTT_FORMAT_NO_FLAGS);
306 }
307 
319 static int execute_command(struct Mailbox *m, const char *command, const char *progress)
320 {
321  if (!m || !command || !progress)
322  return 0;
323 
324  if (m->verbose)
325  mutt_message(progress, m->realpath);
326 
327  int rc = 1;
328  char sys_cmd[STR_COMMAND];
329 
330  mutt_sig_block();
331  endwin();
332  fflush(stdout);
333 
334  expand_command_str(m, command, sys_cmd, sizeof(sys_cmd));
335 
336  if (mutt_system(sys_cmd) != 0)
337  {
338  rc = 0;
340  mutt_error(_("Error running \"%s\""), sys_cmd);
341  }
342 
344 
345  return rc;
346 }
347 
360 {
361  if (!m)
362  return false;
363 
364  /* If this succeeds, we know there's an open-hook */
365  struct CompressInfo *ci = set_compress_info(m);
366  if (!ci)
367  return false;
368 
369  /* We have an open-hook, so to append we need an append-hook,
370  * or a close-hook. */
371  if (ci->cmd_append || ci->cmd_close)
372  return true;
373 
374  mutt_error(_("Can't append without an append-hook or close-hook : %s"), mailbox_path(m));
375  return false;
376 }
377 
388 bool mutt_comp_can_read(const char *path)
389 {
390  if (!path)
391  return false;
392 
393  if (mutt_find_hook(MUTT_OPEN_HOOK, path))
394  return true;
395 
396  return false;
397 }
398 
408 int mutt_comp_valid_command(const char *cmd)
409 {
410  if (!cmd)
411  return 0;
412 
413  return strstr(cmd, "%f") && strstr(cmd, "%t");
414 }
415 
419 static bool comp_ac_owns_path(struct Account *a, const char *path)
420 {
421  return false;
422 }
423 
427 static bool comp_ac_add(struct Account *a, struct Mailbox *m)
428 {
429  return true;
430 }
431 
440 static enum MxOpenReturns comp_mbox_open(struct Mailbox *m)
441 {
442  struct CompressInfo *ci = set_compress_info(m);
443  if (!ci)
444  return MX_OPEN_ERROR;
445 
446  /* If there's no close-hook, or the file isn't writable */
447  if (!ci->cmd_close || (access(mailbox_path(m), W_OK) != 0))
448  m->readonly = true;
449 
450  if (setup_paths(m) != 0)
451  goto cmo_fail;
452  store_size(m);
453 
454  if (!lock_realpath(m, false))
455  {
456  mutt_error(_("Unable to lock mailbox"));
457  goto cmo_fail;
458  }
459 
460  int rc = execute_command(m, ci->cmd_open, _("Decompressing %s"));
461  if (rc == 0)
462  goto cmo_fail;
463 
464  unlock_realpath(m);
465 
467  if (m->type == MUTT_UNKNOWN)
468  {
469  mutt_error(_("Can't identify the contents of the compressed file"));
470  goto cmo_fail;
471  }
472 
473  ci->child_ops = mx_get_ops(m->type);
474  if (!ci->child_ops)
475  {
476  mutt_error(_("Can't find mailbox ops for mailbox type %d"), m->type);
477  goto cmo_fail;
478  }
479 
480  m->account->type = m->type;
481  return ci->child_ops->mbox_open(m);
482 
483 cmo_fail:
484  /* remove the partial uncompressed file */
485  (void) remove(mailbox_path(m));
487  return MX_OPEN_ERROR;
488 }
489 
498 static bool comp_mbox_open_append(struct Mailbox *m, OpenMailboxFlags flags)
499 {
500  /* If this succeeds, we know there's an open-hook */
501  struct CompressInfo *ci = set_compress_info(m);
502  if (!ci)
503  return false;
504 
505  /* To append we need an append-hook or a close-hook */
506  if (!ci->cmd_append && !ci->cmd_close)
507  {
508  mutt_error(_("Can't append without an append-hook or close-hook : %s"),
509  mailbox_path(m));
510  goto cmoa_fail1;
511  }
512 
513  if (setup_paths(m) != 0)
514  goto cmoa_fail2;
515 
516  /* Lock the realpath for the duration of the append.
517  * It will be unlocked in the close */
518  if (!lock_realpath(m, true))
519  {
520  mutt_error(_("Unable to lock mailbox"));
521  goto cmoa_fail2;
522  }
523 
524  /* Open the existing mailbox, unless we are appending */
525  if (!ci->cmd_append && (mutt_file_get_size(m->realpath) > 0))
526  {
527  int rc = execute_command(m, ci->cmd_open, _("Decompressing %s"));
528  if (rc == 0)
529  {
530  mutt_error(_("Compress command failed: %s"), ci->cmd_open);
531  goto cmoa_fail2;
532  }
534  }
535  else
536  {
537  m->type = cs_subset_enum(NeoMutt->sub, "mbox_type");
538  }
539 
540  /* We can only deal with mbox and mmdf mailboxes */
541  if ((m->type != MUTT_MBOX) && (m->type != MUTT_MMDF))
542  {
543  mutt_error(_("Unsupported mailbox type for appending"));
544  goto cmoa_fail2;
545  }
546 
547  ci->child_ops = mx_get_ops(m->type);
548  if (!ci->child_ops)
549  {
550  mutt_error(_("Can't find mailbox ops for mailbox type %d"), m->type);
551  goto cmoa_fail2;
552  }
553 
554  if (!ci->child_ops->mbox_open_append(m, flags))
555  goto cmoa_fail2;
556 
557  return true;
558 
559 cmoa_fail2:
560  /* remove the partial uncompressed file */
561  (void) remove(mailbox_path(m));
562 cmoa_fail1:
563  /* Free the compress_info to prevent close from trying to recompress */
565 
566  return false;
567 }
568 
579 static enum MxStatus comp_mbox_check(struct Mailbox *m)
580 {
581  if (!m->compress_info)
582  return MX_STATUS_ERROR;
583 
584  struct CompressInfo *ci = m->compress_info;
585 
586  const struct MxOps *ops = ci->child_ops;
587  if (!ops)
588  return MX_STATUS_ERROR;
589 
590  int size = mutt_file_get_size(m->realpath);
591  if (size == ci->size)
592  return MX_STATUS_OK;
593 
594  if (!lock_realpath(m, false))
595  {
596  mutt_error(_("Unable to lock mailbox"));
597  return MX_STATUS_ERROR;
598  }
599 
600  int rc = execute_command(m, ci->cmd_open, _("Decompressing %s"));
601  store_size(m);
602  unlock_realpath(m);
603  if (rc == 0)
604  return MX_STATUS_ERROR;
605 
606  return ops->mbox_check(m);
607 }
608 
615 static enum MxStatus comp_mbox_sync(struct Mailbox *m)
616 {
617  if (!m->compress_info)
618  return MX_STATUS_ERROR;
619 
620  struct CompressInfo *ci = m->compress_info;
621 
622  if (!ci->cmd_close)
623  {
624  mutt_error(_("Can't sync a compressed file without a close-hook"));
625  return MX_STATUS_ERROR;
626  }
627 
628  const struct MxOps *ops = ci->child_ops;
629  if (!ops)
630  return MX_STATUS_ERROR;
631 
632  if (!lock_realpath(m, true))
633  {
634  mutt_error(_("Unable to lock mailbox"));
635  return MX_STATUS_ERROR;
636  }
637 
638  enum MxStatus check = comp_mbox_check(m);
639  if (check != MX_STATUS_OK)
640  goto sync_cleanup;
641 
642  check = ops->mbox_sync(m);
643  if (check != MX_STATUS_OK)
644  goto sync_cleanup;
645 
646  int rc = execute_command(m, ci->cmd_close, _("Compressing %s"));
647  if (rc == 0)
648  {
649  check = MX_STATUS_ERROR;
650  goto sync_cleanup;
651  }
652 
653  check = MX_STATUS_OK;
654 
655 sync_cleanup:
656  store_size(m);
657  unlock_realpath(m);
658  return check;
659 }
660 
667 static enum MxStatus comp_mbox_close(struct Mailbox *m)
668 {
669  if (!m->compress_info)
670  return MX_STATUS_ERROR;
671 
672  struct CompressInfo *ci = m->compress_info;
673 
674  const struct MxOps *ops = ci->child_ops;
675  if (!ops)
676  {
678  return MX_STATUS_ERROR;
679  }
680 
681  ops->mbox_close(m);
682 
683  /* sync has already been called, so we only need to delete some files */
684  if (m->append)
685  {
686  const char *append = NULL;
687  const char *msg = NULL;
688 
689  /* The file exists and we can append */
690  if ((access(m->realpath, F_OK) == 0) && ci->cmd_append)
691  {
692  append = ci->cmd_append;
693  msg = _("Compressed-appending to %s...");
694  }
695  else
696  {
697  append = ci->cmd_close;
698  msg = _("Compressing %s");
699  }
700 
701  int rc = execute_command(m, append, msg);
702  if (rc == 0)
703  {
705  mutt_error(_("Error. Preserving temporary file: %s"), mailbox_path(m));
706  }
707  else
708  remove(mailbox_path(m));
709 
710  unlock_realpath(m);
711  }
712  else
713  {
714  /* If the file was removed, remove the compressed folder too */
715  if (access(mailbox_path(m), F_OK) != 0)
716  {
717  const bool c_save_empty = cs_subset_bool(NeoMutt->sub, "save_empty");
718  if (!c_save_empty)
719  {
720  remove(m->realpath);
721  }
722  }
723  else
724  {
725  remove(mailbox_path(m));
726  }
727  }
728 
730 
731  return MX_STATUS_OK;
732 }
733 
737 static bool comp_msg_open(struct Mailbox *m, struct Message *msg, int msgno)
738 {
739  if (!m->compress_info)
740  return false;
741 
742  struct CompressInfo *ci = m->compress_info;
743 
744  const struct MxOps *ops = ci->child_ops;
745  if (!ops)
746  return false;
747 
748  /* Delegate */
749  return ops->msg_open(m, msg, msgno);
750 }
751 
755 static bool comp_msg_open_new(struct Mailbox *m, struct Message *msg, const struct Email *e)
756 {
757  if (!m->compress_info)
758  return false;
759 
760  struct CompressInfo *ci = m->compress_info;
761 
762  const struct MxOps *ops = ci->child_ops;
763  if (!ops)
764  return false;
765 
766  /* Delegate */
767  return ops->msg_open_new(m, msg, e);
768 }
769 
773 static int comp_msg_commit(struct Mailbox *m, struct Message *msg)
774 {
775  if (!m->compress_info)
776  return -1;
777 
778  struct CompressInfo *ci = m->compress_info;
779 
780  const struct MxOps *ops = ci->child_ops;
781  if (!ops)
782  return -1;
783 
784  /* Delegate */
785  return ops->msg_commit(m, msg);
786 }
787 
791 static int comp_msg_close(struct Mailbox *m, struct Message *msg)
792 {
793  if (!m->compress_info)
794  return -1;
795 
796  struct CompressInfo *ci = m->compress_info;
797 
798  const struct MxOps *ops = ci->child_ops;
799  if (!ops)
800  return -1;
801 
802  /* Delegate */
803  return ops->msg_close(m, msg);
804 }
805 
809 static int comp_msg_padding_size(struct Mailbox *m)
810 {
811  if (!m->compress_info)
812  return 0;
813 
814  struct CompressInfo *ci = m->compress_info;
815 
816  const struct MxOps *ops = ci->child_ops;
817  if (!ops || !ops->msg_padding_size)
818  return 0;
819 
820  return ops->msg_padding_size(m);
821 }
822 
826 static int comp_msg_save_hcache(struct Mailbox *m, struct Email *e)
827 {
828  if (!m->compress_info)
829  return 0;
830 
831  struct CompressInfo *ci = m->compress_info;
832 
833  const struct MxOps *ops = ci->child_ops;
834  if (!ops || !ops->msg_save_hcache)
835  return 0;
836 
837  return ops->msg_save_hcache(m, e);
838 }
839 
843 static int comp_tags_edit(struct Mailbox *m, const char *tags, struct Buffer *buf)
844 {
845  if (!m->compress_info)
846  return 0;
847 
848  struct CompressInfo *ci = m->compress_info;
849 
850  const struct MxOps *ops = ci->child_ops;
851  if (!ops || !ops->tags_edit)
852  return 0;
853 
854  return ops->tags_edit(m, tags, buf);
855 }
856 
860 static int comp_tags_commit(struct Mailbox *m, struct Email *e, const char *buf)
861 {
862  if (!m->compress_info)
863  return 0;
864 
865  struct CompressInfo *ci = m->compress_info;
866 
867  const struct MxOps *ops = ci->child_ops;
868  if (!ops || !ops->tags_commit)
869  return 0;
870 
871  return ops->tags_commit(m, e, buf);
872 }
873 
877 static enum MailboxType comp_path_probe(const char *path, const struct stat *st)
878 {
879  if (!st || !S_ISREG(st->st_mode))
880  return MUTT_UNKNOWN;
881 
882  if (mutt_comp_can_read(path))
883  return MUTT_COMPRESSED;
884 
885  return MUTT_UNKNOWN;
886 }
887 
891 static int comp_path_canon(char *buf, size_t buflen)
892 {
893  mutt_path_canon(buf, buflen, HomeDir, false);
894  return 0;
895 }
896 
900 static int comp_path_pretty(char *buf, size_t buflen, const char *folder)
901 {
902  if (mutt_path_abbr_folder(buf, folder))
903  return 0;
904 
905  if (mutt_path_pretty(buf, buflen, HomeDir, false))
906  return 0;
907 
908  return -1;
909 }
910 
914 static int comp_path_parent(char *buf, size_t buflen)
915 {
916  if (mutt_path_parent(buf))
917  return 0;
918 
919  if (buf[0] == '~')
920  mutt_path_canon(buf, buflen, HomeDir, false);
921 
922  if (mutt_path_parent(buf))
923  return 0;
924 
925  return -1;
926 }
927 
934 struct MxOps MxCompOps = {
935  // clang-format off
937  .name = "compressed",
938  .is_local = true,
939  .ac_owns_path = comp_ac_owns_path,
940  .ac_add = comp_ac_add,
941  .mbox_open = comp_mbox_open,
942  .mbox_open_append = comp_mbox_open_append,
943  .mbox_check = comp_mbox_check,
944  .mbox_check_stats = NULL,
945  .mbox_sync = comp_mbox_sync,
946  .mbox_close = comp_mbox_close,
947  .msg_open = comp_msg_open,
948  .msg_open_new = comp_msg_open_new,
949  .msg_commit = comp_msg_commit,
950  .msg_close = comp_msg_close,
951  .msg_padding_size = comp_msg_padding_size,
952  .msg_save_hcache = comp_msg_save_hcache,
953  .tags_edit = comp_tags_edit,
954  .tags_commit = comp_tags_commit,
955  .path_probe = comp_path_probe,
956  .path_canon = comp_path_canon,
957  .path_pretty = comp_path_pretty,
958  .path_parent = comp_path_parent,
959  .path_is_empty = NULL,
960  // clang-format on
961 };
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:447
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
static const struct Command comp_commands[]
Definition: compress.c:58
static void compress_info_free(struct Mailbox *m)
Frees the compress info members and structure.
Definition: compress.c:226
static int setup_paths(struct Mailbox *m)
Set the mailbox paths.
Definition: compress.c:150
static int execute_command(struct Mailbox *m, const char *command, const char *progress)
Run a system command.
Definition: compress.c:319
void mutt_comp_init(void)
Setup feature commands.
Definition: compress.c:69
static void store_size(const struct Mailbox *m)
Save the size of the compressed file.
Definition: compress.c:178
static bool lock_realpath(struct Mailbox *m, bool excl)
Try to lock the ctx->realpath.
Definition: compress.c:85
static struct CompressInfo * set_compress_info(struct Mailbox *m)
Find the compress hooks for a mailbox.
Definition: compress.c:196
bool mutt_comp_can_append(struct Mailbox *m)
Can we append to this path?
Definition: compress.c:359
static void unlock_realpath(struct Mailbox *m)
Unlock the mailbox->realpath.
Definition: compress.c:124
int mutt_comp_valid_command(const char *cmd)
Is this command string allowed?
Definition: compress.c:408
static void expand_command_str(const struct Mailbox *m, const char *cmd, char *buf, int buflen)
Expand placeholders in command string.
Definition: compress.c:299
bool mutt_comp_can_read(const char *path)
Can we read from this file?
Definition: compress.c:388
Convenience wrapper for the config headers.
char * HomeDir
User's home directory.
Definition: mutt_globals.h:49
Convenience wrapper for the core headers.
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:427
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
int mutt_file_lock(int fd, bool excl, bool timeout)
(Try to) Lock a file using fcntl()
Definition: file.c:1206
void mutt_buffer_quote_filename(struct Buffer *buf, const char *filename, bool add_outer)
Quote a filename to survive the shell's quoting rules.
Definition: file.c:866
int mutt_file_unlock(int fd)
Unlock a file previously locked by mutt_file_lock()
Definition: file.c:1254
long mutt_file_get_size(const char *path)
Get the size of a file.
Definition: file.c:1526
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:593
Flags to control mutt_expando_format()
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
uint8_t MuttFormatFlags
Flags for mutt_expando_format(), e.g. MUTT_FORMAT_FORCESUBJ.
Definition: format_flags.h:29
enum CommandResult mutt_parse_hook(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'hook' family of commands - Implements Command::parse() -.
Definition: hook.c:82
static const char * compress_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Expand the filenames in a command string - Implements format_t -.
Definition: compress.c:249
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t callback, intptr_t data, MuttFormatFlags flags)
Expand expandos (x) in a string -.
Definition: muttlib.c:780
#define mutt_error(...)
Definition: logging.h:87
#define mutt_message(...)
Definition: logging.h:86
#define mutt_perror(...)
Definition: logging.h:88
static bool comp_ac_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account - Implements MxOps::ac_add() -.
Definition: compress.c:427
static bool comp_ac_owns_path(struct Account *a, const char *path)
Check whether an Account owns a Mailbox path - Implements MxOps::ac_owns_path() -.
Definition: compress.c:419
struct MxOps MxCompOps
Compressed Mailbox - Implements MxOps -.
Definition: compress.c:934
static enum MxStatus comp_mbox_check(struct Mailbox *m)
Check for new mail - Implements MxOps::mbox_check() -.
Definition: compress.c:579
static enum MxStatus comp_mbox_close(struct Mailbox *m)
Close a Mailbox - Implements MxOps::mbox_close() -.
Definition: compress.c:667
static bool comp_mbox_open_append(struct Mailbox *m, OpenMailboxFlags flags)
Open a Mailbox for appending - Implements MxOps::mbox_open_append() -.
Definition: compress.c:498
static enum MxOpenReturns comp_mbox_open(struct Mailbox *m)
Open a Mailbox - Implements MxOps::mbox_open() -.
Definition: compress.c:440
static enum MxStatus comp_mbox_sync(struct Mailbox *m)
Save changes to the Mailbox - Implements MxOps::mbox_sync() -.
Definition: compress.c:615
static int comp_msg_close(struct Mailbox *m, struct Message *msg)
Close an email - Implements MxOps::msg_close() -.
Definition: compress.c:791
static int comp_msg_commit(struct Mailbox *m, struct Message *msg)
Save changes to an email - Implements MxOps::msg_commit() -.
Definition: compress.c:773
static bool comp_msg_open_new(struct Mailbox *m, struct Message *msg, const struct Email *e)
Open a new message in a Mailbox - Implements MxOps::msg_open_new() -.
Definition: compress.c:755
static bool comp_msg_open(struct Mailbox *m, struct Message *msg, int msgno)
Open an email message in a Mailbox - Implements MxOps::msg_open() -.
Definition: compress.c:737
static int comp_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Implements MxOps::msg_padding_size() -.
Definition: compress.c:809
static int comp_msg_save_hcache(struct Mailbox *m, struct Email *e)
Save message to the header cache - Implements MxOps::msg_save_hcache() -.
Definition: compress.c:826
static int comp_path_canon(char *buf, size_t buflen)
Canonicalise a Mailbox path - Implements MxOps::path_canon() -.
Definition: compress.c:891
static int comp_path_parent(char *buf, size_t buflen)
Find the parent of a Mailbox path - Implements MxOps::path_parent() -.
Definition: compress.c:914
static int comp_path_pretty(char *buf, size_t buflen, const char *folder)
Abbreviate a Mailbox path - Implements MxOps::path_pretty() -.
Definition: compress.c:900
static enum MailboxType comp_path_probe(const char *path, const struct stat *st)
Is this a compressed Mailbox? - Implements MxOps::path_probe() -.
Definition: compress.c:877
static int comp_tags_commit(struct Mailbox *m, struct Email *e, const char *buf)
Save the tags to a message - Implements MxOps::tags_commit() -.
Definition: compress.c:860
static int comp_tags_edit(struct Mailbox *m, const char *tags, struct Buffer *buf)
Prompt and validate new messages tags - Implements MxOps::tags_edit() -.
Definition: compress.c:843
Convenience wrapper for the gui headers.
unsigned char cs_subset_enum(const struct ConfigSubset *sub, const char *name)
Get a enumeration config item by name.
Definition: helpers.c:97
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
char * mutt_find_hook(HookFlags type, const char *pat)
Find a matching hook.
Definition: hook.c:579
Parse and execute user-defined hooks.
#define MUTT_OPEN_HOOK
open-hook: to read a compressed mailbox
Definition: hook.h:51
#define MUTT_CLOSE_HOOK
close-hook: write to a compressed mailbox
Definition: hook.h:53
#define MUTT_APPEND_HOOK
append-hook: append to a compressed mailbox
Definition: hook.h:52
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:215
MailboxType
Supported mailbox formats.
Definition: mailbox.h:44
@ MUTT_MMDF
'mmdf' Mailbox type
Definition: mailbox.h:49
@ MUTT_MBOX
'mbox' Mailbox type
Definition: mailbox.h:48
@ MUTT_COMPRESSED
Compressed file Mailbox type.
Definition: mailbox.h:56
@ MUTT_UNKNOWN
Mailbox wasn't recognised.
Definition: mailbox.h:47
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define FREE(x)
Definition: memory.h:40
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
bool mutt_path_abbr_folder(char *buf, const char *folder)
Create a folder abbreviation.
Definition: path.c:490
bool mutt_path_pretty(char *buf, size_t buflen, const char *homedir, bool is_dir)
Tidy a filesystem path.
Definition: path.c:186
bool mutt_path_canon(char *buf, size_t buflen, const char *homedir, bool is_dir)
Create the canonical version of a path.
Definition: path.c:285
bool mutt_path_parent(char *buf)
Find the parent of a path.
Definition: path.c:458
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:181
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:257
Definitions of NeoMutt commands.
#define COMMANDS_REGISTER(cmds)
Definition: mutt_commands.h:47
Hundreds of global variables to back the user variables.
Some miscellaneous functions.
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
const struct MxOps * mx_get_ops(enum MailboxType type)
Get mailbox operations.
Definition: mx.c:141
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1326
API for mailboxes.
uint8_t OpenMailboxFlags
Flags for mutt_open_mailbox(), e.g. MUTT_NOSORT.
Definition: mxapi.h:59
MxOpenReturns
Return values for mbox_open()
Definition: mxapi.h:89
@ MX_OPEN_ERROR
Open failed with an error.
Definition: mxapi.h:91
MxStatus
Return values from mbox_check(), mbox_check_stats(), mbox_snc(), and mbox_close()
Definition: mxapi.h:76
@ MX_STATUS_ERROR
An error occurred.
Definition: mxapi.h:77
@ MX_STATUS_OK
No changes.
Definition: mxapi.h:78
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
Prototypes for many functions.
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
void mutt_sig_block(void)
Block signals during critical operations.
Definition: signal.c:150
void mutt_sig_unblock(void)
Restore previously blocked signals.
Definition: signal.c:168
Key value store.
#define STR_COMMAND
Enough space for a long command line.
Definition: string2.h:35
A group of associated Mailboxes.
Definition: account.h:37
enum MailboxType type
Type of Mailboxes this Account contains.
Definition: account.h:38
String manipulation buffer.
Definition: buffer.h:34
Private data for compress.
Definition: lib.h:47
const char * cmd_append
append-hook command
Definition: lib.h:48
FILE * fp_lock
fp used for locking
Definition: lib.h:54
const char * cmd_open
open-hook command
Definition: lib.h:50
const struct MxOps * child_ops
callbacks of de-compressed file
Definition: lib.h:52
bool locked
if realpath is locked
Definition: lib.h:53
const char * cmd_close
close-hook command
Definition: lib.h:49
long size
size of the compressed file
Definition: lib.h:51
The envelope/body of an email.
Definition: email.h:37
A mailbox.
Definition: mailbox.h:82
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
bool append
Mailbox is opened in append mode.
Definition: mailbox.h:113
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
struct Buffer pathbuf
Path of the Mailbox.
Definition: mailbox.h:83
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:131
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:124
bool readonly
Don't allow changes to the mailbox.
Definition: mailbox.h:119
bool verbose
Display status messages?
Definition: mailbox.h:118
A local copy of an email.
Definition: mxapi.h:42
Definition: mxapi.h:104
int(* tags_commit)(struct Mailbox *m, struct Email *e, const char *buf)
Definition: mxapi.h:352
int(* msg_save_hcache)(struct Mailbox *m, struct Email *e)
Definition: mxapi.h:316
enum MailboxType type
Mailbox type, e.g. MUTT_IMAP.
Definition: mxapi.h:105
int(* msg_padding_size)(struct Mailbox *m)
Definition: mxapi.h:300
int(* tags_edit)(struct Mailbox *m, const char *tags, struct Buffer *buf)
Definition: mxapi.h:334
int(* msg_commit)(struct Mailbox *m, struct Message *msg)
Definition: mxapi.h:271
enum MxOpenReturns(* mbox_open)(struct Mailbox *m)
Definition: mxapi.h:152
int(* msg_close)(struct Mailbox *m, struct Message *msg)
Definition: mxapi.h:287
bool(* msg_open_new)(struct Mailbox *m, struct Message *msg, const struct Email *e)
Definition: mxapi.h:255
enum MxStatus(* mbox_close)(struct Mailbox *m)
Definition: mxapi.h:220
enum MxStatus(* mbox_sync)(struct Mailbox *m)
Definition: mxapi.h:207
bool(* mbox_open_append)(struct Mailbox *m, OpenMailboxFlags flags)
Definition: mxapi.h:167
enum MxStatus(* mbox_check)(struct Mailbox *m)
Definition: mxapi.h:180
bool(* msg_open)(struct Mailbox *m, struct Message *msg, int msgno)
Definition: mxapi.h:238
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39