-
Notifications
You must be signed in to change notification settings - Fork 0
/
data.c
120 lines (106 loc) · 2.4 KB
/
data.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "links.h"
static void base64_decode(unsigned char **d, int *dl, unsigned char *s, int sl)
{
int bits = 0;
unsigned tmp = 0;
for (; sl > 0; s++, sl--) {
unsigned char val;
unsigned char c = *s;
if (c >= 'A' && c <= 'Z') val = c - 'A';
else if (c >= 'a' && c <= 'z') val = c - 'a' + 26;
else if (c >= '0' && c <= '9') val = c - '0' + 52;
else if (c == '+') val = 62;
else if (c == '/') val = 63;
else continue;
tmp <<= 6;
tmp |= val;
bits += 6;
if (bits >= 8) {
bits -= 8;
add_chr_to_str(d, dl, tmp >> bits);
tmp &= (1 << bits) - 1;
}
}
}
void data_func(struct connection *c)
{
unsigned char *data, *flags, *mime, *str;
size_t length;
int strl;
struct cache_entry *e;
int r;
int base64 = 0;
int was_charset = 0;
flags = cast_uchar strchr(cast_const_char c->url, ':');
if (!flags) {
bad_url:
setcstate(c, S_BAD_URL);
abort_connection(c);
return;
}
flags++;
while (*flags == '/') flags++;
length = strcspn(cast_const_char flags, ";,");
mime = memacpy(flags, length);
while (*(flags += length) == ';') {
unsigned char *arg;
flags++;
length = strcspn(cast_const_char flags, ";,");
arg = memacpy(flags, length);
if (!casestrcmp(arg, cast_uchar "base64")) {
base64 = 1;
} else if (!casecmp(arg, cast_uchar "charset=", 8)) {
if (!was_charset) {
add_to_strn(&mime, cast_uchar ";");
add_to_strn(&mime, arg);
was_charset = 1;
}
}
mem_free(arg);
}
if (*flags != ',') {
mem_free(mime);
goto bad_url;
}
data = flags + 1;
if (!c->cache) {
if (get_connection_cache_entry(c)) {
mem_free(mime);
setcstate(c, S_OUT_OF_MEM);
abort_connection(c);
return;
}
c->cache->refcount--;
}
e = c->cache;
if (e->head) mem_free(e->head);
e->head = stracpy(cast_uchar "");
if (*mime) {
add_to_strn(&e->head, cast_uchar "\r\nContent-type: ");
add_to_strn(&e->head, mime);
add_to_strn(&e->head, cast_uchar "\r\n");
}
mem_free(mime);
str = init_str();
strl = 0;
add_conv_str(&str, &strl, data, (int)strlen(cast_const_char data), -2);
if (!base64) {
r = add_fragment(e, 0, str, strl);
} else {
unsigned char *b64 = init_str();
int b64l = 0;
base64_decode(&b64, &b64l, str, strl);
r = add_fragment(e, 0, b64, b64l);
mem_free(b64);
}
mem_free(str);
if (r < 0) {
setcstate(c, r);
abort_connection(c);
return;
}
truncate_entry(e, strl, 1);
c->cache->incomplete = 0;
setcstate(c, S__OK);
abort_connection(c);
}