/*
 * This file is part of the FEddi package
 *
 * Personal use allowed under the terms of the
 *
 *              GNU GENERAL PUBLIC LICENSE Version 2
 *              (see LICENSE for the complete text)
 *
 *-------------------------------------------------------------------
 *
 *    ENTER AT YOUR OWN RISK !!
 *
 * This source is without any documentation and can drive you mad.
 * In case of sudden epileptic seizures please call your doctor.
 *
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ncurses.h>
#include <signal.h>
#include <sys/stat.h>
#include "structs.h"
#include "proc.h"

#define NIL -1

NLentryType *Entries;
int maxEntries;

void searchstr(FILE *, FILE *, char *, int);
int getentry(FILE *, int, NLentryType *);
void freeentry(NLentryType *);

void searchstr(FILE *fi, FILE *fl, char *x, int a)
{
	int i, back=0;
	StrIndexType ind;
	NLentryType ent;
	char name[100];
	
	if (a!=NIL)
	{
		fseek(fi,4+StrIndexSize*a,SEEK_SET);
		fread(&ind,StrIndexSize,1,fi);
		for (i=0; i<ind.num && !back; i++)
		{
			getentry(fl,ind.entry[i].pos,&ent);
			strcpy(name,ent.Sysop);
			freeentry(&ent);
			if (strncasecmp(name,x,strlen(x))==0)
			{
				if (i==0)
					searchstr(fi,fl,x,ind.next0);
				else
					searchstr(fi,fl,x,ind.entry[i-1].next);
				maxEntries++;
				Entries=(NLentryType *)realloc(Entries,NLentrySize*maxEntries);
				getentry(fl,ind.entry[i].pos,&Entries[maxEntries-1]);
			} else
				if (strncasecmp(name,x,strlen(x))>0)
				{
					back=1;
					if (i==0)
						searchstr(fi,fl,x,ind.next0);
					else
						searchstr(fi,fl,x,ind.entry[i-1].next);
				}
		}
		if (!back)
			searchstr(fi,fl,x,ind.entry[i-1].next);
	}
} 

int getentry(FILE *fl, int pos, NLentryType *e)
{
	char line[256], *d1, *d2;
	
	fseek(fl,pos,SEEK_SET);
	fgets(line,255,fl);
	d1=strchr(line,'\n');
	if (d1) *d1=0;
	switch (line[0])
	{
		case 'Z': e->Type=0; break;
		case 'R': e->Type=1; break;
		case 'H': e->Type=2; break;
		case 'U': e->Type=3; break;
		case 'V': e->Type=4; break;
		case 'O': e->Type=5; break;
		case 'D': e->Type=6; break;
		case 'N': e->Type=7; break;
		case 'P': e->Type=8; break;
		default : e->Type=255; break;
	}
	d1=strchr(line,',');
	*d1++=0;
	Str2Addr(&line[1],&(e->ad));
	d2=strchr(d1,',');
	*d2++=0;
	e->Box=(char *)malloc(strlen(d1)+1);
	strcpy(e->Box,d1);
	d1=strchr(d2,',');
	*d1++=0;
	e->Pos=(char *)malloc(strlen(d2)+1);
	strcpy(e->Pos,d2);
	d2=strchr(d1,',');
	*d2++=0;
	e->Sysop=(char *)malloc(strlen(d1)+1);
	strcpy(e->Sysop,d1);
	d1=strchr(d2,',');
	*d1++=0;
	e->Phone=(char *)malloc(strlen(d2)+1);
	strcpy(e->Phone,d2);
	d2=strchr(d1,',');
	if (d2)
	{
		*d2++=0;
		e->Flags=(char *)malloc(strlen(d2)+1);
		strcpy(e->Flags,d2);
	} else e->Flags=NULL;
	e->Speed=atoi(d1);
	return 0;
}

int keyentry(char *addr, NLentryType *e)
{
	FILE *fl, *fi;
	char file[PATH_MAX], *d1;
	int pos, prim, ok=0, j, q;
	long long int key;
	struct stat st;
	
	sprintf(file,"%sfnlc.Nodeindex",NodelistPath);
	stat(file,&st);
	prim=st.st_size/sizeof(int);
	if ((fi=fopen(file,"rb"))!=NULL)
	{
		sprintf(file,"%sfnlc.Userlist",NodelistPath);
		if ((fl=fopen(file,"rt"))!=NULL)
		{
			key=getkey(addr);
			j=(key%prim)+1;
			q=(key%79)+1;
			do
			{
				fseek(fi,(j-1)*sizeof(int),SEEK_SET);
				fread(&pos,sizeof(int),1,fi);
				if (pos==-1) break;
				fseek(fl,pos,SEEK_SET);
				fgets(file,255,fl);
				d1=strchr(file,',');
				*d1=0;
				j=((j+q)%prim)+1;
			} while (key!=getkey(&file[1]));
			if (pos!=-1)
				getentry(fl,pos,e);
			else
				ok=1;
			fclose(fl);
		} else
			ok=1;
		fclose(fi);
	} else
		ok=1;
	return ok;
}

int nameentry(char *name, NLentryType *e, int freeit)
{
	FILE *fl, *fi;
	char file[PATH_MAX], *d1, *n;
	int pos=0, root, notok=0, x;
	
	sprintf(file,"%sfnlc.Nameindex",NodelistPath);
	if ((fi=fopen(file,"rb"))!=NULL)
	{
		sprintf(file,"%sfnlc.Userlist",NodelistPath);
		if ((fl=fopen(file,"rt"))!=NULL)
		{
			n=(char *)malloc(strlen(name)+1);
			strcpy(n,name);
			d1=strchr(n,32);
			if (d1)
			{
				*d1++=0;
				strcpy(file,d1);
				strcat(file," ");
				strcat(file,n);
			} else strcpy(file,n);
			fseek(fi,0,SEEK_SET);
			fread(&root,sizeof(int),1,fi);
			maxEntries=0;
			searchstr(fi,fl,file,root);
			fclose(fl);
			if (maxEntries==1)
				*e=Entries[0];
			else
				notok=1;
			free(n);
		} else
			notok=1;
		fclose(fi);
	} else
		notok=1;
	if (freeit)
		for (x=0; x<maxEntries; x++)
			if (x!=pos || notok) freeentry(&Entries[x]);
	return notok;
}

void freeentry(NLentryType *e)
{
	free(e->Box);
	free(e->Pos);
	free(e->Sysop);
	free(e->Phone);
	free(e->Flags);
}
