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