ds2.1.1/bin/
ds2.1.1/extra/wolfpaw/
ds2.1.1/lib/cmds/admins/
ds2.1.1/lib/cmds/common/
ds2.1.1/lib/cmds/creators/include/
ds2.1.1/lib/cmds/creators/include/SCCS/
ds2.1.1/lib/daemon/services/
ds2.1.1/lib/doc/
ds2.1.1/lib/doc/efun/all/
ds2.1.1/lib/doc/efun/arrays/
ds2.1.1/lib/doc/efun/buffers/
ds2.1.1/lib/doc/efun/compile/
ds2.1.1/lib/doc/efun/floats/
ds2.1.1/lib/doc/efun/functions/
ds2.1.1/lib/doc/efun/general/
ds2.1.1/lib/doc/efun/mixed/
ds2.1.1/lib/doc/efun/numbers/
ds2.1.1/lib/doc/efun/parsing/
ds2.1.1/lib/doc/faq/
ds2.1.1/lib/doc/hbook/
ds2.1.1/lib/doc/help/classes/
ds2.1.1/lib/doc/lpc/basic/
ds2.1.1/lib/doc/lpc/concepts/
ds2.1.1/lib/doc/lpc/constructs/
ds2.1.1/lib/doc/lpc/etc/
ds2.1.1/lib/doc/lpc/intermediate/
ds2.1.1/lib/doc/lpc/types/
ds2.1.1/lib/doc/misc/
ds2.1.1/lib/doc/old/
ds2.1.1/lib/domains/Ylsrim/
ds2.1.1/lib/domains/Ylsrim/adm/
ds2.1.1/lib/domains/Ylsrim/armor/
ds2.1.1/lib/domains/Ylsrim/broken/
ds2.1.1/lib/domains/Ylsrim/fish/
ds2.1.1/lib/domains/Ylsrim/meal/
ds2.1.1/lib/domains/Ylsrim/npc/
ds2.1.1/lib/domains/Ylsrim/obj/
ds2.1.1/lib/domains/Ylsrim/virtual/
ds2.1.1/lib/domains/Ylsrim/weapon/
ds2.1.1/lib/domains/campus/adm/
ds2.1.1/lib/domains/campus/etc/
ds2.1.1/lib/domains/campus/meals/
ds2.1.1/lib/domains/campus/npc/
ds2.1.1/lib/domains/campus/txt/ai/charles/
ds2.1.1/lib/domains/campus/txt/ai/charles/bak2/
ds2.1.1/lib/domains/campus/txt/ai/charles/bak2/bak1/
ds2.1.1/lib/domains/campus/txt/ai/charly/
ds2.1.1/lib/domains/campus/txt/ai/charly/bak/
ds2.1.1/lib/domains/campus/txt/jenny/
ds2.1.1/lib/domains/default/creator/
ds2.1.1/lib/domains/default/doors/
ds2.1.1/lib/domains/default/etc/
ds2.1.1/lib/domains/default/weap/
ds2.1.1/lib/domains/town/doors/
ds2.1.1/lib/domains/town/txt/
ds2.1.1/lib/domains/town/txt/shame/
ds2.1.1/lib/domains/town/virtual/
ds2.1.1/lib/lib/comp/
ds2.1.1/lib/lib/lvs/
ds2.1.1/lib/lib/user/
ds2.1.1/lib/lib/virtual/
ds2.1.1/lib/log/
ds2.1.1/lib/obj/book_source/
ds2.1.1/lib/obj/include/
ds2.1.1/lib/realms/template/
ds2.1.1/lib/realms/template/area/armor/
ds2.1.1/lib/realms/template/area/npc/
ds2.1.1/lib/realms/template/area/obj/
ds2.1.1/lib/realms/template/area/room/
ds2.1.1/lib/realms/template/area/weap/
ds2.1.1/lib/realms/template/bak/
ds2.1.1/lib/realms/template/cmds/
ds2.1.1/lib/save/kills/o/
ds2.1.1/lib/secure/cfg/
ds2.1.1/lib/secure/cfg/classes/
ds2.1.1/lib/secure/cfg/races/SCCS/
ds2.1.1/lib/secure/cmds/creators/include/
ds2.1.1/lib/secure/cmds/players/
ds2.1.1/lib/secure/cmds/players/include/
ds2.1.1/lib/secure/daemon/include/
ds2.1.1/lib/secure/lib/
ds2.1.1/lib/secure/lib/include/
ds2.1.1/lib/secure/lib/net/
ds2.1.1/lib/secure/lib/net/include/
ds2.1.1/lib/secure/lib/std/
ds2.1.1/lib/secure/modules/
ds2.1.1/lib/secure/npc/
ds2.1.1/lib/secure/obj/include/
ds2.1.1/lib/secure/room/
ds2.1.1/lib/secure/save/
ds2.1.1/lib/secure/save/boards/
ds2.1.1/lib/secure/verbs/creators/
ds2.1.1/lib/shadows/
ds2.1.1/lib/spells/
ds2.1.1/lib/verbs/admins/include/
ds2.1.1/lib/verbs/common/
ds2.1.1/lib/verbs/common/include/
ds2.1.1/lib/verbs/creators/
ds2.1.1/lib/verbs/creators/include/
ds2.1.1/lib/verbs/players/include/SCCS/
ds2.1.1/lib/verbs/rooms/
ds2.1.1/lib/verbs/rooms/include/
ds2.1.1/lib/www/errors/
ds2.1.1/lib/www/images/
ds2.1.1/v22.2b14/
ds2.1.1/v22.2b14/ChangeLog.old/
ds2.1.1/v22.2b14/Win32/
ds2.1.1/v22.2b14/compat/
ds2.1.1/v22.2b14/compat/simuls/
ds2.1.1/v22.2b14/include/
ds2.1.1/v22.2b14/testsuite/
ds2.1.1/v22.2b14/testsuite/clone/
ds2.1.1/v22.2b14/testsuite/command/
ds2.1.1/v22.2b14/testsuite/data/
ds2.1.1/v22.2b14/testsuite/etc/
ds2.1.1/v22.2b14/testsuite/include/
ds2.1.1/v22.2b14/testsuite/inherit/
ds2.1.1/v22.2b14/testsuite/inherit/master/
ds2.1.1/v22.2b14/testsuite/log/
ds2.1.1/v22.2b14/testsuite/single/
ds2.1.1/v22.2b14/testsuite/single/tests/compiler/
ds2.1.1/v22.2b14/testsuite/single/tests/efuns/
ds2.1.1/v22.2b14/testsuite/single/tests/operators/
ds2.1.1/v22.2b14/testsuite/u/
ds2.1.1/v22.2b14/tmp/
ds2.1.1/win32/
// This file written completely by Tim Johnson (Tim@TimMUD)
#include <save.h>

static void process_channel(int fd, mixed *info){
    string mudname;
    trr("extra stuff is ["+info[0][8..]+"]");
    switch(info[0][8..]){ // what is after the "channel-"
    case "m": // message
    case "e": // emote
    case "t": // targetted emote
	trr("they want to do a message...");
	// (drop-through from m/e is intentional)
	// Probably should check if the target is 0@0 like it should be,
	// and give a warning if it's not... I don't carethough, I'll just
	// ignore the target and save some CPU.
	// Check if string parts are strings...
	if(info[0][8..]=="t"){
	    if(sizeof(info)!=13 || !stringp(info[9]) || !stringp(info[10]) ||
	      !stringp(info[11]) || !stringp(info[12])){
		send_error(info[2],info[3],"bad-pkt","Bad packet format.",info);
		return;
	    }
	}
	else{ // m, e
	    if(sizeof(info)!=9){
		send_error(info[2],info[3],"bad-pkt","Bad packet format.",info);
		return;
	    }
	}
	if(info[4]!=0 || info[5]!=0 || !stringp(info[6]) ||
	  !stringp(info[7]) || !stringp(info[8])){
	    send_error(info[2],info[3],"bad-pkt","Bad packet format.",info);
	    return;
	}
	if(!channels[info[6]]){ // error, channel is not registered!
	    send_error(info[2],info[3],"unk-channel",
	      "Unknown channel: "+info[6],info);
	    return;
	}
	if(member_array(info[2],listening[info[6]])==-1){
	    // if mud is not listening, then make them listen
	    // and let them know they weren't listening.
	    send_error(info[2],info[3],"warning",
	      // No applicable message codes... change
	      // "warning" to something else if you want.
	      "Your mud wasn't listening to "+info[6]+
	      ", so I'll start you listening right now.",info);
	    // Could do all the listen stuff, or could just
	    // pretend they requested it... I'm gonna pretend...
	    process_channel(fd,({ "channel-listen", 5, info[2], 0,
		router_name, 0, info[6], 1 }));
	    return;
	}
	if(channels[info[6]][0]==2){ // filtered channel
	    if(channels[info[6]][1]!=info[2]){ // not from chan owner
		// if from anybody else other than the owner,
		// check if the owner is online, then either give
		// an error, or forward to the owner...
		if(!connected_muds[channels[info[6]][1]]){
		    send_error(info[2],info[3],"unk-dst",
		      channels[info[6]][1]+" is not online to filter "+info[6],
		      info);
		    return;
		}
		if(info[4]!=0 || info[5]!=0 || !stringp(info[6]) ||
		  !stringp(info[7]) || !stringp(info[8])){
		    send_error(info[2],info[3],"bad-pkt","Bad packet format",info);
		    return;
		}
		write_data(connected_muds[channels[info[6]][1]],({
		    "chan-filter-req",
		    5,
		    router_name,
		    0,
		    channels[info[6]][1], // mud name of chan owner
		    0,
		    info[6],
		    info
		  }));
		return;
	    }
	    // IS from chan owner, just broadcast it...
	    // drop through and broadcast like the other types do...
	}
	trr("CHAN: I think it's a good message at this point...");
	// at this point, they're wanting to do a message on a
	// selective banned/allowed channel, or else are the owner
	// of a filtered channel and they have not been
	// blocked, so I will just do it...
	foreach(mudname in keys(connected_muds)){
	    if(member_array(mudname, listening[info[6]])!=-1)
		write_data(connected_muds[mudname],info);
	}
	//broadcast_data(muds_not_on_this_fd(fd), info);
	// send to all the other fd's that have a mud listening
	//			write_data(fd,info);
	// also send the message to the connection that this mud is on
	// from too... why do this? 'cause I'm allowing multiple muds to
	// log on from the same connection :)
	// I think the normal I3 server does this too, but I don't know
	// since I can't test at the moment.
	return;
    case "add":
	// check if already exists...
	// check if a valid channel name (illegal characters?)
	// check if other stuff is valid, like channel_type is 0,1,2
	// at this point, is being successfully added...
	channel_update_counter++;
	channels[info[6]]=({ info[7], info[2], ({}) });
	channel_updates[info[6]] = channel_update_counter;
	trr(info[3]+"@"+info[2]+" created the channel: "+info[6],"yellow");
	// broadcast an update saying that this channel is added or changed now
	// chanlist-reply packet to everybody (who has a channel service?)
	broadcast_chanlist(info[6]);
	//			broadcast_data(muds_not_on_this_fd(fd), ({
	//				"chanlist-reply",5,router_name,0,
	//				0, // should be mudname, I think 0 would work just as well?
	//				0, channel_update_counter,
	//				([ info[6]:({ info[2], info[7] }) ])
	//			}));
	//			write_data(fd,({
	//				"chanlist-reply",5,router_name,0,
	//				0, // should be mudname, I think 0 would work just as well?
	//				0, channel_update_counter,
	//				([ info[6]:({ info[2], info[7] }) ])
	//			}));
	save_object(SAVE_ROUTER);
	return;
    case "remove":
	if(!channels[info[6]]){ // error, channel is not registered!
	    send_error(info[2],info[3],"unk-channel",
	      "Unknown channel: "+info[6],info);
	    return;
	}
	if(channels[info[6]][1]!=info[2]){ // error, not owner!
	    send_error(info[2],info[3],"not-allowed","Channel "+
	      info[6]+" owned by: "+channels[info[6]][1],info);
	    return;
	}
	// at this point, is being removed by the owner...
	channel_update_counter++;
	map_delete(channels,info[6]);
	channel_updates[info[6]] = channel_update_counter;
	trr(info[3]+"@"+info[2]+" deleted the channel: "+info[6],"yellow");
	// broadcast an update saying that this channel is gone now
	save_object(SAVE_ROUTER);
	return;
    case "admin":
	// add/delete muds from the 2 lists...
	if(!listening[info[6]]) listening[info[6]] = ({});
	if(info[7]){ // add to list...
	    channels[info[6]][2] += info[7];
	    // if add to ban list, unlisten...
	    if(channels[info[6]][0]==0) // type 0 means selective ban
		listening[info[6]] -= info[7];
	}
	if(info[8]){ // remove from list...
	    channels[info[6]][2] += info[8];
	    if(channels[info[6]][0]!=0) // type 0 means selective ban...
		// selective allow and filtered are the same though...
		// so if not selective ban, then act like selective allow...
		// if removed from allow list, unlisten...
		listening[info[6]] -= info[8];
	}
	save_object(SAVE_ROUTER);
	return;
    case "listen": // mudname=info[2], channame=info[6], on_or_off=info[7]
	if(!channels[info[6]]){ // error, channel is not registered!
	    send_error(info[2],info[3],"unk-channel",
	      "Unknown channel: "+info[6],info);
	    return;
	}
	if(!listening) listening=([ ]);
	if(!listening[info[6]]) listening[info[6]]=({ }); // first MUD to listen
	if(info[7]){ // on_or_off is on
	    if(member_array(info[2],listening[info[6]])!=-1)
		return; // already listening, ignore them
	}
	else{ // on_or_off is on
	    if(member_array(info[2],listening[info[6]])==-1)
		return; // already NOT listening, ignore them
	}
	trr("listening change on chan:"+info[6]+", mud="+info[2]+", on_or_off="+info[7]);
	// only CHANGES should get to this point
	switch(channels[info[6]][0]){
	case 0: // selectively banned
	    if(member_array(info[2],channels[info[6]][2])!=-1){
		// in list, you're banned...
		send_error(info[2],0,"not-allowed",
		  "Banned from "+info[6],info);
		save_object(SAVE_ROUTER);
		return;
	    }
	    // not in ban list at this point
	    if(info[7])
		listening[info[6]] += ({ info[2] });
	    else
		listening[info[6]] -= ({ info[2] });
	    save_object(SAVE_ROUTER);
	    return;
	case 1: // selectively allowed
	    if(member_array(info[2],channels[info[6]][2])==-1 &&
	      info[2] != channels[info[6]][1]){
		// NOT in list, you're banned!
		send_error(info[2],0,"not-allowed",
		  "Not in allow list for "+info[6],info);
		return;
	    }
	    // in allow list at this point
	    if(info[7])
		listening[info[6]] += ({ info[2] });
	    else
		listening[info[6]] -= ({ info[2] });
	    save_object(SAVE_ROUTER);
	    return;
	case 2: // filtered... act like selectively allowed
	    if(member_array(info[2],channels[info[6]][2])==-1 &&
	      info[2] != channels[info[6]][1]){
		// NOT in list, you're banned!
		send_error(info[2],0,"not-allowed",
		  "Not in allow list for "+info[6],
		  info);
		return;
	    }
	    // in allow list at this point
	    if(info[7])
		listening[info[6]] += ({ info[2] });
	    else
		listening[info[6]] -= ({ info[2] });
	    save_object(SAVE_ROUTER);
	    return;
	} // switch
    default: // trying to do "channel-blah"
	send_error(info[2],info[3],"unk-type","I don't know what "+info[0]+
	  " means.",info);
	trr("Don't know what the ["+info[0]+"] packet means.", "yellow");
	return;
    }
    trr("can't get here?");
}