/*
* tags.c Routines to track users and punish wrongdoers
*/
#include "include.h"
char *taggedTypes[] = {"machine #", "account ", "address ", "network "};
char *tagTypes[] = {"reject", "ban", "suicide", "mute", "prefix", "suffix"};
char *tagDescs[] = {"rejected", "banned", "ordered to commit suicide", "muted", "tagged", "tagged"};
/************************************************************************
/
/ FUNCTION NAME: Do_tag_self(struct client_t *c, struct tag_t *theTag)
/
/ FUNCTION: return a char specifying player type
/
/ AUTHOR: Brian Kelly, 01/06/01
/
/ ARGUMENTS:
/ struct client_t c - pointer to the main client strcture
/
/ RETURN VALUE:
/ char - character the describes the character
/
/ MODULES CALLED: strcpy()
/
/ DESCRIPTION:
/ Return a string describing the player type.
/ King, council, valar, supercedes other types.
/ The first character of the string is '*' if the player
/ has a crown.
/ If 'shortflag' is TRUE, return a 3 character string.
/
*************************************************************************/
Do_tag_self(struct client_t *c, struct tag_t *theTag)
{
struct tagged_t theTagged;
struct history_t theHistory;
char error_msg[SZ_ERROR_MESSAGE], string_buffer[SZ_LINE];
/* get the next tag number */
Do_lock_mutex(&c->realm->tag_file_lock);
theTag->number = c->realm->nextTagNumber++;
Do_unlock_mutex(&c->realm->tag_file_lock);
/* write the tag */
Do_save_tag(c, theTag);
/* get the time the ban expires */
ctime_r(&theTag->validUntil, error_msg);
error_msg[strlen(error_msg) - 1] = '\0';
/* log the tag creation */
sprintf(string_buffer,
"[%s] Created %s tag #%d for \"%s\" effective until %s.\n",
c->connection_id, tagTypes[theTag->type], theTag->number,
theTag->description, error_msg);
Do_log(HACK_LOG, string_buffer);
/* prepare a history entry */
theHistory.date = time(NULL);
sprintf(theHistory.description,
"New %s tag #%d for \"%s\" effective until %s.\n",
tagTypes[theTag->type], theTag->number, theTag->description,
error_msg);
/* prepare the tagged entry */
theTagged.tagNumber = theTag->number;
theTagged.validUntil = theTag->validUntil;
/* tag the machine if we have one */
if (c->machineID != 0) {
/* associate the machine to the tag */
theTagged.type = T_MACHINE;
sprintf(theTagged.name, "%ld", c->machineID);
Do_save_tagged(c, &theTagged);
/* log the tag creation */
sprintf(string_buffer, "[%s] Attached machine #%d to tag #%d.\n",
c->connection_id, c->machineID, theTag->number);
Do_log(HACK_LOG, string_buffer);
/* add this to the history file */
theHistory.type = T_MACHINE;
sprintf(theHistory.name, "%ld", c->machineID);
Do_save_history(c, &theHistory);
}
/* if there is an account */
if (c->accountLoaded) {
/* associate the account to the tag */
theTagged.type = T_ACCOUNT;
strcpy(theTagged.name, c->lcaccount);
Do_save_tagged(c, &theTagged);
/* log the tag creation */
sprintf(string_buffer, "[%s] Attached account %s to tag #%d.\n",
c->connection_id, c->lcaccount, theTag->number);
Do_log(HACK_LOG, string_buffer);
/* add this to the history file */
theHistory.type = T_ACCOUNT;
strcpy(theHistory.name, c->lcaccount);
Do_save_history(c, &theHistory);
}
/* see if this tag should affect network */
if (theTag->affectNetwork) {
/* associate the network to the tag */
theTagged.type = T_NETWORK;
strcpy(theTagged.name, c->network);
Do_save_tagged(c, &theTagged);
/* log the tag creation */
sprintf(string_buffer, "[%s] Attached network %s to tag #%d.\n",
c->connection_id, c->network, theTag->number);
Do_log(HACK_LOG, string_buffer);
/* add this to the history file */
theHistory.type = T_NETWORK;
strcpy(theHistory.name, c->network);
Do_save_history(c, &theHistory);
}
/* associate the IP to the tag */
theTagged.type = T_ADDRESS;
strcpy(theTagged.name, c->IP);
/* address can be associated for 1 hour maximum */
if (theTagged.validUntil > theHistory.date + 3600) {
theTagged.validUntil = theHistory.date + 3600;
}
Do_save_tagged(c, &theTagged);
/* log the tag creation */
sprintf(string_buffer, "[%s] Attached address %s to tag #%d.\n",
c->connection_id, c->IP, theTag->number);
Do_log(HACK_LOG, string_buffer);
/* add this to the history file */
theHistory.type = T_ADDRESS;
strcpy(theHistory.name, c->IP);
Do_save_history(c, &theHistory);
/* now implement the tag */
Do_implement_tag(c, theTag);
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_save_tag(struct client_t *c, struct tag_t *theTag)
/
/ FUNCTION: find location in player file of given name
/
/ AUTHOR: Brian Kelly, 01/09/01
/
/ ARGUMENTS:
/ char *name - name of character to look for
/ struct player *playerp - pointer of structure to fill
/
/ RETURN VALUE: location of player if found, -1 otherwise
/
/ MODULES CALLED: fread(), fseek(), strcmp()
/
/ GLOBAL INPUTS: Wizard, *Playersfp
/
/ GLOBAL OUTPUTS: none
/
/ DESCRIPTION:
/ Search the player file for the player of the given name.
/ If player is found, fill structure with player data.
/
*************************************************************************/
int Do_save_tag(struct client_t *c, struct tag_t *theTag)
{
FILE *tag_file;
bool found_flag;
char error_msg[SZ_ERROR_MESSAGE];
Do_lock_mutex(&c->realm->tag_file_lock);
errno = 0;
if ((tag_file=fopen(TAG_FILE, "a")) == NULL) {
Do_unlock_mutex(&c->realm->tag_file_lock);
sprintf(error_msg,
"[%s] fopen of %s failed in Do_save_tag: %s\n",
c->connection_id, TAG_FILE, strerror(errno));
Do_log_error(error_msg);
return FALSE;
}
/* write the tag to the tag file */
if (fwrite((void *)theTag, SZ_TAG, 1, tag_file) != 1) {
fclose(tag_file);
remove(TAG_FILE);
Do_unlock_mutex(&c->realm->tag_file_lock);
sprintf(error_msg,
"[%s] fwrite of %s failed in Do_save_tag: %s.\n",
c->connection_id, TEMP_TAG_FILE, strerror(errno));
Do_log_error(error_msg);
return FALSE;
}
/* close the two files */
fclose(tag_file);
Do_unlock_mutex(&c->realm->tag_file_lock);
return TRUE;
}
/************************************************************************
/
/ FUNCTION NAME: Do_look_tag(struct client_t *c, struct tag_t *theTag, int tagNumber)
/
/ FUNCTION: find location in player file of given name
/
/ AUTHOR: Brian Kelly, 01/09/01
/
/ ARGUMENTS:
/ char *name - name of character to look for
/ struct player *playerp - pointer of structure to fill
/
/ RETURN VALUE: location of player if found, -1 otherwise
/
/ MODULES CALLED: fread(), fseek(), strcmp()
/
/ GLOBAL INPUTS: Wizard, *Playersfp
/
/ GLOBAL OUTPUTS: none
/
/ DESCRIPTION:
/ Search the player file for the player of the given name.
/ If player is found, fill structure with player data.
/
*************************************************************************/
int Do_look_tag(struct client_t *c, struct tag_t *theTag, int tagNumber)
{
struct tag_t readTag;
FILE *tag_file, *temp_file;
time_t timeNow;
bool found_flag;
char error_msg[SZ_ERROR_MESSAGE];
Do_lock_mutex(&c->realm->tag_file_lock);
/* get the time now */
timeNow = time(NULL);
found_flag = FALSE;
/* open a temp file to transfer records to */
errno = 0;
if ((temp_file=fopen(TEMP_TAG_FILE, "w")) == NULL) {
Do_unlock_mutex(&c->realm->tag_file_lock);
sprintf(error_msg,
"[%s] fopen of %s failed in Do_look_tag: %s.\n",
c->connection_id, TEMP_TAG_FILE, strerror(errno));
Do_log_error(error_msg);
return FALSE;
}
errno = 0;
if ((tag_file=fopen(TAG_FILE, "r")) == NULL) {
fclose(temp_file);
Do_unlock_mutex(&c->realm->tag_file_lock);
sprintf(error_msg,
"[%s] fopen of %s failed in Do_look_tag: %s\n",
c->connection_id, TAG_FILE, strerror(errno));
Do_log_error(error_msg);
return FALSE;
}
/* run through the tag entries */
while (fread((void *)&readTag, SZ_TAG, 1, tag_file) == 1) {
/* see if this tag is outdated */
if (readTag.validUntil < timeNow) {
/* don't rewrite it */
continue;
}
/* this is the tag? */
else if (readTag.number == tagNumber) {
/* copy over the tag information */
memcpy(theTag, &readTag, SZ_TAG);
found_flag = TRUE;
}
/* write the tag to the temp file */
if (fwrite((void *)&readTag, SZ_TAG, 1, temp_file) != 1) {
fclose(tag_file);
fclose(temp_file);
remove(TEMP_TAG_FILE);
Do_unlock_mutex(&c->realm->tag_file_lock);
sprintf(error_msg,
"[%s] fwrite of %s failed in Do_look_tag: %s.\n",
c->connection_id, TEMP_TAG_FILE, strerror(errno));
Do_log_error(error_msg);
return FALSE;
}
}
/* close the two files */
fclose(temp_file);
fclose(tag_file);
/* delete the old character record */
remove(TAG_FILE);
/* replace it with the temporary file */
rename(TEMP_TAG_FILE, TAG_FILE);
Do_unlock_mutex(&c->realm->tag_file_lock);
if (found_flag) {
return TRUE;
}
return FALSE;
}
/************************************************************************
/
/ FUNCTION NAME: Do_save_tagged(struct client_t *c, struct tag_t *theTagged)
/
/ FUNCTION: find location in player file of given name
/
/ AUTHOR: Brian Kelly, 01/11/01
/
/ ARGUMENTS:
/ char *name - name of character to look for
/ struct player *playerp - pointer of structure to fill
/
/ RETURN VALUE: location of player if found, -1 otherwise
/
/ MODULES CALLED: fread(), fseek(), strcmp()
/
/ GLOBAL INPUTS: Wizard, *Playersfp
/
/ GLOBAL OUTPUTS: none
/
/ DESCRIPTION:
/ Search the player file for the player of the given name.
/ If player is found, fill structure with player data.
/
*************************************************************************/
int Do_save_tagged(struct client_t *c, struct tagged_t *theTagged)
{
FILE *tagged_file;
bool found_flag;
char error_msg[SZ_ERROR_MESSAGE];
time_t newTime;
Do_lock_mutex(&c->realm->tagged_file_lock);
errno = 0;
if ((tagged_file=fopen(TAGGED_FILE, "a")) == NULL) {
Do_unlock_mutex(&c->realm->tagged_file_lock);
sprintf(error_msg,
"[%s] fopen of %s failed in Do_save_tagged: %s\n",
c->connection_id, TAGGED_FILE, strerror(errno));
Do_log_error(error_msg);
return FALSE;
}
/* write the tagged to the tag file */
if (fwrite((void *)theTagged, SZ_TAGGED, 1, tagged_file) != 1) {
fclose(tagged_file);
remove(TAGGED_FILE);
Do_unlock_mutex(&c->realm->tagged_file_lock);
sprintf(error_msg,
"[%s] fwrite of %s failed in Do_save_tagged: %s.\n",
c->connection_id, TEMP_TAGGED_FILE, strerror(errno));
Do_log_error(error_msg);
return FALSE;
}
/* close the two files */
fclose(tagged_file);
Do_unlock_mutex(&c->realm->tagged_file_lock);
return TRUE;
}
/************************************************************************
/
/ FUNCTION NAME: struct tagged_list_t *Do_look_tagged(struct client_t *c)
/
/ FUNCTION: find location in player file of given name
/
/ AUTHOR: Brian Kelly, 01/09/01
/
/ ARGUMENTS:
/ char *name - name of character to look for
/ struct player *playerp - pointer of structure to fill
/
/ RETURN VALUE: location of player if found, -1 otherwise
/
/ MODULES CALLED: fread(), fseek(), strcmp()
/
/ GLOBAL INPUTS: Wizard, *Playersfp
/
/ GLOBAL OUTPUTS: none
/
/ DESCRIPTION:
/ Search the player file for the player of the given name.
/ If player is found, fill structure with player data.
/
*************************************************************************/
struct tagged_list_t *Do_look_tagged(struct client_t *c)
{
struct tagged_t readTagged;
struct tagged_list_t *taggedList, *taggedList_ptr;
FILE *tagged_file, *temp_file;
time_t timeNow;
char error_msg[SZ_ERROR_MESSAGE], machineID[16];
Do_lock_mutex(&c->realm->tagged_file_lock);
/* get the time now */
timeNow = time(NULL);
taggedList = NULL;
sprintf(machineID, "%ld", c->machineID);
/* open a temp file to transfer records to */
errno = 0;
if ((temp_file=fopen(TEMP_TAGGED_FILE, "w")) == NULL) {
Do_unlock_mutex(&c->realm->tagged_file_lock);
sprintf(error_msg,
"[%s] fopen of %s failed in Do_look_tagged: %s.\n",
c->connection_id, TEMP_TAGGED_FILE, strerror(errno));
Do_log_error(error_msg);
return NULL;
}
/* open the tagged file */
errno = 0;
if ((tagged_file=fopen(TAGGED_FILE, "r")) == NULL) {
fclose(temp_file);
remove(TEMP_TAGGED_FILE);
Do_unlock_mutex(&c->realm->tagged_file_lock);
sprintf(error_msg,
"[%s] fopen of %s failed in Do_look_tagged: %s\n",
c->connection_id, TAGGED_FILE, strerror(errno));
Do_log_error(error_msg);
return NULL;
}
/* run through the tag entries */
while (fread((void *)&readTagged, SZ_TAGGED, 1, tagged_file) == 1) {
/* see if this tag is outdated */
if (readTagged.validUntil < timeNow) {
/* don't rewrite it */
continue;
}
/* is this tagged entry pertain to us? */
else if (
/* see if this machine is us */
(readTagged.type == T_MACHINE && c->machineID > 0 &&
strcmp(readTagged.name, machineID) == 0) ||
/* see if this account is ours */
(readTagged.type == T_ACCOUNT && c->accountLoaded &&
strcmp(readTagged.name, c->account) == 0) ||
/* see if this is the character's account */
(readTagged.type == T_ACCOUNT && c->characterLoaded &&
strcmp(readTagged.name, c->player.parent_account) == 0) ||
/* see if this is our address */
(readTagged.type == T_ADDRESS && strcmp(readTagged.name,
c->IP) == 0) ||
/* see if this is our network */
(readTagged.type == T_NETWORK && strcmp(readTagged.name,
c->network) == 0) ) {
/* create a new list strcture to pass the info back */
taggedList_ptr = (struct tagged_list_t *) Do_malloc(SZ_TAGGED_LIST);
memcpy(&taggedList_ptr->theTagged, &readTagged, SZ_TAGGED);
/* put the strcture into the list */
taggedList_ptr->next = taggedList;
taggedList = taggedList_ptr;
}
/* write the tag to the temp file */
if (fwrite((void *)&readTagged, SZ_TAGGED, 1, temp_file) != 1) {
fclose(tagged_file);
fclose(temp_file);
remove(TEMP_TAGGED_FILE);
Do_unlock_mutex(&c->realm->tagged_file_lock);
sprintf(error_msg,
"[%s] fwrite of %s failed in Do_look_tagged: %s.\n",
c->connection_id, TEMP_TAGGED_FILE, strerror(errno));
Do_log_error(error_msg);
return taggedList;
}
}
/* close the two files */
fclose(temp_file);
fclose(tagged_file);
/* delete the old character record */
remove(TAGGED_FILE);
/* replace it with the temporary file */
rename(TEMP_TAGGED_FILE, TAGGED_FILE);
Do_unlock_mutex(&c->realm->tagged_file_lock);
return taggedList;
}
/************************************************************************
/
/ FUNCTION NAME: Do_check_tags(struct client_t *c)
/
/ FUNCTION: return a char specifying player type
/
/ AUTHOR: Brian Kelly, 01/09/01
/
/ ARGUMENTS:
/ struct client_t c - pointer to the main client strcture
/
/ RETURN VALUE:
/ char - character the describes the character
/
/ MODULES CALLED: strcpy()
/
/ DESCRIPTION:
/ Return a string describing the player type.
/ King, council, valar, supercedes other types.
/ The first character of the string is '*' if the player
/ has a crown.
/ If 'shortflag' is TRUE, return a 3 character string.
/
*************************************************************************/
int Do_check_tags(struct client_t *c)
{
struct tagged_list_t *taggedList, *taggedList_ptr;
struct tag_t theTag;
char error_msg[SZ_ERROR_MESSAGE], string_buffer[SZ_LINE];
/* read all the tags that pertain to us */
taggedList = Do_look_tagged(c);
/* see if this player inherits any tags, skip if wiz backdoor */
if (c->wizaccount[0] == '\0') {
Do_check_inherit(c, taggedList);
}
/* run through the list of tagged recalled */
while (taggedList != NULL) {
if (Do_look_tag(c, &theTag, taggedList->theTagged.tagNumber)) {
/* implement the tag */
Do_implement_tag(c, &theTag);
}
taggedList_ptr = taggedList;
taggedList = taggedList->next;
free((void *)taggedList_ptr);
}
return;
}
/************************************************************************
/
/ FUNCTION NAME: struct tagged_list_t *Do_check_inherit(struct client_t *c)
/
/ FUNCTION: return a char specifying player type
/
/ AUTHOR: Brian Kelly, 01/09/01
/
/ ARGUMENTS:
/ struct client_t c - pointer to the main client strcture
/
/ RETURN VALUE:
/ char - character the describes the character
/
/ MODULES CALLED: strcpy()
/
/ DESCRIPTION:
/ Return a string describing the player type.
/ King, council, valar, supercedes other types.
/ The first character of the string is '*' if the player
/ has a crown.
/ If 'shortflag' is TRUE, return a 3 character string.
/
*************************************************************************/
Do_check_inherit(struct client_t *c, struct tagged_list_t *list_ptr)
{
struct tagged_sort_t *the_sort, *sort_ptr;
the_sort = NULL;
/* run though the tagged list */
while (list_ptr != NULL) {
/* run through the sort list */
sort_ptr = the_sort;
while (sort_ptr != NULL) {
/* see if this list entry is this sort structure */
if (sort_ptr->tag == list_ptr->theTagged.tagNumber) {
/* point the sort strcture to this entry */
sort_ptr->tagged[list_ptr->theTagged.type] =
&list_ptr->theTagged;
break;
}
sort_ptr = sort_ptr->next;
}
/* if we found no sort structure */
if (sort_ptr == NULL) {
/* create one */
sort_ptr = (struct tagged_sort_t *) Do_malloc(SZ_TAGGED_SORT);
sort_ptr->tag = list_ptr->theTagged.tagNumber;
sort_ptr->tagged[0] = NULL;
sort_ptr->tagged[1] = NULL;
sort_ptr->tagged[2] = NULL;
sort_ptr->tagged[3] = NULL;
sort_ptr->tagged[list_ptr->theTagged.type] = &list_ptr->theTagged;
/* put it in place */
sort_ptr->next = the_sort;
the_sort = sort_ptr;
}
list_ptr = list_ptr->next;
}
/* run through the sorted lists */
while (the_sort != NULL) {
/* accounts pass to IP and Machine */
if (the_sort->tagged[T_ACCOUNT] != NULL) {
/* pass to the address if needed */
if (the_sort->tagged[T_ADDRESS] == NULL) {
Do_inherit_tag(c, the_sort->tagged[T_ACCOUNT], T_ADDRESS);
}
/* pass to the machine if needed */
if (c->machineID && the_sort->tagged[T_MACHINE] == NULL) {
Do_inherit_tag(c, the_sort->tagged[T_ACCOUNT], T_MACHINE);
}
}
/* IP passes to the machine */
else if (the_sort->tagged[T_ADDRESS] != NULL) {
/* pass to the machine if needed */
if (c->machineID && the_sort->tagged[T_MACHINE] == NULL) {
Do_inherit_tag(c, the_sort->tagged[T_ADDRESS], T_MACHINE);
}
}
sort_ptr = the_sort->next;
free((void *)the_sort);
the_sort = sort_ptr;
}
}
/************************************************************************
/
/ FUNCTION NAME: Do_inherit_tag(struct client_t *c, struct tagged_t *source, int targetType)
/
/ FUNCTION: return a char specifying player type
/
/ AUTHOR: Brian Kelly, 01/09/01
/
/ ARGUMENTS:
/ struct client_t c - pointer to the main client strcture
/
/ RETURN VALUE:
/ char - character the describes the character
/
/ MODULES CALLED: strcpy()
/
/ DESCRIPTION:
/ Return a string describing the player type.
/ King, council, valar, supercedes other types.
/ The first character of the string is '*' if the player
/ has a crown.
/ If 'shortflag' is TRUE, return a 3 character string.
/
*************************************************************************/
Do_inherit_tag(struct client_t *c, struct tagged_t *source, int targetType)
{
struct tagged_t theTagged;
struct tag_t theTag;
struct history_t theHistory;
char string_buffer[SZ_LINE], sourceName[SZ_FROM + 10];
char targetName[SZ_FROM + 10];
time_t maxDuration;
/* load the tag */
Do_look_tag(c, &theTag, source->tagNumber);
/* create a new tagged */
theTagged.tagNumber = source->tagNumber;
theTagged.type = targetType;
/* prepare the history entry */
theHistory.date = time(NULL);
theHistory.type = targetType;
/* Find the name for the target machine */
switch(targetType) {
case T_MACHINE:
sprintf(targetName, "Machine #%d", c->machineID);
sprintf(theTagged.name, "%d", c->machineID);
sprintf(theHistory.name, "%d", c->machineID);
theTagged.validUntil = source->validUntil;
break;
case T_ACCOUNT:
sprintf(targetName, "Account %s", c->lcaccount);
strcpy(theTagged.name, c->lcaccount);
strcpy(theHistory.name, c->lcaccount);
theTagged.validUntil = source->validUntil;
break;
case T_ADDRESS:
sprintf(targetName, "Address %s", c->IP);
strcpy(theTagged.name, c->IP);
strcpy(theHistory.name, c->IP);
maxDuration = theHistory.date + 3600;
/* IPs can only be tagged for an hour */
if (source->validUntil < maxDuration) {
theTagged.validUntil = source->validUntil;
}
else {
theTagged.validUntil = maxDuration;
}
break;
case T_NETWORK:
sprintf(targetName, "Network %s", c->network);
strcpy(theTagged.name, c->network);
strcpy(theHistory.name, c->network);
theTagged.validUntil = source->validUntil;
break;
}
Do_save_tagged(c, &theTagged);
/* get the time the ban expires */
ctime_r(&theTag.validUntil, string_buffer);
string_buffer[strlen(string_buffer) - 1] = '\0';
sprintf(theHistory.description,
"Inherited %d tag #%d from %s%s for \"%s\" effective until %s.\n",
tagTypes[theTag.type], theTag.number, taggedTypes[source->type],
source->name, theTag.description, string_buffer);
Do_save_history(c, &theHistory);
sprintf(string_buffer, "[%s] %s inherited %s tag #%d from %s%s.\n",
c->connection_id, targetName, tagTypes[theTag.type],
theTag.number, taggedTypes[source->type], source->name);
Do_log(HACK_LOG, string_buffer);
}
/************************************************************************
/
/ FUNCTION NAME: Do_implement_tag(struct client_t *c, struct tag_t *theTag)
/
/ FUNCTION: return a char specifying player type
/
/ AUTHOR: Brian Kelly, 01/14/01
/
/ ARGUMENTS:
/ struct client_t c - pointer to the main client strcture
/
/ RETURN VALUE:
/ char - character the describes the character
/
/ MODULES CALLED: strcpy()
/
/ DESCRIPTION:
/ Return a string describing the player type.
/ King, council, valar, supercedes other types.
/ The first character of the string is '*' if the player
/ has a crown.
/ If 'shortflag' is TRUE, return a 3 character string.
/
*************************************************************************/
Do_implement_tag(struct client_t *c, struct tag_t *theTag)
{
char error_msg[SZ_ERROR_MESSAGE];
char string_buffer[SZ_LINE];
struct event_t *event_ptr;
/* now implement the tag */
switch (theTag->type) {
case T_BAN:
/* add this event to the connection log */
sprintf(error_msg, "[%s] Connection banned by tag #%d.\n",
c->connection_id, theTag->number);
Do_log(CONNECTION_LOG, error_msg);
/* send a message to the user */
Do_send_error(c,
"This location is no longer permitted to play Phantasia.\n");
if (c->characterLoaded == TRUE) {
c->run_level = SAVE_AND_EXIT;
}
else {
c->run_level = EXIT_THREAD;
}
break;
case T_SUICIDE:
if (c->characterLoaded) {
event_ptr = (struct event_t *) Do_create_event();
event_ptr->type = DEATH_EVENT;
event_ptr->to = c->game;
event_ptr->from = c->game;
event_ptr->arg3 = K_SUICIDE;
Do_send_event(event_ptr);
}
break;
case T_MUTE:
if (c->characterLoaded) {
/* send a message to the user */
sprintf(string_buffer, "Your characters are muted due to %s.\n",
theTag->description);
/* send off an error dialog */
Do_dialog(c, string_buffer);
}
c->muteUntil = theTag->validUntil;
break;
case T_PREFIX:
if (c->characterLoaded) {
strcpy(string_buffer, theTag->description);
strcat(string_buffer, " ");
strcat(string_buffer, c->player.name);
if (c->characterAnnounced) {
Do_send_specification(c, REMOVE_PLAYER_EVENT);
}
strncpy(c->modifiedName, string_buffer, SZ_NAME - 1);
if (c->characterAnnounced) {
Do_send_specification(c, ADD_PLAYER_EVENT);
Do_name(c);
}
}
c->tagUntil = theTag->validUntil;
break;
case T_SUFFIX:
if (c->characterLoaded) {
strcpy(string_buffer, c->player.name);
strcat(string_buffer, " ");
strcat(string_buffer, theTag->description);
if (c->characterAnnounced) {
Do_send_specification(c, REMOVE_PLAYER_EVENT);
}
strncpy(c->modifiedName, string_buffer, SZ_NAME - 1);
if (c->characterAnnounced) {
Do_send_specification(c, ADD_PLAYER_EVENT);
Do_name(c);
}
}
c->tagUntil = theTag->validUntil;
break;
}
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_create_tag(struct client_t *c, int tagType)
/
/ FUNCTION: return a char specifying player type
/
/ AUTHOR: Brian Kelly, 01/14/01
/
/ ARGUMENTS:
/ struct client_t c - pointer to the main client strcture
/
/ RETURN VALUE:
/ char - character the describes the character
/
/ MODULES CALLED: strcpy()
/
/ DESCRIPTION:
/ Return a string describing the player type.
/ King, council, valar, supercedes other types.
/ The first character of the string is '*' if the player
/ has a crown.
/ If 'shortflag' is TRUE, return a 3 character string.
/
*************************************************************************/
Do_create_tag(struct client_t *c, int tagType)
{
struct button_t buttons;
struct event_t *eventPtr;
struct tag_t theTag, *tagPtr;
struct tagged_t theTagged;
struct history_t theHistory;
long answer;
char error_msg[SZ_ERROR_MESSAGE];
char string_buffer[SZ_LINE];
char tagee[SZ_NAME];
int i;
time_t timeNow;
int tagTimes[] = {3600, 10800, 86400, 259200, 604800, 2592000, 7776000, 31536000};
/* start filling out the tag */
timeNow = time(NULL);
theTag.type = tagType;
theTag.affectNetwork = FALSE;
theTag.contagious = FALSE;
sprintf(string_buffer, "What life would you like this %s to have? (shorter times under cantrip)\n",
tagTypes[tagType]);
Do_send_line(c, string_buffer);
strcpy(buttons.button[0], "1 hour\n");
strcpy(buttons.button[1], "3 hours\n");
strcpy(buttons.button[2], "1 day\n");
strcpy(buttons.button[3], "3 days\n");
strcpy(buttons.button[4], "1 week\n");
strcpy(buttons.button[5], "1 month\n");
strcpy(buttons.button[6], "3 months\n");
strcpy(buttons.button[7], "1 year\n");
Do_clear_buttons(&buttons, 8);
if (Do_buttons(c, &answer, &buttons) != S_NORM) {
Do_send_clear(c);
return;
}
Do_send_clear(c);
if (answer > 7 || answer < 0) {
sprintf(error_msg,
"[%s] Returned non-option in Do_create_tags.\n",
c->connection_id);
Do_log_error(error_msg);
Do_caught_hack(c, H_SYSTEM);
return;
}
/* convert to a time */
theTag.validUntil = timeNow + tagTimes[answer];
if (tagType == T_PREFIX || tagType == T_SUFFIX) {
sprintf(string_buffer,
"What %s would you like to add to this character's name?\n",
tagTypes[tagType]);
}
else {
sprintf(string_buffer,
"This %s is being created for: (e.g. \"claiming N'Sync rules\".\n",
tagTypes[tagType]);
}
if (Do_string_dialog(c, &theTag.description, SZ_LINE - 1, string_buffer)) {
return;
}
/* find out where it goes */
sprintf(string_buffer, "What do you wish to %s?\n", tagTypes[tagType]);
Do_send_line(c, string_buffer);
strcpy(buttons.button[0], "Player\n");
strcpy(buttons.button[1], "Machine\n");
strcpy(buttons.button[2], "Account\n");
strcpy(buttons.button[3], "Address\n");
strcpy(buttons.button[4], "Network\n");
Do_clear_buttons(&buttons, 5);
strcpy(buttons.button[7], "Cancel\n");
if (Do_buttons(c, &answer, &buttons) != S_NORM || answer == 7) {
Do_send_clear(c);
return;
}
Do_send_clear(c);
if (answer > 5 || answer < 0) {
sprintf(error_msg,
"[%s] Returned non-option in Do_create_tags(2).\n",
c->connection_id);
Do_log_error(error_msg);
Do_caught_hack(c, H_SYSTEM);
return;
}
switch(answer) {
case 0:
sprintf(string_buffer, "Who do you wish to %s?\n", tagTypes[tagType]);
if (Do_player_dialog(c, string_buffer, tagee) != S_NORM) {
return;
}
/* convert the tag to an object */
tagPtr = (struct tag_t *) Do_malloc(SZ_TAG);
memcpy(tagPtr, &theTag, SZ_TAG);
/* create the event */
eventPtr = (struct event_t *) Do_create_event();
eventPtr->type = TAG_EVENT;
eventPtr->from = c->game;
if(tagPtr->type == T_MUTE)
{
eventPtr->arg3 = T_MUTE;
}
eventPtr->arg4 = tagPtr;
/* send off the event */
if (!Do_send_character_event(c, eventPtr, tagee)) {
free((void *)eventPtr);
free((void *)tagPtr);
Do_send_line(c, "That character just left the game.\n");
Do_more(c);
Do_send_clear(c);
return;
}
Do_send_line(c, "The tag has been sent.\n");
Do_more(c);
Do_send_clear(c);
return;
case 1:
sprintf(string_buffer, "What machine number do you wish to %s?\n",
tagTypes[tagType]);
/* associate the machine to the tag */
theTagged.type = T_MACHINE;
theHistory.type = T_MACHINE;
break;
case 2:
sprintf(string_buffer, "What account do you wish to %s?\n",
tagTypes[tagType]);
/* associate the account to the tag */
theTagged.type = T_ACCOUNT;
theHistory.type = T_ACCOUNT;
break;
case 3:
sprintf(string_buffer, "What address do you wish to %s?\n",
tagTypes[tagType]);
/* associate the address to the tag */
theTagged.type = T_ADDRESS;
theHistory.type = T_ADDRESS;
break;
case 4:
sprintf(string_buffer, "What network do you wish to %s?\n",
tagTypes[tagType]);
/* associate the network to the tag */
theTagged.type = T_NETWORK;
theHistory.type = T_NETWORK;
break;
default:
sprintf(error_msg, "[%s] Returned non-option %ld in Do_create_tag.\n",
c->connection_id, answer);
Do_log_error(error_msg);
Do_caught_hack(c, H_SYSTEM);
return;
}
/* get the item to tag */
if (Do_string_dialog(c, &tagee, SZ_NAME - 1, string_buffer)
!= S_NORM) {
return;
}
/* get the next tag number */
Do_lock_mutex(&c->realm->tag_file_lock);
theTag.number = c->realm->nextTagNumber++;
Do_unlock_mutex(&c->realm->tag_file_lock);
/* write the tag */
Do_save_tag(c, &theTag);
/* fill out the tagged and file it */
Do_lowercase(&theTagged.name, tagee);
theTagged.tagNumber = theTag.number;
theTagged.validUntil = theTag.validUntil;
Do_save_tagged(c, &theTagged);
/* put together something for the logs */
ctime_r(&theTagged.validUntil, error_msg);
error_msg[strlen(error_msg) - 1] = '\0';
theHistory.date = timeNow;
strcpy(theHistory.name, theTagged.name);
sprintf(theHistory.description,
"%s created %s tag #%d for \"%s\" effective until %s.\n",
c->modifiedName, tagTypes[tagType], theTag.number,
theTag.description, error_msg);
Do_save_history(c, &theHistory);
sprintf(string_buffer,
"[%s] %s created %s tag #%d for \"%s\" effective until %s.\n",
c->connection_id, c->modifiedName, tagTypes[tagType],
theTag.number, theTag.description, error_msg);
Do_log(HACK_LOG, string_buffer);
sprintf(string_buffer, "[%s] Attached %s%s to tag #%d.\n", c->connection_id,
taggedTypes[tagType], theTagged.name, theTag.number);
Do_log(HACK_LOG, string_buffer);
Do_send_line(c, "The tag has been sent.\n");
Do_more(c);
Do_send_clear(c);
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_create_minitag(struct client_t *c, int tagType)
/
/ FUNCTION: allow trusted players to tag other players for short periods
/
/ AUTHOR: Brian Kelly, 01/14/01
/
/ ARGUMENTS:
/ struct client_t c - pointer to the main client strcture
/
/ RETURN VALUE:
/
/ MODULES CALLED: strcpy()
/
/ DESCRIPTION:
/
*************************************************************************/
Do_create_minitag(struct client_t *c, int tagType)
{
struct button_t buttons;
struct event_t *eventPtr;
struct tag_t theTag, *tagPtr;
struct tagged_t theTagged;
struct history_t theHistory;
long answer;
char error_msg[SZ_ERROR_MESSAGE];
char string_buffer[SZ_LINE];
char tagee[SZ_NAME];
int i;
time_t timeNow;
int tagTimes[] = {60, 300, 900, 1800, 3600, 10800};
/* start filling out the tag */
timeNow = time(NULL);
theTag.type = tagType;
theTag.affectNetwork = FALSE;
theTag.contagious = FALSE;
sprintf(string_buffer, "How long would you like this %s to be?\n",
tagTypes[tagType]);
Do_send_line(c, string_buffer);
strcpy(buttons.button[0], "1 min\n");
strcpy(buttons.button[1], "5 min\n");
strcpy(buttons.button[2], "15 min\n");
strcpy(buttons.button[3], "30 min\n");
if (tagType != T_BAN) {
strcpy(buttons.button[4], "1 hour\n");
strcpy(buttons.button[5], "3 hours\n");
Do_clear_buttons(&buttons, 6);
} else {
Do_clear_buttons(&buttons, 4);
}
strcpy(buttons.button[7], "Cancel\n");
if (Do_buttons(c, &answer, &buttons) != S_NORM || answer == 7) {
Do_send_clear(c);
return;
}
Do_send_clear(c);
if (answer > 7 || answer < 0) {
sprintf(error_msg,
"[%s] Returned non-option in Do_create_minitags.\n",
c->connection_id);
Do_log_error(error_msg);
Do_caught_hack(c, H_SYSTEM);
return;
}
/* convert to a time */
theTag.validUntil = timeNow + tagTimes[answer];
if (tagType == T_PREFIX || tagType == T_SUFFIX) {
sprintf(string_buffer,
"What %s would you like to add to this character's name?\n",
tagTypes[tagType]);
}
else {
sprintf(string_buffer,
"This %s is being created for: (e.g. \"being a moron\".\n",
tagTypes[tagType]);
}
if (Do_string_dialog(c, &theTag.description, SZ_LINE - 1, string_buffer)) {
return;
}
sprintf(string_buffer, "Who do you wish to %s?\n", tagTypes[tagType]);
if (Do_player_dialog(c, string_buffer, tagee) != S_NORM) {
return;
}
/* convert the tag to an object */
tagPtr = (struct tag_t *) Do_malloc(SZ_TAG);
memcpy(tagPtr, &theTag, SZ_TAG);
/* create the event */
eventPtr = (struct event_t *) Do_create_event();
eventPtr->type = TAG_EVENT;
eventPtr->from = c->game;
if(tagPtr->type == T_MUTE)
{
eventPtr->arg3 = T_MUTE;
}
eventPtr->arg4 = tagPtr;
/* send off the event */
if (!Do_send_character_event(c, eventPtr, tagee)) {
free((void *)eventPtr);
free((void *)tagPtr);
Do_send_line(c, "That character just left the game.\n");
Do_more(c);
Do_send_clear(c);
return;
}
/* get the time the ban expires */
ctime_r(&theTag.validUntil, error_msg);
error_msg[strlen(error_msg) - 1] = '\0';
sprintf(string_buffer,
"[%s] %s created %s tag on %s for \"%s\" effective until %s.\n",
c->connection_id, c->modifiedName, tagTypes[tagType], tagee,
theTag.description, error_msg);
Do_log(CANTRIP_LOG, string_buffer);
Do_send_line(c, "The cantrip has been sent.\n");
if ((tagType != T_PREFIX) && (tagType != T_SUFFIX)) {
sprintf(string_buffer,
"%s was %s by %s for %s.\n",
tagee, tagDescs[tagType], c->modifiedName, theTag.description);
Do_broadcast(c, string_buffer);
}
return;
}
/************************************************************************
/
/ FUNCTION NAME: int Do_remove_tagged(struct client_t *c, int tageeType, char *tageeName, int tagNumber)
/
/ FUNCTION: find location in player file of given name
/
/ AUTHOR: Brian Kelly, 01/19/01
/
/ ARGUMENTS:
/ char *name - name of character to look for
/ struct player *playerp - pointer of structure to fill
/
/ RETURN VALUE: location of player if found, -1 otherwise
/
/ MODULES CALLED: fread(), fseek(), strcmp()
/
/ GLOBAL INPUTS: Wizard, *Playersfp
/
/ GLOBAL OUTPUTS: none
/
/ DESCRIPTION:
/ Search the player file for the player of the given name.
/ If player is found, fill structure with player data.
/
*************************************************************************/
int Do_remove_tagged(struct client_t *c, int tageeType, char *tageeName, int tagNumber)
{
struct tagged_t readTagged;
FILE *tagged_file, *temp_file;
time_t timeNow;
char error_msg[SZ_ERROR_MESSAGE];
bool foundTagged;
Do_lock_mutex(&c->realm->tagged_file_lock);
/* get the time now */
timeNow = time(NULL);
/* open a temp file to transfer records to */
errno = 0;
if ((temp_file=fopen(TEMP_TAGGED_FILE, "w")) == NULL) {
Do_unlock_mutex(&c->realm->tagged_file_lock);
sprintf(error_msg,
"[%s] fopen of %s failed in Do_remove_tagged: %s.\n",
c->connection_id, TEMP_TAGGED_FILE, strerror(errno));
Do_log_error(error_msg);
return FALSE;
}
errno = 0;
if ((tagged_file=fopen(TAGGED_FILE, "r")) == NULL) {
fclose(temp_file);
Do_unlock_mutex(&c->realm->tagged_file_lock);
sprintf(error_msg,
"[%s] fopen of %s failed in Do_remove_tagged: %s\n",
c->connection_id, TAGGED_FILE, strerror(errno));
Do_log_error(error_msg);
return FALSE;
}
foundTagged = FALSE;
/* run through the tag entries */
while (fread((void *)&readTagged, SZ_TAGGED, 1, tagged_file) == 1) {
/* this is the a tagged strcture we want? */
if (readTagged.tagNumber == tagNumber && readTagged.type == tageeType
&& strcmp(readTagged.name, tageeName) == 0) {
/* mark it as deleted */
foundTagged = TRUE;
/* and don't re-write it */
continue;
}
/* see if this tag is outdated */
if (readTagged.validUntil < timeNow) {
/* don't rewrite it */
continue;
}
/* write the tag to the temp file */
if (fwrite((void *)&readTagged, SZ_TAGGED, 1, temp_file) != 1) {
fclose(tagged_file);
fclose(temp_file);
remove(TEMP_TAGGED_FILE);
Do_unlock_mutex(&c->realm->tagged_file_lock);
sprintf(error_msg,
"[%s] fwrite of %s failed in Do_remove_tagged: %s.\n",
c->connection_id, TEMP_TAGGED_FILE, strerror(errno));
Do_log_error(error_msg);
return FALSE;
}
}
/* close the two files */
fclose(temp_file);
fclose(tagged_file);
/* delete the old character record */
remove(TAGGED_FILE);
/* replace it with the temporary file */
rename(TEMP_TAGGED_FILE, TAGGED_FILE);
Do_unlock_mutex(&c->realm->tagged_file_lock);
if (foundTagged) {
return TRUE;
}
return FALSE;
}
/************************************************************************
/
/ FUNCTION NAME: Do_untag(struct client_t *c)
/
/ FUNCTION: return a char specifying player type
/
/ AUTHOR: Brian Kelly, 01/18/01
/
/ ARGUMENTS:
/ struct client_t c - pointer to the main client strcture
/
/ RETURN VALUE:
/ char - character the describes the character
/
/ MODULES CALLED: strcpy()
/
/ DESCRIPTION:
/ Return a string describing the player type.
/ King, council, valar, supercedes other types.
/ The first character of the string is '*' if the player
/ has a crown.
/ If 'shortflag' is TRUE, return a 3 character string.
/
*************************************************************************/
Do_untag(struct client_t *c)
{
struct button_t buttons;
struct history_t theHistory;
long tageeType, tagNumber;
char error_msg[SZ_ERROR_MESSAGE];
char string_buffer[SZ_LINE];
char tagee[SZ_NAME];
int i;
Do_send_line(c, "Do you wish to untag an account or an address?\n");
strcpy(buttons.button[0], "Machine\n");
strcpy(buttons.button[1], "Account\n");
strcpy(buttons.button[2], "Address\n");
strcpy(buttons.button[3], "Network\n");
Do_clear_buttons(&buttons, 4);
strcpy(buttons.button[7], "Cancel\n");
if (Do_buttons(c, &tageeType, &buttons) != S_NORM) {
Do_send_clear(c);
return;
}
Do_send_clear(c);
switch (tageeType) {
case 0:
tageeType = T_MACHINE;
if (Do_string_dialog(c, tagee, SZ_NAME - 1,
"What machine do you wish to untag?\n") != S_NORM) {
return;
}
break;
case 1:
tageeType = T_ACCOUNT;
if (Do_string_dialog(c, tagee, SZ_NAME - 1,
"What account do you wish to untag?\n") != S_NORM) {
return;
}
break;
case 2:
tageeType = T_ADDRESS;
if (Do_string_dialog(c, tagee, SZ_NAME - 1,
"What address do you wish to untag?\n") != S_NORM) {
return;
}
break;
case 3:
tageeType = T_NETWORK;
if (Do_string_dialog(c, tagee, SZ_NAME - 1,
"What network do you wish to untag?\n") != S_NORM) {
return;
}
break;
case 7:
return;
break;
default:
sprintf(error_msg, "[%s] Returned non-option %ld in Do_untag.\n",
c->connection_id, tageeType);
Do_log_error(error_msg);
Do_caught_hack(c, H_SYSTEM);
return;
}
Do_lowercase(&tagee, &tagee);
if (Do_long_dialog(c, &tagNumber, "What is the tag number to remove?\n")) {
return;
}
if (Do_remove_tagged(c, (int) tageeType, tagee, (int) tagNumber)) {
theHistory.date = time(NULL);
theHistory.type = (int) tageeType;
strcpy(theHistory.name, tagee);
sprintf(theHistory.description, "%s removed connection to tag #%d.\n",
c->modifiedName, tagNumber);
Do_save_history(c, &theHistory);
Do_send_line(c, "The tag was successfully removed.\n");
}
else {
Do_send_line(c,
"I could not find the tag number or the account/address.\n");
}
Do_more(c);
Do_send_clear(c);
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_remove_prefix_suffix(struct client_t *c)
/
/ FUNCTION: Remove a prefix or suffix tag from a player.
/
/ AUTHOR: Renee Gehlbach, 8/6/2002
/
/ ARGUMENTS:
/ struct client_t c - pointer to the main client strcture
/
/ RETURN VALUE:
/
/ MODULES CALLED: strcpy(), strncpy(), Do_send_specification(), Do_name()
/
/ DESCRIPTION:
/ Remove a prefix or suffix from a player.
/
*************************************************************************/
Do_remove_prefix_suffix(struct client_t *c)
{
char string_buffer[SZ_NAME];
if(c->characterLoaded)
{
if(strcmp(c->player.name, c->modifiedName) != 0)
{
strcpy(string_buffer, c->player.name);
if(c->characterAnnounced)
{
Do_send_specification(c, REMOVE_PLAYER_EVENT);
}
strncpy(c->modifiedName, string_buffer, SZ_NAME - 1);
if(c->characterAnnounced)
{
Do_send_specification(c, ADD_PLAYER_EVENT);
Do_name(c);
}
}
}
return;
}
/************************************************************************
/
/ FUNCTION NAME: int Do_tag_muted(struct client_t *c, stuct tag_t *theMute)
/
/ FUNCTION: Give muted players a tag of "the Silent" which lasts for the
/ duration of their mute
/
/ AUTHOR: Renee Gehlbach, 6/24/2002
/
/ ARGUMENTS: struct client_t *c - stu
/
/
/ RETURN VALUE:
/ char - character the describes the character
/
/ MODULES CALLED: strcpy()
/
/ DESCRIPTION:
/ Return a string describing the player type.
/ King, council, valar, supercedes other types.
/ The first character of the string is '*' if the player
/ has a crown.
/ If 'shortflag' is TRUE, return a 3 character string.
/
*************************************************************************/
int Do_tag_muted(struct client_t *c, struct tag_t *theMute)
{
struct event_t *eventPtr;
struct tag_t theTag, *tagPtr;
char string_buffer[SZ_LINE], error_msg[SZ_LINE];
char tagee[SZ_NAME];
sprintf(tagee, c->player.name);
/* fill out the tag */
theTag.type = T_SUFFIX;
theTag.validUntil = theMute->validUntil;
theTag.affectNetwork = theMute->affectNetwork;
theTag.contagious = theMute->contagious;
sprintf(theTag.description, "the Silent");
/* convert the tag to an object */
tagPtr = (struct tag_t *) Do_malloc(SZ_TAG);
memcpy (tagPtr, &theTag, SZ_TAG);
/* create the event */
eventPtr = (struct event_t *) Do_create_event();
eventPtr->type = TAG_EVENT;
eventPtr->from = c->game;
if(tagPtr->type == T_MUTE)
{
eventPtr->arg3 = T_MUTE;
}
eventPtr->arg4 = tagPtr;
/* send off the event */
if (!Do_send_character_event(c, eventPtr, tagee))
{
free((void *)eventPtr);
free((void *)tagPtr);
Do_more(c);
Do_send_clear(c);
return;
}
ctime_r(&theTag.validUntil, error_msg);
error_msg[strlen(error_msg) - 1] = '\0';
return;
}