Playerdata-Objekt fuer ROOT-Objekte

Da ROOT-Objekte nicht via den BACKBONEID-Mechanismus
ihre UID exportieren, konnten diese den bestehen
/obj/playerdata nicht nutzt (es hat keine ROOT-ID,
sondern die BACKBONEID bekommen).
Daher gibt es jetzt ein Objekt dafuer unter /secure/,
welches die ROOT-ID bekommt und nur von ROOT-Objekten
genutzt werden kann.

Das Objekt unter /obj/ ist funktionsidentisch, bekommt
aber aufgrund des Speicherortes in /obj/ beim Erzeugen
die UID des Erzeugers. Es kann dann von Objekten mit der
UID des Erzeugers benutzt werden.

Change-Id: Ieff3352da60b32459430fa761dbb57517691370a
diff --git a/obj/playerdata.c b/obj/playerdata.c
index a3c9c29..c4353ec 100644
--- a/obj/playerdata.c
+++ b/obj/playerdata.c
@@ -1,105 +1,26 @@
-// Dieses Ding kriegt die UID vom Clonenden.
-// Spielerladen duerfen nur Objekte, welche die gleiche UID wie der Cloner
-// (also dieses Objekt) haben.
-// Abfragen kann es nur das Objekt, welches den Spieler geladen hat.
+// Dieses Ding kann ein Spieler-Savefile laden, um dort Daten via
+// Query/QueryProp abzufragen. Sollte das Spielerobjekt existieren, wird
+// stattdessen dort gefragt.
 
-#pragma no_inherit,no_shadow
+// Das Objekt ist funktionsidentisch zum gleichnamigen Objekt unter /secure/,
+// bekommt hier aufgrund des Speicherortes (/obj/) beim Clonen/Laden
+// aber die UID vom Clonenden/Ladenden. (Ausser es ist ein ROOT-Objekt,
+// dieses exportieren ihre UID nicht. Dann ist die UID von diesem Objekt die
+// Backbone-ID STD).
+
+// Spielerladen duerfen nur Objekte, welche die gleiche UID wie dieses Objekt
+// (damit also der Erzeuger) haben.
+// Daten abfragen darf nur das Objekt, welches den Spieler auch geladen hat.
+// Damit ist sichergestellt, dass Zugriffsrechte beachtet werden.
+
+#pragma no_inherit, no_shadow
 #pragma strong_types,save_types,rtt_checks
 
-#include <config.h>
-#include <wizlevels.h>
-
-inherit "/std/thing/properties";
-
-object|string pl;
-object user;
+inherit "/secure/playerdata";
 
 protected void create()
 {
   ::create();
-  seteuid(getuid());
-  set_next_reset(300);
-}
-
-public int ReleasePlayer()
-{
-  pl = 0;
-  user = 0;
-  return 1;
-}
-
-public int LoadPlayer(string name)
-{
-  // Es duerfen nur Objekte mit der gleichen UID wie wir diesen Clone
-  // benutzen! Ansonsten koennten z.B. nicht-ROOT-Objekte einen von einem
-  // ROOT-Objekt erzeugten Clone hiervon nutzen und alles lesen...
-  if (!previous_object()
-      || getuid(previous_object()) != getuid(this_object()))
-    return 0;
-  if (query_wiz_level(getuid(previous_object())) < WIZARD_LVL)
-    return 0;
-
-  mixed userinfo=MASTER->get_userinfo(name);
-  if (!pointerp(userinfo))
-    return 0;
-  // Wenn es das Spielerobjekt gibt, ist alles gut, dann fragen wir einfach
-  // das.
-  pl = find_player(name) || find_netdead(name);
-  if (!pl)
-  {
-    // wenn nicht: Savefile einlesen.
-    restore_object(SAVEPATH + name[0..0] + "/" + name);
-    pl = name;
-  }
-  user = previous_object();
-  set_next_reset(300);
-  return 1;
-}
-
-public varargs mixed Query( string name, int Type )
-{
-  if (!user || user != previous_object())
-    return 0;
-
-  if (objectp(pl))
-    return pl->Query(name,Type);
-  else if (stringp(pl))
-    return ::Query(name, Type);
-  return 0;
-}
-
-public varargs mixed QueryProp( string name )
-{
-  if (!user || user != previous_object())
-    return 0;
-
-  if (objectp(pl))
-    return pl->QueryProp(name);
-  else if (stringp(pl))
-    return ::QueryProp(name);
-  return 0;
-}
-
-
-// kein Schreibzugriff
-public varargs mixed Set( string name, mixed Value, int Type, int extern )
-{
-  return 0;
-}
-
-public void reset()
-{
-  if (clonep(this_object()))
-    destruct(this_object());
-}
-
-public int clean_up(int ref)
-{
-  if (clonep(this_object())
-      || ref <= 1 )
-  {
-    destruct(this_object());
-  }
-  return 1;
+  replace_program();
 }
 
diff --git a/secure/playerdata.c b/secure/playerdata.c
new file mode 100644
index 0000000..d01e9bb
--- /dev/null
+++ b/secure/playerdata.c
@@ -0,0 +1,113 @@
+// Dieses Ding kann ein Spieler-Savefile laden, um dort Daten via
+// Query/QueryProp abzufragen. Sollte das Spielerobjekt existieren, wird
+// stattdessen dort gefragt.
+
+// Das Objekt hier bekommt aufgrund des Speicherortes (/secure/) die UID ROOT
+// und darf folglich alles lesen.
+
+// Spielerladen duerfen aber nur Objekte, welche die gleiche UID wie dieses
+// Objekt (damit also in diesem Fall ROOT) haben.
+// Daten abfragen darf nur das Objekt, welches den Spieler auch geladen hat.
+// Damit ist sichergestellt, dass nur ROOT-Objekt ueber *dieses* Objekt (was
+// ja ueberall lesen kann) Daten abfragen koennen.
+
+#pragma no_shadow
+#pragma strong_types,save_types,rtt_checks
+
+#include <config.h>
+#include <wizlevels.h>
+
+inherit "/std/thing/properties";
+
+object|string pl;
+object user;
+
+protected void create()
+{
+  ::create();
+  seteuid(getuid());
+  set_next_reset(300);
+}
+
+public int ReleasePlayer()
+{
+  pl = 0;
+  user = 0;
+  return 1;
+}
+
+public int LoadPlayer(string name)
+{
+  // Es duerfen nur Objekte mit der gleichen UID wie wir diesen Clone
+  // benutzen! Ansonsten koennten z.B. nicht-ROOT-Objekte einen von einem
+  // ROOT-Objekt erzeugten Clone hiervon nutzen und alles lesen...
+  if (!previous_object()
+      || getuid(previous_object()) != getuid(this_object()))
+    return 0;
+  if (query_wiz_level(getuid(previous_object())) < WIZARD_LVL)
+    return 0;
+
+  mixed userinfo=MASTER->get_userinfo(name);
+  if (!pointerp(userinfo))
+    return 0;
+  // Wenn es das Spielerobjekt gibt, ist alles gut, dann fragen wir einfach
+  // das.
+  pl = find_player(name) || find_netdead(name);
+  if (!pl)
+  {
+    // wenn nicht: Savefile einlesen.
+    restore_object(SAVEPATH + name[0..0] + "/" + name);
+    pl = name;
+  }
+  user = previous_object();
+  set_next_reset(300);
+  return 1;
+}
+
+public varargs mixed Query( string name, int Type )
+{
+  if (!user || user != previous_object())
+    return 0;
+
+  if (objectp(pl))
+    return pl->Query(name,Type);
+  else if (stringp(pl))
+    return ::Query(name, Type);
+  return 0;
+}
+
+public varargs mixed QueryProp( string name )
+{
+  if (!user || user != previous_object())
+    return 0;
+
+  if (objectp(pl))
+    return pl->QueryProp(name);
+  else if (stringp(pl))
+    return ::QueryProp(name);
+  return 0;
+}
+
+
+// kein Schreibzugriff
+public varargs mixed Set( string name, mixed Value, int Type, int extern )
+{
+  return 0;
+}
+
+public void reset()
+{
+  if (clonep(this_object()))
+    destruct(this_object());
+}
+
+public int clean_up(int ref)
+{
+  if (clonep(this_object())
+      || ref <= 1 )
+  {
+    destruct(this_object());
+  }
+  return 1;
+}
+