1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2003-2021 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Mailutils is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <mh.h>
18 #include <mailutils/sys/msgset.h>
19
20 static char *
private_sequence_name(const char * name)21 private_sequence_name (const char *name)
22 {
23 char *p;
24 char *mbox_dir = mh_expand_name (NULL, mh_current_folder (), NAME_ANY);
25 mu_asprintf (&p, "atr-%s-%s", name, mbox_dir);
26 free (mbox_dir);
27 return p;
28 }
29
30 const char *
mh_seq_read(mu_mailbox_t mbox,const char * name,int flags)31 mh_seq_read (mu_mailbox_t mbox, const char *name, int flags)
32 {
33 const char *value;
34
35 if (flags & SEQ_PRIVATE)
36 {
37 char *p = private_sequence_name (name);
38 value = mh_global_context_get (p, NULL);
39 free (p);
40 }
41 else
42 value = mh_global_sequences_get (mbox, name, NULL);
43 return value;
44 }
45
46 static void
write_sequence(mu_mailbox_t mbox,const char * name,char * value,int private)47 write_sequence (mu_mailbox_t mbox, const char *name, char *value, int private)
48 {
49 if (value && value[0] == 0)
50 value = NULL;
51 if (private)
52 {
53 char *p = private_sequence_name (name);
54 mh_global_context_set (p, value);
55 free (p);
56 }
57 else
58 mh_global_sequences_set (mbox, name, value);
59 }
60
61 static void
delete_sequence(mu_mailbox_t mbox,const char * name,int private)62 delete_sequence (mu_mailbox_t mbox, const char *name, int private)
63 {
64 write_sequence (mbox, name, NULL, private);
65 }
66
67 static void
save_sequence(mu_mailbox_t mbox,const char * name,mu_msgset_t mset,int flags)68 save_sequence (mu_mailbox_t mbox, const char *name, mu_msgset_t mset,
69 int flags)
70 {
71 int rc;
72 mu_stream_t mstr;
73 mu_msgset_t outset;
74 mu_transport_t trans[2];
75
76 rc = mu_msgset_translate (&outset, mset,
77 MU_MSGSET_UID|MU_MSGSET_IGNORE_TRANSERR);
78 if (rc)
79 {
80 mu_diag_funcall (MU_DIAG_ERROR, "mu_msgset_translate", NULL, rc);
81 exit (1);
82 }
83
84 rc = mu_memory_stream_create (&mstr, MU_STREAM_RDWR);
85 if (rc)
86 {
87 mu_diag_funcall (MU_DIAG_ERROR, "mu_memory_stream_create", NULL, rc);
88 exit (1);
89 }
90 mu_stream_msgset_format (mstr, mu_msgset_fmt_mh, outset);
91 mu_stream_write (mstr, "", 1, NULL);
92 mu_stream_ioctl (mstr, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, trans);
93 write_sequence (mbox, name, (char*)trans[0], flags & SEQ_PRIVATE);
94 mu_stream_unref (mstr);
95 mu_msgset_free (outset);
96 }
97
98 void
mh_seq_add(mu_mailbox_t mbox,const char * name,mu_msgset_t mset,int flags)99 mh_seq_add (mu_mailbox_t mbox, const char *name, mu_msgset_t mset, int flags)
100 {
101 const char *value = mh_seq_read (mbox, name, flags);
102
103 delete_sequence (mbox, name, !(flags & SEQ_PRIVATE));
104 if (value && !(flags & SEQ_ZERO))
105 {
106 mu_msgset_t oldset;
107 mh_msgset_parse_string (&oldset, mbox, value, "cur");
108 mu_msgset_add (oldset, mset);
109 save_sequence (mbox, name, oldset, flags);
110 mu_msgset_free (oldset);
111 }
112 else
113 save_sequence (mbox, name, mset, flags);
114 }
115
116 int
mh_seq_delete(mu_mailbox_t mbox,const char * name,mu_msgset_t mset,int flags)117 mh_seq_delete (mu_mailbox_t mbox, const char *name,
118 mu_msgset_t mset, int flags)
119 {
120 const char *value = mh_seq_read (mbox, name, flags);
121 mu_msgset_t oldset;
122
123 if (!value)
124 return 0;
125 mh_msgset_parse_string (&oldset, mbox, value, "cur");
126 mu_msgset_sub (oldset, mset);
127 save_sequence (mbox, name, oldset, flags);
128 mu_msgset_free (oldset);
129 return 0;
130 }
131
132 struct privseq_closure
133 {
134 const char *mbox_dir;
135 mu_mhprop_iterator_t fun;
136 void *data;
137 char *namebuf;
138 size_t namelen;
139 };
140
141 static int
privseq_handler(const char * name,const char * value,void * data)142 privseq_handler (const char *name, const char *value, void *data)
143 {
144 struct privseq_closure *pclos = data;
145
146 if (strncmp (name, "atr-", 4) == 0)
147 {
148 char *p = strchr (name + 4, '-');
149 if (p && strcmp (p + 1, pclos->mbox_dir) == 0)
150 {
151 size_t len = p - name - 4;
152 if (pclos->namelen < len + 1)
153 {
154 pclos->namelen = len + 1;
155 pclos->namebuf = mu_realloc (pclos->namebuf, pclos->namelen);
156 }
157 memcpy (pclos->namebuf, name + 4, len);
158 pclos->namebuf[len] = 0;
159 }
160 return pclos->fun (pclos->namebuf, value, pclos->data);
161 }
162 return 0;
163 }
164
165 int
mh_private_sequences_iterate(mu_mailbox_t mbox,mu_mhprop_iterator_t fp,void * data)166 mh_private_sequences_iterate (mu_mailbox_t mbox,
167 mu_mhprop_iterator_t fp, void *data)
168 {
169 int rc;
170 struct privseq_closure clos;
171 mu_url_t url;
172
173 rc = mu_mailbox_get_url (mbox, &url);
174 if (rc)
175 {
176 mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_get_url", NULL, rc);
177 exit (1);
178 }
179 rc = mu_url_sget_path (url, &clos.mbox_dir);
180 if (rc)
181 {
182 mu_diag_funcall (MU_DIAG_ERROR, "mu_url_sget_path",
183 mu_url_to_string (url), rc);
184 exit (1);
185 }
186
187 clos.fun = fp;
188 clos.data = data;
189 clos.namebuf = NULL;
190 clos.namelen = 0;
191 rc = mu_mhprop_iterate (mu_mh_context, privseq_handler, &clos);
192 free (clos.namebuf);
193 return rc;
194 }
195