示例#1
0
        /// <summary>
        /// Saves the OutboundRule to the database.
        /// </summary>
        /// <param name="outboundRule">The OutboundRule to save.</param>
        public static void Save(OutboundRule outboundRule)
        {
            using (SqlConnection conn = MantaDB.GetSqlConnection())
            {
                SqlCommand cmd = conn.CreateCommand();
                cmd.CommandText = @"
IF EXISTS (SELECT 1 FROM man_rle_rule WHERE rle_mxPattern_id = @mxPatternID AND rle_ruleType_id = @type)
	BEGIN
		UPDATE man_rle_rule
		SET rle_rule_value = @value
		WHERE rle_mxPattern_id = @mxPatternID AND rle_ruleType_id = @type
	END
ELSE
	BEGIN
		INSERT INTO man_rle_rule(rle_mxPattern_id, rle_ruleType_id, rle_rule_value)
		VALUES(@mxPatternID, @type, @value)
	END
";
                cmd.Parameters.AddWithValue("@mxPatternID", outboundRule.OutboundMxPatternID);
                cmd.Parameters.AddWithValue("@type", (int)outboundRule.Type);
                cmd.Parameters.AddWithValue("@value", outboundRule.Value);
                conn.Open();
                cmd.ExecuteNonQuery();
            }
        }
示例#2
0
        internal bool CheckPrecondition(HttpContextBase httpContext, OutboundRule outboundRule)
        {
            Match lastConditionMatch  = null;
            bool  isPreconditionMatch = true;

            if (outboundRule == null)
            {
                return(isPreconditionMatch);
            }
            var precondition = outboundRule.Precondition;

            if (precondition == null)
            {
                return(isPreconditionMatch);
            }
            var conditions = precondition.Conditions;

            // test conditions matches
            if (conditions != null && conditions.Any())
            {
                var replacements = new RewriteHelper.Replacements
                {
                    RequestServerVariables = httpContext.Request.ServerVariables,
                    RequestHeaders         = httpContext.Request.Headers,
                    ResponseHeaders        = httpContext.Response.Headers
                };
                var conditionMatchResult = RewriteHelper.TestConditionMatches(precondition, replacements, out lastConditionMatch);
                isPreconditionMatch = conditionMatchResult.Matched;
            }

            return(isPreconditionMatch);
        }
示例#3
0
        public void ProcessRuleReplacementsWithMatchTagsAndExactMatch()
        {
            // arrange
            var responseString = OutboundRewriterTestData.ProcessRuleReplacementsWithMatchTagsInput;
            var outboundRule   = new OutboundRule
            {
                Using = Using.ExactMatch,
                OutboundMatchScope = new MatchResponseTags()
                {
                    MatchTheContentWithin = new List <MatchTag>
                    {
                        new MatchTag {
                            Tag = "a", Attribute = "href"
                        }
                    }
                },
                Pattern = @"/article\.aspx\?id=([0-9]+)(?:&|&amp;)title=([_0-9a-z-]+)$",
                Action  = new OutboundRewrite()
                {
                    Value = @"/newarticle.aspx"
                },
                MatchingScopeType = ScopeType.Response
            };

            // act
            var output = OutboundRewriter.ProcessRuleReplacements(responseString, outboundRule);

            // assert
            Assert.AreEqual(output, OutboundRewriterTestData.ProcessRuleReplacementsWithMatchTagsAndExactMatchExpectedOutput);
        }
示例#4
0
        public static OutboundRule ToOutboundRule(this OutboundRuleItem outboundRuleItem)
        {
            if (outboundRuleItem == null)
            {
                return(null);
            }

            var conditionItems = GetBaseConditionItems(outboundRuleItem);

            var outboundRule = new OutboundRule
            {
                ItemId = outboundRuleItem.ID.Guid,
                Name   = outboundRuleItem.Name
            };

            SetBaseRule(outboundRuleItem.BaseRuleItem, outboundRule);

            SetOutboundMatch(outboundRuleItem.OutboundMatchItem, outboundRule);

            GetPrecondition(outboundRuleItem.OutboundPreconditionItem, outboundRule);

            if (string.IsNullOrEmpty(outboundRuleItem.BaseRuleItem.BaseMatchItem.MatchPatternItem.Pattern.Value))
            {
                Log.Warn(logObject, outboundRuleItem.Database, "No pattern set on rule with ItemID: {0}", outboundRuleItem.ID);

                return(null);
            }

            if (outboundRuleItem.Action == null)
            {
                Log.Warn(logObject, outboundRuleItem.Database, "No action set on rule with ItemID: {0}", outboundRuleItem.ID);

                return(null);
            }

            var         baseActionItem = outboundRuleItem.Action.TargetItem;
            IBaseAction baseAction     = null;

            if (baseActionItem != null)
            {
                var baseActionItemTemplateId = baseActionItem.TemplateID.ToString();

                if (baseActionItemTemplateId.Equals(OutboundRewriteItem.TemplateId, StringComparison.InvariantCultureIgnoreCase))
                {
                    baseAction = new OutboundRewriteItem(baseActionItem).ToOutboundRewriteAction();
                }
            }
            outboundRule.Action = baseAction;

            if (conditionItems != null)
            {
                SetConditions(conditionItems, outboundRule);
            }

            return(outboundRule);
        }
示例#5
0
 public OutboundRuleListViewItem(OutboundRule item, RewritePage page)
     : base(item.Name)
 {
     Item  = item;
     _page = page;
     SubItems.Add(new ListViewSubItem(this, item.Input));
     SubItems.Add(new ListViewSubItem(this, item.Negate ? "Does not match" : "Matches"));
     SubItems.Add(new ListViewSubItem(this, item.Pattern));
     SubItems.Add(new ListViewSubItem(this, ToString(item.Action)));
     SubItems.Add(new ListViewSubItem(this, item.Value));
     SubItems.Add(new ListViewSubItem(this, item.Stopping ? "True" : "False"));
     SubItems.Add(new ListViewSubItem(this, item.Flag));
 }
示例#6
0
        public static string ProcessRuleReplacements(string responseString, OutboundRule outboundRule)
        {
            string output         = null;
            var    rewritePattern = outboundRule.Pattern;
            // TODO: Not all actions will be OutboundRewriteActions - fix this
            var rewrite               = ((OutboundRewrite)outboundRule.Action);
            var rewriteValue          = rewrite.Value;
            var rewriteMatchScope     = outboundRule.OutboundMatchScope;
            var rewriteMatchScopeType = outboundRule.MatchingScopeType;

            // TODO: catch invalid Regex compilations

            if (rewriteMatchScopeType == ScopeType.Response)
            {
                IEnumerable <MatchTag> matchTags = new List <MatchTag>();

                if (rewriteMatchScope is MatchResponseTags)
                {
                    var matchResponseTags = rewriteMatchScope as MatchResponseTags;
                    matchTags = matchResponseTags.MatchTheContentWithin ?? new List <MatchTag>();
                }

                // if we are not matching on match tags, then we are doing matching on the entire response
                if (matchTags.Any())
                {
                    output = ProcessRuleReplacementsWithMatchTags(responseString, outboundRule.Using, matchTags,
                                                                  rewritePattern, rewriteValue);
                }
                else
                {
                    if (outboundRule.Using == Using.ExactMatch)
                    {
                        output = responseString.Replace(rewritePattern, rewriteValue);
                    }
                    else
                    {
                        var responseRegex = new Regex(rewritePattern);

                        output = responseRegex.Replace(responseString,
                                                       match => RewriteHelper.ReplaceRuleBackReferences(match, rewriteValue));
                    }
                }
            }
            else if (rewriteMatchScopeType == ScopeType.ServerVariables)
            {
            }

            return(output);
        }
示例#7
0
        public void Run(params string[] args)
        {
            PhoneSystem  ps = PhoneSystem.Root;
            Tenant       t  = ps.GetTenants()[0];
            OutboundRule r  = t.CreateOutboundRule();

            r.OutboundRoutes[0].Gateway = ps.GetGateways()[0];
            try
            {
                //this line should throw an exception
                r.OutboundRoutes[5].Gateway = ps.GetGateways()[0];
            }
            catch (IndexOutOfRangeException)
            {
                Console.WriteLine("Number of available routes is " + r.OutboundRoutes.Length + " by default");
            }
            r.Save();
            Console.WriteLine(r);
        }
示例#8
0
        public void ProcessRuleReplacementsWithNoMatchTags()
        {
            // arrange
            var responseString = OutboundRewriterTestData.ProcessRuleReplacementsWithMatchTagsInput;
            var outboundRule   = new OutboundRule
            {
                Pattern = @"/article\.aspx\?id=([0-9]+)(?:&|&amp;)title=([_0-9a-z-]+)",
                Action  = new OutboundRewrite()
                {
                    Value = @"/article/{R:1}/{R:2}"
                },
                MatchingScopeType = ScopeType.Response
            };

            // act
            var output = OutboundRewriter.ProcessRuleReplacements(responseString, outboundRule);

            // assert
            Assert.AreEqual(output, OutboundRewriterTestData.ProcessRuleReplacementsWithMatchTagsExpectedOutput);
        }
        private async Task AddOutboundRule(Message message)
        {
            await _telegramBotClient.SendTextMessageAsync(message.Chat.Id, "\U0001F4C0 Adding outbound rule...");

            var session       = _sessionRepo.Get(message.From.Id);
            var outboundRules = new List <OutboundRule>();
            var userRules     = message.Text.Split(';');

            foreach (var rule in userRules)
            {
                var ruleData = rule.Split(':');
                if (ruleData.Length == 3)
                {
                    var inboundRule = new OutboundRule
                    {
                        Protocol     = ruleData[0],
                        Ports        = ruleData[1],
                        Destinations = new SourceLocation
                        {
                            Addresses = ruleData[2].Split(',').ToList()
                        }
                    };

                    outboundRules.Add(inboundRule);
                }
                else
                {
                    await _telegramBotClient.SendTextMessageAsync(message.Chat.Id, $"Invalid rule: {rule.Replace(".", "\\.")}\nPlease, try again", ParseMode.MarkdownV2);

                    return;
                }
            }

            var digitalOceanApi = _digitalOceanClientFactory.GetInstance(message.From.Id);
            await digitalOceanApi.Firewalls.AddRules((string)session.Data, new FirewallRules
            {
                OutboundRules = outboundRules
            });

            await _telegramBotClient.SendTextMessageAsync(message.Chat.Id, $"Done \U00002705", ParseMode.MarkdownV2);
        }
示例#10
0
        public void ProcessRuleReplacementsWithExactMatch()
        {
            // arrange
            var responseString = OutboundRewriterTestData.ProcessRuleReplacementsWithMatchTagsInput;
            var outboundRule   = new OutboundRule
            {
                Using   = Using.ExactMatch,
                Pattern = @"</body>",
                Action  = new OutboundRewrite()
                {
                    Value = @"<script type='text/javascript'>//Your web analytics tracking code goes here...</script></body>"
                },
                MatchingScopeType = ScopeType.Response
            };

            // act
            var output = OutboundRewriter.ProcessRuleReplacements(responseString, outboundRule);

            // assert
            Assert.AreEqual(output, OutboundRewriterTestData.ProcessRuleReplacementsWithExactMatchExpectedOutput);
        }
示例#11
0
        public void Run(params string[] args)
        {
            PhoneSystem  ps = PhoneSystem.Root;
            Tenant       t  = ps.GetTenants()[0];
            OutboundRule r  = t.CreateOutboundRule();

            r.Name                      = "OMSamples Test Rule";
            r.NumberOfRoutes            = 5;                                             //must be set to specify 5 routes. otherwise it is only 3 routes.
            r.Priority                  = t.GetOutboundRules().Max(x => x.Priority) + 1; //lowest priority of rule. must be unique.
            r.OutboundRoutes[0].Gateway = ps.GetGateways()[0];                           //make first route to any gateway object available in configuration.
            try
            {
                //should fail.
                r.OutboundRoutes[5].Gateway = ps.GetGateways()[0];
            }
            catch (IndexOutOfRangeException)
            {
                Console.WriteLine("Number of available routes is " + r.OutboundRoutes.Length);
                r.OutboundRoutes[4].Gateway = ps.GetGateways()[0]; //it is fifth route of outbound rule.
            }
            r.Save();
            Console.WriteLine(r);
        }
示例#12
0
        private static void GetPrecondition(OutboundPreconditionItem outboundPreconditionItem, OutboundRule outboundRule)
        {
            if (outboundPreconditionItem == null || outboundPreconditionItem.Precondition == null ||
                outboundPreconditionItem.Precondition.TargetItem == null)
            {
                return;
            }

            var preconditionTargetItem = outboundPreconditionItem.Precondition.TargetItem;
            var preconditionItem       = new PreconditionItem(preconditionTargetItem);

            var precondition = new Precondition
            {
                Name = preconditionItem.Name,
            };

            var conditionItems = GetBaseConditionItems(preconditionItem);

            if (conditionItems != null)
            {
                SetConditions(conditionItems, precondition);
            }

            var   usingItem = preconditionItem.PreconditionUsingItem.Using.TargetItem;
            Using?usingType = null;

            if (usingItem != null)
            {
                var usingItemId = usingItem.ID.ToString();
                switch (usingItemId)
                {
                case Constants.UsingType_RegularExpressions_ItemId:
                    usingType = Using.RegularExpressions;
                    break;

                case Constants.UsingType_Wildcards_ItemId:
                    usingType = Using.Wildcards;
                    break;

                case Constants.UsingType_ExactMatch_ItemId:
                    usingType = Using.ExactMatch;
                    break;

                default:
                    break;
                }
            }
            precondition.Using = usingType;

            SetConditionLogicalGrouping(preconditionItem.ConditionLogicalGroupingItem, precondition);

            outboundRule.Precondition = precondition;
        }
示例#13
0
        /// <summary>
        /// Create and fill an OutboundRule object from the Data Record.
        /// </summary>
        /// <param name="record">Datarecord containing values for the new object.</param>
        /// <returns>OutboundRule object.</returns>
        private static OutboundRule CreateAndFillOutboundRule(IDataRecord record)
        {
            OutboundRule rule = new OutboundRule(record.GetInt32("rle_mxPattern_id"), (OutboundRuleType)record.GetInt32("rle_ruleType_id"), record.GetString("rle_rule_value"));

            return(rule);
        }
示例#14
0
文件: Program.cs 项目: lexluga/3cx-1
        private static void CreateAndSaveOutboundRule(PhoneSystem ps, Tenant tenant, OutBoundRuleDetails outbound_rule_to_create)
        {
            OutboundRule[] rules = tenant.GetOutboundRules();
            int            last_maximum_priority = 0;



            /* Determine the highest priority outbound rule in the system at the moment.
             * While we're here, might as well see if this new rule exists or not...there are allowed to be duplicates though */
            foreach (OutboundRule rule in rules)
            {
                if (rule.Priority > last_maximum_priority)
                {
                    last_maximum_priority = rule.Priority;
                }

                if (rule.Name.Equals(outbound_rule_to_create.Name) == true)
                {
                    if (isDebug)
                    {
                        LogMessage("Duplicate rule found, " + rule.Name, Severity.Warn);
                    }
                }

                if (print_rules == true)
                {
                    LogMessage(rule.Name, Severity.Info);
                }
            }

            if (tenant != null)
            {
                OutboundRule outbound_rule = null;
                outbound_rule = tenant.CreateOutboundRule();

                if (outbound_rule != null)
                {
                    /* Populate the outbound rule, using defaults where non is explicity set */

                    outbound_rule.Name               = String.IsNullOrEmpty(outbound_rule_to_create.Name) ? outbound_rule.Name : outbound_rule_to_create.Name;
                    outbound_rule.Prefix             = String.IsNullOrEmpty(outbound_rule_to_create.Prefix) ? outbound_rule.Prefix : outbound_rule_to_create.Prefix;
                    outbound_rule.NumberLengthRanges = String.IsNullOrEmpty(outbound_rule_to_create.Calls_to_numbers_with_a_length_of) ? outbound_rule.NumberLengthRanges : outbound_rule_to_create.Calls_to_numbers_with_a_length_of;

                    /* Get a list of gateways the system is aware of */

                    Gateway[] gateways = ps.GetGateways();
                    bool      found_user_specified_gateway_in_system = false;
                    if (gateways.Length > 0)
                    {
                        foreach (Gateway gw in gateways)
                        {
                            if (print_gateways)
                            {
                                LogMessage(String.Format("GATEWAY {0}", gw.Name), Severity.Info);
                            }

                            /* GetAppPath the gateways that the user wants to add to this outbound_rule_to_create rule */

                            if (gw.Name.Equals(outbound_rule_to_create.Outbound_route[0].name) == true)
                            {
                                outbound_rule.OutboundRoutes[0].Gateway = gw;
                                found_user_specified_gateway_in_system  = true;
                            }
                        }
                        outbound_rule.OutboundRoutes[0].Prepend     = outbound_rule_to_create.Outbound_route[0].prepend;
                        outbound_rule.OutboundRoutes[0].StripDigits = outbound_rule_to_create.Outbound_route[0].strip_count;
                    }
                    else
                    {
                        LogMessage("No gateways are defined in the system, no specifying one in the outbound rule", Severity.Warn);
                    }

                    /*Use default gateway if one is available and we cant find the use specified gateway name*/
                    if (!found_user_specified_gateway_in_system && gateways.Length > 0)
                    {
                        outbound_rule.OutboundRoutes[0].Gateway = gateways[0];
                        LogMessage("Using default gateway as route for outbound rule - route not found or not provided.", Severity.Warn);
                    }



                    if (outbound_rule_to_create.External_lines != null)
                    {
                        if (outbound_rule_to_create.External_lines.Length > 0)
                        {
                            outbound_rule.ExternalLines = outbound_rule_to_create.External_lines;
                        }
                    }

                    if (String.IsNullOrEmpty(outbound_rule_to_create.ExtensionRange) == false)
                    {
                        string[] ranges = outbound_rule_to_create.ExtensionRange.Split(',');
                        //allocate space for extensio nranges
                        DNRange[] made_ranges = new DNRange[ranges.Length];

                        for (int i = 0; i < ranges.Length; i++)
                        {
                            made_ranges[i] = outbound_rule.CreateDNRange();
                            if (ranges[i].Contains("-") == true)
                            {
                                string[] toAndFrom = ranges[i].Split('-');
                                made_ranges[i].From = toAndFrom[0];
                                made_ranges[i].To   = toAndFrom[1];
                            }
                            else
                            {
                                // no range just single extension
                                made_ranges[i].From = ranges[i];
                                made_ranges[i].To   = ranges[i];
                            }
                        }
                        outbound_rule.DNRanges = made_ranges;
                    }

                    if (outbound_rule_to_create.DNGroups != null)
                    {
                        if (outbound_rule_to_create.DNGroups.Length > 0)
                        {
                            outbound_rule.DNGroups = outbound_rule_to_create.DNGroups;
                        }
                    }

                    /* NB - ensure that the priority of the successive Outbound rules are at consecutive multiples of 5 larger than the highest priority in the system */
                    outbound_rule.Priority = last_maximum_priority + 5; //this is a static variable because we cannot determine which order the last outbound rule was saved in when calling GetOutBoundRules
                    outbound_rule.Save();                               // Save it to the system
                    tenant.Refresh();                                   // This is so that the next call to the Tenant Object's GetOutboundRules() contains reference to the rule we just created.
                    LogMessage("Saved outbound rule, " + outbound_rule.Name, Severity.Info);
                }
                else
                {
                    LogMessage("Could not create/allocate an Outbound rule template to use to create a new rule.", Severity.Critical);
                }
            }
            else
            {
                LogMessage("Tenant " + tenant.Name + " is not found but is required.", Severity.Critical);
            }
        }
示例#15
0
        public async Task ExecuteHandlerAsync(Message message)
        {
            var firewallId = _storageService.Get <string>(StorageKeys.FirewallId);

            if (string.IsNullOrEmpty(firewallId))
            {
                return;
            }

            var outboundRules = new List <OutboundRule>();
            var invalidRules  = new List <string>();
            var rules         = message.Text.Split(";");
            var regExp        = new Regex(RegExpPatterns.NetworkAddress);

            foreach (var rule in rules)
            {
                var resultMatch = regExp.Match(rule);

                if (resultMatch.Success)
                {
                    var inboundRule = new OutboundRule
                    {
                        Protocol     = resultMatch.Groups[1].Value,
                        Ports        = resultMatch.Groups[2].Value,
                        Destinations = new SourceLocation
                        {
                            Addresses = new List <string>
                            {
                                $"{resultMatch.Groups[3].Value}/{resultMatch.Groups[4].Value}"
                            }
                        }
                    };

                    outboundRules.Add(inboundRule);
                }
                else
                {
                    invalidRules.Add(rule);
                }
            }

            if (outboundRules.Count > 0)
            {
                await _digitalOceanClient.Firewalls.AddRules(firewallId, new FirewallRules
                {
                    OutboundRules = outboundRules
                });

                await _telegramBotClient.SendTextMessageAsync(
                    chatId : message.Chat.Id,
                    text : FirewallMessage.GetCreatedBoundRulesMessage(outboundRules.Count),
                    parseMode : ParseMode.Markdown);
            }

            if (invalidRules.Count > 0)
            {
                await _telegramBotClient.SendTextMessageAsync(
                    chatId : message.Chat.Id,
                    text : FirewallMessage.GetInvalidBoundRulesMessage(invalidRules),
                    parseMode : ParseMode.Html);
            }

            _storageService.AddOrUpdate(StorageKeys.BotCurrentState, BotStateType.None);
        }
示例#16
0
        private OutboundRuleResult ProcessOutboundRule(HttpContextBase httpContext, string responseString, OutboundRule outboundRule)
        {
            //Log.Debug(this, "Processing inbound rule - requestUri: {0} inboundRule: {1}", originalUri, inboundRule.Name);

            var ruleResult = new OutboundRuleResult()
            {
                OriginalResponseString  = responseString,
                RewrittenResponseString = responseString
            };

            switch (outboundRule.Using)
            {
            case Using.ExactMatch:
            case Using.RegularExpressions:
            case Using.Wildcards:
                ruleResult = ProcessRegularExpressionOutboundRule(ruleResult, outboundRule);

                break;
                //case Using.Wildcards:
                //    //TODO: Implement Wildcards
                //    throw new NotImplementedException("Using Wildcards has not been implemented");
                //    break;
            }

            //Log.Debug(this, "Processing inbound rule - requestUri: {0} inboundRule: {1} rewrittenUrl: {2}", ruleResult.OriginalUri, inboundRule.Name, ruleResult.RewrittenUri);

            //ruleResult.ItemId = inboundRule.ItemId;

            return(ruleResult);
        }
示例#17
0
        private OutboundRuleResult ProcessRegularExpressionOutboundRule(OutboundRuleResult ruleResult, OutboundRule outboundRule)
        {
            Match outboundRuleMatch,
                  lastConditionMatch = null;

            // test rule match
            var isRuleMatch = true;
            ConditionMatchResult conditionMatchResult = null;

            // test conditions matches
            if (outboundRule.Conditions != null && outboundRule.Conditions.Any())
            {
                var replacements = new RewriteHelper.Replacements
                {
                    RequestHeaders         = RequestHeaders,
                    RequestServerVariables = RequestServerVariables,
                    ResponseHeaders        = ResponseHeaders
                };

                conditionMatchResult = RewriteHelper.TestConditionMatches(outboundRule, replacements, out lastConditionMatch);
                isRuleMatch          = conditionMatchResult.Matched;
            }

            if (isRuleMatch)
            {
                ruleResult.RewrittenResponseString = ProcessRuleReplacements(ruleResult.OriginalResponseString, outboundRule);
                ruleResult.RuleMatched             = true;
            }

            return(ruleResult);
        }
示例#18
0
 /// <summary>
 /// Saves the OutboundRule.
 /// </summary>
 /// <param name="rule">The rule to save.</param>
 public static void Save(OutboundRule rule)
 {
     DAL.OutboundRulesDB.Save(rule);
 }
        public void Run(params string[] args)
        {
            PhoneSystem ps     = PhoneSystem.Root;
            int         showid = 0;

            switch (args[1])
            {
            case "create":
            case "update":
            {
                OutboundRule rule = args[1] == "create" ? ps.GetTenant().CreateOutboundRule() : ps.GetByID <OutboundRule>(int.Parse(args[2]));
                foreach (var paramdata in args.Skip(3).Select(x => x.Split('=')))
                {
                    var paramname  = paramdata[0];
                    var paramvalue = paramdata[1];
                    switch (paramname)
                    {
                    case "PREFIX":
                        rule.Prefix = paramvalue;
                        break;

                    case "PRIORITY":
                        rule.Priority = int.Parse(paramvalue);
                        break;

                    case "NUMBERLENGTH":
                        rule.NumberLengthRanges = paramvalue;
                        break;

                    case "DNRENGES":
                        rule.DNRanges = paramvalue.Split(',').Select(x => x.Split('-')).Select(x => { var range = rule.CreateDNRange(); range.From = x[0]; range.To = x.Length > 1 ? x[1] : x[0]; return(range); }).ToArray();
                        break;

                    case "GROUPS":
                        rule.DNGroups = paramvalue.Split(',').Where(x => !string.IsNullOrEmpty(x)).Select(x => ps.GetGroupByName(x)).ToArray();
                        break;

                    case "NAME":
                        using (var existing = ps.GetAll <OutboundRule>().GetDisposer(x => x.Name == paramvalue).ExtractFirstOrDefault())
                        {
                            if (existing != null)
                            {
                                throw new ArgumentException($"Outbound rule where NAME='{paramvalue}' already exists - {existing}");
                            }
                        }
                        rule.Name = paramvalue;
                        break;

                    default:
                        if (paramname.StartsWith("ROUTE"))
                        {
                            var routenumber = int.Parse(paramname.Substring(5));
                            if (routenumber < 1 || routenumber > 5)
                            {
                                throw new ArgumentOutOfRangeException("Only 5 routes [1..5] are allowed");
                            }
                            if (routenumber > rule.NumberOfRoutes)
                            {
                                rule.NumberOfRoutes = routenumber;
                            }
                            var routeindex = routenumber - 1;
                            var routeParam = paramvalue.Split('.');

                            rule[routeindex].StripDigits = byte.Parse(routeParam[0]);
                            rule[routeindex].Prepend     = routeParam[1];
                            var gwid = routeParam.Skip(2).FirstOrDefault();
                            rule[routeindex].Gateway = string.IsNullOrEmpty(gwid) ? null : (ps.GetByID <Gateway>(int.Parse(gwid)) ?? throw new ArgumentException($"Gateway.{gwid} is not found"));
                        }
                        else
                        {
                            throw new ArgumentException($"Unknown parameter {paramname}");
                        }
                        break;
                    }
                }
                rule.Save();
            }
            break;

            case "delete":
                ps.GetByID <OutboundRule>(int.Parse(args[2])).Delete();
                return;

            case "gateways":
                Console.WriteLine($"{string.Join("\n", ps.GetAll<Gateway>().Select(x => $"{x}"))}");
                return;

            case "show":
                break;

            default:
                throw new ArgumentException("Invalid action name");
            }
            using (var outboundrules = (showid != 0 ? new OutboundRule[] { ps.GetByID <OutboundRule>(showid) } : ps.GetAll <OutboundRule>().ToArray()).GetDisposer())
            {
                var first = outboundrules.First();
                foreach (var or in outboundrules)
                {
                    Console.WriteLine($"{or}");
                    Console.WriteLine($"\tNAME={or.Name}");
                    Console.WriteLine($"\tPREFIX={or.Prefix}");
                    Console.WriteLine($"\tPRIORITY={or.Priority}");
                    Console.WriteLine($"\tNUMBERLENGTH={or.NumberLengthRanges}");
                    Console.WriteLine($"\tGROUPS={string.Join(",", or.DNGroups.Select(x => x.Name))}");
                    Console.WriteLine($"\tDNRANGES={string.Join(",", or.DNRanges.Select(x => $"{x.From }-{x.To}"))}");
                    int i = 0;
                    Console.WriteLine($"\t{string.Join("\n\t", or.Select(x => $"ROUTE{++i}={x}"))}");
                }
            }
        }