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

📄 form.c

📁 一个很有名的浏览器
💻 C
📖 第 1 页 / 共 3 页
字号:
		foreachback (sub, *list) if (list_has_next(*list, sub))			if (sub->next->position < sub->position) {				next = sub->next;				del_from_list(sub);				add_at_pos(next, sub);				sub = next;				changed = 1;			}	} while (changed);}static voidget_successful_controls(struct document_view *doc_view,			struct form_control *fc, struct list_head *list){	struct form_control *fc2;	assert(doc_view && fc && fc->form && list);	if_assert_failed return;	foreach (fc2, fc->form->items) {		if (((fc2->type != FC_SUBMIT &&			 fc2->type != FC_IMAGE &&			 fc2->type != FC_RESET &&			 fc2->type != FC_BUTTON) || fc2 == fc)		    && fc2->name && fc2->name[0]) {			struct form_state *fs = find_form_state(doc_view, fc2);			if (!fs) continue;			add_submitted_value_to_list(fc2, fs, list);		}	}	sort_submitted_values(list);}static voidencode_controls(struct list_head *l, struct string *data,		int cp_from, int cp_to){	struct submitted_value *sv;	struct conv_table *convert_table = NULL;	int lst = 0;	assert(l && data);	if_assert_failed return;	foreach (sv, *l) {		unsigned char *p2 = NULL;		if (lst)			add_char_to_string(data, '&');		else			lst = 1;		encode_uri_string(data, sv->name, 1);		add_char_to_string(data, '=');		/* Convert back to original encoding (see html_form_control()		 * for the original recoding). */		if (sv->type == FC_TEXTAREA) {			unsigned char *p;			p = encode_textarea(sv);			if (p) {				if (!convert_table)					convert_table = get_translation_table(cp_from, cp_to);				p2 = convert_string(convert_table, p,						    strlen(p), CSM_FORM, NULL, NULL, NULL);				mem_free(p);			}		} else if (sv->type == FC_TEXT ||			   sv->type == FC_PASSWORD) {			if (!convert_table)				convert_table = get_translation_table(cp_from, cp_to);			p2 = convert_string(convert_table, sv->value,					    strlen(sv->value), CSM_FORM, NULL, NULL, NULL);		} else {			p2 = stracpy(sv->value);		}		if (p2) {			encode_uri_string(data, p2, 1);			mem_free(p2);		}	}}#define BOUNDARY_LENGTH	32#define realloc_bound_ptrs(bptrs, bptrs_size) \	mem_align_alloc(bptrs, bptrs_size, bptrs_size + 1, int, 0xFF)struct boundary_info {	int count;	int *offsets;	unsigned char string[BOUNDARY_LENGTH];};static inline voidinit_boundary(struct boundary_info *boundary){	memset(boundary, 0, sizeof(*boundary));	memset(boundary->string, '0', BOUNDARY_LENGTH);}/* Add boundary to string and save the offset */static inline voidadd_boundary(struct string *data, struct boundary_info *boundary){	add_to_string(data, "--");	if (realloc_bound_ptrs(&boundary->offsets, boundary->count))		boundary->offsets[boundary->count++] = data->length;	add_bytes_to_string(data, boundary->string, BOUNDARY_LENGTH);}static inline unsigned char *increment_boundary_counter(struct boundary_info *boundary){	int j;	/* This is just a decimal string incrementation */	for (j = BOUNDARY_LENGTH - 1; j >= 0; j--) {		if (boundary->string[j]++ < '9')			return boundary->string;		boundary->string[j] = '0';	}	INTERNAL("Form data boundary counter overflow");	return NULL;}static inline voidcheck_boundary(struct string *data, struct boundary_info *boundary){	unsigned char *bound = boundary->string;	int i;	/* Search between all boundaries. There is a starting and an ending	 * boundary so only check the range of chars after the current offset	 * and before the next offset. If some string in the form data matches	 * the boundary string it is changed. */	for (i = 0; i < boundary->count - 1; i++) {		/* Start after the boundary string and also jump past the		 * "\r\nContent-Disposition: form-data; name=\"" string added		 * before any form data. */		int start_offset = boundary->offsets[i] + BOUNDARY_LENGTH + 40;		/* End so that there is atleast BOUNDARY_LENGTH chars to		 * compare. Subtract 2 char because there is no need to also		 * compare the '--' prefix that is part of the boundary. */		int end_offset = boundary->offsets[i + 1] - BOUNDARY_LENGTH - 2;		unsigned char *pos = data->source + start_offset;		unsigned char *end = data->source + end_offset;		for (; pos <= end; pos++) {			if (memcmp(pos, bound, BOUNDARY_LENGTH))				continue;			/* If incrementing causes overflow bail out. There is			 * no need to reset the boundary string with '0' since			 * that is already done when incrementing. */			if (!increment_boundary_counter(boundary))				return;			/* Else start checking all boundaries using the new			 * boundary string */			i = 0;			break;		}	}	/* Now update all the boundaries with the unique boundary string */	for (i = 0; i < boundary->count; i++)		memcpy(data->source + boundary->offsets[i], bound, BOUNDARY_LENGTH);}/* FIXME: shouldn't we encode data at send time (in http.c) ? --Zas */static voidencode_multipart(struct session *ses, struct list_head *l, struct string *data,		 struct boundary_info *boundary, int cp_from, int cp_to){	struct conv_table *convert_table = NULL;	struct submitted_value *sv;	assert(ses && l && data && boundary);	if_assert_failed return;	init_boundary(boundary);	foreach (sv, *l) {		add_boundary(data, boundary);		add_crlf_to_string(data);		/* FIXME: name is not encoded.		 * from RFC 1867:		 * multipart/form-data contains a series of parts.		 * Each part is expected to contain a content-disposition		 * header where the value is "form-data" and a name attribute		 * specifies the field name within the form,		 * e.g., 'content-disposition: form-data; name="xxxxx"',		 * where xxxxx is the field name corresponding to that field.		 * Field names originally in non-ASCII character sets may be		 * encoded using the method outlined in RFC 1522. */		add_to_string(data, "Content-Disposition: form-data; name=\"");		add_to_string(data, sv->name);		add_char_to_string(data, '"');		if (sv->type == FC_FILE) {#define F_BUFLEN 1024			int fh, rd;			unsigned char buffer[F_BUFLEN];			unsigned char *extension;			add_to_string(data, "; filename=\"");			add_to_string(data, get_filename_position(sv->value));			/* It sends bad data if the file name contains ", but			   Netscape does the same */			/* FIXME: We should follow RFCs 1522, 1867,			 * 2047 (updated by rfc 2231), to provide correct support			 * for non-ASCII and special characters in values. --Zas */			add_char_to_string(data, '"');			/* Add a Content-Type header if the type is configured */			extension = strrchr(sv->value, '.');			if (extension) {				unsigned char *type = get_extension_content_type(extension);				if (type) {					add_crlf_to_string(data);					add_to_string(data, "Content-Type: ");					add_to_string(data, type);					mem_free(type);				}			}			add_crlf_to_string(data);			add_crlf_to_string(data);			if (*sv->value) {				unsigned char *filename;				if (get_cmd_opt_bool("anonymous")) {					errno = EPERM;					goto encode_error;				}				/* FIXME: DO NOT COPY FILE IN MEMORY !! --Zas */				filename = expand_tilde(sv->value);				if (!filename) goto encode_error;				fh = open(filename, O_RDONLY);				mem_free(filename);				if (fh == -1) goto encode_error;				set_bin(fh);				do {					rd = safe_read(fh, buffer, F_BUFLEN);					if (rd == -1) {						close(fh);						goto encode_error;					}					if (rd) add_bytes_to_string(data, buffer, rd);				} while (rd);				close(fh);			}#undef F_BUFLEN		} else {			add_crlf_to_string(data);			add_crlf_to_string(data);			/* Convert back to original encoding (see			 * html_form_control() for the original recoding). */			if (sv->type == FC_TEXT || sv->type == FC_PASSWORD ||			    sv->type == FC_TEXTAREA) {				unsigned char *p;				if (!convert_table)					convert_table = get_translation_table(cp_from,									      cp_to);				p = convert_string(convert_table, sv->value,						   strlen(sv->value), CSM_FORM, NULL,						   NULL, NULL);				if (p) {					add_to_string(data, p);					mem_free(p);				}			} else {				add_to_string(data, sv->value);			}		}		add_crlf_to_string(data);	}	/* End-boundary */	add_boundary(data, boundary);	add_to_string(data, "--\r\n");	check_boundary(data, boundary);	mem_free_if(boundary->offsets);	return;encode_error:	mem_free_if(boundary->offsets);	done_string(data);	/* XXX: This error message should move elsewhere. --Zas */	info_box(ses->tab->term, MSGBOX_FREE_TEXT,		 N_("Error while posting form"), ALIGN_CENTER,		 msg_text(ses->tab->term, N_("Could not load file %s: %s"),			  sv->value, strerror(errno)));}static voidencode_newlines(struct string *string, unsigned char *data){	for (; *data; data++) {		if (*data == '\n' || *data == '\r') {			unsigned char buffer[3];			/* Hex it. */			buffer[0] = '%';			buffer[1] = hx((((int) *data) & 0xF0) >> 4);			buffer[2] = hx(((int) *data) & 0xF);			add_bytes_to_string(string, buffer, 3);		} else {			add_char_to_string(string, *data);		}	}}static voidencode_text_plain(struct list_head *l, struct string *data,		  int cp_from, int cp_to){	struct submitted_value *sv;	struct conv_table *convert_table = get_translation_table(cp_from, cp_to);	assert(l && data);	if_assert_failed return;	foreach (sv, *l) {		unsigned char *area51 = NULL;		unsigned char *value = sv->value;		add_to_string(data, sv->name);		add_char_to_string(data, '=');		switch (sv->type) {		case FC_TEXTAREA:			value = area51 = encode_textarea(sv);			if (!area51) break;			/* Fall through */		case FC_TEXT:		case FC_PASSWORD:			/* Convert back to original encoding (see			 * html_form_control() for the original recoding). */			value = convert_string(convert_table, value,					       strlen(value), CSM_FORM, NULL,					       NULL, NULL);		default:			/* Falling right through to free that textarea stuff */			mem_free_if(area51);			/* Did the conversion fail? */			if (!value) break;			encode_newlines(data, value);			/* Free if we did convert something */			if (value != sv->value) mem_free(value);		}		add_crlf_to_string(data);	}}voiddo_reset_form(struct document_view *doc_view, struct form *form){	struct form_control *fc;	assert(doc_view && doc_view->document);	if_assert_failed return;	foreach (fc, form->items) {		struct form_state *fs = find_form_state(doc_view, fc);		if (fs) init_form_state(fc, fs);	}}enum frame_event_statusreset_form(struct session *ses, struct document_view *doc_view, int a){	struct link *link = get_current_link(doc_view);	if (!link) return FRAME_EVENT_OK;	do_reset_form(doc_view, get_link_form_control(link)->form);	draw_forms(ses->tab->term, doc_view);	/* Could be the refresh return value and then ditch the draw_forms()	 * call. */	return FRAME_EVENT_OK;}struct uri *get_form_uri(struct session *ses, struct document_view *doc_view,	     struct form_control *fc){	struct boundary_info boundary;	INIT_LIST_HEAD(submit);	struct string data;	struct string go;	int cp_from, cp_to;	struct uri *uri;	struct form *form;	assert(ses && ses->tab && ses->tab->term);	if_assert_failed return NULL;	assert(doc_view && doc_view->document && fc && fc->form);	if_assert_failed return NULL;	form = fc->form;	if (fc->type == FC_RESET) {		do_reset_form(doc_view, form);		return NULL;	} else if (fc->type == FC_BUTTON) {		return NULL;	}	if (!form->action	    || !init_string(&data))		return NULL;	get_successful_controls(doc_view, fc, &submit);	cp_from = get_opt_codepage_tree(ses->tab->term->spec, "charset");	cp_to = doc_view->document->cp;	switch (form->method) {	case FORM_METHOD_GET:	case FORM_METHOD_POST:		encode_controls(&submit, &data, cp_from, cp_to);		break;	case FORM_METHOD_POST_MP:		encode_multipart(ses, &submit, &data, &boundary, cp_from, cp_to);		break;	case FORM_METHOD_POST_TEXT_PLAIN:		encode_text_plain(&submit, &data, cp_from, cp_to);	}#ifdef CONFIG_FORMHIST	/* XXX: We check data.source here because a NULL value can indicate	 * not only a memory allocation failure, but also an error reading	 * a file that is to be uploaded. TODO: Distinguish between	 * these two classes of errors (is it worth it?). -- Miciah */	if (data.source	    && get_opt_bool("document.browse.forms.show_formhist"))		memorize_form(ses, &submit, form);#endif	done_submitted_value_list(&submit);	if (!data.source	    || !init_string(&go)) {		done_string(&data);		return NULL;	}	switch (form->method) {	case FORM_METHOD_GET:	{		unsigned char *pos = strchr(form->action, '#');		if (pos) {			add_bytes_to_string(&go, form->action, pos - form->action);		} else {			add_to_string(&go, form->action);		}		if (strchr(go.source, '?'))			add_char_to_string(&go, '&');		else			add_char_to_string(&go, '?');		add_string_to_string(&go, &data);		if (pos) add_to_string(&go, pos);		break;	}	case FORM_METHOD_POST:	case FORM_METHOD_POST_MP:	case FORM_METHOD_POST_TEXT_PLAIN:	{		/* Note that we end content type here by a simple '\n',		 * replaced later by correct '\r\n' in http_send_header(). */		int i;		add_to_string(&go, form->action);		add_char_to_string(&go, POST_CHAR);		if (form->method == FORM_METHOD_POST) {			add_to_string(&go, "application/x-www-form-urlencoded\n");		} else if (form->method == FORM_METHOD_POST_TEXT_PLAIN) {			/* Dunno about this one but we don't want the full			 * hextcat thingy. --jonas */			add_to_string(&go, "text/plain\n");			add_to_string(&go, data.source);			break;		} else {			add_to_string(&go, "multipart/form-data; boundary=");			add_bytes_to_string(&go, boundary.string, BOUNDARY_LENGTH);			add_char_to_string(&go, '\n');		}		for (i = 0; i < data.length; i++) {			unsigned char p[3];

⌨️ 快捷键说明

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