⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 objreq.c

📁 ELinks is an advanced and well-established feature-rich text mode web (HTTP/FTP/..) browser. ELinks
💻 C
字号:
/* objreq.c * Object Requester * (c) 2002 Mikulas Patocka * This file is a part of the Links program, released under GPL. */#include "links.h"void objreq_end(struct status *, struct object_request *);void object_timer(struct object_request *);void auth_fn(struct dialog_data *);int auth_cancel(struct dialog_data *, struct dialog_item_data *);int auth_ok(struct dialog_data *, struct dialog_item_data *);int auth_window(struct object_request *, unsigned char *);struct list_head requests = {&requests, &requests};tcount obj_req_count = 1;#define LL gf_val(1, G_BFU_FONT_SIZE)#define MAX_UID_LEN 256struct auth_dialog {	unsigned char uid[MAX_UID_LEN];	unsigned char passwd[MAX_UID_LEN];	unsigned char *realm;	int proxy;	unsigned char msg[1];};static inline struct object_request *find_rq(tcount c){	struct object_request *rq;	foreach(rq, requests) if (rq->count == c) return rq;	return NULL;}void auth_fn(struct dialog_data *dlg){	struct terminal *term = dlg->win->term;	struct auth_dialog *a = dlg->dlg->udata;	int max = 0, min = 0;	int w, rw;	int y = 0;	max_text_width(term, a->msg, &max, AL_LEFT);	min_text_width(term, a->msg, &min, AL_LEFT);	max_text_width(term, TEXT(T_USERID), &max, AL_LEFT);	min_text_width(term, TEXT(T_USERID), &min, AL_LEFT);	max_text_width(term, TEXT(T_PASSWORD), &max, AL_LEFT);	min_text_width(term, TEXT(T_PASSWORD), &min, AL_LEFT);	max_buttons_width(term, dlg->items + 2, 2, &max);	min_buttons_width(term, dlg->items + 2, 2, &min);	w = term->x * 9 / 10 - 2 * DIALOG_LB;	if (w > max) w = max;	if (w < min) w = min;	rw = w;	dlg_format_text(dlg, NULL, a->msg, 0, &y, w, &rw, COLOR_DIALOG_TEXT, AL_LEFT);	y += LL;	dlg_format_text_and_field(dlg, NULL, TEXT(T_USERID), dlg->items, 0, &y, w, &rw, COLOR_DIALOG_TEXT, AL_LEFT);	y += LL;	dlg_format_text_and_field(dlg, NULL, TEXT(T_PASSWORD), dlg->items + 1, 0, &y, w, &rw, COLOR_DIALOG_TEXT, AL_LEFT);	y += LL;	dlg_format_buttons(dlg, NULL, dlg->items + 2, 2, 0, &y, w, &rw, AL_CENTER);	w = rw;	dlg->xw = rw + 2 * DIALOG_LB;	dlg->yw = y + 2 * DIALOG_TB;	center_dlg(dlg);	draw_dlg(dlg);	y = dlg->y + DIALOG_TB;	y += LL;	dlg_format_text(dlg, term, a->msg, dlg->x + DIALOG_LB, &y, w, NULL, COLOR_DIALOG_TEXT, AL_LEFT);	y += LL;	dlg_format_text_and_field(dlg, term, TEXT(T_USERID), dlg->items, dlg->x + DIALOG_LB, &y, w, NULL, COLOR_DIALOG_TEXT, AL_LEFT);	y += LL;	dlg_format_text_and_field(dlg, term, TEXT(T_PASSWORD), dlg->items + 1, dlg->x + DIALOG_LB, &y, w, NULL, COLOR_DIALOG_TEXT, AL_LEFT);	y += LL;	dlg_format_buttons(dlg, term, dlg->items + 2, 2, dlg->x + DIALOG_LB, &y, w, NULL, AL_CENTER);}int auth_cancel(struct dialog_data *dlg, struct dialog_item_data *item){	struct object_request *rq = find_rq((my_intptr_t)dlg->dlg->udata2);	if (rq) {		rq->state = O_OK;		if (rq->timer != -1) kill_timer(rq->timer);		rq->timer = install_timer(0, (void (*)(void *))object_timer, rq);		(rq->ce = rq->stat.ce)->refcount++;	}	cancel_dialog(dlg, item);	return 0;}int auth_ok(struct dialog_data *dlg, struct dialog_item_data *item){	struct object_request *rq = find_rq((my_intptr_t)dlg->dlg->udata2);	if (rq) {		struct auth_dialog *a = dlg->dlg->udata;		struct session *ses;		struct conv_table *ct;		int net_cp;		unsigned char *uid, *passwd;		get_dialog_data(dlg);		ses = ((struct window *)dlg->win->term->windows.prev)->data;		ct = get_convert_table(rq->stat.ce->head, dlg->win->term->spec->charset, ses->ds.assume_cp, &net_cp, NULL, ses->ds.hard_assume);		ct = get_translation_table(dlg->win->term->spec->charset, net_cp);		uid = convert_string(ct, a->uid, strlen(a->uid), NULL);		passwd = convert_string(ct, a->passwd, strlen(a->passwd), NULL);		add_auth(rq->url, a->realm, uid, passwd, a->proxy);		mem_free(uid);		mem_free(passwd);		change_connection(&rq->stat, NULL, PRI_CANCEL);		load_url(rq->url, rq->prev_url, &rq->stat, rq->pri, NC_RELOAD);	}	cancel_dialog(dlg, item);	return 0;}int auth_window(struct object_request *rq, unsigned char *realm){	unsigned char *host, *port;	struct dialog *d;	struct auth_dialog *a;	struct terminal *term;	struct conv_table *ct;	unsigned char *urealm;	struct session *ses;	foreach(term, terminals) if (rq->term == term->count) goto ok;	return -1;	ok:	ses = ((struct window *)term->windows.prev)->data;	ct = get_convert_table(rq->stat.ce->head, term->spec->charset, ses->ds.assume_cp, NULL, NULL, ses->ds.hard_assume);	if (rq->stat.ce->http_code == 407) host = stracpy(proxies.http_proxy);	else {		host = get_host_name(rq->url);		if (!host) return -1;		if ((port = get_port_str(rq->url))) {			add_to_strn(&host, ":");			add_to_strn(&host, port);			mem_free(port);		}	}	urealm = convert_string(ct, realm, strlen(realm), NULL);	d = mem_alloc(sizeof(struct dialog) + 5 * sizeof(struct dialog_item) + sizeof(struct auth_dialog) + strlen(_(TEXT(T_ENTER_USERNAME), term)) + strlen(urealm) + 1 + strlen(_(TEXT(T_AT), term)) + strlen(host) + + 1);	memset(d, 0, sizeof(struct dialog) + 5 * sizeof(struct dialog_item) + sizeof(struct auth_dialog));	a = (struct auth_dialog *)((unsigned char *)d + sizeof(struct dialog) + 5 * sizeof(struct dialog_item));	strcpy(a->msg, _(TEXT(T_ENTER_USERNAME), term));	strcat(a->msg, urealm);	strcat(a->msg, "\n");	strcat(a->msg, _(TEXT(T_AT), term));	strcat(a->msg, host);	mem_free(host);	mem_free(urealm);	a->proxy = rq->stat.ce->http_code == 407;	a->realm = stracpy(realm);	d->udata = a;	d->udata2 = (void *)(my_intptr_t)rq->count;	if (rq->stat.ce->http_code == 401) d->title = TEXT(T_AUTHORIZATION_REQUIRED);	else d->title = TEXT(T_PROXY_AUTHORIZATION_REQUIRED);	d->fn = auth_fn;	d->items[0].type = D_FIELD;	d->items[0].dlen = MAX_UID_LEN;	d->items[0].data = a->uid;	d->items[1].type = D_FIELD_PASS;	d->items[1].dlen = MAX_UID_LEN;	d->items[1].data = a->passwd;	d->items[2].type = D_BUTTON;	d->items[2].gid = B_ENTER;	d->items[2].fn = auth_ok;	d->items[2].text = TEXT(T_OK);	d->items[3].type = D_BUTTON;	d->items[3].gid = B_ESC;	d->items[3].fn = auth_cancel;	d->items[3].text = TEXT(T_CANCEL);	do_dialog(term, d, getml(d, a->realm, NULL));	return 0;}/* prev_url is a pointer to previous url or NULL *//* prev_url will NOT be deallocated */void request_object(struct terminal *term, unsigned char *url, unsigned char *prev_url, int pri, int cache, void (*upcall)(struct object_request *, void *), void *data, struct object_request **rqp){	struct object_request *rq;	rq = mem_calloc(sizeof(struct object_request));	rq->state = O_WAITING;	rq->refcount = 1;	rq->term = term ? term->count : 0;	rq->stat.end = (void (*)(struct status *, void *))objreq_end;	rq->stat.data = rq;	rq->orig_url = stracpy(url);	rq->url = stracpy(url);	rq->pri = pri;	rq->cache = cache;	rq->upcall = upcall;	rq->data = data;	rq->timer = -1;	rq->z = get_time() - STAT_UPDATE_MAX;	rq->last_update = rq->z;	rq->last_bytes = 0;	if (rq->prev_url)mem_free(rq->prev_url);	rq->prev_url=stracpy(prev_url);	if (rqp) *rqp = rq;	rq->count = obj_req_count++;	add_to_list(requests, rq);	load_url(url, prev_url, &rq->stat, pri, cache);}void objreq_end(struct status *stat, struct object_request *rq){	if (stat->state < 0) {		if (stat->ce && rq->state == O_WAITING && stat->ce->redirect) {			if (rq->redirect_cnt++ < MAX_REDIRECTS) {				int cache;				unsigned char *u, *p, *pos;				change_connection(stat, NULL, PRI_CANCEL);				u = join_urls(rq->url, stat->ce->redirect);				if ((pos = extract_position(u))) {					if (rq->goto_position) mem_free(rq->goto_position);					rq->goto_position = pos;				}				if (!http_bugs.bug_302_redirect && !stat->ce->redirect_get && (p = strchr(u, POST_CHAR))) add_to_strn(&u, p);				cache = rq->cache;				if (cache < NC_RELOAD && (!strcmp(u, rq->url) || rq->redirect_cnt >= MAX_CACHED_REDIRECTS)) cache = NC_RELOAD;				mem_free(rq->url);				rq->url = u;				load_url(u, rq->prev_url, &rq->stat, rq->pri, cache);				return;			} else {				maxrd:				rq->stat.state = S_CYCLIC_REDIRECT;			}		}		if (stat->ce && rq->state == O_WAITING && (stat->ce->http_code == 401 || stat->ce->http_code == 407)) {			unsigned char *realm = get_auth_realm(rq->url, stat->ce->head, stat->ce->http_code == 407);			unsigned char *user;			if (!realm) goto xx;			if (stat->ce->http_code == 401 && !find_auth(rq->url, realm)) {				mem_free(realm);				if (rq->redirect_cnt++ >= MAX_REDIRECTS) goto maxrd;				change_connection(stat, NULL, PRI_CANCEL);				load_url(rq->url, rq->prev_url, &rq->stat, rq->pri, NC_RELOAD);				return;			}			user = get_user_name(rq->url);			if (user && *user) {				mem_free(user);				mem_free(realm);				goto xx;			}			mem_free(user);			if (!auth_window(rq, realm)) {				rq->redirect_cnt = 0;				mem_free(realm);				goto tm;			}			mem_free(realm);			goto xx;		}	}	if ((stat->state < 0 || stat->state == S_TRANS) && stat->ce && !stat->ce->redirect && stat->ce->http_code != 401 && stat->ce->http_code != 407) {		rq->state = O_LOADING;		if (0) {			xx:			rq->state = O_OK;		}		if (!rq->ce) (rq->ce = stat->ce)->refcount++;	}	tm:	if (rq->timer != -1) kill_timer(rq->timer);	rq->timer = install_timer(0, (void (*)(void *))object_timer, rq);}void object_timer(struct object_request *rq){	int last = rq->last_bytes;	if (rq->ce) rq->last_bytes = rq->ce->length;	rq->timer = -1;	if (rq->stat.state < 0 && (!rq->stat.ce || (!rq->stat.ce->redirect && rq->stat.ce->http_code != 401 && rq->stat.ce->http_code != 407) || rq->stat.state == S_CYCLIC_REDIRECT)) {		if (rq->stat.ce && rq->stat.state != S_CYCLIC_REDIRECT) {			rq->state = rq->stat.state != S_OK ? O_INCOMPLETE : O_OK;			/*(rq->ce = rq->stat.ce)->refcount++;*/		} else rq->state = O_FAILED;	}	if (rq->stat.state != S_TRANS) {		if (rq->stat.state >= 0)			rq->timer = install_timer(STAT_UPDATE_MAX, (void (*)(void *))object_timer, rq);		rq->last_update = rq->z;		if (rq->upcall) rq->upcall(rq, rq->data);	} else {		ttime ct = get_time();		ttime t = ct - rq->last_update;		rq->timer = install_timer(STAT_UPDATE_MIN, (void (*)(void *))object_timer, rq);		if (t >= STAT_UPDATE_MAX || (t >= STAT_UPDATE_MIN && rq->ce && rq->last_bytes > last)) {			rq->last_update = ct;			if (rq->upcall) rq->upcall(rq, rq->data);		}	}}void release_object_get_stat(struct object_request **rqq, struct status *news, int pri){	struct object_request *rq = *rqq;	if (!rq) return;	*rqq = NULL;	if (--rq->refcount) return;	change_connection(&rq->stat, news, pri);	if (rq->timer != -1) kill_timer(rq->timer);	if (rq->ce) rq->ce->refcount--;	mem_free(rq->orig_url);	mem_free(rq->url);	if (rq->prev_url) mem_free(rq->prev_url);	if (rq->goto_position) mem_free(rq->goto_position);	del_from_list(rq);	mem_free(rq);}void release_object(struct object_request **rqq){	release_object_get_stat(rqq, NULL, PRI_CANCEL);}void detach_object_connection(struct object_request *rq, off_t pos){	if (rq->state == O_WAITING || rq->state == O_FAILED) {		internal("detach_object_connection: no data received");		return;	}	if (rq->refcount == 1) detach_connection(&rq->stat, pos);}void clone_object(struct object_request *rq, struct object_request **rqq){	(*rqq = rq)->refcount++;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -