
/* vim: set sw=4 sts=4 : */

/* Copyright (c) 2007-2008, David B. Cortarello
 * Copyright (c) 2007-2008, Christian Dywan
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice
 *     and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright notice
 *     and the following disclaimer in the documentation and/or other materials
 *     provided with the distribution.
 *   * Neither the name of Kwort nor the names of its contributors may be used
 *     to endorse or promote products derived from this software without
 *     specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
*/

/*
 * Original code by David B. Cortarello
 * Mostly rewritten by Christian Dywan
*/

#include <gtk/gtk.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include "config.h"
#include "errors.h"

int try(const char *username, const char *password, int argc, char **argv);

int main(int argc, char **argv)
{
	gboolean explicit_username = FALSE;
	int error;
	int m = 0, i = 1;
	guint counter = 0;
	const gchar *command = NULL;
	const gchar *username = NULL;
	const gchar *password = NULL;
	gchar *message = NULL;
	GtkWidget *dialog, *dialog_error;
	GtkSizeGroup *sizegroup;
	GtkWidget *hbox;
	GtkWidget *image;
	GtkWidget *align;
	GtkWidget *label;
	GtkWidget *user;
	GtkWidget *pass;

	gtk_init(&argc, &argv);
	if (argc < 2)
		exit(1);
	/* Was there an error? So display it and exit */
	if (!strcmp(argv[1], "-e")) {
		dialog_error = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Could not run command");
		gtk_window_set_title(GTK_WINDOW(dialog_error), "ktsuss");
		gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog_error), KTS_ERRORS[atoi(argv[2])]);
		gtk_dialog_run(GTK_DIALOG(dialog_error));
		gtk_widget_destroy(dialog_error);
		exit(1);
	}

	while (i < argc) {

		if (argv[i][0] != '-')
			break;

		if (!strcmp(argv[i], "--user") || !strcmp(argv[i], "-u")) {
			username = argv[i + 1];
			explicit_username = TRUE;
			if (message == NULL)
				message = g_strdup_printf("Please enter the\npassword for %s:", username);
		}

		if (!strcmp(argv[i], "--message") || !strcmp(argv[i], "-m")) {
			if (message != NULL)
				free(message);
			message = argv[i + 1];
			m = 1;
		}

		i += 2;
	}

	if (message == NULL)
		message = g_strdup("Please enter the desired\nusername and password:");
	command = argv[i];

	dialog = gtk_dialog_new_with_buttons(command, NULL, GTK_DIALOG_NO_SEPARATOR, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
	gtk_window_set_icon_name(GTK_WINDOW(dialog), "ktsuss");
	gtk_container_set_border_width(GTK_CONTAINER(dialog), 5);
	gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), 5);
	gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), 5);
	hbox = gtk_hbox_new(FALSE, 6);
#if GTK_CHECK_VERSION(2, 10, 0)
	image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_AUTHENTICATION, GTK_ICON_SIZE_DIALOG);
#else
	image = gtk_image_new_from_icon_name("ktsuss", GTK_ICON_SIZE_DIALOG);
#endif
	gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
	label = gtk_label_new(message);
	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
	sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
	if (!explicit_username) {
		hbox = gtk_hbox_new(FALSE, 6);
		label = gtk_label_new("Username");
		align = gtk_alignment_new(0, 0.5, 0, 0);
		gtk_container_add(GTK_CONTAINER(align), label);
		gtk_size_group_add_widget(sizegroup, align);
		gtk_box_pack_start(GTK_BOX(hbox), align, FALSE, FALSE, 0);
		user = gtk_entry_new();
		gtk_entry_set_text(GTK_ENTRY(user), username ? username : "root");
		gtk_box_pack_start(GTK_BOX(hbox), user, FALSE, FALSE, 0);
		gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
	}
	hbox = gtk_hbox_new(FALSE, 6);
	label = gtk_label_new("Password");
	align = gtk_alignment_new(0, 0.5, 0, 0);
	gtk_container_add(GTK_CONTAINER(align), label);
	gtk_size_group_add_widget(sizegroup, align);
	gtk_box_pack_start(GTK_BOX(hbox), align, FALSE, FALSE, 0);
	pass = gtk_entry_new_with_max_length(32);
	gtk_entry_set_visibility(GTK_ENTRY(pass), FALSE);
	gtk_box_pack_start(GTK_BOX(hbox), pass, FALSE, FALSE, 0);
	gtk_entry_set_activates_default(GTK_ENTRY(pass), TRUE);
	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
	gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
	gtk_widget_grab_focus(pass);
	gtk_widget_show_all(GTK_DIALOG(dialog)->vbox);

	/* Show the dialog up to 3 times */
	while (counter < 3) {
		if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) {
			if (!explicit_username)
				username = gtk_entry_get_text(GTK_ENTRY(user));
			password = gtk_entry_get_text(GTK_ENTRY(pass));
			error = try(username, password, argc, &(argv[i]));
			if (error != ERR_SUCCESS) {
				dialog_error = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Could not run '%s'", command);
				gtk_window_set_title(GTK_WINDOW(dialog), "ktsuss");
				gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog_error), KTS_ERRORS[error]);
				gtk_dialog_run(GTK_DIALOG(dialog_error));
				gtk_widget_destroy(dialog_error);
				if (error == ERR_WRONG_PASSWD)
					counter++;
				else if (error == ERR_INVALID_USERNAME)
					counter = 3;
			}
		}
		else
			counter = 3;
		if (counter < 3) {
			gtk_widget_grab_focus(pass);
			error = ERR_SUCCESS;
		}
	}
	if (!m)
		g_free(message);

	if (password != NULL)
		memset(password, 0, strlen(password));

	gtk_widget_destroy(dialog);

	return 0;
}
