links

lynx-like text mode web browser
git clone anongit@rnpnr.xyz:links.git
Log | Files | Refs | Feed | README | LICENSE

data.c (2425B)


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