| Left: | ||
| Right: |
| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
| 3 * Copyright (C) 2006-present eyeo GmbH | 3 * Copyright (C) 2006-present eyeo GmbH |
| 4 * | 4 * |
| 5 * Adblock Plus is free software: you can redistribute it and/or modify | 5 * Adblock Plus is free software: you can redistribute it and/or modify |
| 6 * it under the terms of the GNU General Public License version 3 as | 6 * it under the terms of the GNU General Public License version 3 as |
| 7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
| 8 * | 8 * |
| 9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 45 else | 45 else |
| 46 text[pos - delta] = text[pos]; | 46 text[pos - delta] = text[pos]; |
| 47 } | 47 } |
| 48 selectorStart -= delta; | 48 selectorStart -= delta; |
| 49 | 49 |
| 50 text.reset(text, 0, len - delta); | 50 text.reset(text, 0, len - delta); |
| 51 } | 51 } |
| 52 } | 52 } |
| 53 | 53 |
| 54 ElemHideBase::ElemHideBase(Type type, const String& text, const ElemHideData& da ta) | 54 ElemHideBase::ElemHideBase(Type type, const String& text, const ElemHideData& da ta) |
| 55 : ActiveFilter(type, text, false), mData(data) | 55 : ActiveFilter(type, text, false), |
| 56 mData(data) | |
| 56 { | 57 { |
| 57 if (mData.HasDomains()) | 58 if (mData.HasDomains()) |
| 58 ParseDomains(mData.GetDomainsSource(mText), u','); | 59 ParseDomains(mData.GetDomainsSource(mText), u','); |
| 59 } | 60 } |
| 60 | 61 |
| 61 Filter::Type ElemHideBase::Parse(DependentString& text, ElemHideData& data) | 62 Filter::Type ElemHideBase::Parse(DependentString& text, ElemHideData& data) |
| 62 { | 63 { |
| 63 StringScanner scanner(text); | 64 StringScanner scanner(text); |
| 64 | 65 |
| 65 // Domains part | 66 // Domains part |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 82 case u'"': | 83 case u'"': |
| 83 case u'!': | 84 case u'!': |
| 84 return Type::UNKNOWN; | 85 return Type::UNKNOWN; |
| 85 case u' ': | 86 case u' ': |
| 86 seenSpaces = true; | 87 seenSpaces = true; |
| 87 break; | 88 break; |
| 88 } | 89 } |
| 89 } | 90 } |
| 90 | 91 |
| 91 seenSpaces |= scanner.skip(u' '); | 92 seenSpaces |= scanner.skip(u' '); |
| 93 bool emulation = false; | |
| 92 bool exception = scanner.skipOne(u'@'); | 94 bool exception = scanner.skipOne(u'@'); |
| 93 if (exception) | 95 if (exception) |
| 94 seenSpaces |= scanner.skip(u' '); | 96 seenSpaces |= scanner.skip(u' '); |
| 97 else | |
| 98 emulation = scanner.skipOne(u'?'); | |
| 95 | 99 |
| 96 String::value_type next = scanner.next(); | 100 String::value_type next = scanner.next(); |
| 97 if (next != u'#') | 101 if (next != u'#') |
| 98 return Type::UNKNOWN; | 102 return Type::UNKNOWN; |
| 99 | 103 |
| 100 // Selector part | 104 // Selector part |
| 101 | 105 |
| 102 // Selector shouldn't be empty | 106 // Selector shouldn't be empty |
| 103 seenSpaces |= scanner.skip(u' '); | 107 seenSpaces |= scanner.skip(u' '); |
| 104 if (scanner.done()) | 108 if (scanner.done()) |
| 105 return Type::UNKNOWN; | 109 return Type::UNKNOWN; |
| 106 | 110 |
| 107 data.mSelectorStart = scanner.position() + 1; | 111 data.mSelectorStart = scanner.position() + 1; |
| 112 data.mNeedConversion = false; | |
| 108 | 113 |
| 109 // We are done validating, now we can normalize whitespace and the domain part | 114 // We are done validating, now we can normalize whitespace and the domain part |
| 110 if (seenSpaces) | 115 if (seenSpaces) |
| 111 NormalizeWhitespace(text, data.mDomainsEnd, data.mSelectorStart); | 116 NormalizeWhitespace(text, data.mDomainsEnd, data.mSelectorStart); |
| 112 DependentString(text, 0, data.mDomainsEnd).toLower(); | 117 DependentString(text, 0, data.mDomainsEnd).toLower(); |
| 113 | 118 |
| 119 // We still need to check the old syntax. It will be converted when | |
| 120 // we instantiate the filter. | |
| 121 if (!emulation && | |
| 122 text.find(u"[-abp-properties="_str, data.mSelectorStart) != text.npos) | |
| 123 { | |
| 124 data.mNeedConversion = true; | |
| 125 emulation = !exception; | |
|
sergei
2018/02/05 14:51:04
Should it be an invalid filter if it's exception w
hub
2018/02/07 04:13:35
no. This is actually how exceptions for element hi
| |
| 126 } | |
| 127 | |
| 114 if (exception) | 128 if (exception) |
| 115 return Type::ELEMHIDEEXCEPTION; | 129 return Type::ELEMHIDEEXCEPTION; |
| 116 | 130 |
| 117 if (text.find(u"[-abp-properties="_str, data.mSelectorStart) != text.npos) | 131 if (emulation) |
| 118 return Type::ELEMHIDEEMULATION; | 132 return Type::ELEMHIDEEMULATION; |
| 119 | 133 |
| 120 return Type::ELEMHIDE; | 134 return Type::ELEMHIDE; |
| 121 } | 135 } |
| 122 | 136 |
| 137 // Convert filter from the old syntax to the new. | |
| 138 OwnedString ElemHideBase::ConvertFilter(const String& text, String::size_type& a t) | |
| 139 { | |
| 140 static const auto propsSelector = u"[-abp-properties="_str; | |
| 141 static const auto newPropsSelector = u":-abp-properties("_str; | |
| 142 static const auto elemHideDelimiter = u"##"_str; | |
| 143 auto selectorPos = text.find(propsSelector, at); | |
| 144 if (selectorPos != text.npos) | |
| 145 { | |
| 146 auto length = text.length(); | |
| 147 auto properties = selectorPos + propsSelector.length(); | |
| 148 String::value_type quote = 0; | |
| 149 bool escape = false; | |
| 150 String::size_type removed = 0; // how many chars we remove | |
| 151 String::size_type end = properties; | |
| 152 String::size_type quote_start = 0; | |
| 153 String::size_type quote_end = 0; | |
| 154 for (auto index = properties; | |
| 155 index < length && end == properties; index++) | |
| 156 { | |
| 157 if (escape) | |
| 158 { | |
| 159 escape = false; | |
| 160 continue; | |
| 161 } | |
| 162 | |
| 163 auto c = text[index]; | |
| 164 switch (c) | |
| 165 { | |
| 166 case '\\': | |
| 167 escape = true; | |
| 168 break; | |
| 169 case '"': | |
| 170 case '\'': | |
| 171 if (quote == 0) | |
| 172 { | |
| 173 quote = c; | |
| 174 quote_start = index + 1; | |
| 175 } | |
| 176 else if (quote == c) | |
| 177 { | |
| 178 // end of quoted. | |
| 179 quote = 0; | |
| 180 removed += 2; | |
| 181 quote_end = index; | |
| 182 } | |
| 183 break; | |
| 184 case ']': | |
| 185 if (quote == 0) | |
| 186 end = index + 1; // end of properties (after ]) | |
| 187 break; | |
| 188 default: | |
| 189 break; | |
| 190 } | |
| 191 } | |
| 192 | |
| 193 if (quote != 0) | |
| 194 quote_end = end - 1; | |
| 195 else if (quote_end <= quote_start) | |
| 196 { | |
| 197 // we likely didn't find a quoted content so we just take it as is. | |
| 198 quote_start = properties; | |
| 199 quote_end = end - 1; | |
| 200 } | |
| 201 | |
| 202 // +1 for the replacement of "##" by "#?#" | |
| 203 String::size_type offset = 0; | |
| 204 | |
| 205 String::size_type delimiter = text.find(elemHideDelimiter); | |
| 206 OwnedString converted(length + ((delimiter != text.npos) ? 1 : 0) - removed) ; | |
| 207 if (delimiter != text.npos) | |
| 208 { | |
| 209 if (delimiter >= selectorPos) | |
| 210 return OwnedString(text); | |
| 211 | |
| 212 at++; | |
| 213 std::memcpy(converted.data(), text.data(), | |
| 214 delimiter * sizeof(String::value_type)); | |
| 215 offset += delimiter; | |
| 216 std::memcpy(converted.data() + offset, u"#?#", | |
| 217 3 * sizeof(String::value_type)); | |
| 218 offset += 3; | |
| 219 delimiter += 2; | |
| 220 // we have already parsed to past the delimiter. | |
| 221 selectorPos -= delimiter; | |
| 222 } | |
| 223 else | |
| 224 delimiter = 0; | |
| 225 | |
| 226 | |
| 227 std::memcpy(converted.data() + offset, text.data() + delimiter, | |
| 228 selectorPos * sizeof(String::value_type)); | |
| 229 offset += selectorPos; | |
| 230 | |
| 231 std::memcpy(converted.data() + offset, newPropsSelector.data(), | |
| 232 newPropsSelector.length() * sizeof(String::value_type)); | |
| 233 offset += newPropsSelector.length(); | |
| 234 | |
| 235 std::memcpy(converted.data() + offset, text.data() + quote_start, | |
| 236 (quote_end - quote_start) * sizeof(String::value_type)); | |
| 237 offset += quote_end - quote_start; | |
| 238 | |
| 239 std::memcpy(converted.data() + offset, u")", sizeof(String::value_type)); | |
| 240 offset++; | |
| 241 | |
| 242 std::memcpy(converted.data() + offset, text.data() + end, | |
| 243 (length - end) * sizeof(String::value_type)); | |
| 244 offset += (length - end) * sizeof(String::value_type); | |
| 245 | |
| 246 return converted; | |
| 247 } | |
| 248 | |
| 249 return OwnedString(text); | |
| 250 } | |
| 251 | |
| 123 namespace | 252 namespace |
| 124 { | 253 { |
| 125 static constexpr String::value_type OPENING_CURLY_REPLACEMENT[] = u"\\7B "; | 254 static constexpr String::value_type OPENING_CURLY_REPLACEMENT[] = u"\\7B "; |
| 126 static constexpr String::value_type CLOSING_CURLY_REPLACEMENT[] = u"\\7D "; | 255 static constexpr String::value_type CLOSING_CURLY_REPLACEMENT[] = u"\\7D "; |
| 127 static constexpr String::size_type CURLY_REPLACEMENT_SIZE = sizeof(OPENING_CUR LY_REPLACEMENT) / sizeof(OPENING_CURLY_REPLACEMENT[0]) - 1; | 256 static constexpr String::size_type CURLY_REPLACEMENT_SIZE = sizeof(OPENING_CUR LY_REPLACEMENT) / sizeof(OPENING_CURLY_REPLACEMENT[0]) - 1; |
| 128 | 257 |
| 129 OwnedString EscapeCurlies(String::size_type replacementCount, | 258 OwnedString EscapeCurlies(String::size_type replacementCount, |
| 130 const DependentString& str) | 259 const DependentString& str) |
| 131 { | 260 { |
| 132 OwnedString result(str.length() + replacementCount * (CURLY_REPLACEMENT_SIZE - 1)); | 261 OwnedString result(str.length() + replacementCount * (CURLY_REPLACEMENT_SIZE - 1)); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 181 if (item.second && !item.first.empty()) | 310 if (item.second && !item.first.empty()) |
| 182 { | 311 { |
| 183 if (!result.empty()) | 312 if (!result.empty()) |
| 184 result.append(u','); | 313 result.append(u','); |
| 185 result.append(item.first); | 314 result.append(item.first); |
| 186 } | 315 } |
| 187 } | 316 } |
| 188 } | 317 } |
| 189 return result; | 318 return result; |
| 190 } | 319 } |
| OLD | NEW |