/* * 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; }