/* * Delete node. This will not free any cookies that might be in node->cookies. */ static void Cookies_delete_node(DomainNode *node) { dList_remove(domains, node); dFree(node->domain); dList_free(node->cookies); dFree(node); }
/* * Free Authentication fields. */ static void Cache_auth_free(Dlist *auth) { int i; void *auth_field; for (i = 0; (auth_field = dList_nth_data(auth, i)); ++i) dFree(auth_field); dList_free(auth); }
static void Http_host_connection_remove_all() { HostConnection_t *hc; while (dList_length(host_connections) > 0) { hc = (HostConnection_t*) dList_nth_data(host_connections, 0); while (Http_socket_dequeue(&hc->queue)); Http_host_connection_remove(hc); } dList_free(host_connections); }
/*! Free memory used by the services list */ void free_services_list(Dlist *s_list) { int i = 0; struct service *s; for (i=0; i < dList_length(s_list) ; i++) { s = dList_nth_data(s_list, i); dFree(s->name); } dList_free(s_list); }
static void Auth_realm_delete(AuthRealm_t *realm) { int i; MSG("Auth_realm_delete: \"%s\"\n", realm->name); for (i = dList_length(realm->paths) - 1; i >= 0; i--) dFree(dList_nth_data(realm->paths, i)); dList_free(realm->paths); dFree(realm->name); dFree(realm->username); dFree(realm->authorization); dFree(realm->cnonce); dFree(realm->nonce); dFree(realm->opaque); dFree(realm->domain); dFree(realm); }
/* * Memory deallocator (only called at exit time) */ void a_Cache_freeall(void) { CacheClient_t *Client; void *data; /* free the client queue */ while ((Client = dList_nth_data(ClientQueue, 0))) Cache_client_dequeue(Client, NULLKey); /* Remove every cache entry */ while ((data = dList_nth_data(CachedURLs, 0))) { dList_remove_fast(CachedURLs, data); Cache_entry_free(data); } /* Remove the cache list */ dList_free(CachedURLs); }
/* * Extract multiple fields from the header. */ static Dlist *Cache_parse_multiple_fields(const char *header, const char *fieldname) { uint_t i, j; Dlist *fields = dList_new(8); char *field; for (i = 0; header[i]; i++) { /* Search fieldname */ for (j = 0; fieldname[j]; j++) if (D_ASCII_TOLOWER(fieldname[j]) != D_ASCII_TOLOWER(header[i + j])) break; if (fieldname[j]) { /* skip to next line */ for (i += j; header[i] != '\n'; i++); continue; } i += j; if (header[i] == ':') { /* Field found! */ while (header[++i] == ' ' || header[i] == '\t'); for (j = 0; header[i + j] != '\n'; j++); while (j && (header[i + j - 1] == ' ' || header[i + j - 1] == '\t')) j--; field = dStrndup(header + i, j); dList_append(fields, field); } else { while (header[i] != '\n') i++; } } if (dList_length(fields) == 0) { dList_free(fields); fields = NULL; } return fields; }
/* * Flush cookies to disk and free all the memory allocated. */ static void Cookies_save_and_free() { int i, fd, saved = 0; DomainNode *node; CookieData_t *cookie; time_t now; #ifndef HAVE_LOCKF struct flock lck; #endif if (disabled) return; now = time(NULL); rewind(file_stream); fd = fileno(file_stream); if (ftruncate(fd, 0) == -1) MSG("Cookies: Truncate file stream failed: %s\n", dStrerror(errno)); fprintf(file_stream, "%s", cookies_txt_header_str); /* Iterate cookies per domain, saving and freeing */ while ((node = dList_nth_data(domains, 0))) { for (i = 0; (cookie = dList_nth_data(node->cookies, i)); ++i) { if (!cookie->session_only && difftime(cookie->expires_at, now) > 0) { int len; char buf[LINE_MAXLEN]; len = snprintf(buf, LINE_MAXLEN, "%s\t%s\t%s\t%s\t%ld\t%s\t%s\n", cookie->domain, cookie->host_only ? "FALSE" : "TRUE", cookie->path, cookie->secure ? "TRUE" : "FALSE", (long) difftime(cookie->expires_at, cookies_epoch_time), cookie->name, cookie->value); if (len < LINE_MAXLEN) { fprintf(file_stream, "%s", buf); saved++; } else { MSG("Not saving overly long cookie for %s.\n", cookie->domain); } } Cookies_free_cookie(cookie); } Cookies_delete_node(node); } dList_free(domains); dList_free(all_cookies); #ifdef HAVE_LOCKF lockf(fd, F_ULOCK, 0); #else /* POSIX file lock */ lck.l_start = 0; /* start at beginning of file */ lck.l_len = 0; /* lock entire file */ lck.l_type = F_UNLCK; lck.l_whence = SEEK_SET; /* absolute offset */ fcntl(fileno(file_stream), F_SETLKW, &lck); #endif fclose(file_stream); MSG("Cookies saved: %d.\n", saved); }
/* * Scan, allocate, and set things according to header info. * (This function needs the whole header to work) */ static void Cache_parse_header(CacheEntry_t *entry) { char *header = entry->Header->str; char *Length, *Type, *location_str, *encoding; #ifndef DISABLE_COOKIES Dlist *Cookies; #endif Dlist *warnings; void *data; int i; _MSG("Cache_parse_header\n"); if (entry->Header->len > 12) { if (header[9] == '1' && header[10] == '0' && header[11] == '0') { /* 100: Continue. The "real" header has not come yet. */ MSG("An actual 100 Continue header!\n"); entry->Flags &= ~CA_GotHeader; dStr_free(entry->Header, 1); entry->Header = dStr_new(""); return; } if (header[9] == '3' && header[10] == '0' && (location_str = Cache_parse_field(header, "Location"))) { /* 30x: URL redirection */ DilloUrl *location_url = a_Url_new(location_str,URL_STR_(entry->Url)); if (prefs.filter_auto_requests == PREFS_FILTER_SAME_DOMAIN && !a_Url_same_organization(entry->Url, location_url)) { /* don't redirect; just show body like usual (if any) */ MSG("Redirection not followed from %s to %s\n", URL_HOST(entry->Url), URL_STR(location_url)); a_Url_free(location_url); } else { entry->Flags |= CA_Redirect; if (header[11] == '1') entry->Flags |= CA_ForceRedirect; /* 301 Moved Permanently */ else if (header[11] == '2') entry->Flags |= CA_TempRedirect; /* 302 Temporary Redirect */ if (URL_FLAGS(location_url) & (URL_Post + URL_Get) && dStrAsciiCasecmp(URL_SCHEME(location_url), "dpi") == 0 && dStrAsciiCasecmp(URL_SCHEME(entry->Url), "dpi") != 0) { /* Forbid dpi GET and POST from non dpi-generated urls */ MSG("Redirection Denied! '%s' -> '%s'\n", URL_STR(entry->Url), URL_STR(location_url)); a_Url_free(location_url); } else { entry->Location = location_url; } } dFree(location_str); } else if (strncmp(header + 9, "401", 3) == 0) { entry->Auth = Cache_parse_multiple_fields(header, "WWW-Authenticate"); } else if (strncmp(header + 9, "404", 3) == 0) { entry->Flags |= CA_NotFound; } } if ((warnings = Cache_parse_multiple_fields(header, "Warning"))) { for (i = 0; (data = dList_nth_data(warnings, i)); ++i) { MSG_HTTP("%s\n", (char *)data); dFree(data); } dList_free(warnings); } /* * Get Transfer-Encoding and initialize decoder */ encoding = Cache_parse_field(header, "Transfer-Encoding"); entry->TransferDecoder = a_Decode_transfer_init(encoding); if ((Length = Cache_parse_field(header, "Content-Length")) != NULL) { if (encoding) { /* * If Transfer-Encoding is present, Content-Length must be ignored. * If the Transfer-Encoding is non-identity, it is an error. */ if (dStrAsciiCasecmp(encoding, "identity")) MSG_HTTP("Content-Length and non-identity Transfer-Encoding " "headers both present.\n"); } else { entry->Flags |= CA_GotLength; entry->ExpectedSize = MAX(strtol(Length, NULL, 10), 0); } dFree(Length); } dFree(encoding); /* free Transfer-Encoding */ #ifndef DISABLE_COOKIES if ((Cookies = Cache_parse_multiple_fields(header, "Set-Cookie"))) { CacheClient_t *client; for (i = 0; (client = dList_nth_data(ClientQueue, i)); ++i) { if (client->Url == entry->Url) { DilloWeb *web = client->Web; if (!web->requester || a_Url_same_organization(entry->Url, web->requester)) { char *server_date = Cache_parse_field(header, "Date"); a_Cookies_set(Cookies, entry->Url, server_date); dFree(server_date); break; } } } if (i >= dList_length(ClientQueue)) { MSG("Cache: cookies not accepted from '%s'\n", URL_STR(entry->Url)); } for (i = 0; (data = dList_nth_data(Cookies, i)); ++i) dFree(data); dList_free(Cookies); } #endif /* !DISABLE_COOKIES */ /* * Get Content-Encoding and initialize decoder */ encoding = Cache_parse_field(header, "Content-Encoding"); entry->ContentDecoder = a_Decode_content_init(encoding); dFree(encoding); if (entry->ExpectedSize > 0) { if (entry->ExpectedSize > HUGE_FILESIZE) { entry->Flags |= CA_HugeFile; } /* Avoid some reallocs. With MAX_INIT_BUF we avoid a SEGFAULT * with huge files (e.g. iso files). * Note: the buffer grows automatically. */ dStr_free(entry->Data, 1); entry->Data = dStr_sized_new(MIN(entry->ExpectedSize, MAX_INIT_BUF)); } /* Get Content-Type */ if ((Type = Cache_parse_field(header, "Content-Type"))) { /* This HTTP Content-Type is not trusted. It's checked against real data * in Cache_process_queue(); only then CA_GotContentType becomes true. */ a_Cache_set_content_type(entry->Url, Type, "http"); _MSG("TypeHdr {%s} {%s}\n", Type, URL_STR(entry->Url)); _MSG("TypeMeta {%s}\n", entry->TypeMeta); dFree(Type); } Cache_ref_data(entry); }