/* GAdmin-OpenVPN - An easy to use GTK+ frontend for the openvpn server.
 * Copyright (C) 2008 - 2010 Magnus Loef <magnus-swe@telia.com> 
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
*/



#include "../config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <gtk/gtk.h>
#include "gettext.h"
#include "widgets.h"
#include "allocate.h"
#include "show_info.h"
#include "commands.h"
#include "file_chooser.h"
#include "export_window.h"
#include "make_settings_buttons.h"
#include "make_settings_entries.h"
#include "make_settings_checkbuttons.h"
#include "functions.h"
#include "commented.h"



/* Modify the client conf so it works for openvpn-gui on windows. */
/* It doesnt handle chroot so ditch that and use different tap interface name etc. */
void make_openvpn_gui_conf()
{
    FILE *fp;
    gchar *info;
    char *line, *new_conf;
    long file_size = 0;

    gchar *linux_conf_path      = g_strdup_printf("%s/server/client/gadmin-openvpn-client.conf", OPENVPN_SYSCONF_DIR);
    gchar *openvpngui_conf_path = g_strdup_printf("%s/server/client/gadmin-openvpn-client.ovpn", OPENVPN_SYSCONF_DIR);
    gchar *openvpngui_passfile  = g_strdup_printf("%s/server/client/passfile", OPENVPN_SYSCONF_DIR);

    if((fp=fopen(linux_conf_path, "r"))==NULL)
    {
	info = g_strdup_printf("%s %s", _("Error: Can not open file:\n"), linux_conf_path);
        show_info(info);
        g_free(info);
        g_free(linux_conf_path);
        g_free(openvpngui_conf_path);
        g_free(openvpngui_passfile);
    	return;
    }
    fseek(fp, 0, SEEK_END);
    file_size = ftell(fp);
    rewind(fp);
    	                    	                
    line = allocate(file_size);
    new_conf = allocate(file_size);
    	                    	                        
    if( file_size > 1 )
    while(fgets(line, file_size, fp)!=NULL)
    {
	if( strlen(line) < 4 || commented(line) )
          continue;

	/* Switch "dev tap0" to "dev tap" etc */
	if( cmplowercase(line, "dev tap") )
	  strcat(new_conf, "dev tap\n");
	else
	if( cmplowercase(line, "auth-user-pass ") )
	  strcat(new_conf, "auth-user-pass passfile\n");
	else
	if( cmplowercase(line, "log ") )
	{ }
	else
	if( cmplowercase(line, "status ") )
	{ }
	else
	if( cmplowercase(line, "chroot ") )
	{ }
	else
	  strcat(new_conf, line);
    }
    fclose(fp);
    free(line);

    /* Write the new conf. */
    if((fp=fopen(openvpngui_conf_path, "w+"))==NULL)
    {
	info = g_strdup_printf("%s %s", _("Error: Can not write file:\n"), openvpngui_conf_path);
        show_info(info);
        g_free(info);
        g_free(linux_conf_path);
        g_free(openvpngui_conf_path);
        g_free(openvpngui_passfile);
    	return;
    }
    fputs(new_conf, fp);
    fclose(fp);
    free(new_conf);
    g_free(linux_conf_path);
    g_free(openvpngui_conf_path);

    /* Write an initial passfile */
    if((fp=fopen(openvpngui_passfile, "w+"))==NULL)
    {
	info = g_strdup_printf("%s %s", _("Error: Can not write file:\n"), openvpngui_passfile);
        show_info(info);
        g_free(info);
        g_free(openvpngui_passfile);
    	return;
    }
    fputs("PUT_YOUR_USERNAME_HERE\n", fp);
    fputs("PUT_YOUR_PASSWORD_HERE\n\n", fp);
    fclose(fp);
    g_free(openvpngui_passfile);
}


void apply_export_clicked(struct w *widgets)
{
    gchar *pkg_name, *pkg_path, *info, *cmd;
    G_CONST_RETURN gchar *export_dir;
    G_CONST_RETURN gchar *export_user;

    export_dir  = gtk_entry_get_text(GTK_ENTRY(widgets->export_dir_entry));
    export_user = gtk_entry_get_text(GTK_ENTRY(widgets->export_user_entry));

    /* No valid export directory supplied */
    if( export_dir==NULL || strlen(export_dir) < 4 )
    {
	info = g_strdup_printf(_("Error: Directory length is too short.\n"));
	show_info(info);
	g_free(info);
	return;
    }

    /* Create the export directory */
    if( ! file_exists((char *)export_dir) )
    {
	if( export_user!=NULL && strlen(export_user) > 1 )
	  cmd = g_strdup_printf("mkdir -p %s && chown %s %s", export_dir, export_user, export_dir);
	else
	  cmd = g_strdup_printf("mkdir -p %s", export_dir);
	
	if( ! run_command(cmd) )
	{
	    info = g_strdup_printf(_("Error: Can not create export directory.\n"));
	    show_info(info);
	    g_free(info);
	    g_free(cmd);
	    return;
	}
	g_free(cmd);
    }

    /* Adapt the package for windows openvpn-gui */
    if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widgets->export_to_windows_checkbutton)) )
    {
	make_openvpn_gui_conf();

	pkg_name = g_strdup_printf("gadmin-openvpn-client-data-windows.tar.gz");        

	/* Create the tar command that excludes the linux .conf file */
	cmd = g_strdup_printf("cd %s/server && tar -zcf %s client/ --exclude=*.conf", OPENVPN_SYSCONF_DIR, pkg_name);
    }
    else /* Create a package for Linux and other systems */
    {
	pkg_name = g_strdup_printf("gadmin-openvpn-client-data-linux.tar.gz");        

	/* Make the Linux tar command */
	cmd = g_strdup_printf("cd %s/server && tar -zcf %s client/ --exclude=*.ovpn --exclude=passfile", OPENVPN_SYSCONF_DIR, pkg_name);
    }

    /* Tar up the client configuration directory and put it in the server directory. */
    if( ! run_command(cmd) )
    {
    	info = g_strdup_printf(_("Error: Could not package the client configuration and certificates.\n"));
        show_info(info);
        g_free(info);
        g_free(cmd);
	g_free(pkg_name);
        return;
    }
    g_free(cmd);

    /* Put the package in the correct directory. */
    pkg_path = g_strdup_printf("%s/server/%s", OPENVPN_SYSCONF_DIR, pkg_name);
    if( ! file_exists(pkg_path) )
    {
    	info = g_strdup_printf(_("Error: No client configuration package has been created.\nIs the tar package installed ?.\n"));
        show_info(info);
    	g_free(info);
        g_free(pkg_path);
	g_free(pkg_name);
    	return;
    }

    /* Export user is supplied and has valid length. Make this user the owner of the package. */
    if( export_user!=NULL && strlen(export_user) > 1 )
    {
	cmd = g_strdup_printf("cp %s %s && chown %s:%s %s/%s",
                pkg_path, export_dir, export_user, export_user, export_dir, pkg_name);
    }
    else
    {
        cmd = g_strdup_printf("cp %s %s", pkg_path, export_dir);
    }
    g_free(pkg_name);
    
    if( ! run_command(cmd) )
    {
	info = g_strdup_printf(_("Error: Copying client data package has failed.\n"));
	show_info(info);
	g_free(info);
	g_free(pkg_path);
	g_free(cmd);
	return;
    }
    g_free(pkg_path);
    g_free(cmd);

    /* Destroy the export window */
    gtk_widget_destroy(widgets->export_window);
}


void select_directory_clicked(struct w *widgets)
{
    gchar *path = NULL;

    path = get_dialog_path_selection("DIR", "/home", "None");
    if( path!=NULL )
    {
        gtk_entry_set_text(GTK_ENTRY(widgets->export_dir_entry), path);
        g_free(path);
    }
}


/* Show the export window */
void show_export_window(struct w *widgets)
{
    GtkWidget *frame;
    GtkWidget *table;
    GtkWidget *vbox;
    GtkWidget *dir_select_button;
    GtkWidget *cancel_button, *apply_button;
    GtkTooltips *tooltips;
    gchar *utf8=NULL;
    gchar *info, *text;
    int a=0, b=1;

    tooltips = gtk_tooltips_new();

    widgets->export_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_position(GTK_WINDOW(widgets->export_window), GTK_WIN_POS_CENTER);
    gtk_widget_set_size_request(widgets->export_window, 620, -1);

    /* Set window information */
    info = g_strdup_printf(_("GAdmin-OpenVPN-Server - Export certificates"));
    gtk_window_set_title(GTK_WINDOW(widgets->export_window), info);
    g_free(info);

    vbox = gtk_vbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(widgets->export_window), vbox);

    tooltips = gtk_tooltips_new();

    /* 1 tables with some settings and 2 columns */
    table = gtk_table_new(2, 2, FALSE);

    frame = gtk_frame_new(_("Select export directory and settings:"));

    gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 1);
    gtk_container_add(GTK_CONTAINER(frame), table);


    widgets->export_dir_entry = gtk_entry_new();
    dir_select_button = make_button_with_entry(GTK_TABLE(table),
					    widgets->export_dir_entry,
					    "gtk-refresh",
					    "Export directory:",
					    "Select a directory to export the client package to",
					    0,1,a,b,350);
    a++; b++;
    g_signal_connect_swapped(G_OBJECT(dir_select_button), "clicked",
		     G_CALLBACK(select_directory_clicked), widgets);

    widgets->export_user_entry = make_entry_with_label(GTK_TABLE(table), _("Export to user: "), 0,1,a,b, 300);
    a++; b++;
    text = g_strdup_printf(_("The exported package will be owned by this user. Use this if you place the package in a users home or on the desktop"));
    utf8 = g_locale_to_utf8(text, strlen(text), NULL, NULL, NULL);
    gtk_tooltips_set_tip(tooltips, widgets->export_user_entry, utf8, NULL);
    if( text!=NULL )
      g_free(text);
    if( utf8!=NULL )
      g_free(utf8);


    /* Make an export package that is adapted for the windows openvpn-gui */
    widgets->export_to_windows_checkbutton = make_checkbutton_with_label(GTK_TABLE(table), _("Export to windows openvpn-gui:"), 0,1,a,b);
    a++; b++;


    /* Buttons: "Cancel" and "Apply" */
    GtkWidget *hbutton_box = gtk_hbutton_box_new();
    gtk_button_box_set_layout(GTK_BUTTON_BOX(hbutton_box), GTK_BUTTONBOX_SPREAD);

    cancel_button = gtk_button_new_from_stock(GTK_STOCK_QUIT);
    apply_button = gtk_button_new_from_stock(GTK_STOCK_APPLY);

    gtk_box_pack_start(GTK_BOX(hbutton_box), cancel_button, FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(hbutton_box), apply_button, FALSE, FALSE, 0);
    gtk_container_add(GTK_CONTAINER(vbox), hbutton_box);

    /* Window exit signal */
    g_signal_connect(GTK_WINDOW(widgets->export_window), "delete_event",
                     G_CALLBACK(gtk_widget_destroy), NULL);

    /* Cancel button */
    g_signal_connect_swapped((gpointer)cancel_button, "clicked",
            G_CALLBACK(gtk_widget_destroy), GTK_OBJECT(widgets->export_window));

    /* Apply button signals */
    g_signal_connect_swapped((gpointer)apply_button, "clicked",
		 G_CALLBACK(apply_export_clicked), widgets);


    gtk_widget_show_all(widgets->export_window);
}
