Commit 3d8deee3 3d8deee3cae8470f7815fe722b1467c1a74c4bb0 by Sergey Poznyakoff

Use msgset_parse instead of util_expand_msglist().

Added util_msgset_iterate() to iterate over a message set.
Added util_get_content_type() and util_get_hdr_value() (from decode.c).
1 parent eba0f30a
Showing 1 changed file with 99 additions and 212 deletions
...@@ -71,212 +71,6 @@ util_ll_free (node *c) ...@@ -71,212 +71,6 @@ util_ll_free (node *c)
71 } 71 }
72 72
73 /* 73 /*
74 * expands a standard message list into an array of numbers
75 * argc is the number of elements being passed in
76 * argv is the array of strings to parse
77 * list will be populated with message numbers
78 * returns the number of items in list
79 */
80
81 int
82 util_expand_msglist (const int argc, char **argv, int **list)
83 {
84 int i = 0, lc = 0;
85 int undelete = 0;
86 int *ret = NULL;
87 /* let's try a linked list */
88 node *first = xmalloc (sizeof (node));
89 node *current = first;
90 first->next = NULL;
91
92 if (util_command_get (argv[0]) == util_command_get ("undelete"))
93 undelete = 1;
94
95 for (i = 1; i < argc; i++)
96 {
97 if (!strcmp (argv[i], "+"))
98 {
99 /* first [un]deleted message */
100 int n = realcursor + 1;
101 while (n <= total)
102 {
103 if (util_isdeleted (n) && !undelete)
104 n++;
105 else
106 break;
107 }
108 current = util_ll_add (current, n);
109 }
110 else if (!strcmp (argv[i], "-"))
111 {
112 /* previous [un]deleted message */
113 int n = realcursor - 1;
114 while (n > 0)
115 {
116 if (util_isdeleted (n) && !undelete)
117 n--;
118 else
119 break;
120 }
121 current = util_ll_add (current, n);
122 }
123 else if (!strcmp (argv[i], "."))
124 {
125 /* the current cursor location */
126 current = util_ll_add (current, realcursor);
127 }
128 else if (!strcmp (argv[i], "^"))
129 {
130 /* first [un]deleted message */
131 int n = 1;
132 while (n <= total)
133 {
134 if (util_isdeleted (n) && !undelete)
135 n++;
136 else
137 break;
138 }
139 current = util_ll_add (current, 1);
140 }
141 else if (!strcmp (argv[i], "$"))
142 {
143 /* last [un]deleted message */
144 int n = total;
145 while (n > 0)
146 {
147 if (util_isdeleted (n) && !undelete)
148 n--;
149 else
150 break;
151 }
152 current = util_ll_add (current, total);
153 }
154 else if (!strcmp (argv[i], "*"))
155 {
156 /* all messages */
157 util_ll_free (first);
158 current = first = xmalloc (sizeof (node));
159 for (i = 1; i <= total; i++)
160 current = util_ll_add (current, i);
161 i = argc + 1;
162 }
163 else if (argv[i][0] == '/')
164 {
165 /* All messages with pattern following / in
166 the subject line, case insensitive */
167 int j;
168 char *pattern;
169
170 pattern = strdup (&argv[i][1]);
171 util_strupper (pattern);
172
173 for (j = 1; j <= total; j++)
174 {
175 message_t msg = NULL;
176 header_t hdr = NULL;
177 char *subject = NULL;
178 size_t subjlen;
179 int k;
180
181 mailbox_get_message (mbox, j, &msg);
182 message_get_header (msg, &hdr);
183
184 header_aget_value (hdr, MU_HEADER_SUBJECT, &subject);
185 util_strupper (subject);
186
187 if (pattern && subject && strstr (subject, pattern))
188 current = util_ll_add (current, j);
189 free (subject);
190 }
191 free (pattern);
192 }
193 else if (argv[i][0] == ':')
194 {
195 /* All messages of type argv[i][1] */
196 int j;
197 for (j = 1; j <= total; j++)
198 {
199 message_t msg = NULL;
200 attribute_t attr= NULL;
201
202 mailbox_get_message (mbox, j, &msg);
203 message_get_attribute (msg, &attr);
204 if ((argv[i][1] == 'd' && attribute_is_deleted (attr))
205 || (argv[i][1] == 'n' && attribute_is_recent (attr))
206 || (argv[i][1] == 'o' && attribute_is_seen (attr))
207 || (argv[i][1] == 'r' && attribute_is_read (attr))
208 || (argv[i][1] == 'u' && !attribute_is_read (attr)))
209 current = util_ll_add (current, j);
210 }
211 }
212 else if (isalpha(argv[i][0]))
213 {
214 /* FIXME: all messages from sender argv[i] */
215 /* Annoying we can use address_create() for that
216 but to compare against what? The email ? */
217 }
218 else if (strchr (argv[i], '-') != NULL)
219 {
220 /* Message range. */
221 int j, x, y;
222 char *arg = strdup (argv[i]);
223 for (j=0; j < strlen (arg); j++)
224 if (arg[j] == '-')
225 break;
226 arg[j] = '\0';
227 x = strtol (arg, NULL, 10);
228 y = strtol (&(arg[j + 1]), NULL, 10);
229 for (; x <= y; x++)
230 current = util_ll_add (current, x);
231 free (arg);
232 }
233 else if (strchr (argv[i], '[') != NULL)
234 {
235 /* attachments - GNU extension */
236 /*
237 * This is a general extension to the msglist format. Basicallay,
238 * it adds C-like array subscripting to msg numbers to allow access
239 * to just a single part of a MIME multipart message. I.e.:
240 * print 7[1],8[1-2]
241 * should print the first attachment of message 7 and the first
242 * and second attachments of message 8. The format inside the
243 * brackets is the same as a msglist, so we should be able to
244 * reuse this function for its expansion. This will primarily
245 * be used by the new decode command, which needs discussion on
246 * the mailing list to nail its syntax down (should it default to
247 * saving to a file, printing to stdout, or piping?)
248 * -- sparky
249 */
250 }
251 else
252 {
253 /* Single message. */
254 current = util_ll_add (current, strtol (argv[i], NULL, 10));
255 }
256 }
257
258 for (current = first; current->next != NULL; current = current->next)
259 lc++;
260
261 if (!lc)
262 {
263 ret = xcalloc (1, sizeof (int));
264 ret [0] = cursor;
265 lc = 1;
266 }
267 else
268 {
269 ret = xmalloc (lc * sizeof (int));
270 lc = 0;
271 for (current = first; current->next != NULL; current = current->next)
272 ret [lc++] = current->data;
273 }
274 util_ll_free (first);
275 *list = ret;
276 return lc;
277 }
278
279 /*
280 * expands command into its command and arguments, then runs command 74 * expands command into its command and arguments, then runs command
281 * cmd is the command to parse and run 75 * cmd is the command to parse and run
282 * returns exit status of the command 76 * returns exit status of the command
...@@ -345,15 +139,17 @@ util_do_command (const char *c, ...) ...@@ -345,15 +139,17 @@ util_do_command (const char *c, ...)
345 int 139 int
346 util_msglist_command (function_t *func, int argc, char **argv, int set_cursor) 140 util_msglist_command (function_t *func, int argc, char **argv, int set_cursor)
347 { 141 {
348 int i; 142 msgset_t *list = NULL, *mp;
349 int *list = NULL;
350 int status = 0; 143 int status = 0;
351 int number = util_expand_msglist (argc, argv, &list); 144
145 if (msgset_parse (argc, argv, &list))
146 return 1;
147
352 realcursor = cursor; 148 realcursor = cursor;
353 149
354 for (i = 0; i < number; i++) 150 for (mp = list; mp; mp = mp->next)
355 { 151 {
356 cursor = list[i]; 152 cursor = mp->msg_part[0];
357 /* NOTE: Should we bail on error also? */ 153 /* NOTE: Should we bail on error also? */
358 if (func (1, argv) != 0) 154 if (func (1, argv) != 0)
359 status = 1; 155 status = 1;
...@@ -361,7 +157,7 @@ util_msglist_command (function_t *func, int argc, char **argv, int set_cursor) ...@@ -361,7 +157,7 @@ util_msglist_command (function_t *func, int argc, char **argv, int set_cursor)
361 if (ml_got_interrupt () != 0) 157 if (ml_got_interrupt () != 0)
362 break; 158 break;
363 } 159 }
364 free (list); 160 msgset_free (list);
365 161
366 if (set_cursor) 162 if (set_cursor)
367 realcursor = cursor; 163 realcursor = cursor;
...@@ -1033,3 +829,94 @@ util_tempfile(char **namep) ...@@ -1033,3 +829,94 @@ util_tempfile(char **namep)
1033 return fd; 829 return fd;
1034 } 830 }
1035 831
832 int
833 util_descend_subparts (message_t mesg, msgset_t *msgset, message_t *part)
834 {
835 int i;
836
837 for (i = 1; i < msgset->npart; i++)
838 {
839 message_t submsg = NULL;
840 int nparts = 0;
841 char *type = NULL;
842 header_t hdr = NULL;
843
844 message_get_header (mesg, &hdr);
845 util_get_content_type (hdr, &type);
846 if (strncasecmp (type, "message/rfc822", strlen (type)) == 0)
847 {
848 if (message_unencapsulate (mesg, &submsg, NULL))
849 {
850 util_error ("can't unencapsulate message/part");
851 return 1;
852 }
853 mesg = submsg;
854 }
855
856 message_get_num_parts (mesg, &nparts);
857 if (nparts < msgset->msg_part[i])
858 {
859 util_error ("no such (sub)part in the message: %d",
860 msgset->msg_part[i]);
861 return 1;
862 }
863
864 if (message_get_part (mesg, msgset->msg_part[i], &submsg))
865 {
866 util_error ("can't get (sub)part from the message: %d",
867 msgset->msg_part[i]);
868 return 1;
869 }
870
871 mesg = submsg;
872 }
873
874 *part = mesg;
875 return 0;
876 }
877
878 void
879 util_msgset_iterate (msgset_t *msgset, int (*fun)(), void *closure)
880 {
881 for (; msgset; msgset = msgset->next)
882 {
883 message_t mesg;
884
885 if (mailbox_get_message (mbox, msgset->msg_part[0], &mesg) != 0)
886 return;
887
888 if (util_descend_subparts (mesg, msgset, &mesg) == 0)
889 (*fun)(mesg, msgset, closure);
890 }
891 }
892
893 int
894 util_get_content_type (header_t hdr, char **value)
895 {
896 char *type = NULL;
897 util_get_hdr_value (hdr, MU_HEADER_CONTENT_TYPE, &type);
898 if (type == NULL || *type == '\0')
899 {
900 if (type)
901 free (type);
902 type = strdup ("text/plain"); /* Default. */
903 }
904 *value = type;
905 return 0;
906 }
907
908 int
909 util_get_hdr_value (header_t hdr, const char *name, char **value)
910 {
911 int status = header_aget_value (hdr, name, value);
912 if (status == 0)
913 {
914 /* Remove the newlines. */
915 char *nl;
916 while ((nl = strchr (*value, '\n')) != NULL)
917 {
918 *nl = ' ';
919 }
920 }
921 return status;
922 }
......