#include <stdio.h>
#include "struct.h"
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#ifdef DOS
#include <io.h>
#endif

extern struct UserRecord *LoadARecord(int,char *);
extern int WriteRecord(int,struct UserRecord *);
extern void Rewrite(int,struct UserRecord *);
extern int OpenUAF(void);
extern void CloseUAF(int);
extern struct UserRecord *FindUserRecord(char *);
extern struct UserRecord *FindFreeRecord(void);
extern int BuildRecord(ITEM,struct UserRecord *);
extern int CryptX(unsigned char *);

#ifndef O_BINARY
#define O_BINARY	0
#endif


/*
 *	Persona file operations
 */
 
struct UserRecord
{
	char ur_Name[11];
	tag ur_Data[128];
	long ur_PwKey;
};

static struct UserRecord *LoadARecord(fd,name)
int fd;
char *name;
{
	static struct UserRecord udef;
	while(1)
	{
		if(read(fd,&udef,sizeof(struct UserRecord))!=sizeof(struct UserRecord))
			return(NULL);
		if(strcmp(name,udef.ur_Name)==0)
			return(&udef);
	}
}

WriteRecord(fd,udef)
int fd;
struct UserRecord *udef;
{
	lseek(fd,0,2);
	if(write(fd,udef,sizeof(struct UserRecord))!=sizeof(struct UserRecord))
	{
		fprintf(stderr,"[OS ERROR]: ");
		perror("WriteRecord");
		exit(0);
	}
	return(1);
}


static void Rewrite(fd,udef)
int fd;
struct UserRecord *udef;
{
	if(lseek(fd,-sizeof(struct UserRecord),1)==-1)
	{
		fprintf(stderr,"[OS ERROR]: ");		
		perror("Rewrite seek");
		exit(0);
	}
	if(write(fd,udef,sizeof(struct UserRecord))!=sizeof(struct UserRecord))
	{
		fprintf(stderr,"[OS ERROR]: ");		
		perror("ReWriteRecord");
		exit(0);
	}
}


int OpenUAF()
{
	int fd;
	fd=open("UAF.DAT",O_RDWR|O_BINARY);
	if(fd==-1)
	{
		perror("OpenUAF");
		exit(1);
	}
	lseek(fd,0,0);
	return(fd);
}

void CloseUAF(fd)
int fd;
{
	close(fd);
}

struct UserRecord *FindUserRecord(x)
char *x;
{
	struct UserRecord *rec;
	int f=OpenUAF();
	rec=LoadARecord(f,x);
	CloseUAF(f);
	return(rec);
}

struct UserRecord *FindFreeRecord()
{
	return(FindUserRecord(""));
}

LoadUser(n,name)
int n;
char *name;
{
	struct UserRecord *r;
	int ct=0;
	r=FindUserRecord(name);
	if(!r)
		return(0);
	while(ct<32)
	{
		PLAYER(n)->pl_Data[ct]=r->ur_Data[ct];
		ct++;
	}
	if(TYPE(n)!=FL_PLAYER)
	{
		fprintf(stderr,"[SYSTEM WARNING]:  Player '%s' was not of player class (type coerced)\n",name);
		ItemArray[n]->ob_Data[0]&=~3;
		ItemArray[n]->ob_Data[0]|=FL_PLAYER;
	}
	PLAYER(n)->pl_PwKey=r->ur_PwKey;
	return(1);
}

BuildRecord(n,r)
ITEM n;
struct UserRecord *r;
{
	int ct=0;
	strcpy(r->ur_Name,NAME(n));
	while(ct<128)
	{
		r->ur_Data[ct]=PLAYER(n)->pl_Data[ct];
		ct++;
	}
	r->ur_PwKey=PLAYER(n)->pl_PwKey;
}

void SaveUser(n,x)
ITEM n;
char *x;
{
	int f=OpenUAF();
	struct UserRecord *r;
	r=LoadARecord(f,x);
	if(r==NULL)
	{
		lseek(f,0,0);	/* CHECK */
		r=LoadARecord(f,"");
		if(r==NULL)
		{
			struct UserRecord tr;
			BuildRecord(n,&tr);
			WriteRecord(f,&tr);
			CloseUAF(f);
			return;
		}
	}
	BuildRecord(n,r);
	Rewrite(f,r);
	CloseUAF(f);
}

CryptX(x)
unsigned char *x;
{
	char *xo=(char *)x;
	unsigned int ct=0;
	while(*x)
	{
		ct|=(*x++);
		ct<<=(ct&5);
	}
	return((int)ct);
}

void ForcePassword(u)
char *u;
{
	char buf[32];
	char buf2[32];
	int f=OpenUAF();
	struct UserRecord *r;
	if(sscanf(u,"%31s %31s",buf,buf2)!=2)
	{
		UPrintf("Must specify [user] [password].\n");
		CloseUAF(f);
		return;
	}
	r=LoadARecord(f,buf);
	if(r==NULL)
	{
		UPrintf("User %s, not found.\n",buf);
		CloseUAF(f);
		return;
	}
	UPrintf("Chnaging password for '%s' to '%s'.\n",buf,buf2);
	r->ur_PwKey=CryptX(buf2);
	Rewrite(f,r);
	CloseUAF(f);
}