diff -ur src/act_comm.c new/act_comm.c --- src/act_comm.c Fri Feb 21 23:16:36 2003 +++ new/act_comm.c Fri Feb 21 23:27:59 2003 @@ -120,7 +120,7 @@ return TRUE; } -void channel_social(CHAR_DATA * ch, CHAR_DATA * victim, OBJ_DATA * obj, +void channel_social(CHAR_DATA * ch, CHAR_DATA * victim, flag_t bit, const char *string, const char *type, enum special_flags spec_flag) { @@ -141,7 +141,7 @@ char buf[MSL]; sprintf(buf, "%s %s", type, string); - perform_act(buf, ch, obj, victim, FALSE, vch); + perform_act(buf, ch, NULL, victim, FALSE, vch); } } } @@ -232,7 +232,7 @@ { sprintf(buf, "%s %s", type, social_table[cmd].char_no_arg); act_new(buf, ch, NULL, NULL, TO_CHAR, POS_DEAD); - channel_social(ch, NULL, NULL, bitname, + channel_social(ch, NULL, bitname, social_table[cmd].others_no_arg, type, spec_flag); } @@ -252,7 +252,7 @@ { sprintf(buf, "%s %s", type, social_table[cmd].char_auto); act_new(buf, ch, NULL, NULL, TO_CHAR, POS_DEAD); - channel_social(ch, victim, NULL, bitname, + channel_social(ch, victim, bitname, social_table[cmd].others_auto, type, spec_flag); } @@ -268,7 +268,7 @@ social_table[cmd].vict_found); act_new(buf, ch, NULL, victim, TO_VICT, POS_DEAD); } - channel_social(ch, victim, NULL, bitname, + channel_social(ch, victim, bitname, social_table[cmd].others_found, type, spec_flag); } @@ -358,6 +358,12 @@ else chprintln(ch, "OFF"); + chprint(ch, "ooc "); + if (!IS_SET(ch->comm, COMM_NOOOC)) + chprintln(ch, "ON"); + else + chprintln(ch, "OFF"); + chprint(ch, "auction "); if (!IS_SET(ch->comm, COMM_NOAUCTION)) chprintln(ch, "ON"); @@ -415,12 +421,6 @@ else chprintln(ch, "OFF"); - chprint(ch, "gocials "); - if (IS_SET(ch->comm, COMM_NOGOCIAL)) - chprintln(ch, "OFF"); - else - chprintln(ch, "ON"); - if (IS_SET(ch->comm, COMM_AFK)) chprintln(ch, "You are AFK."); @@ -453,6 +453,9 @@ if (IS_SET(ch->comm, COMM_NOEMOTE)) chprintln(ch, "You cannot show emotions."); + + if (IS_SET(ch->comm, COMM_NOGOCIAL)) + chprintln(ch, "You cannot see socials/emotes over public channels."); } diff -ur src/act_info.c new/act_info.c --- src/act_info.c Fri Feb 21 23:16:36 2003 +++ new/act_info.c Fri Feb 21 23:27:59 2003 @@ -265,7 +265,7 @@ strcat(buf, "(Golden Aura) "); if (IS_AFFECTED(victim, AFF_SANCTUARY)) strcat(buf, "(White Aura) "); - if (IS_SET(victim->act, PLR_WAR)) + if (!IS_NPC(victim) && IS_SET(victim->act, PLR_WAR)) strcat(buf, "(WAR) "); if (!IS_NPC(victim) && IS_SET(victim->act, PLR_KILLER)) strcat(buf, "(KILLER) "); @@ -1511,18 +1511,20 @@ CTAG(_SCORE1) " gold and " CTAG(_SCORE2) "%ld" CTAG(_SCORE1) " silver coins.{x", ch->exp, ch->gold, ch->silver); - chprintlnf(ch, - "" CTAG(_SCORE1) "You have " CTAG(_SCORE2) "%ld" - CTAG(_SCORE1) " gold and " CTAG(_SCORE2) "%ld" - CTAG(_SCORE1) " silver in you bank account.{x", - ch->pcdata->gold_bank, ch->pcdata->silver_bank); - - chprintlnf(ch, - "" CTAG(_SCORE1) "You have earned " CTAG(_SCORE2) "%d" - CTAG(_SCORE1) " questpoints and " CTAG(_SCORE2) "%d" - CTAG(_SCORE1) " trivia points.{x", ch->pcdata->questpoints, - ch->pcdata->trivia); + if (!IS_NPC(ch)) + { + chprintlnf(ch, + "" CTAG(_SCORE1) "You have " CTAG(_SCORE2) "%ld" + CTAG(_SCORE1) " gold and " CTAG(_SCORE2) "%ld" + CTAG(_SCORE1) " silver in you bank account.{x", + ch->pcdata->gold_bank, ch->pcdata->silver_bank); + chprintlnf(ch, + "" CTAG(_SCORE1) "You have earned " CTAG(_SCORE2) "%d" + CTAG(_SCORE1) " questpoints and " CTAG(_SCORE2) "%d" + CTAG(_SCORE1) " trivia points.{x", ch->pcdata->questpoints, + ch->pcdata->trivia); + } chprintlnf(ch, "" CTAG(_SCORE2) "You worship " CTAG(_SCORE2) "%s, %s" CTAG(_SCORE1) ".{x", @@ -2082,12 +2084,12 @@ * Format it up. */ if (wch->pcdata->who_descr[0] != '\0' && wch->pcdata->who_descr != NULL) - sprintf(block, "[%-14s] ", wch->pcdata->who_descr); + sprintf(block, "[%s] ", + stringf(14, ALIGN_CENTER, NULL, wch->pcdata->who_descr)); else sprintf(block, - "[" CTAG(_WLEVEL) "%03d " CTAG(_WRACE) "%6s " - CTAG(_WCLASS) "%s{x] ", wch->level, - race_table[wch->race].who_name, Class); + "[" CTAG(_WLEVEL) "%03d " CTAG(_WRACE) "%6s " CTAG(_WCLASS) + "%s{x] ", wch->level, race_table[wch->race].who_name, Class); sprintf(buf, "%s%s%s%s%s%s%s%s%s%s%s%s\n\r", block, format_clan(wch), @@ -2237,6 +2239,12 @@ return; } +struct s_charitem +{ + CHAR_DATA *pch; + long levelkey; +}; + /* * New 'who' command originally by Alander of Rivers of Mud. */ @@ -2252,7 +2260,8 @@ int iLevelLower; int iLevelUpper; int nNumber; - int nMatch; + int nMatch, count = 0, immcount = 0; + int ndesc, totalcount = 0, imminvis = 0; bool *rgfClass; bool *rgfRace; bool *rgfClan; @@ -2261,6 +2270,10 @@ bool fClan = FALSE; bool fRaceRestrict = FALSE; bool fImmortalOnly = FALSE; + struct s_charitem *charitems, tmp_charitem; + bool searched = FALSE; + int j1, j2; + CHAR_DATA *wch; /* * Set default arguments. @@ -2288,6 +2301,8 @@ argument = one_argument(argument, arg); if (arg[0] == '\0') break; + else + searched = TRUE; if (is_number(arg)) { @@ -2364,27 +2379,45 @@ } } + ndesc = 0; + for (d = descriptor_first; d != NULL; d = d->next) + ndesc++; + + alloc_mem(charitems, struct s_charitem, ndesc); + + if (ndesc > max_on) + max_on = ndesc; + /* * Now show matching chars. */ nMatch = 0; buf[0] = '\0'; output = new_buf(); + add_buf(output, draw_line("{r-{R-", 0)); + add_buf(output, "\n\r"); for (d = descriptor_first; d != NULL; d = d->next) { - CHAR_DATA *wch; - /* * Check for match against restrictions. * Don't use trust as that exposes trusted mortals. */ - if (d->connected != CON_PLAYING || !can_see(ch, d->character)) + if (d->connected != CON_PLAYING) continue; wch = (d->original != NULL) ? d->original : d->character; + if (get_trust(wch) >= LEVEL_IMMORTAL && wch->level >= LEVEL_IMMORTAL) + immcount++; + else + count++; + if (!can_see(ch, wch)) + { + if (IS_IMMORTAL(wch)) + imminvis++; continue; + } if (wch->level < iLevelLower || wch->level > iLevelUpper || (fImmortalOnly && wch->level < LEVEL_IMMORTAL) || @@ -2396,13 +2429,62 @@ && !rgfClan[wch->clan])) continue; + charitems[nMatch].pch = wch; + charitems[nMatch].levelkey = wch->level + 1; nMatch++; + } + + totalcount = (count + immcount); + for (j1 = 0; j1 < nMatch - 1; j1++) + { + for (j2 = j1 + 1; j2 < nMatch; j2++) + { + if (charitems[j2].levelkey > charitems[j1].levelkey) + { + tmp_charitem = charitems[j1]; + charitems[j1] = charitems[j2]; + charitems[j2] = tmp_charitem; + } + } + } + + for (j1 = 0; j1 < nMatch; j1++) + { + wch = charitems[j1].pch; add_buf(output, format_who(ch, wch)); + if (j1 == (immcount - imminvis - 1) && j1 != (nMatch - 1) + && IS_IMMORTAL(wch)) + { + add_buf(output, draw_line("{r-{R-", 0)); + add_buf(output, "\n\r"); + } + } + + free_mem(charitems); + + add_buf(output, draw_line("{r-{R-", 0)); + add_buf(output, "\n\r"); + + if (searched) + { + sprintf(buf2, "{WMatches found: {R%d{x\n\r", nMatch); + add_buf(output, buf2); + } + else if (nMatch < (totalcount - imminvis)) + { + sprintf(buf2, + "{WPlayers found: {R%d{W Most since boot: {R%d{W Invisible: {R%d{x\n\r", + nMatch, max_on, (totalcount - nMatch - imminvis)); + add_buf(output, buf2); + } + else + { + sprintf(buf2, "{WPlayers found: {R%d{W Most since boot: {R%d{x\n\r", + totalcount - imminvis, max_on); + add_buf(output, buf2); } - sprintf(buf2, "\n\rPlayers found: %d\n\r", nMatch); - add_buf(output, buf2); if (!ON_GQUEST(ch) && gquest_info.minlevel < ch->level && gquest_info.maxlevel > ch->level) add_buf(output, "There is a Global Quest running you can join.\n\r"); diff -ur src/act_wiz.c new/act_wiz.c --- src/act_wiz.c Fri Feb 21 23:16:36 2003 +++ new/act_wiz.c Fri Feb 21 23:28:00 2003 @@ -47,6 +47,7 @@ #include "../win32/winstuff.h" #endif #include "webserver.h" +#include "magic.h" /* * Local functions. @@ -4391,8 +4392,6 @@ /* This is the executable file */ #define EXE_FILE "../src/rom" -bool write_to_descriptor args((DESCRIPTOR_DATA * d, char *txt, int length)); - /* Copyover - Original idea: Fusion of MUD++ * Adapted to Diku by Erwin S. Andreasen, <erwin@andreasen.org> * http://www.andreasen.org @@ -4582,4 +4581,205 @@ } file_close(fp); +} + +struct qspell_type +{ + SPELL_FUN *spellf; +}; + +int sn_spellfun_lookup(SPELL_FUN * fun) +{ + int sn; + + for (sn = 0; sn < maxSkill; sn++) + { + if (skill_table[sn].spell_fun == fun) + return sn; + } + return -1; +} + +const struct qspell_type qspell_table[] = { + {spell_bless}, + {spell_giant_strength}, + {spell_haste}, + {spell_frenzy}, + {spell_shield}, + {spell_armor}, + {spell_sanctuary}, + {spell_detect_hidden}, + {spell_detect_invis}, + {spell_stone_skin}, + {NULL}, +}; + +CH_CMD(do_spellup) +{ + CHAR_DATA *vch; + char arg[MIL]; + DESCRIPTOR_DATA *tempdesc; + int i, sn; + + argument = one_argument(argument, arg); + + if (IS_NULLSTR(arg)) + { + chprintln(ch, "Syntax: spellup [all, room, <char>]"); + return; + } + + if (!str_cmp(arg, "all")) + { + tempdesc = ch->desc; + ch->desc = NULL; + for (vch = player_first; vch != NULL; vch = vch->next_player) + { + if (vch == ch || !can_see(ch, vch)) + continue; + + do_function(ch, &do_spellup, vch->name); + } + ch->desc = tempdesc; + chprintln(ch, "OK."); + } + else if (!str_cmp(arg, "room")) + { + //Lets not spam the caster out + tempdesc = ch->desc; + ch->desc = NULL; + for (vch = ch->in_room->first_person; vch; vch = vch->next_in_room) + { + if (vch == ch || IS_NPC(vch) || !can_see(ch, vch)) + continue; + + do_function(ch, &do_spellup, vch->name); + } + ch->desc = tempdesc; + chprintln(ch, "OK."); + } + else if ((vch = get_char_world(ch, arg)) != NULL) + { + //Lets not spam the caster out + tempdesc = ch->desc; + ch->desc = NULL; + for (i = 0, sn = 0; qspell_table[i].spellf != NULL; i++) + { + sn = sn_spellfun_lookup(qspell_table[i].spellf); + if (sn == -1) + continue; + if (is_affected(vch, sn)) + continue; + qspell_table[i].spellf(sn, get_trust(ch), ch, vch, TARGET_CHAR); + } + ch->desc = tempdesc; + chprintln(ch, "OK."); + } + else + chprintln(ch, "Syntax: spellup [all, room, <char>]"); + + return; +} + +/** Function: do_pload + * Descr : Loads a player object into the mud, bringing them (and their + * pet) to you for easy modification. Player must not be connected. + * Note: be sure to send them back when your done with them. + * Returns : (void) + * Syntax : pload (who) + * Written : v1.0 12/97 + * Author : Gary McNickle <gary@dharvest.com> + */ +CH_CMD(do_pload) +{ + DESCRIPTOR_DATA d; + bool isChar = FALSE; + char name[MAX_INPUT_LENGTH]; + + if (argument[0] == '\0') + { + chprintln(ch, "Load who?"); + return; + } + + argument = one_argument(argument, name); + + /* Dont want to load a second copy of a player who's allready online! */ + if (get_char_world(ch, name) != NULL) + { + chprintln(ch, "That person is already connected!"); + return; + } + + isChar = load_char_obj(&d, capitalize(name)); /* char pfile exists? */ + + if (!isChar) + { + chprintln(ch, "Load Who? Are you sure? I cant seem to find them."); + return; + } + + d.character->desc = NULL; + LINK(d.character, char_first, char_last, next, prev); + LINK(d.character, player_first, player_last, next_player, prev_player); + d.connected = CON_PLAYING; + reset_char(d.character); + + /* bring player to imm */ + if (d.character->in_room != NULL) + { + char_to_room(d.character, ch->in_room); /* put in room imm is in */ + } + + act("$n has pulled $N from the pattern!", ch, NULL, d.character, TO_ROOM); + + if (d.character->pet != NULL) + { + char_to_room(d.character->pet, d.character->in_room); + act("$n has entered the game.", d.character->pet, NULL, NULL, TO_ROOM); + } + +} + +/** Function: do_punload + * Descr : Returns a player, previously 'ploaded' back to the void from + * whence they came. This does not work if the player is actually + * connected. + * Returns : (void) + * Syntax : punload (who) + * Written : v1.0 12/97 + * Author : Gary McNickle <gary@dharvest.com> + */ +CH_CMD(do_punload) +{ + CHAR_DATA *victim; + char who[MAX_INPUT_LENGTH]; + + argument = one_argument(argument, who); + + if ((victim = get_char_world(ch, who)) == NULL) + { + chprintln(ch, "They aren't here."); + return; + } + + /** Person is legitametly logged on... was not ploaded. + */ + if (victim->desc != NULL) + { + chprintln(ch, "I dont think that would be a good idea..."); + return; + } + + if (victim->was_in_room != NULL) /* return player and pet to orig room */ + { + char_to_room(victim, victim->was_in_room); + if (victim->pet != NULL) + char_to_room(victim->pet, victim->was_in_room); + } + + save_char_obj(victim); + do_quit(victim, ""); + + act("$n has released $N back to the Pattern.", ch, NULL, victim, TO_ROOM); } diff -ur src/board.c new/board.c --- src/board.c Fri Feb 21 23:16:36 2003 +++ new/board.c Fri Feb 21 23:28:00 2003 @@ -172,8 +172,8 @@ last_note_stamp = current_time; } - if (board->note_first) /* are there any notes in there now? */ - LINK(note, board->note_first, board->note_last, next, prev); + LINK(note, board->note_first, board->note_last, next, prev); + /* append note to note file */ sprintf(filename, "%s%s", NOTE_DIR, board->short_name); @@ -535,10 +535,11 @@ chprintln(ch, "{GYour note so far:{x"); chprint(ch, ch->pcdata->in_progress->text); - chprintln + chprintlnf (ch, - "\n\rEnter text. Type {W.q{x or {W@{x on an empty line to end note, or {W.h{x for help.\n\r" - "======================================================================"); + "\n\rEnter text. Type {W%cq{x or {W@{x on an empty line to end note, or {W%ch{x for help.\n\r" + "======================================================================", + STR_EDIT_KEY(ch), STR_EDIT_KEY(ch)); ch->desc->connected = CON_NOTE_TEXT; @@ -1010,10 +1011,11 @@ sprintf(buf, "This note will expire %s\r", ctime(&ch->pcdata->in_progress->expire)); write_to_buffer(d, buf, 0); - write_to_buffer(d, - "\n\rEnter text. Type {W.q{x or {W@{x on an empty line to end note, or {W.h{x for help.\n\r" - "======================================================================\n\r", - 0); + sprintf(buf, + "\n\rEnter text. Type {W%cq{x or {W@{x on an empty line to end note, or {W%ch{x for help.\n\r" + "======================================================================\n\r", + STR_EDIT_KEY(ch), STR_EDIT_KEY(ch)); + write_to_buffer(d, buf, 0); d->connected = CON_NOTE_TEXT; } } @@ -1062,10 +1064,11 @@ /* note that ctime returns XXX\n so we only need to add an \r */ - write_to_buffer(d, - "\n\rEnter text. Type {W.q{x or {W@{x on an empty line to end note, or {W.h{x for help.\n\r" - "======================================================================", - 0); + sprintf(buf, + "\n\rEnter text. Type {W%cq{x or {W@{x on an empty line to end note, or {W%ch{x for help.\n\r" + "======================================================================", + STR_EDIT_KEY(ch), STR_EDIT_KEY(ch)); + write_to_buffer(d, buf, 0); d->connected = CON_NOTE_TEXT; } diff -ur src/comm.c new/comm.c --- src/comm.c Fri Feb 21 23:16:36 2003 +++ new/comm.c Fri Feb 21 23:28:00 2003 @@ -100,7 +100,6 @@ int init_socket args((int prt)); void init_descriptor args((int ctrl)); bool read_from_descriptor args((DESCRIPTOR_DATA * d)); -bool write_to_descriptor args((DESCRIPTOR_DATA * d, char *txt, int length)); void halt_mud args((int sig)); /* diff -ur src/db.c new/db.c --- src/db.c Fri Feb 21 23:16:37 2003 +++ new/db.c Fri Feb 21 23:28:00 2003 @@ -343,6 +343,8 @@ load_bank_data(); log_string("Loading deities..."); load_deities(); + log_string("Loading web passwords..."); + load_webpasses(); } return; diff -ur src/dofun.h new/dofun.h --- src/dofun.h Fri Feb 21 23:16:37 2003 +++ new/dofun.h Fri Feb 21 23:28:00 2003 @@ -315,5 +315,11 @@ COMMAND_FUN (do_dedit) COMMAND_FUN (do_nogocial) COMMAND_FUN (do_ooc) +COMMAND_FUN (do_webpass) +COMMAND_FUN (do_spellup) +COMMAND_FUN (do_strkey) +COMMAND_FUN (do_run) +COMMAND_FUN (do_pload) +COMMAND_FUN (do_punload) // *INDENT-ON* diff -ur src/globals.h new/globals.h --- src/globals.h Fri Feb 21 23:16:37 2003 +++ new/globals.h Fri Feb 21 23:28:00 2003 @@ -121,4 +121,7 @@ GLOBAL_DEF(int maxDeity, 1); GLOBAL_DEF(struct deity_type *deity_table, NULL); +GLOBAL_DEF(WPWD_DATA * wpwd_first, NULL); +GLOBAL_DEF(WPWD_DATA * wpwd_last, NULL); + #endif diff -ur src/mccp.c new/mccp.c --- src/mccp.c Fri Feb 21 23:16:37 2003 +++ new/mccp.c Fri Feb 21 23:28:00 2003 @@ -59,7 +59,6 @@ char compress_start[] = { IAC, SB, TELOPT_COMPRESS, WILL, SE, '\0' }; bool processCompressed(DESCRIPTOR_DATA * desc); -bool write_to_descriptor args((DESCRIPTOR_DATA * d, char *txt, int length)); /* * Memory management - zlib uses these hooks to allocate and free memory diff -ur src/mem.c new/mem.c --- src/mem.c Fri Feb 21 23:16:37 2003 +++ new/mem.c Fri Feb 21 23:28:00 2003 @@ -99,10 +99,10 @@ pArea->max_vnum = 0; pArea->age = 0; pArea->nplayer = 0; + pArea->vnum = top_area; pArea->empty = TRUE; /* ROM patch */ sprintf(buf, "area%d.are", pArea->vnum); pArea->file_name = str_dup(buf); - pArea->vnum = top_area - 1; return pArea; } diff -ur src/merc.h new/merc.h --- src/merc.h Fri Feb 21 23:16:37 2003 +++ new/merc.h Fri Feb 21 23:28:00 2003 @@ -146,6 +146,7 @@ typedef struct auction_data AUCTION_DATA; typedef struct clan_rank RANK_DATA; typedef struct deity_type DEITY_DATA; +typedef struct wpwd_data WPWD_DATA; /* * Function types. @@ -1456,6 +1457,15 @@ int next; }; +struct wpwd_data +{ + WPWD_DATA *next; + WPWD_DATA *prev; + bool valid; + const char *name; + const char *passw; +}; + #define INFO_ALL (BIT_A) #define INFO_QUIET (BIT_B) #define INFO_LOGIN (BIT_C) @@ -1716,6 +1726,8 @@ long gold_bank; long silver_bank; int shares; + const char *webpass; + char str_ed_key; }; /* Data for generating characters -- only used during generation */ @@ -2271,6 +2283,8 @@ #define ON_GQUEST(ch) (!IS_NPC(ch) && IS_SET((ch)->act, PLR_GQUEST) && gquest_info.running != GQUEST_OFF) +#define STR_EDIT_KEY(ch) (IS_NPC(ch) ? '.' : ch->pcdata->str_ed_key) + /* * Object macros. */ @@ -2383,6 +2397,7 @@ #define PIT_FILE DATA_DIR "pit.dat" #define BANK_FILE DATA_DIR "bank.dat" #define DEITY_FILE DATA_DIR "deity.dat" +#define WPWD_FILE DATA_DIR "webpass.dat" #include "proto.h" diff -ur src/multiclass.c new/multiclass.c --- src/multiclass.c Fri Feb 21 23:16:37 2003 +++ new/multiclass.c Fri Feb 21 23:28:00 2003 @@ -424,8 +424,12 @@ return 2; for (iClass = 0; ch->Class[iClass] != -1; iClass++) - temprate = UMIN(temprate, skill_table[sn].rating[ch->Class[iClass]]); + { + if (skill_table[sn].rating[ch->Class[iClass]] < 1) + continue; + temprate = UMIN(temprate, skill_table[sn].rating[ch->Class[iClass]]); + } return temprate == 999 ? 0 : temprate; } @@ -446,8 +450,12 @@ return 2; for (iClass = 0; ch->Class[iClass] != -1; iClass++) - temprate = UMIN(temprate, group_table[gn].rating[ch->Class[iClass]]); + { + if (group_table[gn].rating[ch->Class[iClass]] < 1) + continue; + temprate = UMIN(temprate, group_table[gn].rating[ch->Class[iClass]]); + } return temprate == 999 ? 0 : temprate; } diff -ur src/olc.c new/olc.c --- src/olc.c Fri Feb 21 23:16:37 2003 +++ new/olc.c Fri Feb 21 23:28:00 2003 @@ -211,7 +211,7 @@ sprintf(buf, "object"); break; case ED_MOBILE: - sprintf(buf, "mobile "); + sprintf(buf, "mobile"); break; case ED_MPCODE: sprintf(buf, "mobile program"); @@ -247,7 +247,7 @@ sprintf(buf, "class"); break; case ED_DEITY: - return "deity"; + sprintf(buf, "deity"); break; default: break; diff -ur src/proto.h new/proto.h --- src/proto.h Fri Feb 21 23:16:37 2003 +++ new/proto.h Fri Feb 21 23:28:00 2003 @@ -543,6 +543,12 @@ void load_deities args((void)); void save_deities args((void)); +void update_webpasses args((CHAR_DATA * ch, bool pDelete)); +void save_webpasses args((void)); +void load_webpasses args((void)); + +bool write_to_descriptor args((DESCRIPTOR_DATA * d, char *txt, int length)); + #undef CD #undef MID #undef OD diff -ur src/recycle.c new/recycle.c --- src/recycle.c Fri Feb 21 23:16:37 2003 +++ new/recycle.c Fri Feb 21 23:28:00 2003 @@ -324,6 +324,7 @@ pcdata->buffer = new_buf(); alloc_mem(pcdata->learned, int, maxSkill); alloc_mem(pcdata->group_known, bool, maxGroup); + pcdata->str_ed_key = '/'; VALIDATE(pcdata); return pcdata; } @@ -340,6 +341,7 @@ free_string(pcdata->bamfout); free_string(pcdata->title); free_string(pcdata->who_descr); + free_string(pcdata->webpass); free_buf(pcdata->buffer); free_mem(pcdata->learned); free_mem(pcdata->group_known); @@ -661,4 +663,32 @@ INVALIDATE(auction); PUT_FREE(auction, next, auction_free); +} + +WPWD_DATA *WPWD_free; + +WPWD_DATA *new_pwd(void) +{ + static WPWD_DATA WPWD_zero; + WPWD_DATA *pwd; + + GET_FREE(pwd, WPWD_DATA, next, WPWD_free); + + *pwd = WPWD_zero; + pwd->name = &str_empty[0]; + pwd->passw = &str_empty[0]; + VALIDATE(pwd); + return pwd; +} + +void free_pwd(WPWD_DATA * pwd) +{ + if (!IS_VALID(pwd)) + return; + + free_string(pwd->name); + free_string(pwd->passw); + INVALIDATE(pwd); + + PUT_FREE(pwd, next, WPWD_free); } diff -ur src/recycle.h new/recycle.h --- src/recycle.h Fri Feb 21 23:16:37 2003 +++ new/recycle.h Fri Feb 21 23:28:00 2003 @@ -141,4 +141,7 @@ AUCTION_DATA *new_auction args((void)); void free_auction args((AUCTION_DATA * auction)); +void free_pwd args((WPWD_DATA * pwd)); +WPWD_DATA *new_pwd args((void)); + #endif diff -ur src/save.c new/save.c --- src/save.c Fri Feb 21 23:16:37 2003 +++ new/save.c Fri Feb 21 23:28:00 2003 @@ -254,6 +254,9 @@ if (ch->pcdata->trivia != 0) fprintf(fp, "Trivia %d\n", ch->pcdata->trivia); + if (ch->pcdata->str_ed_key != '.' && ch->pcdata->str_ed_key != ' ') + fprintf(fp, "StrEdKey\t%c\n", ch->pcdata->str_ed_key); + if (ch->pcdata->awins != 0) fprintf(fp, "AWins %d\n", ch->pcdata->awins); @@ -1223,6 +1226,7 @@ KEY("Sec", ch->pcdata->security, fread_number(fp)); /* OLC */ KEY("Silv", ch->silver, fread_number(fp)); KEY("Shares", ch->pcdata->shares, fread_number(fp)); + KEY("StrEdKey", ch->pcdata->str_ed_key, fread_letter(fp)); if (!str_cmp(word, "StayRace")) { ch->pcdata->stay_race = TRUE; diff -ur src/string.c new/string.c --- src/string.c Fri Feb 21 23:16:37 2003 +++ new/string.c Fri Feb 21 23:28:00 2003 @@ -64,8 +64,9 @@ void string_edit(CHAR_DATA * ch, const char **pString) { chprintln(ch, "-========- Entering EDIT Mode -=========-"); - chprintln(ch, " Type .h on a new line for help"); - chprintln(ch, " Terminate with a .q or @ on a blank line."); + chprintlnf(ch, " Type %ch on a new line for help", STR_EDIT_KEY(ch)); + chprintlnf(ch, " Terminate with a %cq or @ on a blank line.", + STR_EDIT_KEY(ch)); chprintln(ch, "-=======================================-"); if (*pString == NULL) @@ -90,8 +91,9 @@ void string_append(CHAR_DATA * ch, const char **pString) { chprintln(ch, "-=======- Entering APPEND Mode -========-"); - chprintln(ch, " Type .h on a new line for help"); - chprintln(ch, " Terminate with a .q or @ on a blank line."); + chprintlnf(ch, " Type %ch on a new line for help", STR_EDIT_KEY(ch)); + chprintlnf(ch, " Terminate with a %cq or @ on a blank line.", + STR_EDIT_KEY(ch)); chprintln(ch, "-=======================================-"); if (*pString == NULL) @@ -205,22 +207,27 @@ case PARSE_HELP: chprintln(ch, "-------------------------------------------------------"); - chprintln(ch, - "Edit help (commands on blank line):\n\r" - ".h - get help (this info)\n\r" - ".s - show string so far\n\r" - ".S - show string so far without line numbers\n\r" - ".f - formats text\n\r" - ".c - clear string so far\n\r" - ".d# - delete line number <num>\n\r" - ".d - delete last line\n\r" - ".i# <str> - insert <str> on line <num>\n\r" - ".e# <str> - replace line <num> with <str>\n\r" - ".r 'a' 'b' - replace first occurance of text\n\r" - ".R 'a' 'b' - replace all occurances of text\n\r" - " usage: .r 'pattern' 'replacement'\n\r" - ".| <command> - execute a mud command\n\r" - ".q - end string"); + chprintlnf(ch, + "Edit help (commands on blank line):\n\r" + "%ch - get help (this info)\n\r" + "%cs - show string so far\n\r" + "%cS - show string so far without line numbers\n\r" + "%cf - formats text\n\r" + "%cc - clear string so far\n\r" + "%cd# - delete line number <num>\n\r" + "%cd - delete last line\n\r" + "%ci# <str> - insert <str> on line <num>\n\r" + "%ce# <str> - replace line <num> with <str>\n\r" + "%cr 'a' 'b' - replace first occurance of text\n\r" + "%cR 'a' 'b' - replace all occurances of text\n\r" + " usage: %cr 'pattern' 'replacement'\n\r" + "%c| <command> - execute a mud command\n\r" + "%cq - end string", STR_EDIT_KEY(ch), + STR_EDIT_KEY(ch), STR_EDIT_KEY(ch), STR_EDIT_KEY(ch), + STR_EDIT_KEY(ch), STR_EDIT_KEY(ch), STR_EDIT_KEY(ch), + STR_EDIT_KEY(ch), STR_EDIT_KEY(ch), STR_EDIT_KEY(ch), + STR_EDIT_KEY(ch), STR_EDIT_KEY(ch), STR_EDIT_KEY(ch), + STR_EDIT_KEY(ch)); chprintln(ch, "------------------------------------------------------"); break; case PARSE_FORMAT: @@ -293,7 +300,7 @@ int i = 2, j = 0; char actions[MAX_INPUT_LENGTH]; - if ((*str == '.')) + if ((*str == STR_EDIT_KEY(ch))) { while (str[i] != '\0') { @@ -1251,4 +1258,28 @@ strcat(result, lbuf); return result; +} + +CH_CMD(do_strkey) +{ + if (IS_NPC(ch)) + return; + + if (IS_NULLSTR(argument) || strlen(argument) > 1) + { + chprintln(ch, "Syntax: strkey <key>"); + chprintln(ch, "Where <key> can be any 1 letter you want "); + chprintln(ch, "to use for string editor commands."); + return; + } + + if (!isascii(argument[0]) || argument[0] == ' ' || argument[0] == '\\') + { + chprintln(ch, "Invalid string editor key."); + return; + } + + ch->pcdata->str_ed_key = argument[0]; + chprintlnf(ch, "The string editor now uses %c for commands.", + STR_EDIT_KEY(ch)); } diff -ur src/tablesave.c new/tablesave.c --- src/tablesave.c Fri Feb 21 23:16:37 2003 +++ new/tablesave.c Fri Feb 21 23:28:00 2003 @@ -79,6 +79,7 @@ BAN_DATA ban; GQUEST gq; DEITY_DATA deity; +WPWD_DATA pwd; const char *do_fun_name(DO_FUN *); DO_FUN *do_fun_lookup(const char *); @@ -350,6 +351,12 @@ {NULL, 0, NULL, NULL, NULL} }; +const struct savetable_type pwdsavetable[] = { + {"name", FIELD_STRING, (void *) &pwd.name, NULL, NULL}, + {"pwd", FIELD_STRING, (void *) &pwd.passw, NULL, NULL}, + {NULL, 0, NULL, NULL, NULL} +}; + void load_struct(FILE * fp, void *typebase, const struct savetable_type *table, void *puntero) { @@ -723,8 +730,8 @@ fprintf(fp, "%s\t\t", temp->field); for (i = 0; i < - (temp->argument ? (int) temp-> - argument : *(int *) temp->argument2); i++) + (temp->argument ? (int) temp->argument : *(int *) temp-> + argument2); i++) fprintf(fp, "%d ", pbool[i] == TRUE ? 1 : 0); fprintf(fp, "@\n"); break; @@ -1639,5 +1646,74 @@ deity_table[maxDeity].name = NULL; + file_close(fp); +} + +void save_webpasses(void) +{ + WPWD_DATA *ppwd; + FILE *fp; +#if !defined(WIN32) + char *TEMPFILE = WPWD_FILE ".tmp"; + + if ((fp = file_open(TEMPFILE, "w")) == NULL) +#else + if ((fp = file_open(WPWD_FILE, "w")) == NULL) +#endif + { + perror(WPWD_FILE); + file_close(fp); + return; + } + + for (ppwd = wpwd_first; ppwd != NULL; ppwd = ppwd->next) + { + fprintf(fp, "#WPWD\n"); + save_struct(fp, &pwd, pwdsavetable, ppwd); + fprintf(fp, "#END\n\n"); + } + + fprintf(fp, "#!\n"); + + file_close(fp); + +#if !defined(WIN32) + rename(TEMPFILE, WPWD_FILE); +#endif +} + +void load_webpasses(void) +{ + FILE *fp; + WPWD_DATA *ppwd; + const char *word; + + fp = file_open(WPWD_FILE, "r"); + + if (!fp) + { + bug("Unable to open " WPWD_FILE " to load pwdlist.", 0); + save_webpasses(); + file_close(fp); + return; + } + + for (;;) + { + word = fread_word(fp); + + if (!str_cmp(word, "#!")) + break; + + if (str_cmp(word, "#WPWD")) + { + bugf("word doesn't exist (%s)", word); + exit(1); + } + + ppwd = new_pwd(); + load_struct(fp, &pwd, pwdsavetable, ppwd); + LINK(ppwd, wpwd_first, wpwd_last, next, prev); + } file_close(fp); } diff -ur src/telnet.c new/telnet.c --- src/telnet.c Fri Feb 21 23:16:37 2003 +++ new/telnet.c Fri Feb 21 23:28:00 2003 @@ -34,8 +34,6 @@ #include "merc.h" #include "telnet.h" -bool write_to_descriptor args((DESCRIPTOR_DATA * d, char *txt, int length)); - char echo_off_str[] = { IAC, WILL, TELOPT_ECHO, '\0' }; char echo_on_str[] = { IAC, WONT, TELOPT_ECHO, '\0' }; char echo_dont[] = { IAC, DONT, TELOPT_ECHO, '\0' }; diff -ur src/webserver.c new/webserver.c --- src/webserver.c Fri Feb 21 23:16:37 2003 +++ new/webserver.c Fri Feb 21 23:31:47 2003 @@ -84,6 +84,147 @@ #include "recycle.h" #include "magic.h" #include "gsn.h" +#include "telnet.h" + +void update_webpasses(CHAR_DATA * ch, bool pDelete) +{ + WPWD_DATA *c_next; + WPWD_DATA *curr; + + if (IS_NPC(ch)) + return; + + for (curr = wpwd_first; curr != NULL; curr = c_next) + { + c_next = curr->next; + + if (!str_cmp(ch->name, curr->name)) + { + UNLINK(curr, wpwd_first, wpwd_last, next, prev); + free_pwd(curr); + save_webpasses(); + } + } + if (pDelete || IS_NULLSTR(ch->pcdata->webpass)) + return; + + curr = new_pwd(); + replace_string(curr->name, ch->name); + replace_string(curr->passw, ch->pcdata->webpass); + LINK(curr, wpwd_first, wpwd_last, next, prev); + save_webpasses(); + return; +} + +CH_CMD(do_webpass) +{ + char arg1[MIL]; + char arg2[MIL]; + char *pArg; + char *pwdnew; + char *p; + char cEnd; + + if (!ch || IS_NPC(ch)) + return; + + if (!IS_IMMORTAL(ch)) + { + chprintln(ch, "This feature is only available to immortals, sorry."); + return; + } + + pArg = arg1; + while (isspace(*argument)) + argument++; + + cEnd = ' '; + if (*argument == '\'' || *argument == '\"') + cEnd = *argument++; + + while (*argument != '\0') + { + if (*argument == cEnd) + { + argument++; + break; + } + *pArg++ = *argument++; + } + *pArg = '\0'; + + pArg = arg2; + while (isspace(*argument)) + argument++; + + cEnd = ' '; + if (*argument == '\'' || *argument == '\"') + cEnd = *argument++; + + while (*argument != '\0') + { + if (*argument == cEnd) + { + argument++; + break; + } + *pArg++ = *argument++; + } + *pArg = '\0'; + + if (IS_NULLSTR(arg1) || IS_NULLSTR(arg2)) + { + chprintln(ch, "Syntax: webpass <old> <new>."); + return; + } + + write_to_descriptor(ch->desc, echo_off_str, 0); + + if (str_cmp(crypt(arg1, ch->pcdata->webpass), ch->pcdata->webpass)) + { + WAIT_STATE(ch, 40); + chprintln(ch, "Wrong password. Wait 10 seconds."); + write_to_descriptor(ch->desc, echo_on_str, 0); + return; + } + + if (strlen(arg2) < 5) + { + chprintln(ch, "New password must be at least five characters long."); + write_to_descriptor(ch->desc, echo_on_str, 0); + return; + } + + pwdnew = crypt(arg2, ch->name); + for (p = pwdnew; *p != '\0'; p++) + { + if (*p == '~') + { + chprintln(ch, "New password not acceptable, try again."); + write_to_descriptor(ch->desc, echo_on_str, 0); + return; + } + } + + replace_string(ch->pcdata->webpass, pwdnew); + save_char_obj(ch); + update_webpasses(ch, FALSE); + chprintln(ch, "Ok."); + write_to_descriptor(ch->desc, echo_on_str, 0); + return; +} + +bool check_web_pass(const char *username, const char *password) +{ + WPWD_DATA *current; + + for (current = wpwd_first; current; current = current->next) + if (!strcasecmp(current->name, username)) + if (!strcasecmp(current->passw, crypt(password, username))) + return TRUE; + + return FALSE; +} /* Thanks to John Ludeman for this code... * Define translation matrix for Base64 decode. @@ -2042,8 +2183,7 @@ } } - if (!strcasecmp(username, SECURE_USERNAME) - && !strcasecmp(password, SECURE_PASSWORD)) + if (check_web_pass(username, password)) { char *buf; diff -ur src/webserver.h new/webserver.h --- src/webserver.h Fri Feb 21 23:16:37 2003 +++ new/webserver.h Fri Feb 21 23:28:00 2003 @@ -44,8 +44,6 @@ */ #define SECURE_URL "staffarea" /* The secure URL. http://mud.is.here:<port>/SECURE_URL */ -#define SECURE_USERNAME "1stmud" /* secure url username */ -#define SECURE_PASSWORD "2003" /* secure url password */ #define AUTH_DOMAIN "Staff Area - Username and Password are CASE SENSITIVE." /* Secure Area Description (tell me where this is used) */ #define MAXDATA 1024