1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2008-2021 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library 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 GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 /* Mail header iterators. */
19
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <mailutils/sys/header.h>
27 #include <mailutils/errno.h>
28
29 struct header_iterator
30 {
31 mu_header_t header;
32 size_t index;
33 int backwards;
34 };
35
36 static int
hdr_first(void * owner)37 hdr_first (void *owner)
38 {
39 struct header_iterator *itr = owner;
40 if (itr->backwards)
41 {
42 if (mu_header_get_field_count (itr->header, &itr->index))
43 return 1;
44 }
45 else
46 itr->index = 1;
47 return 0;
48 }
49
50 static int
hdr_next(void * owner)51 hdr_next (void *owner)
52 {
53 struct header_iterator *itr = owner;
54 if (itr->backwards)
55 {
56 if (itr->index != 0)
57 itr->index--;
58 }
59 else
60 itr->index++;
61 return 0;
62 }
63
64 static int
hdr_getitem(void * owner,void ** pret,const void ** pkey)65 hdr_getitem (void *owner, void **pret, const void **pkey)
66 {
67 struct header_iterator *itr = owner;
68 int rc;
69 size_t count;
70
71 rc = mu_header_get_field_count (itr->header, &count);
72 if (rc)
73 return rc;
74 if (itr->index < 1 || itr->index > count)
75 return MU_ERR_NOENT;
76
77 rc = mu_header_sget_field_value (itr->header, itr->index,
78 (const char**) pret);
79 if (rc == 0)
80 {
81 if (pkey)
82 rc = mu_header_sget_field_name (itr->header, itr->index,
83 (const char**) pkey);
84 }
85 return rc;
86 }
87
88 static int
hdr_finished_p(void * owner)89 hdr_finished_p (void *owner)
90 {
91 struct header_iterator *itr = owner;
92 size_t count;
93
94 if (itr->backwards)
95 return itr->index < 1;
96
97 if (mu_header_get_field_count (itr->header, &count))
98 return 1;
99 return itr->index > count;
100 }
101
102 static int
hdr_destroy(mu_iterator_t iterator,void * data)103 hdr_destroy (mu_iterator_t iterator, void *data)
104 {
105 struct header_iterator *itr = data;
106 mu_iterator_detach (&itr->header->itr, iterator);
107 free (data);
108 return 0;
109 }
110
111 static int
hdr_delitem(void * owner,void * item)112 hdr_delitem (void *owner, void *item)
113 {
114 struct header_iterator *itr = owner;
115 const void *ptr;
116
117 if (mu_header_get_itemptr (itr->header, itr->index, &ptr))
118 return MU_ITR_DELITEM_NOTHING;
119 if (ptr == item && !itr->backwards)
120 return MU_ITR_DELITEM_ADVANCE;
121 return MU_ITR_DELITEM_NOTHING;
122 }
123
124 static int
hdr_data_dup(void ** ptr,void * owner)125 hdr_data_dup (void **ptr, void *owner)
126 {
127 struct header_iterator *itr = owner;
128
129 *ptr = malloc (sizeof (struct header_iterator));
130 if (*ptr == NULL)
131 return ENOMEM;
132 memcpy (*ptr, owner, sizeof (struct header_iterator));
133 mu_iterator_attach (&itr->header->itr, *ptr);
134 return 0;
135 }
136
137 static int
hdr_itrctl(void * owner,enum mu_itrctl_req req,void * arg)138 hdr_itrctl (void *owner, enum mu_itrctl_req req, void *arg)
139 {
140 struct header_iterator *itr = owner;
141
142 switch (req)
143 {
144 case mu_itrctl_tell:
145 /* Return current position in the object */
146 if (hdr_finished_p (owner))
147 return MU_ERR_NOENT;
148 else
149 *(size_t*)arg = itr->index;
150 return 0;
151 break;
152
153 case mu_itrctl_delete:
154 /* Delete current element */
155 if (hdr_finished_p (owner))
156 return MU_ERR_NOENT;
157 else
158 return mu_header_remove (itr->header, NULL, itr->index);
159 break;
160
161 case mu_itrctl_qry_direction:
162 if (!arg)
163 return EINVAL;
164 else
165 *(int*)arg = itr->backwards;
166 break;
167
168 case mu_itrctl_set_direction:
169 if (!arg)
170 return EINVAL;
171 else
172 itr->backwards = !!*(int*)arg;
173 break;
174
175 case mu_itrctl_count:
176 if (!arg)
177 return EINVAL;
178 return mu_header_get_field_count (itr->header, arg);
179
180 default:
181 return ENOSYS;
182 }
183 return 0;
184 }
185
186
187 int
mu_header_get_iterator(mu_header_t hdr,mu_iterator_t * piterator)188 mu_header_get_iterator (mu_header_t hdr, mu_iterator_t *piterator)
189 {
190 mu_iterator_t iterator;
191 int status;
192 struct header_iterator *itr;
193
194 if (!hdr)
195 return EINVAL;
196
197 itr = calloc (1, sizeof *itr);
198 if (!itr)
199 return ENOMEM;
200 itr->header = hdr;
201 itr->index = 1;
202
203 status = mu_iterator_create (&iterator, itr);
204 if (status)
205 {
206 free (itr);
207 return status;
208 }
209
210 mu_iterator_set_first (iterator, hdr_first);
211 mu_iterator_set_next (iterator, hdr_next);
212 mu_iterator_set_getitem (iterator, hdr_getitem);
213 mu_iterator_set_finished_p (iterator, hdr_finished_p);
214 mu_iterator_set_delitem (iterator, hdr_delitem);
215 mu_iterator_set_destroy (iterator, hdr_destroy);
216 mu_iterator_set_dup (iterator, hdr_data_dup);
217 mu_iterator_set_itrctl (iterator, hdr_itrctl);
218
219 mu_iterator_attach (&hdr->itr, iterator);
220
221 *piterator = iterator;
222 return 0;
223 }
224
225
226
227
228
229
230
231
232