예제 #1
0
        public static void HandleRequest(HttpProcessor p, string jsonStr)
        {
            object response = null;

            try
            {
                dynamic       requestObj = JsonConvert.DeserializeObject(jsonStr);
                ServerSession session    = GetSession(requestObj);
                string        cmd        = Try.Get(() => (string)requestObj.cmd);
                if (cmd == "login")
                {
                    if (session == null)
                    {
                        session = ServerSession.CreateUnauthenticated();
                        SessionManager.AddSession(session);
                    }
                    // Get current challenge and generate a new one so the previous one can not be used again, preventing replay attacks.
                    byte[] currentChallenge = session.authChallenge;
                    session.authChallenge = ByteUtil.GenerateRandomBytes(32);
                    // Get user
                    string userName = Try.Get(() => (string)requestObj.user);
                    if (string.IsNullOrEmpty(userName))
                    {
                        response = new ResultFailWithReason(session, "missing parameter: \"user\"");
                        return;
                    }
                    User user = ServiceWrapper.db.GetUser(userName);

                    string responseToken = Try.Get(() => (string)requestObj.response);
                    if (string.IsNullOrEmpty(responseToken))
                    {
                        // No response token was provided. This is step 1 of authentication, where the client requests information necessary to build the response token.
                        string salt;
                        if (user != null)
                        {
                            salt = user.Salt;
                        }
                        else
                        {
                            salt = Util.GenerateFakeUserSalt(userName);
                            Logger.Info("Fake salt \"" + salt + "\" created for user name \"" + userName + "\". Remote IP: " + p.RemoteIPAddressStr);
                        }

                        response = new ResultLoginChallengeAndSalt(session, salt);
                    }
                    else
                    {
                        bool authenticated = false;
                        // If the user hasn't gotten a challenge token yet, currentChallenge will be blank.
                        if (currentChallenge != null && currentChallenge.Length > 0)
                        {
                            if (user != null)
                            {
                                authenticated = user.AuthenticateUser(responseToken, currentChallenge);
                            }
                        }
                        if (authenticated)
                        {
                            session.userId = user.ID;
                            response       = new ResultLoginSuccess(session, user.SettingsKey);
                        }
                        else
                        {
                            response = new ResultFailWithReason(session, "authentication rejected");
                        }
                    }
                    return;
                }
                else
                {
                    if (session == null || !session.IsAuthValid)
                    {
                        response = new ResultFailNoSession(session);
                        return;
                    }
                    ///////////////////////////////////////////////////////////////////////////////////////////////////
                    ///////////////////////////////////////////////////////////////////////////////////////////////////
                    // Commands after this point require an authenticated session, but not administrator permission. //
                    ///////////////////////////////////////////////////////////////////////////////////////////////////
                    ///////////////////////////////////////////////////////////////////////////////////////////////////
                    User user = session.GetUser();
                    if (user == null)
                    {
                        Logger.Debug("Session has user ID " + session.userId + " but GetUser returned null");
                        response = new ResultFailWithReason(session, "session corrupted");
                        return;
                    }
                    bool handled = true;
                    switch (cmd)
                    {
                    case "getComputers":
                        UserGroup[]             userGroups = user.GetGroups();
                        GetComputerGroupsResult result     = new GetComputerGroupsResult();
                        result.Groups = userGroups.Select(g => new GroupOfComputers(g, ServiceWrapper.db.GetComputersInGroup(g.ID))).ToArray();
                        response      = result;
                        break;

                    case "logout":
                        SessionManager.RemoveSession(session.sid);
                        response = new ResultSuccess();
                        break;

                    default:
                        handled = false;
                        break;
                    }
                    if (handled)
                    {
                        return;
                    }

                    if (!user.IsAdmin)
                    {
                        response = new ResultFailInsufficientPrivileges();
                        return;
                    }
                    /////////////////////////////////////////////////////////////////
                    /////////////////////////////////////////////////////////////////
                    // Commands after this point require administrator permission. //
                    /////////////////////////////////////////////////////////////////
                    /////////////////////////////////////////////////////////////////
                    switch (cmd)
                    {
                        #region admin/getComputers
                    case "admin/getComputers":
                    {
                        ResultComputersAndTheirGroups result = new ResultComputersAndTheirGroups();

                        ComputerAndItsGroups[] allComputers = ServiceWrapper.db.GetAllComputersAndTheirGroups();
                        result.Computers = allComputers.Select(c => new AdminResultComputer(c)).ToArray();

                        response = result;
                        break;
                    }

                        #endregion
                        #region admin/getUsers
                    case "admin/getUsers":
                    {
                        ResultAllUsers result = new ResultAllUsers();

                        UserAndItsGroups[] allUsers = ServiceWrapper.db.GetAllUsersAndTheirGroups();
                        result.Users = allUsers.Select(u => new AdminResultUser(u)).ToArray();

                        response = result;
                        break;
                    }

                        #endregion
                    default:
                    {
                        response = new ResultFailWithReason(session, "unrecognized command");
                        break;
                    }
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Debug(ex);
                response = new ResultFail()
                {
                    error = "An unexpected error occurred."
                };
            }
            finally
            {
                if (response == null)
                {
                    response = new ResultFail()
                    {
                        error = "Application Error: A response was not generated, so this response was generated as a fallback."
                    }
                }
                ;
                p.writeSuccess(jsonType);
                p.outputStream.Write(JsonConvert.SerializeObject(response));
            }
        }
예제 #2
0
        public ChaosBoxMixResult Execute(Character @char)
        {
            var cbItems = @char.Inventory.ChaosBox.Items;
            var items   = cbItems.Select(x => x.Value);

            if (BaseCost > @char.Money)
            {
                return(ChaosBoxMixResult.InsufficientMoney);
            }

            @char.Money -= (uint)BaseCost;

            var ingOk = new Dictionary <IngredientInfo, int>();

            foreach (var ing in Ingredients)
            {
                var count = items.Where(x => ing.Match(x)).Count();
                if (ing.Count > count)
                {
                    return(ChaosBoxMixResult.Fail);
                }

                ingOk.Add(ing, count);
            }

            var pairIng = (from ing in Ingredients
                           from it in cbItems
                           where ing.Match(it.Value)
                           select new { Address = it.Key, Item = it.Value, Ingredient = ing }).ToList();

            var leftItems = (from it in cbItems
                             where !pairIng.Any(x => x.Item == it.Value)
                             select it).ToList();

            var successRate = GeneralSuccess;

            foreach (var ing in ingOk)
            {
                var scalar = (ing.Value - ing.Key.Count);
                successRate += scalar * 10;
            }

            if (successRate > 100)
            {
                successRate = 100;
            }
            var rand = new Random();

            if (rand.Next(0, 100) > successRate - 1)
            {
                if (ResultFail.IID == -1)
                {
                    @char.Inventory.DeleteChaosBox();
                }

                return(ChaosBoxMixResult.Fail);
            }

            @char.Inventory.DeleteChaosBox();

            var            prob = rand.Next(0, 100);
            IngredientInfo res  = null;

            foreach (var r in ResultSuccess)
            {
                if (prob < r.Success)
                {
                    res = r;
                    break;
                }
                prob -= r.Success;
            }

            if (res == null)
            {
                res = ResultSuccess.First();
            }

            var res2 = pairIng.FirstOrDefault(x => x.Ingredient.IID == res.IID);

            var mix = new Item(res.ItemNumber != ItemNumber.Invalid ? res.ItemNumber : res2.Item.Number);

            if (res.Level.Length == 1)
            {
                mix.Plus = res.Level[0] == 255 ? res2.Item.Plus : (byte)res.Level[0];
            }
            else if (res.Level.Length == 2)
            {
                mix.Plus = (byte)rand.Next(res.Level[0], res.Level[1]);
            }
            else
            {
                mix.Plus = res2?.Item.Plus ?? 0;
            }

            mix.Luck        = res.Luck == -1 ? res2?.Item.Luck ?? false : (res.Luck > 0 ? true : false);
            mix.Skill       = res.Skill == -1 ? res2?.Item.Skill ?? false : (res.Skill > 0 ? true : false);
            mix.Option28    = (byte)(res.Option == -1 ? res2?.Item.Option28 ?? 0x00 : res.Option);
            mix.Character   = @char;
            mix.AccountId   = @char.Account.ID;
            mix.CharacterId = @char.Id;
            @char.Inventory.ChaosBox.Add(mix);

            return(ChaosBoxMixResult.Success);
        }
예제 #3
0
        public ChaosBoxMixResult Execute(Character @char, CChaosBoxItemMixButtonClick mixAditionalInfo = null)
        {
            var cbItems = @char.Inventory.ChaosBox.Items;
            var items   = cbItems.Select(x => x.Value);

            if (BaseCost > @char.Money)
            {
                return(ChaosBoxMixResult.InsufficientMoney);
            }

            @char.Money -= (uint)BaseCost;

            var ingOk = new Dictionary <IngredientInfo, int>();

            foreach (var ing in Ingredients)
            {
                var count = items.Where(x => ing.Match(x)).Count();
                if (ing.Count > count && !ingOk.Any(x => x.Key.IID == ing.IID))
                {
                    return(ChaosBoxMixResult.IncorrectItems);
                }

                ingOk.Add(ing, count);
            }

            var pairIng = (from ing in Ingredients
                           from it in cbItems
                           where ing.Match(it.Value)
                           select new { Address = it.Key, Item = it.Value, Ingredient = ing }).ToList();

            var leftItems = (from it in cbItems
                             where !pairIng.Any(x => x.Item == it.Value)
                             select it).ToList();

            var successRate = GeneralSuccess;

            foreach (var ing in ingOk)
            {
                var scalar = (ing.Value - ing.Key.Count);
                successRate += scalar * 10;
            }

            if (successRate > 100)
            {
                successRate = 100;
            }
            var rand = new Random();
            ChaosBoxMixResult result = ChaosBoxMixResult.Success;

            if (rand.Next(0, 100) > successRate - 1)
            {
                result = ChaosBoxMixResult.Fail;
            }

            @char.Inventory.DeleteChaosBox();

            var            prob = rand.Next(0, 100);
            IngredientInfo res  = null;

            if (result == ChaosBoxMixResult.Success)
            {
                foreach (var r in ResultSuccess)
                {
                    if (prob < r.Success)
                    {
                        res = r;
                        break;
                    }
                    prob -= r.Success;
                }
            }
            else
            {
                res = ResultFail;
            }

            if (res == null)
            {
                res = ResultSuccess.First();
            }

            var res2 = pairIng.FirstOrDefault(x => x.Ingredient.IID == res.IID);

            // find any Seed Spear
            var seed = pairIng.FirstOrDefault(x => x.Item.Number >= 6244 && x.Item.Number <= 6273);

            if (res.ItemNumber != ItemNumber.Invalid || res2 != null)
            {
                var mix = new Item(res.ItemNumber != ItemNumber.Invalid ? res.ItemNumber : res2.Item.Number);

                if (res.Level.Length == 1)
                {
                    mix.Plus = res.Level[0] == 255 ? res2.Item.Plus : (byte)res.Level[0];
                }
                else if (res.Level.Length == 2)
                {
                    mix.Plus = (byte)rand.Next(res.Level[0], res.Level[1]);
                }
                else
                {
                    mix.Plus = res2?.Item.Plus ?? 0;
                }

                if (res.Harmony != -1)
                {
                    mix.Harmony.Option = (byte)res.Harmony;
                    mix.Harmony.Level  = 0;
                }
                else
                {
                    mix.Harmony.Option = res2?.Item.Harmony.Option ?? 0;
                    mix.Harmony.Level  = res2?.Item.Harmony.Level ?? 0;
                }

                mix.Luck      = res.Luck == -1 ? res2?.Item.Luck ?? false : (res.Luck > 0 ? true : false);
                mix.Skill     = res.Skill == -1 ? res2?.Item.Skill ?? false : (res.Skill > 0 ? true : false);
                mix.Option28  = (byte)(res.Option == -1 ? res2?.Item.Option28 ?? 0x00 : res.Option);
                mix.OptionExe = (byte)(res.Excellent == -1 ? res2?.Item.OptionExe ?? 0x00 : res.Excellent);
                mix.SetOption = (byte)(res.SetOption == -1 ? res2?.Item.SetOption ?? 0x00 : res.SetOption);
                if (res.Socket != -1 && seed != null)
                {
                    var code  = seed.Item.Number.Index - 100;
                    var level = code / 6;
                    var type  = (SocketOption)(seed.Item.Plus + (code % 6) * 10 + level * 50);

                    mix.Slots = res2?.Item.Slots ?? new SocketOption[5];
                    mix.Slots[mixAditionalInfo.Info] = type;
                }
                mix.Character = @char;
                mix.Account   = @char.Account;
                mix.Character = @char;
                @char.Inventory.ChaosBox.Add(mix);
            }

            return(result);
        }
예제 #4
0
        public static void HandleRequest(HttpProcessor p, string jsonStr)
        {
            object response = null;

            try
            {
                dynamic requestObj = JsonConvert.DeserializeObject(jsonStr);
                string  cmd        = Try.Get(() => (string)requestObj.cmd);
                switch (cmd)
                {
                case "log_get":
                {
                    int  nextLine = (int)requestObj.nextLine;
                    long logId    = (long)requestObj.logId;
                    if (logId == -1)
                    {
                        logId = ServiceWrapper.logReader.readerId;
                    }
                    else if (logId != ServiceWrapper.logReader.readerId)
                    {
                        response = new ResultLogGet("REFRESH", -1, ServiceWrapper.logReader.readerId, null);
                        break;
                    }
                    List <string> lines = ServiceWrapper.logReader.GetLogUpdate(logId, ref nextLine);
                    response = new ResultLogGet("OK", nextLine, ServiceWrapper.logReader.readerId, lines);
                    break;
                }

                    #region Hotkeys
                case "hotkey_reorder":
                case "hotkey_names":
                case "hotkey_list":
                case "hotkey_new":
                case "hotkey_get":
                case "hotkey_update":
                case "hotkey_delete":
                {
                    response = NamedItemAPI(requestObj, ServiceWrapper.config.hotkeys);
                    break;
                }

                case "beginHotkeyBind":
                {
                    int    hotkeyId = requestObj.hotkeyId;
                    string bindId   = ServiceWrapper.hotkeyManager.BeginHotkeyBind(hotkeyId);
                    if (bindId == null)
                    {
                        response = new ResultFailWithReason("hotkey not found");
                    }
                    else if (bindId == "")
                    {
                        response = new ResultFailWithReason("another bind is already in progress");
                    }
                    else
                    {
                        response = new ResultWithData(bindId);
                    }
                    break;
                }

                case "endHotkeyBind":
                {
                    int    hotkeyId = requestObj.hotkeyId;
                    Hotkey hotkey   = ServiceWrapper.config.hotkeys.Get(hotkeyId);
                    if (hotkey == null)
                    {
                        response = new ResultFailWithReason("hotkey not found");
                        break;
                    }
                    string bindId = requestObj.bindId;
                    if (string.IsNullOrWhiteSpace(bindId))
                    {
                        response = new ResultFailWithReason("invalid bindId");
                        break;
                    }
                    while (bindId == ServiceWrapper.hotkeyManager.GetCurrentBindId())
                    {
                        Thread.Sleep(100);
                    }
                    response = new ResultWithData(hotkey);
                    break;
                }

                case "cancelHotkeyBind":
                {
                    string bindId = requestObj.bindId;
                    if (string.IsNullOrWhiteSpace(bindId))
                    {
                        response = new ResultFailWithReason("invalid bindId");
                        break;
                    }
                    ServiceWrapper.hotkeyManager.CancelHotkeyBind(bindId);
                    response = new ResultSuccess();
                    break;
                }

                case "unbindHotkey":
                {
                    string bindId = requestObj.bindId;
                    if (string.IsNullOrWhiteSpace(bindId))
                    {
                        response = new ResultFailWithReason("invalid bindId");
                        break;
                    }
                    Hotkey hotkey = ServiceWrapper.hotkeyManager.UnbindHotkey(bindId);
                    if (hotkey != null)
                    {
                        response = new ResultWithData(hotkey);
                    }
                    else
                    {
                        response = new ResultFailWithReason("Unable to unbind hotkey. Please try again.");
                    }
                    break;
                }

                case "executeHotkey":
                {
                    int    hotkeyId = requestObj.hotkeyId;
                    string error    = ServiceWrapper.hotkeyManager.ExecuteHotkeyById(hotkeyId);
                    if (error == null)
                    {
                        response = new ResultSuccess();
                    }
                    else
                    {
                        response = new ResultFailWithReason("Hotkey manual execution failed: " + error);
                    }
                    break;
                }

                    #endregion
                    #region BroadLink
                case "broadlink_reorder":
                case "broadlink_names":
                case "broadlink_list":
                case "broadlink_new":
                case "broadlink_get":
                case "broadlink_update":
                case "broadlink_delete":
                {
                    response = NamedItemAPI(requestObj, ServiceWrapper.config.broadLinks);
                    break;
                }

                case "broadlink_command_short_names":
                {
                    response = new ResultWithData(IRBlasters.IRCommands.GetIRCommandShortNames());
                    break;
                }

                    #endregion
                    #region BroadLink Commands
                case "broadlinkcmd_reorder":
                case "broadlinkcmd_names":
                case "broadlinkcmd_list":
                case "broadlinkcmd_new":
                case "broadlinkcmd_get":
                case "broadlinkcmd_update":
                case "broadlinkcmd_delete":
                {
                    response = NamedItemAPI(requestObj, BroadLinkCommands.commands, (Action)(() =>
                        {
                            BroadLinkCommands.Save(ServiceWrapper.BroadLinkCommandsFile);
                        }));
                    break;
                }

                case "broadlinkcmd_reload_commands":
                {
                    BroadLinkCommands.Load(ServiceWrapper.BroadLinkCommandsFile);
                    response = new ResultSuccess();
                    break;
                }

                case "beginBroadlinkCommandLearn":
                {
                    int    controllerId = requestObj.controllerId;
                    int    commandId    = requestObj.commandId;
                    string lessonId     = BroadLinkCommands.BeginLearning(controllerId, commandId);
                    if (lessonId == null)
                    {
                        response = new ResultFailWithReason("hotkey not found");
                    }
                    else if (lessonId == "")
                    {
                        response = new ResultFailWithReason("another bind is already in progress");
                    }
                    else
                    {
                        response = new ResultWithData(lessonId);
                    }
                    break;
                }

                case "endBroadlinkCommandLearn":
                {
                    int          controllerId = requestObj.controllerId;
                    int          commandId    = requestObj.commandId;
                    BroadLinkCmd command      = BroadLinkCommands.commands.Get(commandId);
                    if (command == null)
                    {
                        response = new ResultFailWithReason("command not found");
                        break;
                    }
                    string lessonId = requestObj.lessonId;
                    if (string.IsNullOrWhiteSpace(lessonId))
                    {
                        response = new ResultFailWithReason("invalid lessonId");
                        break;
                    }
                    BroadLinkCommands.AwaitLearningResult(controllerId, lessonId);
                    response = new ResultWithData(command);
                    break;
                }

                case "cancelBroadlinkCommandLearn":
                {
                    int    controllerId = requestObj.controllerId;
                    string lessonId     = requestObj.lessonId;
                    if (string.IsNullOrWhiteSpace(lessonId))
                    {
                        response = new ResultFailWithReason("invalid lessonId");
                        break;
                    }
                    BroadLinkCommands.CancelLearning(controllerId, lessonId);
                    response = new ResultSuccess();
                    break;
                }

                case "unlearnBroadlinkCommand":
                {
                    int    controllerId = requestObj.controllerId;
                    string lessonId     = requestObj.lessonId;
                    if (string.IsNullOrWhiteSpace(lessonId))
                    {
                        response = new ResultFailWithReason("invalid lessonId");
                        break;
                    }
                    BroadLinkCmd command = BroadLinkCommands.UnlearnCommandCodes(controllerId, lessonId);
                    if (command != null)
                    {
                        response = new ResultWithData(command);
                    }
                    else
                    {
                        response = new ResultFailWithReason("Unable to unbind command. Please try again.");
                    }
                    break;
                }

                    #endregion
                    #region iTach
                case "itach_reorder":
                case "itach_names":
                case "itach_list":
                case "itach_new":
                case "itach_get":
                case "itach_update":
                case "itach_delete":
                {
                    response = NamedItemAPI(requestObj, ServiceWrapper.config.iTachs);
                    break;
                }

                case "ir_command_short_names":
                {
                    response = new ResultWithData(IRBlasters.IRCommands.GetIRCommandShortNames());
                    break;
                }

                case "itach_reload_commands":
                {
                    iTachCommands.Load(ServiceWrapper.iTachCommandsFile);
                    response = new ResultSuccess();
                    break;
                }

                    #endregion
                    #region Vera
                case "vera_reorder":
                case "vera_names":
                case "vera_list":
                case "vera_new":
                case "vera_get":
                case "vera_update":
                case "vera_delete":
                {
                    response = NamedItemAPI(requestObj, ServiceWrapper.config.veras);
                    break;
                }

                case "vera_command_list":
                {
                    List <object> list = new List <object>();
                    Parallel.ForEach(ServiceWrapper.config.veras.List(), vera =>
                        {
                            ConcurrentDictionary <int, string> map = vera.GetDeviceIdToDisplayNameMap();
                            if (map != null)
                            {
                                int[] DeviceIds = map.Keys.ToArray();
                                string[] Names  = DeviceIds.Select(id => map[id]).ToArray();
                                lock (list)
                                {
                                    list.Add(new { Id = vera.id, Name = vera.name, DeviceIds = DeviceIds, Names = Names });
                                }
                            }
                        });
                    response = new ResultWithData(list);
                    break;
                }

                case "vera_reload_commands":
                {
                    int success = 0;
                    int failure = 0;
                    Parallel.ForEach(ServiceWrapper.config.veras.List(), vera =>
                        {
                            if (vera.LoadDisplayNames(true))
                            {
                                Interlocked.Increment(ref success);
                            }
                            else
                            {
                                Interlocked.Increment(ref failure);
                            }
                        });
                    response = new ResultWithData("Vera Command Loading complete. Successful loads: " + success + ". Failed loads: " + failure);
                    break;
                }

                    #endregion
                    #region HomeAssistant
                case "hass_reorder":
                case "hass_names":
                case "hass_list":
                case "hass_new":
                case "hass_get":
                case "hass_update":
                case "hass_delete":
                {
                    response = NamedItemAPI(requestObj, ServiceWrapper.config.homeAssistantServers);
                    break;
                }

                case "hass_entities":
                {
                    List <object> list = new List <object>();
                    Parallel.ForEach(ServiceWrapper.config.homeAssistantServers.List(), hass =>
                        {
                            List <object> listFromOneServer = hass.GetCommandList();
                            list.AddRange(listFromOneServer);
                        });
                    response = new ResultWithData(list);
                    break;
                }

                case "hass_load":
                {
                    int success = 0;
                    int failure = 0;
                    Parallel.ForEach(ServiceWrapper.config.homeAssistantServers.List(), hass =>
                        {
                            if (hass.Load())
                            {
                                Interlocked.Increment(ref success);
                            }
                            else
                            {
                                Interlocked.Increment(ref failure);
                            }
                        });
                    response = new ResultWithData("HomeAssistant Entity Loading complete. Successful loads: " + success + ". Failed loads: " + failure);
                    break;
                }

                    #endregion
                default:
                    response = new ResultFail()
                    {
                        error = "command \"" + cmd + "\" not supported"
                    };
                    break;
                }
            }
            catch (Exception ex)
            {
                Logger.Debug(ex);
                response = new ResultFail()
                {
                    error = "An unexpected error occurred. " + ex.ToString()
                };
            }
            finally
            {
                if (response == null)
                {
                    response = new ResultFail()
                    {
                        error = "Application Error: A response was not generated, so this response was generated as a fallback."
                    }
                }
                ;
                p.CompressResponseIfCompatible();
                p.writeSuccess(jsonType);
                p.outputStream.Write(JsonConvert.SerializeObject(response));
            }
        }