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

quote.c (2212B)


      1 /*
      2  * Copy me if you can.
      3  * by 20h
      4  */
      5 
      6 #include <unistd.h>
      7 #include <stdlib.h>
      8 #include <stdio.h>
      9 #include <string.h>
     10 
     11 #include "ind.h"
     12 
     13 char *
     14 qpenc(char *str, int len, int ishdr)
     15 {
     16 	char *ret, add[6];
     17 	int i, rlen, alen, llen;
     18 
     19 	ret = NULL;
     20 	for (i = 0, llen = 0, rlen = 0; i < len; i++) {
     21 		if (str[i] < 0x20 || str[i] > 0x7E)
     22 			snprintf(add, sizeof(add), "=%02x", str[i] & 0xFF);
     23 		else {
     24 			switch(str[i]) {
     25 			case ' ':
     26 				if (ishdr) {
     27 					add[0] = '_';
     28 					add[1] = '\0';
     29 					break;
     30 				}
     31 			case '?':
     32 			case '_':
     33 			case '=':
     34 			case '(':
     35 			case ')':
     36 			case '<':
     37 			case '>':
     38 			case '@':
     39 			case ',':
     40 			case ';':
     41 			case '\\':
     42 			case '"':
     43 			case '/':
     44 			case '[':
     45 			case ']':
     46 				snprintf(add, sizeof(add), "=%02x",
     47 						str[i] & 0xFF);
     48 				break;
     49 			case '\n':
     50 				if (i > 0 && strchr("\t\r\v\f", str[i-1])) {
     51 					add[0] = '=';
     52 					add[1] = str[i];
     53 					add[2] = '\0';
     54 					break;
     55 				}
     56 			default:
     57 				add[0] = str[i];
     58 				add[1] = '\0';
     59 				break;
     60 			}
     61 		}
     62 		alen = strlen(add);
     63 		if (llen + alen > 76) {
     64 			ret = memdupcat(ret, rlen, "=\n", 3);
     65 			rlen += 2;
     66 			llen = alen;
     67 		}
     68 		ret = memdupcat(ret, rlen, add, alen+1);
     69 		rlen += alen;
     70 		llen += alen;
     71 	}
     72 
     73 	return ret;
     74 }
     75 
     76 char *
     77 qpdec(char *str, int *len, int ishdr)
     78 {
     79 	char *ret, add, abuf[3], *eabuf;
     80 	int i, rlen, pbreak;
     81 	long nval;
     82 
     83 	ret = NULL;
     84 	for (i = 0, rlen = 0; i < *len; i++) {
     85 		add = '\0';
     86 		switch (str[i]) {
     87 		case '_':
     88 			add = (ishdr)? ' ' : '_';
     89 			break;
     90 		case '=':
     91 			pbreak = 0;
     92 			if (str[i+1] == '\r') {
     93 				i++;
     94 				pbreak = 1;
     95 			}
     96 			if (str[i+1] == '\n') {
     97 				i++;
     98 				pbreak = 1;
     99 			}
    100 			if (str[i+1] == '\0') {
    101 				i++;
    102 				pbreak = 1;
    103 			}
    104 			if (pbreak)
    105 				break;
    106 
    107 			memmove(&abuf, &str[i+1], 2);
    108 			abuf[2] = '\0';
    109 
    110 			eabuf = NULL;
    111 			nval = strtol((char *)&abuf, &eabuf, 16);
    112 			if (eabuf != NULL && *eabuf != '\0')
    113 				break;
    114 
    115 			add = (char)(nval & 0xFF);
    116 			i += 2;
    117 			break;
    118 		default:
    119 			/*
    120 			 * Convert CRLF to LF.
    121 			 */
    122 			if (str[i] == '\r' && i < (*len)-1 && str[i+1] == '\n')
    123 				add = '\0';
    124 			else
    125 				add = str[i];
    126 			break;
    127 		}
    128 		if (add == '\0')
    129 			continue;
    130 
    131 		ret = reallocz(ret, (++rlen)+1, 0);
    132 		ret[rlen-1] = add;
    133 		ret[rlen] = '\0';
    134 	}
    135 
    136 	*len = rlen;
    137 	return ret;
    138 }
    139