📄 forms.c
字号:
/* HTML forms parser *//* $Id: forms.c,v 1.60.2.4 2005/04/05 21:08:41 jonas Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "elinks.h"#include "bfu/listmenu.h"#include "bfu/menu.h"#include "document/html/parser/forms.h"#include "document/html/parser/link.h"#include "document/html/parser/stack.h"#include "document/html/parser/parse.h"#include "document/html/parser.h"#include "document/html/renderer.h"#include "document/forms.h"#include "intl/charsets.h"#include "protocol/protocol.h"#include "protocol/uri.h"#include "util/conv.h"#include "util/error.h"#include "util/memdebug.h"#include "util/memlist.h"#include "util/memory.h"#include "util/string.h"/* Unsafe macros */#include "document/html/internal.h"voidhtml_form(unsigned char *a){ unsigned char *al; struct form *form; html_context.was_br = 1; form = init_form(); if (!form) return; form->method = FORM_METHOD_GET; form->form_num = a - html_context.startf; al = get_attr_val(a, "method"); if (al) { if (!strcasecmp(al, "post")) { unsigned char *enctype = get_attr_val(a, "enctype"); form->method = FORM_METHOD_POST; if (enctype) { if (!strcasecmp(enctype, "multipart/form-data")) form->method = FORM_METHOD_POST_MP; if (!strcasecmp(enctype, "text/plain")) form->method = FORM_METHOD_POST_TEXT_PLAIN; mem_free(enctype); } } mem_free(al); } al = get_attr_val(a, "name"); if (al) form->name = al; al = get_attr_val(a, "action"); /* The HTML specification at * http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.3 states * that the behavior of an empty action attribute should be undefined. * Mozilla handles action="" as action="<current-URI>" which seems * reasonable. (bug 615) */ if (al && *al) { form->action = join_urls(html_context.base_href, trim_chars(al, ' ', 0)); mem_free(al); } else { enum uri_component components = URI_ORIGINAL; mem_free_if(al); /* We have to do following for GET method, because we would end * up with two '?' otherwise. */ if (form->method == FORM_METHOD_GET) components = URI_FORM_GET; form->action = get_uri_string(html_context.base_href, components); /* No action URI should contain post data */ assert(!form->action || !strchr(form->action, POST_CHAR)); /* GET method URIs should not have '?'. */ assert(!form->action || form->method != FORM_METHOD_GET || !strchr(form->action, '?')); } al = get_target(a); form->target = al ? al : stracpy(html_context.base_target); html_context.special_f(html_context.part, SP_FORM, form);}intget_form_mode(unsigned char *attr){ if (has_attr(attr, "disabled")) return FORM_MODE_DISABLED; if (has_attr(attr, "readonly")) return FORM_MODE_READONLY; return FORM_MODE_NORMAL;}static struct form_control *init_form_control(enum form_type type, unsigned char *attr){ struct form_control *fc; fc = mem_calloc(1, sizeof(*fc)); if (!fc) return NULL; fc->type = type; fc->position = attr - html_context.startf; fc->mode = get_form_mode(attr); return fc;}voidhtml_button(unsigned char *a){ unsigned char *al; struct form_control *fc; enum form_type type = FC_SUBMIT; html_focusable(a); al = get_attr_val(a, "type"); if (!al) goto no_type_attr; if (!strcasecmp(al, "button")) { type = FC_BUTTON; } else if (!strcasecmp(al, "reset")) { type = FC_RESET; } else if (strcasecmp(al, "submit")) { /* unknown type */ mem_free(al); return; } mem_free(al);no_type_attr: fc = init_form_control(type, a); if (!fc) return; fc->name = get_attr_val(a, "name"); fc->default_value = get_attr_val(a, "value"); if (!fc->default_value && fc->type == FC_SUBMIT) fc->default_value = stracpy("Submit"); if (!fc->default_value && fc->type == FC_RESET) fc->default_value = stracpy("Reset"); if (!fc->default_value && fc->type == FC_BUTTON) fc->default_value = stracpy("Button"); if (!fc->default_value) fc->default_value = stracpy(""); /* XXX: Does this make sense here? Where do we get FC_IMAGE? */ if (fc->type == FC_IMAGE) fc->alt = get_attr_val(a, "alt"); html_context.special_f(html_context.part, SP_CONTROL, fc); format.form = fc; format.style.attr |= AT_BOLD;}voidhtml_input(unsigned char *a){ int i; unsigned char *al; struct form_control *fc; enum form_type type = FC_TEXT; al = get_attr_val(a, "type"); if (!al) goto no_type_attr; if (!strcasecmp(al, "text")) type = FC_TEXT; else if (!strcasecmp(al, "password")) type = FC_PASSWORD; else if (!strcasecmp(al, "checkbox")) type = FC_CHECKBOX; else if (!strcasecmp(al, "radio")) type = FC_RADIO; else if (!strcasecmp(al, "submit")) type = FC_SUBMIT; else if (!strcasecmp(al, "reset")) type = FC_RESET; else if (!strcasecmp(al, "button")) type = FC_BUTTON; else if (!strcasecmp(al, "file")) type = FC_FILE; else if (!strcasecmp(al, "hidden")) type = FC_HIDDEN; else if (!strcasecmp(al, "image")) type = FC_IMAGE; /* else unknown type, let it default to FC_TEXT. */ mem_free(al);no_type_attr: fc = init_form_control(type, a); if (!fc) return; fc->name = get_attr_val(a, "name"); if (fc->type != FC_FILE) fc->default_value = get_attr_val(a, "value"); if (!fc->default_value && fc->type == FC_CHECKBOX) fc->default_value = stracpy("on"); if (!fc->default_value && fc->type == FC_SUBMIT) fc->default_value = stracpy("Submit"); if (!fc->default_value && fc->type == FC_RESET) fc->default_value = stracpy("Reset"); if (!fc->default_value && fc->type == FC_BUTTON) fc->default_value = stracpy("Button"); if (!fc->default_value) fc->default_value = stracpy(""); fc->size = get_num(a, "size"); if (fc->size == -1) fc->size = global_doc_opts->default_form_input_size; fc->size++; if (fc->size > global_doc_opts->box.width) fc->size = global_doc_opts->box.width; fc->maxlength = get_num(a, "maxlength"); if (fc->maxlength == -1) fc->maxlength = INT_MAX; if (fc->type == FC_CHECKBOX || fc->type == FC_RADIO) fc->default_state = has_attr(a, "checked"); if (fc->type == FC_IMAGE) fc->alt = get_attr_val(a, "alt"); if (fc->type == FC_HIDDEN) goto hid;#if 0 /* wait for better times --witekfl */ format.form = fc; process_hidden_link(html_context.part); goto hid; }#endif put_chrs(" ", 1, html_context.put_chars_f, html_context.part); html_stack_dup(ELEMENT_KILLABLE); html_focusable(a); format.form = fc; if (format.title) mem_free(format.title); format.title = get_attr_val(a, "title"); switch (fc->type) { case FC_TEXT: case FC_PASSWORD: case FC_FILE: format.style.attr |= AT_BOLD; for (i = 0; i < fc->size; i++) put_chrs("_", 1, html_context.put_chars_f, html_context.part); break; case FC_CHECKBOX: format.style.attr |= AT_BOLD; put_chrs("[ ]", 8, html_context.put_chars_f, html_context.part); break; case FC_RADIO: format.style.attr |= AT_BOLD; put_chrs("( )", 8, html_context.put_chars_f, html_context.part); break; case FC_IMAGE: mem_free_set(&format.image, NULL); al = get_url_val(a, "src"); if (!al) al = get_url_val(a, "dynsrc"); if (al) { format.image = join_urls(html_context.base_href, al); mem_free(al); } format.style.attr |= AT_BOLD; put_chrs("[ ", 7, html_context.put_chars_f, html_context.part); if (fc->alt) put_chrs(fc->alt, strlen(fc->alt), html_context.put_chars_f, html_context.part); else if (fc->name) put_chrs(fc->name, strlen(fc->name), html_context.put_chars_f, html_context.part); else put_chrs("Submit", 6, html_context.put_chars_f, html_context.part); put_chrs(" ]", 7, html_context.put_chars_f, html_context.part); break; case FC_SUBMIT: case FC_RESET: case FC_BUTTON: format.style.attr |= AT_BOLD; put_chrs("[ ", 7, html_context.put_chars_f, html_context.part); if (fc->default_value) put_chrs(fc->default_value, strlen(fc->default_value), html_context.put_chars_f, html_context.part); put_chrs(" ]", 7, html_context.put_chars_f, html_context.part); break; case FC_TEXTAREA: case FC_SELECT: case FC_HIDDEN: INTERNAL("bad control type"); } kill_html_stack_item(&html_top); put_chrs(" ", 1, html_context.put_chars_f, html_context.part);hid: html_context.special_f(html_context.part, SP_CONTROL, fc);}voidhtml_select(unsigned char *a){ /* Note I haven't seen this code in use, do_html_select() seems to take * care of bussiness. --FF */ /* It gets called when the "multiple" attribute is set. --jonas */ unsigned char *al = get_attr_val(a, "name"); if (!al) return; html_focusable(a); html_top.type = ELEMENT_DONT_KILL; mem_free_set(&format.select, al); format.select_disabled = has_attr(a, "disabled") ? FORM_MODE_DISABLED : FORM_MODE_NORMAL;}voidhtml_option(unsigned char *a){ struct form_control *fc; unsigned char *val; if (!format.select) return; val = get_attr_val(a, "value"); if (!val) { struct string str; unsigned char *p, *r; unsigned char *name; int namelen; for (p = a - 1; *p != '<'; p--); if (!init_string(&str)) goto end_parse; if (parse_element(p, html_context.eoff, NULL, NULL, NULL, &p)) { INTERNAL("parse element failed"); val = str.source; goto end_parse; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -