/*
 *      file.c from Access Point SNMP Utils for Linux
 * file accessing functions
 *
 * Copyright (c) 2002 Roman Festchook <roma at polesye dot net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2 from
 * June 1991 as published by the Free Software Foundation.
 *
 * 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 <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include "ap-utils.h"

extern WINDOW *main_sub, *win_for_help, *main_win;
extern char *ap_types[], *ap_vendorexts[][3];
extern short ap_type, ap_vendorext;
extern struct in_addr ap_ip;
extern int atmel410_filter;

#define MAX_LINES LINES-6

struct APList {
    char *ip;
    char *passwd;
    int type;
    int vendorext;
    char *label;

    struct APList * next;
};

void
_scroll_rows(struct APList *first, int begin, int end)
{
    int i = 1;
    struct APList *curr = first;
    char message[80];

    clear_main(3);

    while (i++ < begin)
        curr = curr->next;

    i = 0;
    while (end-- > begin) {
	sprintf(message, "  %3u  %-15s  %-10s  %-8s  %-16s", begin + i,
	    curr->ip, ap_types[curr->type],
	    ap_vendorexts[curr->type][curr->vendorext], curr->label);
	mvwaddstr(main_sub, 2 + i, 0, message);
	i++;
	curr = curr->next;
    }
    wrefresh(main_sub);
}

struct APList *parse_db_str(char *str)
{
    struct APList *curr=NULL;
    char *ip=NULL, *passwd=NULL, *label=NULL, *aptype=NULL, mess[1024];
    int i=0, pos=0, j=0;

    while(str[i] != '\0') {
	if(str[i] == ':') {
	    switch (pos) {
		case 0: 
		    ip = (char *) malloc(j+1);
		    memcpy(ip, mess, j+1);
		    ip[j] = '\0';
		    break;
		case 1:
		    passwd = (char *) malloc(j+1);
		    memcpy(passwd, mess, j+1);
		    passwd[j] = '\0';
		    break;
		case 2:
		    label = (char *) malloc(j+1);
		    memcpy(label, mess, j+1);
		    label[j > 16 ? 16 : j] = '\0';
		    break;
		case 3:
		    aptype = (char *) malloc(j+1);
		    memcpy(aptype, mess, j+1);
		    aptype[j] = '\0';
		    break;
	    }
	    i++;
	    j=0;
	    pos++;
	} else
	    mess[j++] = str[i++];

    }

    mess[j]='\0';
    if (pos==4 && ip && passwd && ((atmel410_filter && atoi(aptype) == ATMEL410)
	|| !atmel410_filter)) {
	curr = (struct APList *) malloc(sizeof(struct APList));
	curr->type = atoi(aptype);
	curr->vendorext = atoi(mess);
	curr->next = NULL;
	curr->ip = (char *) malloc(strlen(ip) + 1);
	strcpy(curr->ip, ip);
	curr->passwd = (char *) malloc(strlen(passwd) + 1);
	strcpy(curr->passwd, passwd);
	curr->label = (char *) malloc(strlen(label) + 1);
	strcpy(curr->label, label);
    }

    if (ip)
	free(ip);

    if (passwd)
	free(passwd);

    if (label)
	free(label);

    if (aptype)
	free(aptype);

    return curr;
}

int get_opts()
{
    extern char *community;
    extern struct in_addr ap_ip;

    char *home_dir, buf[1024], mess[64];
    char message[50];
    int c, fd, rval = 0, pos;
    signed int j, i, begin, end, record_num = 0;
    struct APList *first = NULL, *curr = NULL, *pmac; 


    if ((home_dir = getenv("HOME")) == NULL)
	return 0;

    sprintf(buf, "%s/.ap-config", home_dir);
    if ((fd = open(buf, O_RDONLY)) == -1)
	return 0;

    pos=0;
    while((j = read(fd, buf, sizeof(buf))) > 0) 
	for(i=0; i < j; i++) {
	    if (buf[i] == 0x0a) {
		mess[pos]='\0';
		if (first == NULL) {
		    if ((first = parse_db_str(mess)) != NULL) {
			curr = first;
			record_num = 1;
		    }
		} else {
		    if ((curr->next = parse_db_str(mess)) != NULL) {
			curr = curr->next;
			record_num++;
		    }
		}
		pos=0;
	    } else	
		mess[pos++] = buf[i];

	}

    mess[pos]='\0';
    if (first == NULL) {
	if ((first = parse_db_str(mess)) != NULL) {
	    curr = first;
	    record_num = 1;
	}
    } else {
	if ((curr->next = parse_db_str(mess)) != NULL) 
	    curr = curr->next;

	record_num++;
    }

    close(fd);
    if (!record_num)
	return 0;

    mvwaddstr(main_sub, 0, 2,
	_("NUM  IP ADDRESS       MIB TYPE    MIB EXT.  LABEL"));
    print_top(NULL, _("Choose an AP to connect to"));
    begin = 1;
    end = (MAX_LINES < record_num) ? MAX_LINES : record_num;
    _scroll_rows(first, begin, end);
    noecho();
    while (1) {
	print_help(_("1-9,C: connect; N: new; D: delete; W: save; Q: quit; arrows: scroll"));
	switch (c = getch()) {
	    case 'q':
	    case 'Q':
		exit_program();

	    case 'n':
	    case 'N':
		goto quit;

	    case '0':
	    case '1':
	    case '2':
	    case '3':
	    case '4':
	    case '5':
	    case '6':
	    case '7':
	    case '8':
	    case '9':
		i = c - '0';
		if (record_num <= i || i <= 0)
		    goto wrong_num;

		curr = first;
		while (--i > 0)
		    curr = curr->next;

		inet_aton(curr->ip, &ap_ip);
		if (community)
		    free(community);

		i = strlen(curr->passwd) + 1;
		community = (char *) malloc(i);
		strncpy(community, curr->passwd, i);
		ap_type = curr->type;
		ap_vendorext = curr->vendorext;

		rval = 1;
		if (reopen_sockfd() == -1)
		    rval = 0;

		print_bottom(inet_ntoa(ap_ip));
		goto quit;

	    case 'c':
	    case 'C':
		/* Nothing to connect */
		if (record_num == 1)
		    continue;

		mvwaddstr(main_sub, 1, 1, _("Connect to AP num:"));
		get_value(message, 1, 20, 6, INT_STRING, 1, record_num - 1,
		    NULL);
		i = atoi(message);
		curr = first;
		while (--i > 0)
		    curr = curr->next;

		inet_aton(curr->ip, &ap_ip);
		if (community)
		    free(community);

		i = strlen(curr->passwd) + 1;
		community = (char *) malloc(i);
		strncpy(community, curr->passwd, i);
		ap_type = curr->type;
		ap_vendorext = curr->vendorext;

		rval = 1;
		if (reopen_sockfd() == -1)
		    rval = 0;

		print_bottom(inet_ntoa(ap_ip));
		goto quit;

	    case 'd':
	    case 'D':
		/* Nothing to delete */
		if (record_num == 1)
		    continue;

		mvwaddstr(main_sub, 1, 0, _("Delete num:"));
		get_value(message, 1, 15, 6, INT_STRING,
		    1, (record_num == 1 ? 1 : record_num - 1), NULL);
		i = atoi(message);
		if (i == 1) {
		    curr = first;
		    first = first->next;
		    free(curr->ip);
		    free(curr->passwd);
		    free(curr->label);
		    free(curr);
		} else {
		    curr = first;
		    while (--i > 1)
			curr = curr->next;

		    pmac = curr->next;
		    curr->next = pmac->next;
		    free(pmac->ip);
		    free(pmac->passwd);
		    free(pmac->label);
		    free(pmac);
		}
		record_num--;
		/* Clear incl. line with last AP record */
		if (record_num == 1) {
		    clear_main_new(1, 3);
		    continue;
		}

		begin = 1;
		end = (MAX_LINES < record_num) ? MAX_LINES : record_num;
		_scroll_rows(first, begin, end);
wrong_num:
		clear_main_new(1, 2);
		continue;

	    case KEY_DOWN:
	    case KEY_RIGHT:
		if (end < record_num) {
		    begin++;
		    end++;
		    _scroll_rows(first, begin, end);
		}
		continue;

	    case KEY_UP:
	    case KEY_LEFT:
		if (begin > 1) {
		    begin--;
		    end--;
		    _scroll_rows(first, begin, end);
		}
		continue;

	    case KEY_NPAGE:
		if (end < record_num) {
		    end = (end + (MAX_LINES) - 1 < record_num) ?
			end + (MAX_LINES) - 1 : record_num;
		    begin = (end - (MAX_LINES) + 1 > 0) ?
			end - (MAX_LINES) + 1 : 1;
		    _scroll_rows(first, begin, end);
		}
		continue;

	    case KEY_PPAGE:
		if (begin > 1) {
		    begin = (begin - (MAX_LINES) + 1 > 0) ?
			begin - (MAX_LINES) + 1 : 1;
		    end = (begin + (MAX_LINES) - 1 < record_num) ?
			begin + (MAX_LINES) - 1 : record_num;
		    _scroll_rows(first, begin, end);
		}
		continue;

	    case KEY_END:
		if (end < record_num) {
		    begin = (record_num > MAX_LINES) ? record_num + 1 - (MAX_LINES) : 1;
		    end = record_num;
		    _scroll_rows(first, begin, end);
		}
		continue;

	    case KEY_HOME:
		if (begin > 1) {
		    begin = 1;
		    end = (record_num > MAX_LINES) ? MAX_LINES : record_num;
		    _scroll_rows(first, begin, end);
		}
		continue;

	    case 'w':
	    case 'W':
		sprintf(buf, "%s/.ap-config", home_dir);
		if ((fd = creat(buf, 0600)) != -1) {
		    curr=first;
		    while (curr) {
			sprintf(buf, "%s:%s:%s:%d:%d\n", curr->ip, curr->passwd,
			    curr->label,curr->type, curr->vendorext);
			write(fd, buf, strlen(buf));
			curr = curr->next;
		    }
		    close(fd);
		    print_help(DONE_WRITING_APCONF);
		} else
		    print_helperr(ERR_WRITING_APCONF);

		getch();
		continue;
	}
    }
/*
    print_help(ANY_KEY);
    getch();
*/  quit:
    while ((curr = first)) {
	first = curr->next;
	free(curr->ip);
	free(curr->passwd);
	free(curr->label);
	free(curr);
    }
    print_help("");
    print_top(NULL, NULL);
    wclear(main_sub);
    wrefresh(main_sub);
    return rval;
}

void save_Stations(struct MacListStat *curr)
{
    int fd, err_f = 0;
    char *home_dir;
    char message[1024];
    if ((home_dir = getenv("HOME"))) {
	sprintf(message, "%s/ap-%s-%s-%s.stations", home_dir, inet_ntoa(ap_ip),
	    ap_types[ap_type],ap_vendorexts[ap_type][ap_vendorext]);
	if ((fd = creat(message, 0600)) != -1) {
	    while (curr) {
		sprintf(message, "%02X%02X%02X%02X%02X%02X\n",
		    curr->addr[0] & 0xFF, curr->addr[1] & 0xFF,
		    curr->addr[2] & 0xFF, curr->addr[3] & 0xFF,
		    curr->addr[4] & 0xFF, curr->addr[5] & 0xFF);
		write(fd, message, 13);
		curr = curr->next;
	    }
	    close(fd);
	} else {
	    err_f = 1;
	}
    } else {
	err_f = 1;
    }
    if (err_f)
	print_helperr(_("Unable to write stations file. Press any key."));
    else
	print_help(_("Stations file succesfully written. Press any key."));
    getch();
    print_help("");
}

