/*
 *      Code from:              Philipp Meinen
 *      Copyright (C):          2003-2004 Philipp Meinen
 *
 *      Email:                  lancelot@lancelot2k.dyndns.org
 *      Homepage:               http://lancelot2k.dyndns.org
 *      License:                GPL
 *                                                      */

#define _SERVER_CC_
#include <cstdio>
#include <cstring>
#include <ctime>
#include <cstdlib>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#include "server.h"

Server::Server(void)
{
	connect_status = STATUS_NOTHING;
	cs_printed = 0;
	maybe_reconnect = 0;
	do_connect = 0;
	socketfd = -1;
	memset(&socket_data, '\0', sizeof(struct sockaddr));
	help_buffer[0] = '\0';
	normal_text[0] = '\0';
	OneInputLine[0] = '\0';
	InputData[0] = '\0';
	last_ping = 0;
	StartCommandsSent = 0;
	LastCommandTime = time(NULL)+2;
	Num_InputParameters = 0;
	ModesSet = 0;
	InputParameters = new char * [NUM_INPUTPARAMETERS_MAX];
	for(int i = 0; i < NUM_INPUTPARAMETERS_MAX; i++)
		InputParameters[i] = NULL;
	return;
}

Server::~Server(void)
{
	return;
}

void Server::Connect(void)
{
	if(do_connect) Disconnect(); /* clean up if we have to connect */
	do_connect = 0;
	if(connect_status == STATUS_NOTHING) {
		SetConnectStatus(STATUS_RESOLV_IN_PROGRESS);
		if(pthread_create(&nameresolver, NULL, nameresolv_wrapper, (void *)this) != 0)
		{
			/* create thread error */
			SetConnectStatus(STATUS_NOTHING);
			int screen_nr = Classes.IrcScreen->GetActiveChannel();
			Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_ERROR, MESSAGE_ERR_PTHREAD);
			if(screen_nr)
				Classes.MsgDB->SetIrcChatMessage(0, DISPLAY_ERROR, MESSAGE_ERR_PTHREAD);
			Classes.IrcScreen->DrawTextScreen();
		}
	} else if(connect_status == STATUS_RESOLV_IN_PROGRESS) {
		/* name resolving still in progress */
		return;
	} else if(connect_status == STATUS_RESOLVING_FINISHED) {
		maybe_reconnect = 1;
		/* Get a socket */
		snprintf(help_buffer, HELP_BUF_LEN, "Connecting to %s:%i ...", servername, port);
		Classes.MsgDB->SetIrcChatMessage(0, DISPLAY_AUTHINFO, help_buffer);
		Classes.IrcScreen->DrawTextScreen();
		socketfd = socket(PF_INET, SOCK_STREAM, 0);
		if(socketfd == -1) {
			SetConnectStatus(STATUS_NOTHING);
			return;
		}
		fcntl(socketfd, F_SETFL, O_NONBLOCK); /* the socket should be non-blocking */
		/* and now connect */
		SetConnectStatus(STATUS_SYN_SENT);
		connect(socketfd, (struct sockaddr *)&socket_data, sizeof(socket_data));
	}
	return;
}

void Server::Disconnect(void)
{
	if(socketfd && connect_status > STATUS_SYN_SENT)
		Classes.MsgDB->SetIrcChatMessage(0, DISPLAY_SERVERMSG, MESSAGE_DISCONNECT);
	if(socketfd != -1)
		close(socketfd);
	socketfd = -1;
	ResetParameters();
	Classes.IrcScreen->EmptyAllScreens();
	Classes.IrcUserDB->Reset_All_UserDB();
	Classes.IrcScreen->DrawTextScreen();
	Classes.IrcScreen->DrawBottomScreen();
	Classes.IrcScreen->DrawTopScreen();
	return;
}

void Server::GetHostname(void)
{
	SetConnectStatus(STATUS_RESOLV_IN_PROGRESS);
	SetServername(Classes.IrcUser->GetServername());
	SetServerport(Classes.IrcUser->GetPort());
	snprintf(help_buffer, HELP_BUF_LEN, "%s%s ...", MESSAGE_HOST_LOOKUP, servername);
	Classes.MsgDB->SetIrcChatMessage(0, DISPLAY_AUTHINFO, help_buffer);
	Classes.IrcScreen->DrawTextScreen();
	struct hostent * serverparams = NULL;
	/* fill the socket_data structure whith values */
	if(inet_aton(servername, &socket_data.sin_addr) == 0)
	{
		serverparams = gethostbyname(servername);
		if(serverparams == NULL) {
			Classes.MsgDB->SetIrcChatMessage(0, DISPLAY_ERROR, MESSAGE_HOST_NOTFOUND);
			Classes.IrcScreen->DrawTextScreen();
			SetConnectStatus(STATUS_NOTHING);
			pthread_exit(NULL);
		}
		memcpy(&socket_data.sin_addr.s_addr, serverparams->h_addr, serverparams->h_length);
	}
	socket_data.sin_port = htons(port);
	socket_data.sin_family = AF_INET;
	Classes.MsgDB->SetIrcChatMessage(0, DISPLAY_AUTHINFO, MESSAGE_HOST_LOOKUP_OK);
	Classes.IrcScreen->DrawTextScreen();
	SetConnectStatus(STATUS_RESOLVING_FINISHED);
	pthread_exit(NULL);
	/* never reached */
	return;
}

int Server::SetServername(char * new_servername)
{
	if(new_servername == NULL) return 0;
	if(new_servername[0] == '\0') return 0;
	if(strlen(new_servername) >= SERVER_NAME_LEN) return 0; /* to long */
	strncpy(servername, new_servername, SERVER_NAME_LEN-1);
	return 1; /* OK */
}

int Server::SetServerport(int new_port)
{
	if((new_port < 1) || (new_port > 65535)) return 0; /* port out of range */
	port = new_port;
	return 1; /* OK */
}

char * Server::GetServername(void)
{
	return servername;
}

int Server::GetServerport(void)
{
	return port;
}

int Server::GetInput(void)
{
	int had_input    = 1;
	int read_num     = 0;
	int newlen       = 0;
	int oldlen       = strlen(InputData);
	int max_read_len = INPUT_BUFFER_LEN - oldlen - 1;
	char tmp_buf[max_read_len+1];
	read_num = recv(socketfd, tmp_buf, max_read_len, 0);
	if(read_num == 0) had_input = 0;  /* connection was closed by server */
	if(read_num == -1) {              /* there was an error              */
		had_input =  0; 
		if(errno == ENOTCONN) {   /* the socket is not connected     */
			Disconnect();
		}
	}
	if(read_num > max_read_len) had_input = 0; /* wtf?                   */
	if(had_input == 1) {
		tmp_buf[read_num] = '\0';
		newlen = oldlen + read_num;
		memcpy(InputData+oldlen, tmp_buf, read_num);
		InputData[newlen] = '\0';
		ParseInput();
	}
	return had_input;
}

void Server::ParseInput(void)
{
	do {
		parsing_finished = 0;
		int atnum = 0; /* irc-answer-type-nr */
		/* main loop of server input parsing */
		ReadOneLineFromInput();
		if(OneInputLine[0] == '\0') return;
#ifdef DEBUG
fprintf(stderr, "FromServer <--- \"%s\"\n", OneInputLine); fflush(stderr);
#endif
		Bring_away_special_chars(OneInputLine);
		Read_InputParameters();
		atnum = GetAnswerTypeNr();
		if(atnum && Check_InputData(atnum)) {
			/* We have a Answertypenumber */
			if(atnum >= 1 && atnum <= 9) {
				SetConnectStatus(STATUS_MAX_NUM);
				cs_printed = 1;
				PrintNormalText(DISPLAY_SERVERMSG);
			}
			else if(atnum == 221) ParseCommand_221();
			else if(atnum >= 250 && atnum <= 255) PrintNormalText(DISPLAY_SERVERMSG);
			else if(atnum == 265) ParseCommand_265();
			else if(atnum == 266) ParseCommand_266();
			else if(atnum == 267) ParseCommand_267();
			else if(atnum == 315) ParseCommand_315();
			else if(atnum == 318) ParseCommand_318();
			else if(atnum == 324) ParseCommand_324();
			else if(atnum == 329) ParseCommand_329();
			else if(atnum == 331) ParseCommand_331();
			else if(atnum == 332) ParseCommand_332();
			else if(atnum == 333) ParseCommand_333();
			else if(atnum == 353) ParseCommand_353();
			else if(atnum == 366) ParseCommand_366();
			else if(atnum == 372) ParseCommand_372();
			else if(atnum == 375) ParseCommand_375();
			else if(atnum == 376) ParseCommand_376();
			else if(atnum == 401) ParseCommand_401();
			else if(atnum == 403) ParseCommand_403();
			else if(atnum == 421) ParseCommand_421();
			else if(atnum == 433) ParseCommand_433();
			else if(atnum == 451) ParseCommand_451();
			else if(atnum == 461) ParseCommand_461();
			else if(atnum == 473) ParseCommand_473();
			else if(atnum == 474) ParseCommand_474();
			else if(atnum == 475) ParseCommand_475();
			else if(atnum == 502) ParseCommand_502();
			else if(atnum == PROTOCOL_NUM_PONG        ) ParseCommand_PONG();
			else if(atnum == PROTOCOL_NUM_PRIVMSG     ) ParseCommand_PRIVMSG();
			else if(atnum == PROTOCOL_NUM_NOTICE      ) ParseCommand_NOTICE();
			else if(atnum == PROTOCOL_NUM_JOIN        ) ParseCommand_JOIN();
			else if(atnum == PROTOCOL_NUM_PART        ) ParseCommand_PART();
			else if(atnum == PROTOCOL_NUM_QUIT        ) ParseCommand_QUIT();
			else if(atnum == PROTOCOL_NUM_NICK        ) ParseCommand_NICK();
			else if(atnum == PROTOCOL_NUM_MODE        ) ParseCommand_MODE();
			else if(atnum == PROTOCOL_NUM_KICK        ) ParseCommand_KICK();
			else if(atnum == PROTOCOL_NUM_TOPIC       ) ParseCommand_TOPIC();
			else if(atnum == PROTOCOL_NUM_PING        ) ParseCommand_PING();
			else if(atnum == PROTOCOL_NUM_WALLOPS     ) ParseCommand_WALLOPS();
			else if(atnum == PROTOCOL_NUM_SERVERNOTICE) ParseCommand_SERVERNOTICE();
			else {
				/* if we do not know the command: just print it */
				snprintf(help_buffer, HELP_BUF_LEN, "not implemented: %s", OneInputLine);
				Classes.MsgDB->SetIrcChatMessage(0, DISPLAY_NOTIMPLEMENTED, help_buffer);
				Parsing_Finished();
			}
		} else {
			/* there is no type number for this message
			 * raw text will be simply printed on the infoscreen */
			Classes.MsgDB->SetIrcChatMessage(0, DISPLAY_RAWTEXT, OneInputLine);
			Parsing_Finished();
		}
		if(!parsing_finished) {
			/* one of the parsing functions failed */
			Classes.MsgDB->SetIrcChatMessage(0, DISPLAY_NOTPARSED, OneInputLine);
		}
		Cleanup_InputParameters();
	} while(InputData[0] != '\0');
	Classes.IrcScreen->DrawTextScreen();
	Classes.IrcScreen->DrawBottomScreen();
	return;
}

void Server::Read_InputParameters(void)
{
	/* clean the existing parameters before reading the new ones */
	if(Num_InputParameters != 0)
		Cleanup_InputParameters();
	int start_position = 0,
	    end_position   = 0;
	int param_len;
	int len = strlen(OneInputLine);
	do {
		if(Num_InputParameters == NUM_INPUTPARAMETERS_MAX) break;
		if(Num_InputParameters != 0) {
			/* we allready have parameters */
			start_position = end_position;
		}
		end_position = search_next_num_char(OneInputLine, ' ', 1, end_position+1);
		if(end_position != -1) {
			while(OneInputLine[end_position+1] == ' ') {
				end_position++;
			}
		}
		if(end_position != -1) { /* this is not the last Parameter */
			if(Num_InputParameters != 0) {
				param_len = (end_position - start_position) - 1;
			} else {
				param_len = end_position - start_position;
			}
		} else { /* this is the last parameter */
			param_len = (len - start_position) - 1;
		}
		if(Num_InputParameters != 0) start_position++; /* add one if we are not on the begining (so we dont take the space) */
		if(start_position >= len) break;
		InputParameters[Num_InputParameters] = new char[param_len+1];
		if(param_len > 0)
			memcpy(InputParameters[Num_InputParameters], OneInputLine+start_position, param_len);
		InputParameters[Num_InputParameters][param_len] = '\0';
		Num_InputParameters++;
	} while(end_position != -1);
	return;
}

void Server::Cleanup_InputParameters(void)
{
	while(Num_InputParameters > 0) {
		if(InputParameters[Num_InputParameters-1] != NULL) {
			delete[] InputParameters[Num_InputParameters-1];
			InputParameters[Num_InputParameters-1] = NULL;
		}
		Num_InputParameters--;
	}
	return;
}

int Server::Check_InputData(int atnum)
{
	if(atnum < 1 || atnum > PROTOCOL_HIGHEST_NUMBER) return 0;
	if(!input_params[atnum].defined) return 0;
	if(Num_InputParameters < input_params[atnum].parameters_min) return 0;
	if(Num_InputParameters > input_params[atnum].parameters_max) return 0;
	return 1;
}

int Server::Check_Parameter_for_space(int parameter_nr)
{
	char *x = &InputParameters[parameter_nr][0];
	while(*x) {
		if(*x == ' ') return 1;
		x++;
	}
	return 0;
}

void Server::Put_Text_together(int startposition)
{
	normal_text[0] = '\0';
	int num_params = Num_InputParameters - startposition;
	if(num_params < 1) return;
	strncpy(normal_text, InputParameters[startposition], HELP_BUF_LEN-1);
	int rest_len;
	for(int i = 1; i < num_params; i++)
	{
		rest_len = HELP_BUF_LEN - (strlen(normal_text) + 1);
		if(rest_len < 2) return;
		strncat(normal_text, " ", 1);
		strncat(normal_text, InputParameters[startposition+i], (rest_len-1));
	}
	/* If there is a ':' we can Ignore it! */
	if(normal_text[0] == ':') {
		make_first_char_away(normal_text);
	}
	return;
}

void Server::ReadOneLineFromInput(void)
{
	OneInputLine[0] = '\0';
	if(InputData[0] == '\0') return; /* return when there is anyway no data */
	int len = (signed)strlen(InputData);
	int position = 0;
	/* find the position where '\n' can be found */
	position = position_of_num_char(InputData, '\n', 1);
	if(position == -1) return; /* there is no new message is available */
	if(position < 1) return; /* there is not a single char of message */
	if(position >= ONELINE_READ_MAXLEN - 1) position = ONELINE_READ_MAXLEN - 2;
	memcpy(OneInputLine, InputData, position);
	/* I dont want a "\r\n" ond the end */
	if(InputData[position-1] == '\r') {
		OneInputLine[position - 1] = '\0';
	} else {
		OneInputLine[position] = '\0';
	}
	/* also I dont want a '\r' in the hole input string */
	int i;
	for(i = 0; i < position; i++)
		if(OneInputLine[i] == '\r') OneInputLine[i] = ' ';
	int rest_len = (len - position) - 1;
	/* not I move the rest over the input-data on the begining of the string */
	for(i = 0; i < rest_len; i++)
	{
		InputData[i] = InputData[i+position+1];
	}
	InputData[rest_len] = '\0';
	return;
}

int Server::WriteMessageToServer(char * new_message)
{
	if(connect_status < STATUS_CONNECTED) return 0;
	int ret = -1, len = 0;
	len = strlen(new_message);
	if(len <= 0) return 0;
	/* check for \r\n at the end of the data */
#ifdef DEBUG
fprintf(stderr, "ToServer   ---> \"%s\"\n", new_message); fflush(stderr);
#endif
	if((new_message[len-1] != '\n') || (new_message[len-2] != '\r')) {
		/* end of new_message is not \r\n */
		char send_buf[len+3];
		memcpy(send_buf, new_message, len);
		send_buf[len] = '\r';
		send_buf[len+1] = '\n';
		send_buf[len+2] = '\0';
		ret = write(socketfd, send_buf, len+2);
	} else ret = write(socketfd, new_message, len);
	if(ret == -1) {
		Disconnect();
		if(Classes.IrcUser->GetAutoReconnect()) do_connect = 1;
			else do_connect = 0;
		if(errno == ECONNABORTED) { /* connection aborted */
			Classes.MsgDB->SetIrcChatMessage(0, DISPLAY_SERVERMSG, MESSAGE_ABORTED);
		} else if(errno == ECONNREFUSED) { /* connection refused */
			Classes.MsgDB->SetIrcChatMessage(0, DISPLAY_SERVERMSG, MESSAGE_REFUSED);
		} else if(errno == ECONNRESET) { /* connection reset */
			Classes.MsgDB->SetIrcChatMessage(0, DISPLAY_SERVERMSG, MESSAGE_RESET);
		} else { /* another error */
			char * connect_error = strerror(errno);
			snprintf(help_buffer, HELP_BUF_LEN, "Connection closed because of error \"%s\", please report this error to bugs@lancelot2k.dyndnsn.org", connect_error);
			Classes.MsgDB->SetIrcChatMessage(0, DISPLAY_ERROR, help_buffer);
		}
	} else {
		if(!cs_printed) {
			cs_printed = 1;
			Classes.MsgDB->SetIrcChatMessage(0, DISPLAY_AUTHINFO, MESSAGE_CONNECTED);
		}
	}
	Classes.IrcScreen->DrawTextScreen();
	return 1; /* OK */
}

int Server::GetAnswerTypeNr(void)
{
	if(Num_InputParameters <= 1) return 0; /* to less parameters */
	if(Num_InputParameters == 2) {
		/* the message has only 2 parts */
		if(Check_Parameter_for_space(0) || Check_Parameter_for_space(1)) return 0;
		if(strcmp(InputParameters[0], "PING") == 0) return PROTOCOL_NUM_PING;
		return 0;
	}
	if(strcmp(InputParameters[0], "NOTICE") == 0) return PROTOCOL_NUM_SERVERNOTICE;
	if(Num_InputParameters < 3) return 0; /* to less parameters */
	if(Check_Parameter_for_space(0) || Check_Parameter_for_space(1)) return 0;
	if(InputParameters[0][0] != ':') return 0; /* if the very first character is no dblpoint it is to be seen as a raw message */
	int len = strlen(&InputParameters[1][0]);
	/* Check the text for commands */
	if(len == 3) {
		/* we possibly have a numeric command */
		return atoi(InputParameters[1]);
	} else if(len == 4) {
		if(strcmp(InputParameters[1], "PONG") == 0) return PROTOCOL_NUM_PONG;
		if(strcmp(InputParameters[1], "JOIN") == 0) return PROTOCOL_NUM_JOIN;
		if(strcmp(InputParameters[1], "PART") == 0) return PROTOCOL_NUM_PART;
		if(strcmp(InputParameters[1], "QUIT") == 0) return PROTOCOL_NUM_QUIT;
		if(strcmp(InputParameters[1], "NICK") == 0) return PROTOCOL_NUM_NICK;
		if(strcmp(InputParameters[1], "MODE") == 0) return PROTOCOL_NUM_MODE;
		if(strcmp(InputParameters[1], "KICK") == 0) return PROTOCOL_NUM_KICK;
	} else if(len == 5) {
		if(strcmp(InputParameters[1], "TOPIC") == 0) return PROTOCOL_NUM_TOPIC;
	} else if(len == 6) {
		if(strcmp(InputParameters[1], "NOTICE") == 0) return PROTOCOL_NUM_NOTICE;
	} else if(len == 7) {
		if(strcmp(InputParameters[1], "PRIVMSG") == 0) return PROTOCOL_NUM_PRIVMSG;
		if(strcmp(InputParameters[1], "WALLOPS") == 0) return PROTOCOL_NUM_WALLOPS;
	}
	return 0;
}

void Server::LoginToServer(void)
{
	/* RFC 2812 entry about the USER command:
	 * Command: USER
	 * Parameters: <user> <mode> <unused> <realname>
	 *
	 * The USER command is used at the beginning of connection to specify
	 * the username, hostname and realname of a new user.

	 * The <mode> parameter should be a numeric, and can be used to
	 * automatically set user modes when registering with the server.  This
	 * parameter is a bitmask, with only 2 bits having any signification: if
	 * the bit 2 is set, the user mode 'w' will be set and if the bit 3 is
	 * set, the user mode 'i' will be set.  (See Section 3.1.5 "User
	 * Modes").
	 *
	 * The <realname> may contain space characters.
	 *
	 * Numeric Replies:
	 * ERR_NEEDMOREPARAMS              ERR_ALREADYREGISTRED
	 * Example:
	 *
	 * USER guest 0 * :Ronnie Reagan   ; User registering themselves with a
	 * 					username of "guest" and real name
	 * 					"Ronnie Reagan".
	 *
	 * USER guest 8 * :Ronnie Reagan   ; User registering themselves with a
	 * 					username of "guest" and real name
	 * 					"Ronnie Reagan", and asking to be set
	 * 					invisible.
	 * 
	 *
	 * and here some nice things from rfc 1459
	 * A "PASS" command is not required for either client or server
	 * connection to be registered, but it must precede the server message
	 * or the latter of the NICK/USER combination.  It is strongly
	 * recommended that all server connections have a password in order to
	 * give some level of security to the actual connections.  The
	 * recommended order for a client to register is as follows:
	 *
	 *     1. Pass message
	 *     2. Nick message
	 *     3. User message
	 * now make our user command */
	if(connect_status != STATUS_CONNECTED) return;
	/* try to set the nickname */
	snprintf(help_buffer, HELP_BUF_LEN, "NICK %s", Classes.IrcUser->GetNickname());
	WriteMessageToServer(help_buffer);
//	char * username = getenv("USER");;
//	if(username != NULL) {
//		if(username[0] == '\0') username = Classes.IrcUser->GetNickname();
//	} else username = Classes.IrcUser->GetNickname();
	snprintf(help_buffer, HELP_BUF_LEN, "USER netwalker 0 * :%s", Classes.IrcUser->GetRealname());
	WriteMessageToServer(help_buffer);
	connect_status = STATUS_LOGIN_TRIED;
	return;
}

void Server::ParseCommand_221(void)
{
	/* :network 221 <nickname> +<modes> */
	if(InputParameters[3][0] != '+') return; /* false format ? I have to check this! */
	snprintf(help_buffer, HELP_BUF_LEN, "modes for user %s: %s", InputParameters[2], InputParameters[3]);
	int screen_nr = Classes.IrcScreen->GetActiveChannel();
	Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_MODE, help_buffer);
	Parsing_Finished();
	return;
}

void Server::ParseCommand_265(void)
{
	PrintNormalText(DISPLAY_SERVERMSG);
	return;
}

void Server::ParseCommand_266(void)
{
	PrintNormalText(DISPLAY_SERVERMSG);
	return;
}

void Server::ParseCommand_267(void)
{
	PrintNormalText(DISPLAY_SERVERMSG);
	return;
}

void Server::ParseCommand_315(void)
{	
	/* we can safely ignore this */
	Parsing_Finished();
	return;
}

void Server::ParseCommand_318(void)
{	
	/* we can safely ignore this */
	Parsing_Finished();
	return;
}

void Server::ParseCommand_324(void)
{
	/* :network 324 <your nickname> #channel +<channel modes> [parameter1] [parameter2] [...] */
	char tmp_channelname[CHANNELS_NAME_LEN];
	GetChannelName(tmp_channelname, 3, CHANNELS_NAME_LEN);
	if(tmp_channelname[0] == '\0') return; /* false format */
	int screen_nr = Classes.IrcScreen->GetScreenNr(tmp_channelname, 0);
	Put_Text_together(3);
	snprintf(help_buffer, HELP_BUF_LEN, "Modes for #%s: %s", tmp_channelname, normal_text);
	Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_MODE, help_buffer);
	Parsing_Finished();
	return;
}

void Server::ParseCommand_329(void)
{
	/* :network 329 <your nickname> #channel <unix-timestamp> */
	char tmp_channelname[CHANNELS_NAME_LEN];
	GetChannelName(tmp_channelname, 3, CHANNELS_NAME_LEN);
	if(tmp_channelname[0] == '\0') return; /* false format */
	int screen_nr = Classes.IrcScreen->GetScreenNr(tmp_channelname, 0);
	if((signed)strlen(InputParameters[4]) < 9) return; /* this cant be a unix-timestamp, or the channel has been created a veeeery long time ago :) (actual timestamp len: 10) */
	time_t timestamp = atoi(InputParameters[4]);
	if(!timestamp) return; /* this were not only numbers */
	struct tm time_info;
	localtime_r(&timestamp, &time_info);
	snprintf(help_buffer, HELP_BUF_LEN, "This Channel has been built on %i.%i.%i - %.2i:%.2i", 
			time_info.tm_mday, time_info.tm_mon, (time_info.tm_year + 1900),
			time_info.tm_hour, time_info.tm_min);
	Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_DEFAULT, help_buffer);
	Parsing_Finished();
	return;
}

void Server::ParseCommand_331(void)
{
	/* :server 331 your_nickname #channel :No topic is set. */
	int screen_nr = Classes.IrcScreen->GetScreenNumForChannel(InputParameters[3]+1);
	if(!screen_nr) return; /* illegal command */
	snprintf(help_buffer, HELP_BUF_LEN, "no topic is set for this channel");
	Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_TOPIC, help_buffer);
	Parsing_Finished();
	return;
}

void Server::ParseCommand_332(void)
{
	TopicHandler(0);
	return;
}

void Server::ParseCommand_333(void)
{
	/* :network 333 <your nickname> #channel <the guy who set the topic> <unix-timestamp> */
	char tmp_channelname[CHANNELS_NAME_LEN];
	GetChannelName(tmp_channelname, 3, CHANNELS_NAME_LEN);
	if(tmp_channelname[0] == '\0') return; /* false format */
	int screen_nr = Classes.IrcScreen->GetScreenNr(tmp_channelname, 0);
	if(!screen_nr) return; /* no such channel */
	time_t timestamp = atoi(InputParameters[5]);
	if(!timestamp) { /* this were not only numbers */
		snprintf(help_buffer, HELP_BUF_LEN, "Topic set by %s", InputParameters[4]);
	} else {
		struct tm time_settings;
		localtime_r(&timestamp, &time_settings);
		snprintf(help_buffer, HELP_BUF_LEN, "Topic set by %s on %i.%i.%i - %.2i:%.2i",
				InputParameters[4], time_settings.tm_mday, time_settings.tm_mon,
				(time_settings.tm_year + 1900), time_settings.tm_hour, time_settings.tm_min);
	}
	Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_TOPIC, help_buffer);
	Parsing_Finished();
	return;
}

void Server::ParseCommand_353(void)
{
	/* :network 353 <your nickname> (= or * or @) #channel :[@ or +]<nick1> [[[@ or +]<nick2>]] [[[@ or +]<nick n>]] */
	if((signed)strlen(InputParameters[3]) != 1) return; /* false format */
	if((InputParameters[3][0] != '=') && (InputParameters[3][0] != '*') && (InputParameters[3][0] != '@')) return; /* false format */
	char tmp_channelname[CHANNELS_NAME_LEN];
	GetChannelName(tmp_channelname, 4, CHANNELS_NAME_LEN);
	if(tmp_channelname[0] == '\0') return; /* false format */
	if(InputParameters[5][0] != ':') return; /* false format */
	/* make the ':' away */
	make_first_char_away(InputParameters[5]);
	int num_names = Num_InputParameters - 5;
	for(int i = 0; i < num_names; i++)
	{
		if(InputParameters[5+i][0] == '@' || InputParameters[5+i][0] == '+')
			make_first_char_away(InputParameters[5+i]);
		if(InputParameters[5+i][0] != '\0') {
			Classes.IrcUserDB->Add_User(InputParameters[5+i], tmp_channelname);
		}
	}
	Classes.IrcScreen->DrawBottomScreen();
	Parsing_Finished();
	return;
}

void Server::ParseCommand_366(void)
{
	/* I dont have anything to do when I receive such a command.
	 * The reason is, that I simply add the usernames (commands: JOIN and 353) if they are not not in the database */
	Parsing_Finished();
	return;
}

void Server::ParseCommand_372(void)
{
	PrintNormalText(DISPLAY_SERVERMSG);
	return;
}

void Server::ParseCommand_375(void)
{
	PrintNormalText(DISPLAY_SERVERMSG);
	return;
}

void Server::ParseCommand_376(void)
{
	PrintNormalText(DISPLAY_SERVERMSG);
	return;
}

void Server::ParseCommand_401(void)
{
	/* :server 401 your_nickname #channel :No such nick/channel
	 * :server 401 your_nickanem other_nickname :No such nick/channel*/
	if(InputParameters[3][0] == '#') {
		/* this is because of a channel */
		snprintf(help_buffer, HELP_BUF_LEN, "No such channel: %s", InputParameters[3]);
	} else {
		/* this is because of a nickname */
		snprintf(help_buffer, HELP_BUF_LEN, "No such nickname: %s", InputParameters[3]);
	}
	int active_channel = Classes.IrcScreen->GetActiveChannel();
	Classes.MsgDB->SetIrcChatMessage(active_channel, DISPLAY_ERROR, help_buffer);
	Parsing_Finished();
	return;
}

void Server::ParseCommand_403(void)
{
	/* :server 403 your_nickname #channel :That channel doesn't exist */
	snprintf(help_buffer, HELP_BUF_LEN, "That channel doesn't exist: %s", InputParameters[3]);
	int active_channel = Classes.IrcScreen->GetActiveChannel();
	Classes.MsgDB->SetIrcChatMessage(active_channel, DISPLAY_ERROR, help_buffer);
	Parsing_Finished();
	return;
}

void Server::ParseCommand_421(void)
{
	/* :server 421 your_nickname command :Unknown command */
	snprintf(help_buffer, HELP_BUF_LEN, "Unknown command: %s", InputParameters[3]);
	int active_channel = Classes.IrcScreen->GetActiveChannel();
	Classes.MsgDB->SetIrcChatMessage(active_channel, DISPLAY_ERROR, help_buffer);
	Parsing_Finished();
	return;
}

void Server::ParseCommand_433(void)
{
	int screen_nr = Classes.IrcScreen->GetActiveChannel();
	if(STATUS_ALL_OK != 1) {
		/* we are not successfully logged in
		 * lets add a '_' to the nickname and try it again */
		snprintf(help_buffer, HELP_BUF_LEN, "%s_", Classes.IrcUser->GetNickname());
		if(strlen(help_buffer) > NICKNAME_LEN - 1) help_buffer[NICKNAME_LEN/2] = '\0';
		Classes.IrcUser->SetNickname(help_buffer);
		snprintf(help_buffer, HELP_BUF_LEN, "NICK %s", Classes.IrcUser->GetNickname());
		WriteMessageToServer(help_buffer);
		snprintf(help_buffer, HELP_BUF_LEN, "Nickname allready in use, retrying with %s", Classes.IrcUser->GetNickname());
		Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_ERROR, help_buffer);
	} else Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_ERROR, "Nickname allready in use.");
	Parsing_Finished();
	return;
}

void Server::ParseCommand_451(void)
{
	/* blub, and what now? :)
	 * the messages will be repeatet anyway, so I can ignore that. */
	Parsing_Finished();
	return;
}

void Server::ParseCommand_461(void)
{
	/* :server 461 your_nickname MODE :Not enough parameters */
	snprintf(help_buffer, HELP_BUF_LEN, "not enough parameters for command: %s", InputParameters[3]);
	int active_channel = Classes.IrcScreen->GetActiveChannel();
	Classes.MsgDB->SetIrcChatMessage(active_channel, DISPLAY_ERROR, help_buffer);
	Parsing_Finished();
	return;
}

void Server::ParseCommand_473(void)
{
	/* :server 473 your_nickname #channel :Cannot join channel (+i) */
	snprintf(help_buffer, HELP_BUF_LEN, "you cannot join the channel %s because this channel is invite only!", InputParameters[3]);
	int active_channel = Classes.IrcScreen->GetActiveChannel();
	Classes.MsgDB->SetIrcChatMessage(active_channel, DISPLAY_ERROR, help_buffer);
	Parsing_Finished();
	return;
}

void Server::ParseCommand_474(void)
{
	/* :server 474 your_nickname #channel :Cannot join channel (+b) */
	snprintf(help_buffer, HELP_BUF_LEN, "you cannot join the channel %s because you are banned from this server!", InputParameters[3]);
	int active_channel = Classes.IrcScreen->GetActiveChannel();
	Classes.MsgDB->SetIrcChatMessage(active_channel, DISPLAY_ERROR, help_buffer);
	Parsing_Finished();
	return;
}

void Server::ParseCommand_475(void)
{
	/* :server 475 your_nickname #channel :Cannot join channel (+k) */
	snprintf(help_buffer, HELP_BUF_LEN, "you cannot join the channel %s because this channel is password protected! (use /join %s password)", InputParameters[3], InputParameters[3]);
	int active_channel = Classes.IrcScreen->GetActiveChannel();
	Classes.MsgDB->SetIrcChatMessage(active_channel, DISPLAY_ERROR, help_buffer);
	Parsing_Finished();
	return;
}

void Server::ParseCommand_502(void)
{
	/* :network 502 <your nickname> :<message> */
	int screen_nr = Classes.IrcScreen->GetActiveChannel();
	Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_ERROR, "You can't change someone else's modes");
	Parsing_Finished();
	return;
}

void Server::ParseCommand_PONG(void)
{
	/* perhaps I'll later write some code to check the delay between
	 * PING and PONG */
	Parsing_Finished();
	return;
}

void Server::ParseCommand_PRIVMSG(void)
{
	 /* here some examples for /me or ctcp
	 * +----+----+----+----+----+----+----+----+----+----+----+
	 * |  0 |  1 |  2 |  3 |  4 |  5 |  6 |  7 |  8 |  9 | 10 |
	 * +----+----+----+----+----+----+----+----+----+----+----+
	 * | \1 |  A |  C |  T |  I |  O |  N |    |  A | \1 | \0 |
	 * +----+----+----+----+----+----+----+----+----+----+----+
	 * | \1 |  V |  E |  R |  S |  I |  O |  N | \1 | \0 |    |
	 * +----+----+----+----+----+----+----+----+----+----+----+
	 * */
	char nickname[NICKNAME_LEN];
	GetSenderName(nickname, 0, NICKNAME_LEN);
	if(nickname[0] == '\0') return; /* false format */
	Put_Text_together(3);
	int slashme = 0;
	int actionmsg = 0;
	int len = strlen(normal_text);
	if(len >= 3) {
		if((normal_text[0] == 1) && (normal_text[len-1] == 1)) {
			normal_text[len-1] = '\0';
			actionmsg = 1;
			if((len >= 10) && (strncmp(normal_text+1, "ACTION ", 7) == 0)) {
				slashme = 1;
				snprintf(help_buffer, HELP_BUF_LEN, "%s %s", nickname, normal_text+8);
			}
		}
	}
	/* is there a # after the PRIVMSG? when yes: this message is for a channel */
	if(InputParameters[2][0] == '#') {
		/* OK, this is for a channel */
		char channelname[CHANNELS_NAME_LEN];
		GetChannelName(channelname, 2, CHANNELS_NAME_LEN);
		if(channelname[0] == '\0') return; /* false format */
		int screen = Classes.IrcScreen->GetScreenNr(channelname, 0);
		if(slashme) {
			Classes.MsgDB->SetIrcChatMessage(screen, DISPLAY_MEACTION, help_buffer);
		} else {
			Classes.MsgDB->SetIrcChatMessage(screen, nickname, normal_text);
		}
	} else {
		int screen = Classes.IrcScreen->GetScreenNr(nickname, 1);
		if(!screen) {
			/* there was no screen found for this message, get a new one */
			screen = Classes.IrcScreen->GetNotUsedScreen(1);
			if(!screen) return; /* no screen left */
			Classes.IrcScreen->SetDirectChatNick(screen, nickname);
			Classes.IrcScreen->SetActiveChannel(screen); /* we change to this screen because it is the inital message */
		}
		/* It seems to be a direct chat message but it could also be a CTCP message!
		 * so I first check if it is a CTCP message */
		if((actionmsg) && (!slashme)) {
			snprintf(help_buffer, HELP_BUF_LEN, "%s", normal_text+1);
			string_toupper(help_buffer);
			if(strcmp(help_buffer, "VERSION") == 0) {
				snprintf(normal_text, HELP_BUF_LEN, "received a CTCP %s from %s", help_buffer, nickname);
				snprintf(help_buffer, HELP_BUF_LEN, "NOTICE %s :\1VERSION %s\1", nickname, CTCP_VERSION_REPLY);
				WriteMessageToServer(help_buffer);
			} else {
				snprintf(normal_text, HELP_BUF_LEN, "received a CTCP %s from %s", help_buffer, nickname);
			}
			Classes.MsgDB->SetIrcChatMessage(screen, DISPLAY_CTCP, normal_text);
			Parsing_Finished();
			return;
		}
		if(slashme) {
			Classes.MsgDB->SetIrcChatMessage(screen, DISPLAY_MEACTION, help_buffer);
		} else {
			Classes.MsgDB->SetIrcChatMessage(screen, nickname, normal_text);
		}
	}
	Parsing_Finished();
	return;
}

void Server::ParseCommand_NOTICE(void)
{
	/* :nickname@addr NOTICE <your nickname> :message
	 * :nickname@addr NOTICE <your nickname> :[#channel] channelmessage
	 * :nickname@addr NOTICE #channel :message */
	char notice_nickname[NICKNAME_LEN];
	GetSenderName(notice_nickname, 0, NICKNAME_LEN);
	if(notice_nickname[0] == '\0') return; /* false format */
	if(InputParameters[3][0] != ':') return;
	/* check if this is a channelnotice */
	int channelmsg = 0;
	int len = (signed)strlen(InputParameters[3]);
	if(len >= 5 && !Check_Parameter_for_space(3)) { /* exapmle: ":[#A]" is possible, but ":[#]" or ":[# ]" is not ! */
		if((InputParameters[3][0] == ':') && (InputParameters[3][1] == '[')  && (InputParameters[3][2] == '#') && (InputParameters[3][len-1] == ']')) {
			/* ok, this is a notice for a channel */
			Put_Text_together(4);
			channelmsg = 1;
			char notice_channel[CHANNELS_NAME_LEN];
			int channelnamelen = len - 4;
			if(channelnamelen >= CHANNELS_NAME_LEN) channelnamelen = CHANNELS_NAME_LEN - 1;
			memcpy(notice_channel, &InputParameters[3][3], channelnamelen);
			notice_channel[channelnamelen] = '\0';
			notice_channel[channelnamelen] = '\0';
			snprintf(help_buffer, HELP_BUF_LEN, "%s: %s", notice_nickname, normal_text);
			int screen_nr = Classes.IrcScreen->GetScreenNumForChannel(notice_channel);
			Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_NOTICE, help_buffer);
			Parsing_Finished();
		}
	}
	if(!channelmsg) {
		Put_Text_together(3);
		int ctcp = 0;
		int len = strlen(normal_text);
		if((normal_text[0] == 1) && (normal_text[len-1] == 1)) { /* could be a CTCP reply */
			ctcp = 1;
			if(len < 3) return; /* false format*/
			int first_space_pos = position_of_num_char(normal_text, ' ', 1);
			normal_text[0] = normal_text[len-1] = '\0';
			if(first_space_pos == 1) return; /* false format -> "\1 anything\1"*/
			if(first_space_pos == len-2) return; /* false format -> "\1anything \1" */
			if(first_space_pos != -1) { /* we have parameters */
				normal_text[first_space_pos] = '\0';
				string_toupper(normal_text+1);
				snprintf(help_buffer, HELP_BUF_LEN, "%s response from %s: \"%s\"", normal_text+1, notice_nickname, normal_text+first_space_pos+1);
			} else {
				snprintf(help_buffer, HELP_BUF_LEN, "%s response from %s without parameters", normal_text+1, notice_nickname);
			}
			Classes.MsgDB->SetIrcChatMessage(Classes.IrcScreen->GetActiveChannel(), DISPLAY_CTCP, help_buffer);
		}
		if(!ctcp) {
			int screen_nr = 0;
			if(InputParameters[2][0] == '#') {
				/* channelnotice from a user */
				char tmp_channel[CHANNELS_NAME_LEN];
				GetChannelName(tmp_channel, 2, CHANNELS_NAME_LEN);
				if(tmp_channel[0] == '\0') return;
				screen_nr = Classes.IrcScreen->GetScreenNumForChannel(tmp_channel);
				if(!screen_nr) return;
			} else {
				screen_nr = Classes.IrcScreen->GetActiveChannel();
			}
			snprintf(help_buffer, HELP_BUF_LEN, "%s: %s", notice_nickname, normal_text);
			Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_NOTICE, help_buffer);
		}
	}
	Parsing_Finished();
	return;
}

void Server::ParseCommand_JOIN(void)
{
	/* :user!~pcname@addr JOIN :#channel */
	char tmp_channelname[CHANNELS_NAME_LEN];
	char tmp_nickname[NICKNAME_LEN];
	GetChannelName(tmp_channelname, 2, CHANNELS_NAME_LEN);
	GetSenderName(tmp_nickname, 0, NICKNAME_LEN);
	if(tmp_nickname[0] == '\0' || tmp_channelname[0] == '\0') return; /* false format */
	if(strcmp(tmp_nickname, Classes.IrcUser->GetNickname()) == 0) {
		/* this is a join Message for our nickname */
		int new_screen = Classes.IrcScreen->GetNotUsedScreen(0); /* get a screen for a channel */
		if(!new_screen) return;
		Classes.IrcScreen->SetChannelName(new_screen, tmp_channelname);
		Classes.IrcScreen->SetActiveChannel(new_screen);
		snprintf(help_buffer, HELP_BUF_LEN, "You have joined #%s", tmp_channelname);
		Classes.MsgDB->SetIrcChatMessage(new_screen, DISPLAY_JOIN, help_buffer);
		Classes.IrcUserDB->Init_UserDB(tmp_channelname); /* create a new database for the usersnames in this channel */
		Classes.IrcScreen->DrawBottomScreen();
		Parsing_Finished();
		return;
	}
	/* this is a normal join message 
	 * now check if there is a channel called like the string in tmp_channelname */
	int screen = Classes.IrcScreen->GetScreenNr(tmp_channelname, 0);
	if(!screen) return;
	snprintf(help_buffer, HELP_BUF_LEN, "%s has joined #%s", tmp_nickname, tmp_channelname);
	Classes.MsgDB->SetIrcChatMessage(screen, DISPLAY_JOIN, help_buffer);
	Classes.IrcUserDB->Add_User(tmp_nickname, tmp_channelname);
	Classes.IrcScreen->DrawBottomScreen();
	Parsing_Finished();
	return;
}

void Server::ParseCommand_PART(void)
{
	/* :user!~pcname@addr PART #channel :"message" */
	char tmp_channelname[CHANNELS_NAME_LEN];
	char tmp_nickname[NICKNAME_LEN];
	GetChannelName(tmp_channelname, 2, CHANNELS_NAME_LEN);
	GetSenderName(tmp_nickname, 0, NICKNAME_LEN);
	if(tmp_nickname[0] == '\0' || tmp_channelname[0] == '\0') return; /* false format */
	if(strcmp(tmp_nickname, Classes.IrcUser->GetNickname()) == 0) {
		/* this is a part Message for our nickname */
		int screen = Classes.IrcScreen->GetScreenNr(tmp_channelname, 0);
		if(!screen) return;
		Classes.IrcScreen->EmptyScreen(screen);
		snprintf(help_buffer, HELP_BUF_LEN, "You have left #%s", tmp_channelname);
		Classes.MsgDB->SetIrcChatMessage(screen, DISPLAY_PART, help_buffer);
		Classes.IrcUserDB->Reset_UserDB(tmp_channelname);
		Classes.IrcScreen->DrawBottomScreen();
		Parsing_Finished();
		return;
	}
	/* this is a normal part message 
	 * now check if there is a channel called like the string in tmp_channelname */
	int screen = Classes.IrcScreen->GetScreenNr(tmp_channelname, 0);
	if(!screen) return;
	/* now get the leave message */
	Put_Text_together(3);
	if(normal_text[0] == '\0') {
		snprintf(help_buffer, HELP_BUF_LEN, "%s has left #%s", tmp_nickname, tmp_channelname);
	} else {
		snprintf(help_buffer, HELP_BUF_LEN, "%s has left #%s - %s", tmp_nickname, tmp_channelname, normal_text);
	}
	Classes.MsgDB->SetIrcChatMessage(screen, DISPLAY_PART, help_buffer);
	Classes.IrcUserDB->Remove_User_from_Channel(tmp_nickname, tmp_channelname);
	Classes.IrcScreen->DrawBottomScreen();
	Parsing_Finished();
	return;
}

void Server::ParseCommand_QUIT(void)
{
	/* :nickname!pcname@addr QUIT :"leave-message" */
	char tmp_nickname[NICKNAME_LEN];
	GetSenderName(tmp_nickname, 0, NICKNAME_LEN);
	if(tmp_nickname == '\0') return; /* false format */
	/* get the quit message */
	Put_Text_together(2);
	if(normal_text[0] == '\0') {
		snprintf(help_buffer, HELP_BUF_LEN, "%s has quit from the IRC-Network", tmp_nickname);
	} else {
		snprintf(help_buffer, HELP_BUF_LEN, "%s has quit from the IRC-Network - %s", tmp_nickname, normal_text);
	}
	/* write a message to every channel this user was in */
	for(int i = 1; i < CHANNELS_MAX; i++)
	{
		if(Classes.IrcScreen->GetScreenUse(i) == 0) continue; /* this screen is anyway not used */
		if(Classes.IrcScreen->GetScreenType(i) == 1) {
			/* this screen is used for a direct chat */
			if(strcmp(Classes.IrcScreen->GetDirectChatNick(i), tmp_nickname) == 0) {
				Classes.IrcScreen->EmptyScreen(i);
				Classes.MsgDB->SetIrcChatMessage(i, DISPLAY_QUIT, help_buffer);
			}
		} else {
			char * tmp_channel = Classes.IrcScreen->GetChannelName(i);
			if(tmp_channel == NULL) continue;
			int index = Classes.IrcUserDB->Is_User_in_Channel(tmp_nickname, tmp_channel);
			if(index != -1) {
				/* the user is in this channel */
				Classes.IrcUserDB->Remove_User_from_Channel(index, tmp_channel); 
				Classes.MsgDB->SetIrcChatMessage(i, DISPLAY_QUIT, help_buffer);
			}
		}
	}
	Classes.IrcScreen->DrawBottomScreen();
	Parsing_Finished();
	return;
}

void Server::ParseCommand_NICK(void)
{
	/* :old_name!~pcname@ip NICK :new_name */
	char tmp_nickname[NICKNAME_LEN];
	GetSenderName(tmp_nickname, 0, NICKNAME_LEN);
	if(tmp_nickname[0] == '\0') return; /* false format */
	if(InputParameters[2][0] != ':') return;
	make_first_char_away(InputParameters[2]);
	if(InputParameters[2][0] == '\0') return;
	if(strcmp(Classes.IrcUser->GetNickname(), tmp_nickname) == 0) {
		/* we changed our nickname */
		Classes.IrcUser->SetNickname(InputParameters[2]);
		snprintf(help_buffer, HELP_BUF_LEN, "you have changed your nickname to %s", InputParameters[2]);
		if(Classes.IrcScreen->GetActiveChannel() == 0)
			/* we are on the server screen */
			Classes.MsgDB->SetIrcChatMessage(0, DISPLAY_NICKNAME, help_buffer);
		Classes.IrcScreen->DrawBottomScreen();
	} else {
		snprintf(help_buffer, HELP_BUF_LEN, "%s has changed his nickname to %s", tmp_nickname, InputParameters[2]);
	}
	int index;
	char * tmp_channel;
	int screen_nr = Classes.IrcScreen->GetScreenNumForDirectChat(tmp_nickname);
	if(screen_nr > 0) {
		Classes.IrcScreen->SetDirectChatNick(screen_nr, InputParameters[2]);
		Classes.IrcScreen->DrawTopScreen();
		Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_NICKNAME, help_buffer);
	}
	for(int i = 0; i < CHANNELS_MAX; i++)
	{
		/* check every screen if we have to update the informations */
		if(Classes.IrcScreen->GetScreenUse(i) != 1) continue; /* this screen is not used */
		if(Classes.IrcScreen->GetScreenType(i) == 0) { /* channel */
			tmp_channel = Classes.IrcScreen->GetChannelName(i);
			index = Classes.IrcUserDB->Is_User_in_Channel(tmp_nickname, tmp_channel);
			if(index != -1) {
				/* replace the nickname for this user in the database and print a message on the screen */
				Classes.IrcUserDB->Remove_User_from_Channel(index, tmp_channel);
				Classes.IrcUserDB->Add_User(InputParameters[2], tmp_channel);
				Classes.MsgDB->SetIrcChatMessage(i, DISPLAY_NICKNAME, help_buffer);
			}
		} else { /* direct chat */
		}
	}
	Parsing_Finished();
	return;
}

void Server::ParseCommand_MODE(void)
{
	/*            :who!pcname@network MODE #channel [:]+<modes> <parameter1> [parameter2] [...]
	   user modes :<nickname who changed a mode of a user> MODE <nickname of the target> [:]+<modes> */
	char tmp_channelname[CHANNELS_NAME_LEN];
	char tmp_nickname[NICKNAME_LEN];
	GetChannelName(tmp_channelname, 2, CHANNELS_NAME_LEN);
	GetSenderName(tmp_nickname, 0, NICKNAME_LEN);
	if(tmp_nickname[0] == '\0') return; /* false format*/
	int screen_nr;
	int dblp = 1;
	int modelen = (signed)strlen(InputParameters[3]) - 1;
	if(InputParameters[3][0] != ':')
		dblp = 0;
	else
		modelen--;
	if(modelen < 1) return; /* false format -> not a single mode :/ */
	if((InputParameters[3][dblp] != '-') && (InputParameters[3][dblp] != '+')) return;
	int plus = 1;
	if(InputParameters[3][dblp] == '-') plus = 0;
	if(tmp_channelname[0] == '\0') {
		screen_nr = Classes.IrcScreen->GetActiveChannel();
		/* possibly user modes */
		for(int i = 0; i < modelen; i++) {
			switch(InputParameters[3][i+1+dblp])
			{
				case 'i':
					if(plus) {
						snprintf(help_buffer, HELP_BUF_LEN, "%s sets invisible mode on %s", tmp_nickname, InputParameters[2]);
					} else snprintf(help_buffer, HELP_BUF_LEN, "%s removes invisible mode from %s", tmp_nickname, InputParameters[2]);
					Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_MODE, help_buffer);
					break;
				case 'w':
					if(plus) {
						snprintf(help_buffer, HELP_BUF_LEN, "%s sets the wallop flag on %s", tmp_nickname, InputParameters[2]);
					} else snprintf(help_buffer, HELP_BUF_LEN, "%s removes the wallop flag form %s", tmp_nickname, InputParameters[2]);
					Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_MODE, help_buffer);
					break;
				case 'C':
					if(plus) {
						snprintf(help_buffer, HELP_BUF_LEN, "%s sets mode +C on %s (this user no longer receives CTCP messages)", tmp_nickname, InputParameters[2]);
					} else snprintf(help_buffer, HELP_BUF_LEN, "%s sets mode -C on %s (this user can receive CTCP messages)", tmp_nickname, InputParameters[2]);
					Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_MODE, help_buffer);
					break;
				default:
					snprintf(help_buffer, HELP_BUF_LEN, "%s sets mode %c%c on %s", tmp_nickname, InputParameters[3][dblp], InputParameters[3][i+1+dblp], InputParameters[2]);
					Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_MODE, help_buffer);
					break;
			} /* end of "switch(InputParameters[3][i+1+dblp])" */
		} /* end of "for(int i = 0; i < modelen; i++)" */
	} else {
		screen_nr = Classes.IrcScreen->GetScreenNumForChannel(tmp_channelname);
		/* channel modes */
		int nextparameter = 0;
		for(int i = 0; i < modelen; i++) {
			switch(InputParameters[3][i+1+dblp])
			{
				case 'l':
					if(plus) {
						snprintf(help_buffer, HELP_BUF_LEN, "%s set the user limit for this channel to %i", tmp_nickname, atoi(InputParameters[4+nextparameter]));
						nextparameter++;
					} else snprintf(help_buffer, HELP_BUF_LEN, "%s removes the user limit from this channel", tmp_nickname);
					Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_MODE, help_buffer);
					break;
				case 'o':
					if(plus) {
						snprintf(help_buffer, HELP_BUF_LEN, "%s gives channel operator status to %s", tmp_nickname, InputParameters[4+nextparameter]);
					} else snprintf(help_buffer, HELP_BUF_LEN, "%s removes operator status from %s", tmp_nickname, InputParameters[4+nextparameter]);
					nextparameter++;
					Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_MODE, help_buffer);
					break;
				case 'v':
					if(plus) {
						snprintf(help_buffer, HELP_BUF_LEN, "%s gives voice on %s", tmp_nickname, InputParameters[4+nextparameter]);
					} else snprintf(help_buffer, HELP_BUF_LEN, "%s removes voice on %s", tmp_nickname, InputParameters[4+nextparameter]);
					nextparameter++;
					Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_MODE, help_buffer);
					break;
				case 'b':
					if(plus) {
						snprintf(help_buffer, HELP_BUF_LEN, "%s sets ban on %s", tmp_nickname, InputParameters[4+nextparameter]);
					} else snprintf(help_buffer, HELP_BUF_LEN, "%s removes ban on %s", tmp_nickname, InputParameters[4+nextparameter]);
					nextparameter++;
					Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_MODE, help_buffer);
					break;
				case 'e':
					if(plus) {
						snprintf(help_buffer, HELP_BUF_LEN, "%s marks you as an identified user", tmp_nickname);
					} else snprintf(help_buffer, HELP_BUF_LEN, "%s marks you as no longer identified", tmp_nickname);
					Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_MODE, help_buffer);
					break;
				case 'k':
					if(plus) {
						snprintf(help_buffer, HELP_BUF_LEN, "%s sets a password for this channel: \"%s\"", tmp_nickname, InputParameters[4+nextparameter]);
					} else snprintf(help_buffer, HELP_BUF_LEN, "%s removes the password from this channel, which was: \"%s\"", tmp_nickname, InputParameters[4+nextparameter]);
					nextparameter++;
					Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_MODE, help_buffer);
					break;
				case 'n':
					if(plus) {
						snprintf(help_buffer, HELP_BUF_LEN, "%s set mode +n -> users outside this channel may not send messages to it", tmp_nickname);
					} else snprintf(help_buffer, HELP_BUF_LEN, "%s set mode -n -> users outside this channel may send messages to it", tmp_nickname);
					Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_MODE, help_buffer);
					break;
				default:
					snprintf(help_buffer, HELP_BUF_LEN, "%s sets mode %c%c on %s", tmp_nickname, InputParameters[3][dblp], InputParameters[3][i+1+dblp], InputParameters[2]);
					Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_MODE, help_buffer);
					break;
			} /* end of "switch(OneInputLine[position+1+i])" */
		} /* end of "for(int i = 0; i < modelen; i++)"*/
	} /* end of "if(tmp_channelname[0] == '\0')" */
	Classes.IrcScreen->DrawBottomScreen();
	Parsing_Finished();
	return;
}

void Server::ParseCommand_KICK(void)
{
	/* :admin_name!~pcname_of_admin@ip_of_admin KICK #channel kicked_person :reason */
	char tmp_channelname[CHANNELS_NAME_LEN];
	char tmp_nickname[NICKNAME_LEN];
	GetChannelName(tmp_channelname, 2, CHANNELS_NAME_LEN);
	GetSenderName(tmp_nickname, 0, NICKNAME_LEN);
	if(tmp_channelname[0] == '\0' || tmp_nickname[0] == '\0') return; /* false format */
	int tmp_channr = Classes.IrcScreen->GetScreenNr(tmp_channelname, 0);
	if(strcmp(Classes.IrcUser->GetNickname(), InputParameters[3]) == 0)
	{
		/* damn, we were kicked out :( */
		if(Num_InputParameters >= 5) { /* we have a reason */
			Put_Text_together(4);
			snprintf(help_buffer, HELP_BUF_LEN, "%s kicked you - reason: %s", tmp_nickname, normal_text);
		} else {
			snprintf(help_buffer, HELP_BUF_LEN, "%s kicked you", tmp_nickname);
		}
		Classes.IrcScreen->EmptyScreen(tmp_channr);
		Classes.IrcUserDB->Reset_UserDB(tmp_channelname);
	} else {
		if(Num_InputParameters >= 5) { /* we have a reason */
			Put_Text_together(4);
			snprintf(help_buffer, HELP_BUF_LEN, "%s kicked %s - reason: %s", tmp_nickname, InputParameters[3], normal_text);
		} else {
			snprintf(help_buffer, HELP_BUF_LEN, "%s kicked %s", tmp_nickname, InputParameters[3]);
		}
		Classes.IrcUserDB->Remove_User_from_Channel(InputParameters[3], tmp_channelname);
		Classes.IrcScreen->DrawBottomScreen();
	}
	Classes.MsgDB->SetIrcChatMessage(tmp_channr, DISPLAY_KICK, help_buffer);
	Parsing_Finished();
	return;
}

void Server::ParseCommand_TOPIC(void)
{
	TopicHandler(1);
	return;
}

void Server::ParseCommand_PING(void)
{
	/* PING :number */
	if(InputParameters[1][0] != ':' || strlen(InputParameters[1]) < 2) return; /* false format */
	snprintf(help_buffer, HELP_BUF_LEN, "PONG %s", InputParameters[1]);
	WriteMessageToServer(help_buffer);
	Parsing_Finished();
	return;
}

void Server::ParseCommand_WALLOPS(void)
{
	/* :wallop!pcname@addr WALLOPS :wallop message */
	char wallop[NICKNAME_LEN];
	if(wallop[0] == '\0') return; /* hmmmm? */
	GetSenderName(wallop, 0, NICKNAME_LEN);
	Put_Text_together(3);
	snprintf(help_buffer, HELP_BUF_LEN, "%s: %s", wallop, normal_text);
	Classes.MsgDB->SetIrcChatMessage(Classes.IrcScreen->GetActiveChannel(), DISPLAY_WALLOPS, help_buffer);
	Parsing_Finished();
	return;
}

void Server::ParseCommand_SERVERNOTICE(void)
{
	/* "NOTICE <something> :*** <blabla text>" */
	if(strcmp(InputParameters[2], ":***") == 0 && Num_InputParameters > 3) {
		Put_Text_together(3);
		Classes.MsgDB->SetIrcChatMessage(0, DISPLAY_AUTHINFO, normal_text);
		Parsing_Finished();
	}
	return;
}

void Server::PingServer(void)
{
	if(connect_status < STATUS_CONNECTED) return;
	/* do we have to send a ping? */
	int time_now = time(NULL);
	if((time_now - last_ping) < DELAY_BETWEEN_PING) return;
	/* we have to send a ping */
	last_ping = time_now;
	int random_lag_nr = (int)(1+(rand() % 1000000000));
	snprintf(help_buffer, HELP_BUF_LEN, "PING LAG%i", random_lag_nr);
	WriteMessageToServer(help_buffer);
	return;
}

void Server::GetSenderName(char * Destination, int Source_Parameter, int max_dest_len)
{
	Destination[0] = '\0';
	if(Check_Parameter_for_space(Source_Parameter)) return;
	if(InputParameters[Source_Parameter][0] != ':') return; /* false format */
	int position = position_of_num_char(InputParameters[Source_Parameter], '!', 1);
	if((position != -1) && (position < 2)) return; /* false format (we have a '!' but the format is ":!")*/
	position--;
	/* 'position' is now the length of the nickname if we have a '!'. in the other case the rest of the string is the username */
	if(position == -2) {
		int len = (signed)strlen(InputParameters[Source_Parameter]) - 1;
		if(len >= max_dest_len) len = max_dest_len - 1;
	        memcpy(Destination, &InputParameters[Source_Parameter][1], len);
	        Destination[len] = '\0';
	} else {
	        if(position >= max_dest_len) position = max_dest_len - 1;
	        memcpy(Destination, &InputParameters[Source_Parameter][1], position);
	        Destination[position] = '\0';
	}
	return;
}

void Server::GetChannelName(char * Destination, int Source_Parameter, int max_dest_len)
{
	Destination[0] = '\0';
	if(Check_Parameter_for_space(Source_Parameter)) return;
	int msg_len = strlen(InputParameters[Source_Parameter]);
	int with_dblpoint = -1;
	if(InputParameters[Source_Parameter][0] == '#') {
		with_dblpoint = 0;
	} else if((InputParameters[Source_Parameter][0] == ':') || (InputParameters[Source_Parameter][1] == '#')) {
		with_dblpoint = 1;
	} else return; /* false format */
	int channel_namelen = (msg_len - 1) - with_dblpoint;
	if(channel_namelen < 1) return; /* channel name is smaller than 1 char :) */
	if(channel_namelen >= max_dest_len) channel_namelen = max_dest_len - 1;
	memcpy(Destination, &InputParameters[Source_Parameter][1+with_dblpoint], channel_namelen);
	Destination[channel_namelen] = '\0';
	/* make the channel name to lowercase */
	string_tolower(Destination);
	return;
}

void Server::PARTChannelorChat(char * user_input)
{
	if(connect_status < STATUS_CONNECTED) return;
	int active_channel = Classes.IrcScreen->GetActiveChannel();
	if(!active_channel) {
		Classes.MsgDB->SetIrcChatMessage(0, DISPLAY_PART, "cannot leave this screen :)");
		return;
	}
	if(!Classes.IrcScreen->GetScreenUse(active_channel)) return; /* screen is not used */
	if(Classes.IrcScreen->GetScreenType(active_channel) == 1) {
		/* this is a direct chat */
		Classes.IrcScreen->EmptyScreen(active_channel);
		return;
	}
	/* we are in a channel */
	int msg = 0;
	if(user_input) {
		if(strlen(user_input)) {
			/* we have a leavemsg */
			snprintf(help_buffer, HELP_BUF_LEN, "PART #%s :%s", Classes.IrcScreen->GetChannelName(active_channel), user_input);
			msg = 1;
		}
	}
	if(!msg) {
		/* we havent got a leavemsg */
		snprintf(help_buffer, HELP_BUF_LEN, "PART #%s :%s", Classes.IrcScreen->GetChannelName(active_channel), Classes.IrcUser->GetLeaveMessage());
	}
	WriteMessageToServer(help_buffer);
	return;
}

void Server::QUITIrc(char * user_input)
{
	if(connect_status < STATUS_CONNECTED) {
		Classes.IrcScreen->EndNcurses();
		exit(0);
	}
	int msg = 0;
	if(user_input) {
		if(strlen(user_input)) {
			/* we have a leavemsg */
			snprintf(help_buffer, HELP_BUF_LEN, "QUIT :%s", user_input);
			msg = 1;
		}
	}
	if(!msg) {
		/* we havent got a leavemsg */
		snprintf(help_buffer, HELP_BUF_LEN, "QUIT :%s", Classes.IrcUser->GetLeaveMessage());
	}
	WriteMessageToServer(help_buffer);
	Disconnect();
	Classes.IrcScreen->EndNcurses();
	exit(0);
	return;
}

void Server::JOINChannel(char * channel_name)
{
	if(connect_status < STATUS_CONNECTED) return;
	int controll = 0;
	if(channel_name) {
		/* we have got a channel name */
		controll = 1;
		int len = strlen(channel_name);
		if(len < 2) {
			controll = 0;
		} else {
			/* we have at least 2 chars */
			if(channel_name[0] == '#') {
				snprintf(help_buffer, HELP_BUF_LEN, "JOIN %s", channel_name);
				WriteMessageToServer(help_buffer);
			} else controll = 0;
		}
	}
	if(!controll) {
		/* we do not have a channel name */
		help_me("join");
	}
	return;
}

void Server::DirectMSG(char * user_input)
{
	if(connect_status < STATUS_CONNECTED) return;
	int controll = 0;
	if(user_input) {
		/* we have a nickname */
		controll = 1;
		int len = strlen(user_input);
		int spacepos = position_of_num_char(user_input, ' ', 1);
		if((spacepos == -1) || (spacepos == 0)) {
			controll = 0; /* no space or space at the beginning */
		} else if((len < 3) || (spacepos < 1) || (len-1 == spacepos)) {
			controll = 0;
		} else {
			user_input[spacepos] = '\0';
			snprintf(help_buffer, HELP_BUF_LEN, "PRIVMSG %s :%s", user_input, user_input+spacepos+1);
			WriteMessageToServer(help_buffer);
		}
	}
	if(!controll) {
		/* no nickname given */
		help_me("msg");
	}
	return;
}

void Server::MECommand(char * user_input)
{
	if(connect_status < STATUS_CONNECTED) return;
	int len;
	if(user_input)
		len = strlen(user_input);
	else
		len = 0;
	int active_channel = Classes.IrcScreen->GetActiveChannel();
	if(len > 0) {
		if(!Classes.IrcScreen->GetScreenUse(active_channel) || !active_channel) {
			/* no chat or on the server screen */
			Classes.MsgDB->SetIrcChatMessage(active_channel, DISPLAY_ERROR, "you cant use this command on this screen");
			return;
		}
		snprintf(normal_text, HELP_BUF_LEN, "AACTION %s", user_input);
		int endpos = len+8;
		if(endpos >= HELP_BUF_LEN - 1) endpos = HELP_BUF_LEN - 2;
		normal_text[0] = normal_text[endpos] = 1;
		normal_text[endpos+1] = '\0';
		snprintf(help_buffer, HELP_BUF_LEN, "%s %s", Classes.IrcUser->GetNickname(), user_input);
		Classes.MsgDB->SetIrcChatMessage(active_channel, DISPLAY_MEACTION, help_buffer);
		if(!Classes.IrcScreen->GetScreenType(active_channel)) {
			/* message for a channel */
			snprintf(help_buffer, HELP_BUF_LEN, "PRIVMSG #%s :%s",
				Classes.IrcScreen->GetChannelName(active_channel), normal_text);
		} else {
			/* direct message */
			snprintf(help_buffer, HELP_BUF_LEN, "PRIVMSG %s :%s",
				Classes.IrcScreen->GetDirectChatNick(active_channel), normal_text);
		}
		WriteMessageToServer(help_buffer);
	} else {
		help_me("me");
	}
	return;
}

void Server::TopicHandler(int type)
{
	/* type = 0:        :network 332 <your nickname> #channel :topic
	 * type = 1:        :username!~pcname@ip_addr TOPIC #channel :new topic */
	char tmp_channelname[CHANNELS_NAME_LEN];
	if(type) {
		GetChannelName(tmp_channelname, 2, CHANNELS_NAME_LEN);
	} else {
		GetChannelName(tmp_channelname, 3, CHANNELS_NAME_LEN);
	}
	if(tmp_channelname[0] == '\0') return; /* false format */
	int screen_nr = Classes.IrcScreen->GetScreenNr(tmp_channelname, 0);
	if(!screen_nr) return; /* no such channel */
	if(type) {
		Put_Text_together(3);
		char tmp_nickname[NICKNAME_LEN];
		GetSenderName(tmp_nickname, 0, NICKNAME_LEN);
		if(tmp_nickname[0] == '\0') return; /* false format */
		snprintf(help_buffer, HELP_BUF_LEN, "%s set a new Topic: %s", tmp_nickname, normal_text);
	} else {
		Put_Text_together(4);
		snprintf(help_buffer, HELP_BUF_LEN, "Topic: %s", normal_text);
	}
	Classes.IrcScreen->SetTopic(screen_nr, normal_text);
	Classes.IrcScreen->DrawTopScreen();
	Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_TOPIC, help_buffer);
	Parsing_Finished();
	return;
}

void Server::TOPIC_Change(char * user_input)
{
	if(connect_status < STATUS_CONNECTED) return;
	int active_channel = Classes.IrcScreen->GetActiveChannel();
	if((!Classes.IrcScreen->GetScreenUse(active_channel)) || (Classes.IrcScreen->GetScreenType(active_channel))) {
		/* screen is not used or direct chat */
		Classes.MsgDB->SetIrcChatMessage(active_channel, DISPLAY_ERROR, "you are not in a channel, so you cant change the topic for this screen");
		return;
	}
	if(user_input) {
		snprintf(help_buffer, HELP_BUF_LEN, "TOPIC #%s :%s", Classes.IrcScreen->GetChannelName(active_channel), user_input);
	} else {
		snprintf(help_buffer, HELP_BUF_LEN, "TOPIC #%s", Classes.IrcScreen->GetChannelName(active_channel));	
	}
	WriteMessageToServer(help_buffer);
	return;
}

void Server::NICK_Change(char * user_input)
{
	if(!user_input) {
		help_me("nick");
		return;
	}
	int pos = position_of_num_char(user_input, ' ', 1);
	if(pos == 0) {
		help_me("nick");
		return;
	}
	if(pos != -1) user_input[pos] = '\0';
	if(connect_status >= STATUS_CONNECTED) {
		/* we are connected */
		snprintf(help_buffer, HELP_BUF_LEN, "NICK %s", user_input);
		WriteMessageToServer(help_buffer);
	} else {
		/* we are not connected */
		Classes.IrcUser->SetNickname(user_input);
		int screen_nr = Classes.IrcScreen->GetActiveChannel();
		snprintf(help_buffer, HELP_BUF_LEN, "changed your nickname to %s", user_input);
		Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_NICKNAME, help_buffer);
	}
	return;
}

void Server::CTCP_User(char * user_input)
{
	if(connect_status < STATUS_CONNECTED) return;
	if(user_input) {
		int space_pos = position_of_num_char(user_input, ' ', 1);
		if(space_pos == -1) {
			/* we have only 1 argument, so send a CTCP VERSION to this user */
			snprintf(help_buffer, HELP_BUF_LEN, "PRIVMSG %s :", user_input);
			int len = strlen(help_buffer);
			if(len > HELP_BUF_LEN-10) return; /* we need enoug space to add "\1VERSION\1" */
			strncat(help_buffer, "\1VERSION\1", 9);
			WriteMessageToServer(help_buffer);
		} else {
			/* we have to send a specific ctcp command */
			if(user_input[space_pos+1] == '\0') return; /* we have a space, but there is no command after this */
			string_toupper(user_input+space_pos+1);
			user_input[space_pos] = '\0';
			snprintf(help_buffer, HELP_BUF_LEN, "PRIVMSG %s :\1%s\1", user_input, user_input+space_pos+1);
			WriteMessageToServer(help_buffer);
		}
	} else help_me("ctcp");
	return;
}

void Server::Connect_to_Server(char * user_input)
{
	if(user_input) {
		/* we dont really connect to this server, we only disconnect from the old server ond set the new parameters */
		int len = strlen(user_input);
		int first_space_pos = position_of_num_char(user_input, ' ', 1);
		int second_space_pos = position_of_num_char(user_input, ' ', 2);
		if(first_space_pos == -1 && len) { /* we have a servername */
			Classes.IrcUser->SetServername(user_input);
			Classes.IrcUser->SetPort(DEFAULT_PORT_NUM);
			do_connect = 1;
			Disconnect();
		} else if(first_space_pos > 0 && len) { /* we have at least one space */
			int portlen = 0;
			if(second_space_pos != -1) {/* we have more spaces -> wth ??? */
				portlen = (second_space_pos - first_space_pos) - 1;
				user_input[second_space_pos] = '\0';
			} else {
				portlen = (len - first_space_pos) - 1;
			}
			if(portlen < 1) return;
			user_input[first_space_pos] = '\0';
			Classes.IrcUser->SetServername(user_input);
			Classes.IrcUser->SetPort(atoi(user_input+first_space_pos+1));
			do_connect = 1;
			Disconnect();
		} //else print help
	} else {
		/* we have no user input, this means we have to connect to the default server */
		Disconnect();
		Connect();
	}
	return;
}

void Server::Parsing_Finished(void) {
	parsing_finished = 1;
	return;
}

void Server::DoStartupJobs(void)
{
	if(connect_status < STATUS_ALL_OK) return;
	if(!ModesSet) {
		ModesSet = 1;
		char * modes = Classes.IrcUser->GetModes();
		if(modes[0] != '\0') {
			snprintf(help_buffer, HELP_BUF_LEN, "MODE %s +%s", Classes.IrcUser->GetNickname(), modes);
			WriteMessageToServer(help_buffer);
		}
	}
	if(StartCommandsSent >= Classes.IrcUser->GetTotalCommandNum()) return; /* allready all commands sent */
	int currenttime = time(NULL);
	if(LastCommandTime < currenttime) {
		/* only send one startup command every second */
		LastCommandTime = currenttime;
		if((signed)strlen(Classes.IrcUser->GetStartupcommand(StartCommandsSent)) > 0) {
			Classes.IrcScreen->ParseCommandToServer(Classes.IrcUser->GetStartupcommand(StartCommandsSent));
		}
		StartCommandsSent++;
	}
	return;
}

void Server::ResetParameters(void)
{
	SetConnectStatus(STATUS_NOTHING);
	cs_printed          = 0;
	StartCommandsSent   = 0;
	ModesSet            = 0;
	return;
}

int Server::GetNetworkSocket(void)
{
	return socketfd;
}

void Server::PrintNormalText(char * nickname)
{
	if(Num_InputParameters < 4) return;
	help_buffer[0] = '\0';
	if(strcmp(InputParameters[2], Classes.IrcUser->GetNickname()) != 0)
	{
		/* nickname change by server */
		Classes.IrcUser->SetNickname(InputParameters[2]);
		snprintf(help_buffer, HELP_BUF_LEN, "your nickname was changed by the server; new nickname: %s", InputParameters[2]);
		int screen_nr = Classes.IrcScreen->GetActiveChannel();
		Classes.MsgDB->SetIrcChatMessage(screen_nr, DISPLAY_NICKNAME, help_buffer);
		if(screen_nr) Classes.MsgDB->SetIrcChatMessage(0, DISPLAY_NICKNAME, help_buffer);
		Classes.IrcScreen->DrawBottomScreen();
	}
	Put_Text_together(3);
	Classes.MsgDB->SetIrcChatMessage(0, nickname, normal_text);
	Parsing_Finished();
	return;
}

int Server::GetConnectStatus(void)
{
	return connect_status;
}

void Server::SetConnectStatus(int new_status)
{
	if(new_status < 0 || new_status > STATUS_MAX_NUM) return;
	connect_status = new_status;
	return;
}

int Server::GetMaybeReconnect(void)
{
	return maybe_reconnect;
}

void Server::UnsetMaybeReconnect(void)
{
	maybe_reconnect = 0;
	return;
}

int Server::GetDoConnect(void)
{
	return do_connect;
}

#undef _SERVER_CC_