/************************************************************** * FFTacticsMUD : admin.cpp * ************************************************************** * (c) 2002 Damien Dailidenas (Trenton). All rights reserved. * **************************************************************/ #include <iomanip> #include <strstream> #include <fstream> #include <cstdio> #include <unistd.h> #include "main.h" #include "mysql/mysql.h" const struct wiznet_type wiznet_table[] = { { "on", WIZ_ON }, { "links", WIZ_LINKS }, { "spam", WIZ_SPAM }, { "deaths", WIZ_DEATHS }, { "memory", WIZ_MEMORY }, {} }; bool CH::is_admin() { MYSQL mysql; MYSQL_RES *res; MYSQL_ROW row; mysql_init(&mysql); if(!mysql_real_connect(&mysql, DB_LOC, DB_USER, DB_PASS, DB_NAME, 0, NULL, 0)) return false; ostrstream ost; ost << "SELECT * FROM admins WHERE name='" + name + "'" << ends; mysql_query(&mysql, ost.str()); res = mysql_store_result(&mysql); if(mysql_num_rows(res)) { row = mysql_fetch_row(res); wiznet = db_read_flags(row[1]); mysql_free_result(res); mysql_close(&mysql); return true; } mysql_free_result(res); mysql_close(&mysql); return false; } long wiznet_lookup(const string name) { for(short flag = 0; wiznet_table[flag].name; ++flag) if(find(name, wiznet_table[flag].name)) return flag; return -1; } void do_wiznet(CH *ch, string argument = "") { if(argument.empty()) { ch->printf("Usage: wiznet [on | off | show | status | [option]]\n\r"); return; } if(find(argument, "on")) { ch->printf("wiznet> on\n\r"); SET_BIT(ch->wiznet, WIZ_ON); return; } else if(find(argument, "off")) { ch->printf("wiznet> off\n\r"); REM_BIT(ch->wiznet, WIZ_ON); return; } short flag; string str; if(find(argument, "status")) { if(!IS_SET(ch->wiznet, WIZ_ON)) str = "off "; for(flag = 0; wiznet_table[flag].name; ++flag) if(IS_SET(ch->wiznet, wiznet_table[flag].flag)) str += (string)wiznet_table[flag].name + " "; str += ENDL; ch->printf("wiznet> status> " + str); return; } if(find(argument, "show")) { for(flag = 0; wiznet_table[flag].name; ++flag) str += (string)wiznet_table[flag].name + " "; str += ENDL; ch->printf("wiznet> options> " + str); return; } flag = wiznet_lookup(argument); if(flag == -1) { ch->printf("wiznet: ERROR: No such option, " + argument + ".\n\r"); return; } if(IS_SET(ch->wiznet, wiznet_table[flag].flag)) { ch->printf("wiznet> " + (string)wiznet_table[flag].name + "> off\n\r"); REM_BIT(ch->wiznet, wiznet_table[flag].flag); } else { ch->printf("wiznet> " + (string)wiznet_table[flag].name + "> on\n\r"); SET_BIT(ch->wiznet, wiznet_table[flag].flag); } return; } void wiz_echo(const string str, long flag = 0) { for(DESC *d = desc_list; d; d = d->next) if(d->ch && d->connected == CON_PLAYING && IS_SET(d->ch->wiznet, WIZ_ON) && (!flag || IS_SET(d->ch->wiznet, flag))) d->ch->printf(str); return; } void do_disconnect(CH *ch, string argument = "") { string arg; DESC *d; CH *victim; split(argument, arg); if(arg.empty()) { ch->printf("Usage: disconnect [name]\n\r"); return; } if(is_num(arg)) { short desc = atoi(arg.c_str()); for(d = desc_list; d; d = d->next) { if(d->desc == desc) { d->close_socket(); return; } } } if(!(victim=get_ch(arg))) { ch->printf("disconnect: ERROR: " + arg + " not found.\n\r"); return; } for(d = desc_list; d; d = d->next ) { if(d == victim->desc) { d->close_socket(); return; } } ch->printf("disconnect: ERROR: Descriptor not found.\n\r"); return; } void do_echo(CH *ch, string argument = "") { if(argument.empty()) { ch->printf("Usage: echo [msg]\n\r"); return; } for(DESC *d = desc_list; d; d = d->next) if(d->connected == CON_PLAYING) d->printf(argument + ENDL); return; } void do_reboot(CH *ch, string argument = "") { reboot(); return; } void reboot() { extern bool game_down; log_string("Rebooting..."); for(DESC *d = desc_list, *d_next; d; d = d_next) { d_next = d->next; d->printf("Rebooting...\n\r"); d->ch->save(); d->close_socket(); } game_down = true; return; } void do_shutdown(CH *ch, string argument = "") { extern bool game_down; append_file(ch, "../shutdown.txt"); game_down = true; for(DESC *d = desc_list, *d_next; d; d = d_next) { d_next = d->next; d->close_socket(); } return; } void do_snoop(CH *ch, string argument = "") { DESC *d; CH *victim=NULL; if(argument.empty()) { ch->printf("Usage: snoop [name]\n\r"); return; } if(argument != "self" && !(victim = get_ch(argument))) { ch->printf("snoop: ERROR: " + argument + " not found.\n\r"); return; } if(argument == "self") victim = ch; if(!victim->desc) { ch->printf("snoop: ERROR: No descriptor to snoop.\n\r"); return; } if(victim == ch) { ch->snooping = false; for(d = desc_list; d; d = d->next) if(d->snoop_by == ch->desc) d->snoop_by = NULL; return; } if(victim->desc->snoop_by) { ch->printf("snoop: ERROR: Already snooping.\n\r"); return; } if(ch->desc) { for(d = ch->desc->snoop_by; d; d = d->snoop_by) { if(d->ch == victim) { ch->printf("snoop: ERROR: No snoop loops.\n\r"); return; } } } victim->desc->snoop_by=ch->desc; ch->snooping=true; return; } void do_freeze(CH *ch, string argument = "") { CH *victim; if(argument.empty()) { ch->printf("Usage: freeze [target]\n\r"); return; } if(!(victim = get_ch(argument))) { ch->printf("freeze: ERROR: Target not found.\n\r"); return; } if(IS_SET(victim->act, PLR_FROZEN)) { REM_BIT(victim->act, PLR_FROZEN); ch->printf("freeze: removed\n\r"); } else { SET_BIT(victim->act, PLR_FROZEN); ch->printf("freeze: set\n\r"); } victim->save(); return; } void do_log(CH *ch, string argument = "") { CH *victim; if(argument.empty()) { ch->printf("Usage: log [name]\n\r"); return; } if(!(victim = get_ch(argument))) { ch->printf("log: ERROR: " + argument + " not found.\n\r"); return; } if(IS_SET(victim->act, PLR_LOG)) { REM_BIT(victim->act, PLR_LOG); ch->printf("log: " + victim->name + ": enabled\n\r"); } else { SET_BIT(victim->act, PLR_LOG); ch->printf("log: " + victim->name + ": disabled\n\r"); } return; } void do_wizlock(CH *ch, string argument = "") { extern bool wizlock; wizlock = !wizlock; ch->printf("wizlock: " + (string)(wizlock ? "on" : "off") + ENDL); return; } void do_newlock(CH *ch, string argument = "") { extern bool newlock; newlock = !newlock; ch->printf("newlock: " + (string)(newlock ? "on" : "off") + ENDL); return; } const struct connected_type connected_table[] = { { "PLAYING" }, { "GET_NAME" }, { "GET_OLD_PASSWORD" }, { "CONFIRM_NEW_NAME" }, { "GET_NEW_PASSWORD" }, { "CONFIRM_NEW_PASSWORD" }, { "BREAK_CONNECT" }, { "FINISH" }, { "COPYOVER_RECOVER" }, { "GET_SEX" }, { "GET_PK", }, { "GET_EMAIL", }, {} }; void do_sockets(CH *ch, string argument = "") { ostrstream ost; ost << setw(2) << "ID " << setiosflags(ios::left) << setw(12) << "NAME" << " " << setiosflags(ios::left) << setw(20) << "STATUS" << " " << setiosflags(ios::left) << setw(16) << "HOST" << endl; for(DESC *d = desc_list; d; d = d->next) ost << setw(2) << d->desc << " " << setiosflags(ios::left) << setw(12) << (d->ch ? d->ch->name.c_str() : "--") << " " << setiosflags(ios::left) << setw(20) << d->conn_status().c_str() << " " << d->host << endl; ost << ends; ch->printf(ost.str()); return; } void do_force(CH *ch, string argument = "") { string arg; split(argument, arg); if(arg.empty() || argument.empty()) { ch->printf("Usage: force [name] [command]\n\r"); return; } if(arg == "all") { for(CH *vch = ch_list, *vch_next; vch; vch = vch_next) { vch_next = vch->next; vch->interpret(argument); } } else { CH *victim; if(!(victim = get_ch(arg))) { ch->printf("force: ERROR: " + arg + " not found.\n\r"); return; } victim->interpret(argument); } return; } void do_invis(CH *ch, string argument = "") { if(IS_INVIS(ch)) { ch->printf("invis> off\n\r"); REM_BIT(ch->act, PLR_INVIS); } else { ch->printf("invis> on\n\r"); SET_BIT(ch->act, PLR_INVIS); } return; } void do_omnipotent(CH *ch, string argument = "") { if(IS_OMNIPOTENT(ch)) { ch->printf("omnipotent> off\n\r"); REM_BIT(ch->act, PLR_OMNIPOTENT); } else { ch->printf("omnipotent> on\n\r"); SET_BIT(ch->act, PLR_OMNIPOTENT); } return; } #define COPYOVER_FILE "copyover.data" #define EXE_FILE "../bin/FFTacticsMUD_exe" void save_global_settings() { extern bool wizlock, newlock; ostrstream ost; ost << "UPDATE global_settings SET wizlock=" << wizlock << ", newlock=" << newlock << ends; mysql(NULL, ost.str()); return; } void do_copyover(CH *ch, string argument = "") { ofstream file(COPYOVER_FILE, ios::trunc); extern int port, control; if(!file.is_open()) { ch->printf("Copyover file not writeable, aborted.\n\r"); ostrstream ost; ost << "Could not write to copyover file: " << COPYOVER_FILE << ends; log_string(ost.str()); perror("do_copyover:fopen"); return; } if(ch) log_string("Copyover by " + ch->name); for(DESC *d = desc_list, *d_next; d; d = d_next) { d_next = d->next; d->write("updating changes..."); if(!d->ch || d->connected > CON_PLAYING) d->close_socket(); else { file << d->desc << " " << d->ch->name << " " << d->host << endl; zap(d->ch); } } file << "-1" << endl; file.close(); save_global_settings(); ostrstream ost_port, ost_control; ost_port << port << ends; ost_control << control << ends; execl(EXE_FILE, "./FFTacticsMUD_exe", ost_port.str(), "copyover", ost_control.str(), (char *)NULL); perror("do_copyover: execl"); ch->printf("Copyover FAILED!\n\r"); return; } void copyover_recover() { string name, host; int desc; log_string("Copyover recovery initiated"); ifstream file(COPYOVER_FILE); if(!file.is_open()) { perror("copyover_recover: fopen"); log_string("Copyover file not found. Exitting.\n\r"); exit(1); } for(;;) { file >> desc >> name >> host; if(desc == -1) break; if(!write_to_desc(desc, ".")) { close(desc); continue; } DESC *d = new DESC; d->desc = desc; d->host = host; d->connected = CON_COPYOVER_RECOVER; if(!d->load_ch(name)) { d->write("\n\rYour character was lost in the copyover, recreate.\n\r"); d->close_socket(); } else { d->write("done."); d->ch->printf(CLEAR); d->ch->next = ch_list; ch_list = d->ch; d->connected = CON_PLAYING; d->ch->to(d->ch->area->room[ROOM_OUTSIDE]); d->ch->socket = host; d->ch->login = str_time().substr(0, 3) + str_time().substr(11, 5); d->ch->check_battle(); } } file.close(); log_string("Copyover complete."); return; } void do_finger(CH *ch, string argument = "") { MYSQL mysql; MYSQL_RES *res; if(argument.empty()) { ch->printf("Usage: finger [name]\n\r"); return; } mysql_init(&mysql); if(!mysql_real_connect(&mysql, DB_LOC, DB_USER, DB_PASS, DB_NAME, 0, NULL, 0)) return; ostrstream ost; ost << "SELECT name, pwd, email, created, llogoff, sex, money, FROM players WHERE name='" << argument << "'" << ends; mysql_query(&mysql, ost.str()); res = mysql_store_result(&mysql); if(mysql_num_rows(res)) { mysql_free_result(res); mysql_close(&mysql); mysql_print_res(ch, ost.str()); return; } else ch->printf("finger: ERROR: " + argument + " not found.\n\r"); mysql_free_result(res); mysql_close(&mysql); return; } void do_tell(CH *ch, string argument = "") { string arg; CH *victim; split(argument, arg); if(argument.empty() || arg.empty()) { ch->printf("Usage: tell [name] [msg]\n\r"); return; } if(!(victim = get_ch(arg))) { ch->printf("tell: ERROR: " + arg + " not found.\n\r"); return; } ch->printf("{2You tell " + victim->name + " '" + argument + "{2'{0\n\r"); victim->printf("{2" + ch->name + " tells you '" + argument + "{2'{0\n\r"); return; } void do_delplayers(CH *ch, string argument = "") { MYSQL mysql; MYSQL_RES *res; if(argument.empty()) { ch->printf("Usage: deleteplayers (where llogoff =) [YYYY/MM/D]\n\r"); return; } mysql_init(&mysql); if(!mysql_real_connect(&mysql, DB_LOC, DB_USER, DB_PASS, DB_NAME, 0, NULL, 0)) return; ostrstream ost; ost << "SELECT * FROM players WHERE llogoff LIKE '" << argument << "%'" << ends; mysql_query(&mysql, ost.str()); res = mysql_store_result(&mysql); ost.freeze(false); ost.seekp(0, ios::beg); ost << (int)mysql_num_rows(res) << " players deleted.\n\r" << ends; ch->printf(ost.str()); mysql_free_result(res); ost.freeze(false); ost.seekp(0, ios::beg); ost << "DELETE FROM players WHERE llogoff LIKE '" << argument << "%'" << ends; mysql_query(&mysql, ost.str()); mysql_close(&mysql); return; } void mysql(CH *ch, const string query) { if(ch && find("select", query)) { mysql_print_res(ch, query); return; } MYSQL mysql; mysql_init(&mysql); if(!mysql_real_connect(&mysql, DB_LOC, DB_USER, DB_PASS, DB_NAME, 0, NULL, 0)) return; ostrstream ost; ost << query << ends; mysql_query(&mysql, ost.str()); mysql_close(&mysql); return; } void do_mysql(CH *ch, string argument = "") { if(argument.empty()) { ch->printf("Usage: mysql [query]\n\r"); return; } mysql(ch, argument); return; } void do_beep(CH *ch, string argument = "") { CH *victim; if(!(victim = get_ch(argument))) { ch->printf("beep: ERROR: " + argument + " not found.\n\r"); return; } ch->printf("\aYou beep " + victim->name + ".\n\r"); victim->printf("\a" + ch->name + " beeps you.\n\r"); return; } void do_chlist(CH *ch, string argument="") { CH *x; short cnt = 0; ch->printf("%2s %-15s %7s %7s %2s %2s %2s %s %3s %2s %2s\n\r", "ID", "NAME", "HP", "MP", "PA", "MA", "Sp", "M", "Ev", "Br", "Fa"); for(x = ch_list; x; x = x->next) ch->printf("%2d %-15s %3d/%3d %3d/%3d %2d %2d %2d %d %2d%% %2d %2d\n\r", cnt++, x->name.c_str(), x->HP[0], x->HP[1], x->MP[0], x->MP[1], x->PA, x->MA, x->Sp, x->Mv, x->Ev, x->Br, x->Fa); return; } void do_createobj(CH *ch, string argument="") { OBJ *obj; if(argument.empty() || !(obj = create_obj(argument))) { ch->printf("Usage: object create [name]\n\r"); return; } obj->to(ch); ch->printf("Object " + obj->name() + " created.\n\r"); return; } void do_destroy(CH *ch, string argument="") { OBJ *obj; if(argument.empty() || !(obj = ch->obj(argument, false))) { ch->printf("Usage: object destroy [name]\n\r"); do_items(ch); return; } ch->printf("Object " + obj->name() + " destroyed.\n\r"); zap(obj); return; } void do_disable(CH *ch, string argument = "") { MYSQL mysql; MYSQL_RES *res; if(argument.empty()) { ch->printf("Usage: disable [name]\n\r"); return; } mysql_init(&mysql); if(!mysql_real_connect(&mysql, DB_LOC, DB_USER, DB_PASS, DB_NAME, 0, NULL, 0)) return; ostrstream ost; ost << "SELECT name FROM players WHERE name='" << argument << "'" << ends; mysql_query(&mysql, ost.str()); res = mysql_store_result(&mysql); if(mysql_num_rows(res)) { mysql_free_result(res); mysql_close(&mysql); ost.freeze(false); ost.seekp(0, ios::beg); ost << "UPDATE players SET disabled=1 WHERE name='" << argument << "'" << ends; ::mysql(ch, ost.str()); ch->printf("Account (" + argument + ") has been disabled.\n\r"); return; } else ch->printf("disable: ERROR: Account not found.\n\r"); mysql_free_result(res); mysql_close(&mysql); return; } void do_enable(CH *ch, string argument = "") { MYSQL mysql; MYSQL_RES *res; if(argument.empty()) { ch->printf("Usage: enable [name]\n\r"); return; } mysql_init(&mysql); if(!mysql_real_connect(&mysql, DB_LOC, DB_USER, DB_PASS, DB_NAME, 0, NULL, 0)) return; ostrstream ost; ost << "SELECT name FROM players WHERE name='" << argument << "'" << ends; mysql_query(&mysql, ost.str()); res = mysql_store_result(&mysql); if(mysql_num_rows(res)) { mysql_free_result(res); mysql_close(&mysql); ost.freeze(false); ost.seekp(0, ios::beg); ost << "UPDATE players SET disabled=0 WHERE name='" << argument << "'" << ends; ::mysql(ch, ost.str()); ch->printf("Account (" + argument + ") has been enabled.\n\r"); return; } else ch->printf("enable: ERROR: Account not found.\n\r"); mysql_free_result(res); mysql_close(&mysql); return; }