plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

unvf.c (2429B)


      1 /*
      2  * For decoding the files that get passed to validateattachment.
      3  * NOT a general mime decoder.
      4  */
      5 #include <u.h>
      6 #include <libc.h>
      7 #include <bio.h>
      8 
      9 enum { None, Base64, Quoted };
     10 static int decquoted(char *out, char *in, char *e);
     11 
     12 void
     13 main(void)
     14 {
     15 	Biobuf b, b1;
     16 	char *p, *encoding;
     17 	int e, len;
     18 
     19 	Binit(&b, 0, OREAD);
     20 	Binit(&b1, 1, OWRITE);
     21 
     22 	/* header */
     23 	encoding = nil;
     24 	while((p = Brdstr(&b, '\n', 1)) != nil){
     25 		if(p[0] == 0)
     26 			break;
     27 		if(cistrncmp(p, "Content-Transfer-Encoding: ", 27) == 0)
     28 			encoding = strdup(p+27);
     29 		free(p);
     30 	}
     31 
     32 	e = None;
     33 	if(encoding == nil)
     34 		e = None;
     35 	else if(strcmp(encoding, "base64") == 0)
     36 		e = Base64;
     37 	else if(strcmp(encoding, "quoted-printable") == 0)
     38 		e = Quoted;
     39 
     40 	while((p = Brdstr(&b, '\n', 0)) != nil){
     41 		if(strncmp(p, "--", 2) == 0 && e != None)
     42 			break;
     43 		len = strlen(p);
     44 		switch(e){
     45 		case None:
     46 			break;
     47 		case Base64:
     48 			len = dec64((uchar*)p, len, p, len);
     49 			break;
     50 		case Quoted:
     51 			len = decquoted(p, p, p+len);
     52 			break;
     53 		}
     54 		Bwrite(&b1, p, len);
     55 		free(p);
     56 	}
     57 	exits(0);
     58 }
     59 
     60 /*
     61  *  decode quoted
     62  */
     63 enum
     64 {
     65 	Self=	1,
     66 	Hex=	2
     67 };
     68 uchar	tableqp[256];
     69 
     70 static void
     71 initquoted(void)
     72 {
     73 	int c;
     74 
     75 	memset(tableqp, 0, 256);
     76 	for(c = ' '; c <= '<'; c++)
     77 		tableqp[c] = Self;
     78 	for(c = '>'; c <= '~'; c++)
     79 		tableqp[c] = Self;
     80 	tableqp['\t'] = Self;
     81 	tableqp['='] = Hex;
     82 }
     83 
     84 static int
     85 hex2int(int x)
     86 {
     87 	if(x >= '0' && x <= '9')
     88 		return x - '0';
     89 	if(x >= 'A' && x <= 'F')
     90 		return (x - 'A') + 10;
     91 	if(x >= 'a' && x <= 'f')
     92 		return (x - 'a') + 10;
     93 	return 0;
     94 }
     95 
     96 static char*
     97 decquotedline(char *out, char *in, char *e)
     98 {
     99 	int c, soft;
    100 
    101 	/* dump trailing white space */
    102 	while(e >= in && (*e == ' ' || *e == '\t' || *e == '\r' || *e == '\n'))
    103 		e--;
    104 
    105 	/* trailing '=' means no newline */
    106 	if(*e == '='){
    107 		soft = 1;
    108 		e--;
    109 	} else
    110 		soft = 0;
    111 
    112 	while(in <= e){
    113 		c = (*in++) & 0xff;
    114 		switch(tableqp[c]){
    115 		case Self:
    116 			*out++ = c;
    117 			break;
    118 		case Hex:
    119 			c = hex2int(*in++)<<4;
    120 			c |= hex2int(*in++);
    121 			*out++ = c;
    122 			break;
    123 		}
    124 	}
    125 	if(!soft)
    126 		*out++ = '\n';
    127 	*out = 0;
    128 
    129 	return out;
    130 }
    131 
    132 static int
    133 decquoted(char *out, char *in, char *e)
    134 {
    135 	char *p, *nl;
    136 
    137 	if(tableqp[' '] == 0)
    138 		initquoted();
    139 
    140 	p = out;
    141 	while((nl = strchr(in, '\n')) != nil && nl < e){
    142 		p = decquotedline(p, in, nl);
    143 		in = nl + 1;
    144 	}
    145 	if(in < e)
    146 		p = decquotedline(p, in, e-1);
    147 
    148 	/* make sure we end with a new line */
    149 	if(*(p-1) != '\n'){
    150 		*p++ = '\n';
    151 		*p = 0;
    152 	}
    153 
    154 	return p - out;
    155 }