part.c - rohrpost - A commandline mail client to change the world as we see it.
(HTM) git clone git://r-36.net/rohrpost
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
part.c (6151B)
---
1 /*
2 * Copy me if you can.
3 * by 20h
4 */
5
6 #include <unistd.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <time.h>
10 #include <strings.h>
11 #include <string.h>
12
13 #include "ind.h"
14 #include "arg.h"
15 #include "cfg.h"
16 #include "llist.h"
17 #include "folder.h"
18 #include "imap.h"
19 #include "pager.h"
20 #include "mime.h"
21 #include "scan.h"
22
23 void
24 part_printpart(char *id, mime_t *mime)
25 {
26 llistelem_t *part;
27 char *filename;
28
29 filename = mime_mkfilename(id, mime);
30 printf("%s %s %d Bytes %s\n", mime->partid, mime->ct,
31 mime->bodylen, filename);
32 free(filename);
33
34 if (mime->parts->len > 0) {
35 forllist(mime->parts, part)
36 part_printpart(id, (mime_t *)part->data);
37 }
38 }
39
40 void
41 part_print(char *id, mime_t *mime)
42 {
43 if (id != NULL)
44 printf("---%s---\n", id);
45 part_printpart(id, mime);
46 }
47
48 int
49 part_write(char *id, mime_t *mime, llist_t *partl, char *type,
50 char *filename, int bequiet, int tostdout, int raw)
51 {
52 llistelem_t *part;
53 char *content, *lfilename, *lcontent;
54 int clen, dowrite;
55
56 dowrite = 0;
57 if (partl == NULL && type == NULL)
58 dowrite = 1;
59 if (!dowrite && type != NULL) {
60 if (strstr(mime->ct, type))
61 dowrite = 1;
62 }
63 if (!dowrite && partl != NULL) {
64 part = llist_ciget(partl, mime->partid);
65 if (part != NULL)
66 dowrite = 1;
67 }
68
69 if (dowrite) {
70 if (filename == NULL) {
71 lfilename = mime_mkfilename(id, mime);
72 } else {
73 lfilename = filename;
74 }
75
76 clen = 0;
77 lcontent = mime->body;
78 clen = mime->bodylen;
79 content = NULL;
80 if (!raw) {
81 content = mime_decodepartencoding(mime, &clen);
82 if (content != NULL) {
83 lcontent = content;
84 } else {
85 clen = mime->bodylen;
86 }
87 }
88 //printf("mime->body = \"%s\"\ncontent = \"%s\"\n",
89 // mime->body, lcontent);
90
91 if (tostdout) {
92 if (raw)
93 writeallfd(1, mime->rawhdrs, mime->rawhdrslen);
94 writeallfd(1, lcontent, clen);
95 } else {
96 if (raw) {
97 writefile(lfilename, mime->rawhdrs,
98 mime->rawhdrslen, "w+");
99 }
100 if (writefile(lfilename, lcontent, clen,
101 (raw)? "a+" : "w+")) {
102 edie("Could not write file %s.", lfilename);
103 }
104 }
105
106 if (!bequiet && !tostdout)
107 printf("%s -> %s\n", mime->partid, lfilename);
108
109 if (content != NULL)
110 free(content);
111 if (filename == NULL)
112 free(lfilename);
113 }
114
115 if (mime->parts->len > 0) {
116 forllist(mime->parts, part) {
117 if (!part_write(id, (mime_t *)part->data, partl,
118 type, filename, bequiet, tostdout,
119 raw)) {
120 dowrite = 1;
121 }
122 }
123 }
124
125 return dowrite;
126 }
127
128 void
129 partusage(char *argv0)
130 {
131 die("usage: %s [-hqr] [-c cfg] [-m folder] [-s|-g|-f filename] "
132 "[-t type|-p part|-a|-l]"
133 " [msgs]\n", argv0);
134 }
135
136 int
137 partmain(int argc, char *argv[])
138 {
139 config_t *cfg;
140 imap_t *imap;
141 int status, filelen, retc;
142 char *user, *pass, *netspec, *selected, *filename, *type,
143 *parts, *filec, *cfgn, *argv0;
144 llist_t *ids, *msgs, *partl;
145 llistelem_t *elem, *msg, *ide;
146 mime_t *mime;
147
148 enum {
149 BEQUIET = 0x01,
150 ALLPARTS = 0x02,
151 LISTPARTS = 0x04,
152 GIVENNAME = 0x08,
153 TOSTDOUT = 0x10,
154 RAW = 0x20,
155 RECURSIVE = 0x40,
156 };
157
158 retc = 1;
159 status = 0;
160 filename = NULL;
161 parts = NULL;
162 type = NULL;
163 selected = NULL;
164 cfgn = NULL;
165
166 ARGBEGIN(argv0) {
167 case 'a':
168 status |= ALLPARTS;
169 break;
170 case 'c':
171 cfgn = EARGF(partusage(argv0));
172 break;
173 case 'f':
174 filename = EARGF(partusage(argv0));
175 break;
176 case 'g':
177 status |= GIVENNAME;
178 break;
179 case 'l':
180 status |= LISTPARTS;
181 break;
182 case 'm':
183 selected = EARGF(partusage(argv0));
184 break;
185 case 'p':
186 parts = EARGF(partusage(argv0));
187 break;
188 case 'q':
189 status |= BEQUIET;
190 break;
191 case 'r':
192 status |= RAW;
193 break;
194 case 's':
195 status |= TOSTDOUT;
196 break;
197 case 't':
198 type = EARGF(partusage(argv0));
199 break;
200 case 'h':
201 default:
202 partusage(argv0);
203 } ARGEND;
204
205 filelen = 0;
206 if (argc < 1) {
207 filec = readtoeoffd(0, &filelen);
208 if (filec == NULL)
209 edie("readtoeoffd");
210 } else {
211 filec = NULL;
212 }
213
214 partl = NULL;
215 if (parts != NULL)
216 partl = imap_str2ids(NULL, NULL, parts);
217
218 if (partl == NULL && !(status & ALLPARTS) && type == NULL &&
219 !(status & LISTPARTS)) {
220 die("Please specify -p, -a, -c or -l for what to do.\n");
221 }
222
223 if (!(status & GIVENNAME) && !(status & TOSTDOUT) && filename == NULL
224 && !(status & LISTPARTS)) {
225 die("You need to specify either -g, -s or -f when"
226 " requesting parts.\n");
227 }
228
229 /*
230 * Stdin handling.
231 */
232 if (filec != NULL) {
233 mime = mime_parsebuf(filec, filelen);
234 free(filec);
235
236 if (mime == NULL)
237 die("Given input does not seem to be valid MIME.\n");
238
239 if (status & LISTPARTS) {
240 part_print(NULL, mime);
241 retc = 0;
242 } else {
243 retc = part_write(NULL, mime, partl, type,
244 filename, status & BEQUIET,
245 status & TOSTDOUT, status & RAW);
246 }
247
248 if (partl != NULL)
249 llist_free(partl);
250 mime_free(mime);
251
252 return retc;
253 }
254
255 cfg = config_init(cfgn);
256 user = config_checkgetstr(cfg, "imapuser");
257 pass = config_checkgetstr(cfg, "imappass");
258 netspec = config_checkgetstr(cfg, "imapnet");
259 if (selected == NULL) {
260 selected = config_checkgetstr(cfg, "selected");
261 } else {
262 selected = memdup(selected, strlen(selected)+1);
263 }
264 config_free(cfg);
265
266 imap = imap_new(netspec, user, pass);
267 free(user);
268 free(pass);
269 free(netspec);
270
271 ids = imap_argv2ids(cfgn, selected, argc, argv);
272 if (ids == NULL)
273 die("No msgsids selected. Aborting.\n");
274
275 if (imap_init(imap))
276 imap_die(imap, "imap_init");
277 if (imap_select(imap, selected))
278 imap_die(imap, "imap_select");
279 free(selected);
280
281 msgs = imap_fetchraw(imap, ids);
282 if (msgs == NULL)
283 imap_die(imap, "imap_fetchraw");
284 llist_efree(ids);
285 imap_close(imap);
286 imap_free(imap);
287
288 forllist(msgs, msg) {
289 elem = llist_get((llist_t *)msg->data, "literal");
290 if (elem == NULL)
291 continue;
292
293 ide = llist_get((llist_t *)msg->data, "id");
294 if (ide == NULL)
295 continue;
296 mime = mime_parsebuf((char *)elem->data, elem->datalen);
297 if (mime == NULL)
298 continue;
299
300 if (status & LISTPARTS) {
301 part_print((char *)ide->data, mime);
302 retc = 0;
303 } else {
304 retc = part_write((char *)ide->data, mime, partl, type,
305 filename, status & BEQUIET,
306 status & TOSTDOUT, status & RAW);
307 retc = 0;
308 }
309
310 mime_free(mime);
311 }
312 if (partl != NULL)
313 llist_free(partl);
314 llist_efree(msgs);
315
316 return retc;
317 }
318