preserve the contents of the www-authenticate header and use them to detect authentic...
[project/uclient.git] / uclient-utils.c
1 #include <stdint.h>
2 #include <stdlib.h>
3 #include <ctype.h>
4
5 #include "uclient-utils.h"
6
7 static const char *b64 =
8 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
9
10 void base64_encode(const void *inbuf, unsigned int len, void *outbuf)
11 {
12         unsigned char *out = outbuf;
13         const uint8_t *in = inbuf;
14         unsigned int i;
15         int pad = len % 3;
16
17         for (i = 0; i < len - pad; i += 3) {
18                 uint32_t in3 = (in[0] << 16) | (in[1] << 8) | in[2];
19                 int k;
20
21                 for (k = 3; k >= 0; k--) {
22                         out[k] = b64[in3 & 0x3f];
23                         in3 >>= 6;
24                 }
25                 in += 3;
26                 out += 4;
27         }
28
29         if (pad) {
30                 uint32_t in2 = in[0] << (16 - 6);
31
32                 out[3] = '=';
33
34                 if (pad > 1) {
35                         in2 |= in[1] << (8 - 6);
36                         out[2] = b64[in2 & 0x3f];
37                 } else {
38                         out[2] = '=';
39                 }
40
41                 in2 >>= 6;
42                 out[1] = b64[in2 & 0x3f];
43                 in2 >>= 6;
44                 out[0] = b64[in2 & 0x3f];
45
46                 out += 4;
47         }
48
49         *out = '\0';
50 }
51
52 int uclient_urldecode(const char *in, char *out, bool decode_plus)
53 {
54         static char dec[3];
55         int ret = 0;
56         char c;
57
58         while ((c = *(in++))) {
59                 if (c == '%') {
60                         if (!isxdigit(in[0]) || !isxdigit(in[1]))
61                                 return -1;
62
63                         dec[0] = in[0];
64                         dec[1] = in[1];
65                         c = strtol(dec, NULL, 16);
66                         in += 2;
67                 } else if (decode_plus && c == '+') {
68                         c = ' ';
69                 }
70
71                 *(out++) = c;
72                 ret++;
73         }
74
75         *out = 0;
76         return ret;
77 }