/* * Allocate and set safe values for a DilloWeb structure */ DilloWeb* a_Web_new(const DilloUrl *url) { DilloWeb *web= g_new(DilloWeb, 1); _MSG(" a_Web_new: ValidWebs ==> %d\n", g_slist_length(ValidWebs)); web->url = a_Url_dup(url); web->bw = NULL; web->flags = 0; web->Image = NULL; web->stream = NULL; web->SavedBytes = 0; ValidWebs = g_slist_append(ValidWebs, (gpointer)web); return web; }
/* * Create a new connection data structure */ static capi_conn_t * Capi_conn_new(DilloUrl *url, void *bw, char *server, char *datastr) { capi_conn_t *conn; conn = dNew(capi_conn_t, 1); conn->url = url ? a_Url_dup(url) : NULL; conn->bw = bw; conn->server = dStrdup(server); conn->datastr = dStrdup(datastr); conn->SockFD = -1; conn->Flags = (strcmp(server, "http") != 0) ? PENDING : 0; conn->InfoSend = NULL; conn->InfoRecv = NULL; conn->Ref = 0; /* Reference count */ return conn; }
/* * Set a timeout function to ask for user/password. */ static void Cache_auth_entry(CacheEntry_t *entry, BrowserWindow *bw) { static int busy = 0; CacheAuthData_t *data; if (!entry) { busy = 0; } else if (busy) { MSG_WARN("Cache_auth_entry: caught busy!\n"); } else if (entry->Auth) { busy = 1; data = dNew(CacheAuthData_t, 1); data->auth = entry->Auth; data->url = a_Url_dup(entry->Url); data->bw = bw; entry->Auth = NULL; a_Timeout_add(0.0, Cache_auth_callback, data); } }
/* * Set safe values for a new cache entry */ static void Cache_entry_init(CacheEntry_t *NewEntry, const DilloUrl *Url) { NewEntry->Url = a_Url_dup(Url); NewEntry->TypeDet = NULL; NewEntry->TypeHdr = NULL; NewEntry->TypeMeta = NULL; NewEntry->TypeNorm = NULL; NewEntry->Header = dStr_new(""); NewEntry->Location = NULL; NewEntry->Auth = NULL; NewEntry->Data = dStr_sized_new(8*1024); NewEntry->UTF8Data = NULL; NewEntry->DataRefcount = 0; NewEntry->TransferDecoder = NULL; NewEntry->ContentDecoder = NULL; NewEntry->CharsetDecoder = NULL; NewEntry->ExpectedSize = 0; NewEntry->TransferSize = 0; NewEntry->Flags = CA_IsEmpty; }
/* * Return: Nonzero if we got new credentials from the user and everything * seems fine. */ static int Auth_do_auth_dialog(const AuthParse_t *auth_parse, const DilloUrl *url) { int ret; char *title, *msg; AuthDialogData_t *data; const char *typestr = auth_parse->type == DIGEST ? "Digest" : "Basic"; _MSG("auth.c: Auth_do_auth_dialog: realm = '%s'\n", auth_parse->realm); title = dStrconcat("Dillo: Password for ", auth_parse->realm, NULL); msg = dStrconcat("The server at ", URL_HOST(url), " requires a username" " and password for \"", auth_parse->realm, "\".\n\n" "Authentication scheme: ", typestr, NULL); data = dNew(AuthDialogData_t, 1); data->auth_parse = auth_parse; data->url = a_Url_dup(url); ret = a_Dialog_user_password(title, msg, Auth_do_auth_dialog_cb, data); dFree(title); dFree(msg); a_Url_free((void *)data->url); dFree(data); return ret; }
/* * Initialize proxy vars and Accept-Language header */ int a_Http_init(void) { char *env_proxy = getenv("http_proxy"); HTTP_Language_hdr = prefs.http_language ? dStrconcat("Accept-Language: ", prefs.http_language, "\r\n", NULL) : dStrdup(""); if (env_proxy && strlen(env_proxy)) HTTP_Proxy = a_Url_new(env_proxy, NULL); if (!HTTP_Proxy && prefs.http_proxy) HTTP_Proxy = a_Url_dup(prefs.http_proxy); /* This allows for storing the proxy password in "user:passwd" format * in dillorc, but as this constitutes a security problem, it was disabled. * if (HTTP_Proxy && prefs.http_proxyuser && strchr(prefs.http_proxyuser, ':')) HTTP_Proxy_Auth_base64 = a_Misc_encode_base64(prefs.http_proxyuser); */ host_connections = dList_new(5); return 0; }
/* * 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; }