dillo-patch.diffView |
---|
| 1 … | +diff --git a/src/cache.c b/src/cache.c |
| 2 … | +index bdda48fd..6d2fa56b 100644 |
| 3 … | +--- a/src/cache.c |
| 4 … | |
| 5 … | +@@ -15,9 +15,12 @@ |
| 6 … | + |
| 7 … | + #include <sys/types.h> |
| 8 … | + |
| 9 … | ++#include <errno.h> |
| 10 … | + #include <limits.h> |
| 11 … | + #include <stdlib.h> |
| 12 … | + #include <string.h> |
| 13 … | ++#include <time.h> |
| 14 … | ++#include <unistd.h> |
| 15 … | + |
| 16 … | + #include "msg.h" |
| 17 … | + #include "IO/Url.h" |
| 18 … | +@@ -35,6 +38,8 @@ |
| 19 … | + #include "timeout.hh" |
| 20 … | + #include "uicmd.hh" |
| 21 … | + |
| 22 … | ++#include <mbedtls/sha256.h> |
| 23 … | ++ |
| 24 … | + /* Maximum initial size for the automatically-growing data buffer */ |
| 25 … | + #define MAX_INIT_BUF 1024*1024 |
| 26 … | + /* Maximum filesize for a URL, before offering a download */ |
| 27 … | +@@ -62,6 +67,7 @@ typedef struct { |
| 28 … | + int ExpectedSize; /* Goal size of the HTTP transfer (0 if unknown)*/ |
| 29 … | + int TransferSize; /* Actual length of the HTTP transfer */ |
| 30 … | + uint_t Flags; /* See Flag Defines in cache.h */ |
| 31 … | ++ mbedtls_sha256_context Hash; /* sha256 hash state */ |
| 32 … | + } CacheEntry_t; |
| 33 … | + |
| 34 … | + |
| 35 … | +@@ -207,6 +213,7 @@ static void Cache_entry_init(CacheEntry_t *NewEntry, const DilloUrl *Url) |
| 36 … | + NewEntry->ExpectedSize = 0; |
| 37 … | + NewEntry->TransferSize = 0; |
| 38 … | + NewEntry->Flags = CA_IsEmpty | CA_InProgress | CA_KeepAlive; |
| 39 … | ++ mbedtls_sha256_init(&NewEntry->Hash); |
| 40 … | + } |
| 41 … | + |
| 42 … | + /* |
| 43 … | +@@ -247,6 +254,7 @@ static CacheEntry_t *Cache_entry_search_with_redirect(const DilloUrl *Url) |
| 44 … | + */ |
| 45 … | + static CacheEntry_t *Cache_entry_add(const DilloUrl *Url) |
| 46 … | + { |
| 47 … | ++ int rc; |
| 48 … | + CacheEntry_t *old_entry, *new_entry; |
| 49 … | + |
| 50 … | + if ((old_entry = Cache_entry_search(Url))) { |
| 51 … | +@@ -256,6 +264,10 @@ static CacheEntry_t *Cache_entry_add(const DilloUrl *Url) |
| 52 … | + |
| 53 … | + new_entry = dNew(CacheEntry_t, 1); |
| 54 … | + Cache_entry_init(new_entry, Url); /* Set safe values */ |
| 55 … | ++ rc = mbedtls_sha256_starts_ret(&new_entry->Hash, 0); |
| 56 … | ++ if (rc < 0) { |
| 57 … | ++ MSG_WARN("Failed to start SHA-256 calculation.\n"); |
| 58 … | ++ } |
| 59 … | + dList_insert_sorted(CachedURLs, new_entry, Cache_entry_cmp); |
| 60 … | + return new_entry; |
| 61 … | + } |
| 62 … | +@@ -312,6 +324,7 @@ static void Cache_entry_free(CacheEntry_t *entry) |
| 63 … | + a_Decode_transfer_free(entry->TransferDecoder); |
| 64 … | + if (entry->ContentDecoder) |
| 65 … | + a_Decode_free(entry->ContentDecoder); |
| 66 … | ++ mbedtls_sha256_init(&entry->Hash); |
| 67 … | + dFree(entry); |
| 68 … | + } |
| 69 … | + |
| 70 … | +@@ -845,6 +858,143 @@ static int Cache_get_header(CacheEntry_t *entry, |
| 71 … | + return 0; |
| 72 … | + } |
| 73 … | + |
| 74 … | ++static char *dGetblobsdir () |
| 75 … | ++{ |
| 76 … | ++ static char *blobsdir = NULL; |
| 77 … | ++ |
| 78 … | ++ if (!blobsdir) { |
| 79 … | ++ blobsdir = dStrconcat(dGethomedir(), "/.ssb/blobs", NULL); |
| 80 … | ++ } |
| 81 … | ++ return blobsdir; |
| 82 … | ++} |
| 83 … | ++ |
| 84 … | ++static int hash_to_path(char *buf, size_t *lenp, unsigned char id[32]) |
| 85 … | ++{ |
| 86 … | ++ int len = snprintf(buf, *lenp, "%s/sha256/%02x/" |
| 87 … | ++ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", |
| 88 … | ++ dGetblobsdir(), |
| 89 … | ++ id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], |
| 90 … | ++ id[8], id[9], id[10], id[11], id[12], id[13], id[14], id[15], |
| 91 … | ++ id[16], id[17], id[18], id[19], id[20], id[21], id[22], id[23], |
| 92 … | ++ id[24], id[25], id[26], id[27], id[28], id[29], id[30], id[31]); |
| 93 … | ++ if (len < 0 || len >= (int)*lenp) { errno = EMSGSIZE; return -1; } |
| 94 … | ++ *lenp = len; |
| 95 … | ++ return 0; |
| 96 … | ++} |
| 97 … | ++ |
| 98 … | ++static void Cache_finish_write(CacheEntry_t *entry) |
| 99 … | ++{ |
| 100 … | ++ int rc; |
| 101 … | ++ FILE *entry_fp, *history_fp; |
| 102 … | ++ unsigned char hash_result[32]; |
| 103 … | ++ char *hash_b64; |
| 104 … | ++ char filename_tmp[512], filename[512], history_filename[512]; |
| 105 … | ++ char history_line[512]; |
| 106 … | ++ char time_str[64]; |
| 107 … | ++ const char *url = URL_STR_(entry->Url); |
| 108 … | ++ int url_len = strlen(url); |
| 109 … | ++ size_t filename_len = sizeof(filename); |
| 110 … | ++ size_t history_line_len; |
| 111 … | ++ time_t tmp_time; |
| 112 … | ++ static unsigned int tmp_i = 0; |
| 113 … | ++ |
| 114 … | ++ rc = mbedtls_sha256_finish_ret(&entry->Hash, hash_result); |
| 115 … | ++ if (rc < 0) { |
| 116 … | ++ MSG_WARN("Failed to finish SHA-256 calculation.\n"); |
| 117 … | ++ return; |
| 118 … | ++ } |
| 119 … | ++ |
| 120 … | ++ hash_b64 = a_Misc_encode_base64_2((char *)hash_result, 32); |
| 121 … | ++ |
| 122 … | ++ tmp_time = time(NULL); |
| 123 … | ++ rc = snprintf(filename_tmp, sizeof(filename_tmp), "%s/tmp/%d-%d", |
| 124 … | ++ dGetblobsdir(), (int)tmp_time, tmp_i++); |
| 125 … | ++ if (rc < 0 || rc > (int)sizeof(filename_tmp)) { |
| 126 … | ++ MSG_WARN("Failed to calculate filename.\n"); |
| 127 … | ++ return; |
| 128 … | ++ } |
| 129 … | ++ |
| 130 … | ++ rc = hash_to_path(filename, &filename_len, hash_result); |
| 131 … | ++ if (rc < 0) { |
| 132 … | ++ MSG_WARN("Failed to calculate path. %s\n", dStrerror(errno)); |
| 133 … | ++ unlink(filename); |
| 134 … | ++ return; |
| 135 … | ++ } |
| 136 … | ++ |
| 137 … | ++ if (access(filename, F_OK) != 0) { |
| 138 … | ++ entry_fp = fopen(filename_tmp, "w"); |
| 139 … | ++ if (entry_fp == NULL) { |
| 140 … | ++ MSG_WARN("Unable to open file for writing. " |
| 141 … | ++ "Error: %s. Filename: %s URL: %s\n", |
| 142 … | ++ dStrerror(errno), filename_tmp, url); |
| 143 … | ++ return; |
| 144 … | ++ } |
| 145 … | ++ |
| 146 … | ++ if (fwrite(entry->Data->str, (size_t)entry->Data->len, 1, entry_fp) != 1) { |
| 147 … | ++ MSG_WARN("Failed to write blob file. %s\n", dStrerror(errno)); |
| 148 … | ++ fclose(entry_fp); |
| 149 … | ++ unlink(filename_tmp); |
| 150 … | ++ return; |
| 151 … | ++ } |
| 152 … | ++ |
| 153 … | ++ if (fclose(entry_fp) != 0) { |
| 154 … | ++ MSG_WARN("Failed to close blob file. %s\n", dStrerror(errno)); |
| 155 … | ++ unlink(filename_tmp); |
| 156 … | ++ return; |
| 157 … | ++ } |
| 158 … | ++ |
| 159 … | ++ rc = rename(filename_tmp, filename); |
| 160 … | ++ if (rc < 0) { |
| 161 … | ++ MSG_WARN("Failed to rename blob file. %s\n", dStrerror(errno)); |
| 162 … | ++ unlink(filename_tmp); |
| 163 … | ++ return; |
| 164 … | ++ } |
| 165 … | ++ _MSG("Saved blob %s\n", filename); |
| 166 … | ++ } |
| 167 … | ++ |
| 168 … | ++ /* write it to history file */ |
| 169 … | ++ |
| 170 … | ++ rc = snprintf(history_filename, sizeof(history_filename), |
| 171 … | ++ "%s/.dillo/history.txt", |
| 172 … | ++ dGethomedir()); |
| 173 … | ++ if (rc < 0 || rc > (int)sizeof(history_filename)) { |
| 174 … | ++ MSG_WARN("Failed to calculate history filename.\n"); |
| 175 … | ++ return; |
| 176 … | ++ } |
| 177 … | ++ |
| 178 … | ++ if (strftime(time_str, sizeof(time_str), "%F %T %z", gmtime(&tmp_time)) == 0) { |
| 179 … | ++ MSG_WARN("Failed to format timestamp.\n"); |
| 180 … | ++ return; |
| 181 … | ++ } |
| 182 … | ++ |
| 183 … | ++ history_fp = fopen(history_filename, "a"); |
| 184 … | ++ if (history_fp == NULL) { |
| 185 … | ++ MSG_WARN("Failed to open history file.\n"); |
| 186 … | ++ return; |
| 187 … | ++ } |
| 188 … | ++ |
| 189 … | ++ if (!strncmp(url, "data:", 5)) url_len = 0; |
| 190 … | ++ |
| 191 … | ++ history_line_len = snprintf(history_line, sizeof(history_line), |
| 192 … | ++ "%s\t&%s.sha256\t%.*s\n", |
| 193 … | ++ time_str, |
| 194 … | ++ hash_b64, |
| 195 … | ++ url_len, |
| 196 … | ++ url); |
| 197 … | ++ if (history_line_len <= 0 || history_line_len > (int)sizeof(history_line)) { |
| 198 … | ++ MSG_WARN("Failed to create history entry.\n"); |
| 199 … | ++ fclose(history_fp); |
| 200 … | ++ return; |
| 201 … | ++ } |
| 202 … | ++ |
| 203 … | ++ if (fwrite(history_line, history_line_len, 1, history_fp) != 1) { |
| 204 … | ++ MSG_WARN("Failed to write history entry. %s\n", dStrerror(errno)); |
| 205 … | ++ fclose(history_fp); |
| 206 … | ++ return; |
| 207 … | ++ } |
| 208 … | ++ fclose(history_fp); |
| 209 … | ++} |
| 210 … | ++ |
| 211 … | + static void Cache_finish_msg(CacheEntry_t *entry) |
| 212 … | + { |
| 213 … | + if (!(entry->Flags & CA_InProgress)) { |
| 214 … | +@@ -872,6 +1022,8 @@ static void Cache_finish_msg(CacheEntry_t *entry) |
| 215 … | + } |
| 216 … | + dStr_fit(entry->Data); /* fit buffer size! */ |
| 217 … | + |
| 218 … | ++ Cache_finish_write(entry); |
| 219 … | ++ |
| 220 … | + if ((entry = Cache_process_queue(entry))) { |
| 221 … | + if (entry->Flags & CA_GotHeader) { |
| 222 … | + Cache_unref_data(entry); |
| 223 … | +@@ -891,6 +1043,7 @@ bool_t a_Cache_process_dbuf(int Op, const char *buf, size_t buf_size, |
| 224 … | + const DilloUrl *Url) |
| 225 … | + { |
| 226 … | + int offset, len; |
| 227 … | ++ int rc; |
| 228 … | + const char *str; |
| 229 … | + Dstr *dstr1, *dstr2, *dstr3; |
| 230 … | + bool_t done = FALSE; |
| 231 … | +@@ -932,6 +1085,10 @@ bool_t a_Cache_process_dbuf(int Op, const char *buf, size_t buf_size, |
| 232 … | + len = dstr2->len; |
| 233 … | + } |
| 234 … | + dStr_append_l(entry->Data, str, len); |
| 235 … | ++ rc = mbedtls_sha256_update_ret(&entry->Hash, (unsigned char *)str, len); |
| 236 … | ++ if (rc < 0) { |
| 237 … | ++ MSG_WARN("Failed to update SHA-256 calculation.\n"); |
| 238 … | ++ } |
| 239 … | + if (entry->CharsetDecoder && entry->UTF8Data) { |
| 240 … | + dstr3 = a_Decode_process(entry->CharsetDecoder, str, len); |
| 241 … | + dStr_append_l(entry->UTF8Data, dstr3->str, dstr3->len); |
| 242 … | +diff --git a/src/misc.c b/src/misc.c |
| 243 … | +index 00589999..dfd85b50 100644 |
| 244 … | +--- a/src/misc.c |
| 245 … | |
| 246 … | +@@ -456,6 +456,40 @@ char *a_Misc_encode_base64(const char *in) |
| 247 … | + return out; |
| 248 … | + } |
| 249 … | + |
| 250 … | ++char *a_Misc_encode_base64_2(const char *in, int len) |
| 251 … | ++{ |
| 252 … | ++ static const char *const base64_hex = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" |
| 253 … | ++ "abcdefghijklmnopqrstuvwxyz" |
| 254 … | ++ "0123456789+/"; |
| 255 … | ++ char *out = NULL; |
| 256 … | ++ int i = 0; |
| 257 … | ++ |
| 258 … | ++ if (in == NULL) return NULL; |
| 259 … | ++ |
| 260 … | ++ out = (char *)dMalloc((len + 2) / 3 * 4 + 1); |
| 261 … | ++ |
| 262 … | ++ for (; len >= 3; len -= 3) { |
| 263 … | ++ out[i++] = base64_hex[in[0] >> 2]; |
| 264 … | ++ out[i++] = base64_hex[((in[0]<<4) & 0x30) | (in[1]>>4)]; |
| 265 … | ++ out[i++] = base64_hex[((in[1]<<2) & 0x3c) | (in[2]>>6)]; |
| 266 … | ++ out[i++] = base64_hex[in[2] & 0x3f]; |
| 267 … | ++ in += 3; |
| 268 … | ++ } |
| 269 … | ++ |
| 270 … | ++ if (len > 0) { |
| 271 … | ++ unsigned char fragment; |
| 272 … | ++ out[i++] = base64_hex[in[0] >> 2]; |
| 273 … | ++ fragment = (in[0] << 4) & 0x30; |
| 274 … | ++ if (len > 1) fragment |= in[1] >> 4; |
| 275 … | ++ out[i++] = base64_hex[fragment]; |
| 276 … | ++ out[i++] = (len < 2) ? '=' : base64_hex[(in[1] << 2) & 0x3c]; |
| 277 … | ++ out[i++] = '='; |
| 278 … | ++ } |
| 279 … | ++ out[i] = '\0'; |
| 280 … | ++ return out; |
| 281 … | ++} |
| 282 … | ++ |
| 283 … | ++ |
| 284 … | + /* |
| 285 … | + * Load a local file into a dStr. |
| 286 … | + * Return value: dStr on success, NULL on error. |
| 287 … | +diff --git a/src/misc.h b/src/misc.h |
| 288 … | +index 75f0f78a..340dd45e 100644 |
| 289 … | +--- a/src/misc.h |
| 290 … | |
| 291 … | +@@ -19,6 +19,7 @@ int a_Misc_content_type_cmp(const char* ct1, const char *ct2); |
| 292 … | + int a_Misc_parse_geometry(char *geom, int *x, int *y, int *w, int *h); |
| 293 … | + int a_Misc_parse_search_url(char *source, char **label, char **urlstr); |
| 294 … | + char *a_Misc_encode_base64(const char *in); |
| 295 … | ++char *a_Misc_encode_base64_2(const char *in, int len); |
| 296 … | + Dstr *a_Misc_file2dstr(const char *filename); |
| 297 … | + |
| 298 … | + #ifdef __cplusplus |