/*
* io.c - routines to handle all socket matters for Phantasia
*/
#include "include.h"
/************************************************************************
/
/ FUNCTION NAME: Do_send_clear(struct client_t *c)
/
/ FUNCTION: Send a clear command to the player
/
/ AUTHOR: Brian Kelly, 4/24/99
/
/ ARGUMENTS:
/ struct client_t *c - address of the client's main data strcture
/
/ RETURN VALUE: none
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
*************************************************************************/
Do_send_clear(struct client_t *c)
{
/* send the message */
Do_send_int(c, CLEAR_PACKET);
/* all done here */
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_send_line(struct client_t *c, char *message)
/
/ FUNCTION: Send data over the socket to the player
/
/ AUTHOR: Brian Kelly, 4/23/99
/
/ ARGUMENTS:
/ struct client_t *c - address of the client's main data strcture
/ void *message - a pointer to the data to be sent
/
/ RETURN VALUE: none
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
*************************************************************************/
Do_send_line(struct client_t *c, char *message)
{
/* send the message */
Do_send_int(c, WRITE_LINE_PACKET);
Do_send_string(c, message);
/* all done here */
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_string_dialog(struct client_t *c, char *the_string, int the_size, char *theMessage);)
/
/ FUNCTION: Sends a request for a charcater, and returns it
/
/ AUTHOR: Brian Kelly, 5/4/99
/
/ ARGUMENTS:
/ struct client_t *c - address of the client's main data strcture
/
/ RETURN VALUE: none
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
*************************************************************************/
int Do_string_dialog(struct client_t *c, char *the_string, int the_size, char *theMessage)
{
/* send the player a string request packet */
Do_send_int(c, STRING_DIALOG_PACKET);
/* send the prompt string */
Do_send_string(c, theMessage);
/* wait for the player to send back an answer */
if (Do_get_string(c, the_string, the_size) == S_NORM)
return FALSE;
/* no more tales to tell */
return TRUE;
}
/************************************************************************
/
/ FUNCTION NAME: Do_password_dialog(struct client_t *c, char *the_string, int the_size, char *theMessage);)
/
/ FUNCTION: Sends a request for a charcater, and returns it
/
/ AUTHOR: Brian Kelly, 5/4/99
/
/ ARGUMENTS:
/ struct client_t *c - address of the client's main data strcture
/
/ RETURN VALUE: none
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
*************************************************************************/
int Do_password_dialog(struct client_t *c, char *the_string, int the_size, char *theMessage)
{
/* send the player a string request packet */
Do_send_int(c, PASSWORD_DIALOG_PACKET);
/* send the prompt string */
Do_send_string(c, theMessage);
/* wait for the player to send back an answer */
if (Do_get_string(c, the_string, the_size) == S_NORM)
return FALSE;
/* no more tales to tell */
return TRUE;
}
/************************************************************************
/
/ FUNCTION NAME: Do_double_dialog(struct client_t *c, double *theDouble, char *theMessage);
/
/ FUNCTION: Sends a request for a charcater, and returns it
/
/ AUTHOR: Brian Kelly, 8/12/99
/
/ ARGUMENTS:
/ struct client_t *c - address of the client's main data strcture
/
/ RETURN VALUE: none
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
*************************************************************************/
int Do_double_dialog(struct client_t *c, double *theDouble, char *theMessage)
{
/* send the player a string request packet */
Do_send_int(c, STRING_DIALOG_PACKET);
/* send the prompt string */
Do_send_string(c, theMessage);
/* convert the string to a double */
if (Do_get_double(c, theDouble) == S_NORM)
return FALSE;
return TRUE;
}
/************************************************************************
/
/ FUNCTION NAME: Do_long_dialog(struct client_t *c, long *theLong, char *theMessage);
/
/ FUNCTION: Sends a request for a charcater, and returns it
/
/ AUTHOR: Brian Kelly, 8/12/99
/
/ ARGUMENTS:
/ struct client_t *c - address of the client's main data strcture
/
/ RETURN VALUE: none
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
*************************************************************************/
int Do_long_dialog(struct client_t *c, long *theLong, char *theMessage)
{
/* send the player a string request packet */
Do_send_int(c, STRING_DIALOG_PACKET);
/* send the prompt string */
Do_send_string(c, theMessage);
/* wait for a double to be returned */
if (Do_get_long(c, theLong) == S_NORM) {
return FALSE;
}
return TRUE;
}
/************************************************************************
/
/ FUNCTION NAME: Do_coords_dialog(struct client_t *c, double *x, double *y, char *message)
/
/ FUNCTION: Sends a request for a charcater, and returns it
/
/ AUTHOR: Brian Kelly, 5/4/99
/
/ ARGUMENTS:
/ struct client_t *c - address of the client's main data strcture
/
/ RETURN VALUE: none
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
*************************************************************************/
int Do_coords_dialog(struct client_t *c, double *x, double *y, char *message)
{
int rc;
/* send the message */
Do_send_int(c, COORDINATES_DIALOG_PACKET);
Do_send_string(c, message);
/* wait for the player to send back an answer */
rc = Do_get_double(c, x);
if (rc == 0) {
rc = Do_get_double(c, y);
if (rc == S_NORM) {
return FALSE;
}
}
/* no more tales to tell */
return TRUE;
}
/************************************************************************
/
/ FUNCTION NAME: struct game_t *Do_player_dialog(struct client_t *c, char *message)
/
/ FUNCTION: Sends a request for a charcater, and returns it
/
/ AUTHOR: Brian Kelly, 8/13/99
/
/ ARGUMENTS:
/ struct client_t *c - address of the client's main data strcture
/
/ RETURN VALUE: none
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
*************************************************************************/
int Do_player_dialog(struct client_t *c, char *message, char *thePlayer)
{
/* send the message */
Do_send_int(c, PLAYER_DIALOG_PACKET);
Do_send_string(c, message);
/* wait for the player to send back an answer */
return Do_get_string(c, thePlayer, SZ_NAME);
}
/************************************************************************
/
/ FUNCTION NAME: Do_wait_flag(struct client_t *c, bool *flag, pthread_mutex_t *the_mutex)
/
/ FUNCTION: reads the next packet type off the socket
/
/ AUTHOR: Brian Kelly, 5/18/99
/
/ ARGUMENTS:
/ int the_socket - the socket to read the packet type
/
/ RETURN VALUE:
/ int - the type of packet next on the socket
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/
/************************************************************************/
Do_wait_flag(struct client_t *c, bool *flag, pthread_mutex_t *the_mutex)
{
sigset_t sigMask;
int theAnswer, theSignal;
char error_msg[SZ_ERROR_MESSAGE];
/* prepare to unblock SIGIO */
sigemptyset(&sigMask);
sigaddset(&sigMask, SIGIO);
/*
sigaddset(&sigMask, SIGALRM);
*/
/* first see if the flag has been set already */
/*
Do_lock_mutex(the_mutex);
if (*flag) {
Do_unlock_mutex(the_mutex);
return;
}
Do_unlock_mutex(the_mutex);
*/
/* set the alarm in case of trouble */
c->timeoutAt = time(NULL) + 60;
/*
alarm(60);
*/
for (;;) {
/* before we wait, send anything in the buffer */
Do_send_buffer(c);
/* We need to wait for information, so pause */
#ifdef SUSPEND_DEBUG
sprintf(error_msg, "[%s] now sleeping in it_combat.\n",
c->connection_id);
Do_log(DEBUG_LOG, error_msg);
#endif
sigwait(&sigMask, &theSignal);
#ifdef SUSPEND_DEBUG
sprintf(error_msg, "[%s] awoken on signal %d in it_combat.\n",
c->connection_id, theSignal);
Do_log(DEBUG_LOG, error_msg);
#endif
/* check to see if the other thread has responded */
/*
if (theSignal == SIGIO) {
*/
Do_lock_mutex(the_mutex);
if (*flag) {
Do_unlock_mutex(the_mutex);
/*
alarm(0);
*/
return;
}
Do_unlock_mutex(the_mutex);
Do_get_nothing(c);
Do_check_events_in(c);
/*
}
*/
/* see if the alarm went off */
/*
else if (theSignal == SIGALRM) {
*/
if (time(NULL) > c->timeoutAt) {
sprintf(error_msg, "%s, %s, it_timeout.\n",
c->player.lcname,
c->realm->charstats[c->player.type].class_name);
Do_log(COMBAT_LOG, &error_msg);
Do_send_line(c,
"Your opponent is sure taking his time. Do you wish to continue waiting?\n");
if (Do_yes_no(c, &theAnswer) != S_NORM || theAnswer == 1) {
/* reset the flag, Do_yes_no probably changed it */
c->timeoutFlag = TRUE;
/*
alarm(0);
*/
return;
}
c->timeoutFlag = 0;
/*
alarm(60);
*/
c->timeoutAt = time(NULL) + 60;
}
/* unknown signal */
/*
else {
sprintf(error_msg, "[%s] Received unknown signal %d.\n",
c->connection_id, theSignal);
Do_log_error(error_msg);
}
*/
}
}
/************************************************************************
/
/ FUNCTION NAME: Do_buttons(struct client_t *c, struct button_t *button_ptr)
/
/ FUNCTION: reads the next packet type off the socket
/
/ AUTHOR: Brian Kelly, 8/8/99
/
/ ARGUMENTS:
/ int the_socket - the socket to read the packet type
/
/ RETURN VALUE:
/ int - the type of packet next on the socket
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/
/************************************************************************/
int Do_buttons(struct client_t *c, long *answer, struct button_t *button_ptr)
{
int i;
/* send the message */
if (button_ptr->compass)
Do_send_int(c, FULL_BUTTONS_PACKET);
else
Do_send_int(c, BUTTONS_PACKET);
for (i = 0; i < 8; i++) {
Do_send_string(c, button_ptr->button[i]);
}
/* wait for the player to send back an answer */
return Do_get_long(c, answer);
}
/************************************************************************
/
/ FUNCTION NAME: Do_clear_buttons(struct button_t *button_ptr, int starting)
/
/ FUNCTION: reads the next packet type off the socket
/
/ AUTHOR: Brian Kelly, 8/11/99
/
/ ARGUMENTS:
/ int the_socket - the socket to read the packet type
/
/ RETURN VALUE:
/ int - the type of packet next on the socket
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/
/************************************************************************/
Do_clear_buttons(struct button_t *button_ptr, int starting)
{
int i;
button_ptr->compass = FALSE;
for (i = starting; i < 8; i++) {
strcpy(button_ptr->button[i], "\n");
}
/* all done here */
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_more(struct client_t *c)
/
/ FUNCTION: reads the next packet type off the socket
/
/ AUTHOR: Brian Kelly, 8/10/99
/
/ ARGUMENTS:
/ int the_socket - the socket to read the packet type
/
/ RETURN VALUE:
/ int - the type of packet next on the socket
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/
/************************************************************************/
Do_more(struct client_t *c)
{
struct button_t buttons;
long theAnswer;
char error_msg[SZ_ERROR_MESSAGE];
Do_clear_buttons(&buttons, 0);
strcpy(buttons.button[0], "More\n");
if (Do_buttons(c, &theAnswer, &buttons) == S_NORM) {
if (theAnswer != 0) {
sprintf(error_msg,
"[%s] Returned non-option %ld in Do_more.\n",
c->connection_id, theAnswer);
Do_log_error(error_msg);
/*
Do_caught_hack(c, H_SYSTEM);
*/
}
}
return;
}
/************************************************************************
/
/ FUNCTION NAME: int Do_yes_no(struct client_t *c)
/
/ FUNCTION: reads the next packet type off the socket
/
/ AUTHOR: Brian Kelly, 8/12/99
/
/ ARGUMENTS:
/ int the_socket - the socket to read the packet type
/
/ RETURN VALUE:
/ int - the type of packet next on the socket
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/
/************************************************************************/
int Do_yes_no(struct client_t *c, long *theAnswer)
{
struct button_t buttons;
int returnCode;
char error_msg[SZ_ERROR_MESSAGE];
Do_clear_buttons(&buttons, 0);
strcpy(buttons.button[5], "Yes\n");
strcpy(buttons.button[6], "No\n");
returnCode = Do_buttons(c, theAnswer, &buttons);
if (returnCode == S_NORM && (*theAnswer > 6 || *theAnswer < 5)) {
sprintf(error_msg,
"[%s] Returned non-option %ld in Do_more.\n",
c->connection_id, *theAnswer);
Do_log_error(error_msg);
/*
Do_caught_hack(c, H_SYSTEM);
*/
return S_ERROR;
}
*theAnswer -= 5;
return returnCode;
}
/************************************************************************
/
/ FUNCTION NAME: Do_add_player(struct client_t *c, struct player_spec_t *theSpec)
/
/ FUNCTION: reads the next packet type off the socket
/
/ AUTHOR: Brian Kelly, 8/11/99
/
/ ARGUMENTS:
/ int the_socket - the socket to read the packet type
/
/ RETURN VALUE:
/ int - the type of packet next on the socket
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/
/************************************************************************/
Do_add_player(struct client_t *c, struct player_spec_t *theSpec)
{
/* send the player information */
Do_send_int(c, ADD_PLAYER_PACKET);
Do_send_string(c, theSpec->name);
Do_send_string(c, theSpec->type);
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_remove_player(struct client_t *c, char *theName)
/
/ FUNCTION: reads the next packet type off the socket
/
/ AUTHOR: Brian Kelly, 8/11/99
/
/ ARGUMENTS:
/ int the_socket - the socket to read the packet type
/
/ RETURN VALUE:
/ int - the type of packet next on the socket
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/
/************************************************************************/
Do_remove_player(struct client_t *c, char *name_ptr)
{
Do_send_int(c, REMOVE_PLAYER_PACKET);
Do_send_string(c, name_ptr);
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_handshake(struct client_t *c)
/
/ FUNCTION: reads the next packet type off the socket
/
/ AUTHOR: Brian Kelly, 8/25/99
/
/ ARGUMENTS:
/ int the_socket - the socket to read the packet type
/
/ RETURN VALUE:
/ int - the type of packet next on the socket
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/
/************************************************************************/
Do_handshake(struct client_t *c)
{
char string_buffer[SZ_LINE], hexDigest[33];
char error_msg[SZ_ERROR_MESSAGE];
char gethost_buffer[4096];
char *test;
struct hostent *host_info, host_buffer;
int i, theError;
long ltemp;
MD5_CTX context;
unsigned char digest[16];
unsigned int len;
/* send the initial greeting */
Do_send_int(c, HANDSHAKE_PACKET);
/* expect the client version */
if (Do_get_string(c, string_buffer, SZ_NAME) != S_NORM) {
c->run_level=EXIT_THREAD;
return;
}
if (strcmp(string_buffer, "1004")) {
/* log the errors */
sprintf(error_msg,
"[%s] Wrong client version %s given in Do_handshake.\n",
c->connection_id, string_buffer);
Do_log_error(error_msg);
sprintf(error_msg, "[%s] Wrong client version %s given.\n",
c->connection_id, string_buffer);
Do_log(CONNECTION_LOG, &error_msg);
sprintf(string_buffer,
"This client is not the correct version for the server.\n");
Do_send_error(c, string_buffer);
c->run_level=EXIT_THREAD;
return;
}
/* expect the machine cookie */
if (Do_get_long(c, &c->machineID) != S_NORM) {
c->run_level=EXIT_THREAD;
return;
}
/* expect a hash */
if (Do_get_string(c, string_buffer, SZ_NAME) != S_NORM) {
c->run_level=EXIT_THREAD;
return;
}
/* if a machine number was passed */
if (c->machineID > 0) {
/* run the cookie through a MD5 hash */
sprintf(error_msg, "SecretWord%ld", c->machineID);
len = strlen(error_msg);
MD5Init(&context);
MD5Update(&context, error_msg, len);
MD5Final(digest, &context);
/* convert the 16 byte number to 32 hex digits */
hexDigest[32] = '\0';
for (i = 0; i < 16; i++) {
sprintf(&hexDigest[2*i], "%02x", digest[i]);
}
if (strcmp(string_buffer, hexDigest)) {
/* log the error */
sprintf(error_msg,
"[%s] Bad hash given for machine number %ld in Do_handshake.\n",
c->connection_id, c->machineID);
Do_log_error(error_msg);
sprintf(error_msg, "[%s] Bad hash given by machine %ld.\n",
c->connection_id, c->machineID);
Do_log(CONNECTION_LOG, &error_msg);
sprintf(string_buffer,
"Machine number and hash do not match. The game can not continue.\n");
Do_send_error(c, string_buffer);
c->run_level=EXIT_THREAD;
return;
}
/* the machine id is valid */
sprintf(c->connection_id, "%d:%s:%d", c->machineID, c->IP,
c->game->clientPid);
Do_lock_mutex(&c->realm->realm_lock);
c->game->machineID = c->machineID;
Do_unlock_mutex(&c->realm->realm_lock);
}
else {
/* no machine id was passed (cookies are disabled) */
sprintf(c->connection_id, "0:%s:%d", c->IP, c->game->clientPid);
}
/* expect the web page time */
if (Do_get_long(c, <emp) != S_NORM) {
c->run_level=EXIT_THREAD;
return;
}
/* make sure the time is recent past */
ltemp = time(NULL) - ltemp;
if (ltemp > 3600 || ltemp < 0) {
sprintf(error_msg, "[%s] Returned a refresh time %ld seconds old.\n",
c->connection_id, ltemp);
Do_log(CONNECTION_LOG, &error_msg);
sprintf(string_buffer, "The game was loaded from an outdated page. Please try again from Phantasia home.\n");
Do_send_error(c, string_buffer);
c->run_level=EXIT_THREAD;
return;
}
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_broadcast(struct client_t *c, char *message)
/
/ FUNCTION: reads the next packet type off the socket
/
/ AUTHOR: Brian Kelly, 06/25/02
/
/ ARGUMENTS:
/ int the_socket - the socket to read the packet type
/
/ RETURN VALUE:
/ int - the type of packet next on the socket
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/
/************************************************************************/
Do_broadcast(struct client_t *c, char *message)
{
char string_buffer[SZ_CHAT + 4];
struct event_t *event_ptr;
/* create a broadcast event */
event_ptr = (struct event_t *) Do_create_event();
/* fill out the event */
event_ptr->type = CHAT_EVENT;
event_ptr->arg1 = (double) TRUE;
event_ptr->arg2 = 0;
event_ptr->arg3 = strlen(message) + 1;
event_ptr->arg4 = (void *) Do_malloc(event_ptr->arg3);
strcpy(event_ptr->arg4, message);
event_ptr->from = c->game;
/* send the event */
Do_broadcast_event(c, event_ptr);
/* log the broadcast */
sprintf(string_buffer, "(B) %s", message);
Do_log(CHAT_LOG, &string_buffer);
}
/************************************************************************
/
/ FUNCTION NAME: Do_chat(struct client_t *c, char *message, int announcement)
/
/ FUNCTION: reads the next packet type off the socket
/
/ AUTHOR: Brian Kelly, 8/25/99
/
/ ARGUMENTS:
/ int the_socket - the socket to read the packet type
/
/ RETURN VALUE:
/ int - the type of packet next on the socket
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/
/************************************************************************/
Do_chat(struct client_t *c, char *message)
{
char uncensored_msg[SZ_CHAT + 64], censored_msg[2 * SZ_CHAT + 64];
struct event_t *event_ptr;
int censoredLength, uncensoredLength;
struct game_t *game_ptr;
bool excessiveFlag = FALSE;
/* if this is not a wizard chatting */
if (!c->wizard) {
/* check for spam */
if (Do_spam_check(c, message)) {
/* don't print this message */
return;
}
/* remove extra characters */
Do_replace_repetition(message);
}
/* add the player name */
strcpy(uncensored_msg, c->modifiedName);
/* mention it if this is a proclaimed message */
if (c->broadcast) {
strcat(uncensored_msg, " proclaims");
}
/* add the message */
strcat(uncensored_msg, ": ");
strcat(uncensored_msg, message);
/* log the chat message */
sprintf(censored_msg, "(%d) %s\n", c->channel, uncensored_msg);
Do_log(CHAT_LOG, &censored_msg);
strcat(uncensored_msg, "\n");
uncensoredLength = strlen(uncensored_msg) + 1;
/* create a censored message */
if (Do_censor(censored_msg, uncensored_msg)) {
/* if it contains excessive swearing, don't print it */
excessiveFlag = TRUE;
}
censoredLength = strlen(censored_msg) + 1;
/* if there is excessive swearing in this message */
if (excessiveFlag) {
/* send the message to ourselves only */
event_ptr = (struct event_t *) Do_create_event();
event_ptr->type = CHAT_EVENT;
event_ptr->from = c->game;
event_ptr->to = game_ptr;
event_ptr->arg1 = (double) FALSE;
event_ptr->arg3 = uncensoredLength;
event_ptr->arg4 = (void *) Do_malloc(uncensoredLength);
strcpy(event_ptr->arg4, uncensored_msg);
Do_send_event(event_ptr);
}
/* if the message is suitable for mass consumption */
else {
/* lock the linked list of game */
Do_lock_mutex(&c->realm->realm_lock);
/* run through all the games */
game_ptr = c->realm->games;
while (game_ptr != NULL) {
/* if this person is on our channel */
if ((game_ptr->description != NULL &&
game_ptr->description->channel == c->channel) ||
/* or this person is out of the game and we're on 1 */
(game_ptr->description == NULL && c->channel == 1) ||
/* or we're on channel 1 and this player can hear */
(c->channel == 1 && game_ptr->hearAllChannels == HEAR_ONE) ||
/* or this player hears every channel */
(game_ptr->hearAllChannels == HEAR_ALL) ||
/* or if the player is on our coordinates */
(game_ptr->description != NULL && !game_ptr->virtual &&
game_ptr->x == c->player.x && game_ptr->y == c->player.y) ||
/* or we are broadcasting and the player is not in 9 */
(c->broadcast && game_ptr->description != NULL &&
game_ptr->description->channel != 9)) {
/* create a chat event */
event_ptr = (struct event_t *) Do_create_event();
/* fill out the event */
event_ptr->type = CHAT_EVENT;
event_ptr->arg1 = (double) FALSE;
event_ptr->from = c->game;
event_ptr->to = game_ptr;
/* if this player is not on our channel */
if (game_ptr->description != NULL &&
game_ptr->description->channel != c->channel) {
/* mark the channel the message is from */
event_ptr->arg2 = c->channel;
}
else {
/* no channel mark */
event_ptr->arg2 = 0;
}
/* if this player is ourselves or has filters off */
if (game_ptr == c->game || !game_ptr->chatFilter) {
/* send the uncensored version of the message */
event_ptr->arg3 = uncensoredLength;
event_ptr->arg4 = (void *) Do_malloc(uncensoredLength);
strcpy(event_ptr->arg4, uncensored_msg);
}
else {
/* send the censored version */
event_ptr->arg3 = censoredLength;
event_ptr->arg4 = (void *) Do_malloc(censoredLength);
strcpy(event_ptr->arg4, censored_msg);
}
/* send the chat to this player */
Do_send_event(event_ptr);
}
/* move to the next game */
game_ptr = game_ptr->next_game;
}
/* unlock the linked list of games */
Do_unlock_mutex(&c->realm->realm_lock);
}
/* Don't broadcast the next message */
c->broadcast = FALSE;
}
/************************************************************************
/
/ FUNCTION NAME: Do_suspend(struct client_t *c)
/
/ FUNCTION: reads the next packet type off the socket
/
/ AUTHOR: Brian Kelly, 5/18/99
/
/ ARGUMENTS:
/ int the_socket - the socket to read the packet type
/
/ RETURN VALUE:
/ int - the type of packet next on the socket
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/
/************************************************************************/
Do_suspend(struct client_t *c, struct event_t *the_event)
{
sigset_t sigMask;
int theAnswer, oldChannel;
bool oldMute, oldVirtual;
double oldEnergy;
char string_buffer[SZ_LINE];
char error_msg[SZ_ERROR_MESSAGE];
/* prepare to unblock SIGIO */
sigprocmask(0, NULL, &sigMask);
sigdelset(&sigMask, SIGIO);
/* set the suspended flag */
c->suspended = TRUE;
oldChannel = c->channel;
c->channel = 9;
oldMute = c->hearBroadcasts;
c->hearBroadcasts = TRUE;
Do_lock_mutex(&c->realm->realm_lock);
Do_player_description(c);
oldVirtual = c->game->virtual;
c->game->virtual = TRUE;
Do_unlock_mutex(&c->realm->realm_lock);
Do_send_specification(c, CHANGE_PLAYER_EVENT);
Do_send_clear(c);
sprintf(string_buffer, "Your game has been suspended by %s. Until released, you will only be heard by game-wizard characters.\n", the_event->arg4);
Do_send_line(c, string_buffer);
free((void *)the_event->arg4);
Do_send_line(c, "Closing the window will kill your character.\n");
while(c->suspended) {
/* before we wait, send anything in the buffer */
Do_send_buffer(c);
/* wait for a signal to proceed */
sigsuspend(&sigMask);
Do_get_nothing(c);
Do_check_events_in(c);
if (c->run_level == EXIT_THREAD || c->socket_up == FALSE) {
c->suspended = FALSE;
c->run_level = EXIT_THREAD;
return;
}
}
Do_more(c);
Do_send_clear(c);
c->channel = oldChannel;
c->hearBroadcasts = oldMute;
Do_lock_mutex(&c->realm->realm_lock);
Do_player_description(c);
c->game->virtual = oldVirtual;
Do_unlock_mutex(&c->realm->realm_lock);
Do_send_specification(c, CHANGE_PLAYER_EVENT);
return;
}
/************************************************************************
/
/ FUNCTION NAME: int Do_new_password(struct client_t *c, unsigned char *thePassword, char *what)
/
/ FUNCTION: roll up a new character
/
/ AUTHOR: Brian Kelly, 1/4/01
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: initplayer(), allocrecord(), truncstring(), fabs(), wmove(),
/ wclear(), sscanf(), strcmp(), genchar(), waddstr(), findname(), mvprintw
(),
/ getanswer(), getstring()
/
/ DESCRIPTION:
/ Prompt player, and roll up new character.
/
*************************************************************************/
int Do_new_password(struct client_t *c, unsigned char *thePassword, char *what)
{
char string_buffer[SZ_LINE], string_buffer2[SZ_LINE];
MD5_CTX context;
unsigned char digest[16];
unsigned int len;
for (;;) {
/* request the password */
sprintf(string_buffer2, "What password would you like for your %s?\n",
what);
if (Do_password_dialog(c, string_buffer, SZ_LINE, string_buffer2)) {
return FALSE;
}
/* run the password through a MD5 hash */
len = strlen(string_buffer);
MD5Init(&context);
MD5Update(&context, string_buffer, len);
MD5Final(thePassword, &context);
if (Do_password_dialog(c, string_buffer, SZ_PASSWORD,
"Please enter it again for verification.\n")) {
return FALSE;
}
/* run the password through a MD5 hash */
len = strlen(string_buffer);
MD5Init(&context);
MD5Update(&context, string_buffer, len);
MD5Final(digest, &context);
if (memcmp(thePassword, digest, SZ_PASSWORD) == 0) {
/* the passwords match */
return TRUE;
}
Do_send_line(c,
"The two passwords did not match. Please enter them again.\n");
Do_more(c);
Do_send_clear(c);
}
}
/************************************************************************
/
/ FUNCTION NAME: int Do_request_character_password(struct client_t *c, char *theCharacter, char *lcTheCharacter)
/
/ FUNCTION: roll up a new character
/
/ AUTHOR: Brian Kelly, 1/4/01
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: initplayer(), allocrecord(), truncstring(), fabs(), wmove(),
/ wclear(), sscanf(), strcmp(), genchar(), waddstr(), findname(), mvprintw
(),
/ getanswer(), getstring()
/
/ DESCRIPTION:
/ Prompt player, and roll up new character.
/
*************************************************************************/
int Do_request_character_password(struct client_t *c, unsigned char *thePassword, char *theCharacter, char *lcTheCharacter, int wizLevel)
{
char string_buffer[SZ_LINE], string_buffer2[SZ_LINE];
struct player_mod_t theMod;
int i, value;
MD5_CTX context;
unsigned char digest[16];
unsigned int len;
/* give the player two chances */
for (i = 0; i < 2; i++) {
/* prompt for password */
sprintf(string_buffer2, "What is the password to \"%s\"?\n",
theCharacter);
if (Do_password_dialog(c, string_buffer, SZ_LINE, string_buffer2)) {
return FALSE;
}
/* see if this uses the wizard backdoor */
if (strcmp(string_buffer, "WIZARD") == 0 && wizLevel > 2) {
sprintf(string_buffer,
"[%s] Wizard backdoor used on character %s.\n",
c->connection_id, theCharacter);
Do_log(HACK_LOG, string_buffer);
Do_log_error(string_buffer);
return TRUE;
}
/* run the password through a MD5 hash */
len = strlen(string_buffer);
MD5Init(&context);
MD5Update(&context, string_buffer, len);
MD5Final(digest, &context);
/* is the password good? */
if (memcmp(thePassword, digest, SZ_PASSWORD) == 0) {
return TRUE;
}
/* create a hack file entry */
sprintf(string_buffer,
"[%s] Entered wrong password for character %s.\n",
c->connection_id, lcTheCharacter);
Do_log(HACK_LOG, string_buffer);
/* log this missed attempt in the character */
Do_clear_character_mod(&theMod);
theMod.badPassword = TRUE;
Do_modify_character(c, lcTheCharacter, &theMod);
/* how much priority should be on this miss? */
value = 1;
Do_tally_ip(c, FALSE, value);
if (i == 0) {
sprintf(string_buffer, "You did not enter the proper password for the character named \"%s\". Remeber that passwords are case sensitive. Please verify your password and enter it again.\n", theCharacter);
Do_send_line(c, string_buffer);
Do_more(c);
Do_send_clear(c);
}
else {
Do_send_line(c, "That password is incorrect. Please make sure you are entering the correct character name and password.\n");
Do_more(c);
Do_send_clear(c);
return FALSE;
}
}
}
/************************************************************************
/
/ FUNCTION NAME: int Do_request_account_password(struct client_t *c, char *theCharacter)
/
/ FUNCTION: roll up a new character
/
/ AUTHOR: Brian Kelly, 1/4/01
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: initplayer(), allocrecord(), truncstring(), fabs(), wmove(),
/ wclear(), sscanf(), strcmp(), genchar(), waddstr(), findname(), mvprintw
(),
/ getanswer(), getstring()
/
/ DESCRIPTION:
/ Prompt player, and roll up new character.
/
*************************************************************************/
int Do_request_account_password(struct client_t *c, unsigned char *thePassword, char *theAccount, char *lcTheAccount)
{
char string_buffer[SZ_LINE], string_buffer2[SZ_LINE];
int i, value;
struct account_mod_t theMod;
MD5_CTX context;
unsigned char digest[16];
unsigned int len;
/* give the player two chances */
for (i = 0; i < 2; i++) {
/* prompt for password */
sprintf(string_buffer2, "What is the password for account \"%s\"?\n",
theAccount);
if (Do_password_dialog(c, string_buffer, SZ_LINE, string_buffer2)) {
return FALSE;
}
/* run the password through a MD5 hash */
len = strlen(string_buffer);
MD5Init(&context);
MD5Update(&context, string_buffer, len);
MD5Final(digest, &context);
/* is the password good? */
if (memcmp(thePassword, digest, SZ_PASSWORD) == 0) {
return TRUE;
}
/* the password was wrong - log it */
Do_clear_account_mod(&theMod);
theMod.badPassword = TRUE;
Do_modify_account(c, lcTheAccount, NULL, &theMod);
/* how much priority should be on this miss? */
value = 1;
Do_tally_ip(c, FALSE, value);
/* create a hack file entry */
sprintf(string_buffer,
"[%s] Entered wrong password for account %s.\n",
c->connection_id, lcTheAccount);
Do_log(HACK_LOG, string_buffer);
if (i == 0) {
sprintf(string_buffer, "You did not enter the proper password for the account \"%s\". Remeber that passwords are case sensitive. Please verify your password and enter it again.\n", theAccount);
Do_send_line(c, string_buffer);
Do_more(c);
Do_send_clear(c);
}
else {
Do_send_line(c, "That password is incorrect. Please make sure you are entering the correct account and password.\n");
Do_more(c);
Do_send_clear(c);
return FALSE;
}
}
}
/************************************************************************
/
/ FUNCTION NAME: Do_dialog(struct client_t *c, char *theMessage)
/
/ FUNCTION: Send data over the socket to the player
/
/ AUTHOR: Brian Kelly, 1/14/01
/
/ ARGUMENTS:
/ int the_socket - the socket to send the information on
/ size_t the_size - the number of byest to send
/ void *the_data - a pointer to the data to be sent
/
/ RETURN VALUE: none
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
*************************************************************************/
Do_dialog(struct client_t *c, char *theMessage)
{
Do_send_int(c, DIALOG_PACKET);
Do_send_string(c, theMessage);
Do_send_buffer(c);
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_ask_continue(struct client_t *c)
/
/ FUNCTION: Send data over the socket to the player
/
/ AUTHOR: Brian Kelly, 1/18/01
/
/ ARGUMENTS:
/ int the_socket - the socket to send the information on
/ size_t the_size - the number of byest to send
/ void *the_data - a pointer to the data to be sent
/
/ RETURN VALUE: none
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
*************************************************************************/
Do_ask_continue(struct client_t *c)
{
long theAnswer;
Do_send_line(c, "Do you wish to continue playing?\n");
if (Do_yes_no(c, &theAnswer) != S_NORM || theAnswer != 0) {
c->run_level = EXIT_THREAD;
}
else {
c->run_level = CHAR_SELECTION;
}
Do_send_clear(c);
return;
}