Added public files
Roughly added all public files. Probably missed some, though.
diff --git a/secure/udp/channel.c b/secure/udp/channel.c
new file mode 100644
index 0000000..3592ffe
--- /dev/null
+++ b/secure/udp/channel.c
@@ -0,0 +1,110 @@
+// MorgenGrauen MUDlib
+//
+// channel.c
+//
+// $Id: channel.c 9142 2015-02-04 22:17:29Z Zesstra $
+
+#include <udp.h>
+
+#include <properties.h>
+#include <daemon.h>
+
+#ifdef ZEBEDEE
+inherit "/sys/format";
+#endif
+
+#define COMMAND "cmd"
+#define CHANNEL "channel"
+
+private nosave mixed _name_;
+
+int filter_listeners(object ob, string channel) {
+ return ob->QueryProp(P_INTERMUD);
+}
+
+int udp_channel(mapping data) {
+ object *list;
+ string msg;
+ int i, type;
+
+ /* Compatability with older systems. */
+ if (!data[CHANNEL])
+ data[CHANNEL] = data["CHANNEL"];
+ if (!data[COMMAND])
+ data[COMMAND] = data["CMD"];
+ if (!data[DATA])
+ data[DATA]="";
+
+ if (!stringp(data[CHANNEL]) || !sizeof(data[CHANNEL])
+ || !stringp(data[DATA]) || !sizeof(data[DATA])
+ || !stringp(data[NAME]) || !sizeof(data[NAME])
+ || !stringp(data[SENDER]) || !sizeof(data[SENDER]))
+ return 0;
+
+ data[DATA]=
+ implode(filter(explode(data[DATA], ""), #'>=, " "), "");//'))
+ data[NAME]=
+ implode(filter(explode(data[NAME], ""), #'>=, " "), "");//'))
+ switch(data[COMMAND]) {
+ case "list":
+ /* Request for a list of people listening to a certain channel. */
+ list = filter(users(), "filter_listeners",
+ this_object(), data[CHANNEL]);
+ if (i = sizeof(list)) {
+ msg = "[" + capitalize(data[CHANNEL]) + "@" +
+ LOCAL_NAME + "] Listening:\n";
+ while(i--)
+ msg +=
+ " " + capitalize(list[i]->query_real_name()) + "\n";
+ }
+ else
+ msg = "[" + capitalize(data[CHANNEL]) + "@" + LOCAL_NAME
+ + "] Nobody Listening.\n";
+ INETD->_send_udp(data[NAME], ([
+ REQUEST: REPLY,
+ RECIPIENT: data[SENDER],
+ ID: data[ID],
+ DATA: msg
+ ]));
+ return 1;
+ case "emote": /* A channel emote. */
+ type = MSG_EMOTE;
+ break;
+ default: /* A regular channel message. */
+ type = MSG_SAY;
+ break;
+ }
+ _name_ = capitalize(data[SENDER])+"@"+capitalize(data[NAME]);
+ CHMASTER->send(capitalize(data[CHANNEL]), this_object(),
+ data[DATA], type);
+ _name_ = 0;
+ return 1;
+}
+
+string name() { return _name_ || "<Intermud>"; }
+string Name() {return capitalize(_name_ || "<Intermud>");}
+
+private void _send(string mud, mixed data, mapping request)
+{
+ if(member(data[HOST_COMMANDS], "channel") != -1 ||
+ member(data[HOST_COMMANDS], "*") != -1)
+ INETD->_send_udp(data[HOST_NAME], request);
+}
+
+void ChannelMessage(mixed m)
+{
+ mapping request;
+ if(m[1] == this_object()) return;
+ request = ([
+ REQUEST : "channel",
+ SENDER : m[1]->name() || capitalize(getuid(m[1])),
+ "CHANNEL": lower_case(m[0]),
+ DATA : implode(old_explode(m[2], "\n"), " ")]);
+ if(m[3] == MSG_GEMOTE || m[3] == MSG_EMOTE)
+ {
+ request["EMOTE"] = 1;
+ request["CMD"] = "emote";
+ }
+ walk_mapping(INETD->query("hosts") - ([lower_case(MUDNAME)]),
+ #'_send/*'*/, request);
+}
diff --git a/secure/udp/finger.c b/secure/udp/finger.c
new file mode 100644
index 0000000..c9d4c4d
--- /dev/null
+++ b/secure/udp/finger.c
@@ -0,0 +1,31 @@
+// MorgenGrauen MUDlib
+//
+// finger.c
+//
+// $Id: finger.c 6081 2006-10-23 14:12:34Z Zesstra $
+
+#include <udp.h>
+
+string last_finger;
+
+#ifdef ZEBEDEE
+#include <system.h>
+#elif !defined(INETD)
+#define INETD "/secure/inetd"
+#endif
+
+void udp_finger(mapping data)
+{
+ last_finger=capitalize(to_string(data[SENDER]))+"@"+data[NAME];
+ INETD->_send_udp(data[NAME], ([
+ REQUEST: REPLY,
+ RECIPIENT: data[SENDER],
+ ID: data[ID],
+ DATA: "/p/daemon/finger"->finger_single(data[DATA])
+ ]) );
+}
+
+string QueryLastFinger()
+{
+ return last_finger;
+}
diff --git a/secure/udp/htmlwho.c b/secure/udp/htmlwho.c
new file mode 100644
index 0000000..d9cd899
--- /dev/null
+++ b/secure/udp/htmlwho.c
@@ -0,0 +1,53 @@
+// MorgenGrauen MUDlib
+//
+// htmlwho.c
+//
+// $Id: htmlwho.c 8755 2014-04-26 13:13:40Z Zesstra $
+
+#pragma weak_types
+
+#include <udp.h>
+
+#define TJ(x) if (find_player("jof")) tell_object(find_player("jof"),x)
+
+string adjust(string str,int wid)
+{
+ int w2;
+
+ w2=wid/2;
+ wid=wid-w2;
+ return extract(" ",0,wid-1)+str+
+ extract(" ",0,w2-1);
+}
+
+udp_htmlwho(data)
+{
+ int i,num;
+ string *mdata;
+ string wholiste,tmp,tmp2;
+
+ mdata="/obj/werliste"->QueryWhoListe(0,0,1);
+ num=sizeof(mdata);
+ for (i=num-1;i>=0;i--)
+ {
+ tmp=mdata[i][0]->name();
+ if (tmp&&sizeof(tmp))
+ {
+ tmp2=explode(mdata[i][1],tmp);
+ if (sizeof(tmp2)>1)
+ {
+ tmp2[0]="<A HREF=\"/htbin/mudwww?finger?"+getuid(mdata[i][0])+"\"><b>";
+ tmp2[1]="</b></A>"+tmp2[1];
+ mdata[i][1]=implode(tmp2,tmp);
+ }
+ mdata[i]=" <LI> "+mdata[i][1];
+ }
+ }
+ wholiste=implode(mdata,"\n");
+ INETD->_send_udp(data[NAME], ([
+ REQUEST: REPLY,
+ RECIPIENT: data[SENDER],
+ ID: data[ID],
+ DATA: wholiste
+ ]) );
+}
diff --git a/secure/udp/locate.c b/secure/udp/locate.c
new file mode 100644
index 0000000..d793d05
--- /dev/null
+++ b/secure/udp/locate.c
@@ -0,0 +1,33 @@
+// MorgenGrauen MUDlib
+//
+// locate.c
+//
+// $Id: locate.c 6081 2006-10-23 14:12:34Z Zesstra $
+
+#include <udp.h>
+
+#define FOUND "fnd"
+#define USER "user"
+#define VERBOSE "vbs"
+
+void udp_locate(mapping data) {
+ mapping ret;
+ object ob;
+
+ ret = ([
+ REQUEST: REPLY,
+ RECIPIENT: data[SENDER],
+ ID: data[ID],
+ USER: data[USER],
+ VERBOSE: data[VERBOSE],
+ ]);
+ if (data[DATA] && (ob = find_player(data[DATA])) &&
+ interactive(ob) && !ob->query_invis()) {
+ ret[FOUND] = 1;
+ ret[DATA] = "locate@" + LOCAL_NAME + ": " + ob->short();
+ }
+ else
+ ret[DATA] = "locate@" + LOCAL_NAME + ": No such player: " +
+ data[DATA] + "\n";
+ INETD->_send_udp(data[NAME], ret);
+}
diff --git a/secure/udp/mail.c b/secure/udp/mail.c
new file mode 100644
index 0000000..04f8651
--- /dev/null
+++ b/secure/udp/mail.c
@@ -0,0 +1,64 @@
+// MorgenGrauen MUDlib
+//
+// mail.c
+//
+// $Id: mail.c 6081 2006-10-23 14:12:34Z Zesstra $
+
+/*
+ * VERSION 1.0
+ * udp module for the UDP MAIL system (Author: Alvin@Sushi)
+ * Requires INETD V0.60 or higher (INETD Author: Nostradamus@Zebedee)
+ */
+
+#include <udp.h>
+#include <udp_mail.h>
+
+/*
+#define DEBUG(msg) if (find_player("hate")) tell_object(find_player("hate"),msg)
+*/
+#undef DEBUG
+#define DEBUG(x)
+
+void udp_mail(mapping data)
+{
+ DEBUG(sprintf("UDPMAIL %O\n",data));
+ if(!member(data,RECIPIENT) || !data[RECIPIENT])
+ {
+ log_file("INETD","Invalid udp_mail packet. No Recipient.\n");
+ return;
+ }
+
+ if(!LOCAL_MAILER->query_recipient_ok(data[RECIPIENT]))
+ {
+ INETD->_send_udp(data[NAME], ([
+ REQUEST: REPLY,
+ RECIPIENT: data[SENDER],
+ UDPM_STATUS: UDPM_STATUS_UNKNOWN_PLAYER,
+ UDPM_WRITER: data[UDPM_WRITER],
+ UDPM_SPOOL_NAME: data[UDPM_SPOOL_NAME],
+ ID: data[ID],
+ DATA: "Reason: Unknown player \""+capitalize(data[RECIPIENT])+
+ "\"\n\nINCLUDED MESSAGE FOLLOWS :-\n\n"+
+ "Subject: "+data[UDPM_SUBJECT]+"\n"+data[DATA]
+ ]) );
+
+ return;
+ }
+
+ LOCAL_MAILER->deliver_mail(
+ data[RECIPIENT], /* To */
+ data[UDPM_WRITER]+"@"+data[NAME], /* From */
+ data[UDPM_SUBJECT], /* Subj */
+ data[DATA] /* Mail Body */
+ );
+
+ INETD->_send_udp(data[NAME], ([
+ REQUEST: REPLY,
+ RECIPIENT: data[SENDER],
+ UDPM_STATUS: UDPM_STATUS_DELIVERED_OK,
+ UDPM_WRITER: data[UDPM_WRITER],
+ UDPM_SPOOL_NAME: data[UDPM_SPOOL_NAME],
+ ID: data[ID],
+ DATA: data[RECIPIENT]
+ ]) );
+}
diff --git a/secure/udp/man.c b/secure/udp/man.c
new file mode 100644
index 0000000..88c4b57
--- /dev/null
+++ b/secure/udp/man.c
@@ -0,0 +1,98 @@
+#pragma strict_types
+#include <udp.h>
+#include <daemon.h>
+
+#define MAX_READ_FILE_LEN 50000
+
+// TEMPORARY
+
+#include <udp_language.h>
+#include <logging.h>
+
+#ifndef LOCAL_NAME
+#define LOCAL_NAME "MorgenGrauen"
+#endif
+
+#ifndef INETD_INVALID_ACCESS
+#define INETD_INVALID_ACCESS INTERMUDLOG("INVALID_ACCESS")
+#endif
+
+#ifndef INVALID_ACCESS
+#define INVALID_ACCESS(x) \
+ log_file(INETD_INVALID_ACCESS, \
+ sprintf(INETD_INV_ACCESS_MSG "TI: %O PO: %O\n", \
+ ctime()[4..15],this_interactive(), \
+ previous_object()))
+#endif
+
+
+// END TEMPORARY
+
+void udp_man(mapping data)
+{
+ mapping pages;
+ int index;
+ string manpage,ret;
+ string|string* tmp;
+
+ if (previous_object()!=find_object(INETD))
+ {
+ INVALID_ACCESS(Man);
+ return;
+ }
+
+ manpage=data[DATA];
+ tmp=explode(manpage,"/");
+ if (sizeof(tmp)>1)
+ {
+ if (file_size(MAND_DOCDIR+manpage)>=0)
+ tmp=({tmp[<1],manpage});
+ else
+ tmp=({});
+ }
+ else
+ tmp=(string *)call_other(MAND,"locate",data[DATA],0);
+ pages=([]);
+ index=sizeof(tmp);
+ while(index--)
+ {
+ if (tmp[1][0..1]!="g.") pages[tmp[index]]=tmp[index-1];
+ index--;
+ }
+ switch(sizeof(pages))
+ {
+ case 0:
+ ret=sprintf(INETD_NO_MANPAGE,LOCAL_NAME,manpage);
+ break;
+ case 1:
+ tmp=m_indices(pages)[0];
+ ret=sprintf(INETD_MANPAGE_FOUND,LOCAL_NAME,pages[tmp]);
+ index=0;
+ while(manpage=read_file(MAND_DOCDIR+tmp,index))
+ {
+ ret+=manpage;
+ index+=MAX_READ_FILE_LEN;
+ }
+ break;
+ default:
+ ret=sprintf(INETD_MANPAGES,LOCAL_NAME,"",
+ break_string(implode(m_values(pages)," "),78),"");
+ break;
+ }
+ INETD->_send_udp(data[NAME],
+ ([
+ REQUEST: REPLY,
+ RECIPIENT: data[SENDER],
+ ID: data[ID],
+ DATA: ret
+ ]));
+}
+
+string send_request(string mudname, string pagename)
+{
+ return (INETD->_send_udp(mudname,
+ ([REQUEST: "man",
+ DATA: pagename,
+ SENDER: getuid(previous_object())]),1)||
+ sprintf(INETD_MAN_REQUESTED,pagename,mudname));
+}
diff --git a/secure/udp/ping.c b/secure/udp/ping.c
new file mode 100644
index 0000000..f48329d
--- /dev/null
+++ b/secure/udp/ping.c
@@ -0,0 +1,22 @@
+// MorgenGrauen MUDlib
+//
+// ping.c
+//
+// $Id: ping.c 6081 2006-10-23 14:12:34Z Zesstra $
+
+#include <udp.h>
+
+#ifdef ZEBEDEE
+#include <system.h>
+#elif !defined(INETD)
+#define INETD "/secure/inetd"
+#endif
+
+void udp_ping(mapping data) {
+ INETD->_send_udp(data[NAME], ([
+ REQUEST: REPLY,
+ RECIPIENT: data[SENDER],
+ ID: data[ID],
+ DATA: LOCAL_NAME + " is alive.\n"
+ ]) );
+}
diff --git a/secure/udp/query.c b/secure/udp/query.c
new file mode 100644
index 0000000..f9bc7cd
--- /dev/null
+++ b/secure/udp/query.c
@@ -0,0 +1,88 @@
+// MorgenGrauen MUDlib
+//
+// query.c
+//
+// $Id: query.c 7397 2010-01-26 21:48:11Z Zesstra $
+
+#include <udp.h>
+#include <udp_language.h>
+#include <strings.h>
+
+#ifdef ZEBEDEE
+#include <system.h>
+#elif !defined(INETD)
+#define INETD "/secure/inetd"
+#endif
+
+/* Mud / Admin email address. */
+#define EMAIL "mud@mg.mud.de"
+
+void udp_query(mapping data) {
+ mapping ret;
+
+ switch(data[DATA]) {
+ case "commands":
+ ret = INETD->query("hosts");
+ if (ret[lower_case(data[NAME])])
+ ret = ([
+ DATA: implode(ret[lower_case(data[NAME])][LOCAL_COMMANDS], ":")
+ ]);
+ else
+ ret = ([ DATA: implode(INETD->query("commands"), ":") ]);
+ break;
+ case "email":
+ ret = ([ DATA: EMAIL ]);
+ break;
+ case "hosts":
+ {
+ string tmp = "";
+ foreach(string mudname, mixed fields: INETD->query("hosts")) {
+ tmp += fields[HOST_NAME] + ":" +
+ fields[HOST_IP] + ":" +
+ fields[HOST_UDP_PORT] + ":" +
+ implode(fields[LOCAL_COMMANDS], ",") + ":" +
+ implode(fields[HOST_COMMANDS], ",") + "\n";
+ }
+ ret = ([ DATA: trim(tmp,TRIM_RIGHT, "\n") ]);
+ break;
+ }
+ case "inetd":
+ ret = ([ DATA: INETD_VERSION ]);
+ break;
+ case "list":
+ /* List of thingsthat can be queried. */
+ ret = ([ DATA: "commands:email:hosts:inetd:mud_port:time:version" ]);
+ break;
+ case "mud_port":
+ ret = ([ DATA: query_mud_port() ]);
+ break;
+ case "time":
+ ret = ([ DATA: time() ]);
+ break;
+ case "version":
+ ret = ([ DATA: version() ]);
+ break;
+ default:
+ /* Just ignore it for the time being. */
+ return;
+ }
+ INETD->_send_udp(data[NAME], ret + ([
+ REQUEST: REPLY,
+ RECIPIENT: data[SENDER],
+ ID: data[ID],
+ "QUERY": data[DATA]
+ ]) );
+}
+
+string send_request(string mudname, string prop)
+{
+ if (!stringp(mudname) || !stringp(prop))
+ return 0;
+
+ return (INETD->_send_udp(mudname,
+ ([REQUEST: "query",
+ DATA: prop,
+ SENDER: getuid(previous_object())]),1)||
+ sprintf(INETD_QUERY_REQUESTED, prop, mudname));
+}
+
diff --git a/secure/udp/reply.c b/secure/udp/reply.c
new file mode 100644
index 0000000..d60661a
--- /dev/null
+++ b/secure/udp/reply.c
@@ -0,0 +1,54 @@
+// MorgenGrauen MUDlib
+//
+// reply.c
+//
+// $Id: reply.c,v 1.2 2003/04/08 09:28:17 Rikus Exp $
+
+#include <udp.h>
+
+#ifndef DATE
+#define DATE ctime()[4..15]
+#endif
+
+void udp_reply(mapping data)
+{
+ string err,recpt,serv;
+ object ob;
+
+
+ if (pointerp(data[SYSTEM])&&member(data[SYSTEM],TIME_OUT)>-1)
+ {
+ if (data[SENDER])
+ {
+ if (stringp(data[SENDER])&&(ob=find_player(data[SENDER])))
+ {
+ switch(data[REQUEST])
+ {
+ case "tell": serv="teile mit: ";break;
+ case "who": serv="wer: ";break;
+ default: serv=data[REQUEST]+": "; break;
+ }
+ tell_object(ob, break_string("Das Mud \'" + data[NAME] +
+ "\' konnte nicht erreicht werden.\n",
+ 78,serv));
+ }
+ else
+ if (objectp(ob = data[SENDER])||(ob = find_object(data[SENDER])))
+ ob->udp_reply(data);
+ }
+ return;
+ }
+ if (data[RECIPIENT])
+ {
+ if (stringp(data[RECIPIENT])&&(ob = find_player(data[RECIPIENT])))
+ tell_object(ob, "\n" + data[DATA]);
+ else if (ob=find_object(data[RECIPIENT]))
+ ob->udp_reply(data);
+ return;
+ }
+ if (data[REQUEST]=="ping")return;
+ if (data[DATA])
+ log_file(INETD_LOG_FILE, DATE + ": Antwort von " + data[NAME] +
+ "\n" + data[DATA] + "\n");
+ return;
+}
diff --git a/secure/udp/tell.c b/secure/udp/tell.c
new file mode 100644
index 0000000..7b1ab61
--- /dev/null
+++ b/secure/udp/tell.c
@@ -0,0 +1,118 @@
+// MorgenGrauen MUDlib
+//
+// tell.c
+//
+// $Id: tell.c 8755 2014-04-26 13:13:40Z Zesstra $
+
+#include <config.h>
+#include <udp.h>
+#include <properties.h>
+
+#ifdef ZEBEDEE
+#include <system.h>
+inherit "/sys/format";
+#elif !defined(INETD)
+#define INETD "/secure/inetd"
+#endif
+
+
+void udp_tell(mapping data) {
+ object ob;
+ string message_string, message_prefix, away;
+ int i,re;
+ string *message_array;
+
+ if (data[RECIPIENT] &&
+ (ob = find_player(lower_case(data[RECIPIENT]))) &&
+ interactive(ob)) {
+
+ if (!stringp(data[SENDER]) || !sizeof(data[SENDER]))
+ data[SENDER]="<Unknown>";
+ if (!stringp(data[DATA]) || !sizeof(data[DATA]))
+ data[DATA]="<Nichts>";
+
+ data[SENDER]=
+ implode(filter(explode(data[SENDER], ""),
+ #'>=,/*'*/ " "), "");
+ data[DATA]=
+ implode(filter(explode(data[DATA], ""),
+ #'>=,/*'*/ " "), "");
+ message_prefix=capitalize(data[SENDER])+"@"+data[NAME]+
+ " teilt Dir mit: ";
+ message_string=break_string(data[DATA],78,message_prefix,0);
+
+ /* Die Anzahl der Leerzeilen am Ende eines tm's scheint nicht genormt */
+ while(message_string[<1]=='\n')message_string=message_string[0..<2];
+ message_string += "\n";
+
+ re = ob->Message("\n"+message_string, MSGFLAG_RTELL);
+
+ if (!ob->QueryProp(P_INVIS)){
+ /* Erst testen, ob die Meldung ueberhaupt angekommen ist! */
+ if(re==MESSAGE_DEAF)
+ message_string=sprintf("%s@"MUDNAME" ist momentan leider taub.\n",
+ capitalize(getuid(ob)));
+ else if(re==MESSAGE_IGNORE_YOU)
+ message_string=sprintf("%s@"MUDNAME" ignoriert Dich.\n",
+ capitalize(getuid(ob)));
+ else if(re==MESSAGE_IGNORE_MUD)
+ message_string=sprintf("%s@"MUDNAME" ignoriert das Mud '%s'.\n",
+ capitalize(getuid(ob)),
+ data[NAME]);
+ else {
+ /* Erst dann die Erfolgs-Rueckmeldung abschicken */
+ message_prefix="Du teilst "+capitalize(data[RECIPIENT]) + "@"
+ LOCAL_NAME + " mit: ";
+ message_string=break_string(data[DATA],78,message_prefix,0);
+ if(ob->QueryProp(P_AWAY))
+ message_string=sprintf("%s%s@"MUDNAME" ist gerade nicht "
+ "da: %s\n",
+ message_string,
+ ob->name(WER),
+ ob->QueryProp(P_AWAY));
+ else if ((i=query_idle(ob))>=600){ // 10 Mins
+ if (i<3600) away=time2string("%m %M",i);
+ else away=time2string("%h %H und %m %M",i);
+ message_string=
+ sprintf("%s%s@"MUDNAME" ist seit %s voellig untaetig.\n",
+ message_string,
+ ob->Name(WER),
+ away);
+ }
+ switch(re) {
+ case MESSAGE_CACHE:
+ message_string +=
+ sprintf("%s@"MUDNAME" moechte gerade nicht gestoert werden.\n"+
+ "Die Mittelung wurde von einem kleinen Kobold in Empfang"+
+ "genommen.\nEr wird sie spaeter weiterleiten.\n",
+ capitalize(getuid(ob)));
+ break;
+ case MESSAGE_CACHE_FULL:
+ message_string +=
+ sprintf("%s@"MUDNAME" moechte gerade nicht gestoert werden.\n"+
+ "Die Mitteilung ging verloren, denn der Kobold kann sich "+
+ "nichts mehr merken.\n",
+ capitalize(getuid(ob)));
+ break;
+ }
+ }
+ }
+ else message_string="\nRoot@"MUDNAME": Spieler "+
+ capitalize(data[RECIPIENT])+
+ " finde ich in "MUDNAME" nicht!\n";
+ INETD->_send_udp(data[NAME],
+ ([ REQUEST: REPLY,
+ RECIPIENT: data[SENDER],
+ ID: data[ID],
+ DATA: "\n"+message_string ]) );
+ }
+ else
+ INETD->_send_udp(data[NAME],
+ ([ REQUEST: REPLY,
+ RECIPIENT: data[SENDER],
+ ID: data[ID],
+ DATA: sprintf("Root@"MUDNAME": Spieler %s finde "+
+ "ich in "MUDNAME" nicht!\n",
+ capitalize(data[RECIPIENT]))
+ ]) );
+}
diff --git a/secure/udp/who.c b/secure/udp/who.c
new file mode 100644
index 0000000..7be9bb3
--- /dev/null
+++ b/secure/udp/who.c
@@ -0,0 +1,58 @@
+// MorgenGrauen MUDlib
+//
+// who.c
+//
+// $Id: who.c 8755 2014-04-26 13:13:40Z Zesstra $
+
+#include <config.h>
+#include <udp.h>
+
+int last;
+int maxtoday, maxever;
+
+void create()
+{
+ string tmp1, tmp2, dummy;
+
+ if (time()-last<1800) return;
+ last=time();
+ tmp1=read_file("/etc/maxusers.ever",0,1);
+ tmp2=read_file("/etc/maxusers",0,1);
+ if (stringp(tmp1)&&sizeof(tmp1)) sscanf(tmp1,"%d %s",maxever,dummy);
+ if (stringp(tmp2)&&sizeof(tmp2)) sscanf(tmp2,"%d %s",maxtoday,dummy);
+}
+
+string adjust(string str,int wid) {
+ return sprintf("%*|s",wid,str);
+}
+
+void udp_who(mapping data)
+{
+ int i;
+ string *lines;
+ string wholiste,header;
+
+ create();
+ lines="/obj/werliste"->QueryWhoListe(0, 1);
+ wholiste=implode(lines,"\n");
+ lines=({
+ "*------------------------------------------------------------------------*",
+ "","","","",
+ "*------------------------------------------------------------------------*"});
+ header=MUDNAME", LDMud "+__VERSION__;
+ lines[1]="|"+adjust(header,sizeof(lines[0])-2)+"|";
+ header="Adresse: MG.Mud.DE (87.79.24.60) 23 (alternativ 4711)";
+ lines[2]="|"+adjust(header,sizeof(lines[0])-2)+"|";
+ header="Uptime: "+uptime();
+ lines[3]="|"+adjust(header,sizeof(lines[0])-2)+"|";
+ header=_MUDLIB_NAME_"-Mudlib "_MUDLIB_VERSION_;
+ lines[4]="|"+adjust(header,sizeof(lines[0])-2)+"|";
+ header=implode(lines,"\n");
+ wholiste=header+"\n"+wholiste+sprintf("\n*** Anwesende im "MUDNAME": Max. heute %d, Rekord %d\n",maxtoday,maxever);
+ INETD->_send_udp(data[NAME], ([
+ REQUEST: REPLY,
+ RECIPIENT: data[SENDER],
+ ID: data[ID],
+ DATA: wholiste
+ ]) );
+}
diff --git a/secure/udp/www.c b/secure/udp/www.c
new file mode 100644
index 0000000..cad4ffc
--- /dev/null
+++ b/secure/udp/www.c
@@ -0,0 +1,130 @@
+// MorgenGrauen MUDlib
+//
+// www.c -- WWW Guest Client
+//
+// $Id: www.c 8755 2014-04-26 13:13:40Z Zesstra $
+
+#pragma strong_types
+#pragma combine_strings
+
+#ifdef MORGENGRAUEN
+# include <properties.h>
+#endif
+
+#include <udp.h>
+#include <www.h>
+
+#undef DEBUG
+
+private mixed pending; // pending udp requests
+
+// HTMLunescape -- try to resolve %<hex> escape codes from HTML/WWW
+private string HTMLunescape(string char)
+{
+ int len;
+ if(!char || !(len = sizeof(char))) return "";
+ if(char[0] == '%' && len = 3) {
+ int val, ch;
+ while(--len) {
+ switch(char[len]) {
+ case '0'..'9':
+ val = (int)char[len..len];
+ break;
+ case 'A'..'F':
+ val = char[len]-55;
+ break;
+ }
+ if(len < 2) val <<= 4;
+ ch += val;
+ }
+ return sprintf("%c", ch);
+ }
+ return char;
+}
+
+private string translate(string str)
+{
+ return implode(map(regexplode(str, "[%].."), #'HTMLunescape/*'*/), "");
+}
+
+// decode() -- decode the input cmds string
+private mapping decode(string input)
+{
+ mixed tmp; int i;
+ mapping cmds;
+ cmds = ([]);
+ i = sizeof(tmp = old_explode(translate(input), "&"));
+ while(i--)
+ {
+ if(sizeof(tmp[i] = old_explode(tmp[i], "=")) == 2)
+ cmds[tmp[i][0]] = tmp[i][1];
+ }
+ return cmds;
+}
+
+// put() -- put together a key and a value
+private string put(string key, mapping val)
+{
+ return key+"="+val[key];
+}
+// encode() -- encode the input cmds string
+private string encode(mapping input)
+{ return implode(map(m_indices(input), #'put/*'*/, input), "&"); }
+
+void Send(mapping data, string text, mixed back)
+{
+ if(strstr((string)previous_object(), UDPPATH+"/")) return;
+ if(!data && !pending) return;
+ else if(!data && pending)
+ {
+ data = pending[0]; back = pending[1]; pending = 0;
+ }
+ INETD->_send_udp(data[NAME], ([
+ REQUEST: REPLY,
+ RECIPIENT: data[SENDER],
+ ID: data[ID],
+ "URL":data[DATA],
+ DATA: "\n\n"+text+"\n"
+ ]));
+}
+
+private string exch(string str, mapping to)
+{
+ if(!to[str]) return str;
+ return to[str];
+}
+
+private string xcode(string str, mapping to)
+{
+ return implode(map(regexplode(str, implode(m_indices(to), "|")),
+ #'exch/*'*/, to), "");
+}
+
+void udp_www(mapping data)
+{
+ string text, error;
+ string back; int size;
+ mapping cmds;
+ error = catch(size = sizeof(cmds = decode(data[DATA])));
+ if(cmds[BACK]) back = xcode(cmds[BACK], (["XampX":"&", "XeqX":"="]));
+ cmds[BACK] = xcode(encode(cmds-([BACK])), (["&":"XampX", "=":"XeqX"]));
+ if(error ||
+ error=catch(text=("/"+object_name(this_object())+"."+cmds[REQ])->Request(cmds)))
+ {
+#ifdef DEBUG
+ text = "<H1>Fehler: "+error+"</H1><HR><H3>Kontext:</H3>"
+ + "<PRE>"+sprintf("%O", data)+"</PRE>";
+#else
+ text = "<H1>Fehler: Anfrage konnte nicht bearbeitet werden!</H1>";
+#endif
+ log_file(WWWLOG, "ERROR: "+error[0..<2]+", DATA FOLLOWS:\n");
+ }
+ log_file(WWWLOG, sprintf("[%s] %s\n", ctime(time())[4..15], data[DATA]));
+ if(cmds[REQ] == R_INTERMUD && !text)
+ {
+ pending = ({data, back});
+ return 0;
+ }
+ pending = 0;
+ funcall(#'Send, data, text, back);
+}
diff --git a/secure/udp/www.finger.c b/secure/udp/www.finger.c
new file mode 100644
index 0000000..dbbccaf
--- /dev/null
+++ b/secure/udp/www.finger.c
@@ -0,0 +1,72 @@
+// MorgenGrauen MUDlib
+//
+// www.finger.c
+//
+// $Id: www.finger.c 8755 2014-04-26 13:13:40Z Zesstra $
+
+#pragma strong_types
+#pragma combine_strings
+
+#include <properties.h>
+#include <www.h>
+#include <regexp.h>
+
+string Request(mapping cmds)
+{
+ if(!sizeof(cmds) || !stringp(cmds[USER]))
+ return ERROR("Kein Nutzer angegeben!");
+ /*
+ * Kann ja sein, dass ein Spieler auf die Idee kommt, HTML-Tags
+ * in seine Beschreibung einzubauen. Unsere Seite ist aber schon
+ * interaktiv genug. (Anm: Nur <.*>-Vorkommnisse zu ersetzen nutzt
+ * nix, da man auch mit einzelnen Zeichen Schaden machen kann.
+ */
+ string result = regreplace(FINGER("-a "+cmds[USER]), "<","\\<",1);
+ result = regreplace(result, ">","\\>",1);
+ string *reslines = explode(result,"\n");
+ /*
+ * Grund des kommenden Codeblocks ist , dass manche Spieler ihre
+ * Homepage mit "http://mg.mud.de" angeben, andere nur"mg.mud.de"
+ * schreiben. Damit aber der Browser den Link als absolut interpretiert,
+ * muss das http:// davor stehen, und zwar nur einmal.
+ */
+ string *tmp = regexp(reslines,"^Homepage:");
+ if (sizeof(tmp)&&stringp(tmp[0])&&sizeof(tmp[0])>16) {
+ string tmp2;
+ string quoted = regreplace(tmp[0],"([[\\]+*?.\\\\])","\\\\\\1", 1);
+ if (tmp[0][10..16]=="http://")
+ tmp2=sprintf("Homepage: <A HREF=\"%s\">%s</A>",
+ tmp[0][10..],tmp[0][10..]);
+ else
+ tmp2=sprintf("Homepage: <A HREF=\"http://%s\">%s</A>",
+ tmp[0][10..],tmp[0][10..]);
+ result = regreplace(result,quoted,tmp2,1);
+ }
+ tmp = regexp(reslines,"^Avatar-URI:");
+ if (sizeof(tmp)) {
+ result = regreplace(result,
+ "Avatar-URI: ([^\n]*)",
+ "Avatar-URI: <a href=\\1>\\1</a>",1);
+ if (sizeof(regexp(({tmp[0]}),"http[s]{0,1}://",RE_PCRE))) {
+ string uri = regreplace(tmp[0], "Avatar-URI: ([^\n]*)", "\\1",1);
+ result = "<img src=\""+uri+"\" height=150 alt=\"" + capitalize(cmds[USER])
+ + "\" /><br>"
+ + result;
+ }
+ }
+
+ result = regreplace(result,
+ "E-Mail-Adresse: ([^\n]*)",
+ "E-Mail-Adresse: Bitte nachfragen...",1);
+
+ result = regreplace(result,
+ "Messenger: ([^\n]*)",
+ "Messenger: Bitte nachfragen...", 1);
+
+ result = regreplace(result,
+ "ICQ: ([^\n]*)",
+ "ICQ: Bitte nachfragen...", 1);
+
+ return "<H2>Wer ist "+capitalize(cmds[USER])+"?</H2><HR>"
+ +"<PRE>"+result+"</PRE>";
+}
diff --git a/secure/udp/www.news.c b/secure/udp/www.news.c
new file mode 100644
index 0000000..ce068db
--- /dev/null
+++ b/secure/udp/www.news.c
@@ -0,0 +1,214 @@
+// MorgenGrauen MUDlib
+//
+// www.news.c -- WWW frontend for reading mud news
+//
+// $Id: www.news.c 8755 2014-04-26 13:13:40Z Zesstra $
+
+#pragma strong_types
+#pragma combine_strings
+
+#include <www.h>
+
+#define DBG(x) tell_object(find_player("hate"), sprintf("DBG: %O\n", x))
+
+#define NEWSD "/secure/news"
+
+#define N_GROUP 0
+#define N_AUTHOR 1
+#define N_TID 2
+#define N_DATE 3
+#define N_TITLE 4
+#define N_ARTICLE 5
+
+varargs private string url(string group, string article)
+{
+ return "\""+MUDWWW+"?"+REQ+"="+R_NEWS
+ +(group?"&"+GROUP+"="+group:"")
+ +(article?"&"+ARTICLE+"="+article:"")+"\"";
+}
+
+varargs private string make_link(string text, string group, string article)
+{
+ if(!text || !sizeof(text)) text = "-Unbenannt-";
+ return "<A HREF="+url(group, article)+">"+text+"</A>";
+}
+
+string GroupList()
+{
+ string *list, ret;
+ int i, t;
+
+ list = NEWSD->GetGroups();
+ for (i = 0, ret = ""; i < sizeof(list); i++)
+ ret += sprintf("[%3d Artikel, %-6s] %s\n",
+ sizeof(NEWSD->GetNotes(list[i])),
+ dtime(t = NEWSD->GetNewsTime(list[i]))[5..11],
+ make_link(list[i],list[i]+":"+t));
+ return "<H2>Übersicht</H2>"
+ +"<H3>["+sizeof(list)+" Gruppen, "
+ +"letzte Änderung "+dtime(NEWSD->GetNewsTime())+"]</H3>"
+ +"<PRE>" + ret +"</PRE>";
+}
+
+#define THREAD(a) ("~#! rn="+(a[N_AUTHOR])+" rt="+(a[N_DATE])+ \
+ " rg="+(a[N_GROUP]))
+#define TEXPR "rn=[^\n ]*|rt=[^\n ]*|rg=[^\n ]*"
+
+private mixed tinfo(mixed article)
+{
+ mixed tmp, info;
+ string rn, rt, rg, tid;
+ int j, k;
+
+ tmp = regexp(old_explode(article[N_ARTICLE], "\n"), "^~#!");
+ for(j = sizeof(tmp); j--;) {
+ mixed line;
+ line = old_explode(tmp[j], " ");
+ for(k = sizeof(line); k--;) {
+ if(line[k][0..1]=="rn") rn = line[k][3..];
+ if(line[k][0..1]=="rt") rt = line[k][3..];
+ if(line[k][0..1]=="rg") rg = line[k][3..];
+ if(line[k][0..2]=="tid") tid = line[k][4..];
+ }
+ }
+ if(!tid) tid = ""+article[N_DATE];
+ return ({ rn, rt, rg, tid });
+}
+
+#define RN 0
+#define RT 1
+#define RG 2
+#define TID 3
+
+private int thread(mixed article, int i, mapping t)
+{
+ mixed info;
+ info = tinfo(article);
+
+ if(info[TID]) {
+ t[info[TID]]++;
+ t[info[TID], 1] = sprintf("%3.3d [%-12s %-6s]%-3s %s\n",
+ i+1,
+ article[N_AUTHOR]+":",
+ dtime(article[N_DATE])[5..11],
+ (t[info[TID]] - 1) ? "+"+(t[info[TID]]-1) : " - ",
+ make_link(article[N_TITLE],
+ article[N_GROUP], to_string(i)))
+ + (t[info[TID], 1] ? t[info[TID], 1] : "");
+ t[info[TID], 2] = info;
+ if(article[N_DATE] > to_int(t[info[TID], 3]))
+ t[info[TID], 3] = ""+article[N_DATE];
+ return 1;
+ }
+}
+
+private int expired(mixed *list, int i)
+{
+ mixed info;
+ info = tinfo(list[i]);
+ for(i--; i >= 0; i--)
+ if(list[i][N_AUTHOR] == info[RN] &&
+ list[i][N_DATE] == to_int(info[RT]))
+ return 0;
+ return 1;
+}
+
+string ArticleList(string group)
+{
+ string *list, ret;
+ mapping t;
+ int i;
+
+ list = NEWSD->GetNotes(group = old_explode(group, ":")[0]);
+ if (!pointerp(list)) {
+ return "<H2>Gruppe: "+group+"</H2>"
+ "<H3>existiert nicht.</H3>"
+ "["+make_link("Gruppenübersicht")+"]";
+ }
+ t = m_allocate(0,4);
+ for (i = sizeof(list)-1, ret = ""; i >= 0; i--)
+ if(!thread(list[i], i, t) || expired(list, i))
+ {
+ int ttmp;
+ string tid;
+ mixed tt; tt = tinfo(list[i]);
+ ttmp = t[tid = tt[TID]] - 1;
+ ret = sprintf("%3.3d [%-12s %-6s]%-3s %s\n",
+ i+1,
+ list[i][N_AUTHOR]+":",
+ dtime(list[i][N_DATE])[5..11],
+ ttmp > 0 ? "+"+ttmp : " - ",
+ make_link((string)list[i][N_TITLE]
+ +(ttmp > 0 ?
+ " ("+dtime(to_int(t[tid, 3]))[5..11]
+ +dtime(to_int(t[tid, 3]))[17..]+")" : ""),
+ group, to_string(i)+":"+t[tid, 3])) + ret;
+ }
+
+ return "<H2>Gruppe: "+group+"</H2>"
+ +"<H3>["+sizeof(list)+" Artikel, "
+ +"letzte Änderung "+dtime(NEWSD->GetNewsTime(group))+"]</H3>"
+ +"<PRE>" + ret + "</PRE>"
+ +"["+make_link("Gruppenübersicht")+"]";
+}
+
+private varargs string Message(string group, mixed article)
+{
+ mixed text, tmp, ttmp, next, prev, info;
+ string art;
+ mapping t;
+ int i;
+
+ if (!article) article = 0;
+ else article = to_int(old_explode(article, ":")[0]);
+
+ tmp = NEWSD->GetNotes(group = old_explode(group, ":")[0]);
+ if (pointerp(tmp) && (article >= sizeof(tmp)))
+ return("Artikel nicht gefunden, soviele Artikel hat diese Rubrik "
+ "nicht!\n");
+
+ text = tmp[article];
+
+ t = m_allocate(0,4);
+ for(i = sizeof(tmp)-1; i > article; i--)
+ thread(tmp[i], i, t);
+ next = "Nächster Artikel";
+ prev = "Voriger Artikel";
+
+ art = implode((ttmp = old_explode(text[N_ARTICLE], "\n"))
+ - regexp(ttmp, "^~#!"), "\n");
+
+ art = regreplace(art, "<", "\\<", 1);
+ art = regreplace(art, ">", "\\>", 1);
+ art = regreplace(art, "([a-zA-Z][a-zA-Z]*://[^ \n\t][^ \n\t]*)", "<a href=\"\\1\">\\1</a>", 1);
+
+ info = tinfo(text);
+
+ return "<H1>" + text[N_TITLE] + "</H1><HR>\n"
+ + "<H3>" + group + ": " + text[N_AUTHOR]
+ + " (Artikel " + (article + 1) + ", " + dtime(text[N_DATE]) + ")\n</H3>"
+ + (info[RN] ? ("<H4>Antwort auf "+info[RN]+
+ (expired(tmp, article) ? " (verfallen)" : "")+"</H4>")
+ : "")
+ + "<PRE>" + art + "</PRE>\n"
+ + (t[info[TID]] ?
+ "<HR>Weitere Artikel zu diesem Thema:"
+ + "<PRE>" + t[info[TID], 1] + "</PRE><HR>" : "")
+ + " ["+(article < sizeof(tmp)-1 ? make_link(next, group,to_string(article+1)) :
+ next)+"]"
+ + " ["+(article ? make_link(prev, group, to_string(article-1)) : prev)+"]"
+ + " ["+make_link("Artikelübersicht", group)+"]"
+ + " ["+make_link("Gruppenübersicht")+"]";
+}
+
+string Request(mapping cmds)
+{
+ string text;
+ if(!cmds[GROUP]) text = GroupList();
+ else
+ if(!cmds[ARTICLE]) text = ArticleList(cmds[GROUP]);
+ else text = Message(cmds[GROUP], cmds[ARTICLE]);
+
+ return "<H2>"+MUDNAME+" Zeitung</H2><HR>"
+ +text;
+}
diff --git a/secure/udp/www.who.c b/secure/udp/www.who.c
new file mode 100644
index 0000000..6646569
--- /dev/null
+++ b/secure/udp/www.who.c
@@ -0,0 +1,41 @@
+// MorgenGrauen MUDlib
+//
+// www.who.c
+//
+// $Id: www.who.c 8755 2014-04-26 13:13:40Z Zesstra $
+
+#pragma strong_types
+#pragma combine_strings
+
+#include <config.h>
+#include <properties.h>
+#include <www.h>
+
+string MakeLink(mixed entry)
+{
+ string nm;
+ int idx;
+
+ entry[1] = regreplace(entry[1], "<", "\\<", 1);
+ entry[1] = regreplace(entry[1], ">", "\\>", 1);
+ nm = getuid(entry[0]);
+ if(nm == " R O O T ") return "<TT>"+entry[1][0..2]+"</TT>"+entry[1][3..];
+ idx = strstr(lower_case(entry[1]), nm);
+ return "<TT>"+entry[1][0..2]+"</TT>"+entry[1][3..idx-1]
+ + "<A HREF=\""+MUDWWW+"?"+REQ+"="+R_FINGER+"&"+USER+"="+nm+"\"><B>"
+ + entry[1][idx..idx = idx+sizeof(nm)]
+ + "</B></A>"
+ + entry[1][idx+1..];
+}
+
+string Request(mapping cmds)
+{
+ string *who, *list; int i, s;
+ if (!sizeof(cmds)) return ERROR("Anfrage ungültig!");
+ who = allocate(s = sizeof(list = WHO));
+ for(i = s; i--; i > 0)
+ who[i] = MakeLink(list[s - i - 1]);
+ // who = map(WHO, #'MakeLink/*'*/);
+ return "<H2>Wer ist gerade in "MUDNAME"?</H2><HR>"
+ + "<OL><LI>"+implode(who, "\n<LI>")+"</OL>";
+}