Index: /binary-improvements/7dtd-server-fixes/7dtd-server-fixes.csproj
===================================================================
--- /binary-improvements/7dtd-server-fixes/7dtd-server-fixes.csproj	(revision 153)
+++ /binary-improvements/7dtd-server-fixes/7dtd-server-fixes.csproj	(revision 154)
@@ -100,4 +100,14 @@
     <Compile Include="src\PersistentData\Player.cs" />
     <Compile Include="src\CustomCommands\ListKnownPlayers.cs" />
+    <Compile Include="src\NetConnections\Servers\Web\ApiHandler.cs" />
+    <Compile Include="src\NetConnections\Servers\Web\API\GetPlayersOnline.cs" />
+    <Compile Include="src\NetConnections\Servers\Web\API\WebAPI.cs" />
+    <Compile Include="src\JSON\JSONNode.cs" />
+    <Compile Include="src\JSON\JSONArray.cs" />
+    <Compile Include="src\JSON\JSONObject.cs" />
+    <Compile Include="src\JSON\JSONNumber.cs" />
+    <Compile Include="src\JSON\JSONString.cs" />
+    <Compile Include="src\JSON\JSONBoolean.cs" />
+    <Compile Include="src\NetConnections\Servers\Web\API\GetPlayersLocation.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
@@ -111,4 +121,5 @@
     <Folder Include="src\NetConnections\Servers\Web\" />
     <Folder Include="src\PersistentData\" />
+    <Folder Include="src\NetConnections\Servers\Web\API\" />
   </ItemGroup>
 </Project>
Index: /binary-improvements/7dtd-server-fixes/src/JSON/JSONArray.cs
===================================================================
--- /binary-improvements/7dtd-server-fixes/src/JSON/JSONArray.cs	(revision 154)
+++ /binary-improvements/7dtd-server-fixes/src/JSON/JSONArray.cs	(revision 154)
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace AllocsFixes.JSON
+{
+	public class JSONArray : JSONNode
+	{
+		private List<JSONNode> nodes = new List<JSONNode> ();
+
+		public void Add (JSONNode node)
+		{
+			nodes.Add(node);
+		}
+
+		public override string ToString ()
+		{
+			StringBuilder sb = new StringBuilder ("[");
+			foreach (JSONNode n in nodes) {
+				sb.Append (n.ToString ());
+				sb.Append (",");
+			}
+			if (sb.Length > 1)
+				sb.Remove (sb.Length - 1, 1);
+			sb.Append ("]");
+			return sb.ToString ();
+		}
+
+	}
+}
+
Index: /binary-improvements/7dtd-server-fixes/src/JSON/JSONBoolean.cs
===================================================================
--- /binary-improvements/7dtd-server-fixes/src/JSON/JSONBoolean.cs	(revision 154)
+++ /binary-improvements/7dtd-server-fixes/src/JSON/JSONBoolean.cs	(revision 154)
@@ -0,0 +1,21 @@
+using System;
+
+namespace AllocsFixes.JSON
+{
+	public class JSONBoolean : JSONNode
+	{
+		private bool value;
+
+		public JSONBoolean (bool value)
+		{
+			this.value = value;
+		}
+
+		public override string ToString ()
+		{
+			return value.ToString (System.Globalization.CultureInfo.InvariantCulture).ToLower ();
+		}
+
+	}
+}
+
Index: /binary-improvements/7dtd-server-fixes/src/JSON/JSONNode.cs
===================================================================
--- /binary-improvements/7dtd-server-fixes/src/JSON/JSONNode.cs	(revision 154)
+++ /binary-improvements/7dtd-server-fixes/src/JSON/JSONNode.cs	(revision 154)
@@ -0,0 +1,10 @@
+using System;
+
+namespace AllocsFixes.JSON
+{
+	public abstract class JSONNode
+	{
+		public abstract string ToString();
+	}
+}
+
Index: /binary-improvements/7dtd-server-fixes/src/JSON/JSONNumber.cs
===================================================================
--- /binary-improvements/7dtd-server-fixes/src/JSON/JSONNumber.cs	(revision 154)
+++ /binary-improvements/7dtd-server-fixes/src/JSON/JSONNumber.cs	(revision 154)
@@ -0,0 +1,21 @@
+using System;
+
+namespace AllocsFixes.JSON
+{
+	public class JSONNumber : JSONNode
+	{
+		private float value;
+
+		public JSONNumber (float value)
+		{
+			this.value = value;
+		}
+
+		public override string ToString ()
+		{
+			return value.ToString (System.Globalization.CultureInfo.InvariantCulture);
+		}
+
+	}
+}
+
Index: /binary-improvements/7dtd-server-fixes/src/JSON/JSONObject.cs
===================================================================
--- /binary-improvements/7dtd-server-fixes/src/JSON/JSONObject.cs	(revision 154)
+++ /binary-improvements/7dtd-server-fixes/src/JSON/JSONObject.cs	(revision 154)
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace AllocsFixes.JSON
+{
+	public class JSONObject : JSONNode
+	{
+		private Dictionary<string, JSONNode> nodes = new Dictionary<string, JSONNode> ();
+
+		public void Add (string name, JSONNode node)
+		{
+			nodes.Add (name, node);
+		}
+
+		public override string ToString ()
+		{
+			StringBuilder sb = new StringBuilder ("{");
+			foreach (KeyValuePair<string, JSONNode> kvp in nodes) {
+				sb.Append (String.Format ("\"{0}\":", kvp.Key));
+				sb.Append (kvp.Value.ToString ());
+				sb.Append (",");
+			}
+			if (sb.Length > 1)
+				sb.Remove (sb.Length - 1, 1);
+			sb.Append ("}");
+			return sb.ToString ();
+		}
+
+	}
+}
+
Index: /binary-improvements/7dtd-server-fixes/src/JSON/JSONString.cs
===================================================================
--- /binary-improvements/7dtd-server-fixes/src/JSON/JSONString.cs	(revision 154)
+++ /binary-improvements/7dtd-server-fixes/src/JSON/JSONString.cs	(revision 154)
@@ -0,0 +1,21 @@
+using System;
+
+namespace AllocsFixes.JSON
+{
+	public class JSONString : JSONNode
+	{
+		private string value;
+
+		public JSONString (string value)
+		{
+			this.value = value;
+		}
+
+		public override string ToString ()
+		{
+			return string.Format ("\"{0}\"", value);
+		}
+
+	}
+}
+
Index: /binary-improvements/7dtd-server-fixes/src/NetConnections/Servers/Web/API/GetPlayersLocation.cs
===================================================================
--- /binary-improvements/7dtd-server-fixes/src/NetConnections/Servers/Web/API/GetPlayersLocation.cs	(revision 154)
+++ /binary-improvements/7dtd-server-fixes/src/NetConnections/Servers/Web/API/GetPlayersLocation.cs	(revision 154)
@@ -0,0 +1,39 @@
+using AllocsFixes.JSON;
+using AllocsFixes.PersistentData;
+using System;
+using System.Collections.Generic;
+using System.Net;
+
+namespace AllocsFixes.NetConnections.Servers.Web.API
+{
+	public class GetPlayersLocation : WebAPI
+	{
+		public override void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, HttpListenerBasicIdentity user)
+		{
+			JSONArray playersJsResult = new JSONArray ();
+
+			Players playersList = PersistentContainer.Instance.Players;
+
+			foreach (string sid in playersList.SteamIDs) {
+				Player p = playersList[sid];
+
+				JSONObject pos = new JSONObject();
+				pos.Add("x", new JSONNumber(p.LastPosition.x));
+				pos.Add("y", new JSONNumber(p.LastPosition.y));
+				pos.Add("z", new JSONNumber(p.LastPosition.z));
+
+				JSONObject pJson = new JSONObject();
+				pJson.Add("steamid", new JSONString(sid));
+				pJson.Add("ip", new JSONString(p.IP));
+				pJson.Add("name", new JSONString(p.Name));
+				pJson.Add("online", new JSONBoolean(p.IsOnline));
+				pJson.Add("position", pos);
+
+				playersJsResult.Add(pJson);
+			}
+
+			WriteJSON(resp, playersJsResult);
+		}
+	}
+}
+
Index: /binary-improvements/7dtd-server-fixes/src/NetConnections/Servers/Web/API/GetPlayersOnline.cs
===================================================================
--- /binary-improvements/7dtd-server-fixes/src/NetConnections/Servers/Web/API/GetPlayersOnline.cs	(revision 154)
+++ /binary-improvements/7dtd-server-fixes/src/NetConnections/Servers/Web/API/GetPlayersOnline.cs	(revision 154)
@@ -0,0 +1,41 @@
+using AllocsFixes.JSON;
+using System;
+using System.Collections.Generic;
+using System.Net;
+
+namespace AllocsFixes.NetConnections.Servers.Web.API
+{
+	public class GetPlayersOnline : WebAPI
+	{
+		public override void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, HttpListenerBasicIdentity user)
+		{
+			JSONArray players = new JSONArray();
+
+			World w = CommonMappingFunctions.GetGameManager ().World;
+			foreach (KeyValuePair<int, EntityPlayer> current in w.playerEntities.dict) {
+				ClientInfo ci = CommonMappingFunctions.GetClientInfoFromEntityID (current.Key);
+				string ip = string.Empty;
+				if (ci != null) {
+					ip = ci.networkPlayer.ipAddress;
+				}
+
+				JSONObject pos = new JSONObject();
+				pos.Add("x", new JSONNumber((int)current.Value.GetPosition().x));
+				pos.Add("y", new JSONNumber((int)current.Value.GetPosition().y));
+				pos.Add("z", new JSONNumber((int)current.Value.GetPosition().z));
+
+				JSONObject p = new JSONObject();
+				p.Add("steamid", new JSONString(CommonMappingFunctions.GetSteamID (ci)));
+				p.Add("ip", new JSONString(ip));
+				p.Add("name", new JSONString(current.Value.EntityName));
+				p.Add("online", new JSONBoolean(true));
+				p.Add("position", pos);
+
+				players.Add(p);
+			}
+
+			WriteJSON(resp, players);
+		}
+	}
+}
+
Index: /binary-improvements/7dtd-server-fixes/src/NetConnections/Servers/Web/API/WebAPI.cs
===================================================================
--- /binary-improvements/7dtd-server-fixes/src/NetConnections/Servers/Web/API/WebAPI.cs	(revision 154)
+++ /binary-improvements/7dtd-server-fixes/src/NetConnections/Servers/Web/API/WebAPI.cs	(revision 154)
@@ -0,0 +1,21 @@
+using System;
+using System.Net;
+using System.Text;
+
+namespace AllocsFixes.NetConnections.Servers.Web.API
+{
+	public abstract class WebAPI
+	{
+		public void WriteJSON (HttpListenerResponse resp, JSON.JSONNode root)
+		{
+			byte[] buf = Encoding.UTF8.GetBytes (root.ToString());
+			resp.ContentLength64 = buf.Length;
+			resp.ContentType = "application/json";
+			resp.ContentEncoding = Encoding.UTF8;
+			resp.OutputStream.Write (buf, 0, buf.Length);
+		}
+
+		public abstract void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, HttpListenerBasicIdentity user);
+	}
+}
+
Index: /binary-improvements/7dtd-server-fixes/src/NetConnections/Servers/Web/ApiHandler.cs
===================================================================
--- /binary-improvements/7dtd-server-fixes/src/NetConnections/Servers/Web/ApiHandler.cs	(revision 154)
+++ /binary-improvements/7dtd-server-fixes/src/NetConnections/Servers/Web/ApiHandler.cs	(revision 154)
@@ -0,0 +1,48 @@
+using AllocsFixes.NetConnections.Servers.Web.API;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Net;
+using System.Threading;
+
+namespace AllocsFixes.NetConnections.Servers.Web
+{
+	public class ApiHandler : PathHandler
+	{
+		private string staticPart;
+		private Dictionary<String, WebAPI> apis = new Dictionary<string, WebAPI> ();
+
+		public ApiHandler (string staticPart)
+		{
+			this.staticPart = staticPart;
+			apis.Add ("getplayersonline", new GetPlayersOnline ());
+			apis.Add ("getplayerslocation", new GetPlayersLocation ());
+		}
+
+		public override void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, HttpListenerBasicIdentity user)
+		{
+			string apiName = req.Url.AbsolutePath.Remove (0, staticPart.Length);
+			if (!AuthorizeForCommand (apiName, user)) {
+				resp.StatusCode = (int)HttpStatusCode.Forbidden;
+			} else {
+				foreach (KeyValuePair<string, WebAPI> kvp in apis) {
+					if (apiName.StartsWith (kvp.Key)) {
+						kvp.Value.HandleRequest (req, resp, user);
+						return;
+					}
+				}
+			}
+	
+			Log.Out ("Error in ApiHandler.HandleRequest(): No handler found for API \"" + apiName + "\"");
+			resp.StatusCode = (int)HttpStatusCode.NotFound;
+		}
+
+		private bool AuthorizeForCommand (string apiName, HttpListenerBasicIdentity user)
+		{
+			return true;
+		}
+
+	}
+
+}
+
Index: /binary-improvements/7dtd-server-fixes/src/NetConnections/Servers/Web/PathHandler.cs
===================================================================
--- /binary-improvements/7dtd-server-fixes/src/NetConnections/Servers/Web/PathHandler.cs	(revision 153)
+++ /binary-improvements/7dtd-server-fixes/src/NetConnections/Servers/Web/PathHandler.cs	(revision 154)
@@ -6,5 +6,5 @@
 	public abstract class PathHandler
 	{
-		public abstract void HandleRequest(HttpListenerRequest req, HttpListenerResponse resp, HttpListenerBasicIdentity user);
+		public abstract void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, HttpListenerBasicIdentity user);
 	}
 }
Index: /binary-improvements/7dtd-server-fixes/src/NetConnections/Servers/Web/StaticHandler.cs
===================================================================
--- /binary-improvements/7dtd-server-fixes/src/NetConnections/Servers/Web/StaticHandler.cs	(revision 153)
+++ /binary-improvements/7dtd-server-fixes/src/NetConnections/Servers/Web/StaticHandler.cs	(revision 154)
@@ -34,8 +34,5 @@
 						if (!fileCache.ContainsKey (fn)) {
 							if (!File.Exists (datapath + "/" + fn)) {
-								resp.StatusCode = (int)HttpStatusCode.NotFound;
-								if (logMissingFiles)
-									Log.Out ("Web:Static:FileNotFound: \"" + req.Url.AbsolutePath + "\" @ \"" + datapath + "/" + fn + "\"");
-								return;
+								throw new FileNotFoundException ();
 							}
 
@@ -49,8 +46,5 @@
 				} else {
 					if (!File.Exists (datapath + "/" + fn)) {
-						resp.StatusCode = (int)HttpStatusCode.NotFound;
-						if (logMissingFiles)
-							Log.Out ("Web:Static:FileNotFound: \"" + req.Url.AbsolutePath + "\" @ \"" + datapath + "/" + fn + "\"");
-						return;
+						throw new FileNotFoundException ();
 					}
 
@@ -61,4 +55,9 @@
 				resp.ContentLength64 = content.Length;
 				resp.OutputStream.Write (content, 0, content.Length);
+			} catch (FileNotFoundException e) {
+				resp.StatusCode = (int)HttpStatusCode.NotFound;
+				if (logMissingFiles)
+					Log.Out ("Web:Static:FileNotFound: \"" + req.Url.AbsolutePath + "\" @ \"" + datapath + "/" + req.Url.AbsolutePath.Remove (0, staticPart.Length) + "\"");
+				return;
 			} catch (Exception e) {
 				Log.Out ("Error in StaticHandler.HandleRequest: " + e);
Index: /binary-improvements/7dtd-server-fixes/src/NetConnections/Servers/Web/Web.cs
===================================================================
--- /binary-improvements/7dtd-server-fixes/src/NetConnections/Servers/Web/Web.cs	(revision 153)
+++ /binary-improvements/7dtd-server-fixes/src/NetConnections/Servers/Web/Web.cs	(revision 154)
@@ -19,7 +19,8 @@
 					throw new NotSupportedException ("Needs Windows XP SP2, Server 2003 or later.");
  
-				handlers.Add ("/index.", new SimpleRedirectHandler ("/static/index.html"));
+				handlers.Add ("/index.htm", new SimpleRedirectHandler ("/static/index.html"));
 				handlers.Add ("/static/", new StaticHandler ("/static/", Application.dataPath + "/../webserver", false/*true*/, true)); // TODO: Enable cache
 				handlers.Add ("/map/", new StaticHandler ("/map/", StaticDirectories.GetSaveGameDir () + "/map", false, false));
+				handlers.Add ("/api/", new ApiHandler ("/api/"));
 
 				_listener.Prefixes.Add (String.Format ("http://*:{0}/", port));
@@ -53,25 +54,20 @@
 				ctx.Response.ProtocolVersion = new Version ("1.1");
 
-				HttpListenerBasicIdentity user;
+				HttpListenerBasicIdentity user = Authorize (ctx);
 
-				if (Authorize (ctx, out user)) {
-					if (ctx.Request.Url.AbsolutePath.Length < 2) {
-						handlers ["/index."].HandleRequest (ctx.Request, ctx.Response, user);
-						return;
-					} else {
-						foreach (KeyValuePair<string, PathHandler> kvp in handlers) {
-							if (ctx.Request.Url.AbsolutePath.StartsWith (kvp.Key)) {
-								kvp.Value.HandleRequest (ctx.Request, ctx.Response, user);
-								return;
-							}
+				if (ctx.Request.Url.AbsolutePath.Length < 2) {
+					handlers ["/index.htm"].HandleRequest (ctx.Request, ctx.Response, user);
+					return;
+				} else {
+					foreach (KeyValuePair<string, PathHandler> kvp in handlers) {
+						if (ctx.Request.Url.AbsolutePath.StartsWith (kvp.Key)) {
+							kvp.Value.HandleRequest (ctx.Request, ctx.Response, user);
+							return;
 						}
 					}
+				}
 
-					Log.Out ("Error in Web.HandleRequest(): No handler found for path \"" + ctx.Request.Url.AbsolutePath + "\"");
-					ctx.Response.StatusCode = (int)HttpStatusCode.NotFound;
-				} else {
-					ctx.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
-					ctx.Response.AddHeader("WWW-Authenticate", "Basic realm=\"\"");
-				}
+				Log.Out ("Error in Web.HandleRequest(): No handler found for path \"" + ctx.Request.Url.AbsolutePath + "\"");
+				ctx.Response.StatusCode = (int)HttpStatusCode.NotFound;
 
 //				byte[] buf = Encoding.UTF8.GetBytes ("Hello World");
@@ -87,14 +83,10 @@
 		}
 
-		private bool Authorize (HttpListenerContext ctx, out HttpListenerBasicIdentity user)
+		private HttpListenerBasicIdentity Authorize (HttpListenerContext ctx)
 		{
-			user = null;
-			return true;
 			try {
-				user = (HttpListenerBasicIdentity)ctx.User.Identity;
-				return user.Name.Equals ("admin") && user.Password.Equals (GamePrefs.GetString (EnumGamePrefs.ControlPanelPassword));
+				return (HttpListenerBasicIdentity)ctx.User.Identity;
 			} catch (NullReferenceException) {
-				user = null;
-				return false;
+				return null;
 			}
 		}
Index: /binary-improvements/7dtd-server-fixes/src/PersistentData/Player.cs
===================================================================
--- /binary-improvements/7dtd-server-fixes/src/PersistentData/Player.cs	(revision 153)
+++ /binary-improvements/7dtd-server-fixes/src/PersistentData/Player.cs	(revision 154)
@@ -17,4 +17,7 @@
 			lastOnline;
 		private Inventory inventory;
+		[OptionalField]
+		private int
+			lastPositionX, lastPositionY, lastPositionZ;
 		[NonSerialized]
 		private ClientInfo
@@ -82,7 +85,20 @@
 		}
 
+		public Vector3i LastPosition {
+			get {
+				if (IsOnline)
+					return new Vector3i (Entity.GetPosition ());
+				else
+					return new Vector3i (lastPositionX, lastPositionY, lastPositionZ);
+			}
+		}
+
 		public void SetOffline ()
 		{
 			Log.Out ("Player set to offline: " + steamId);
+			Vector3i lastPos = new Vector3i (Entity.GetPosition ());
+			lastPositionX = lastPos.x;
+			lastPositionY = lastPos.y;
+			lastPositionZ = lastPos.z;
 			totalPlayTime += (long)(Time.timeSinceLevelLoad - Entity.CreationTimeSinceLevelLoad);
 			lastOnline = DateTime.Now;
Index: /binary-improvements/bin/Release/7dtd-server-fixes_version.txt
===================================================================
--- /binary-improvements/bin/Release/7dtd-server-fixes_version.txt	(revision 153)
+++ /binary-improvements/bin/Release/7dtd-server-fixes_version.txt	(revision 154)
@@ -1,1 +1,1 @@
-Version:       0.91.5356.41724
+Version:       0.91.5358.38435
