/* GADMIN-PROFTPD - An easy to use GTK+ frontend for the ProFTPD standalone server.
 * Copyright (C) 2001 - 2008 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 <gtk/gtk.h>
#include "support.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "allocate.h"
#include "widgets.h"
#include <dirent.h>
#include "chars_are_digits.h"
#include "commands.h"
#include "status_update.h"
#include "show_info.h"

extern int activated;
extern int MAX_READ_POPEN;



char * get_process_pid(char process[1024], char extmatch[1024])
{
    FILE *fp;
    long num, file_size = 4000;
    char *line, *sub_proc_path, *pid;
    int x=0;
    struct dirent **namelist;

    pid = allocate(1024);
    strcpy(pid, "0");
    
    sub_proc_path = allocate(1024);

    num = scandir(PROC_PATH, &namelist, 0, alphasort);
    if( num < 0 )
    {
        perror("scandir");
        return pid;
    }
    else
    {
        /* List all directories in PROC_PATH */
        for(x=0; x<num; x++)
        {
	    /* Now list PROC_PATH/24207/cmdline */
	    snprintf(sub_proc_path, 1000, "%s/%s/cmdline", PROC_PATH, namelist[x]->d_name);

	    if((fp=fopen(sub_proc_path, "r"))==NULL)
	    {
        	free(namelist[x]);
	        continue;
	    }
	    line = allocate(file_size+1);
	    
	    if( file_size > 1 )
	    while(fgets(line, file_size, fp)!=NULL)
	    {
		/* If the following strings are detected in this file its running */
		if( strstr(line, process) && strstr(line, extmatch) )
		{
		    snprintf(pid, 1000, "%s", namelist[x]->d_name);
		    break;
		}
	    }
	    fclose(fp);
	    free(line);
            free(namelist[x]);
	}
    }
    free(namelist);
    free(sub_proc_path);

    return pid;
}



int status_update(struct w *widgets)
{
    /* Status update for ftpwho, total transfer rates and activated/deactivated status. */
    FILE *fp;
    GtkTreeIter iter;
    long i=0, in_val=0, out_val=0, inxfer=0, outxfer=0, totalxfer=0;
    int incoming=0, outgoing=0;
    char *line, *tmp;
    gchar *info, *path, *cmd, *utf8=NULL;

    char *pid;
    pid = get_process_pid("proftpd", "accepting connections");

    if( strcmp(pid, "0") == 0 )
    {
	activated = 0;
	info = g_strdup_printf(_("Status: Deactivated"));
	utf8 = g_locale_to_utf8(info, strlen(info), NULL, NULL, NULL);
	gtk_label_set_text(GTK_LABEL(widgets->status_label), utf8);
	g_free(info);
	if( utf8!=NULL )
	  g_free(utf8);

	/* Show non ftp usage */    
        info = g_strdup_printf(_("The server is deactivated.\n"));
	utf8 = g_locale_to_utf8(info, strlen(info), NULL, NULL, NULL);


//	transfer_textbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widgets->transfer_textview));
//	gtk_text_buffer_set_text(transfer_textbuffer, utf8, strlen(utf8));


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

	return (TRUE);
    }
    else
      {
	  activated = 1;
	  /* printf("Proftpd is running as pid: %s\n", pid); */
	  info = g_strdup_printf(_("Status: Activated"));
    	  utf8 = g_locale_to_utf8(info, strlen(info), NULL, NULL, NULL);
    	  gtk_label_set_text(GTK_LABEL(widgets->status_label), utf8);
	  g_free(info);
	  if( utf8!=NULL )
	    g_free(utf8);
      }
    free(pid);



    /* The server is activated, insert ftpwho information in the treeview */

    
    /* Add the scoreboard file if its missing to avoid useless message */
    path = g_strdup_printf("%s/%s", GP_VARDIR, "run/proftpd");
    if( file_exists(path) )
    {
        g_free(path);

	path = g_strdup_printf("%s/%s", GP_VARDIR, "run/proftpd/proftpd.scoreboard");
        if( ! file_exists(path) )
        {
            cmd = g_strdup_printf("echo \"NOTHING\" > %s/%s", GP_VARDIR, "run/proftpd/proftpd.scoreboard");
            run_command(cmd);
            g_free(cmd);
        }
    }
    g_free(path);

    /* Again in another common location */
    path = g_strdup_printf("%s/%s", GP_VARDIR, "proftpd");
    if( file_exists(path) )
    {
        g_free(path);

        path = g_strdup_printf("%s/%s", GP_VARDIR, "proftpd/proftpd.scoreboard");
        if( ! file_exists(path) )
        {
            cmd = g_strdup_printf("echo \"NOTHING\" > %s/%s", GP_VARDIR, "proftpd/proftpd.scoreboard");
            run_command(cmd);
            g_free(cmd);
        }
    }
    g_free(path);



    /* FTP who update and total xferrates */
    
    gtk_list_store_clear(GTK_LIST_STORE(widgets->transfer_store));
    
    
    cmd = g_strdup_printf("%s -v", FTPWHO_BINARY);
    if((fp=popen(cmd, "r"))==NULL)
    {

	/* Show ftpwho error information in the textview */    
        info = g_strdup_printf(_("Error running ftpwho -v.\n"));
	utf8 = g_locale_to_utf8(info, strlen(info), NULL, NULL, NULL);


//	transfer_textbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widgets->transfer_textview));
//	gtk_text_buffer_set_text(transfer_textbuffer, utf8, strlen(utf8));


        g_free(cmd);
	g_free(info);
	if( utf8!=NULL )
	  g_free(utf8);
	
        return(TRUE);
    }
    g_free(cmd);
    fflush(fp);

    line = allocate(MAX_READ_POPEN+1);
    tmp  = allocate(MAX_READ_POPEN+20000); /* +20000 for translations and filenames */

    while(fgets(line, MAX_READ_POPEN, fp)!=NULL)
    {	
	if( line==NULL || strlen(line) < 10
	|| strstr(line, "FTP daemon [")  || strstr(line, "up for")
	|| strstr(line, "Service class") || strstr(line, "no users connected") )
	  continue;

	if( strstr(line, " idle") /* idle is located at the end of the line */ 
	||  strstr(line, " STOR ") 
	||  strstr(line, " STOU ") 
	||  strstr(line, " APPE ") 
	||  strstr(line, " DELE ") 
	||  strstr(line, " RETR ") )
	{
	    gtk_list_store_append(GTK_LIST_STORE(widgets->transfer_store), &iter);
	
	    /* The line looks like this:
	       7154 test [ 0m27s] (n/a) APPE 05 - Soundfile.ogg */
	    
	    /* Insert PID */
	    sscanf(line, "%s", tmp);
	    utf8 = g_locale_to_utf8(tmp, strlen(tmp), NULL, NULL, NULL);
	    gtk_list_store_set(GTK_LIST_STORE(widgets->transfer_store), &iter, 0, utf8, -1);
	    if( utf8!=NULL )
	      g_free(utf8);

	    /* Insert Username */
	    sscanf(line, "%*s %s", tmp);
	    utf8 = g_locale_to_utf8(tmp, strlen(tmp), NULL, NULL, NULL);
	    gtk_list_store_set(GTK_LIST_STORE(widgets->transfer_store), &iter, 1, utf8, -1);
	    if( utf8!=NULL )
	      g_free(utf8);

	    /* Insert Action */
	    if( strstr(line, " idle") )
	      snprintf(tmp, 100, "%s", _("Idle"));
	    if( strstr(line, " APPE ") || strstr(line, " STOR ") || strstr(line, " STOU ") )
	      snprintf(tmp, 100, "%s", _("Uploading"));
	    if( strstr(line, " RETR ") )
	      snprintf(tmp, 100, "%s", _("Downloading"));
	    if( strstr(line, " DELE ") )
	      snprintf(tmp, 100, "%s", _("Deleting"));

	    utf8 = g_locale_to_utf8(tmp, strlen(tmp), NULL, NULL, NULL);
	    gtk_list_store_set(GTK_LIST_STORE(widgets->transfer_store), &iter, 2, utf8, -1);
	    if( utf8!=NULL )
	      g_free(utf8);

	    /* Insert filename and handle split filenames */
	    if( ! strstr(line, " idle") )
	    for(i=0; line[i]!='\0'; i++)
	    {
		if( line[i]=='A' && line[i+1]=='P' && line[i+2]=='P' && line[i+3]=='E'  )
	    	{
		    snprintf(tmp, 16384, "%s", &line[i+5]);
		    break;
		}
		if( line[i]=='S' && line[i+1]=='T' && line[i+2]=='O' && line[i+3]=='R'  )
	    	{
		    snprintf(tmp, 16384, "%s", &line[i+5]);
		    break;
		}
		if( line[i]=='S' && line[i+1]=='T' && line[i+2]=='O' && line[i+3]=='U'  )
	    	{
		    snprintf(tmp, 16384, "%s", &line[i+5]);
		    break;
		}
		if( line[i]=='R' && line[i+1]=='E' && line[i+2]=='T' && line[i+3]=='R'  )
	    	{
		    snprintf(tmp, 16384, "%s", &line[i+5]);
		    break;
		}
		if( line[i]=='D' && line[i+1]=='E' && line[i+2]=='L' && line[i+3]=='E'  )
	    	{
		    snprintf(tmp, 16384, "%s", &line[i+5]);
		    break;
		}
	    }
	    if( strstr(line, " idle") )
	      snprintf(tmp, 16384, "%s", "None");

	    if( tmp[strlen(tmp)-1]=='\n' )
	        tmp[strlen(tmp)-1]='\0';
	    
	    utf8 = g_locale_to_utf8(tmp, strlen(tmp), NULL, NULL, NULL);
	    gtk_list_store_set(GTK_LIST_STORE(widgets->transfer_store), &iter, 5, utf8, -1);
	    if( utf8!=NULL )
	      g_free(utf8);
	}

        /* Total Xferrates incoming/outgoing/total bandwidth usage */
        /* Assumes that the ftpwho output shows stor retr appe and on the next line KB/s */
		
        /* Incoming transfers */
        if(  strstr(line, "KB/s: ") && incoming == 1 
        && ! strstr(line, "inf") && ! strstr(line, "nan") )
        {
	    if( chars_are_digits(&line[7]) )
	    {
	        sscanf(line, "%*s %li", &in_val);
	    }
	    
	    if( in_val > 0 )
	    {
		inxfer = inxfer+in_val;
		totalxfer = totalxfer+in_val;
	    }
	}

	if( strstr(line, "KB/s: ") && ! strstr(line, "inf") && ! strstr(line, "nan") )
	{
	    /* Insert KB/s */
	    snprintf(tmp, 100, "%s", &line[7]);
	    if( tmp[strlen(tmp)-1]=='\n' )
        	tmp[strlen(tmp)-1]='\0';
	    utf8 = g_locale_to_utf8(tmp, strlen(tmp), NULL, NULL, NULL);
	    gtk_list_store_set(GTK_LIST_STORE(widgets->transfer_store), &iter, 3, utf8, -1);
	    if( utf8!=NULL )
	      g_free(utf8);
	}
	if( strstr(line, "client: ") )
	{
	    /* Insert Client address */
	    sscanf(line, "%*s %s", tmp);
	    utf8 = g_locale_to_utf8(tmp, strlen(tmp), NULL, NULL, NULL);
	    gtk_list_store_set(GTK_LIST_STORE(widgets->transfer_store), &iter, 6, utf8, -1);
	    if( utf8!=NULL )
	      g_free(utf8);
	}
	if( strstr(line, "server: ") )
	{
	    /* Insert Server address */
	    sscanf(line, "%*s %s", tmp);
	    utf8 = g_locale_to_utf8(tmp, strlen(tmp), NULL, NULL, NULL);
	    gtk_list_store_set(GTK_LIST_STORE(widgets->transfer_store), &iter, 7, utf8, -1);
	    if( utf8!=NULL )
	      g_free(utf8);
	}
	if( strstr(line, "location: ") )
	{
	    /* Insert directory location */
	    sscanf(line, "%*s %s", tmp);
	    utf8 = g_locale_to_utf8(tmp, strlen(tmp), NULL, NULL, NULL);
	    gtk_list_store_set(GTK_LIST_STORE(widgets->transfer_store), &iter, 4, utf8, -1);
	    if( utf8!=NULL )
	      g_free(utf8);
	}


	if( strstr(line, " STOR ") || strstr(line, " STOU ") || strstr(line, " APPE ") )
	  incoming++;
	else
	  incoming = 0;
	
	/* Outgoing transfers */
	if(  strstr(line, "KB/s: ") && outgoing == 1 
	&& ! strstr(line, "inf") && ! strstr(line, "nan") )
	{
	    if( chars_are_digits(&line[7]) )
	      sscanf(line, "%*s %li", &out_val);

	    if( out_val > 0 )
	    {
	        outxfer = outxfer+out_val;
	        totalxfer = totalxfer+out_val;
	    }
	}

	if( strstr(line, " RETR ") )
	  outgoing++;
	else
	  outgoing = 0;
    }
    pclose(fp);
    free(line);
    free(tmp);

    
    /* Total bandwidth usage */
    if( totalxfer >= 0 )
    {
	info = g_strdup_printf("\t\t %s %li", _(" Total KB/s: "), totalxfer);
        utf8 = g_locale_to_utf8(info, strlen(info), NULL, NULL, NULL);

	gtk_label_set_text(GTK_LABEL(widgets->total_bandwidth_label), utf8);

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

    /* Total incoming xfers */
    if( inxfer >= 0 )
    {    
        info = g_strdup_printf("\t\t\t %s %li", _(" Incoming KB/s: "), inxfer);
        utf8 = g_locale_to_utf8(info, strlen(info), NULL, NULL, NULL);

	gtk_label_set_text(GTK_LABEL(widgets->total_incoming_label), utf8);

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

    /* Total outgoing xfers */
    if( outxfer >= 0 )
    {
        info = g_strdup_printf("\t\t\t %s %li", _(" Outgoing KB/s: "), outxfer);
        utf8 = g_locale_to_utf8(info, strlen(info), NULL, NULL, NULL);

	gtk_label_set_text(GTK_LABEL(widgets->total_outgoing_label), utf8);

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

    return(TRUE);
}
