/*****************************************************************************
 *
 * $Id$
 * Purpose ...............: Main user login procedure.  Checks for limits, 
 *                          new ratio's cats all the welcome screens, and 
 *                          does a lot of checking in general.
 *
 *****************************************************************************
 * Copyright (C) 1997-2002
 *   
 * Michiel Broek		FIDO:		2:280/2802
 * Beekmansbos 10
 * 1971 BV IJmuiden
 * the Netherlands
 *
 * This file is part of MBSE BBS.
 *
 * This BBS 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, or (at your option) any
 * later version.
 *
 * MBSE BBS 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 MBSE BBS; see the file COPYING.  If not, write to the Free
 * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *****************************************************************************/

#include "../lib/libs.h"
#include "../lib/mbse.h"
#include "../lib/structs.h"
#include "../lib/users.h"
#include "../lib/records.h"
#include "../lib/common.h"
#include "../lib/clcomm.h"
#include "timeout.h"
#include "user.h"
#include "dispfile.h"
#include "funcs.h"
#include "input.h"
#include "misc.h"
#include "bye.h"
#include "file.h"
#include "mail.h"
#include "change.h"
#include "menu.h"
#include "exitinfo.h"
#include "language.h"
#include "offline.h"
#include "email.h"



extern int	sock;
extern pid_t	mypid;
char		*StartTime;


/* 
 * Non global function prototypes
 */
void SwapDate(char *, char *);              /* Swap two Date strings around     */



void GetLastUser(void);
void GetLastUser(void)
{
        FILE    *pCallerLog;
        char    *sDataFile;

        sDataFile = calloc(PATH_MAX, sizeof(char));
        sprintf(sDataFile, "%s/etc/sysinfo.data", getenv("MBSE_ROOT"));
	/*
	 * Fix security in case it is wrong.
	 */
	chmod(sDataFile, 0660);
	
        if((pCallerLog = fopen(sDataFile, "r+")) == NULL)
                WriteError("GetLastUser: Can't open file: %s", sDataFile);
        else {
                fread(&SYSINFO, sizeof(SYSINFO), 1, pCallerLog);

                /* Get lastcaller in memory */
                strcpy(LastCaller, SYSINFO.LastCaller);
                LastCallerTime = SYSINFO.LastTime;

                /* Set next lastcaller (this user) */
                if (!usrconfig.Hidden) {
                        strcpy(SYSINFO.LastCaller,exitinfo.sUserName);
                        SYSINFO.LastTime = time(NULL);
                }

                SYSINFO.SystemCalls++;
                switch(ttyinfo.type) {
                        case POTS:
                                SYSINFO.Pots++;
                                break;

                        case ISDN:
                                SYSINFO.ISDN++;
                                break;

                        case NETWORK:
                                SYSINFO.Network++;
                                break;

                        case LOCAL:
                                SYSINFO.Local++;
                                break;
                }

                rewind(pCallerLog);
                fwrite(&SYSINFO, sizeof(SYSINFO), 1, pCallerLog);

                fclose(pCallerLog);
        }
        free(sDataFile);
}



/*
 * Function will take two date strings in the following format DD-MM-YYYY and 
 * swap them around in the following format YYYYMMDD
 * ie. 01-02-1995 will become 19950201 so that the leading Zeros are not in
 * the beginning as leading Zeros will fall away if you try compare the
 * two with a if statement (Millenium proof).
 */
void SwapDate(char *Date3, char *Date4)
{
        char *temp2, *temp3;

        temp2 = calloc(10, sizeof(char));
        temp3 = calloc(10, sizeof(char));
        Date1 = calloc(10, sizeof(char));
        Date2 = calloc(10, sizeof(char));

        temp2[0] = Date3[6];
        temp2[1] = Date3[7];
        temp2[2] = Date3[8];
        temp2[3] = Date3[9];
        temp2[4] = Date3[3];
        temp2[5] = Date3[4];
        temp2[6] = Date3[0];
        temp2[7] = Date3[1];
        temp2[8] = '\0';

        temp3[0] = Date4[6];
        temp3[1] = Date4[7];
        temp3[2] = Date4[8];
        temp3[3] = Date4[9];
        temp3[4] = Date4[3];
        temp3[5] = Date4[4];
        temp3[6] = Date4[0];
        temp3[7] = Date4[1];
        temp3[8] = '\0';

        strcpy(Date1, temp2);
        strcpy(Date2, temp3);

        free(temp2);
        free(temp3);
}



void user()
{
	FILE		*pUsrConfig, *pLimits;
	int		i, x;
	int		FoundName = FALSE, iFoundLimit = FALSE;
	long		l1, l2;
	char		*token;
	char		temp[PATH_MAX];
	char		temp1[84];
	time_t		LastLogin;
	struct stat 	st;
	char		UserName[37];
	int		IsNew = FALSE;

	grecno = 0;
	Syslog('+', "Unixmode login: %s", sUnixName);

	sprintf(temp, "%s/etc/users.data", getenv("MBSE_ROOT"));
	if ((pUsrConfig = fopen(temp,"r+b")) == NULL) {
	    /*
	     * This should not happen.
	     */
	    WriteError("$Can't open %s", temp);
	    printf("Can't open userfile, run \"newuser\" first");
	    ExitClient(0);
	}

	fread(&usrconfighdr, sizeof(usrconfighdr), 1, pUsrConfig);
	while (fread(&usrconfig, usrconfighdr.recsize, 1, pUsrConfig) == 1) {
	    if (strcmp(usrconfig.Name, sUnixName) == 0) {
		FoundName = TRUE;
		break;
	    } else
		grecno++;
	}
							
	if (!FoundName) {
	    printf("Unknown username: %s\n", sUnixName);
	    /* FATAL ERROR: You are not in the BBS users file.*/
	    printf("%s\n", (char *) Language(389));
	    /* Please run 'newuser' to create an account */
	    printf("%s\n", (char *) Language(390));
	    Syslog('?', "FATAL: Could not find user in BBS users file.");
	    Syslog('?', "       and system is using unix accounts\n");
	    ExitClient(0);
	}

	/*
	 * Copy username, split first and lastname.
	 */
	strcpy(UserName, usrconfig.sUserName);
	if ((strchr(UserName,' ') == NULL && !CFG.iOneName)) {
		token = strtok(UserName, " ");
  		strcpy(FirstName, token);
  		token = strtok(NULL, "\0");
		i = strlen(token);
		for(x = 2; x < i; x++) {
			if(token[x] == ' ')
				token[x] = '\0';
		}
	 	strcpy(LastName, token);
	} else
		strcpy(FirstName, UserName);
	strcpy(UserName, usrconfig.sUserName);
	Syslog('+', "%s On-Line at %s", UserName, ttyinfo.comment);
	IsDoing("Just Logged In");

	/*
	 * Check some essential files, create them if they don't exist.
	 */
 	ChkFiles();

	/*
	 * Setup users favourite language.
	 */
	Set_Language(usrconfig.iLanguage);
	Free_Language();
	InitLanguage();

	/*
	 * User logged in, tell it to the server.
	 */
	UserCity(mypid, usrconfig.sUserName, usrconfig.sLocation);

	/*
	 * See if this user is the Sysop.
	 */
	strcpy(temp, UserName);
	strcpy(temp1, CFG.sysop_name);
	if ((strcasecmp(CFG.sysop_name, UserName)) == 0) {
		/*
		 * If login name is sysop, set SYSOP true 
		 */
		SYSOP = TRUE;
		Syslog('+', "Sysop is online");
	}

	/*
	 * Is this a new user?
	 */
	if (usrconfig.iTotalCalls == 0)
	    IsNew = TRUE;

	TermInit(usrconfig.GraphMode);

	/*
	 * Pause after logo screen.
	 */
	alarm_on();
	Pause();

	if (usrconfig.Archiver[0] == '\0') {
		usrconfig.Archiver[0] = 'Z';
		usrconfig.Archiver[1] = 'I';
		usrconfig.Archiver[2] = 'P';
		Syslog('+', "Setup default archiver ZIP");
	}

	/*
	 * Check users date format. We do it strict as we
	 * need this to be good for several other purposes.
	 * If it is correct, the users age is set in UserAge
	 */
	if (!Test_DOB(usrconfig.sDateOfBirth)) {
		Syslog('!', "Error in Date of Birth");
		Chg_DOB();
		strcpy(usrconfig.sDateOfBirth, exitinfo.sDateOfBirth);
	}

	/*
	 * Check to see if user must expire
	 */
	sprintf(temp,"%s", (char *) GetDateDMY());
	SwapDate(temp, usrconfig.sExpiryDate);

	/* Convert Date1 & Date2 to longs for compare */
	l1 = atol(Date1);
	l2 = atol(Date2);

	if (l1 >= l2 && l2 != 0) {
		/* 
		 * If Expiry Date is the same as today expire to 
		 * Expire Sec level
		 */
		usrconfig.Security = usrconfig.ExpirySec;
		Syslog('!', "User is expired, resetting level");
		/*
		 * Show texfile to user telling him about this.
		 */
		DisplayFile((char *)"expired");
	}

	free(Date1); 
	free(Date2);

	/* 
	 * Copy limits.data into memory
	 */
	sprintf(temp, "%s/etc/limits.data", getenv("MBSE_ROOT"));

	if ((pLimits = fopen(temp,"rb")) == NULL) {
		WriteError("$Can't open %s", temp);
	} else {
		fread(&LIMIThdr, sizeof(LIMIThdr), 1, pLimits);

		while (fread(&LIMIT, sizeof(LIMIT), 1, pLimits) == 1) {
 			if (LIMIT.Security == usrconfig.Security.level) {
				iFoundLimit = TRUE;
				break;
			}
		}
		fclose(pLimits);
	}

	if (!iFoundLimit) {
		WriteError("Unknown Security Level in limits.data");
		usrconfig.iTimeLeft = 0; /* Could not find limit, so set to Zero */
		usrconfig.iTimeUsed = 0; /* Set to Zero as well  */
	} else {
		/*
		 * Give user new time limit everyday, also new users get a new limit.
		 */
		sprintf(temp,"%s", (char *) GetDateDMY());
		if (((strcmp(StrDateDMY(usrconfig.tLastLoginDate), temp)) != 0) || IsNew) {
			/*
			 *  If no timelimit set give user 24 hours.
			 */
			if (LIMIT.Time)
				usrconfig.iTimeLeft = LIMIT.Time;
			else
				usrconfig.iTimeLeft = 86400;
			usrconfig.iTimeUsed    = 0;          /* Set time used today to Zero       */
			usrconfig.iConnectTime = 0;	     /* Set connect time to Zero          */

			/*
			 * Give user new bytes and files every day if needed.
			 */
			if (LIMIT.DownK && LIMIT.DownF) {
				usrconfig.DownloadKToday = LIMIT.DownK;
				usrconfig.DownloadsToday = LIMIT.DownF;
			}
		}
	} /* End of else  */

	usrconfig.iConnectTime = 0;

	/* Copy Users Protocol into Memory */
	Set_Protocol(usrconfig.sProtocol);
	tlf(usrconfig.sProtocol);

	/* 
	 * Set last login Date and Time, copy previous session
	 * values in memory.
	 */
	sprintf(LastLoginDate, "%s", StrDateDMY(usrconfig.tLastLoginDate));
	sprintf(LastLoginTime, "%s", StrTimeHMS(usrconfig.tLastLoginDate));
	LastLogin = usrconfig.tLastLoginDate;
	usrconfig.tLastLoginDate = ltime; /* Set current login to current date */
	usrconfig.iTotalCalls++;

	/*
	 * Update user record.
	 */
	if (fseek(pUsrConfig, usrconfighdr.hdrsize + (grecno * usrconfighdr.recsize), 0) != 0) {
		WriteError("Can't seek in %s/etc/users.data", getenv("MBSE_ROOT"));
	} else {
		fwrite(&usrconfig, sizeof(usrconfig), 1, pUsrConfig);
		fclose(pUsrConfig);
	}

	/*
	 * Write users structure to tmp file in ~/home/unixname/exitinfo
	 * A copy of the userrecord is also in the variable exitinfo.
	 */
	if (! InitExitinfo())
	    Good_Bye(1);

	GetLastUser();
	StartTime = xstrcpy(GetLocalHM());
	ChangeHomeDir(exitinfo.Name, exitinfo.Email);

	Syslog('+', "User successfully logged into BBS");
	Syslog('+', "Level %d (%s), %d mins. left, port %s", 
		usrconfig.Security.level, LIMIT.Description, usrconfig.iTimeLeft, pTTY);
	Time2Go = time(NULL);
	Time2Go += usrconfig.iTimeLeft * 60;
	iUserTimeLeft = exitinfo.iTimeLeft;

	DisplayFile((char *)"mainlogo");
	DisplayFile((char *)"welcome");

	/*
	 * The following files are only displayed if the user has
	 * turned the Bulletins on.
	 */
	if (exitinfo.ieNEWS) {
		DisplayFile((char *)"welcome1");
		DisplayFile((char *)"welcome2");
		DisplayFile((char *)"welcome3");
		DisplayFile((char *)"welcome4");
		DisplayFile((char *)"welcome5");
		DisplayFile((char *)"welcome6");
		DisplayFile((char *)"welcome7");
		DisplayFile((char *)"welcome8");
		DisplayFile((char *)"welcome9");

		sprintf(temp, "%s", (char *) GetDateDMY() );
		if ((strcmp(exitinfo.sDateOfBirth, temp)) == 0)
			DisplayFile((char *)"birthday");

		/*
		 * Displays file if it exists DD-MM.A??
		 */
		sprintf(temp, "%s", (char *) GetDateDMY());
		strcpy(temp1, "");
		strncat(temp1, temp, 5);
		sprintf(temp, "%s", temp1);
		DisplayFile(temp);
	
		/*
		 * Displays users security file if it exists
		 */
		sprintf(temp, "sec%d", exitinfo.Security.level);
		DisplayFile(temp);

		/*
		 * Display News file
		 */
		DisplayFile((char *)"news");
	}

	/*
	 * Display Onceonly file, first get the date of that
	 * file, search order is the same as in DisplayFile()
	 */
	st.st_mtime = 0;
	if (exitinfo.GraphMode) {
		sprintf(temp, "%s/onceonly.ans", lang.TextPath);
		stat(temp, &st);
		if (st.st_mtime == 0) {
			sprintf(temp, "%s/onceonly.ans", CFG.bbs_txtfiles);
			stat(temp, &st);
		}
	}
	if (st.st_mtime == 0) {
		sprintf(temp, "%s/onceonly.asc", lang.TextPath);
		stat(temp, &st);
		if (st.st_mtime == 0) {
			sprintf(temp, "%s/onceonly.asc", CFG.bbs_txtfiles);
			stat(temp, &st);
		}
	}

	if ((st.st_mtime != 0) && (LastLogin < st.st_mtime))
		DisplayFile((char *)"onceonly");
	
	OLR_SyncTags();

	if (exitinfo.MailScan)
		CheckMail();

	/*
	 * We don't show new files to new users.
	 */
	if (exitinfo.ieFILE && (!IsNew))
		NewfileScan(FALSE);

	/* 
	 * Copy last file Area in to current Area 
	 */
	SetFileArea(exitinfo.iLastFileArea);

	/*
	 * Copy Last Message Area in to Current Msg Area
	 */
	SetMsgArea(usrconfig.iLastMsgArea);
	SetEmailArea((char *)"mailbox");

	/*
	 * Set or Reset the DoNotDisturb flag, now is the time
	 * we may be interrupted.
	 */
	UserSilent(usrconfig.DoNotDisturb);

	/*
	 * Start the menu.
	 */
       	menu();
}