rohrpost

A commandline mail client to change the world as we see it.
git clone git://r-36.net/rohrpost
Log | Files | Refs | README | 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