OLD | NEW |
(Empty) | |
| 1 #include "ElemHideBase.h" |
| 2 #include "ElemHideFilter.h" |
| 3 #include "ElemHideException.h" |
| 4 #include "CSSPropertyFilter.h" |
| 5 #include "InvalidFilter.h" |
| 6 #include "StringScanner.h" |
| 7 |
| 8 ElemHideBase::ElemHideBase(const String& text, |
| 9 String::size_type domainsEnd, String::size_type selectorStart) |
| 10 : ActiveFilter(text, false), |
| 11 mSelector(String(mText, selectorStart)) |
| 12 { |
| 13 if (domainsEnd) |
| 14 ParseDomains(String(mText, 0, domainsEnd), u','); |
| 15 } |
| 16 |
| 17 Filter::Type ElemHideBase::Parse(const String& text, |
| 18 String::size_type* domainsEnd, |
| 19 String::size_type* selectorStart, |
| 20 String::size_type* prefixEnd, |
| 21 String::size_type* regexpStart, |
| 22 String::size_type* regexpEnd, |
| 23 String::size_type* suffixStart) |
| 24 { |
| 25 StringScanner scanner(text); |
| 26 |
| 27 // Domains part |
| 28 loop: |
| 29 while (!scanner.done()) |
| 30 { |
| 31 String::value_type next = scanner.next(); |
| 32 if (next == u'#') |
| 33 { |
| 34 *domainsEnd = scanner.position(); |
| 35 break; |
| 36 } |
| 37 |
| 38 switch (next) |
| 39 { |
| 40 case u'/': |
| 41 case u'*': |
| 42 case u'|': |
| 43 case u'@': |
| 44 case u'"': |
| 45 case u'!': |
| 46 return Type::UNKNOWN; |
| 47 } |
| 48 } |
| 49 |
| 50 bool exception = false; |
| 51 String::value_type next = scanner.next(); |
| 52 if (next == u'@') |
| 53 { |
| 54 exception = true; |
| 55 next = scanner.next(); |
| 56 } |
| 57 |
| 58 if (next != u'#') |
| 59 return Type::UNKNOWN; |
| 60 |
| 61 // Selector part |
| 62 |
| 63 // Selector shouldn't be empty |
| 64 if (scanner.done()) |
| 65 return Type::UNKNOWN; |
| 66 |
| 67 *selectorStart = scanner.position() + 1; |
| 68 while (!scanner.done()) |
| 69 { |
| 70 switch (scanner.next()) |
| 71 { |
| 72 case u'{': |
| 73 case u'}': |
| 74 return Type::UNKNOWN; |
| 75 } |
| 76 } |
| 77 |
| 78 if (exception) |
| 79 return Type::ELEMHIDEEXCEPTION; |
| 80 |
| 81 do |
| 82 { |
| 83 // Is this a CSS property rule maybe? |
| 84 if (!prefixEnd) |
| 85 { |
| 86 // Caller doesn't care |
| 87 break; |
| 88 } |
| 89 |
| 90 String searchString(u"[-abp-properties="_str); |
| 91 *prefixEnd = text.find(searchString, *selectorStart); |
| 92 if (*prefixEnd == text.npos || |
| 93 *prefixEnd + searchString.length() + 1 >= text.length()) |
| 94 { |
| 95 break; |
| 96 } |
| 97 |
| 98 *regexpStart = *prefixEnd + searchString.length() + 1; |
| 99 char16_t quotation = text[*regexpStart - 1]; |
| 100 if (quotation != u'\'' && quotation != u'"') |
| 101 break; |
| 102 |
| 103 *regexpEnd = text.find(quotation, *regexpStart); |
| 104 if (*regexpEnd == text.npos || *regexpEnd + 1 >= text.length() || |
| 105 text[*regexpEnd + 1] != u']') |
| 106 { |
| 107 break; |
| 108 } |
| 109 |
| 110 *suffixStart = *regexpEnd + 2; |
| 111 return Type::CSSPROPERTY; |
| 112 } while (false); |
| 113 |
| 114 return Type::ELEMHIDE; |
| 115 } |
| 116 |
| 117 Filter* ElemHideBase::Create(const String& text) |
| 118 { |
| 119 size_t domainsEnd; |
| 120 size_t selectorStart; |
| 121 size_t prefixEnd; |
| 122 size_t regexpStart; |
| 123 size_t regexpEnd; |
| 124 size_t suffixStart; |
| 125 Type type = Parse(text, &domainsEnd, &selectorStart, &prefixEnd, ®expStart, |
| 126 ®expEnd, &suffixStart); |
| 127 if (type == Type::UNKNOWN) |
| 128 return nullptr; |
| 129 |
| 130 try |
| 131 { |
| 132 if (type == Type::ELEMHIDEEXCEPTION) |
| 133 return new ElemHideException(text, domainsEnd, selectorStart); |
| 134 else if (type == Type::CSSPROPERTY) |
| 135 { |
| 136 return new CSSPropertyFilter(text, domainsEnd, selectorStart, prefixEnd, |
| 137 regexpStart, regexpEnd, suffixStart); |
| 138 } |
| 139 else |
| 140 return new ElemHideFilter(text, domainsEnd, selectorStart); |
| 141 } |
| 142 catch (const String& e) |
| 143 { |
| 144 return new InvalidFilter(text, e); |
| 145 } |
| 146 } |
| 147 |
| 148 String ElemHideBase::GetSelectorDomain() const |
| 149 { |
| 150 /* TODO this is inefficient */ |
| 151 String result; |
| 152 if (mDomains) |
| 153 { |
| 154 for (auto it = mDomains->begin(); it != mDomains->end(); ++it) |
| 155 { |
| 156 if (it->second && !it->first.empty()) |
| 157 { |
| 158 if (!result.empty()) |
| 159 result.append(u','); |
| 160 result.append(it->first); |
| 161 } |
| 162 } |
| 163 } |
| 164 return std::move(result); |
| 165 } |
OLD | NEW |