/* * Let the client know that we're not following a redirection. */ static void Cache_provide_redirection_blocked_page(CacheEntry_t *entry, CacheClient_t *client) { DilloWeb *clientWeb = client->Web; a_Web_dispatch_by_type("text/html", clientWeb, &client->Callback, &client->CbData); client->Buf = dStrconcat("<!doctype html><html><body>" "Dillo blocked a redirection from <a href=\"", URL_STR(entry->Url), "\">", URL_STR(entry->Url), "</a> to <a href=\"", URL_STR(entry->Location), "\">", URL_STR(entry->Location), "</a> based on your domainrc " "settings.</body></html>", NULL); client->BufSize = strlen(client->Buf); (client->Callback)(CA_Send, client); dFree(client->Buf); }
/* * Update cache clients for a single cache-entry * Tasks: * - Set the client function (if not already set) * - Look if new data is available and pass it to client functions * - Remove clients when done * - Call redirect handler * * Return: Cache entry, which may be NULL if it has been removed. * * TODO: Implement CA_Abort Op in client callback */ static CacheEntry_t *Cache_process_queue(CacheEntry_t *entry) { uint_t i; int st; const char *Type; Dstr *data; CacheClient_t *Client; DilloWeb *ClientWeb; BrowserWindow *Client_bw = NULL; static bool_t Busy = FALSE; bool_t AbortEntry = FALSE; bool_t OfferDownload = FALSE; bool_t TypeMismatch = FALSE; if (Busy) MSG_ERR("FATAL!: >>>> Cache_process_queue Caught busy!!! <<<<\n"); if (!(entry->Flags & CA_GotHeader)) return entry; if (!(entry->Flags & CA_GotContentType)) { st = a_Misc_get_content_type_from_data( entry->Data->str, entry->Data->len, &Type); _MSG("Cache: detected Content-Type '%s'\n", Type); if (st == 0 || entry->Flags & CA_GotData) { if (a_Misc_content_type_check(entry->TypeHdr, Type) < 0) { MSG_HTTP("Content-Type '%s' doesn't match the real data.\n", entry->TypeHdr); TypeMismatch = TRUE; } entry->TypeDet = dStrdup(Type); entry->Flags |= CA_GotContentType; } else return entry; /* i.e., wait for more data */ } Busy = TRUE; for (i = 0; (Client = dList_nth_data(ClientQueue, i)); ++i) { if (Client->Url == entry->Url) { ClientWeb = Client->Web; /* It was a (void*) */ Client_bw = ClientWeb->bw; /* 'bw' in a local var */ if (ClientWeb->flags & WEB_RootUrl) { if (!(entry->Flags & CA_MsgErased)) { /* clear the "expecting for reply..." message */ a_UIcmd_set_msg(Client_bw, ""); entry->Flags |= CA_MsgErased; } if (TypeMismatch) { a_UIcmd_set_msg(Client_bw,"HTTP warning: Content-Type '%s' " "doesn't match the real data.", entry->TypeHdr); OfferDownload = TRUE; } if (entry->Flags & CA_Redirect) { if (!Client->Callback) { Client->Callback = Cache_null_client; Client_bw->redirect_level++; } } else { Client_bw->redirect_level = 0; } if (entry->Flags & CA_HugeFile) { a_UIcmd_set_msg(Client_bw,"Huge file! (%dMB)", entry->ExpectedSize / (1024*1024)); AbortEntry = OfferDownload = TRUE; } } else { /* For non root URLs, ignore redirections and 404 answers */ if (entry->Flags & CA_Redirect || entry->Flags & CA_NotFound) Client->Callback = Cache_null_client; } /* Set the client function */ if (!Client->Callback) { Client->Callback = Cache_null_client; if (TypeMismatch) { AbortEntry = TRUE; } else { const char *curr_type = Cache_current_content_type(entry); st = a_Web_dispatch_by_type(curr_type, ClientWeb, &Client->Callback, &Client->CbData); if (st == -1) { /* MIME type is not viewable */ if (ClientWeb->flags & WEB_RootUrl) { MSG("Content-Type '%s' not viewable.\n", curr_type); /* prepare a download offer... */ AbortEntry = OfferDownload = TRUE; } else { /* TODO: Resource Type not handled. * Not aborted to avoid multiple connections on the same * resource. A better idea is to abort the connection and * to keep a failed-resource flag in the cache entry. */ } } } if (AbortEntry) { if (ClientWeb->flags & WEB_RootUrl) a_Nav_cancel_expect_if_eq(Client_bw, Client->Url); a_Bw_remove_client(Client_bw, Client->Key); Cache_client_dequeue(Client, NULLKey); --i; /* Keep the index value in the next iteration */ continue; } } /* Send data to our client */ if (ClientWeb->flags & WEB_Download) { /* for download, always provide original data, not translated */ data = entry->Data; } else { data = Cache_data(entry); } if ((Client->BufSize = data->len) > 0) { Client->Buf = data->str; (Client->Callback)(CA_Send, Client); if (ClientWeb->flags & WEB_RootUrl) { /* show size of page received */ a_UIcmd_set_page_prog(Client_bw, entry->Data->len, 1); } } /* Remove client when done */ if (entry->Flags & CA_GotData) { /* Copy flags to a local var */ int flags = ClientWeb->flags; /* We finished sending data, let the client know */ (Client->Callback)(CA_Close, Client); if (ClientWeb->flags & WEB_RootUrl) a_UIcmd_set_page_prog(Client_bw, 0, 0); Cache_client_dequeue(Client, NULLKey); --i; /* Keep the index value in the next iteration */ /* within CA_GotData, we assert just one redirect call */ if (entry->Flags & CA_Redirect) Cache_redirect(entry, flags, Client_bw); } } } /* for */ if (AbortEntry) { /* Abort the entry, remove it from cache, and maybe offer download. */ DilloUrl *url = a_Url_dup(entry->Url); a_Capi_conn_abort_by_url(url); entry = NULL; if (OfferDownload) { /* Remove entry when 'conn' is already done */ Cache_entry_remove(NULL, url); if (a_Cache_download_enabled(url)) { Cache_savelink_t *data = dNew(Cache_savelink_t, 1); data->bw = Client_bw; data->url = a_Url_dup(url); a_Timeout_add(0.0, Cache_savelink_cb, data); } } a_Url_free(url); } else if (entry->Auth && (entry->Flags & CA_GotData)) { Cache_auth_entry(entry, Client_bw); } /* Trigger cleanup when there are no cache clients */ if (dList_length(ClientQueue) == 0) { _MSG(" a_Dicache_cleanup()\n"); a_Dicache_cleanup(); } Busy = FALSE; _MSG("QueueSize ====> %d\n", dList_length(ClientQueue)); return entry; }