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).
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 | } | ... | ... |
-
Please register or sign in to post a comment