/* * Free the components of a CacheEntry_t struct. */ static void Cache_entry_free(CacheEntry_t *entry) { a_Url_free((DilloUrl *)entry->Url); dFree(entry->TypeDet); dFree(entry->TypeHdr); dFree(entry->TypeMeta); dFree(entry->TypeNorm); dStr_free(entry->Header, TRUE); a_Url_free((DilloUrl *)entry->Location); Cache_auth_free(entry->Auth); dStr_free(entry->Data, 1); dStr_free(entry->UTF8Data, 1); if (entry->CharsetDecoder) a_Decode_free(entry->CharsetDecoder); if (entry->TransferDecoder) a_Decode_free(entry->TransferDecoder); if (entry->ContentDecoder) a_Decode_free(entry->ContentDecoder); dFree(entry); }
/* * Change Content-Type for cache entry found by url. * from = { "http" | "meta" } * Return new content type. */ const char *a_Cache_set_content_type(const DilloUrl *url, const char *ctype, const char *from) { const char *curr; char *major, *minor, *charset; CacheEntry_t *entry = Cache_entry_search(url); dReturn_val_if_fail (entry != NULL, NULL); _MSG("a_Cache_set_content_type {%s} {%s}\n", ctype, URL_STR(url)); curr = Cache_current_content_type(entry); if (entry->TypeMeta || (*from == 'h' && entry->TypeHdr) ) { /* Type is already been set. Do nothing. * BTW, META overrides TypeHdr */ } else { if (*from == 'h') { /* Content-Type from HTTP header */ entry->TypeHdr = dStrdup(ctype); } else { /* Content-Type from META */ entry->TypeMeta = dStrdup(ctype); } if (a_Misc_content_type_cmp(curr, ctype)) { /* ctype gives one different from current */ a_Misc_parse_content_type(ctype, &major, &minor, &charset); if (*from == 'm' && charset && ((!major || !*major) && (!minor || !*minor))) { /* META only gives charset; use detected MIME type too */ entry->TypeNorm = dStrconcat(entry->TypeDet, ctype, NULL); } else if (*from == 'm' && !dStrnAsciiCasecmp(ctype, "text/xhtml", 10)) { /* WORKAROUND: doxygen uses "text/xhtml" in META */ entry->TypeNorm = dStrdup(entry->TypeDet); } if (charset) { if (entry->CharsetDecoder) a_Decode_free(entry->CharsetDecoder); entry->CharsetDecoder = a_Decode_charset_init(charset); curr = Cache_current_content_type(entry); /* Invalidate UTF8Data */ dStr_free(entry->UTF8Data, 1); entry->UTF8Data = NULL; } dFree(major); dFree(minor); dFree(charset); } } return curr; }
static void Cache_finish_msg(CacheEntry_t *entry) { if (entry->Flags & CA_GotData) { /* already finished */ return; } if ((entry->ExpectedSize || entry->TransferSize) && entry->TypeHdr == NULL) { MSG_HTTP("Message with a body lacked Content-Type header.\n"); } if ((entry->Flags & CA_GotLength) && (entry->ExpectedSize != entry->TransferSize)) { MSG_HTTP("Content-Length does NOT match message body at\n" "%s\n", URL_STR_(entry->Url)); MSG("Expected size: %d, Transfer size: %d\n", entry->ExpectedSize, entry->TransferSize); } entry->Flags |= CA_GotData; entry->Flags &= ~CA_Stopped; /* it may catch up! */ if (entry->TransferDecoder) { a_Decode_transfer_free(entry->TransferDecoder); entry->TransferDecoder = NULL; } if (entry->ContentDecoder) { a_Decode_free(entry->ContentDecoder); entry->ContentDecoder = NULL; } dStr_fit(entry->Data); /* fit buffer size! */ if ((entry = Cache_process_queue(entry))) { if (entry->Flags & CA_GotHeader) { Cache_unref_data(entry); } } }
/* * Receive new data, update the reception buffer (for next read), update the * cache, and service the client queue. * * This function gets called whenever the IO has new data. * 'Op' is the operation to perform * 'VPtr' is a (void) pointer to the IO control structure */ void a_Cache_process_dbuf(int Op, const char *buf, size_t buf_size, const DilloUrl *Url) { int offset, len; const char *str; Dstr *dstr1, *dstr2, *dstr3; CacheEntry_t *entry = Cache_entry_search(Url); /* Assert a valid entry (not aborted) */ dReturn_if_fail (entry != NULL); _MSG("__a_Cache_process_dbuf__\n"); if (Op == IORead) { /* * Cache_get_header() will set CA_GotHeader if it has a full header, and * Cache_parse_header() will unset it if the header ends being * merely an informational response from the server (i.e., 100 Continue) */ for (offset = 0; !(entry->Flags & CA_GotHeader) && (len = Cache_get_header(entry, buf + offset, buf_size - offset)); Cache_parse_header(entry) ) { offset += len; } if (entry->Flags & CA_GotHeader) { str = buf + offset; len = buf_size - offset; entry->TransferSize += len; dstr1 = dstr2 = dstr3 = NULL; /* Decode arrived data (<= 3 stages) */ if (entry->TransferDecoder) { dstr1 = a_Decode_process(entry->TransferDecoder, str, len); str = dstr1->str; len = dstr1->len; } if (entry->ContentDecoder) { dstr2 = a_Decode_process(entry->ContentDecoder, str, len); str = dstr2->str; len = dstr2->len; } dStr_append_l(entry->Data, str, len); if (entry->CharsetDecoder && entry->UTF8Data) { dstr3 = a_Decode_process(entry->CharsetDecoder, str, len); dStr_append_l(entry->UTF8Data, dstr3->str, dstr3->len); } dStr_free(dstr1, 1); dStr_free(dstr2, 1); dStr_free(dstr3, 1); if (entry->Data->len) entry->Flags &= ~CA_IsEmpty; entry = Cache_process_queue(entry); } } else if (Op == IOClose) { if ((entry->ExpectedSize || entry->TransferSize) && entry->TypeHdr == NULL) { MSG_HTTP("Message with a body lacked Content-Type header.\n"); } if ((entry->Flags & CA_GotLength) && (entry->ExpectedSize != entry->TransferSize)) { MSG_HTTP("Content-Length does NOT match message body,\n" " at: %s\n", URL_STR_(entry->Url)); MSG("entry->ExpectedSize = %d, entry->TransferSize = %d\n", entry->ExpectedSize, entry->TransferSize); } if (!entry->TransferSize && !(entry->Flags & CA_Redirect) && (entry->Flags & WEB_RootUrl)) { char *eol = strchr(entry->Header->str, '\n'); if (eol) { char *status_line = dStrndup(entry->Header->str, eol - entry->Header->str); MSG_HTTP("Body was empty. Server sent status: %s\n", status_line); dFree(status_line); } } entry->Flags |= CA_GotData; entry->Flags &= ~CA_Stopped; /* it may catch up! */ if (entry->TransferDecoder) { a_Decode_free(entry->TransferDecoder); entry->TransferDecoder = NULL; } if (entry->ContentDecoder) { a_Decode_free(entry->ContentDecoder); entry->ContentDecoder = NULL; } dStr_fit(entry->Data); /* fit buffer size! */ if ((entry = Cache_process_queue(entry))) { if (entry->Flags & CA_GotHeader) { Cache_unref_data(entry); } } } else if (Op == IOAbort) { /* unused */ MSG("a_Cache_process_dbuf Op = IOAbort; not implemented!\n"); } }