#include "links.h" struct list_head mailto_prog = { &mailto_prog, &mailto_prog }; struct list_head telnet_prog = { &telnet_prog, &telnet_prog }; struct list_head tn3270_prog = { &tn3270_prog, &tn3270_prog }; struct list_head assoc = { &assoc, &assoc }; tcount get_assoc_cnt() { static tcount assoc_cnt = 0; if (!++assoc_cnt) assoc_cnt = 1; return assoc_cnt; } struct list_head extensions = { &extensions, &extensions }; void delete_association(struct assoc *del) { del_from_list(del); mem_free(del->label); mem_free(del->ct); mem_free(del->prog); mem_free(del); } void delete_extension(struct extension *del) { del_from_list(del); mem_free(del->ext); mem_free(del->ct); mem_free(del); } int is_in_list(unsigned char *list, unsigned char *str, int l) { unsigned char *l2, *l3; if (!l) return 0; rep: while (*list && *list <= ' ') list++; if (!*list) return 0; for (l2 = list; *l2 && *l2 != ','; l2++) ; for (l3 = l2 - 1; l3 >= list && *l3 <= ' '; l3--) ; l3++; if (l3 - list == l && !casecmp(str, list, l)) return 1; list = l2; if (*list == ',') list++; goto rep; } unsigned char *get_content_type(unsigned char *head, unsigned char *url) { struct extension *e; struct assoc *a; unsigned char *ct, *ext, *exxt; int extl, el; if (head && (ct = parse_http_header(head, "Content-Type", NULL))) { unsigned char *s; if ((s = strchr(ct, ';'))) *s = 0; while (*ct && ct[strlen(ct) - 1] <= ' ') ct[strlen(ct) - 1] = 0; return ct; } ext = NULL, extl = 0; for (ct = url; *ct && !end_of_dir(*ct); ct++) if (*ct == '.') ext = ct + 1; else if (dir_sep(*ct)) ext = NULL; if (ext) while (ext[extl] && !dir_sep(ext[extl]) && !end_of_dir(ext[extl])) extl++; if (force_html || (extl == 3 && !casecmp(ext, "htm", 3)) || (extl == 4 && !casecmp(ext, "html", 4))) return stracpy("text/html"); foreach(e, extensions) if (is_in_list(e->ext, ext, extl)) return stracpy(e->ct); exxt = init_str(); el = 0; add_to_str(&exxt, &el, "application/x-"); add_bytes_to_str(&exxt, &el, ext, extl); foreach(a, assoc) if (is_in_list(a->ct, exxt, el)) return exxt; mem_free(exxt); return !force_html ? stracpy("text/plain") : stracpy("text/html"); } struct assoc *get_type_assoc(struct terminal *term, unsigned char *type) { struct assoc *a; foreach(a, assoc) if (a->system == SYSTEM_ID && (term->environment & ENV_XWIN ? a->xwin : a->cons) && is_in_list(a->ct, type, strlen(type))) return a; return NULL; } void free_types() { struct assoc *a; struct extension *e; struct protocol_program *p; foreach(a, assoc) { mem_free(a->ct); mem_free(a->prog); mem_free(a->label); } free_list(assoc); foreach(e, extensions) { mem_free(e->ext); mem_free(e->ct); } free_list(extensions); foreach(p, mailto_prog) mem_free(p->prog); free_list(mailto_prog); foreach(p, telnet_prog) mem_free(p->prog); free_list(telnet_prog); foreach(p, tn3270_prog) mem_free(p->prog); free_list(tn3270_prog); } unsigned char *ct_msg[] = { TEXT(T_LABEL), TEXT(T_CONTENT_TYPES), TEXT(T_PROGRAM__IS_REPLACED_WITH_FILE_NAME), #ifdef ASSOC_BLOCK TEXT(T_BLOCK_TERMINAL_WHILE_PROGRAM_RUNNING), #endif #ifdef ASSOC_CONS_XWIN TEXT(T_RUN_ON_TERMINAL), TEXT(T_RUN_IN_XWINDOW), #endif TEXT(T_ASK_BEFORE_OPENING), }; void add_ct_fn(struct dialog_data *dlg) { struct terminal *term = dlg->win->term; int max = 0, min = 0; int w, rw; int y = -1; int p = 1; #ifdef ASSOC_BLOCK p++; #endif #ifdef ASSOC_CONS_XWIN p += 2; #endif max_text_width(term, ct_msg[0], &max); min_text_width(term, ct_msg[0], &min); max_text_width(term, ct_msg[1], &max); min_text_width(term, ct_msg[1], &min); max_text_width(term, ct_msg[2], &max); min_text_width(term, ct_msg[2], &min); max_group_width(term, ct_msg + 3, dlg->items + 3, p, &max); min_group_width(term, ct_msg + 3, dlg->items + 3, p, &min); max_buttons_width(term, dlg->items + 3 + p, 2, &max); min_buttons_width(term, dlg->items + 3 + p, 2, &min); w = term->x * 9 / 10 - 2 * DIALOG_LB; if (w > max) w = max; if (w < min) w = min; if (w > term->x - 2 * DIALOG_LB) w = term->x - 2 * DIALOG_LB; if (w < 1) w = 1; rw = 0; dlg_format_text(NULL, term, _(ct_msg[0], term), 0, &y, w, &rw, COLOR_DIALOG_TEXT, AL_LEFT); y += 2; dlg_format_text(NULL, term, _(ct_msg[1], term), 0, &y, w, &rw, COLOR_DIALOG_TEXT, AL_LEFT); y += 2; dlg_format_text(NULL, term, _(ct_msg[2], term), 0, &y, w, &rw, COLOR_DIALOG_TEXT, AL_LEFT); y += 2; dlg_format_group(NULL, term, ct_msg + 3, dlg->items + 3, p, 0, &y, w, &rw); y++; dlg_format_buttons(NULL, term, dlg->items + 3 + p, 2, 0, &y, w, &rw, AL_CENTER); w = rw; dlg->xw = w + 2 * DIALOG_LB; dlg->yw = y + 2 * DIALOG_TB; center_dlg(dlg); draw_dlg(dlg); y = dlg->y + DIALOG_TB; dlg_format_text(term, term, ct_msg[0], dlg->x + DIALOG_LB, &y, w, NULL, COLOR_DIALOG_TEXT, AL_LEFT); dlg_format_field(term, term, &dlg->items[0], dlg->x + DIALOG_LB, &y, w, NULL, AL_LEFT); y++; dlg_format_text(term, term, ct_msg[1], dlg->x + DIALOG_LB, &y, w, NULL, COLOR_DIALOG_TEXT, AL_LEFT); dlg_format_field(term, term, &dlg->items[1], dlg->x + DIALOG_LB, &y, w, NULL, AL_LEFT); y++; dlg_format_text(term, term, ct_msg[2], dlg->x + DIALOG_LB, &y, w, NULL, COLOR_DIALOG_TEXT, AL_LEFT); dlg_format_field(term, term, &dlg->items[2], dlg->x + DIALOG_LB, &y, w, NULL, AL_LEFT); y++; dlg_format_group(term, term, ct_msg + 3, &dlg->items[3], p, dlg->x + DIALOG_LB, &y, w, NULL); y++; dlg_format_buttons(term, term, &dlg->items[3 + p], 2, dlg->x + DIALOG_LB, &y, w, NULL, AL_CENTER); } void update_assoc(struct assoc *new) { struct assoc *repl; if (!new->label[0] || !new->ct[0] || !new->prog[0]) return; if (new->cnt) { foreach(repl, assoc) if (repl->cnt == new->cnt) { mem_free(repl->label); mem_free(repl->ct); mem_free(repl->prog); goto replace; } return; } new->cnt = get_assoc_cnt(); if (!(repl = mem_alloc(sizeof(struct assoc)))) return; add_to_list(assoc, repl); replace: repl->label = stracpy(new->label); repl->ct = stracpy(new->ct); repl->prog = stracpy(new->prog); repl->block = new->block; repl->cons = new->cons; repl->xwin = new->xwin; repl->ask = new->ask; repl->system = new->system; repl->cnt = new->cnt; } void really_del_ct(void *fcp) { int fc = (int)fcp; struct assoc *del; foreach(del, assoc) if (del->cnt == fc) goto ok; return; ok: delete_association(del); } void menu_del_ct(struct terminal *term, void *fcp, void *xxx2) { unsigned char *str; int l; int fc = (int)fcp; struct assoc *del; foreach(del, assoc) if (del->cnt == fc) goto ok; return; ok: str = init_str(), l = 0; add_to_str(&str, &l, del->ct); add_to_str(&str, &l, " -> "); add_to_str(&str, &l, del->prog); msg_box(term, getml(str, NULL), TEXT(T_DELETE_ASSOCIATION), AL_CENTER | AL_EXTD_TEXT, TEXT(T_DELETE_ASSOCIATION), ": ", str, "?", NULL, fcp, 2, TEXT(T_YES), really_del_ct, B_ENTER, TEXT(T_NO), NULL, B_ESC); } void menu_add_ct(struct terminal *term, void *fcp, void *xxx2) { int p; int fc = (int)fcp; struct assoc *new, *from; unsigned char *label; unsigned char *ct; unsigned char *prog; struct dialog *d; if (fc) { foreach(from, assoc) if (from->cnt == fc) goto ok; return; } from = NULL; ok: if (!(d = mem_alloc(sizeof(struct dialog) + 10 * sizeof(struct dialog_item) + sizeof(struct assoc) + 3 * MAX_STR_LEN))) return; memset(d, 0, sizeof(struct dialog) + 10 * sizeof(struct dialog_item) + sizeof(struct assoc) + 3 * MAX_STR_LEN); new = (struct assoc *)&d->items[10]; new->label = label = (unsigned char *)(new + 1); new->ct = ct = label + MAX_STR_LEN; new->prog = prog = ct + MAX_STR_LEN; if (from) { strncpy(label, from->label, MAX_STR_LEN - 1); strncpy(ct, from->ct, MAX_STR_LEN - 1); strncpy(prog, from->prog, MAX_STR_LEN - 1); new->block = from->block; new->cons = from->cons; new->xwin = from->xwin; new->ask = from->ask; new->system = from->system; new->cnt = from->cnt; } else { new->block = new->xwin = new->cons = 1; new->ask = 1; new->system = SYSTEM_ID; } d->title = TEXT(T_ASSOCIATION); d->fn = add_ct_fn; d->refresh = (void (*)(void *))update_assoc; d->refresh_data = new; d->items[0].type = D_FIELD; d->items[0].dlen = MAX_STR_LEN; d->items[0].data = label; d->items[0].fn = check_nonempty; d->items[1].type = D_FIELD; d->items[1].dlen = MAX_STR_LEN; d->items[1].data = ct; d->items[1].fn = check_nonempty; d->items[2].type = D_FIELD; d->items[2].dlen = MAX_STR_LEN; d->items[2].data = prog; d->items[2].fn = check_nonempty; p = 3; #ifdef ASSOC_BLOCK d->items[p].type = D_CHECKBOX; d->items[p].data = (unsigned char *)&new->block; d->items[p++].dlen = sizeof(int); #endif #ifdef ASSOC_CONS_XWIN d->items[p].type = D_CHECKBOX; d->items[p].data = (unsigned char *)&new->cons; d->items[p++].dlen = sizeof(int); d->items[p].type = D_CHECKBOX; d->items[p].data = (unsigned char *)&new->xwin; d->items[p++].dlen = sizeof(int); #endif d->items[p].type = D_CHECKBOX; d->items[p].data = (unsigned char *)&new->ask; d->items[p++].dlen = sizeof(int); d->items[p].type = D_BUTTON; d->items[p].gid = B_ENTER; d->items[p].fn = ok_dialog; d->items[p++].text = TEXT(T_OK); d->items[p].type = D_BUTTON; d->items[p].gid = B_ESC; d->items[p].text = TEXT(T_CANCEL); d->items[p++].fn = cancel_dialog; d->items[p++].type = D_END; do_dialog(term, d, getml(d, NULL)); } struct menu_item mi_no_assoc[] = { TEXT(T_NO_ASSOCIATIONS), "", M_BAR, NULL, NULL, 0, 0, NULL, NULL, 0, NULL, NULL, 0, 0 }; void menu_list_assoc(struct terminal *term, void *fn, void *xxx) { struct assoc *a; struct menu_item *mi = NULL; int n = 0; foreachback(a, assoc) if (a->system == SYSTEM_ID) { if (!mi && !(mi = new_menu(7))) return; add_to_menu(&mi, stracpy(a->label), stracpy(a->ct), "", MENU_FUNC fn, (void *)a->cnt, 0), n++; } if (!mi) do_menu(term, mi_no_assoc, xxx); else do_menu(term, mi, xxx); } unsigned char *ext_msg[] = { TEXT(T_EXTENSION_S), TEXT(T_CONTENT_TYPE), }; void add_ext_fn(struct dialog_data *dlg) { struct terminal *term = dlg->win->term; int max = 0, min = 0; int w, rw; int y = -1; max_text_width(term, ext_msg[0], &max); min_text_width(term, ext_msg[0], &min); max_text_width(term, ext_msg[1], &max); min_text_width(term, ext_msg[1], &min); 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; if (w > term->x - 2 * DIALOG_LB) w = term->x - 2 * DIALOG_LB; if (w < 1) w = 1; rw = 0; dlg_format_text(NULL, term, ext_msg[0], 0, &y, w, &rw, COLOR_DIALOG_TEXT, AL_LEFT); y += 2; dlg_format_text(NULL, term, ext_msg[1], 0, &y, w, &rw, COLOR_DIALOG_TEXT, AL_LEFT); y += 2; dlg_format_buttons(NULL, term, dlg->items + 2, 2, 0, &y, w, &rw, AL_CENTER); w = rw; dlg->xw = w + 2 * DIALOG_LB; dlg->yw = y + 2 * DIALOG_TB; center_dlg(dlg); draw_dlg(dlg); y = dlg->y + DIALOG_TB; dlg_format_text(term, term, ext_msg[0], dlg->x + DIALOG_LB, &y, w, NULL, COLOR_DIALOG_TEXT, AL_LEFT); dlg_format_field(term, term, &dlg->items[0], dlg->x + DIALOG_LB, &y, w, NULL, AL_LEFT); y++; dlg_format_text(term, term, ext_msg[1], dlg->x + DIALOG_LB, &y, w, NULL, COLOR_DIALOG_TEXT, AL_LEFT); dlg_format_field(term, term, &dlg->items[1], dlg->x + DIALOG_LB, &y, w, NULL, AL_LEFT); y++; dlg_format_buttons(term, term, &dlg->items[2], 2, dlg->x + DIALOG_LB, &y, w, NULL, AL_CENTER); } void update_ext(struct extension *new) { struct extension *repl; if (!new->ext[0] || !new->ct[0]) return; if (new->cnt) { foreach(repl, extensions) if (repl->cnt == new->cnt) { mem_free(repl->ext); mem_free(repl->ct); goto replace; } return; } new->cnt = get_assoc_cnt(); if (!(repl = mem_alloc(sizeof(struct extension)))) return; add_to_list(extensions, repl); replace: repl->ext = stracpy(new->ext); repl->ct = stracpy(new->ct); repl->cnt = new->cnt; } void really_del_ext(void *fcp) { int fc = (int)fcp; struct extension *del; foreach(del, extensions) if (del->cnt == fc) goto ok; return; ok: delete_extension(del); } void menu_del_ext(struct terminal *term, void *fcp, void *xxx2) { unsigned char *str; int l; int fc = (int)fcp; struct extension *del; foreach(del, extensions) if (del->cnt == fc) goto ok; return; ok: str = init_str(), l = 0; add_to_str(&str, &l, del->ext); add_to_str(&str, &l, " -> "); add_to_str(&str, &l, del->ct); msg_box(term, getml(str, NULL), TEXT(T_DELETE_EXTENSION), AL_CENTER | AL_EXTD_TEXT, TEXT(T_DELETE_EXTENSION), " ", str, "?", NULL, fcp, 2, TEXT(T_YES), really_del_ext, B_ENTER, TEXT(T_NO), NULL, B_ESC); } void menu_add_ext(struct terminal *term, void *fcp, void *xxx2) { int fc = (int)fcp; struct extension *new, *from; unsigned char *ext; unsigned char *ct; struct dialog *d; if (fc) { foreach(from, extensions) if (from->cnt == fc) goto ok; return; } from = NULL; ok: if (!(d = mem_alloc(sizeof(struct dialog) + 5 * sizeof(struct dialog_item) + sizeof(struct extension) + 2 * MAX_STR_LEN))) return; memset(d, 0, sizeof(struct dialog) + 5 * sizeof(struct dialog_item) + sizeof(struct extension) + 2 * MAX_STR_LEN); new = (struct extension *)&d->items[5]; new->ext = ext = (unsigned char *)(new + 1); new->ct = ct = ext + MAX_STR_LEN; if (from) { strncpy(ext, from->ext, MAX_STR_LEN - 1); strncpy(ct, from->ct, MAX_STR_LEN - 1); new->cnt = from->cnt; } d->title = TEXT(T_EXTENSION); d->fn = add_ext_fn; d->refresh = (void (*)(void *))update_ext; d->refresh_data = new; d->items[0].type = D_FIELD; d->items[0].dlen = MAX_STR_LEN; d->items[0].data = ext; d->items[0].fn = check_nonempty; d->items[1].type = D_FIELD; d->items[1].dlen = MAX_STR_LEN; d->items[1].data = ct; d->items[1].fn = check_nonempty; d->items[2].type = D_BUTTON; d->items[2].gid = B_ENTER; d->items[2].fn = ok_dialog; d->items[2].text = TEXT(T_OK); d->items[3].type = D_BUTTON; d->items[3].gid = B_ESC; d->items[3].text = TEXT(T_CANCEL); d->items[3].fn = cancel_dialog; d->items[4].type = D_END; do_dialog(term, d, getml(d, NULL)); } struct menu_item mi_no_ext[] = { TEXT(T_NO_EXTENSIONS), "", M_BAR, NULL, NULL, 0, 0, NULL, NULL, 0, NULL, NULL, 0, 0 }; void menu_list_ext(struct terminal *term, void *fn, void *xxx) { struct extension *a; struct menu_item *mi = NULL; int n = 0; foreachback(a, extensions) { if (!mi && !(mi = new_menu(7))) return; add_to_menu(&mi, stracpy(a->ext), stracpy(a->ct), "", MENU_FUNC fn, (void *)a->cnt, 0), n++; } if (!mi) do_menu(term, mi_no_ext, xxx); else do_menu(term, mi, xxx); } void update_prog(struct list_head *l, unsigned char *p, int s) { struct protocol_program *repl; foreach(repl, *l) if (repl->system == s) { mem_free(repl->prog); goto ss; } if (!(repl = mem_alloc(sizeof(struct protocol_program)))) return; add_to_list(*l, repl); repl->system = s; ss: if ((repl->prog = mem_alloc(MAX_STR_LEN))) { strncpy(repl->prog, p, MAX_STR_LEN); repl->prog[MAX_STR_LEN - 1] = 0; } } unsigned char *get_prog(struct list_head *l) { struct protocol_program *repl; foreach(repl, *l) if (repl->system == SYSTEM_ID) return repl->prog; update_prog(l, "", SYSTEM_ID); foreach(repl, *l) if (repl->system == SYSTEM_ID) return repl->prog; return NULL; }