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 }