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