/*
 * GProFTPD - A GTK+ frontend for the ProFTPD standalone server.
 * Copyright (C) 2001 - 2006 Magnus Loef (Magnus-swe) <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 2 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
 *
 */


#include "../config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include "gettext.h"
#include "allocate.h"
#include "widgets.h"
#include "functions.h"
#include "populate_user_settings.h"
#include "chars_are_digits.h"
#include "show_info.h"

#include "populate_shell_combo.h"


extern char global_server_address[1024];
extern char global_server_port[1024];
extern char global_server_name[1024];
extern char global_server_type[1024];
extern char global_user_name[1024];


void set_toggle_values(char *new_buffer, GtkTreeIter iter, struct w *widgets);



/* Set toggle values for each directory in the directory treeview */
void set_toggle_values(char *new_buffer, GtkTreeIter iter, struct w *widgets)
{
    int x = 0;

    if( strstr(new_buffer, "LIST") || strstr(new_buffer, "NLST") )
	gtk_list_store_set(GTK_LIST_STORE(widgets->directory_store), &iter, 1, 1, -1);
		
    if( strstr(new_buffer, "STOR") || strstr(new_buffer, "STOU") )
	gtk_list_store_set(GTK_LIST_STORE(widgets->directory_store), &iter, 2, 1, -1);

    if( strstr(new_buffer, "APPE") )
	gtk_list_store_set(GTK_LIST_STORE(widgets->directory_store), &iter, 3, 1, -1);

    if( strstr(new_buffer, "RETR") )
	gtk_list_store_set(GTK_LIST_STORE(widgets->directory_store), &iter, 4, 1, -1);

    if( strstr(new_buffer, "RNFR") || strstr(new_buffer, "RNTO") )
	gtk_list_store_set(GTK_LIST_STORE(widgets->directory_store), &iter, 5, 1, -1);

    if( strstr(new_buffer, "DELE") )
	gtk_list_store_set(GTK_LIST_STORE(widgets->directory_store), &iter, 7, 1, -1);

    if( strstr(new_buffer, "MKD") || strstr(new_buffer, "XMKD") )
	gtk_list_store_set(GTK_LIST_STORE(widgets->directory_store), &iter, 8, 1, -1);

    if( strstr(new_buffer, "RMD") || strstr(new_buffer, "XRMD") )
	gtk_list_store_set(GTK_LIST_STORE(widgets->directory_store), &iter, 9, 1, -1);

    if( strstr(new_buffer, "SITE") ) /* dont match SITE_CHMOD or SITE_CHGRP */
    {
	for(x=0; new_buffer[x]!='\0'; x++)
	{
	    if( new_buffer[x]=='\0' || new_buffer[x+1]=='\0' || new_buffer[x+2]=='\0' || new_buffer[x+3]=='\0' || new_buffer[x+4]=='\0' )
	      break;
				    
	    if( new_buffer[x]=='S' && new_buffer[x+1]=='I' && new_buffer[x+2]=='T' && new_buffer[x+3]=='E' && new_buffer[x+4]==' ' )
	    {
		gtk_list_store_set(GTK_LIST_STORE(widgets->directory_store), &iter, 10, 1, -1);
		break;
	    }
	}
    }

    if( strstr(new_buffer, "SITE_CHMOD") )
	gtk_list_store_set(GTK_LIST_STORE(widgets->directory_store), &iter, 11, 1, -1);

    if( strstr(new_buffer, "SITE_CHGRP") )
	gtk_list_store_set(GTK_LIST_STORE(widgets->directory_store), &iter, 12, 1, -1);

    if( strstr(new_buffer, "MTDM") )
	gtk_list_store_set(GTK_LIST_STORE(widgets->directory_store), &iter, 13, 1, -1);

    /* Show working directory. Cant strstr PWD for some reason ! */
    if( strstr(new_buffer, "WD") ) /* PWD and XPWD */
    {
	for(x=0; new_buffer[x]!='\0'; x++)
	{
	    if( new_buffer[x]=='\0' || new_buffer[x+1]=='\0' || new_buffer[x+2]=='\0' )
	      break;
				    
	    if( new_buffer[x]=='P' && new_buffer[x+1]=='W' && new_buffer[x+2]=='D' )
	    {
		gtk_list_store_set(GTK_LIST_STORE(widgets->directory_store), &iter, 14, 1, -1);
		break;
	    }
	}
    }
			    
    if( strstr(new_buffer, "SIZE") )
	gtk_list_store_set(GTK_LIST_STORE(widgets->directory_store), &iter, 15, 1, -1);

    if( strstr(new_buffer, "STAT") )
	gtk_list_store_set(GTK_LIST_STORE(widgets->directory_store), &iter, 16, 1, -1);

    if( strstr(new_buffer, "CWD") && strstr(new_buffer, "XCWD") )
	gtk_list_store_set(GTK_LIST_STORE(widgets->directory_store), &iter, 17, 1, -1);

    if( strstr(new_buffer, "CDUP") && strstr(new_buffer, "XCUP") )
	gtk_list_store_set(GTK_LIST_STORE(widgets->directory_store), &iter, 18, 1, -1);
}



void populate_user_settings(struct w *widgets)
{
    FILE *fp;
    gchar *utf8=NULL;
    gchar *info;
    GtkTreeIter iter;
    char *new_buffer, *old_buffer, *user_buffer, *address_buffer;
    char *port_buffer, *spinval;
    long conf_size;
    int found = 0, homedir_vals_set = 0, i = 0, x = 0;
    int stats_checked = 1;
    gint spinvalue = 0;
    gchar *username, *what, *val;

    /* Clear the directory treeview */
    gtk_list_store_clear(GTK_LIST_STORE(widgets->directory_store));

    username = g_strdup_printf("%s", global_user_name);


    /* Always set an empty password */
    gtk_entry_set_text(GTK_ENTRY(widgets->user_set_entry[1]), "");


    /* Set all widget values to default if no user is selected */
    info = g_strdup_printf("%s", global_user_name);
    if( info == NULL || strlen(info) < 1 )
    {
	/* User */
	gtk_entry_set_text(GTK_ENTRY(widgets->user_set_entry[0]), "");

	/* Password */
	gtk_entry_set_text(GTK_ENTRY(widgets->user_set_entry[1]), "");

	/* Group */
	gtk_entry_set_text(GTK_ENTRY(widgets->user_set_entry[2]), "");

	/* Comment */
	gtk_entry_set_text(GTK_ENTRY(widgets->user_set_entry[3]), "");

	/* Home directory */
	gtk_entry_set_text(GTK_ENTRY(widgets->user_set_entry[4]), "/var/ftp");

	/* Shell */
	gtk_combo_box_set_active(GTK_COMBO_BOX(widgets->user_set_combo[0]), 0);

	/* Require password */
        gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(widgets->user_set_checkbutton[1]), TRUE);

	/* Show user in statistics */
        gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(widgets->user_set_checkbutton[2]), TRUE);

	/* Max logins */
	gtk_spin_button_set_value(GTK_SPIN_BUTTON(widgets->user_set_spinbutton[0]), 10);

	/* Allow logins from */
	gtk_entry_set_text(GTK_ENTRY(widgets->user_set_entry[5]), "All");
    }
    g_free(info);


    if((fp=fopen(PROFTPD_CONF, "r"))==NULL)
    {
	info = g_strdup_printf(_("Error reading the configuration here:\n%s\n"), PROFTPD_CONF);
	show_info(info);
	g_free(info);
        return;
    }
    fseek(fp, 0, SEEK_END);
    conf_size = ftell(fp);
    rewind(fp);

    old_buffer = allocate(conf_size);
    new_buffer = allocate(conf_size);   
    user_buffer = allocate(4096);
    address_buffer = allocate(8192);
    port_buffer = allocate(8192);


    /* Set the banned checkbuttons state */
    if( is_banned(global_user_name) )
       gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(widgets->user_set_checkbutton[0]), TRUE);
    else
       gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(widgets->user_set_checkbutton[0]), FALSE);


    /* Dont match a similar user */
    sprintf(user_buffer, "User %s\n", global_user_name);


    if( strstr((char *)global_server_type, "Virtualhost") )
       sprintf(address_buffer, "<VirtualHost %s>\n", global_server_address);
    else
       sprintf(address_buffer, global_server_address);
     
    sprintf(port_buffer, "Port %s\n", global_server_port);


    /* Scroll to the selected vhost */
    if( strstr((char *)global_server_type, "Virtualhost") )
    {
	if( conf_size > 1 )
	while(fgets(old_buffer, conf_size, fp)!=NULL)
	{
	    /* If its the correct address */
	    if( ! strcmp(old_buffer, address_buffer) )
	    {
	       while(fgets(old_buffer, conf_size, fp)!=NULL)
	       {
		  /* This server was not the right one */
		  if( strstr(old_buffer, "</VirtualHost>") )
		    break;
		 
		  if( ! strcmp(old_buffer, port_buffer) )
		  {
		     found = 1;
	             break;
	          }
	       }
	    }
	    if( found )
	      break;
	}
    }


    /* We have scrolled to a vhost or just began at the top */
    found = 0;

    if( conf_size > 1 )
    while(fgets(old_buffer, conf_size, fp)!=NULL)
    {
	/* Pick up all <Anonymous (with the the root directory) */
	if( strstr(old_buffer, "<Anonymous") )
          strcpy(new_buffer, old_buffer);

	if( strlen(old_buffer) > 4000 )
	{
	    info = g_strdup_printf(_("A line with over 4000 chars is not valid in:\n%s\n"), PROFTPD_CONF);
	    show_info(info);
	    fclose(fp);
	    free(old_buffer);
	    free(new_buffer);
	    free(user_buffer);
	    free(address_buffer);
	    free(port_buffer);
	    free(info);
	    return;
	}


	/* We have found the correct user .. insert the settings */
	if( ! strcmp(old_buffer, user_buffer) && ! strstr(old_buffer, "AllowUser")
        &&  ! strstr(old_buffer, "DenyUser") && ! strstr(old_buffer, "FakeUser") )
	{

		/* Insert the root directory to the directory treeview (collected in the loop above) */
		new_buffer[strlen(new_buffer)-2]='\0';
		utf8 = g_locale_to_utf8(&new_buffer[11], strlen(&new_buffer[11]), NULL, NULL, NULL);
		gtk_list_store_append(GTK_LIST_STORE(widgets->directory_store), &iter);
		gtk_list_store_set(GTK_LIST_STORE(widgets->directory_store), &iter, 0, utf8, -1);

		/* Insert the root directory into the entry */
		gtk_entry_set_text(GTK_ENTRY(widgets->user_set_entry[4]), utf8);

		/* Username on the line after <Anonymous /var/ftp/dir> (cant be set before root dir) */
		sscanf(old_buffer, "%*s %s", new_buffer);
		utf8 = g_locale_to_utf8(new_buffer, strlen(new_buffer), NULL, NULL, NULL);
		gtk_entry_set_text(GTK_ENTRY(widgets->user_set_entry[0]), utf8);


		found = 1;



		/* Insert all the standard values like user, group etc */
		while(fgets(old_buffer, conf_size, fp)!=NULL)
		{
    		    if( strstr(old_buffer, "Group") && found ) 
    		    {
			sscanf(old_buffer, "%*s %s", new_buffer);
			utf8 = g_locale_to_utf8(new_buffer, strlen(new_buffer), NULL, NULL, NULL);
			gtk_entry_set_text(GTK_ENTRY(widgets->user_set_entry[2]), utf8);
    		    }

    		    if( strstr(old_buffer, "AnonRequirePassword") && found ) 
    		    {
			sscanf(old_buffer, "%*s %s", new_buffer);
			
			if( strstr(new_buffer, "off") ) /* cant use 'on' so this is reversed */
    			  gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(widgets->user_set_checkbutton[1]), FALSE);
			else
    			  gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(widgets->user_set_checkbutton[1]), TRUE);
    		    }

    		    if( strstr(old_buffer, "Allow from") && found )
    		    {
        		strcpy(new_buffer, old_buffer);
			for(i=0; new_buffer[i]!='\0'; i++)
			{
			    if( new_buffer[i-2]=='m' )
			    {
				new_buffer[strlen(new_buffer)-1]='\0';
				utf8 = g_locale_to_utf8(&new_buffer[i], strlen(&new_buffer[i]), NULL, NULL, NULL);
				gtk_entry_set_text(GTK_ENTRY(widgets->user_set_entry[5]), utf8);
				break;
			    }
			    if( i > 1000 )
		    	      break;
			}	    
    		    }

    		    if( strstr(old_buffer, "MaxClients") && found )
    		    {
			for(x=0; old_buffer[x]!='\0'; x++)
			{
	    	    	   if( old_buffer[x]=='"' )
		    	     break;
			}
			x++;
			if( old_buffer[x]!='\0' )
	    	          sprintf(new_buffer, "%s", &old_buffer[x]);
			for(x=0; new_buffer[x]!='\0'; x++)
			{
	    	    	    if( new_buffer[x]=='"' )
	    	    	    {
				new_buffer[x]='\0';
				break;
		    	    }
			}
			/* Max clients spinbutton */
			spinval = allocate(4096);
			sscanf(old_buffer, "%*s %s", spinval);
			if( chars_are_digits(spinval) )
			{
			    spinvalue = atoi(spinval);
			    gtk_spin_button_set_value(GTK_SPIN_BUTTON(widgets->user_set_spinbutton[0]), spinvalue);
    			}
			free(spinval);
		    }

		    
		    /* AllowOverwite setting in the directory treeview for the root directory */
		    if( strstr(old_buffer, "AllowOverwrite on") )
		      gtk_list_store_set(GTK_LIST_STORE(widgets->directory_store), &iter, 6, 1, -1);


		    /* Append the Home directory values */
		    if( strstr(old_buffer, "<Limit") 
		    && ! strstr(old_buffer, "<Limit LOGIN") 
		    && homedir_vals_set == 0 )
		    {
        		strcpy(new_buffer, old_buffer);
			while(fgets(old_buffer, conf_size, fp)!=NULL)
			{
			    if( strstr(old_buffer, "Allow") )
			    {
				homedir_vals_set = 1;
				set_toggle_values(new_buffer, iter, widgets);
			    }
			    /* Break in any case */
			    break;
			}
		    }


		    /* Append other directories to the directory treeview */
		    if( strstr(old_buffer, "<Directory ") && found )
		    {
        		strcpy(new_buffer, old_buffer);
			for(i=0; new_buffer[i]!='\0'; i++)
			{
	    		    /* "y " */
			    if( new_buffer[i-2]=='y' )
			    {
				new_buffer[strlen(new_buffer)-2]='\0';
				utf8 = g_locale_to_utf8(&new_buffer[i], strlen(&new_buffer[i]), NULL, NULL, NULL);

				/* Append the directory */
				gtk_list_store_append(GTK_LIST_STORE(widgets->directory_store), &iter);
    				gtk_list_store_set(GTK_LIST_STORE(widgets->directory_store), &iter, 0, utf8, -1);

				break;
			    }
			    if( i > 1000 )
		    	      break;
			}	    

			/* List settings for this directory */
			while(fgets(old_buffer, conf_size, fp)!=NULL)
			{
			    if( strstr(old_buffer, "</Directory") 
			    ||  strstr(old_buffer, "</Anonymous")
			    ||  strstr(old_buffer, "</Limit") )
		    	      break;


			    /* AllowOverwite on/off directory treeview checkbutton */
			    if( strstr(old_buffer, "AllowOverwrite on") )
		    	      gtk_list_store_set(GTK_LIST_STORE(widgets->directory_store), &iter, 6, 1, -1);
			    
			    /* Save the allow limit line with the cmds */
			    if( strstr(old_buffer, "<Limit") )
			    {
			        snprintf(new_buffer, 1000, "%s", old_buffer);

				while(fgets(old_buffer, conf_size, fp)!=NULL)
				{

				    if( strstr(old_buffer, "</Directory") 
				    ||  strstr(old_buffer, "</Anonymous")
				    ||  strstr(old_buffer, "</Limit") )
			    	      break;
				      


				    if( strstr(old_buffer, "Allow") && ! strstr(old_buffer, "AllowOverwrite") )
				    {
					/* We have a limit allow directive (with cmds, FIXME) */
					set_toggle_values(new_buffer, iter, widgets);
					break;
				    }
				}
				/* We can add more limit types here */
			    }
			}
		    }   /* If the line contained "<Directory" and the user is found end. */
		    

		    if( strstr(old_buffer, "#gplockstats") && found )
		      stats_checked = 0;
		    
		
		    /* The user has been listed .. break */
		    if( strstr(old_buffer, "</Anonymous") )
		      break;
		}
	}
	
	if( found )
	  break;
    }
    fclose(fp);
    free(old_buffer);
    free(new_buffer);
    free(user_buffer);
//    gtk_tree_path_free(path);


    /* Statistics checkbutton */
    if( stats_checked )
      gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(widgets->user_set_checkbutton[2]), TRUE);
    else
      gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(widgets->user_set_checkbutton[2]), FALSE);


    /* Get and insert the users comment */
    what = g_strdup_printf("comment");
    val = get_user_setting(username, what);
    gtk_entry_set_text(GTK_ENTRY(widgets->user_set_entry[3]), val);
    g_free(what); g_free(val);


    /* Get the users shell, itll be the selected shell in the combo */
    what = g_strdup_printf("shell");
    val = get_user_setting(username, what);
    g_free(what);

    /* Select the shell we just got in the shell combo box */
    GtkListStore *shell_store;
    shell_store = GTK_LIST_STORE (gtk_combo_box_get_model(GTK_COMBO_BOX(widgets->user_set_combo[0])));

    if( shell_store )
    {
        GtkTreeIter shell_iter;
        gchar *shell;

        if( gtk_tree_model_get_iter_first(GTK_TREE_MODEL(shell_store), &shell_iter) )
        {
            do {
                    gtk_tree_model_get(GTK_TREE_MODEL(shell_store), &shell_iter, 0, &shell, -1);
                    if( shell )
                    {
                        if( ! strcmp(val, shell) )
                        {
                            gtk_combo_box_set_active_iter(GTK_COMBO_BOX(widgets->user_set_combo[0]), &shell_iter);
                            break;
                        }
                    }
               }    while(gtk_tree_model_iter_next(GTK_TREE_MODEL(shell_store), &shell_iter));
	}
    }
    g_free(val);

    if( utf8!=NULL )
      g_free(utf8);


    gtk_widget_show_all(widgets->main_window);
}
