Пример #1
0
        public static void BeginRequest <T>(string uri, T state, WebAPIRequestSend <T> send, WebAPIRequestReceive <T> receive)
        {
            VitaNexCore.TryCatch(
                () =>
            {
                CSOptions.ToConsole("Requesting: {0}", uri);

                var request = (HttpWebRequest)WebRequest.Create(uri);

                request.Proxy       = null;
                request.Credentials = null;

                if (send != null)
                {
                    send(request, state);
                }

                if (RequestSend != null)
                {
                    RequestSend(request, state);
                }

                RequestUtility.BeginGetResponse(request, state, receive);
            },
                CSOptions.ToConsole);
        }
Пример #2
0
            public static void AsyncRequestResult <T>(IAsyncResult r)
            {
                try
                {
                    using (var state = (AsyncState <T>)r.AsyncState)
                    {
                        try
                        {
                            var response = (HttpWebResponse)state.Request.EndGetResponse(r);

                            if (state.Receive != null)
                            {
                                state.Receive(state.Request, state.State, response);
                            }

                            if (RequestReceive != null)
                            {
                                RequestReceive(state.Request, state.State, response);
                            }

                            response.Close();
                        }
                        catch (Exception e)
                        {
                            CSOptions.ToConsole(e);
                        }
                    }
                }
                catch (Exception e)
                {
                    CSOptions.ToConsole(e);
                }
            }
Пример #3
0
        public static void BeginRequest <T>(string uri, T state, WebAPIRequestSend <T> send, WebAPIRequestReceive <T> receive)
        {
            try
            {
                CSOptions.ToConsole("Requesting: {0}", uri);

                var request = (HttpWebRequest)WebRequest.Create(uri);

                request.UserAgent = "VitaNexCore/" + VitaNexCore.Version + " " + CSOptions.Service.FullName;

                // ReSharper disable once AssignNullToNotNullAttribute
                request.Proxy       = null;
                request.Credentials = null;

                if (send != null)
                {
                    send(request, state);
                }

                if (RequestSend != null)
                {
                    RequestSend(request, state);
                }

                RequestUtility.BeginGetResponse(request, state, receive);
            }
            catch (Exception e)
            {
                CSOptions.ToConsole(e);
            }
        }
Пример #4
0
        public static void LoadProfiles()
        {
            DataStoreResult result = Templates.Import();

            CSOptions.ToConsole("Result: {0}", result.ToString());

            switch (result)
            {
            case DataStoreResult.Null:
            case DataStoreResult.Busy:
            case DataStoreResult.Error:
            {
                if (Templates.HasErrors)
                {
                    CSOptions.ToConsole("Profiles database has errors...");

                    Templates.Errors.ForEach(CSOptions.ToConsole);
                }
            }
            break;

            case DataStoreResult.OK:
                CSOptions.ToConsole("Profile count: {0:#,0}", Templates.Count);
                break;
            }
        }
Пример #5
0
            public static void ListenAsync()
            {
                AcquireListener();

                if (Listener == null)
                {
                    return;
                }

                VitaNexCore.TryCatch(
                    () =>
                {
                    Listener.BeginAcceptTcpClient(
                        r =>
                    {
                        var client = VitaNexCore.TryCatchGet(Listener.EndAcceptTcpClient, r, CSOptions.ToConsole);

                        ListenAsync();

                        if (client != null && client.Connected)
                        {
                            //client.NoDelay = true;

                            if (_ServerStarted)
                            {
                                var ip = ((IPEndPoint)client.Client.RemoteEndPoint).Address;

                                var allow = !CSOptions.UseWhitelist;

                                if (allow)
                                {
                                    allow = !CSOptions.Blacklist.Any(l => Utility.IPMatch(l, ip)) && !Firewall.IsBlocked(ip);
                                }

                                if (!allow && CSOptions.UseWhitelist)
                                {
                                    allow = CSOptions.Whitelist.Any(l => Utility.IPMatch(l, ip));
                                }

                                if (allow)
                                {
                                    Connect(new WebAPIClient(client));
                                    return;
                                }
                            }

                            client.Close();
                        }
                    },
                        null);
                },
                    e =>
                {
                    if (!(e is SocketException) && !(e is ObjectDisposedException))
                    {
                        CSOptions.ToConsole(e);
                    }
                });
            }
Пример #6
0
            public static void AcquireListener()
            {
                if (Listener != null && ((IPEndPoint)Listener.LocalEndpoint).Port != CSOptions.Port)
                {
                    ReleaseListener();
                }

                if (Listener == null)
                {
                    var ipep = Server.Network.Listener.EndPoints.FirstOrDefault(ep => !ep.Address.IsPrivateNetwork());
                    var ip   = ipep != null ? ipep.Address : IPAddress.Any;

                    Listener = new TcpListener(ip, CSOptions.Port)
                    {
                        ExclusiveAddressUse = false
                    };
                }

                if (!Listener.Server.IsBound)
                {
                    try
                    {
                        Listener.Start(CSOptions.MaxConnections);
                    }
                    catch (Exception e)
                    {
                        CSOptions.ToConsole(e);

                        if (Insensitive.Contains(e.ToString(), "access permissions"))
                        {
                            CSOptions.ToConsole(
                                "Another process may be bound to port {0}.\n" +
                                "The WebAPI service requires port {0} to be unbound and available for use on the target IP Address.",
                                CSOptions.Port);
                        }
                    }

                    if (!Listener.Server.IsBound)
                    {
                        return;
                    }

                    var ipep = Listener.LocalEndpoint as IPEndPoint;

                    if (ipep != null)
                    {
                        foreach (var ip in ipep.Address.FindInternal())
                        {
                            CSOptions.ToConsole("Listening: {0}:{1}", ip, ipep.Port);
                        }
                    }
                }

                _Listening = true;
            }
Пример #7
0
        public static string GetContent(this HttpWebResponse response)
        {
            try
            {
                using (var s = response.GetResponseStream())
                {
                    if (s == null)
                    {
                        return(String.Empty);
                    }

                    var enc = Encoding.UTF8;

                    if (!String.IsNullOrWhiteSpace(response.ContentEncoding))
                    {
                        enc = Encoding.GetEncoding(response.ContentEncoding);
                    }

                    using (var r = new StreamReader(s, enc))
                    {
                        char[]        b = null;
                        StringBuilder c = null;

                        int len;

                        while (r.Peek() >= 0)
                        {
                            if (b == null)
                            {
                                b = new char[4096];
                                c = new StringBuilder();
                            }

                            while ((len = r.Read(b, 0, b.Length)) > 0)
                            {
                                c.Append(b, 0, len);
                            }
                        }

                        if (c != null)
                        {
                            return(c.ToString());
                        }
                    }
                }
            }
            catch (ObjectDisposedException)
            { }
            catch (Exception e)
            {
                CSOptions.ToConsole(e);
            }

            return(String.Empty);
        }
Пример #8
0
        public static void Index()
        {
            CSOptions.ToConsole("Indexing names...");

            World.Mobiles.Values.AsParallel().OfType <PlayerMobile>().ForEach(Register);

            CSOptions.ToConsole("Indexing complete.");
            CSOptions.ToConsole(
                "{0:#,0} registered names by {1:#,0} players.",
                Registry.Count,
                Registry.Values.Aggregate(0, (c, list) => c + list.Count));
        }
Пример #9
0
        public static void Register(
            Type type,
            ClientVersion highVersion,
            ClientVersion lowVersion,
            int highItemID,
            int lowItemID)
        {
            List <ArtworkInfo> infoList;

            if (!Info.TryGetValue(type, out infoList) || infoList == null)
            {
                Info[type] = infoList = new List <ArtworkInfo>();
            }

            var info =
                infoList.Find(i => i.HighVersion == highVersion && i.LowVersion == lowVersion && i.HighItemID == highItemID);

            if (info != null)
            {
                if (CSOptions.ServiceDebug)
                {
                    CSOptions.ToConsole(
                        "Replacing ArtworkInfo for '{0}' -> \n({1} -> {2}, 0x{3:X4} -> 0x{4:X4}) with ({5} -> {6}, 0x{7:X4} -> 0x{8:X4})",
                        type.Name,
                        info.HighVersion,
                        info.LowVersion,
                        info.HighItemID,
                        info.LowItemID,
                        highVersion,
                        lowVersion,
                        highItemID,
                        lowItemID);
                }

                info.HighItemID = highItemID;
                info.LowItemID  = lowItemID;
            }
            else
            {
                if (CSOptions.ServiceDebug)
                {
                    CSOptions.ToConsole(
                        "Adding ArtworkInfo for '{0}' -> \n({1} -> {2}, 0x{3:X4} -> 0x{4:X4})",
                        type.Name,
                        highVersion,
                        lowVersion,
                        highItemID,
                        lowItemID);
                }

                infoList.Add(new ArtworkInfo(highVersion, lowVersion, highItemID, lowItemID));
            }
        }
Пример #10
0
            public static void BeginGetResponse <T>(HttpWebRequest request, T state, WebAPIRequestReceive <T> receive)
            {
                try
                {
                    var a = new Action <HttpWebRequest, AsyncState <T> >((r, o) => r.BeginGetResponse(AsyncRequestResult <T>, o));

                    a.BeginInvoke(request, new AsyncState <T>(request, receive, state), a.EndInvoke, null);
                }
                catch (Exception e)
                {
                    CSOptions.ToConsole(e);
                }
            }
Пример #11
0
        public static bool CanConnect(MySQLConnection c, bool message = true)
        {
            if (c == null)
            {
                if (message)
                {
                    CSOptions.ToConsole("Connection invalid: The connection no longer exists.");
                }

                return(false);
            }

            if (c.HasError)
            {
                if (message)
                {
                    CSOptions.ToConsole("Connection invalid: The connection has errors.");
                }

                return(false);
            }

            if (c.Credentials == null || !c.Credentials.IsValid())
            {
                if (message)
                {
                    CSOptions.ToConsole("Connection invalid: The connection credentials are invalid.");
                }

                return(false);
            }

            if (Connections.Count >= CSOptions.MaxConnections)
            {
                if (message)
                {
                    CSOptions.ToConsole("Connection invalid: Max connection limit ({0:#,0}) reached.", CSOptions.MaxConnections);
                }

                return(false);
            }

            if (message)
            {
                CSOptions.ToConsole("Connection validated.");
            }

            return(true);
        }
Пример #12
0
        public static void RequestVersion()
        {
            if (_Timeout != null && _Timeout.Running)
            {
                CSOptions.ToConsole("Previous request has not been handled yet.");
                return;
            }

            CSOptions.ToConsole("Requesting remote version...");

            NotifyStaff("Checking for updates...", false);

            _Timeout = Timer.DelayCall(
                TimeSpan.FromMilliseconds(CSOptions.Timeout.TotalMilliseconds + 1000),
                () =>
            {
                CSOptions.ToConsole("Request timed-out.");

                NotifyStaff("Update request failed, the connection timed-out.", true, 1.0, 10.0);
            });

            VitaNexCore.TryCatch(
                () =>
                HttpService.SendRequest(
                    URL != null ? URL.ToString() : DefaultURL,
                    (int)CSOptions.Timeout.TotalMilliseconds,
                    (i, send, receive) =>
            {
                if (URL == null)
                {
                    URL = i.URL;
                }

                string rcv = String.Join(String.Empty, receive.GetContent());

                OnDataReceived(rcv);

                if (_Timeout == null)
                {
                    return;
                }

                _Timeout.Stop();
                _Timeout = null;
            }),
                CSOptions.ToConsole);
        }
Пример #13
0
        public static void Register(Type type, ClientVersion version, int oldItemID, int newItemID)
        {
            List <ArtworkInfo> infoList;

            if (!Info.TryGetValue(type, out infoList))
            {
                Info.Add(type, (infoList = new List <ArtworkInfo>()));
            }
            else if (infoList == null)
            {
                Info[type] = infoList = new List <ArtworkInfo>();
            }

            var info = infoList.FirstOrDefault(i => i.ItemID.Left == oldItemID);

            if (info != null)
            {
                if (CSOptions.ServiceDebug)
                {
                    CSOptions.ToConsole(
                        "Replacing ArtworkInfo for '{0}' -> \n({1}, 0x{2:X4} -> 0x{3:X4}) with ({4}, 0x{5:X4} -> 0x{6:X4})",
                        type.Name,
                        info.Version,
                        info.ItemID.Left,
                        info.ItemID.Right,
                        version,
                        oldItemID,
                        newItemID);
                }

                info.Version = version;
                info.ItemID  = Pair.Create(oldItemID, newItemID);
            }
            else
            {
                if (CSOptions.ServiceDebug)
                {
                    CSOptions.ToConsole(
                        "Adding ArtworkInfo for '{0}' -> \n({1}, 0x{2:X4} -> 0x{3:X4})", type.Name, version, oldItemID, newItemID);
                }

                infoList.Add(new ArtworkInfo(version, oldItemID, newItemID));
            }
        }
Пример #14
0
        private static void ExportCommand(CommandEventArgs e)
        {
            if (e.Mobile == null || e.Mobile.Deleted)
            {
                return;
            }

            e.Mobile.SendMessage(0x55, "Export requested...");

            if (e.Arguments == null || e.Arguments.Length == 0 || String.IsNullOrWhiteSpace(e.Arguments[0]))
            {
                e.Mobile.SendMessage("Usage: {0}{1} <{2}>", CommandSystem.Prefix, e.Command, String.Join(" | ", _Languages));
                return;
            }

            ClilocLNG lng;

            if (Enum.TryParse(e.Arguments[0], true, out lng) && lng != ClilocLNG.NULL)
            {
                VitaNexCore.TryCatch(
                    () =>
                {
                    var file = Export(lng);

                    if (file != null && file.Exists && file.Length > 0)
                    {
                        e.Mobile.SendMessage(0x55, "{0} clilocs have been exported to: {1}", lng, file.FullName);
                    }
                    else
                    {
                        e.Mobile.SendMessage(0x22, "Could not export clilocs for {0}", lng);
                    }
                },
                    ex =>
                {
                    e.Mobile.SendMessage(0x22, "A fatal exception occurred, check the console for details.");
                    CSOptions.ToConsole(ex);
                });
            }
            else
            {
                e.Mobile.SendMessage("Usage: {0}{1} <{2}>", CommandSystem.Prefix, e.Command, String.Join(" | ", _Languages));
            }
        }
Пример #15
0
        private static void HandleWorldItemSAHS(NetState state, PacketReader reader, ref byte[] buffer, ref int length)
        {
            if (_Parent0xF3 != null)
            {
                _Parent0xF3(state, reader, ref buffer, ref length);
            }

            if (state == null || reader == null || buffer == null)
            {
                return;
            }

            var pos = reader.Seek(0, SeekOrigin.Current);

            reader.Seek(4, SeekOrigin.Begin);
            Serial serial = reader.ReadInt32();

            reader.Seek(pos, SeekOrigin.Begin);

            if (!serial.IsValid || !serial.IsItem)
            {
                return;
            }

            var item = World.FindItem(serial);
            var info = Lookup(state.Version, item);

            if (info == null)
            {
                return;
            }

            if (CSOptions.ServiceDebug)
            {
                CSOptions.ToConsole(
                    "Rewriting packet buffer ItemID for '{0}' -> \n(0x{1:X4} -> 0x{2:X4})",
                    item.GetType().Name,
                    info.HighItemID,
                    info.LowItemID);
            }

            info.SwitchWorldItemSAHS(item is BaseMulti, ref buffer);
            length = buffer.Length;
        }
Пример #16
0
            private static void EndAcceptTcpClient(IAsyncResult r)
            {
                TcpClient client;

                try
                {
                    client = Listener.EndAcceptTcpClient(r);
                }
                catch (Exception e)
                {
                    CSOptions.ToConsole(e);
                    return;
                }
                finally
                {
                    ListenAsync();
                }

                if (client.Connected && _ServerStarted)
                {
                    var ip = ((IPEndPoint)client.Client.RemoteEndPoint).Address;

                    var allow = !CSOptions.UseWhitelist;

                    if (allow)
                    {
                        allow = !CSOptions.Blacklist.Any(l => Utility.IPMatch(l, ip)) && !Firewall.IsBlocked(ip);
                    }

                    if (!allow && CSOptions.UseWhitelist)
                    {
                        allow = CSOptions.Whitelist.Any(l => Utility.IPMatch(l, ip));
                    }

                    if (allow)
                    {
                        Connect(new WebAPIClient(client));
                        return;
                    }
                }

                client.Close();
            }
Пример #17
0
        private static void OnDataReceived(string data)
        {
            CSOptions.ToConsole("{0} bytes of data received, parsing...", Encoding.Default.GetByteCount(data));

            VersionInfo version;

            if (!VersionInfo.TryParse(data, out version))
            {
                CSOptions.ToConsole("The remote version could not be resolved.");
                NotifyStaff("Update request failed, the remote version could not be resolved.", true, 1.0, 10.0);
                return;
            }

            RemoteVersion = version;

            CSOptions.ToConsole("Remote version resolved as {0}", RemoteVersion);

            if (LocalVersion >= RemoteVersion)
            {
                NotifyStaff(
                    String.Format("No updates are available, your version [b]{0}[/b] is up-to-date.", LocalVersion),
                    true,
                    1.0,
                    10.0);
            }
            else
            {
                NotifyStaff(
                    String.Format(
                        "Updates are available, your version [b]{0}[/b] is out-of-date, the remote version is [b]{1}[/b].",
                        LocalVersion,
                        RemoteVersion),
                    true,
                    1.0,
                    10.0);
            }

            if (OnVersionResolved != null)
            {
                OnVersionResolved(LocalVersion, RemoteVersion);
            }
        }
Пример #18
0
        public static void RequestVersion()
        {
            if (_Timeout != null && _Timeout.Running)
            {
                CSOptions.ToConsole("Previous request has not been handled yet.");
                return;
            }

            CSOptions.ToConsole("Requesting remote version...");

            _Timeout = Timer.DelayCall(
                TimeSpan.FromMilliseconds(CSOptions.Timeout.TotalMilliseconds + 1000),
                () =>
            {
                CSOptions.ToConsole("Request timed-out.");

                NotifyStaff("Update request failed, the connection timed-out.", true, 1.0, 10.0);
            });

            WebAPI.BeginRequest(URL != null ? URL.ToString() : DefaultURL, null, OnSend, OnReceive);
        }
Пример #19
0
            public static void ListenAsync()
            {
                AcquireListener();

                if (Listener == null)
                {
                    return;
                }

                try
                {
                    Listener.BeginAcceptTcpClient(EndAcceptTcpClient, null);
                }
                catch (SocketException)
                { }
                catch (ObjectDisposedException)
                { }
                catch (Exception e)
                {
                    CSOptions.ToConsole(e);
                }
            }
Пример #20
0
        public static void Disconnect(WebAPIClient client)
        {
            VitaNexCore.TryCatch(
                () =>
            {
                lock (Clients)
                {
                    if (!Clients.Remove(client))
                    {
                        return;
                    }
                }

                if (!client.IsDisposed)
                {
                    var addr = client.Client.Client.RemoteEndPoint;

                    if (ClientDisconnected != null)
                    {
                        ClientDisconnected(client);
                    }

                    client.Close(true);

                    CSOptions.ToConsole("[{0}] Client Disconnected: {1}", Clients.Count, addr);
                }
            },
                e =>
            {
                CSOptions.ToConsole(e);

                lock (Clients)
                {
                    Clients.Remove(client);
                }

                client.Close(true);
            });
        }
Пример #21
0
        public static void Connect(WebAPIClient client)
        {
            VitaNexCore.TryCatch(
                () =>
            {
                lock (Clients)
                {
                    if (Clients.Contains(client))
                    {
                        return;
                    }

                    Clients.Add(client);
                }

                CSOptions.ToConsole("[{0}] Client Connected: {1}", Clients.Count, client.Client.Client.RemoteEndPoint);

                if (ClientConnected != null)
                {
                    ClientConnected(client);
                }

                if (!client.IsDisposed && client.Connected)
                {
                    ClientUtility.HandleConnection(client);
                }
                else
                {
                    Disconnect(client);
                }
            },
                e =>
            {
                CSOptions.ToConsole(e);

                Disconnect(client);
            });
        }
Пример #22
0
        public static void SetContent(this HttpWebRequest request, string content, Encoding enc)
        {
            try
            {
                request.Headers[HttpRequestHeader.ContentEncoding] = enc.WebName;

                if (String.IsNullOrEmpty(content))
                {
                    return;
                }

                using (var s = request.GetRequestStream())
                {
                    var buf = new byte[Math.Min(4096, content.Length * 2)];

                    int idx = 0, len, cnt;

                    while ((len = enc.GetBytes(content, idx, cnt = content.Length - idx, buf, 0)) > 0)
                    {
                        s.Write(buf, 0, len);
                        s.Flush();

                        if ((idx += cnt) >= content.Length)
                        {
                            break;
                        }
                    }
                }
            }
            catch (ObjectDisposedException)
            { }
            catch (Exception e)
            {
                CSOptions.ToConsole(e);
            }
        }
Пример #23
0
            public static bool HandleConnection(WebAPIClient client)
            {
                using (client)
                {
                    KeyValueString[] headers;

                    if (!client.ReceiveHeaders(out headers))
                    {
                        return(false);
                    }

                    var m = headers[0].Key;

                    if (String.IsNullOrWhiteSpace(m))
                    {
                        return(false);
                    }

                    WebAPIMethod method;

                    if (!Enum.TryParse(m, out method))
                    {
                        return(false);
                    }

                    var u = headers[0].Value;
                    var i = u.LastIndexOf(' ');

                    if (i > -1)
                    {
                        u = u.Substring(0, i);
                    }

                    u = HttpUtility.UrlDecode(u);

                    if (String.IsNullOrWhiteSpace(u))
                    {
                        u = "/";
                    }

                    using (var context = new WebAPIContext(client, method, u))
                    {
                        foreach (var h in headers.Skip(1))
                        {
                            context.Request.Headers[h.Key] = h.Value;
                        }

                        foreach (var q in DecodeQuery(u))
                        {
                            context.Request.Queries[q.Key] = q.Value;
                        }

                        if (!String.IsNullOrWhiteSpace(context.Request.Headers["Content-Type"]))
                        {
                            context.Request.ContentType = context.Request.Headers["Content-Type"];
                        }

                        var length = 0;

                        if (!String.IsNullOrWhiteSpace(context.Request.Headers["Content-Length"]))
                        {
                            Int32.TryParse(context.Request.Headers["Content-Length"], out length);
                        }

                        if (Insensitive.Contains(context.Request.Headers["Accept-Encoding"], "deflate"))
                        {
                            context.Response.Compress = true;
                        }

                        var encoding = Encoding.UTF8;

                        if (!String.IsNullOrWhiteSpace(context.Request.Headers["Accept-Charset"]))
                        {
                            var h = context.Request.Headers["Accept-Charset"].Trim();

                            if (h.Contains(','))
                            {
                                foreach (var e in h.Split(','))
                                {
                                    try
                                    {
                                        encoding = Encoding.GetEncoding(e.Trim());
                                    }
                                    catch
                                    {
                                        encoding = Encoding.UTF8;
                                    }
                                }
                            }
                            else
                            {
                                try
                                {
                                    encoding = Encoding.GetEncoding(h);
                                }
                                catch
                                {
                                    encoding = Encoding.UTF8;
                                }
                            }
                        }

                        context.Request.Encoding = context.Response.Encoding = encoding;

                        context.Response.Headers["Date"]   = DateTime.UtcNow.ToSimpleString("D, d M y t@h:m:s@") + " GMT";
                        context.Response.Headers["Server"] = String.Format(
                            "Vita-Nex: Core/{0} [{1}/{2}] ({3})",
                            VitaNexCore.Version,
                            CSOptions.ServiceName,
                            CSOptions.ServiceVersion,
                            ServerList.ServerName);

                        if (!context.Method.AnyFlags(WebAPIMethod.OPTIONS, WebAPIMethod.GET, WebAPIMethod.POST))
                        {
                            context.Response.Headers["Allow"]      = "OPTIONS, GET, POST";
                            context.Response.Headers["Connection"] = "close";

                            client.Send(false, "HTTP/1.1 405 Method Not Allowed\r\n" + context.Response.Headers, Encoding.ASCII);
                            return(true);
                        }

                        if (context.Method == WebAPIMethod.OPTIONS)
                        {
                            if (!String.IsNullOrWhiteSpace(context.Request.Headers["Origin"]))
                            {
                                context.Response.Headers["Access-Control-Allow-Methods"] = "POST, GET, OPTIONS";
                                context.Response.Headers["Access-Control-Allow-Headers"] = "Origin, X-Requested-With, Content-Type, Accept";
                                context.Response.Headers["Access-Control-Allow-Origin"]  = context.Request.Headers["Origin"];
                            }

                            context.Response.Headers["Vary"]       = "Accept-Encoding";
                            context.Response.Headers["Keep-Alive"] = "timeout=2, max=120";
                            context.Response.Headers["Connection"] = "keep-alive";

                            client.Send(false, "HTTP/1.1 200 OK\r\n" + context.Response.Headers, Encoding.ASCII);
                            return(true);
                        }

                        if (length > CSOptions.MaxReceiveBufferSizeBytes)
                        {
                            context.Response.Headers["Connection"] = "close";

                            client.Send(false, "HTTP/1.1 413 Request Entity Too Large\r\n" + context.Response.Headers, Encoding.ASCII);
                            return(true);
                        }

                        WebAPIHandler handler;

                        var key = u.Trim();
                        var idx = u.IndexOf('?');

                        if (idx > 0)
                        {
                            key = u.Substring(0, idx);
                        }

                        if (key.Length > 1)
                        {
                            key = key.TrimEnd('/');
                        }

                        if (!Handlers.TryGetValue(key, out handler) || handler == null)
                        {
                            key = "/";
                        }

                        byte[] buffer;

                        if (handler != null || (Handlers.TryGetValue(key, out handler) && handler != null))
                        {
                            try
                            {
                                if (length > 0)
                                {
                                    string data;

                                    client.Receive(false, context.Request.Encoding, out data, out buffer, out length);

                                    context.Request.Data   = data;
                                    context.Request.Length = length;
                                }

                                handler.Handler(context);
                            }
                            catch (Exception e)
                            {
                                CSOptions.ToConsole(e);

                                if (e is InternalBufferOverflowException)
                                {
                                    context.Response.Status = HttpStatusCode.RequestEntityTooLarge;
                                }
                                else
                                {
                                    context.Response.Status = HttpStatusCode.InternalServerError;
                                }
                            }
                        }
                        else
                        {
                            context.Response.Status = HttpStatusCode.NotFound;
                        }

                        if (ContextHandler != null)
                        {
                            ContextHandler(context);
                        }

                        string status;

                        if ((int)context.Response.Status >= 400)
                        {
                            context.Response.Headers["Connection"] = "close";

                            status = String.Format("{0} {1}", (int)context.Response.Status, context.Response.Status.ToString().SpaceWords());

                            client.Send(false, "HTTP/1.1 " + status + "\r\n" + context.Response.Headers, Encoding.ASCII);
                            return(true);
                        }

                        var encoded    = false;
                        var compressed = false;

                        try
                        {
                            GetResponseBuffer(context, out buffer, out length, out encoded);

                            if (length > 0 && context.Response.Compress)
                            {
                                client.Compress(ref buffer, ref length);
                                compressed = true;
                            }
                        }
                        catch (Exception e)
                        {
                            CSOptions.ToConsole(e);

                            buffer = _EmptyBuffer;
                            length = 0;

                            if (e is InternalBufferOverflowException)
                            {
                                context.Response.Status = HttpStatusCode.RequestEntityTooLarge;
                            }
                            else
                            {
                                context.Response.Status = HttpStatusCode.InternalServerError;
                            }
                        }

                        if (!String.IsNullOrWhiteSpace(context.Request.Headers["Origin"]))
                        {
                            context.Response.Headers["Access-Control-Allow-Origin"] = context.Request.Headers["Origin"];
                        }

                        if (String.IsNullOrWhiteSpace(context.Response.Headers["Vary"]))
                        {
                            context.Response.Headers["Vary"] = "Accept-Encoding";
                        }

                        if (length > 0)
                        {
                            if (compressed)
                            {
                                context.Response.Headers["Content-Encoding"] = "deflate";
                            }

                            if (context.Response.ContentType.IsDefault && !String.IsNullOrWhiteSpace(context.Response.FileName))
                            {
                                var mime = FileMime.Lookup(context.Response.FileName);

                                if (!mime.IsDefault && mime != context.Response.ContentType)
                                {
                                    context.Response.ContentType = mime;
                                }
                            }

                            var contentType = context.Response.ContentType.MimeType;

                            if (encoded)
                            {
                                contentType = String.Format("{0}; charset={1}", contentType, context.Response.Encoding.WebName);
                            }

                            context.Response.Headers["Content-Type"]   = contentType;
                            context.Response.Headers["Content-Length"] = length.ToString();

                            if (!String.IsNullOrWhiteSpace(context.Response.FileName))
                            {
                                var inline = context.Response.ContentType.IsCommonText() || context.Response.ContentType.IsCommonImage();

                                var disp = inline ? "inline" : "attachment";

                                disp = String.Format("{0}; filename=\"{1}\"", disp, context.Response.FileName);

                                context.Response.Headers["Content-Disposition"] = disp;
                            }
                        }

                        if (context.Response.Cache < 0)
                        {
                            context.Response.Headers["Pragma"]        = "no-cache";
                            context.Response.Headers["Cache-Control"] = "no-cache, no-store";
                        }
                        else if (context.Response.Cache > 0)
                        {
                            context.Response.Headers["Cache-Control"] = "max-age=" + context.Response.Cache;
                        }

                        if (String.IsNullOrWhiteSpace(context.Response.Headers["Connection"]))
                        {
                            context.Response.Headers["Connection"] = "close";
                        }

                        status = String.Format("{0} {1}", (int)context.Response.Status, context.Response.Status.ToString().SpaceWords());

                        client.Send(false, "HTTP/1.1 " + status + "\r\n" + context.Response.Headers, Encoding.ASCII);

                        if (buffer.Length > 0 && length > 0)
                        {
                            client.Send(false, ref buffer, ref length);
                        }
                    }
                }

                return(true);
            }
Пример #24
0
            private static void GetResponseBuffer(WebAPIContext context, out byte[] buffer, out int length, out bool encoded)
            {
                buffer  = _EmptyBuffer;
                length  = 0;
                encoded = false;

                try
                {
                    if (context.Response.Data == null)
                    {
                        return;
                    }

                    if (context.Response.Data is byte[])
                    {
                        buffer = (byte[])context.Response.Data;
                        length = buffer.Length;

                        encoded = context.Response.ContentType.IsCommonText();

                        return;
                    }

                    if (context.Response.Data is Image)
                    {
                        var image = (Image)context.Response.Data;

                        var path = VitaNexCore.CacheDirectory + "/WebAPI/Images/" + image.GetHashCode() + ".png";
                        var file = IOUtility.EnsureFile(path, true);

                        image.Save(file.FullName, ImageFormat.Png);

                        if (FromFile(context, file, out buffer, out length, out encoded))
                        {
                            context.Response.Status = HttpStatusCode.OK;
                        }

                        file.Delete();

                        return;
                    }

                    if (context.Response.Data is DirectoryInfo)
                    {
                        var dir = (DirectoryInfo)context.Response.Data;

                        FileInfo file = null;

                        if (!String.IsNullOrWhiteSpace(context.Response.FileName))
                        {
                            file = new FileInfo(IOUtility.GetSafeFilePath(dir + "/" + context.Response.FileName, true));
                        }

                        if (file == null || !file.Exists)
                        {
                            file = new FileInfo(IOUtility.GetSafeFilePath(dir + "/index.html", true));
                        }

                        if (FromFile(context, file, out buffer, out length, out encoded) ||
                            (CSOptions.DirectoryIndex && FromDirectory(context, dir, out buffer, out length, out encoded)))
                        {
                            context.Response.Status = HttpStatusCode.OK;
                        }

                        return;
                    }

                    if (context.Response.Data is FileInfo)
                    {
                        var file = (FileInfo)context.Response.Data;

                        if (FromFile(context, file, out buffer, out length, out encoded))
                        {
                            context.Response.Status = HttpStatusCode.OK;
                        }

                        return;
                    }

                    string response;

                    if (context.Response.Data is string || context.Response.Data is StringBuilder || context.Response.Data is ValueType)
                    {
                        response = context.Response.Data.ToString();

                        if (!context.Response.ContentType.IsCommonText())
                        {
                            context.Response.ContentType = "txt";
                        }
                    }
                    else
                    {
                        JsonException je;

                        response = Json.Encode(context.Response.Data, out je) ?? String.Empty;

                        if (je != null)
                        {
                            response = je.ToString();

                            if (!context.Response.ContentType.IsCommonText())
                            {
                                context.Response.ContentType = "txt";
                            }
                        }
                        else if (!String.IsNullOrWhiteSpace(response))
                        {
                            context.Response.ContentType = "json";
                        }
                    }

                    if (String.IsNullOrWhiteSpace(context.Response.FileName))
                    {
                        context.Response.FileName =                                          //
                                                    Math.Abs(response.GetHashCode()) + "." + //
                                                    context.Response.ContentType.Extension;
                    }

                    context.Client.Encode(context.Response.Encoding, response, out buffer, out length);
                    encoded = true;
                }
                catch (Exception e)
                {
                    CSOptions.ToConsole(e);
                }
            }