Changeset 244 for binary-improvements


Ignore:
Timestamp:
Jul 21, 2015, 9:51:32 PM (9 years ago)
Author:
alloc
Message:

Fixes intermediate state

Location:
binary-improvements
Files:
22 added
15 edited
5 moved

Legend:

Unmodified
Added
Removed
  • binary-improvements/7dtd-binaries/README.txt

    r238 r244  
    11Put the Assembly-CSharp.dll, Assembly-CSharp-firstpass.dll, LogLibrary.dll, mscorlib.dll,
    2 System.dll and UnityEngine.dll from your dedicated server in this folder.
     2System.dll, System.Xml.dll and UnityEngine.dll from your dedicated server in this folder.
    33
  • binary-improvements/7dtd-server-fixes/7dtd-server-fixes.csproj

    r238 r244  
    2828    <CustomCommands>
    2929      <CustomCommands>
    30         <Command type="AfterBuild" command="bash -c &quot;monodis --assembly ${TargetFile} | grep Version &gt; ${TargetDir}/${ProjectName}_version.txt&quot;" />
     30        <Command type="AfterBuild" command="bash -c &quot;${SolutionDir}/versions.sh &gt; ${TargetDir}/${ProjectName}_version.txt&quot;" workingdir="${SolutionDir}" />
    3131      </CustomCommands>
    3232    </CustomCommands>
  • binary-improvements/7dtd-server-fixes/src/AssemblyInfo.cs

    r238 r244  
    1818// and "{Major}.{Minor}.{Build}.*" will update just the revision.
    1919
    20 [assembly: AssemblyVersion("0.12.0.0")]
     20[assembly: AssemblyVersion("0.0.0.0")]
    2121
    2222// The following attributes are used to specify the signing key for the assembly,
  • binary-improvements/MapRendering/Web/API/GetLandClaims.cs

    r238 r244  
    99        public class GetLandClaims : WebAPI
    1010        {
    11                 public override void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, HttpListenerBasicIdentity user)
     11                public override void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, WebConnection user, int permissionLevel)
    1212                {
    1313                        string steamid = string.Empty;
     
    1717                                steamid = req.QueryString ["steamid"];
    1818                                if (steamid.Length != 17 || !long.TryParse (steamid, out tempLong)) {
    19                                         resp.StatusCode = (int)HttpStatusCode.InternalServerError;
     19                                        resp.StatusCode = (int)HttpStatusCode.BadRequest;
    2020                                        Web.SetResponseTextContent (resp, "Invalid SteamID given");
    2121                                        return;
  • binary-improvements/MapRendering/Web/API/GetPlayerInventory.cs

    r233 r244  
    99        public class GetPlayerInventory : WebAPI
    1010        {
    11                 public override void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, HttpListenerBasicIdentity user)
     11                public override void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, WebConnection user, int permissionLevel)
    1212                {
    1313                        if (req.QueryString ["steamid"] == null) {
  • binary-improvements/MapRendering/Web/API/GetPlayersLocation.cs

    r233 r244  
    99        public class GetPlayersLocation : WebAPI
    1010        {
    11                 public override void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, HttpListenerBasicIdentity user)
     11                public override void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, WebConnection user, int permissionLevel)
    1212                {
    1313                        JSONArray playersJsResult = new JSONArray ();
  • binary-improvements/MapRendering/Web/API/GetPlayersOnline.cs

    r233 r244  
    99        public class GetPlayersOnline : WebAPI
    1010        {
    11                 public override void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, HttpListenerBasicIdentity user)
     11                public override void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, WebConnection user, int permissionLevel)
    1212                {
    1313                        JSONArray players = new JSONArray();
  • binary-improvements/MapRendering/Web/API/WebAPI.cs

    r230 r244  
    1616                }
    1717
    18                 public abstract void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, HttpListenerBasicIdentity user);
     18                public abstract void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, WebConnection user, int permissionLevel);
    1919        }
    2020}
  • binary-improvements/MapRendering/Web/Handlers/ApiHandler.cs

    r230 r244  
    66using System.Threading;
    77
    8 namespace AllocsFixes.NetConnections.Servers.Web
     8namespace AllocsFixes.NetConnections.Servers.Web.Handlers
    99{
    10         public class ApiHandler : PathHandler
    11         {
     10        public class ApiHandler : PathHandler {
    1211                private string staticPart;
    1312                private Dictionary<String, WebAPI> apis = new Dictionary<string, WebAPI> ();
    1413
    15                 public ApiHandler (string staticPart)
    16                 {
     14                public ApiHandler (string staticPart, string moduleName = null) : base(moduleName) {
    1715                        this.staticPart = staticPart;
    18                         apis.Add ("getlandclaims", new GetLandClaims ());
    19                         apis.Add ("getplayersonline", new GetPlayersOnline ());
    20                         apis.Add ("getplayerslocation", new GetPlayersLocation ());
    21                         apis.Add ("getplayerinventory", new GetPlayerInventory ());
     16                        addApi ("getlandclaims", new GetLandClaims ());
     17                        addApi ("getplayersonline", new GetPlayersOnline ());
     18                        addApi ("getplayerslocation", new GetPlayersLocation ());
     19                        addApi ("getplayerinventory", new GetPlayerInventory ());
     20                        addApi ("getstats", new GetStats ());
    2221                }
    2322
    24                 public override void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, HttpListenerBasicIdentity user)
    25                 {
     23                private void addApi (string _apiName, WebAPI _api) {
     24                        apis.Add (_apiName, _api);
     25                        WebPermissions.Instance.AddKnownModule ("webapi." + _apiName);
     26                }
     27
     28                public override void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, WebConnection user, int permissionLevel) {
    2629                        string apiName = req.Url.AbsolutePath.Remove (0, staticPart.Length);
    27                         if (!AuthorizeForCommand (apiName, user)) {
     30                        if (!AuthorizeForCommand (apiName, user, permissionLevel)) {
    2831                                resp.StatusCode = (int)HttpStatusCode.Forbidden;
     32                                if (user != null) {
     33                                        Log.Out ("ApiHandler: user '{0}' not allowed to execute '{1}'", user.SteamID, apiName);
     34                                } else {
     35                                        Log.Out ("ApiHandler: unidentified user from '{0}' not allowed to execute '{1}'", req.RemoteEndPoint.Address, apiName);
     36                                }
     37                                return;
    2938                        } else {
    3039                                foreach (KeyValuePair<string, WebAPI> kvp in apis) {
    3140                                        try {
    3241                                                if (apiName.StartsWith (kvp.Key)) {
    33                                                         kvp.Value.HandleRequest (req, resp, user);
     42                                                        kvp.Value.HandleRequest (req, resp, user, permissionLevel);
    3443                                                        return;
    3544                                                }
     
    4655                }
    4756
    48                 private bool AuthorizeForCommand (string apiName, HttpListenerBasicIdentity user)
    49                 {
    50                         return true;
     57                private bool AuthorizeForCommand (string apiName, WebConnection user, int permissionLevel) {
     58                        return WebPermissions.Instance.ModuleAllowedWithLevel ("webapi." + apiName, permissionLevel);
    5159                }
    5260
  • binary-improvements/MapRendering/Web/Handlers/ItemIconHandler.cs

    r242 r244  
    77using UnityEngine;
    88
    9 namespace AllocsFixes.NetConnections.Servers.Web
     9namespace AllocsFixes.NetConnections.Servers.Web.Handlers
    1010{
    1111        public class ItemIconHandler : PathHandler
     
    1616                private bool loaded = false;
    1717
    18                 public ItemIconHandler (string staticPart, bool logMissingFiles) {
     18                public ItemIconHandler (string staticPart, bool logMissingFiles, string moduleName = null) : base(moduleName) {
    1919                        this.staticPart = staticPart;
    2020                        this.logMissingFiles = logMissingFiles;
    2121                }
    2222
    23                 public override void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, HttpListenerBasicIdentity user) {
     23                public override void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, WebConnection user, int permissionLevel) {
    2424                        if (!loaded) {
    2525                                if (!LoadIcons ()) {
  • binary-improvements/MapRendering/Web/Handlers/PathHandler.cs

    r230 r244  
    22using System.Net;
    33
    4 namespace AllocsFixes.NetConnections.Servers.Web
     4namespace AllocsFixes.NetConnections.Servers.Web.Handlers
    55{
    66        public abstract class PathHandler
    77        {
    8                 public abstract void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, HttpListenerBasicIdentity user);
     8                private string moduleName = null;
     9                public string ModuleName {
     10                        get { return moduleName; }
     11                }
     12
     13                protected PathHandler (string _moduleName) {
     14                        this.moduleName = _moduleName;
     15                        WebPermissions.Instance.AddKnownModule (_moduleName);
     16                }
     17
     18                public abstract void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, WebConnection user, int permissionLevel);
     19
     20                public bool IsAuthorizedForHandler (WebConnection user, int permissionLevel) {
     21                        if (moduleName != null) {
     22                                return WebPermissions.Instance.ModuleAllowedWithLevel (moduleName, permissionLevel);
     23                        } else {
     24                                return true;
     25                        }
     26                }
    927        }
    1028}
  • binary-improvements/MapRendering/Web/Handlers/SimpleRedirectHandler.cs

    r230 r244  
    22using System.Net;
    33
    4 namespace AllocsFixes.NetConnections.Servers.Web
     4namespace AllocsFixes.NetConnections.Servers.Web.Handlers
    55{
    66        public class SimpleRedirectHandler : PathHandler
     
    88                string target;
    99
    10                 public SimpleRedirectHandler (string target)
     10                public SimpleRedirectHandler (string target, string moduleName = null) : base(moduleName)
    1111                {
    1212                        this.target = target;
    1313                }
    1414
    15                 public override void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, HttpListenerBasicIdentity user)
     15                public override void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, WebConnection user, int permissionLevel)
    1616                {
    1717                        resp.Redirect (target);
  • binary-improvements/MapRendering/Web/Handlers/StaticHandler.cs

    r230 r244  
    55using System.Threading;
    66
    7 namespace AllocsFixes.NetConnections.Servers.Web
     7namespace AllocsFixes.NetConnections.Servers.Web.Handlers
    88{
    99        public class StaticHandler : PathHandler
     
    1414                private bool logMissingFiles;
    1515
    16                 public StaticHandler (string staticPart, string filePath, AllocsFixes.FileCache.AbstractCache cache, bool logMissingFiles)
     16                public StaticHandler (string staticPart, string filePath, AllocsFixes.FileCache.AbstractCache cache, bool logMissingFiles, string moduleName = null) : base(moduleName)
    1717                {
    1818                        this.staticPart = staticPart;
     
    2222                }
    2323
    24                 public override void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, HttpListenerBasicIdentity user)
     24                public override void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, WebConnection user, int permissionLevel)
    2525                {
    2626                        string fn = req.Url.AbsolutePath.Remove (0, staticPart.Length);
  • binary-improvements/MapRendering/Web/Web.cs

    r238 r244  
    11using System;
    22using System.Collections.Generic;
     3using System.Collections.Specialized;
    34using System.IO;
    45using System.Net;
     
    910using UnityEngine;
    1011
     12using AllocsFixes.NetConnections.Servers.Web.Handlers;
     13
    1114namespace AllocsFixes.NetConnections.Servers.Web
    1215{
    1316        public class Web : IConsoleServer {
     17                private const int GUEST_PERMISSION_LEVEL = 2000;
    1418                private readonly HttpListener _listener = new HttpListener ();
    1519                private Dictionary<string, PathHandler> handlers = new Dictionary<string, PathHandler> ();
    16                 private bool authEnabled = false;
    17                 private string realm = "7dtd Admin Panel";
    1820                public static int handlingCount = 0;
    1921                public static int currentHandlers = 0;
    2022                private string dataFolder;
    21                 private bool mapEnabled = false;
     23                private bool useStaticCache = false;
     24
     25                public bool isSslRedirected {
     26                        private set;
     27                        get;
     28                }
     29
     30                public ConnectionHandler connectionHandler;
    2231
    2332                public Web () {
     
    2534                                int webPort = GamePrefs.GetInt (EnumGamePrefs.ControlPanelPort);
    2635                                if (webPort < 1 || webPort > 65533) {
    27                                         Log.Out ("Webserver not started (ControlPanelPort not within 1-65534)");
     36                                        Log.Out ("Webserver not started (ControlPanelPort not within 1-65533)");
    2837                                        return;
    2938                                }
     
    3342                                }
    3443
     44                                // TODO: Read from config
     45                                isSslRedirected = false;
     46                                useStaticCache = false;
     47
    3548                                dataFolder = Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location) + "/webserver";
    3649
     
    4760                                                new SimpleRedirectHandler ("/static/favicon.ico"));
    4861                                handlers.Add (
    49                                                 "/static/",
    50                                                 new StaticHandler (
    51                                                                 "/static/",
    52                                                                 dataFolder,
    53                                                                 new AllocsFixes.FileCache.DirectAccess (),
    54                                                                 true)
    55                                 ); // TODO: Enable cache
     62                                                "/session/",
     63                                                new SessionHandler (
     64                                                                        "/session/",
     65                                                                        dataFolder,
     66                                                                        this)
     67                                );
     68                                handlers.Add (
     69                                                "/userstatus",
     70                                                new UserStatusHandler ()
     71                                );
     72                                if (useStaticCache) {
     73                                        handlers.Add (
     74                                                        "/static/",
     75                                                        new StaticHandler (
     76                                                                        "/static/",
     77                                                                        dataFolder,
     78                                                                        new AllocsFixes.FileCache.SimpleCache (),
     79                                                                        true)
     80                                        );
     81                                } else {
     82                                        handlers.Add (
     83                                                        "/static/",
     84                                                        new StaticHandler (
     85                                                                        "/static/",
     86                                                                        dataFolder,
     87                                                                        new AllocsFixes.FileCache.DirectAccess (),
     88                                                                        true)
     89                                        );
     90                                }
    5691
    5792                                handlers.Add (
     
    68103                                                GameUtils.GetSaveGameDir () + "/map",
    69104                                                MapRendering.MapRendering.GetTileCache (),
    70                                                 false)
    71                                 );
    72 
    73                                 handlers.Add ("/api/", new ApiHandler ("/api/"));
     105                                                false,
     106                                                "web.map")
     107                                );
     108
     109                                handlers.Add (
     110                                        "/api/",
     111                                        new ApiHandler ("/api/")
     112                                );
     113
     114                                connectionHandler = new ConnectionHandler (this);
    74115
    75116                                _listener.Prefixes.Add (String.Format ("http://*:{0}/", webPort + 2));
    76                                 authEnabled = File.Exists (dataFolder + "/protect");
    77                                 if (authEnabled) {
    78                                         _listener.AuthenticationSchemes = AuthenticationSchemes.Basic;
    79                                 }
    80117                                _listener.Start ();
    81                                 _listener.Realm = realm;
    82118
    83119                                SdtdConsole.Instance.RegisterServer (this);
     
    85121                                _listener.BeginGetContext (new AsyncCallback (HandleRequest), _listener);
    86122
    87                                 Log.Out ("Started Webserver on " + (webPort + 2) + " (authentication " + (authEnabled ? "enabled" : "disabled") + ")");
     123                                Log.Out ("Started Webserver on " + (webPort + 2));
    88124                        } catch (Exception e) {
    89125                                Log.Out ("Error in Web.ctor: " + e);
     
    98134                                _listener.BeginGetContext (new AsyncCallback (HandleRequest), _listener);
    99135                                try {
    100                                         ctx.Response.ProtocolVersion = new Version ("1.0");
    101 
    102                                         HttpListenerBasicIdentity user = Authorize (ctx);
    103 
    104                                         if (!authEnabled || (user.Name.ToLower ().Equals ("admin") && user.Password.Equals (GamePrefs.GetString (EnumGamePrefs.ControlPanelPassword)))) {
    105                                                 if (ctx.Request.Url.AbsolutePath.Length < 2) {
    106                                                         handlers ["/index.htm"].HandleRequest (ctx.Request, ctx.Response, user);
    107                                                         return;
    108                                                 } else {
    109                                                         foreach (KeyValuePair<string, PathHandler> kvp in handlers) {
    110                                                                 if (ctx.Request.Url.AbsolutePath.StartsWith (kvp.Key)) {
    111                                                                         kvp.Value.HandleRequest (ctx.Request, ctx.Response, user);
    112                                                                         return;
     136                                        HttpListenerRequest request = ctx.Request;
     137                                        HttpListenerResponse response = ctx.Response;
     138
     139                                        response.ProtocolVersion = new Version ("1.1");
     140
     141                                        WebConnection conn;
     142                                        int permissionLevel = DoAuthentication (request, out conn);
     143
     144
     145                                        //Log.Out ("Login status: conn!=null: {0}, permissionlevel: {1}", conn != null, permissionLevel);
     146
     147
     148                                        if (conn != null) {
     149                                                Cookie cookie = new Cookie ("sid", conn.SessionID, "/");
     150                                                cookie.Expired = false;
     151                                                cookie.Expires = new DateTime (2020, 1, 1);
     152                                                cookie.HttpOnly = true;
     153                                                cookie.Secure = false;
     154                                                response.AppendCookie (cookie);
     155                                        }
     156
     157                                        if (request.Url.AbsolutePath.Length < 2) {
     158                                                handlers ["/index.htm"].HandleRequest (request, response, conn, permissionLevel);
     159                                                return;
     160                                        } else {
     161                                                foreach (KeyValuePair<string, PathHandler> kvp in handlers) {
     162                                                        if (request.Url.AbsolutePath.StartsWith (kvp.Key)) {
     163                                                                if (!kvp.Value.IsAuthorizedForHandler (conn, permissionLevel)) {
     164                                                                        response.StatusCode = (int)HttpStatusCode.Forbidden;
     165                                                                        if (conn != null) {
     166                                                                                Log.Out ("Web.HandleRequest: user '{0}' not allowed to access '{1}'", conn.SteamID, kvp.Value.ModuleName);
     167                                                                        } else {
     168                                                                                Log.Out ("Web.HandleRequest: unidentified user from '{0}' not allowed to access '{1}'", request.RemoteEndPoint.Address, kvp.Value.ModuleName);
     169                                                                        }
     170                                                                } else {
     171                                                                        kvp.Value.HandleRequest (request, response, conn, permissionLevel);
    113172                                                                }
     173                                                                return;
    114174                                                        }
    115175                                                }
    116 
    117                                                 Log.Out ("Error in Web.HandleRequest(): No handler found for path \"" + ctx.Request.Url.AbsolutePath + "\"");
    118                                                 ctx.Response.StatusCode = (int)HttpStatusCode.NotFound;
    119                                         } else {
    120                                                 ctx.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
    121                                                 ctx.Response.Headers ["WWW-Authenticate"] = "Basic realm=\"" + realm + "\"";
    122                                         }
     176                                        }
     177
     178                                        Log.Out ("Error in Web.HandleRequest(): No handler found for path \"" + request.Url.AbsolutePath + "\"");
     179                                        response.StatusCode = (int)HttpStatusCode.NotFound;
    123180                                } catch (IOException e) {
    124181                                        if (e.InnerException is SocketException) {
     
    131188                                } finally {
    132189                                        if (ctx != null) {
    133                                                 ctx.Response.OutputStream.Close ();
     190                                                ctx.Response.Close ();
    134191                                        }
    135192                                        Interlocked.Decrement (ref currentHandlers);
     
    138195                }
    139196
    140                 private HttpListenerBasicIdentity Authorize (HttpListenerContext ctx) {
    141                         try {
    142                                 return (HttpListenerBasicIdentity)ctx.User.Identity;
    143                         } catch (NullReferenceException) {
    144                                 return null;
    145                         }
     197                private int DoAuthentication (HttpListenerRequest _req, out WebConnection _con) {
     198                        _con = null;
     199
     200                        string sessionId = null;
     201                        if (_req.Cookies ["sid"] != null) {
     202                                sessionId = _req.Cookies ["sid"].Value;
     203                        }
     204
     205                        if (!string.IsNullOrEmpty (sessionId)) {
     206                                WebConnection con = connectionHandler.IsLoggedIn (sessionId, _req.RemoteEndPoint.Address.ToString ());
     207                                if (con != null) {
     208                                        _con = con;
     209                                        return GameManager.Instance.adminTools.GetAdminToolsClientInfo (_con.SteamID.ToString ()).PermissionLevel;
     210                                }
     211                        }
     212
     213                        if (_req.QueryString ["adminuser"] != null && _req.QueryString ["admintoken"] != null) {
     214                                WebPermissions.AdminToken admin = WebPermissions.Instance.GetWebAdmin (_req.QueryString ["adminuser"], _req.QueryString ["admintoken"]);
     215                                if (admin != null) {
     216                                        return admin.permissionLevel;
     217                                } else {
     218                                        Log.Warning ("Invalid Admintoken used from " + _req.RemoteEndPoint.ToString ());
     219                                }
     220                        }
     221
     222                        if (_req.Url.AbsolutePath.StartsWith ("/session/verify")) {
     223                                ulong id = OpenID.Validate (_req);
     224                                if (id > 0) {
     225                                        WebConnection con = connectionHandler.LogIn (id, _req.RemoteEndPoint.Address.ToString ());
     226                                        _con = con;
     227                                        //Log.Out ("Logged in with session id: {0}", con.SessionID);
     228                                        return GameManager.Instance.adminTools.GetAdminToolsClientInfo (id.ToString ()).PermissionLevel;
     229                                } else {
     230                                        Log.Out ("Steam OpenID login failed from {0}", _req.RemoteEndPoint.ToString ());
     231                                }
     232                        }
     233
     234                        return GUEST_PERMISSION_LEVEL;
    146235                }
    147236
     
    156245
    157246                public void SendLine (string line) {
    158                         try {
    159                                 //Log.Out ("NOT IMPLEMENTED: Web.WriteToClient");
    160                         } catch (Exception e) {
    161                                 Log.Out ("Error in Web.WriteToClient: " + e);
    162                         }
     247                        connectionHandler.SendLine (line);
    163248                }
    164249
    165250                public void SendLog (string text, string trace, UnityEngine.LogType type) {
    166                         //throw new System.NotImplementedException ();
     251                        connectionHandler.SendLog (text, trace, type);
    167252                }
    168253
  • binary-improvements/MapRendering/WebAndMapRendering.csproj

    r238 r244  
    3838      <Private>False</Private>
    3939    </Reference>
     40    <Reference Include="System.Xml">
     41      <HintPath>..\7dtd-binaries\System.Xml.dll</HintPath>
     42      <Private>False</Private>
     43    </Reference>
    4044  </ItemGroup>
    4145  <ItemGroup>
     
    4852    <Compile Include="API.cs" />
    4953    <Compile Include="Web\Web.cs" />
    50     <Compile Include="Web\PathHandler.cs" />
    51     <Compile Include="Web\StaticHandler.cs" />
    52     <Compile Include="Web\SimpleRedirectHandler.cs" />
    5354    <Compile Include="Web\MimeType.cs" />
    54     <Compile Include="Web\ApiHandler.cs" />
    5555    <Compile Include="Web\API\GetPlayersOnline.cs" />
    5656    <Compile Include="Web\API\WebAPI.cs" />
     
    5959    <Compile Include="Web\API\GetLandClaims.cs" />
    6060    <Compile Include="Commands\webstat.cs" />
    61     <Compile Include="Web\ItemIconHandler.cs" />
     61    <Compile Include="Web\API\GetStats.cs" />
     62    <Compile Include="Web\WebConnection.cs" />
     63    <Compile Include="Web\OpenID.cs" />
     64    <Compile Include="Web\ConnectionHandler.cs" />
     65    <Compile Include="Web\WebPermissions.cs" />
     66    <Compile Include="Web\Handlers\ApiHandler.cs" />
     67    <Compile Include="Web\Handlers\ItemIconHandler.cs" />
     68    <Compile Include="Web\Handlers\PathHandler.cs" />
     69    <Compile Include="Web\Handlers\SimpleRedirectHandler.cs" />
     70    <Compile Include="Web\Handlers\StaticHandler.cs" />
     71    <Compile Include="Web\Handlers\SessionHandler.cs" />
     72    <Compile Include="Web\API\ExecuteConsoleCommand.cs" />
     73    <Compile Include="Commands\ReloadWebPermissions.cs" />
     74    <Compile Include="Web\Handlers\UserStatusHandler.cs" />
     75    <Compile Include="Commands\WebTokens.cs" />
     76    <Compile Include="Commands\WebPermissionsCmd.cs" />
    6277  </ItemGroup>
    6378  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
     
    7186  <ItemGroup>
    7287    <Folder Include="Commands\" />
     88    <Folder Include="Web\Handlers\" />
    7389  </ItemGroup>
    7490  <ItemGroup>
  • binary-improvements/bundle_creation/makefile

    r238 r244  
    44
    55VERSIONFILE=../bin/Mods/Allocs_CommonFunc/7dtd-server-fixes_version.txt
    6 VERSION=$(shell cat ${VERSIONFILE} | grep "Version" | cut -d\  -f8)
     6VERSION=$(shell cat ${VERSIONFILE} | grep "Combined" | cut -d\  -f2)
    77ARCHIVENAME=server_fixes_v${VERSION}.tar.gz
    88
  • binary-improvements/server-fixes.userprefs

    r240 r244  
    11<Properties>
    22  <MonoDevelop.Ide.Workspace ActiveConfiguration="Release_Version" />
    3   <MonoDevelop.Ide.Workbench ActiveDocument="MapRendering/Web/ApiHandler.cs">
     3  <MonoDevelop.Ide.Workbench ActiveDocument="7dtd-server-fixes/src/AssemblyInfo.cs">
    44    <Files>
    55      <File FileName="MapRendering/MapRendering/Constants.cs" Line="1" Column="1" />
    6       <File FileName="7dtd-server-fixes/src/PersistentData/Player.cs" Line="130" Column="40" />
    76      <File FileName="7dtd-server-fixes/src/AssemblyInfo.cs" Line="20" Column="35" />
    8       <File FileName="7dtd-server-fixes/ModInfo.xml" Line="7" Column="20" />
     7      <File FileName="7dtd-server-fixes/ModInfo.xml" Line="2" Column="6" />
    98      <File FileName="AllocsCommands/ModInfo.xml" Line="7" Column="20" />
    109      <File FileName="MapRendering/ModInfo.xml" Line="7" Column="20" />
    11       <File FileName="MapRendering/Web/ApiHandler.cs" Line="31" Column="3" />
    12       <File FileName="7dtd-server-fixes/src/API.cs" Line="12" Column="29" />
     10      <File FileName="MapRendering/Web/Web.cs" Line="245" Column="3" />
     11      <File FileName="MapRendering/Web/WebPermissions.cs" Line="156" Column="25" />
     12      <File FileName="MapRendering/Web/Handlers/SessionHandler.cs" Line="16" Column="123" />
     13      <File FileName="MapRendering/Web/Handlers/ApiHandler.cs" Line="34" Column="1" />
     14      <File FileName="MapRendering/Web/API/ExecuteConsoleCommand.cs" Line="36" Column="114" />
    1315    </Files>
    1416    <Pads>
  • binary-improvements/webserver/css/style.css

    r179 r244  
    1 html, body {
    2         height: 100%;
    3         margin: 0px;
    4         padding: 0px;
    5         background-color: #230000;
     1/* Generic page layout */
     2
     3body {
     4        margin: 0;
     5        padding: 0;
    66}
    7 #map {
    8         height: 100%;
    9         margin: 0px;
    10         padding: 0px;
    11         background-color: #230000;
     7
     8.adminwrapper {
     9        width: 100%;
     10        height: 100vh;
     11        background-color: #ccc;
    1212}
     13
     14.adminmenu,
     15.admincontent {
     16        position: absolute;
     17        top: 0;
     18        bottom: 0;
     19}
     20
     21.adminmenu {
     22        width: 200px;
     23        left: 0;
     24        background-color: purple;
     25}
     26
     27.adminmenu .current_tab {
     28        font-weight: bold;
     29        text-transform: uppercase;
     30}
     31
     32.adminmenu .menu_button a {
     33        color: #000;
     34}
     35
     36.adminmenu #userstate {
     37        position: absolute;
     38        bottom: 5px;
     39        left: 5px;
     40        right: 5px;
     41        background-color: green;
     42}
     43
     44.adminmenu #userstate #username {
     45        padding-left: 10px;
     46}
     47
     48.adminmenu #userstate > div {
     49        display: none;
     50}
     51
     52.admincontent {
     53        position: absolute;
     54        right: 0;
     55        left: 200px;
     56        background-color: #fff;
     57}
     58
     59.admincontent .contenttab {
     60        position: absolute;
     61        top: 0;
     62        right: 0;
     63        left: 0px;
     64        display: none;
     65}
     66
     67.admincontent .current_tab {
     68        display: block;
     69}
     70
     71/* Individual tabs */
     72
     73.adminmap {
     74        background-color: #260040;
     75        bottom: 0;
     76}
     77
     78
     79
     80/* Inventory dialog overlay */
     81
    1382#info {
    1483        background-color: #aaaaaa;
     
    2594}
    2695.invField {
    27         width: 60px;
    28         height: 42px;
     96        width: 58px;
     97        height: 40px;
    2998        padding: 1px 4px;
    3099        margin: 0px;
     
    58127}
    59128
    60 .control-reloadtiles a,
    61 .control-reloadtiles a:hover {
    62         padding: 1px 5px 1px 5px;
    63         width: auto;
     129
     130/* Map controls */
     131
     132
     133.webmap-control a,
     134.webmap-control a:hover {
     135        text-decoration: none;
    64136}
    65137
    66 .control-coordinates {
     138.webmap-control {
    67139        box-shadow: 0 1px 5px rgba(0,0,0,0.4);
    68140        background: #fff;
     
    70142        padding: 6px 10px 6px 6px;
    71143        color: #333;
     144        white-space: nowrap;
    72145}
    73146
  • binary-improvements/webserver/index.html

    r179 r244  
    2828        <link rel="stylesheet" href="leaflet/minimap/Control.MiniMap.css" />
    2929        <script type="text/javascript" src="leaflet/minimap/Control.MiniMap.js"></script>
     30       
     31        <!-- Own JS stuff -->
     32        <script type="text/javascript" src="js/leaflet.regionlayer.js"></script>
     33        <script type="text/javascript" src="js/leaflet.control.coordinates.js"></script>
     34        <script type="text/javascript" src="js/leaflet.control.reloadtiles.js"></script>
     35        <script type="text/javascript" src="js/leaflet.control.gametime.js"></script>
     36        <script type="text/javascript" src="js/util.js"></script>
    3037
    3138        <!-- Own stylesheet -->
     
    3441</head>
    3542<body>
    36         <div id="map"></div>
     43
     44
     45        <div class="adminwrapper">
     46                <div class="adminmenu">
     47                        <ul>
     48                                <li><a href="#tab_map" data-permission="web.map">Map</a></li>
     49                                <li><a href="#tab_log" data-permission="web.log">Log</a></li>
     50                        </ul>
     51                       
     52                        <div id="userstate">
     53                                <div id="userstate_loggedin">
     54                                        Logged in as:<br/>
     55                                        <a id="username" href="" target="_blank"></a><br/>
     56                                        <a href="/session/logout">Sign out</a>
     57                                </div>
     58                                <div id="userstate_loggedout">
     59                                        Not logged in<br/>
     60                                        <center>
     61                                        <a href="/session/login">
     62                                                <img src="img/steamlogin.png" title="Sign in through Steam">
     63                                        </a>
     64                                        </center>
     65                                </div>
     66                        </div>
     67                </div>
     68                <div class="admincontent">
     69                        <div id="tab_map" class="adminmap"></div>
     70                        <div id="tab_log" class="adminlog"></div>
     71                </div>
     72        </div>
     73       
     74
    3775        <div id="playerInventoryDialog" title="Player inventory">
    3876                Player: <span id="invPlayerName"></span>
     
    4381                </table>
    4482        </div>
    45 
     83       
    4684        <script type="text/javascript" src="js/index.js"></script>
    4785</body>
    4886</html>
     87
  • binary-improvements/webserver/js/index.js

    r243 r244  
    22// Constants
    33
    4 var REGIONSIZE = 512;
    5 var CHUNKSIZE = 16;
    6 var TILESIZE = 128;
    7 var MAXZOOM = 4;
     4var mapinfo = {
     5        regionsize: 512,
     6        chunksize: 16,
     7        tilesize: 128,
     8        maxzoom: 4
     9}
    810
    911var BAG_COLS = 8;
     
    1315var INV_ITEM_HEIGHT = 40;
    1416
     17var userdata = false;
     18
    1519
    1620function initMap() {
     
    2125                project: function (latlng) {
    2226                        return new L.Point(
    23                                 (latlng.lat) / Math.pow(2, MAXZOOM),
    24                                 (latlng.lng) / Math.pow(2, MAXZOOM) );
     27                                (latlng.lat) / Math.pow(2, mapinfo.maxzoom),
     28                                (latlng.lng) / Math.pow(2, mapinfo.maxzoom) );
    2529                },
    2630               
    2731                unproject: function (point) {
    2832                        return new L.LatLng(
    29                                 point.x * Math.pow(2, MAXZOOM),
    30                                 point.y * Math.pow(2, MAXZOOM) );
     33                                point.x * Math.pow(2, mapinfo.maxzoom),
     34                                point.y * Math.pow(2, mapinfo.maxzoom) );
    3135                }
    3236        };
     
    4145        });
    4246
    43         var CoordToChunk = function(latlng) {
    44                 var x = Math.floor(((latlng.lat + 16777216) / CHUNKSIZE) - (16777216 / CHUNKSIZE));
    45                 var y = Math.floor(((latlng.lng + 16777216) / CHUNKSIZE) - (16777216 / CHUNKSIZE));
    46                 return L.latLng(x, y);
    47         }
    48 
    49         var CoordToRegion = function(latlng) {
    50                 var x = Math.floor(((latlng.lat + 16777216) / REGIONSIZE) - (16777216 / REGIONSIZE));
    51                 var y = Math.floor(((latlng.lng + 16777216) / REGIONSIZE) - (16777216 / REGIONSIZE));
    52                 return L.latLng(x, y);
    53         }
    54 
    55         var FormatCoord = function(latlng) {
    56                 return "" +
    57                         Math.abs(latlng.lng) + (latlng.lng>=0 ? " N" : " S") + " / " +
    58                         Math.abs(latlng.lat) + (latlng.lat>=0 ? " E" : " W");
    59         }
    60 
    61         var FormatRegionFileName = function(latlng) {
    62                 return "r." + latlng.lat + "." + latlng.lng + ".7rg";
    63         }
    6447
    6548
     
    6851        // Map and basic tile layers
    6952
    70         var tileTime = new Date().getTime();
    71 
    72         map = L.map('map', {
     53        var initTime = new Date().getTime();
     54
     55        map = L.map('tab_map', {
    7356                zoomControl: false, // Added by Zoomslider
    7457                zoomsliderControl: true,
    7558                attributionControl: false,
    7659                crs: SDTD_CRS
    77         }).setView([0, 0], Math.max(0, MAXZOOM-5));
     60        }).setView([0, 0], Math.max(0, mapinfo.maxzoom - 5));
    7861
    7962        var tileLayer = L.tileLayer('../map/{z}/{x}/{y}.png?t={time}', {
    80                 maxZoom:MAXZOOM+1,
    81                 minZoom: Math.max(0, MAXZOOM-5),
    82                 maxNativeZoom: MAXZOOM,
    83                 tileSize: TILESIZE,
     63                maxZoom: mapinfo.maxzoom + 1,
     64                minZoom: Math.max(0, mapinfo.maxzoom - 5),
     65                maxNativeZoom: mapinfo.maxzoom,
     66                tileSize: mapinfo.tilesize,
    8467                continuousWorld: true,
    8568                tms: true,
    8669                unloadInvisibleTiles: false,
    87                 time: function() { return tileTime; }
    88         }).addTo(map);
     70                time: initTime
     71        });
    8972       
    9073        // TileLayer w/ TMS=true fix for zoomlevel >= 8
     
    9477
    9578        var tileLayerMiniMap = L.tileLayer('../map/{z}/{x}/{y}.png?t={time}', {
    96                 maxZoom: MAXZOOM,
     79                maxZoom: mapinfo.maxzoom,
    9780                minZoom: 0,
    98                 maxNativeZoom: MAXZOOM,
    99                 tileSize: TILESIZE,
     81                maxNativeZoom: mapinfo.maxzoom,
     82                tileSize: mapinfo.tilesize,
    10083                continuousWorld: true,
    10184                tms: true,
    10285                unloadInvisibleTiles: false,
    103                 time: function() { return tileTime; }
    104         });
    105 
    106         var regionLayer = L.tileLayer.canvas({
    107                 maxZoom: MAXZOOM+1,
    108                 minZoom: 0,
    109                 maxNativeZoom: MAXZOOM+1,
    110                 tileSize: TILESIZE,
    111                 continuousWorld: true
    112         });
    113 
    114         regionLayer.drawTile = function(canvas, tilePoint, zoom) {
    115                 var blockWorldSize = TILESIZE * Math.pow(2, MAXZOOM-zoom);
    116                 var tileLeft = tilePoint.x * blockWorldSize;
    117                 var tileBottom = (-1-tilePoint.y) * blockWorldSize;
    118                 var blockPos = L.latLng(tileLeft, tileBottom);
    119        
    120                 var ctx = canvas.getContext('2d');
    121        
    122                 ctx.strokeStyle = "lightblue";
    123                 ctx.fillStyle = "lightblue";
    124                 ctx.lineWidth = 1;
    125                 ctx.font="14px Arial";
    126        
    127                 var lineCount = blockWorldSize / REGIONSIZE;
    128                 if (lineCount >= 1) {
    129                         var pos = 0;
    130                         while (pos < TILESIZE) {
    131                                 // Vertical
    132                                 ctx.beginPath();
    133                                 ctx.moveTo(pos, 0);
    134                                 ctx.lineTo(pos, TILESIZE);
    135                                 ctx.stroke();
    136                        
    137                                 // Horizontal
    138                                 ctx.beginPath();
    139                                 ctx.moveTo(0, pos);
    140                                 ctx.lineTo(TILESIZE, pos);
    141                                 ctx.stroke();
    142 
    143                                 pos += TILESIZE / lineCount;
    144                         }
    145                         ctx.fillText(FormatRegionFileName(CoordToRegion(blockPos)), 4, TILESIZE-5);
    146                 } else {
    147                         if ((tileLeft % REGIONSIZE) == 0) {
    148                                 // Vertical
    149                                 ctx.beginPath();
    150                                 ctx.moveTo(0, 0);
    151                                 ctx.lineTo(0, TILESIZE);
    152                                 ctx.stroke();
    153                         }
    154                         if ((tileBottom % REGIONSIZE) == 0) {
    155                                 // Horizontal
    156                                 ctx.beginPath();
    157                                 ctx.moveTo(0, TILESIZE);
    158                                 ctx.lineTo(TILESIZE, TILESIZE);
    159                                 ctx.stroke();
    160                         }
    161                         if ((tileLeft % REGIONSIZE) == 0 && (tileBottom % REGIONSIZE) == 0) {
    162                                 ctx.fillText(FormatRegionFileName(CoordToRegion(blockPos)), 4, TILESIZE-5);
    163                         }
    164                 }
    165 
    166         }
    167 
    168 
    169         // ===============================================================================================
    170         // Reload control
    171 
    172         L.Control.ReloadTiles = L.Control.extend({
    173                 options: {
    174                         position: 'bottomleft'
    175                 },
    176 
    177                 onAdd: function (map) {
    178                         var name = 'control-reloadtiles',
    179                             container = L.DomUtil.create('div', name + ' leaflet-bar');
    180 
    181                         this._map = map;
    182 
    183                         this._reloadbutton = this._createButton(
    184                                 "Reload tiles", "Reload tiles",
    185                                 name + "-btn", container, this._reload, this);
    186 
    187                         return container;
    188                 },
    189 
    190                 onRemove: function (map) {
    191                 },
    192 
    193                 _reload: function (e) {
    194                         tileTime = new Date().getTime();
    195                         tileLayer.redraw();
    196                         tileLayerMiniMap.redraw();
    197                 },
    198 
    199                 _createButton: function (html, title, className, container, fn, context) {
    200                         var link = L.DomUtil.create('a', className, container);
    201                         link.innerHTML = html;
    202                         link.href = '#';
    203                         link.title = title;
    204 
    205                         var stop = L.DomEvent.stopPropagation;
    206 
    207                         L.DomEvent
    208                             .on(link, 'click', stop)
    209                             .on(link, 'mousedown', stop)
    210                             .on(link, 'dblclick', stop)
    211                             .on(link, 'click', L.DomEvent.preventDefault)
    212                             .on(link, 'click', fn, context)
    213                             .on(link, 'click', this._refocusOnMap, context);
    214 
    215                         return link;
    216                 }
    217 
    218         });
    219 
    220         new L.Control.ReloadTiles({
    221         }).addTo(map);
    222 
    223 
    224         // ===============================================================================================
    225         // Coordinates control
    226         //      <div id="info">
    227         //              MouseCoords: <span id="pos"></span>
    228         //      </div>
    229 
    230         L.Control.Coordinates = L.Control.extend({
    231                 options: {
    232                         position: 'bottomleft'
    233                 },
    234 
    235                 onAdd: function (map) {
    236                         var name = 'control-coordinates',
    237                             container = L.DomUtil.create('div', name + ' leaflet-bar');
    238                
    239                         container.innerHTML = "- N / - E"
    240 
    241                         this._map = map;
    242                         this._div = container;
    243 
    244                         map.on('mousemove', this._onMouseMove, this);
    245 
    246                         return container;
    247                 },
    248 
    249                 onRemove: function (map) {
    250                 },
    251        
    252                 _onMouseMove: function (e) {
    253                         this._div.innerHTML = FormatCoord(e.latlng);
    254                 }
    255 
    256 
    257         });
    258 
    259         new L.Control.Coordinates({
    260         }).addTo(map);
     86                time: initTime
     87        });
     88
     89
     90
    26191
    26292
     
    26898        var playersOnlineMarkerGroup = L.layerGroup();
    26999        var playersOfflineMarkerGroup = L.markerClusterGroup({
    270                 maxClusterRadius: function(zoom) { return zoom == MAXZOOM ? 10 : 50; }
     100                maxClusterRadius: function(zoom) { return zoom == mapinfo.maxzoom ? 10 : 50; }
    271101        });
    272102
     
    274104        var landClaimsGroup = L.layerGroup();
    275105        var landClaimsClusterGroup = L.markerClusterGroup({
    276                 disableClusteringAtZoom: MAXZOOM,
     106                disableClusteringAtZoom: mapinfo.maxzoom,
    277107                singleMarkerMode: true,
    278108                maxClusterRadius: 50
     
    287117        };
    288118
    289         var overlays = {
    290                 "Land claims" : landClaimsGroup,
    291                 "Players (offline) (<span id='mapControlOfflineCount'>0</span>)" : playersOfflineMarkerGroup,
    292                 "Players (online) (<span id='mapControlOnlineCount'>0</span>)" : playersOnlineMarkerGroup,
    293                 "Region files": regionLayer,
    294         };
    295 
     119        var layerControl = L.control.layers(baseLayers, null, {
     120                collapsed: false
     121        });
    296122       
    297         L.control.layers(baseLayers, overlays, {
    298                 collapsed: false
    299         }).addTo(map);
    300 
    301         var miniMap = new L.Control.MiniMap(tileLayerMiniMap, {
    302                 zoomLevelOffset: -6,
    303                 toggleDisplay: true
    304         }).addTo(map);
     123        var layerCount = 0;
     124
     125
     126        if (hasPermission ("web.map")) {
     127                tileLayer.addTo(map);
     128                new L.Control.Coordinates({}).addTo(map);
     129                new L.Control.ReloadTiles({layers: [tileLayer, tileLayerMiniMap]}).addTo(map);
     130                layerControl.addOverlay (GetRegionLayer (mapinfo), "Region files");
     131                var miniMap = new L.Control.MiniMap(tileLayerMiniMap, {
     132                        zoomLevelOffset: -6,
     133                        toggleDisplay: true
     134                }).addTo(map);
     135               
     136                if (hasPermission ("webapi.getstats")) {
     137                        new L.Control.GameTime({}).addTo(map);
     138                }
     139        }
     140        if (hasPermission ("webapi.getlandclaims")) {
     141                layerControl.addOverlay (landClaimsGroup, "Land claims");
     142                layerCount++;
     143        }
     144        if (hasPermission ("webapi.getplayerslocation")) {
     145                layerControl.addOverlay (playersOfflineMarkerGroup, "Players (offline) (<span id='mapControlOfflineCount'>0</span>)");
     146                layerControl.addOverlay (playersOnlineMarkerGroup, "Players (online) (<span id='mapControlOnlineCount'>0</span>)");
     147                layerCount++;
     148        }
     149
     150        if (layerCount > 0) {
     151                layerControl.addTo(map);
     152        }
    305153
    306154
     
    392240                        } else {
    393241                                marker = L.marker([val.position.x, val.position.z]).bindPopup(
    394                                         "Player: " + val.name + "<br/>" +
    395                                         "<a class='inventoryButton' data-steamid='"+val.steamid+"'>Show inventory</a>"
     242                                        "Player: " + val.name +
     243                                        (hasPermission ("webapi.getplayerinventory") ?
     244                                                "<br/><a class='inventoryButton' data-steamid='"+val.steamid+"'>Show inventory</a>"
     245                                                : "")
    396246                                );
    397247                                playersMappingList[val.steamid] = { online: !val.online };
     
    431281        }
    432282
    433         window.setTimeout(updatePlayerEvent, 500);
     283        if (hasPermission ("webapi.getplayerslocation")) {
     284                window.setTimeout(updatePlayerEvent, 0);
     285        }
    434286
    435287
     
    443295       
    444296                var claimPower = Math.floor(Math.log(data.claimsize) / Math.LN2);
    445                 var maxClusterZoomUnlimited = MAXZOOM - (claimPower - 3);
    446                 var maxClusterZoomLimitedMax = Math.min(maxClusterZoomUnlimited, MAXZOOM+1);
     297                var maxClusterZoomUnlimited = mapinfo.maxzoom - (claimPower - 3);
     298                var maxClusterZoomLimitedMax = Math.min(maxClusterZoomUnlimited, mapinfo.maxzoom+1);
    447299                maxZoomForCluster = Math.max(maxClusterZoomLimitedMax, 0);
    448300       
     
    516368
    517369
    518 $.getJSON( "../map/mapinfo.json")
    519 .done(function(data) {
    520         TILESIZE = data.blockSize;
    521         MAXZOOM = data.maxZoom;
    522 })
    523 .fail(function(jqxhr, textStatus, error) {
    524         console.log("Error fetching map information");
    525 })
    526 .always(function() {
    527         initMap();
    528 });
    529 
     370
     371function doTabs () {
     372        $(".adminmenu > ul > li").addClass ("menu_button");
     373        $(".admincontent > div").addClass ("contenttab");
     374        $(".adminmenu .menu_button").first ().addClass ("current_tab");
     375        $(".menu_button").on ('click.action', null, function (event) {
     376                var menuElement = $(this);
     377                var linkElement = menuElement.children ("a");
     378                var linkName = linkElement.attr ("href");
     379               
     380                $("*").removeClass ("current_tab");
     381                menuElement.addClass ("current_tab");
     382                $(linkName).addClass ("current_tab");
     383        });
     384       
     385        $(".adminmenu .menu_button").first ().click ();
     386}
     387
     388function initMapInfo () {
     389        $.getJSON( "../map/mapinfo.json")
     390        .done(function(data) {
     391                mapinfo.tilesize = data.blockSize;
     392                mapinfo.maxzoom = data.maxZoom;
     393        })
     394        .fail(function(jqxhr, textStatus, error) {
     395                console.log("Error fetching map information");
     396        })
     397        .always(function() {
     398                initMap();
     399        });
     400}
     401
     402function initUser () {
     403        $.getJSON( "../userstatus")
     404        .done(function(data) {
     405                userdata = data;
     406               
     407                var userdataDiv = $("#userstate");
     408                if (userdata.loggedin == true) {
     409                        var data = userdataDiv.children ("#userstate_loggedin");
     410                        data.attr ("style", "display: block");
     411                        data.children ("#username").attr ("href", "http://steamcommunity.com/profiles/" + userdata.username);
     412                        data.children ("#username").html (userdata.username);
     413                } else {
     414                        var data = userdataDiv.children ("#userstate_loggedout");
     415                        data.attr ("style", "display: block");
     416                }
     417
     418                initMapInfo ();
     419        })
     420        .fail(function(jqxhr, textStatus, error) {
     421                console.log("Error fetching user data");
     422        })
     423}
     424
     425doTabs ();
     426initUser ();
Note: See TracChangeset for help on using the changeset viewer.