14#define WHO "822mimeparts" 
   35  logmsg(
WHO,111,FATAL,
"out of memory");
 
   38static int issafe(
char ch)
 
   40  if ((ch >= 
'a') && (ch <= 
'z')) 
return 1;
 
   41  if ((ch >= 
'A') && (ch <= 
'Z')) 
return 1;
 
   42  if ((ch >= 
'0') && (ch <= 
'9')) 
return 1;
 
   46static void die_write(
char *fn) { unlink(fn); _exit(1); };
 
   52char name[11] = { 
'0', 
'0', 
'0', 
'u', 
'n', 
'k', 
'n', 
'o', 
'w', 
'n', 
'\0' };
 
   53char pname[7] = { 
'0', 
'0', 
'0', 
'0', 
'0', 
'0', 
'\0' };
 
   55static int msgname(
char *
out,
const char *in)
 
   60  int at = str_chr(in,
'@');
 
   61  if (in[at] == 
'@' && at > 9) {
 
   65      if (issafe(
c)) 
out[j--] = 
c;
 
   73static int mime_partname(
char *
out,
char *in,
int len)
 
   80    if (issafe(
c)) 
out[j--] = 
c;
 
   93     case 1: 
case -1: 
return "7bit"; 
 
   94     case 2: 
case -2: 
return "8bit"; 
 
   95     case 3: 
case -3: 
return "base64"; 
 
   96     case 4: 
case -4: 
return "binary"; 
 
   97     case 5: 
case -5: 
return "quoted-printable"; 
 
   98     default: 
return "unkown";
 
 
  103static int printpart(
char *
name,stralloc *in,
int mimetype,stralloc *
alias)
 
  108  char size[FMT_ULONG];
 
  112  fd = open_trunc(
name);
 
  113  if (fd == -1) die_write(
name);
 
  117  size[fmt_ulong(size,(
unsigned long) len)] = 0;
 
  123    buffer_put(&
bo,in->s,
out);
 
  126  } 
while (in->len > 0); 
 
  128  if (buffer_flush(&
bo)) die_write(
name);
 
  129  if (close(fd) == -1) die_write(
name);
 
  132    logmsg(
WHO,0,INFO,B(
"Created: ",
name,
" (",
type,
", ",size,
" byte) [",
alias->s,
"]."));
 
  137    logmsg(
WHO,0,INFO,B(
"Created: ",
name,
" (",
type,
", ",size,
" byte)."));
 
  144  { 
"Message-ID", &
flag, 0, &
valuem, 0, 0, 0 } , { 0, 0, 0, 0, 0, 0, 0 }
 
 
  148  { 
"Content-Type", &
flag, 0, &
valuet, 0, 0, 0 } , { 0, 0, 0, 0, 0, 0, 0 }
 
 
  152  { 
"Content-Transfer-Encoding", &
flag, 0, &
valuec, 0, 0, 0 } , { 0, 0, 0, 0, 0, 0, 0 }
 
 
  158  char sizes[FMT_ULONG];
 
  159  char sizee[FMT_ULONG];
 
  165  stralloc decoded = {0};
 
  168  if (mimetype == -1) {
 
  170    if (r < 0) logmsg(
WHO,111,WARN,
"malformed base64 mime part");
 
  171  } 
else if (mimetype == -2) {
 
  173    if (r < 0) logmsg(
WHO,111,WARN,
"malformed quoted-printable part");
 
  178      sizes[fmt_ulong(sizes,(
unsigned long) 
start + 3)] = 0;
 
  179      sizee[fmt_ulong(sizee,(
unsigned long) end + 2)] = 0;
 
  180      if (
verbose) logmsg(
WHO,0,INFO,B(
"Start of part: @line=",sizes,
" End of part: @line=",sizee));
 
 
  188  char sizes[FMT_ULONG];
 
  189  char sizee[FMT_ULONG];
 
  195  sizes[fmt_ulong(sizes,(
unsigned long) num)] = 0;
 
  198  mime_partname(
pname,bound->s,bound->len);
 
  206  stralloc decoded = {0};
 
  211    if (r < 0) logmsg(
WHO,111,INFO,
"malformed base64 mime part");
 
  212  } 
else if (mimetype == 5) {
 
  214    if (r < 0) logmsg(
WHO,111,INFO,
"malformed quoted-printable part");
 
  219      sizes[fmt_ulong(sizes,(
unsigned long) 
start + 3)] = 0;
 
  220      sizee[fmt_ulong(sizee,(
unsigned long) end + 2)] = 0;
 
  221      if (
verbose) logmsg(
WHO,0,INFO,B(
"Start of part: @line=",sizes,
" End of part: @line=",sizee));
 
 
  242   if (*(
name->s) != 
'=' && *(
name->s + 1) != 
'?') 
return 0;
 
  247   if (!stralloc_copys(&in,
"")) 
nomem();
 
  248   if (!stralloc_copys(&
out,
"")) 
nomem();
 
  250   for (
int i = 0; i < 
name->len; i++) {
 
  253     if (ch == 
'\0') 
break;
 
  254     if (ch == 
'?') seenq++;
 
  256       if (!stralloc_copys(&in,
"")) 
nomem();
 
  258       if (ch == 
'q' || ch == 
'Q') {             
 
  260       } 
else if (ch == 
'b' || ch == 
'B') {      
 
  269       if (seenq == 3 && ch != 
'?') 
if (!stralloc_append(&in,&ch)) 
nomem();
 
  270       if (seenq == 4) { done = 1; 
if (!stralloc_0(&in)) 
nomem(); } 
 
  272       if (!stralloc_append(&in,&ch)) 
nomem();
 
  274     if (i == 
name->len - 1) done = 1;        
 
  280       case 3: 
if (!stralloc_copys(&word,
"")) 
nomem(); 
 
  282                 if (!stralloc_catb(&
out,word.s,done)) 
nomem();
 
  284                 logmsg(
WHO,0,WARN,B(
"error in decoding 'Name:' ",word.s));
 
  285                 if (!stralloc_catb(&
out,in.s,in.len)) 
nomem();
 
  286               } done = 0; seenq = 0; 
break;
 
  287       case 5: 
if (!stralloc_copys(&word,
"")) 
nomem();
 
  289                 if (!stralloc_catb(&
out,word.s,done)) 
nomem(); 
 
  291                 if (!stralloc_catb(&
out,in.s,in.len)) 
nomem();
 
  292                 logmsg(
WHO,0,WARN,B(
"error in decoding 'Name:' ",word.s));
 
  293                 if (!stralloc_catb(&
out,in.s,in.len)) 
nomem();
 
  294               } done = 0; seenq = 0; 
break;
 
 
  310   if (*(
name->s) != 
'=' && *(
name->s + 1) != 
'?') 
return 0;
 
  315   if (!stralloc_copys(&in,
"")) 
nomem();
 
  317   for (
int i = 2; i < 
name->len; i++) {
 
  319     if (ch == 
'?') { seen++; 
continue; }
 
  320     if (seen == 2) 
if (!stralloc_append(&in,&ch)) 
nomem();
 
  322   if (!stralloc_0(&in)) 
nomem();
 
  326     logmsg(
WHO,0,WARN,B(
"error in BASE64 decoding: ",in.s));
 
 
  342    if (ch == 
'C' || ch == 
'\n') seen = 3;                 
 
  344  if (seen == 0 && in->len > 10) {                         
 
  345    for (
int i = 0; i < in->len - 5; i++) {
 
  346      if (!case_diffb(in->s + i,5,
"name=")) {              
 
  351        for (
int j = i; j < in->len - 2; j++) {
 
  353          if (ch == 
'"') { seena++; 
continue; }            
 
  354          if (ch == 
';') { seen = 3; 
goto DONE; }          
 
  358        if (seena == 2) { seen = 3; 
goto DONE; }
 
  364  if (seen && seen < 3) {
 
  365    if (ch  == 
' ' || ch  == 
'\t') {
 
  366      for (
int j = 1 ; j < in->len - 2; j++) {
 
  368        if (ch == 
'"') { seena++; 
continue; }              
 
  369        if (ch == 
';') { seen = 3; 
goto DONE; }            
 
  373      if (seen == 3 || seena == 2) 
goto DONE;
 
  376    if (ch == 
'\n') { seen == 3; 
goto DONE; }              
 
 
  396  int part[4] = {0, 0, 0, 0}; 
 
  404  while ((opt = getoptb(argc,argv,
"hlv")) != opteof)
 
  406       case 'h': logmsg(
WHO,99,USAGE,
"822mimeparts [-v|-l] < message."); 
break;
 
  407       case 'l': 
slink = 1; 
break;
 
  409       default : logmsg(
WHO,99,USAGE,
"822mimeparts [-v|-l] < message."); 
break;
 
  418  for (len = 0;;len++) {
 
  419    if (getln(buffer_0,&
line,&
match,
'\n') == -1)
 
  420      logmsg(
WHO,111,FATAL,
"unable to read input: ");
 
  428    logmsg(
WHO,111,ERROR,
"malformed message (first non-header line not blank)");
 
  440  if (!case_diffb(
valuec.s,16,
"quoted-printable")) { mimetype = -2; part[3] = -1; } 
 
  441  else if (!case_diffb(
valuec.s,6,
"base64")) { mimetype = -1; part[3] = -1; }
 
  442  if (mimetype < 0) { 
if (!stralloc_cats(&
bodybuf,
"")) 
return -1; }
 
  448  for (
int i = 0; i < 
valuet.len - 12; i++) {
 
  449    if (*(
valuet.s + i) == 
'\0') 
break;
 
  450    if (!case_diffb(
valuet.s + i,9,
"boundary=")) {    
 
  454      for (
int j = i; j < 
valuet.len - 2; j++) {
 
  456        if (ch == 
';' || ch == 
'"') 
continue;  
 
  466  for (
int l = len;;l++) {
 
  467    if (getln(buffer_0,&
line,&
match,
'\n') == -1)
 
  468      logmsg(
WHO,111,FATAL,
"unable to read input: ");
 
  478      if (!part[1]) part[1] = l; part[2] = l;
 
  483    if (case_startb(
line.s,26,
"Content-Transfer-Encoding:")) {
 
  484      part[0] += 1; part[1] = l; part[3] = 1; 
 
  486       if (case_startb(
line.s + 27,4,
"7bit")) mimetype = 1; 
 
  487       else if (case_startb(
line.s + 27,4,
"8bit")) mimetype = 2; 
 
  488       else if (case_startb(
line.s + 27,6,
"base64")) mimetype = 3; 
 
  489       else if (case_startb(
line.s + 27,6,
"binary")) mimetype = 4; 
 
  490       else if (case_startb(
line.s + 27,16,
"quoted-printable")) mimetype = 5;
 
  497    if (case_startb(
line.s,13,
"Content-Type:")) { 
 
  499      if (*(
line.s + 
line.len - 3) == 
';') skip = 1;       
 
  500      if (case_startb(
line.s + 14,27,
"application/pgp-signature")) mimetype = 10;
 
  502    if (case_startb(
line.s,2,
"X-")) 
continue;              
 
  506    for (
int i = 0; i < 
line.len - 12; i++) {
 
  508      if (*(
line.s + i) == 
'\n') 
break;
 
  509      if (!case_diffb(
line.s + i,9,
"boundary=")) {    
 
  513        for (
int j = i; j < 
line.len - 2; j++) {
 
  515          if (ch == 
';') 
break;                
 
  516          if (ch == 
'"') 
continue;             
 
  533      if (case_startb(
line.s,12,
"MIME-Version")) { part[3] = 3; 
continue; }
 
  534      if (case_startb(
line.s,25,
"Content-Type: application") ||
 
  535          case_startb(
line.s,23,
"Content-Type: text/html") ||
 
  536          case_startb(
line.s,19,
"Content-Type: image") ||
 
  537          case_startb(
line.s,19,
"Content-Type: audio") ||
 
  538          case_startb(
line.s,19,
"Content-Type: video") ||
 
  539          case_startb(
line.s,19,
"Content-Type: octet") ||
 
  540          case_startb(
line.s,19,
"Content-Disposition")) { part[3] = 4; }
 
  547      if (seen == 1) 
continue;
 
  554      if (*
line.s == 
'\n') 
continue;
 
  555      if (case_startb(
line.s,10,
"Content-")) 
continue;
 
  556      if (skip == 1) { skip = 0; 
continue; }     
 
  564          case 3: 
if (*
line.s == 
' ' || *
line.s == 
'-' || *
line.s == 
'\t') 
break;
 
  566                  part[2] = l; part[3] = 5;
 
  569                  part[2] = l; part[3] = 5;
 
  576        if (mimetype != 5 && !str_diffn(
line.s,
"--",2)) {
 
 
int mess822_qpdecode(stralloc *, const char *, int, int)
int mess822_line(mess822_header *, stralloc *)
int mess822_end(mess822_header *)
int mess822_ok(stralloc *)
int mess822_begin(mess822_header *, mess822_action *)
int mess822_b64decode(stralloc *, const char *, int, int)
void c(char *, char *, char *, int, int, int)
void mime_partproc(stralloc *bound, int mimetype, int start, int end)
char * mime_type(int type)
int attachment_name(stralloc *name, stralloc *in)
int b64name(stralloc *name)
int decode_name(stralloc *name)
void msg_bodyproc(int mimetype, int start, int end)