120 lines
2.4 KiB
C
120 lines
2.4 KiB
C
#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);
|
|
}
|