[go: up one dir, main page]

Menu

Diff of /forms.c [000000] .. [r1]  Maximize  Restore

Switch to side-by-side view

--- a
+++ b/forms.c
@@ -0,0 +1,431 @@
+/*
+ * forms.c
+ *
+ * Heath Caldwell
+ * hncaldwell@gmail.com
+ */
+
+#include <ncurses.h>
+#include <form.h>
+#include <string.h>
+#include <kpass.h>
+#include <time.h>
+
+#include "forms.h"
+
+int password_form(char *buffer, int length) {
+	FIELD *fields[5];
+	FORM *form;
+	WINDOW *win;
+	int press;
+	int rows, cols;
+	int ret_val;
+	int i;
+	int max_x, max_y;
+
+	char *labels[] = {"Password:", "[OK]", "[CANCEL]"};
+
+	fields[0] = new_field(1, strlen(labels[0]), 0, 0, 0 , 0);
+	fields[1] = new_field(1, 16, 0, 1 + strlen(labels[0]), 0 , 0);
+	fields[2] = new_field(1, strlen(labels[1]), 2, 4, 0 , 0);
+	fields[3] = new_field(1, strlen(labels[2]), 2, 6 + strlen(labels[2]), 0 , 0);
+	fields[4] = 0;
+
+	field_opts_off(fields[0], O_ACTIVE);
+
+	set_field_back(fields[1], A_UNDERLINE);
+	field_opts_off(fields[1], O_PUBLIC);
+	field_opts_off(fields[1], O_STATIC);
+	field_opts_off(fields[1], O_AUTOSKIP);
+	set_max_field(fields[1], length);
+
+	field_opts_off(fields[2], O_EDIT);
+	field_opts_off(fields[3], O_EDIT);
+
+	form = new_form(fields);
+	form_opts_off(form, O_BS_OVERLOAD);
+	scale_form(form, &rows, &cols);
+
+	getmaxyx(stdscr, max_y, max_x);
+
+	win = newwin(rows + 4, cols + 4, (max_y - (rows + 4)) / 2, (max_x - (cols + 4)) / 2);
+	keypad(win, TRUE);
+	set_form_win(form, win);
+	set_form_sub(form, derwin(win, rows, cols, 2, 2));
+	box(win, 0, 0);
+
+	post_form(form);
+	curs_set(1);
+	wrefresh(win);
+
+	set_field_just(fields[0], JUSTIFY_LEFT);
+	set_field_buffer(fields[0], 0, labels[0]);
+	set_field_buffer(fields[2], 0, labels[1]);
+	set_field_buffer(fields[3], 0, labels[2]);
+
+	while(1) {
+		press = wgetch(win);
+
+		if(press == KEY_RESIZE) {
+			// This might be a mess to deal with.
+			continue;
+		} else if(press == '\t') {
+			if(current_field(form) != fields[1]) {
+				set_field_fore(current_field(form), A_NORMAL);
+				curs_set(1);
+			}
+			form_driver(form, REQ_NEXT_FIELD);
+			form_driver(form, REQ_END_LINE);
+			if(current_field(form) != fields[1]) {
+				set_field_fore(current_field(form), A_REVERSE);
+				curs_set(0);
+			}
+		} else if(press == KEY_LEFT) {
+			form_driver(form, REQ_PREV_CHAR);
+		} else if(press == KEY_RIGHT) {
+			form_driver(form, REQ_NEXT_CHAR);
+		} else if(press == KEY_BACKSPACE) {
+			form_driver(form, REQ_DEL_PREV);
+		} else if(press == '\n') {
+			if(current_field(form) == fields[3]) {
+				ret_val = 1;
+				break;
+			}
+
+			/* Force the field buffer to be written. */
+			if(current_field(form) == fields[1]) form_driver(form, REQ_NEXT_FIELD);
+
+			strncpy(buffer, field_buffer(fields[1], 0), length);
+
+			/* Trim trailing spaces (should probably be revisited). */
+			i = strlen(buffer) - 2;
+			for(; buffer[i] == ' ' && i > 0; i--) ;
+			buffer[i + 1] = '\0';
+
+			ret_val = 0;
+			break;
+		} else {
+			form_driver(form, press);
+			set_field_status(fields[1], true);
+		}
+	}
+
+	unpost_form(form);
+	free_form(form);
+
+	for(i = 0; fields[i]; i++) {
+		free_field(fields[i]);
+	}
+
+	delwin(win);
+
+	curs_set(0);
+	return ret_val;
+}
+
+int open_database_form(char *buffer, int length) {
+	FIELD *fields[5];
+	FORM *form;
+	WINDOW *win;
+	int press;
+	int rows, cols;
+	int ret_val;
+	int i;
+	int max_x, max_y;
+
+	char *labels[] = {"Database File:", "[OK]", "[CANCEL]"};
+
+	fields[0] = new_field(1, strlen(labels[0]), 0, 0, 0 , 0);
+	fields[1] = new_field(1, 32, 0, 1 + strlen(labels[0]), 0 , 0);
+	fields[2] = new_field(1, strlen(labels[1]), 2, 16, 0 , 0);
+	fields[3] = new_field(1, strlen(labels[2]), 2, 18 + strlen(labels[2]), 0 , 0);
+	fields[4] = 0;
+
+	field_opts_off(fields[0], O_ACTIVE);
+
+	set_field_back(fields[1], A_UNDERLINE);
+	field_opts_off(fields[1], O_STATIC);
+	field_opts_off(fields[1], O_AUTOSKIP);
+	set_max_field(fields[1], length);
+
+	field_opts_off(fields[2], O_EDIT);
+	field_opts_off(fields[3], O_EDIT);
+
+	form = new_form(fields);
+	form_opts_off(form, O_BS_OVERLOAD);
+	scale_form(form, &rows, &cols);
+
+	getmaxyx(stdscr, max_y, max_x);
+
+	win = newwin(rows + 4, cols + 4, (max_y - (rows + 4)) / 2, (max_x - (cols + 4)) / 2);
+	keypad(win, TRUE);
+	set_form_win(form, win);
+	set_form_sub(form, derwin(win, rows, cols, 2, 2));
+	box(win, 0, 0);
+
+	post_form(form);
+	curs_set(1);
+	wrefresh(win);
+
+	set_field_just(fields[0], JUSTIFY_LEFT);
+	set_field_buffer(fields[0], 0, labels[0]);
+	set_field_buffer(fields[2], 0, labels[1]);
+	set_field_buffer(fields[3], 0, labels[2]);
+
+	while(1) {
+		press = wgetch(win);
+
+		if(press == KEY_RESIZE) {
+			// This might be a mess to deal with.
+			continue;
+		} else if(press == '\t') {
+			if(current_field(form) != fields[1]) {
+				set_field_fore(current_field(form), A_NORMAL);
+				curs_set(1);
+			}
+			form_driver(form, REQ_NEXT_FIELD);
+			form_driver(form, REQ_END_LINE);
+			if(current_field(form) != fields[1]) {
+				set_field_fore(current_field(form), A_REVERSE);
+				curs_set(0);
+			}
+		} else if(press == KEY_LEFT) {
+			form_driver(form, REQ_PREV_CHAR);
+		} else if(press == KEY_RIGHT) {
+			form_driver(form, REQ_NEXT_CHAR);
+		} else if(press == KEY_BACKSPACE) {
+			form_driver(form, REQ_DEL_PREV);
+		} else if(press == '\n') {
+			if(current_field(form) == fields[3]) {
+				ret_val = 1;
+				break;
+			}
+
+			/* Force the field buffer to be written. */
+			if(current_field(form) == fields[1]) form_driver(form, REQ_NEXT_FIELD);
+
+			strncpy(buffer, field_buffer(fields[1], 0), length);
+
+			/* Trim trailing spaces (should probably be revisited). */
+			i = strlen(buffer) - 2;
+			for(; buffer[i] == ' ' && i > 0; i--) ;
+			buffer[i + 1] = '\0';
+
+			ret_val = 0;
+			break;
+		} else {
+			form_driver(form, press);
+			set_field_status(fields[1], true);
+		}
+	}
+
+	unpost_form(form);
+	free_form(form);
+
+	for(i = 0; fields[i]; i++) {
+		free_field(fields[i]);
+	}
+
+	delwin(win);
+
+	curs_set(0);
+	return ret_val;
+}
+
+int entry_form(struct kpass_db *db, struct kpass_entry *entry) {
+	enum {f_uuid, f_group, f_image, f_title, f_url, f_username, f_password,
+		f_desc, f_ctime, f_mtime, f_atime, f_etime, f_notes, f_last};
+
+	FIELD *fields[2*f_last + 3];
+	FORM *form;
+	WINDOW *win;
+	int press;
+	int rows, cols;
+	int ret_val;
+	int i, j;
+	int max_x, max_y;
+	int init_length = 40;
+	int max_length = 256;
+	char buffer[max_length];
+	struct tm tms;
+
+	char *labels[] = {"uuid:", "Group:", "Image:", "Title:", "URL:", "Username:", "Password:",
+		"Description:", "ctime:", "mtime:", "atime:", "etime:", "Notes:"};
+	char *buttons[] = {"[OK]", "[CANCEL]"};
+
+	for(i = 0; i < f_last; i++) {
+		fields[2*i]     = new_field(1, strlen(labels[i]), i, 0,  0 , 0);
+		fields[2*i + 1] = new_field(1, init_length,       i, 14, 0 , 0);
+		
+		set_field_fore(fields[2*i], A_NORMAL);
+		field_opts_off(fields[2*i], O_ACTIVE);
+		set_field_just(fields[2*i], JUSTIFY_LEFT);
+		set_field_buffer(fields[2*i], 0, labels[i]);
+
+		set_field_fore(fields[2*i + 1], A_NORMAL);
+		set_field_back(fields[2*i + 1], A_UNDERLINE);
+		field_opts_off(fields[2*i + 1], O_STATIC);
+		field_opts_off(fields[2*i + 1], O_AUTOSKIP);
+		set_max_field(fields[2*i + 1], max_length);
+
+		switch(i) {
+			case f_uuid:
+				field_opts_off(fields[2*i + 1], O_ACTIVE);
+				set_field_back(fields[2*i + 1], A_NORMAL);
+
+				for(j=0; j<16; j++) {
+					sprintf(buffer + (j*2), "%02x", entry->uuid[j]);
+				}
+				buffer[j] = 0;
+				set_field_buffer(fields[2*i + 1], 0, buffer);
+				break;
+			case f_group:
+				field_opts_off(fields[2*i + 1], O_ACTIVE);
+				set_field_back(fields[2*i + 1], A_NORMAL);
+
+				for(j=0; j < db->groups_len && db->groups[j]->id != entry->group_id; j++);
+				set_field_buffer(fields[2*i + 1], 0, db->groups[j]->name);
+				break;
+			case f_image:
+				field_opts_off(fields[2*i + 1], O_ACTIVE);
+				set_field_back(fields[2*i + 1], A_NORMAL);
+
+				snprintf(buffer, max_length, "%d", entry->image_id);
+
+				set_field_buffer(fields[2*i + 1], 0, buffer);
+				break;
+			case f_title:
+				set_field_buffer(fields[2*i + 1], 0, entry->title);
+				break;
+			case f_url:
+				set_field_buffer(fields[2*i + 1], 0, entry->url);
+				break;
+			case f_username:
+				set_field_buffer(fields[2*i + 1], 0, entry->username);
+				break;
+			case f_password:
+				set_field_buffer(fields[2*i + 1], 0, entry->password);
+				break;
+			case f_desc:
+				set_field_buffer(fields[2*i + 1], 0, entry->desc);
+				break;
+			case f_ctime:
+				kpass_unpack_time(entry->ctime, &tms);
+				strftime(buffer, max_length, "%Y-%m-%d %H:%M:%S", &tms);
+				set_field_buffer(fields[2*i + 1], 0, buffer);
+				break;
+			case f_mtime:
+				kpass_unpack_time(entry->mtime, &tms);
+				strftime(buffer, max_length, "%Y-%m-%d %H:%M:%S", &tms);
+				set_field_buffer(fields[2*i + 1], 0, buffer);
+				break;
+			case f_atime:
+				kpass_unpack_time(entry->atime, &tms);
+				strftime(buffer, max_length, "%Y-%m-%d %H:%M:%S", &tms);
+				set_field_buffer(fields[2*i + 1], 0, buffer);
+				break;
+			case f_etime:
+				kpass_unpack_time(entry->etime, &tms);
+				strftime(buffer, max_length, "%Y-%m-%d %H:%M:%S", &tms);
+
+				if(!strcmp(buffer, "2999-12-28 23:59:59")) {
+					strcpy(buffer, "Never");
+				}
+
+				set_field_buffer(fields[2*i + 1], 0, buffer);
+				break;
+			case f_notes:
+				set_field_buffer(fields[2*i + 1], 0, entry->notes);
+				break;
+		}
+	}
+
+	fields[2*f_last]     = new_field(1, strlen(buttons[0]), f_last + 1, 19, 0 , 0);
+	set_field_buffer(fields[2*i], 0, buttons[0]);
+	fields[2*f_last + 1] = new_field(1, strlen(buttons[1]), f_last + 1, 27, 0 , 0);
+	set_field_buffer(fields[2*i + 1], 0, buttons[1]);
+	fields[2*f_last + 2] = 0; /* terminating field */
+
+	field_opts_off(fields[2*f_last], O_EDIT);
+	field_opts_off(fields[2*f_last + 1], O_EDIT);
+
+	form = new_form(fields);
+	form_opts_off(form, O_BS_OVERLOAD);
+	scale_form(form, &rows, &cols);
+
+	getmaxyx(stdscr, max_y, max_x);
+
+	win = newwin(rows + 4, cols + 4, (max_y - (rows + 4)) / 2, (max_x - (cols + 4)) / 2);
+	keypad(win, TRUE);
+	set_form_win(form, win);
+	set_form_sub(form, derwin(win, rows, cols, 2, 2));
+	box(win, 0, 0);
+
+	post_form(form);
+	curs_set(1);
+	wrefresh(win);
+
+	while(1) {
+		press = wgetch(win);
+
+		if(press == KEY_RESIZE) {
+			// This might be a mess to deal with.
+			continue;
+		} else if(press == '\t' || press == KEY_DOWN || (press == '\n' && current_field(form) < fields[2*f_last])) {
+			if(current_field(form) == fields[2*f_last] || current_field(form) == fields[2*f_last + 1]) {
+				set_field_fore(current_field(form), A_NORMAL);
+				curs_set(1);
+			}
+			form_driver(form, REQ_NEXT_FIELD);
+			form_driver(form, REQ_END_LINE);
+			if(current_field(form) == fields[2*f_last] || current_field(form) == fields[2*f_last + 1]) {
+				set_field_fore(current_field(form), A_REVERSE);
+				curs_set(0);
+			}
+		} else if(press == KEY_UP) {
+			if(current_field(form) == fields[2*f_last] || current_field(form) == fields[2*f_last + 1]) {
+				set_field_fore(current_field(form), A_NORMAL);
+				curs_set(1);
+			}
+			form_driver(form, REQ_PREV_FIELD);
+			form_driver(form, REQ_END_LINE);
+			if(current_field(form) == fields[2*f_last] || current_field(form) == fields[2*f_last + 1]) {
+				set_field_fore(current_field(form), A_REVERSE);
+				curs_set(0);
+			}
+		} else if(press == KEY_LEFT) {
+			form_driver(form, REQ_PREV_CHAR);
+		} else if(press == KEY_RIGHT) {
+			form_driver(form, REQ_NEXT_CHAR);
+		} else if(press == KEY_BACKSPACE) {
+			form_driver(form, REQ_DEL_PREV);
+		} else if(press == '\n') {
+			if(current_field(form) == fields[2*f_last]) {
+				/* OK button. */
+
+				/* STORE THE STUFF */
+				ret_val = 0;
+				break;
+			} else if(current_field(form) == fields[2*f_last + 1]) {
+				/* Cancel button. */
+				ret_val = 1;
+				break;
+			}
+		} else {
+			form_driver(form, press);
+		}
+	}
+
+	unpost_form(form);
+	free_form(form);
+
+	for(i = 0; fields[i]; i++) {
+		free_field(fields[i]);
+	}
+
+	delwin(win);
+
+	curs_set(0);
+	return ret_val;
+}
+