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 + -
显示快捷键?