예제 #1
0
        public void Parse(string ruleset)
        {
            int rlen      = ruleset.Length;
            int lineCount = 0;

            for (int i = 0; i < ruleset.Length; i++)
            {
                if (ruleset[i] == '\n')
                {
                    lineCount++;
                }
            }

            blackDomainList         = new List <SubRange>(lineCount / 2);
            blackWildcardDomainList = new List <SubRange>();
            blackRegexUrlList       = new List <Regex>();
            blackWildcardUrlList    = new List <SubRange>(lineCount / 2);
            whiteDomainList         = new List <SubRange>();
            whiteWildcardDomainList = new List <SubRange>();
            whiteRegexUrlList       = new List <Regex>();
            whiteWildcardUrlList    = new List <SubRange>();
            if (rlen > 1024)
            {
                resultCache     = new Dictionary <string, bool>(32);
                resultCacheLock = new ReaderWriterLockSlim();
                computingLocks  = new Dictionary <string, ManualResetEvent>();
            }

            var bssb = new StringBuilder(ruleset.Length);

            RulesCount = 0;
            int cur     = 0;
            int lineNum = 0;

            while (cur < rlen)
            {
                var begin = cur;
                while (cur < rlen && ruleset[cur++] != '\n')
                {
                }
                var line = new SubString()
                {
                    str    = ruleset,
                    Offset = begin,
                    Length = cur - begin
                };
                lineNum++;
                line.TrimSelf();
                if (line.Length == 0)
                {
                    continue;
                }
                var firstCh = line[0];
                if (firstCh == '!' || firstCh == '#' || firstCh == '[')
                {
                    continue;
                }
                RulesCount++;
                var ch0 = line.CharOrZero(0);
                var ch1 = line.CharOrZero(1);
                var ch2 = line.CharOrZero(2);
                var ch3 = line.CharOrZero(3);
                if (ch0 == '|')
                {
                    if (ch1 == '|')   // ||
                    {
                        const int lineOffset = 2;
                        var       offset     = bssb.Length;
                        var       len        = line.Length - 2;
                        if (line.Contains('*', 2))
                        {
                            // add "*." + value
                            bssb.Append("*.");
                            line.AppendTo(bssb, lineOffset);
                            blackWildcardDomainList.Add(new SubRange(offset, len + 2));
                            // and value without "*."
                            blackWildcardDomainList.Add(new SubRange(offset + 2, len));
                        }
                        else
                        {
                            line.AppendTo(bssb, lineOffset);
                            blackDomainList.Add(new SubRange(offset, len));
                        }
                    }
                    else     // |
                    {
                        var offset = bssb.Length;
                        var len    = line.Length - 1 + 1;
                        //var wc = line.Substring(1) + "*";
                        line.AppendTo(bssb, 1); bssb.Append('*');
                        blackWildcardUrlList.Add(new SubRange(offset, len));
                    }
                }
                else if (ch0 == '@' & ch1 == '@')
                {
                    if (ch2 == '|')
                    {
                        if (ch3 == '|')   // @@||
                        {
                            const int lineOffset = 4;
                            var       offset     = bssb.Length;
                            var       len        = line.Length - 4;
                            if (line.Contains('*', 4))
                            {
                                // add "*." + value
                                bssb.Append("*.");
                                line.AppendTo(bssb, lineOffset);
                                whiteWildcardDomainList.Add(new SubRange(offset, len + 2));
                                // and value without "*."
                                whiteWildcardDomainList.Add(new SubRange(offset + 2, len));
                            }
                            else
                            {
                                line.AppendTo(bssb, lineOffset);
                                whiteDomainList.Add(new SubRange(offset, len));
                            }
                        }
                        else     // @@|
                        {
                            var offset = bssb.Length;
                            var len    = line.Length - 3 + 1;
                            //var wc = line.Substring(3) + "*";
                            line.AppendTo(bssb, 3); bssb.Append('*');
                            whiteWildcardUrlList.Add(new SubRange(offset, len));
                        }
                    }
                    else     // @@
                    {
                        if (ch2.IsValidDomainCharacter() || ch2 == '*')
                        {
                            var offset = bssb.Length;
                            var len    = line.Length - 2 + 2;
                            //var wc = "*" + line.Substring(2) + "*";
                            bssb.Append('*'); line.AppendTo(bssb, 2); bssb.Append('*');
                            whiteWildcardUrlList.Add(new SubRange(offset, len));
                        }
                        else if (ch2 == '/')
                        {
                            var regex = Regex.Match(line.Get(), "/(.+)/");
                            if (regex.Success)
                            {
                                whiteRegexUrlList.Add(new Regex(regex.Groups[1].Value, RegexOptions.ECMAScript));
                            }
                        }
                    }
                }
                else if (ch0.IsValidDomainCharacter() || ch0 == '*')
                {
                    //var wc = "*" + line + "*";
                    var offset = bssb.Length;
                    var len    = line.Length + 2;
                    bssb.Append('*').Append(line).Append('*');
                    blackWildcardUrlList.Add(new SubRange(offset, len));
                }
                else if (ch0 == '/')
                {
                    var regex = Regex.Match(line.Get(), "/(.+)/");
                    if (regex.Success)
                    {
                        blackRegexUrlList.Add(new Regex(regex.Groups[1].Value, RegexOptions.ECMAScript));
                    }
                    else
                    {
                        goto WRONG;
                    }
                }
                else
                {
                    goto WRONG;
                }
                continue;
WRONG:
                RulesCount--;
                Logg?.warning($"unsupported/wrong ABP filter at line {lineNum}: {line.Get().Quoted()}");
            }
            bigString = bssb.ToString();
            blackDomainList.TrimExcess();
            blackWildcardDomainList.TrimExcess();
            blackRegexUrlList.TrimExcess();
            blackWildcardUrlList.TrimExcess();
            whiteDomainList.TrimExcess();
            whiteWildcardDomainList.TrimExcess();
            whiteRegexUrlList.TrimExcess();
            whiteWildcardUrlList.TrimExcess();
        }