/*
 *	MELANGE		- CHAT server for LINUX
 *			  Version 1.10
 *			  Released Apr-25-1999
 *
 *	Christian Walter
 *	chris@terminal.at
 * 	http://melange.terminal.at
 *	Vienna, Austria
 *
 **************************************
 *
 *	melange.h
 *
 *	REVISIONS:
 *		10-10-98 [cw]	original implementation
 *		12-15-98 [cw]	complete code revision
 *		02-23-99 [cw]	first stable release
 *		04-25-99 [cw]	release 1.10
 */

#include <ctype.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <signal.h>
#include <arpa/inet.h>
#include "language.h"

/*****************************************************************************/
/* If you want, you can change the following default parameter settings.     */
/* NOTE: All of these parameters can be changed at runtime, too !            */
/*****************************************************************************/

#define ACTIVEFILE              "melange.active"            /*** MANHATTAN: this line added */


#define CONFIGFILE		"melange.conf"

#define PORT 6666

/* The following parameters can not be changed via commandline or configfile */
/* If you want to change them, do it now !                                   */






/*****************************************************************************/
/* STOP ! You do NOT need to change anything in the following lines ! STOP ! */
/*****************************************************************************/

#define VERSION "Melange Chat Server (Modified for Manhattan) Nov-12-2003\r\n"
#define YES 1
#define NO 0
#define ALLOW 1
#define DENY 0
#define DEFAULT 1
#define KILL 2
#define PERMANENT 10

#define SYSMSG 1000
#define SYSTEM 1001  /* Seems to mean 'no user'.  This number must be outside of the range 0 ... maxClients  */
#define NOBODY 1002



/*********************************
*    adminFeature mAdmin
*********************************/



#define MAX_ADMIN_PASSWORD 99    /* The maximum length of the admin's password, which is stored
                                 ** in the configuration file.  Manhattan's Chat management function
                                 ** allows the Manhattan admin to set/clear this password from a web
                                 ** browser
                                  */


#define BANNTIME 3600            /* how long, in seconds, will a host be denied access to the chat
                                 ** after he was kicked out by the Admin???  This sets the default
                                 ** time, which can be overidden in the configuration file.
                                 ** In practice, Manhattan admins shouldn't ever have to kick a user out???
                                 */
/** The following struct controls basic security (and similar) settings for
*** the chat.
***
*** There is exactly one global variable of this type: mAdmin
*** The mAdmin structure is initialized with default values via a call to 
*** util_LoadDefaults() in util.c, Then the wanted settings are read from
*** the melange.conf file via a call to util_ReadConfigFile(..) in 
*** util.c
***
***  int activated;  - Should it be possible for a person to become the 
***                    administrator by typing the command:
***                             /admin login password
***
***                    This gets set to '1' only if the administrator's
***                    password, read from melange.conf, is different
***                    from the default value of "changethis" see
***                    util_ReadConfigFile() in util.c
***
***  int administrator;    The line number of the person who is currently the administrator
***
***  char password[MAX_ADMIN_PASSWORD + 1];   The administrator's password, read from the
***                                           configuration file.  A user becomes the 
***                                           admin by typing the command:
***                                                 /admin login <password>
***
***
***  int allowUserChannels;              Allow users to create their own channels?  Default is YES.
***                                      For Manhattan, we want to keep this at 'yes'
***
***  int allowAnonymousChannel;          Allow users to switch to the anonymous channel.  Default is NO
***                                      For Manhattan, we don't even want to let users know about the
***                                      existence of the anonymous channel.
***
*** 
*** int securityType;                    Can either be ALLOW or DENY.  It's ALLOW by default, which means
***                                      that hosts which are to be denied must be explicitly listed in 
***                                      the config file.  Most Manhattan admins will never use this.
***
*** int sysMsg;                          Default is NO. Set via SYSMSG on/off parameter in config file.  Should
**                                       certain system messages be sent to Java clients that are able to interpret
***                                      them?  At this time, always leave this set to NO for Manhattan.
*** 
*** defaultBannTime;                     Default value is #defined as BANNTIME above.  Can be set in config
***                                      file via KICKOUTTIME option.  This is how long a person (host actually)
***                                      is banned from the chat after they have been kicked out by the adminstrator
***
*** int uniqueNames;                     Default is NO, set by config file parameter UNIQUE.  Within Manhattan, this
***                                      should be left set to NO.  Users can never select their nicknames, and must
***                                      stick to how they are known within Manhattan.
*** 
*** int guestLogin;                      Default is NO.  Allow users to login as 'guest'?  Should be always NO for Manhattan
***                                      Set via GUESTLOGIN parameter in the config file
***
***
*** int changeNames;                    Corresponds to CHANGENICKS parameter in the config file.  Set to 'NO' by default
***                                     should always be set to NO for Manhattan.
**
*** int maxIdleTime;                    Corresponds to the IDLETIME parameter in the config file:
***                                     This paramter sets the time after a user is kicked out of the chat if he 
***                                     doesn't say a word for time seconds. If the time is set to 0 users will not be 
***                                     kicked out even if they don't say a word for days. NOTE: Users
***                                     are not kicked exactly at the time you set via time but when the first new user 
***                                     after time is over connects to the chat. (This is to speed up the server).
*** 
*** int msgLog;                         Corresponds to the MSGLOGFILE parameter in the config file:
***                                     Use this parameter if you want to enable an additional logfile which logs 
***                                     only the messages (instead of all sysmessages, commands, servermessages, etc. 
***                                     in the default logfile) and if a user connects/disconnects to the server. If you 
***                                     specify a filename, this name is used, if you only set the parameter to
***                                     ON the default logfile is used. (default is: /var/log/melange_msg.log).
***                                     IN PRACTICE, this is always set to NO (no message logging) since Manhattan
***                                     adds it's own logging functions.
***
**/

typedef struct _adminFeature 
{
    int activated;             /* if zero, the ADMIN features are completely disabled */
    int administrator;         /* the line number of the current administrator  */
    char password[MAX_ADMIN_PASSWORD + 1];
    int allowUserChannels;
    int allowAnonymousChannel;
    int securityType;
    int sysMsg;
    int defaultBannTime;
    int uniqueNames;
    int guestLogin;
    int changeNames;
    int maxIdleTime;
    int msgLog;
} adminFeature;

adminFeature mAdmin;








#define MAX_HOSTMASK 99
#define maxSecurityProfiles 50
typedef struct _securityProfile {
    char hostmask[MAX_HOSTMASK + 1];
    time_t banntime;
} securityProfile;

securityProfile mSecurity[maxSecurityProfiles];





#define MAX_CHANNEL_NAME 99
#define maxChannels 1000
typedef struct _channelDescription channelDescription;
typedef struct _channelDescription {
    char name[MAX_CHANNEL_NAME + 1];
    int owner;
    int locked;
    int group;
} ChannelDescription;

channelDescription mChannel[maxChannels];





/***************************************
*     clientDescription mClient[maxClients];
***************************************/

/**  Each chat user is described using the
***  ClientDescription structure defined next.
***  
***  An array, mClient, which is maxClients
***  long holds the info for everyon currently
***  logged in.
***/



#define maxClients 100              /* only this # of people can be logged in at one time
                                    ** If you try to login and the server is full, you'll
                                    ** be told that and denied entry
                                    **/

#define MAX_CLIENT_NAME 49         /* Maximum length of a person's name.  A person's name
                                   ** is passed in directly from Manhattan, so MAX_CLIENT_NAME
                                   ** must be at least as long as Manhattan's MAX_NAME 
                                   ** #defined in its global.h
                                   */


#define MAX_HOST_NAME 99           /* Max len of an internet host name, e.g. 
                                   **  wiggly.woogly.com
                                   */


typedef struct _clientDescription 
  {
    int socket;                        /* what socket do we communicate them via? */
    char name[MAX_CLIENT_NAME + 1];    /* What's their name e.g. Steven-Narmontas */
    int channel;                       /* What channel are they currently in? */
    int invite;                        /* What channel has this user been invited to join? */
    int online;                        /* Is this person online (YES/NO)   */
    char host[MAX_HOST_NAME + 1];      /* The computer name they are connecting from eg. wiggly.woogly.com */
    int squelch[maxClients];           /* A list of other users this person /SQUELCHed */

    unsigned char syscap;              /* QUESTION: system capabilites???? maybe set by the client to say 
                                       ** what the client can do????
                                       */
                                       
    time_t idle;                       /* actually, stores the time when this user last typed a msg - consulted
                                       ** when kicking out idle users
                                       */

    int group;                         /* part of melange's group system, which allows only members of the same
                                       ** group to access certain channels  QUESTION: how is this used now???
                                       */   
} clientDescription;

clientDescription mClient[maxClients];









/***  QUESTION:IS NEXT USED FOR MANHATTAN ????
***
***/
#define MAX_GROUP_PASSWORD 7
#define maxGroups 200
typedef struct _groupDescription {
    char passwd[MAX_GROUP_PASSWORD + 1];
} groupDescription;

groupDescription mGroup[maxGroups];



int mServerPort;                                    /* What port is melange running on?  
                                                    ** QUESTION: does this need to be a global???
                                                    ** It is only used briefly at start-up
                                                    */

time_t mServerStartupTime;                          /* The time the server was started. Used to report server uptime */
                                                    





#define MAX_LOGFILE_NAME 249
#define MAX_LOG_STRING 400         /* max len of a single entry written to the log file.  Log entries longer than this
                                   ** are discarded????
                                   */
#define LOGFILE  "melange.log"     /* the default name for the system log file QUESTION:should ability to change
                                   ** this via the config file be removed?
                                   */

char logFileName[MAX_LOGFILE_NAME + 1];  /* LOGFILE is copied to this string at init time.  QUESTION: if 
                                         ** logFileHandle is also global, why make this global too?
                                         */
int logIsActive;                         /** Flag: is logFileHandle available for writing?  QUESTION: what does this do? */
int logFileHandle;                       /*  File handle to open log file */
int mLogLevel;                           /* What should be logged?  Each call to add a msg to the system log is
                                         ** accompanied by a log level. This is set via the configuration file.
                                         */


/*** QUESTION: does Manhattan use this? ****/
#define MSGLOGFILE 		"melange_msg.log"
char msgLogFileName[MAX_LOGFILE_NAME + 1];
int msgLogFileHandle;





/* Used to construct general system messages???? "John has entered the chat" */
#define MAX_INFO_TEXT 500
char infoText[MAX_INFO_TEXT + 1];


/* Used to construct and store messages typed by a user and sent to others in the 
** chat.  Must include room for their name, which precedes what was typed
*/
#define MAX_MSG_TEXT 600
char msgText[MAX_MSG_TEXT + 1];

/* util.c */
extern void util_AdjustUserCount(int adjustment);        /*** MANHATTAN: this prototype added ****/
extern void util_WriteClassLog(int sender, char *sender_name, char *msg, char *group_name); /*MANHATTAN: this prototype added ***/
extern void util_WriteLog(int logLevel, char *logString);
extern void util_WriteMsgLog(char *logString);
extern void util_LogInit();
extern void util_LoadDefaults();
extern void util_ReadConfigFile(char *configFileName);
extern void util_ChatInit(char *configFileName, int quiet); /*** MANHATTAN - quiet parameter added */
extern void util_PrintConfiguration();
extern void util_printf(char *infoText);
extern char *util_FitString(char *string);
extern int util_IndexOf(char *string, int offset);
extern int util_GetUserId(int sender, char *data);
extern void util_ResetLog(int mode);
extern int util_GetBMT();

/* chatutil.c */
extern int chat_ChangeChannelName(int user, char *channelName);
extern void logout_unknown_intruder(int sender);
extern int chat_ChangeNick(int user, char *newNick, int require_colon);
extern int chat_ChangeOwner(int user, char *owner);
extern void chat_CloseChannel(int user, int myChannel, int moveToChannel);
extern void chat_Finger(int user);
extern int chat_GetChannelId(int user, char *channelName);
extern int chat_GetLine(int socket);
extern void chat_Help(int user);
extern void chat_HelpLogin(int user);
extern void chat_HelpOnline(int user);
extern void chat_Id(int user);
extern int chat_Invite(int user, char *userToInvite);
extern int chat_JoinChannel(int user, char *newChannel);
extern int chat_KickOutOfChannel(int user, char *userID);
extern void chat_ListChannels(int user);
extern int chat_Login(int user,char *nickName);
extern int chat_LockChannel(int user);
extern void chat_Logout(int user, int mode);
extern int chat_Squelch(int user, char *userToSquelch);
extern void chat_ShowTime(int user);
extern void chat_Uptime(int user);
extern int chat_Whisper(int user, char *receiver, char *message);
extern int chat_Page(int user, char *receiver, char *message);
extern void chat_Whois(int user);
extern void chat_Yell(int user, char *message1, char *message2);
extern int chat_SetUserGroup(int user, char *group, char *passwd);
extern int chat_SetChannelGroup(int user, char *group);
extern int chat_FetchUser(int user, char *userToFetch);

/* comm.c */
extern int comm_SendAll(int sender, char *msg);
extern int comm_SendAllBut(int sender, int mask, char *msg);
extern int comm_SendChannel(int sender, int channel, char *msg);
extern int comm_SendChannelBut(int sender, int channel, int mask, char *msg);
extern int comm_SendGroup(int sender, char *msg);
extern int comm_SendGroupBut(int sender, int mask, char *msg);
extern int comm_SendTo(int sender,int receiver,char *msg);
extern int comm_SendPage(int sender,int receiver,char *msg);

/* interpret.c */
extern int chat_InterpretData(int sender, char *data, int *shutDownServer);

/* admin.c */
extern int admin_CreateSysChannel(int user, char *syschannelName);
extern int admin_CheckIfAllowed(int socket, char *clientIP, char *clientHostName);
extern int admin_InterpretAdminCommand(int sender, char *option, char *parameter);
extern int admin_JoinChannel(int user, char *newChannel);
extern void admin_ShutDown();
extern int admin_ChangeTopic(int user, char *newTopic);
extern int admin_ChangeOwner(int user, char *newOwner);
extern int admin_SetUniqueNames(int user, char *param);
extern int admin_SetChangeNames(int user, char *param);
extern void admin_ShowServerStat(int user);
extern int admin_AddHostMask(int user, char *hostMask, int mode);
extern int admin_RemoveHostMask(int user, char *hostMask);
extern int admin_SetLogLevel(int user, char *newLevel);
extern int admin_SetBannTime(int user, char *newTime);
extern int admin_SetIdleTime(int user, char *newTime);
extern int admin_SetSysMsg(int user, char *newStat);
extern int admin_KickIdleUsers();
extern int admin_KickUser(int user, char *userToKick);
extern void admin_Whois(int user);
extern void admin_ListChannels(int user);
extern int admin_CloseChannel(int user, char *channel);
extern int admin_ListGroup(int user, int group);
extern int admin_ListGroups(int user, char *group);
extern void admin_ListAllGroups(int user);
extern int admin_CreateGroup(int user, char *group, char *passwd);
extern void admin_Help(int user);
extern int admin_SetGuestLogin(int user, char *param);

/* sysutil.c */
extern void sys_SetSysCap(int user, char *capability);
extern int sys_SendChannelUpdate(int user);
extern int sys_SendUserUpdate(int channel,int user);
extern int sys_SendAllUserUpdate(int user);
extern void sys_SendShutdownCommand(int user);
extern void sys_SendLoginCommand(int user,int mode);
extern int sys_SendSysMsg(int mask,int channel,char *msg,int user);
extern int sys_SendReqAnswer(int user);

/* signals.c */
extern void signal_ResetSignals();
extern void signal_SetSignals();
extern void signal_MainSignalHandler(int sigNum);
extern void signal_SignalBrokenPipe(int sigNum);
extern void signal_SignalHangUp(int sigNum);
extern void signal_SignalProgrammFault(int sigNum);
extern void signal_SignalKill(int sigNum);

