session.c

来自「this is the file used to browse web」· C语言 代码 · 共 1,618 行 · 第 1/4 页

C
1,618
字号
	l = mem_alloc(sizeof(struct location) + strlen(ses->tq_url));	memset(l, 0, sizeof(struct location));	init_list(l->frames);	memcpy(&l->stat, &ses->tq, sizeof(struct status));	init_vs(&l->vs, ses->tq_url);	if (ses->tq_goto_position) {		l->vs.goto_position = ses->tq_goto_position;		ses->tq_goto_position = NULL;	}	add_to_list(ses->history, l);	cur_loc(ses)->stat.end = (void (*)(struct status *, void *))doc_end_load;	cur_loc(ses)->stat.data = ses;	if (ses->tq.state >= 0) change_connection(&ses->tq, &cur_loc(ses)->stat, PRI_MAIN);	else cur_loc(ses)->stat.state = ses->tq.state;	cur_loc(ses)->vs.plain = 1;	display_timer(ses);	tp_free(ses);}void type_query(struct session *ses, struct cache_entry *ce, unsigned char *ct, struct assoc *a){	unsigned char *m1;	unsigned char *m2;	if (ses->tq_prog) mem_free(ses->tq_prog), ses->tq_prog = NULL;	if (a) ses->tq_prog = stracpy(a->prog), ses->tq_prog_flags = a->block;	if (a && !a->ask) {		tp_open(ses);		return;	}	m1 = stracpy(ct);	if (!a) {		if (!anonymous) msg_box(ses->term, getml(m1, NULL), TEXT(T_UNKNOWN_TYPE), AL_CENTER | AL_EXTD_TEXT, TEXT(T_CONTEN_TYPE_IS), " ", m1, ".\n", TEXT(T_DO_YOU_WANT_TO_SAVE_OR_DISLPAY_THIS_FILE), NULL, ses, 3, TEXT(T_SAVE), tp_save, B_ENTER, TEXT(T_DISPLAY), tp_display, 0, TEXT(T_CANCEL), tp_cancel, B_ESC);		else msg_box(ses->term, getml(m1, NULL), TEXT(T_UNKNOWN_TYPE), AL_CENTER | AL_EXTD_TEXT, TEXT(T_CONTEN_TYPE_IS), " ", m1, ".\n", TEXT(T_DO_YOU_WANT_TO_SAVE_OR_DISLPAY_THIS_FILE), NULL, ses, 2, TEXT(T_DISPLAY), tp_display, B_ENTER, TEXT(T_CANCEL), tp_cancel, B_ESC);	} else {		m2 = stracpy(a->label ? a->label : (unsigned char *)"");		if (!anonymous) msg_box(ses->term, getml(m1, m2, NULL), TEXT(T_WHAT_TO_DO), AL_CENTER | AL_EXTD_TEXT, TEXT(T_CONTEN_TYPE_IS), " ", m1, ".\n", TEXT(T_DO_YOU_WANT_TO_OPEN_FILE_WITH), " ", m2, ", ", TEXT(T_SAVE_IT_OR_DISPLAY_IT), NULL, ses, 4, TEXT(T_OPEN), tp_open, B_ENTER, TEXT(T_SAVE), tp_save, 0, TEXT(T_DISPLAY), tp_display, 0, TEXT(T_CANCEL), tp_cancel, B_ESC);		else msg_box(ses->term, getml(m1, m2, NULL), TEXT(T_WHAT_TO_DO), AL_CENTER | AL_EXTD_TEXT, TEXT(T_CONTEN_TYPE_IS), " ", m1, ".\n", TEXT(T_DO_YOU_WANT_TO_OPEN_FILE_WITH), " ", m2, ", ", TEXT(T_SAVE_IT_OR_DISPLAY_IT), NULL, ses, 3, TEXT(T_OPEN), tp_open, B_ENTER, TEXT(T_DISPLAY), tp_display, 0, TEXT(T_CANCEL), tp_cancel, B_ESC);	}}int ses_chktype(struct session *ses, struct status **stat, struct cache_entry *ce){	struct assoc *a;	unsigned char *ct;	int r = 0;	if (!(ct = get_content_type(ce->head, ce->url))) goto f;	if (is_html_type(ct)) goto ff;	r = 1;	if (!strcasecmp(ct, "text/plain") || !strcasecmp(ct, "file/txt")) goto ff;	if (!(a = get_type_assoc(ses->term, ct)) && strlen(ct) >= 4 && !casecmp(ct, "text", 4)) goto ff;	if (ses->tq_url) internal("type query to %s already in prgress", ses->tq_url);	ses->tq_url = stracpy(ses->loading_url);	change_connection(&ses->loading, *stat = &ses->tq, PRI_MAIN);	(ses->tq_ce = ce)->refcount++;	if (ses->tq_goto_position) mem_free(ses->tq_goto_position);	ses->tq_goto_position = stracpy(ses->goto_position);	type_query(ses, ce, ct, a);	mem_free(ct);	return 1;	ff:	mem_free(ct);	f:	if (ses->wtd_target && r) *ses->wtd_target = 0;	ses_forward(ses);	cur_loc(ses)->vs.plain = r;	return 0;}struct wtd_data {	struct session *ses;	unsigned char *url;	int pri;	int cache;	int wtd;	unsigned char *target;	unsigned char *pos;	void (*fn)(struct status *, struct session *);};void post_yes(struct wtd_data *w){	abort_preloading(w->ses);	if (w->ses->goto_position) mem_free(w->ses->goto_position);	w->ses->goto_position = stracpy(w->pos);	w->ses->loading.end = (void (*)(struct status *, void *))w->fn;	w->ses->loading.data = w->ses;	w->ses->loading_url = stracpy(w->url);	w->ses->wtd = w->wtd;	w->ses->wtd_target = w->target;	load_url(w->ses->loading_url, &w->ses->loading, w->pri, w->cache);}void post_no(struct wtd_data *w){	*strchr(w->url, POST_CHAR) = 0;	post_yes(w);}void post_cancel(struct wtd_data *w){	reload(w->ses, NC_CACHE);}void ses_goto(struct session *ses, unsigned char *url, unsigned char *target, int pri, int cache, int wtd, unsigned char *pos, void (*fn)(struct status *, struct session *), int redir){	struct wtd_data *w;	unsigned char *m1, *m2;	struct cache_entry *e;	if (!strchr(url, POST_CHAR) || (cache == NC_ALWAYS_CACHE && !find_in_cache(url, &e) && !e->incomplete)) {		if (ses->goto_position) mem_free(ses->goto_position);		ses->goto_position = pos;		ses->loading.end = (void (*)(struct status *, void *))fn;		ses->loading.data = ses;		ses->loading_url = url;		ses->wtd = wtd;		ses->wtd_target = target;		load_url(url, &ses->loading, pri, cache);		return;	}	w = mem_alloc(sizeof(struct wtd_data));	w->ses = ses;	w->url = url;	w->pri = pri;	w->cache = cache;	w->wtd = wtd;	w->target = target;	w->pos = pos;	w->fn = fn;	if (redir) m1 = TEXT(T_DO_YOU_WANT_TO_FOLLOW_REDIRECT_AND_POST_FORM_DATA_TO_URL);	else if (wtd == WTD_FORWARD) m1 = TEXT(T_DO_YOU_WANT_TO_POST_FORM_DATA_TO_URL);	else m1 = TEXT(T_DO_YOU_WANT_TO_REPOST_FORM_DATA_TO_URL);	m2 = memacpy(url, (unsigned char *)strchr(url, POST_CHAR) - url);	msg_box(ses->term, getml(m2, w, w->url, w->pos, NULL), TEXT(T_WARNING), AL_CENTER | AL_EXTD_TEXT, m1, " ", m2, "?", NULL, w, 3, TEXT(T_YES), post_yes, B_ENTER, TEXT(T_NO), post_no, 0, TEXT(T_CANCEL), post_cancel, B_ESC);}int do_move(struct session *ses, struct status **stat){	struct cache_entry *ce = NULL;	if (!ses->loading_url) {		internal("no ses->loading_url");		return 0;	}	if (!(ce = (*stat)->ce) || (ses->wtd == WTD_IMGMAP && (*stat)->state >= 0)) {		return 0;	}	if (ce->redirect && ses->redirect_cnt++ < MAX_REDIRECTS) {		unsigned char *u, *p, *gp, *pos;		int w = ses->wtd;		if (ses->wtd == WTD_BACK && (void *)cur_loc(ses)->next == &ses->history)			goto b;		if (!(u = join_urls(ses->loading_url, ce->redirect))) goto b;		if (!http_bugs.bug_302_redirect) if (!ce->redirect_get && (p = strchr(ses->loading_url, POST_CHAR))) add_to_strn(&u, p);		/* ^^^^ According to RFC2068 POST must not be redirected to GET,			but some BUGGY message boards rely on it :-( */		gp = stracpy(ses->goto_position);		if ((pos = extract_position(u))) {			if (!gp) gp = pos;			else mem_free(pos);		}		abort_loading(ses);		if (!list_empty(ses->history)) *stat = &cur_loc(ses)->stat;		else *stat = NULL;		if (w == WTD_FORWARD || w == WTD_IMGMAP) {			ses_goto(ses, u, ses->wtd_target, PRI_MAIN, ses->redirect_cnt < MAX_CACHED_REDIRECTS ? NC_CACHE : NC_RELOAD, w, gp, end_load, 1);			return 2;		}		if (gp) mem_free(gp);		if (w == WTD_BACK) {			ses_goto(ses, u, NULL, PRI_MAIN, ses->redirect_cnt < MAX_CACHED_REDIRECTS ? NC_CACHE : NC_RELOAD, WTD_RELOAD, NULL, end_load, 1);			return 2;		}		if (w == WTD_RELOAD) {			ses_goto(ses, u, NULL, PRI_MAIN, ses->redirect_cnt < MAX_CACHED_REDIRECTS && ses->reloadlevel < NC_RELOAD ? ses->reloadlevel : NC_RELOAD, WTD_RELOAD, NULL, end_load, 1);			return 2;		}	}	b:	if (ses->display_timer != -1) kill_timer(ses->display_timer), ses->display_timer = -1;	if (ses->wtd == WTD_FORWARD) {		if (ses_chktype(ses, stat, ce)) {			free_wtd(ses);			reload(ses, NC_CACHE);			return 2;		}	}	if (ses->wtd == WTD_IMGMAP) ses_imgmap(ses);	if (ses->wtd == WTD_BACK) ses_back(ses);	if (ses->wtd == WTD_RELOAD) ses_back(ses), ses_forward(ses);	if ((*stat)->state >= 0) change_connection(&ses->loading, *stat = &cur_loc(ses)->stat, PRI_MAIN);	else cur_loc(ses)->stat.state = ses->loading.state;	free_wtd(ses);	return 1;}void request_frameset(struct session *, struct frameset_desc *);void request_frame(struct session *ses, unsigned char *name, unsigned char *uurl){	struct location *loc = cur_loc(ses);	struct frame *frm;	unsigned char *url, *pos;	if (list_empty(ses->history)) {		internal("request_frame: no location");		return;	}	foreach(frm, loc->frames) if (!strcasecmp(frm->name, name)) {		struct f_data_c *fd;		foreach(fd, ses->scrn_frames) if (fd->vs == &frm->vs && fd->f_data->frame_desc) {			request_frameset(ses, fd->f_data->frame_desc);			return;		}		url = stracpy(frm->vs.url);		/*		if (frm->vs.f && frm->vs.f->f_data && frm->vs.f->f_data->frame) {			request_frameset(ses, frm->vs.f->f_data->frame_desc);			mem_free(url);			return;		}*/		goto found;	}	url = stracpy(uurl);	pos = extract_position(url);	frm = mem_alloc(sizeof(struct frame) + strlen(url) + 1);	memset(frm, 0, sizeof(struct frame));	if (!(frm->name = stracpy(name))) {		mem_free(frm);		mem_free(url);		if (pos) mem_free(pos);		return;	}	init_vs(&frm->vs, url);	if (pos) frm->vs.goto_position = pos;	add_to_list(loc->frames, frm);	found:	if (*url) request_additional_file(ses, url, PRI_FRAME);	mem_free(url);}void request_frameset(struct session *ses, struct frameset_desc *fd){	int i;	static int depth = 0;	if (++depth <= HTML_MAX_FRAME_DEPTH) {		for (i = 0; i < fd->n; i++) {			if (fd->f[i].subframe) request_frameset(ses, fd->f[i].subframe);			else if (fd->f[i].name) request_frame(ses, fd->f[i].name, fd->f[i].url);		}	}	depth--;}void load_frames(struct session *ses, struct f_data_c *fd){	struct f_data *ff = fd->f_data;	if (!ff || !ff->frame) return;	request_frameset(ses, ff->frame_desc);}void display_timer(struct session *ses){	ttime t = get_time();	html_interpret(ses);	draw_formatted(ses);	t = (get_time() - t) * DISPLAY_TIME;	if (t < DISPLAY_TIME_MIN) t = DISPLAY_TIME_MIN;	ses->display_timer = install_timer(t, (void (*)(void *))display_timer, ses);	load_frames(ses, ses->screen);	process_file_requests(ses);}void end_load(struct status *stat, struct session *ses){	int d;	if (!ses->wtd) {		internal("end_load: !ses->wtd");		return;	}	d = do_move(ses, &stat);	if (!stat) return;	if (d == 1) {		stat->end = (void (*)(struct status *, void *))doc_end_load;		display_timer(ses);	}	if (stat->state < 0) {		if (d != 2 && ses->wtd) {			free_wtd(ses);		}		if (d == 1) doc_end_load(stat, ses);	}	if (stat->state < 0 && stat->state != S_OK && d != 2 && d != 1) {		print_error_dialog(ses, stat, TEXT(T_ERROR));		if (!d) reload(ses, NC_CACHE);	}	print_screen_status(ses);}void doc_end_load(struct status *stat, struct session *ses){	if (stat->state < 0) {		if (ses->display_timer != -1) kill_timer(ses->display_timer), ses->display_timer = -1;		html_interpret(ses);		draw_formatted(ses);		load_frames(ses, ses->screen);		process_file_requests(ses);		if (stat->state != S_OK) print_error_dialog(ses, stat, TEXT(T_ERROR));	} else if (ses->display_timer == -1) display_timer(ses);	print_screen_status(ses);}void file_end_load(struct status *stat, struct file_to_load *ftl){	if (ftl->stat.ce) {		if (ftl->ce) ftl->ce->refcount--;		(ftl->ce = ftl->stat.ce)->refcount++;	}	doc_end_load(stat, ftl->ses);}struct file_to_load *request_additional_file(struct session *ses, unsigned char *url, int pri){	struct file_to_load *ftl;	foreach(ftl, ses->more_files) {		if (!strcmp(ftl->url, url)) {			if (ftl->pri > pri) {				ftl->pri = pri;				change_connection(&ftl->stat, &ftl->stat, pri);			}			return NULL;		}	}	ftl = mem_alloc(sizeof(struct file_to_load));	ftl->url = stracpy(url);	ftl->stat.end = (void (*)(struct status *, void *))file_end_load;	ftl->stat.data = ftl;	ftl->req_sent = 0;	ftl->pri = pri;	ftl->ce = NULL;	ftl->ses = ses;	add_to_list(ses->more_files, ftl);	return ftl;}struct file_to_load *request_additional_loading_file(struct session *ses, unsigned char *url, struct status *stat, int pri){	struct file_to_load *ftl;	if (!(ftl = request_additional_file(ses, url, pri))) {		change_connection(stat, NULL, PRI_CANCEL);		return NULL;	}	ftl->req_sent = 1;	ftl->ce = stat->ce;	change_connection(stat, &ftl->stat, pri);	return ftl;}void process_file_requests(struct session *ses){	static int stop_recursion = 0;	struct file_to_load *ftl;	int more;	if (stop_recursion) return;	stop_recursion = 1;	do {		more = 0;		foreach(ftl, ses->more_files) if (!ftl->req_sent) {			ftl->req_sent = 1;			load_url(ftl->url, &ftl->stat, ftl->pri, NC_CACHE);			more = 1;		}	} while (more);	stop_recursion = 0;}struct session *create_session(struct window *win){	struct terminal *term = win->term;	struct session *ses;	ses = mem_alloc(sizeof(struct session));	memset(ses, 0, sizeof(struct session));	init_list(ses->history);	init_list(ses->scrn_frames);	init_list(ses->more_files);	ses->term = term;	ses->win = win;	ses->id = session_id++;	ses->screen = NULL;	ses->wtd = WTD_NO;	ses->display_timer = -1;	ses->loading_url = NULL;	ses->goto_position = NULL;	memcpy(&ses->ds, &dds, sizeof(struct document_setup));	add_to_list(sessions, ses);	if (first_use) {		first_use = 0;		msg_box(term, NULL, TEXT(T_WELCOME), AL_CENTER | AL_EXTD_TEXT, TEXT(T_WELCOME_TO_LINKS), "\n\n", TEXT(T_BASIC_HELP), NULL, NULL, 1, TEXT(T_OK), NULL, B_ENTER | B_ESC);	}	return ses;}void copy_session(struct session *old, struct session *new){	/*struct location *l;	foreachback(l, old->history) {		struct location *nl;

⌨️ 快捷键说明

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