/* /daemon/services.c
* from the Nightmare Mudlib 3.2
* daemon to handle all UDP services
* created by Descartes of Borg 940130
*/
#include <std.h>
#include <daemons.h>
#include <security.h>
#include <network.h>
inherit DAEMON;
void send_affirmation_a(string host, string port, string de, string a, string msg, string type);
static private string *build_mudlist(mapping muds);
void create() {
daemon::create();
set_no_clean(1);
}
void incoming_affirmation_a(mapping info) {
object ob;
if(file_name(previous_object(0)) != NETWORK_D) return;
if(!info["WIZTO"] || !(ob = find_player(lower_case(info["WIZTO"])))) return;
message("tell", sprintf("Affirmation from %s: %s",
(string)NETWORK_D->query_real_name(info["NAME"]), info["MSG"]), ob);
}
void send_affirmation_a(string host, string port, string de, string a,
string msg, string type) {
NETWORK_D->send_udp(host, port, sprintf("@@@%s||NAME:%s||PORTUDP:%d"
"||WIZTO:%s||WIZFROM:%s||TYPE:%s||MSG:%s@@@\n",
SERVICE_UDP_AFFIRMATION_A, mud_name(), (int)NETWORK_D->query_port("udp"),
a, de, type, msg));
}
void incoming_gfinger_a(mapping info) {
object ob;
if(file_name(previous_object(0)) != NETWORK_D) return;
if(ob = find_player(info["ASKWIZ"])) message("info",info["MSG"],ob);
}
void incoming_gfinger_q(mapping info) {
string tmp, msg;
string *borg;
int i, maxi;
if(file_name(previous_object(0)) != NETWORK_D) return;
msg=info["PLAYER"] ? (string)FINGER_D->user_finger_display(info["PLAYER"]):
(string)FINGER_D->general_finger_display();
if(!msg) msg = "\n";
for(i=0, tmp = "", maxi = sizeof(borg=explode(msg, "\n")); i < maxi; i++) {
if(strlen(tmp) < 200) tmp += sprintf("%s\n", borg[i]);
else {
NETWORK_D->send_udp(info["HOSTADDRESS"], info["PORTUDP"],
sprintf("@@@%s||NAME:%s||PORTUDP:%d||ASKWIZ:%s||MSG:%s@@@\n",
SERVICE_UDP_FINGER_A, mud_name(), PORT_UDP, info["ASKWIZ"], tmp));
tmp = sprintf("%s\n", borg[i]);
}
}
NETWORK_D->send_udp(info["HOSTADDRESS"], info["PORTUDP"],
sprintf("@@@%s||NAME:%s||PORTUDP:%d||ASKWIZ:%s||MSG:%s@@@\n",
SERVICE_UDP_FINGER_A, mud_name(), PORT_UDP, info["ASKWIZ"], tmp));
}
int send_gfinger_q(string mud, string who, object ob) {
mapping info;
if(!ob && !(ob = this_player())) return 0;
if(mud == mud_name()) return 0;
if(!(info = (mapping)NETWORK_D->query_mud_info(mud))) return 0;
NETWORK_D->send_udp(info["HOSTADDRESS"], info["PORTUDP"],
sprintf("@@@%s||NAME:%s||PORTUDP:%d%s||ASKWIZ:%s@@@\n",
SERVICE_UDP_FINGER_Q, mud_name(), PORT_UDP, (who ? "||PLAYER:"+who : ""),
(string)ob->query_name()));
return 1;
}
void incoming_gtell(mapping info) {
string msg;
object ob;
if(file_name(previous_object(0)) != NETWORK_D) return;
if(ob = find_player(lower_case(info["WIZTO"]))) {
replace_string(info["MSG"], " \b|", "|");
message("tell", sprintf("%s@%s tells you: %s", capitalize(info["WIZFROM"]),
info["NAME"], info["MSG"]), ob);
ob->set_property("reply", sprintf("%s@%s", info["WIZFROM"], info["NAME"]));
}
if(!ob || ob->query_invis() || hiddenp(ob))
msg = sprintf("%s cannot be found in the reality of %s.\n",
capitalize(info["WIZTO"]), mud_name());
else if(!interactive(ob))
msg = sprintf("%s is zoning in nothingness.\n", capitalize(info["WIZTO"]));
else if(query_idle(ob) > 60)
msg = sprintf("%s is currently idle.\n", capitalize(info["WIZTO"]));
else if(ob->query_blocked("tell"))
msg = sprintf("%s is currently blocking incoming tells.\n",
capitalize(info["WIZTO"]));
else msg = sprintf("%s has assimilated your message.\n",capitalize(info["WIZTO"]));
send_affirmation_a(info["HOSTADDRESS"], info["PORTUDP"],
"Something@"+mud_name(), info["WIZFROM"], msg, "gtell");
}
int send_gtell(string mud, string who, string msg) {
mapping info;
if(mud == mud_name() || !(info=(mapping)NETWORK_D->query_mud_info(mud)))
return 0;
msg = replace_string(replace_string(msg, "|", " \b|"), "@@@", "");
message("tell", sprintf("You tell %s@%s: %s", capitalize(who),
(string)NETWORK_D->query_real_name(mud), msg), this_player());
NETWORK_D->send_udp(info["HOSTADDRESS"], info["PORTUDP"],
sprintf("@@@%s||NAME:%s||PORTUDP:%d||WIZTO:%s||WIZFROM:%s||MSG:%s@@@\n",
SERVICE_UDP_TELL, mud_name(), PORT_UDP, who,
(string)this_player()->query_cap_name(), msg));
return 1;
}
void incoming_gwizmsg(mapping info) {
string msg;
if(file_name(previous_object(0)) != NETWORK_D || !info["WIZNAME"]) return;
replace_string(info["GWIZ"], " \b|", "|");
if(info["EMOTE"] && info["EMOTE"] != "0")
msg = sprintf("%s@%s: %s", info["WIZNAME"], info["NAME"], info["GWIZ"]);
CHAT_D->inter_channels(sprintf("%s@%s", capitalize(info["WIZNAME"]),info["NAME"]),
INTERCHANNELS[info["CHANNEL"]], info["GWIZ"],
(info["EMOTE"] && info["EMOTE"] != "0"));
}
void send_gwizmsg(string msg, int emoted) {
mapping info, borg;
string *muds;
int i;
i = sizeof(muds = keys(borg = (mapping)NETWORK_D->query_known_muds()));
msg = replace_string(replace_string(msg, "|", " \b|"), "@@@", "");
while(i--) {
if(!mapp(info = borg[muds[i]])) continue;
if(info["REAL NAME"] == mud_name()) continue;
NETWORK_D->send_udp(info["HOSTADDRESS"], info["PORTUDP"],
sprintf("@@@%s||NAME:%s||PORTUDP:%d||WIZNAME:%s||GWIZ:%s"
"||CHANNEL:%s%s", SERVICE_UDP_INTERMUD, mud_name(), PORT_UDP,
(string)this_player()->query_cap_name(), msg, "CREATOR",
(emoted ? "||EMOTE:1@@@\n" : "@@@\n")));
}
}
void incoming_locate_a(mapping info) {
object ob;
if(file_name(previous_object(0)) != NETWORK_D) return;
if(!stringp(info["ASKWIZ"]) || !(ob = find_player(lower_case(info["ASKWIZ"]))))
return;
switch(info["LOCATE"]) {
case "NO": return;
case "YES": case "yes":
message("info", sprintf("%s was just located on %s.",
capitalize(info["TARGET"]), info["NAME"]), ob);
break;
default: /* log bad answers here if you want */
}
}
void incoming_locate_q(mapping info) {
string tmp;
if(file_name(previous_object(0)) != NETWORK_D) return;
if(!info["TARGET"]) tmp = "NO";
else tmp = (find_player(lower_case(info["TARGET"])) ? "YES" : "NO");
NETWORK_D->send_udp(info["HOSTADDRESS"], info["PORTUDP"],
sprintf("@@@%s||NAME:%s||PORTUDP:%d||LOCATE:%s||TARGET:%s||ASKWIZ:%s@@@\n",
SERVICE_UDP_LOCATE_A, mud_name(),PORT_UDP, tmp, info["TARGET"], info["ASKWIZ"]));
}
void send_locate_q(string who) {
mapping info;
string *muds;
int i;
i = sizeof(muds = keys(info = (mapping)NETWORK_D->query_known_muds()));
while(i--) {
NETWORK_D->send_udp(info[muds[i]]["HOSTADDRESS"], info[muds[i]]["PORTUDP"],
sprintf("@@@%s||NAME:%s||PORTUDP:%d||TARGET:%s||ASKWIZ:%s@@@\n",
SERVICE_UDP_LOCATE_Q, mud_name(), PORT_UDP, lower_case(who),
(string)this_player()->query_name()));
}
}
void incoming_mail_q(mapping info) {
if(file_name(previous_object(0)) != NETWORK_D) return;
if(info["CC"]) info["CC"] = explode(info["CC"], ",");
else info["CC"] = ({});
info["MSG"] = replace_string(info["MSG"], " \b|", "|");
if(info["WIZTO"]) info["WIZTO"] = explode(info["WIZTO"], ",");
if(!((int)REMOTEPOST_D->incoming_post(info))) info["RESEND"] = 1;
log_file("reports/incoming_mail", info["NAME"]+" "+info["MSG"]);
NETWORK_D->send_udp(info["HOSTADDRESS"], info["PORTUDP"],
sprintf("@@@%s||NAME:%s||PORTUDP:%d%s%s@@@\n", SERVICE_UDP_MAIL_A,
mud_name(), PORT_UDP, (info["ENDMSG"] ? "||ENDMSG:1" : ""),
(info["RESEND"] ? "||RESEND:1" :"")));
}
void incoming_mail_a(mapping info) {
string str;
if(file_name(previous_object(0)) != NETWORK_D) return;
log_file("reports/incoming_confirm", info["NAME"]+"\n");
if(info["RESEND"]) str = (string)REMOTEPOST_D->resend_post(info["NAME"]);
else if(!(str = (string)REMOTEPOST_D->next_post(info["NAME"])))
str = (string)REMOTEPOST_D->postal_check(info["NAME"]);
if(!str) return;
NETWORK_D->send_udp(info["HOSTADDRESS"], info["PORTUDP"],
sprintf("@@@%s||NAME:%s||PORTUDP:%d%s@@@\n", SERVICE_UDP_MAIL_Q,
mud_name(), PORT_UDP, str));
}
void incoming_mudlist_a(mapping info) {
string *borg, *dat;
string cle, val;
mapping tmp;
int i, j;
if(file_name(previous_object(0)) != NETWORK_D) return;
i = sizeof(borg = keys(info));
while(i--) {
j = sizeof(dat = explode(info[borg[i]], "|"));
tmp = ([]);
while(j--) if(sscanf(dat[j], "%s:%s", cle, val) ==2) tmp[cle] = val;
if(!tmp["NAME"]) continue;
if(replace_string(lower_case(tmp["NAME"]), " ", ".") ==
replace_string(lower_case(mud_name()), " ", ".")) continue;
if((int)NETWORK_D->mud_exists(tmp["NAME"])) continue;
NETWORK_D->add_mud(tmp);
}
}
void incoming_mudlist_q(mapping info) {
string *bits;
int i;
if(file_name(previous_object(0)) != NETWORK_D) return;
i = sizeof(bits = build_mudlist((mapping)NETWORK_D->query_known_muds()));
while(i--)
NETWORK_D->send_udp(info["HOSTADDRESS"], info["PORTUDP"],
sprintf("@@@%s%s@@@\n", SERVICE_UDP_MUDLIST_A, bits[i]));
}
void send_mudlist_q(string host, string port) {
NETWORK_D->send_udp(host, port,
sprintf("@@@%s||NAME:%s||PORTUDP:%d@@@\n", SERVICE_UDP_MUDLIST_Q, mud_name(),
PORT_UDP));
}
void incoming_ping_a(mapping info) {
if(file_name(previous_object(0)) != NETWORK_D) return;
if((int)NETWORK_D->mud_exists(info["NAME"])) return;
NETWORK_D->add_mud(info);
}
void incoming_ping_q(mapping info) {
string str;
if(file_name(previous_object(0)) != NETWORK_D) return;
log_file("reports/ping_q", info["NAME"]+"\n");
NETWORK_D->send_udp(info["HOSTADDRESS"], info["PORTUDP"],
sprintf("@@@%s%s@@@\n", SERVICE_UDP_PING_A, START_MSG));
if(str = (string)REMOTEPOST_D->postal_check(info["NAME"]))
NETWORK_D->send_udp(info["HOSTADDRESS"], info["PORTUDP"],
sprintf("@@@%s||NAME:%s||PORTUDP:%d%s@@@\n",
SERVICE_UDP_MAIL_Q, mud_name(), PORT_UDP, str));
if(str)
log_file("reports/daemon", info["NAME"]+" "+str+"\n");
}
void send_ping_q(string host, int port) {
NETWORK_D->send_udp(host, port,
sprintf("@@@%s||NAME:%s||PORTUDP:%d@@@\n", SERVICE_UDP_PING_Q, mud_name(),
PORT_UDP));
}
void incoming_rwho_a(mapping info) {
object ob;
if(file_name(previous_object(0)) != NETWORK_D) return;
if(!(ob = find_player(lower_case(info["ASKWIZ"])))) return;
message("info", "%^RED%^rwho@"+info["NAME"]+":%^RESET%^\n"+info["RWHO"], ob);
}
int incoming_rwho_q(mapping info) {
string tmp, list;
string *bits;
object *who, *borg;
int i, maxi;
if(file_name(previous_object(0)) != NETWORK_D) return 0;
who = filter_array(users(), "filter_invis", this_object());
list = sprintf("%s (driver: %s, mudlib: %s %s)\n", mud_name(), version(),
mudlib(), mudlib_version());
if(!sizeof(who)) list += "Reality is void of being.\n";
else {
if(maxi=sizeof(borg=filter_array(who,"filter_admins",this_object()))) {
for(i=0, tmp="";i<maxi;i++) tmp += (string)borg[i]->query_cap_name()+" ";
list += "Admins: "+wrap(tmp);
}
if(maxi=sizeof(borg=filter_array(who,"filter_creators",this_object()))) {
for(i=0, tmp="";i<maxi;i++) tmp += (string)borg[i]->query_cap_name()+" ";
list += "Creators: "+wrap(tmp);
}
if(maxi=sizeof(borg=filter_array(who,"filter_hm",this_object()))) {
for(i=0, tmp="";i<maxi;i++) tmp += (string)borg[i]->query_cap_name()+" ";
list += "High Mortals: "+wrap(tmp);
}
if(maxi=sizeof(borg=filter_array(who, "filter_mortals", this_object()))) {
for(i=0, tmp="";i<maxi;i++) tmp += (string)borg[i]->query_cap_name()+" ";
list += "Mortals: "+wrap(tmp);
}
}
NETWORK_D->send_udp(info["HOSTADDRESS"], info["PORTUDP"],
sprintf("@@@%s||NAME:%s||PORTUDP:%d||RWHO:%s||ASKWIZ:%s@@@\n",
SERVICE_UDP_RWHO_A, mud_name(), PORT_UDP, list, info["ASKWIZ"]));
}
int send_rwho_q(string mud, object ob) {
mapping info;
if((!ob && !(ob=this_player()))) return 0;
if(!(info=(mapping)NETWORK_D->query_mud_info(mud))) return 0;
NETWORK_D->send_udp(info["HOSTADDRESS"], info["PORTUDP"],
sprintf("@@@%s||NAME:%s||PORTUDP:%d||ASKWIZ:%s@@@\n", SERVICE_UDP_RWHO_Q,
mud_name(), PORT_UDP, (string)ob->query_name()));
return 1;
}
void incoming_shutdown(mapping info) {
if(file_name(previous_object(0)) != NETWORK_D) return;
NETWORK_D->remove_mud(info["NAME"]);
}
void send_shutdown(string host, int port) {
if(file_name(previous_object(0)) != NETWORK_D) return;
NETWORK_D->send_udp(host, port,
sprintf("@@@%s||NAME:%s||PORTUDP:%d@@@\n", SERVICE_UDP_SHUTDOWN,
mud_name(), PORT_UDP));
}
void incoming_startup(mapping info) {
if(file_name(previous_object(0)) != NETWORK_D) return;
incoming_ping_a(info);
incoming_ping_q(info);
}
void incoming_support_a(mapping info) {
object ob;
string fl, fun, id;
if(file_name(previous_object(0)) != NETWORK_D) return;
if(!info["ANSWERID"] || sscanf(info["ANSWERID"],"%s#%s#%s",fl,fun,id) != 3)
return;
if(!(ob = find_object(fl))) return;
if(info["SUPPORTED"] && lower_case(info["SUPPORTED"]) == "yes")
call_other(ob, fun, ({ 1, id }));
else call_other(ob, fun, ({ 0, id }) );
}
void incoming_support_q(mapping info) {
string ret;
if(file_name(previous_object(0)) != NETWORK_D) return;
if(!stringp(info["PARAM"])) info["PARAM"] = "";
if(!function_exists(sprintf("incoming_%s",info["CMD"]),
this_object()) && member_array(info["CMD"], TCP_SERVICES) == -1)
ret = "||NOTSUPPORTED:yes";
else ret = "||SUPPORTED:yes";
NETWORK_D->send_udp(info["HOSTADDRESS"], info["PORTUDP"],
sprintf("@@@%s||NAME:%s||PORTUDP:%d||CMD:%s||PARAM:%s%s||ANSWERID:%s@@@\n",
SERVICE_UDP_SUPPORT_A, mud_name(), PORT_UDP, info["CMD"], info["PARAM"],
ret, info["ANSWERID"]));
}
int send_support_q(string mud, string cmd, string param, string fun, string id) {
mapping info;
string fl;
if(!param) param = "";
fl = file_name(previous_object());
id = sprintf("%s#%s#%s", fl, fun, id);
if(!(info = (mapping)NETWORK_D->query_mud_info(mud))) return 0;
NETWORK_D->send_udp(info["HOSTADDRESS"], info["PORTUDP"],
sprintf("@@@%s||NAME:%s||PORTUDP:%d||CMD:%s||PARAM:%s||ANSWERID:%s@@@\n",
SERVICE_UDP_SUPPORT_Q, mud_name(), PORT_UDP, cmd, param, id));
return 1;
}
static int filter_invis(object ob) {
return (!((int)ob->query_invis()) && !hiddenp(ob) &&
(string)ob->query_cap_name());
}
static int filter_admins(object ob) { return archp(ob); }
static int filter_creators(object ob) { return creatorp(ob) && !archp(ob); }
static int filter_hm(object ob) { return high_mortalp(ob); }
static int filter_mortals(object ob) {
return (!creatorp(ob) && !high_mortalp(ob));
}
static private string *build_mudlist(mapping muds) {
string *noms, *ret;
int i, pos, maxi;
maxi = sizeof(noms = keys(muds));
for(i=0, pos = 0, ret = ({ "" }); i<maxi; i++) {
ret[pos] += "||"+i+":"+
"|NAME:"+muds[noms[i]]["REAL NAME"]+
"|HOST:"+muds[noms[i]]["HOST"]+
"|HOSTADDRESS:"+muds[noms[i]]["HOSTADDRESS"]+
"|PORT:"+muds[noms[i]]["PORT"]+
"|TCP:"+(undefinedp(muds[noms[i]]["TCP"]) ? "none" : muds[noms[i]]["TCP"])+
"|PORTUDP:"+muds[noms[i]]["PORTUDP"]+
(muds[noms[i]]["MUDLIB"] ? "|MUDLIB:"+muds[noms[i]]["MUDLIB"] : "") +
(muds[noms[i]]["VERSION"] ? "|VERSION:"+muds[noms[i]]["VERSION"] : "") +
(muds[noms[i]]["DRIVER"] ? "|DRIVER:"+muds[noms[i]]["DRIVER"] : "") +
(muds[noms[i]]["TIME"] ? "|TIME:"+muds[noms[i]]["TIME"] : "");
if(strlen(ret[pos]) > 256) {
ret += ({ "" });
pos++;
}
}
return ret;
}
void new_mail(string mud) {
mapping info;
if(file_name(previous_object()) != REMOTEPOST_D) return;
if(!(info = (mapping)NETWORK_D->query_mud_info(mud))) return;
this_object()->send_ping_q(info["HOSTADDRESS"], info["PORTUDP"]);
}