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

📄 formhist.c

📁 一个很有名的浏览器
💻 C
字号:
/* Implementation of a login manager for HTML forms *//* $Id: formhist.c,v 1.95.2.4 2005/05/01 22:03:23 jonas Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <string.h>#include "elinks.h"#include "bfu/dialog.h"#include "document/forms.h"#include "formhist/dialogs.h"#include "formhist/formhist.h"#include "intl/gettext/libintl.h"#include "lowlevel/home.h"#include "modules/module.h"#include "sched/session.h"#include "terminal/window.h"#include "util/base64.h"#include "util/file.h"#include "util/lists.h"#include "util/object.h"#include "util/secsave.h"#include "util/string.h"#include "viewer/text/form.h"#define FORMS_HISTORY_FILENAME		"formhist"/* TODO: Remember multiple login for the same form. * TODO: Password manager GUI (here?) (in dialogs.c, of course --pasky). */static struct option_info forms_history_options[] = {	INIT_OPT_BOOL("document.browse.forms", N_("Show form history dialog"),		"show_formhist", 0, 0,		N_("Ask if a login form should be saved to file or not.\n"		"This option only disables the dialog, already saved login\n"		"forms are unaffected.")),	NULL_OPTION_INFO,};INIT_LIST_HEAD(saved_forms);struct form_type_name {	enum form_type num;	unsigned char *name;};static struct form_type_name form_type2name[] = {	{ FC_TEXT,	"text"		},	{ FC_PASSWORD,	"password"	},	{ FC_FILE,	"file"		},	{ FC_TEXTAREA,	"textarea"	},	{ FC_CHECKBOX,	"checkbox"	},	{ FC_RADIO,	"radio"		},	{ FC_SELECT,	"select"	},	{ FC_SUBMIT,	"submit"	},	{ FC_IMAGE,	"image"		},	{ FC_HIDDEN,	"hidden"	},};#define FORM_TYPE_COUNT (sizeof(form_type2name)/sizeof(struct form_type_name))intstr2form_type(unsigned char *s){	int n;	for (n = 0; n < FORM_TYPE_COUNT; n++)		if (!strcmp(form_type2name[n].name, s))			return form_type2name[n].num;	return -1;}unsigned char *form_type2str(enum form_type num){	int n;	for (n = 0; n < FORM_TYPE_COUNT; n++)		if (form_type2name[n].num == num)			return form_type2name[n].name;	return NULL;}#undef FORM_TYPE_COUNTstatic struct formhist_data *new_form(unsigned char *url){	struct formhist_data *form;	int url_len = strlen(url);	form = mem_calloc(1, sizeof(*form) + url_len);	if (!form) return NULL;	memcpy(form->url, url, url_len);	form->submit = mem_alloc(sizeof(*form->submit));	if (!form->submit) { mem_free(form); return NULL; }	object_nolock(form, "formhist");	init_list(*form->submit);	form->box_item = add_listbox_leaf(&formhist_browser, NULL, form);	return form;}voidfree_form(struct formhist_data *form){	done_submitted_value_list(form->submit);	mem_free(form->submit);	if (form->box_item)		done_listbox_item(&formhist_browser, form->box_item);	mem_free(form);}static int loaded = 0;intload_forms_from_file(void){	struct formhist_data *form;	unsigned char tmp[MAX_STR_LEN];	unsigned char *file;	FILE *f;	if (loaded) return 1;	if (!elinks_home) return 0;	file = straconcat(elinks_home, FORMS_HISTORY_FILENAME, NULL);	if (!file) return 0;	f = fopen(file, "rb");	mem_free(file);	if (!f) return 0;	while (fgets(tmp, MAX_STR_LEN, f)) {		unsigned char *p;		int dontsave = 0;		if (tmp[0] == '\n' && !tmp[1]) continue;		p = strchr(tmp, '\t');		if (p) {			*p = '\0';			++p;			if (!strcmp(tmp, "dontsave"))				dontsave = 1;		} else {			/* Compat. with older file formats. Remove it at some			 * time. --Zas */			if (!strncmp(tmp, "dontsave,", 9)) {				dontsave = 1;				p = tmp + 9;			} else {				p = tmp;			}		}		/* URL */		p[strlen(p) - 1] = '\0';		form = new_form(p);		if (!form) continue;		if (dontsave) form->dontsave = 1;		/* Fields type, name, value */		while (fgets(tmp, MAX_STR_LEN, f)) {			struct submitted_value *sv;			unsigned char *type, *name, *value;			unsigned char *enc_value;			enum form_type ftype;			int ret;			if (tmp[0] == '\n' && !tmp[1]) break;			/* Type */			type = tmp;			p = strchr(type, '\t');			if (!p) goto fail;			*p = '\0';			/* Name */			name = ++p;			p = strchr(name, '\t');			if (!p) {				/* Compatibility with previous file formats.				 * REMOVE AT SOME TIME --Zas */				value = name;				name = type;				if (*name == '*') {					name++;					type = "password";				} else {					type = "text";				}				goto cont;			}			*p = '\0';			/* Value */			value = ++p;cont:			p = strchr(value, '\n');			if (!p) goto fail;			*p = '\0';			ret = str2form_type(type);			if (ret == -1) goto fail;			ftype = ret;			if (form->dontsave) continue;			enc_value = *value ? base64_decode(value)					   : stracpy(value);			if (!enc_value) goto fail;			sv = init_submitted_value(name, enc_value,						 ftype, NULL, 0);			mem_free(enc_value);			if (!sv) goto fail;			add_to_list(*form->submit, sv);		}		add_to_list(saved_forms, form);	}	fclose(f);	loaded = 1;	return 1;fail:	free_form(form);	return 0;}intsave_forms_to_file(void){	struct secure_save_info *ssi;	unsigned char *file;	struct formhist_data *form;	int r;	if (!elinks_home || get_cmd_opt_bool("anonymous"))		return 0;	file = straconcat(elinks_home, FORMS_HISTORY_FILENAME, NULL);	if (!file) return 0;	ssi = secure_open(file, 0177);	mem_free(file);	if (!ssi) return 0;	/* Write the list to password file ($ELINKS_HOME/formhist) */	foreach (form, saved_forms) {		struct submitted_value *sv;		if (form->dontsave) {			secure_fprintf(ssi, "dontsave\t%s\n\n", form->url);			continue;		}		secure_fprintf(ssi, "%s\n", form->url);		foreach (sv, *form->submit) {			unsigned char *encvalue;			if (sv->value && *sv->value) {				/* Obfuscate the value. If we do				 * $ cat ~/.elinks/formhist				 * we don't want someone behind our back to read our				 * password (androids don't count). */				encvalue = base64_encode(sv->value);			} else {				encvalue = stracpy("");			}			if (!encvalue) return 0;			/* Format is : type[TAB]name[TAB]value[CR] */			secure_fprintf(ssi, "%s\t%s\t%s\n", form_type2str(sv->type),				       sv->name, encvalue);			mem_free(encvalue);		}		secure_fputc(ssi, '\n');	}	r = secure_close(ssi);	if (r == 0) loaded = 1;	return r;}/* Check whether the form (chain of @submit submitted_values at @url document) * is already present in the form history. */static intform_exists(struct formhist_data *form1){	struct formhist_data *form;	if (!load_forms_from_file()) return 0;	foreach (form, saved_forms) {		int count = 0;		int exact = 0;		struct submitted_value *sv;		if (strcmp(form->url, form1->url)) continue;		if (form->dontsave) return 1;		/* Iterate through submitted entries. */		foreach (sv, *form1->submit) {			struct submitted_value *sv2;			unsigned char *value = NULL;			count++;			foreach (sv2, *form->submit) {				if (sv->type != sv2->type) continue;				if (!strcmp(sv->name, sv2->name)) {					exact++;					value = sv2->value;					break;				}			}			/* If we found a value for that name, check if value			 * has changed or not. */			if (value && strcmp(sv->value, value)) return 0;		}		/* Check if submitted values have changed or not. */		if (count && exact && count == exact) return 1;	}	return 0;}static intforget_forms_with_url(unsigned char *url){	struct formhist_data *form, *tmpform;	int count = 0;	foreach (form, saved_forms) {		if (strcmp(form->url, url)) continue;		tmpform = form;		form = form->prev;		del_from_list(tmpform);		free_form(tmpform);		count++;	}	return count;}/* Appends form data @form1 (url and submitted_value(s)) to the password file. * Returns 1 on success, 0 otherwise. */static intremember_form(struct formhist_data *form){	forget_forms_with_url(form->url);	add_to_list(saved_forms, form);	return save_forms_to_file();}static intnever_for_this_site(struct formhist_data *form){	form->dontsave = 1;	return remember_form(form);}unsigned char *get_form_history_value(unsigned char *url, unsigned char *name){	struct formhist_data *form;	if (!url || !*url || !name || !*name) return NULL;	if (!load_forms_from_file()) return NULL;	foreach (form, saved_forms) {		if (form->dontsave) continue;		if (!strcmp(form->url, url)) {			struct submitted_value *sv;			foreach (sv, *form->submit)				if (!strcmp(sv->name, name))					return sv->value;		}	}	return NULL;}voidmemorize_form(struct session *ses, struct list_head *submit,	      struct form *forminfo){	struct formhist_data *form;	struct submitted_value *sv;	int save = 0;	/* XXX: For now, we only save these types of form fields. */	foreach (sv, *submit) {		if (sv->type == FC_PASSWORD && sv->value && *sv->value) {			save = 1;			break;		}	}	if (!save) return;	/* Create a temporary form. */	form = new_form(forminfo->action);	if (!form) return;	foreach (sv, *submit) {		if ((sv->type == FC_TEXT) || (sv->type == FC_PASSWORD)) {			struct submitted_value *sv2;			sv2 = init_submitted_value(sv->name, sv->value,					 	   sv->type, NULL, 0);			if (!sv2) goto fail;			add_to_list(*form->submit, sv2);		}	}	if (form_exists(form)) goto fail;	msg_box(ses->tab->term, NULL, 0,		N_("Form history"), ALIGN_CENTER,		N_("Should this login be remembered?\n\n"		"Please note that the password will be stored "		"obscured (but unencrypted) in a file on your disk.\n\n"		"If you are using a valuable password, answer NO."),		form, 3,		N_("~Yes"), remember_form, B_ENTER,		N_("~No"), free_form, B_ESC,		N_("Ne~ver for this site"), never_for_this_site, NULL);	return;fail:	free_form(form);}static voiddone_form_history(struct module *module){	struct formhist_data *form;	foreach(form, saved_forms) {		done_submitted_value_list(form->submit);		mem_free(form->submit);		if (form->box_item)			done_listbox_item(&formhist_browser, form->box_item);	}	free_list(saved_forms);}struct module forms_history_module = struct_module(	/* name: */		N_("Form History"),	/* options: */		forms_history_options,	/* events: */		NULL,	/* submodules: */	NULL,	/* data: */		NULL,	/* init: */		NULL,	/* done: */		done_form_history);

⌨️ 快捷键说明

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