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]), "<","\\&lt;",1); 
+  result = regreplace(result, ">","\\&gt;",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>&Uuml;bersicht</H2>"
+        +"<H3>["+sizeof(list)+" Gruppen, "
+        +"letzte &Auml;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&uuml;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 &Auml;nderung "+dtime(NEWSD->GetNewsTime(group))+"]</H3>"
+    +"<PRE>" + ret + "</PRE>"
+    +"["+make_link("Gruppen&uuml;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&auml;chster Artikel";
+  prev = "Voriger Artikel";
+
+  art = implode((ttmp = old_explode(text[N_ARTICLE], "\n"))
+                - regexp(ttmp, "^~#!"), "\n");
+
+  art = regreplace(art, "<", "\\&lt;", 1);
+  art = regreplace(art, ">", "\\&gt;", 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&uuml;bersicht", group)+"]"
+       + " ["+make_link("Gruppen&uuml;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], "<", "\\&lt;", 1);
+  entry[1] = regreplace(entry[1], ">", "\\&gt;", 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&uuml;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>";
+}