/* Bastards.c takes care of suspension, banished sites and now also banished
* playernames.
* Baldrick, oct '95
*/
/* Tweaked Sept 1995 -- Hamlet
Trying to fix NO_NEW and add NO_GUEST
*/
#include "access.h"
#include "mail.h"
#define POSTAL_D "/obj/handlers/postal_d"
static string *names;
static string def;
mapping access; /* Site access control */
string *preferred;
mapping suspended, banished;
int query_access(string *address, string ident);
mapping query_access_mapping() { return access; }
string get_nomulti_string(string site, string userid);
void create() {
names = ({ "root", "/global/player",
"failsafe", "/global/failsafe", });
def = "/global/player";
seteuid("Root");
access = ([ ]);
suspended = ([ ]);
banished = ([ ]);
restore_object(file_name(this_object()),1);
move_object("/room/void"); /* Make it unclonable... */
preferred = ({ });
} /* create() */
int check_access(object ob, int existing)
{
string *tmp = explode(query_ip_name(ob),".");
switch (query_access(explode(query_ip_number(ob), "."),
ob->query_ident())) {
case NO_NEW :
if (!existing) {
write("Site banned for new players.\n");
return NO_NEW;
}
else
return ACCESS;
case NO_ACCESS :
write("Site banned for all players.\n");
return NO_ACCESS;
case NO_GUEST :
if(ob->query_name() == "guest") {
write("Site banned for guests.\n");
return NO_GUEST;
}
else
return ACCESS;
case NO_IMMORTS :
if(ob->query_creator()) {
write("Site banned for immortals.\n");
return NO_IMMORTS;
}
else
return ACCESS;
case NO_PLAYERS :
if(!ob->query_creator()) {
write("Site banned for players.\n");
return NO_PLAYERS;
}
else
return ACCESS;
case ACCESS :
return ACCESS;
case NO_MULTIPLAY:
ob->add_static_property("NOMULTI",
get_nomulti_string(query_ip_number(ob),
ob->query_ident()));
return DEFAULT;
default :
return DEFAULT;
}
} /* check_access() */
/* The flag skips the initial check for query_creator(). This is
needed for the first call to the fcn, when restore_object() hasn't
been called yet. Only purpose of this first call is to determine
whether the person is banished, so security isn't really an issue.
Check for query_creator() needs skipped so I can install immortal
slots, which have to decide whether let person in according to whether
this fcn returns "global/player" or not. flag should not be passed in
any subsequent calls to the function. -- Hamlet
*/
varargs string query_player_ob(string name, int flag)
{
int i;
int existing;
int reason;
if (POSTAL_D->query_mailing_list(name))
{
write("Name is a mailing list.\n");
return 0;
}
if(member_array(name,get_dir("/d/")) != -1) {
write("Name is a domain.\n");
return 0;
}
i = member_array(name, names);
if (i != -1)
{
return names[i+1];
}
if (banished[name])
{
write("This name is banished, pick a different one.\n");
return 0;
}
if (suspended[name] > time())
{
write("You have been suspended until "+ctime(suspended[name])+".\n");
return 0;
}
suspended = m_delete(suspended, name);
/*
if ("secure/master"->query_lord(name))
{
return "global/lord";
}
*/
if(file_size("/players/" + name[0..0] + "/" + name + ".o") < 1)
existing = 0;
else
existing = 1;
reason = check_access(previous_object(), existing);
if(reason != ACCESS)
return "";
/* I hope this is the right place to put this code in.
* Baldrick, sept '93
* Added more files, oct '95.
* First, a check if the player is a creator..
* to be sure it isn't a new player using a non-existing .o
*/
if(previous_object()->query_creator() ||flag)
{
if ("/secure/gods"->query_boo(name))
return "global/god";
if ("/secure/lords"->query_boo(name))
return "global/lord";
if ("/secure/mudlibber"->query_boo(name))
return "global/lord";
if ("/secure/thanes"->query_of(name))
return "global/thane";
if ("/secure/patrons"->query_patronage(name))
return "global/patron";
if(previous_object()->query_creator()) /* Will actually need this now. */
return "global/creator";
}
return def;
} /* query_player_ob() */
int query_prevent_shadow() { return 1; }
/*
* Ok, acces checking stuff...
*/
mapping query_all_access() { return access + ([ ]); }
/*
* Look up the address and find out if it is nice and floppy
* Adress is of the format ({ "130", "95", "100", "2" })
*/
int query_access(string *address, string ident) {
mixed rest;
if (!pointerp(address) || sizeof(address) != 4)
return ERROR;
if (!(rest = access[address[0]]))
return DEFAULT;
address = address[1..4];
while (sizeof(address)) {
if (!rest[address[0]])
if (!rest["*"])
return DEFAULT;
else
rest = rest["*"];
else
rest = rest[address[0]];
address = address[1..4];
}
if (rest[ident])
return rest[ident];
if (rest["*"])
return rest["*"];
return DEFAULT;
} /* query_access() */
static mixed add_access(mixed bing, string *address, string ident,
int level) {
if (!mappingp(bing))
bing = ([ ]);
if (!sizeof(address)) {
if (!level)
bing = m_delete(bing, ident);
else
bing[ident] = level;
if (!m_sizeof(bing))
return 0;
return bing;
}
bing[address[0]] = add_access(bing[address[0]], address[1..4], ident, level);
if (!bing[address[0]])
bing = m_delete(bing, address[0]);
if (!m_sizeof(bing))
return 0;
return bing;
} /* add_access() */
int change_access(string *address, string ident, int level, string reason) {
if (!"/secure/master"->high_programmer(geteuid(previous_object())) ||
this_player() != this_player(1)) {
notify_fail("Wrong euid.\n");
return 0;
}
if (!pointerp(address) || sizeof(address) != 4 || !reason) {
notify_fail("Invalid paramters.\n");
return 0;
}
access = add_access(access, address, ident, level);
if (!access)
access = ([ ]);
save_object(file_name(this_object()),1);
switch (level) {
case NO_NEW :
reason = "no new for "+reason;
break;
case NO_ACCESS :
reason = "no access for "+reason;
break;
case ACCESS :
reason = "access for "+reason;
break;
case 0 :
reason = "deleted for "+reason;
break;
}
write_file("/log/ACCESS",
ident+"@"+implode(address, ".")+" set to "+reason+" by "+
this_player()->query_name()+".\n");
return 1;
} /* check_access() */
int suspend_person(string str, int tim)
{
if (!"/secure/master"->query_lord(geteuid(previous_object())))
return 0;
if (file_size("/players/"+str[0..0]+"/"+str+".o") < 0)
return 0;
suspended[str] = time()+tim;
save_object(file_name(this_object()),1);
write_file("/log/SUSPEND", str+" suspended until "+ctime(time()+tim)+
" by "+this_player()->query_name()+".\n");
return 1;
} /* suspend_person() */
int unsuspend_person(string str)
{
if (!"/secure/master"->query_lord(geteuid(previous_object())))
return 0;
suspended = m_delete(suspended, str);
save_object(file_name(this_object()),1);
// Radix...
write_file("/log/SUSPEND", str+" unsuspended by "+
this_player()->query_name()+".\n");
// write_file("/log/SUSPEND", str+" unsuspended.\n");
return 1;
} /* unsuspend_person() */
/* Banish code:
* Added by Baldrick for simplifying banishing..
*/
int banish_playername(string str, string reason)
{
if (!"/secure/master"->query_lord(geteuid(previous_object())))
return 0;
/*
if (file_size("/players/"+str[0..0]+"/"+str+".o") < 0)
return 0;
*/
banished[str] = reason;
save_object(file_name(this_object()),1);
write_file("/log/BANISHED", str+" banished because of " + reason +
" by "+this_player()->query_name()+".\n");
return 1;
} /* banish player name */
int unbanish_playername(string str)
{
if (!"/secure/master"->query_lord(geteuid(previous_object())))
return 0;
banished = m_delete(banished, str);
save_object(file_name(this_object()),1);
write_file("/log/BANISHED", str+" unbanished.\n");
return 1;
} /* unbanish playername */
string get_nomulti_string(string site, string userid) {
string *ret;
string *thesite;
int i;
mapping acc;
acc = copy(access);
thesite = explode(site, ".");
ret = ({ thesite[0] });
acc = acc[thesite[0]];
for(i=1; i < sizeof(thesite); i++) {
if(acc["*"]) {
acc = acc["*"];
ret += ({ "*" });
}
else {
acc = acc[thesite[i]];
ret += ({ thesite[i] });
}
}
if(acc["*"])
userid = "*";
return userid + "@" + implode(ret, ".");
}