File: data.c

package info (click to toggle)
links2 2.29-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 27,852 kB
  • sloc: ansic: 181,859; sh: 2,585; cpp: 1,450; makefile: 84; awk: 49; perl: 34
file content (120 lines) | stat: -rw-r--r-- 2,461 bytes parent folder | download | duplicates (4)
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);
}