1 /*
2 ** Copyright 2002-2009, Double Precision Inc.
3 **
4 ** See COPYING for distribution information.
5 */
6 #include "libmail_config.h"
7 
8 #include "qp.H"
9 
10 #include <string.h>
11 
12 using namespace std;
13 
xdigit(char c)14 static inline int xdigit(char c)
15 {
16 	static const char xdigits[]="0123456789ABCDEFabcdef";
17 
18 	const char *p=strchr(xdigits, c);
19 
20 	if (p == NULL)
21 		return -1;
22 
23 	int n= p - xdigits;
24 
25 	if (n >= 16)
26 		n -= 6;
27 	return n;
28 }
29 
decodeqp()30 mail::decodeqp::decodeqp()
31 	: decodeBuffer("")
32 {
33 }
34 
~decodeqp()35 mail::decodeqp::~decodeqp()
36 {
37 }
38 
decode(string text)39 void mail::decodeqp::decode(string text)
40 {
41 	string decodedString="";
42 
43 	text=decodeBuffer + text;
44 
45 	// Just decode as much as possible, and leave the rest for next time.
46 
47 	string::iterator b=text.begin(), e=text.end(), c=b;
48 
49 	while (b != e)
50 	{
51 		// Look for the next =
52 
53 		for (c=b; c != e; c++)
54 			if (*c == '=')
55 				break;
56 
57 		decodedString += string(b, c);
58 
59 		if (c == e) // Got everything.
60 		{
61 			b=c;
62 			break;
63 		}
64 
65 		b=c++;
66 
67 		if (c == e)
68 			break;
69 
70 		if (*c == '\r')
71 			c++;
72 
73 		if (c == e)
74 			break;
75 
76 		if (*c == '\n')
77 		{
78 			c++;
79 			b=c;
80 			continue;
81 		}
82 
83 		int a1=xdigit(*c++);
84 
85 		if (a1 < 0)
86 		{
87 			b=c;
88 			continue;
89 		}
90 
91 		if (c == e)
92 			break;
93 
94 		int a2=xdigit(*c++);
95 
96 		if (a2 < 0)
97 		{
98 			b=c;
99 			continue;
100 		}
101 
102 		decodedString += (char)(a1 * 16 + a2);
103 
104 		b=c;
105 	}
106 
107 	decodeBuffer=string(b, e); // Leftovers
108 
109 	decoded(decodedString);
110 }
111 
112 #if 0
113 
114 class testqp : public mail::decodeqp {
115 
116 	void decoded(string buffer)
117 	{
118 		cout << buffer;
119 	}
120 };
121 
122 int main(int argc, char **argv)
123 {
124 	testqp qp;
125 
126 	int argn;
127 
128 	for (argn=1; argn < argc; argn++)
129 	{
130 		string s=argv[argn];
131 
132 		size_t p;
133 
134 		while ((p=s.find('~')) != std::string::npos)
135 			s[p]='\n';
136 
137 		qp.decode(s);
138 	}
139 
140 	cout << endl;
141 
142 	return (0);
143 }
144 #endif
145