| 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 25 matching lines...) Expand all  Loading... | 
| 36     String::size_type len = text.length(); | 36     String::size_type len = text.length(); | 
| 37 | 37 | 
| 38     // The first character is guaranteed to be a non-space, the string has been | 38     // The first character is guaranteed to be a non-space, the string has been | 
| 39     // trimmed earlier. | 39     // trimmed earlier. | 
| 40     for (String::size_type pos = 1; pos < len; pos++) | 40     for (String::size_type pos = 1; pos < len; pos++) | 
| 41     { | 41     { | 
| 42       if (pos == domainsEnd) | 42       if (pos == domainsEnd) | 
| 43         domainsEnd -= delta; | 43         domainsEnd -= delta; | 
| 44 | 44 | 
| 45       // Only spaces before selectorStart position should be removed. | 45       // Only spaces before selectorStart position should be removed. | 
| 46       if (pos < selectorStart && text[pos] == ' ') | 46       if (pos < selectorStart && text[pos] == ABP_TEXT(' ')) | 
| 47         delta++; | 47         delta++; | 
| 48       else | 48       else | 
| 49         text[pos - delta] = text[pos]; | 49         text[pos - delta] = text[pos]; | 
| 50     } | 50     } | 
| 51     selectorStart -= delta; | 51     selectorStart -= delta; | 
| 52 | 52 | 
| 53     text.reset(text, 0, len - delta); | 53     text.reset(text, 0, len - delta); | 
| 54   } | 54   } | 
| 55 | 55 | 
| 56   static constexpr String::value_type ELEM_HIDE_DELIMITER[] = u"##"; | 56   static constexpr String::value_type ELEM_HIDE_DELIMITER[] = ABP_TEXT("##"); | 
| 57   static constexpr String::size_type ELEM_HIDE_DELIMITER_LEN = str_length_of(ELE
     M_HIDE_DELIMITER); | 57   static constexpr String::size_type ELEM_HIDE_DELIMITER_LEN = str_length_of(ELE
     M_HIDE_DELIMITER); | 
| 58 | 58 | 
| 59   static constexpr String::value_type ELEM_HIDE_EMULATION_DELIMITER[] = u"#?#"; | 59   static constexpr String::value_type ELEM_HIDE_EMULATION_DELIMITER[] = ABP_TEXT
     ("#?#"); | 
| 60   static constexpr String::size_type ELEM_HIDE_EMULATION_DELIMITER_LEN = str_len
     gth_of(ELEM_HIDE_EMULATION_DELIMITER); | 60   static constexpr String::size_type ELEM_HIDE_EMULATION_DELIMITER_LEN = str_len
     gth_of(ELEM_HIDE_EMULATION_DELIMITER); | 
| 61 | 61 | 
| 62   static constexpr String::value_type OLD_PROPS_SELECTOR[] = u"[-abp-properties=
     "; | 62   static constexpr String::value_type OLD_PROPS_SELECTOR[] = ABP_TEXT("[-abp-pro
     perties="); | 
| 63   static constexpr String::size_type OLD_PROPS_SELECTOR_LEN = str_length_of(OLD_
     PROPS_SELECTOR); | 63   static constexpr String::size_type OLD_PROPS_SELECTOR_LEN = str_length_of(OLD_
     PROPS_SELECTOR); | 
| 64 | 64 | 
| 65   static constexpr String::value_type PROPS_SELECTOR[] = u":-abp-properties("; | 65   static constexpr String::value_type PROPS_SELECTOR[] = ABP_TEXT(":-abp-propert
     ies("); | 
| 66   static constexpr String::size_type PROPS_SELECTOR_LEN = str_length_of(PROPS_SE
     LECTOR); | 66   static constexpr String::size_type PROPS_SELECTOR_LEN = str_length_of(PROPS_SE
     LECTOR); | 
| 67 } | 67 } | 
| 68 | 68 | 
| 69 ElemHideBase::ElemHideBase(Type type, const String& text, const ElemHideData& da
     ta) | 69 ElemHideBase::ElemHideBase(Type type, const String& text, const ElemHideData& da
     ta) | 
| 70     : ActiveFilter(type, text, false), mData(data) | 70     : ActiveFilter(type, text, false), mData(data) | 
| 71 { | 71 { | 
| 72   if (mData.HasDomains()) | 72   if (mData.HasDomains()) | 
| 73     ParseDomains(mData.GetDomainsSource(mText), u','); | 73     ParseDomains(mData.GetDomainsSource(mText), ABP_TEXT(',')); | 
| 74 } | 74 } | 
| 75 | 75 | 
| 76 Filter::Type ElemHideBase::Parse(DependentString& text, ElemHideData& data, bool
     & needConversion) | 76 Filter::Type ElemHideBase::Parse(DependentString& text, ElemHideData& data, bool
     & needConversion) | 
| 77 { | 77 { | 
| 78   needConversion = false; | 78   needConversion = false; | 
| 79 | 79 | 
| 80   StringScanner scanner(text); | 80   StringScanner scanner(text); | 
| 81 | 81 | 
| 82   // Domains part | 82   // Domains part | 
| 83   bool seenSpaces = false; | 83   bool seenSpaces = false; | 
| 84   while (!scanner.done()) | 84   while (!scanner.done()) | 
| 85   { | 85   { | 
| 86     String::value_type next = scanner.next(); | 86     String::value_type next = scanner.next(); | 
| 87     if (next == u'#') | 87     if (next == ABP_TEXT('#')) | 
| 88     { | 88     { | 
| 89       data.mDomainsEnd = scanner.position(); | 89       data.mDomainsEnd = scanner.position(); | 
| 90       break; | 90       break; | 
| 91     } | 91     } | 
| 92 | 92 | 
| 93     switch (next) | 93     switch (next) | 
| 94     { | 94     { | 
| 95       case u'/': | 95       case ABP_TEXT('/'): | 
| 96       case u'*': | 96       case ABP_TEXT('*'): | 
| 97       case u'|': | 97       case ABP_TEXT('|'): | 
| 98       case u'@': | 98       case ABP_TEXT('@'): | 
| 99       case u'"': | 99       case ABP_TEXT('"'): | 
| 100       case u'!': | 100       case ABP_TEXT('!'): | 
| 101         return Type::UNKNOWN; | 101         return Type::UNKNOWN; | 
| 102       case u' ': | 102       case ABP_TEXT(' '): | 
| 103         seenSpaces = true; | 103         seenSpaces = true; | 
| 104         break; | 104         break; | 
| 105     } | 105     } | 
| 106   } | 106   } | 
| 107 | 107 | 
| 108   seenSpaces |= scanner.skip(u' '); | 108   seenSpaces |= scanner.skip(ABP_TEXT(' ')); | 
| 109   bool emulation = false; | 109   bool emulation = false; | 
| 110   bool exception = scanner.skipOne(u'@'); | 110   bool exception = scanner.skipOne(ABP_TEXT('@')); | 
| 111   if (exception) | 111   if (exception) | 
| 112     seenSpaces |= scanner.skip(u' '); | 112     seenSpaces |= scanner.skip(ABP_TEXT(' ')); | 
| 113   else | 113   else | 
| 114     emulation = scanner.skipOne(u'?'); | 114     emulation = scanner.skipOne(ABP_TEXT('?')); | 
| 115 | 115 | 
| 116   String::value_type next = scanner.next(); | 116   String::value_type next = scanner.next(); | 
| 117   if (next != u'#') | 117   if (next != u'#') | 
| 118     return Type::UNKNOWN; | 118     return Type::UNKNOWN; | 
| 119 | 119 | 
| 120   // Selector part | 120   // Selector part | 
| 121 | 121 | 
| 122   // Selector shouldn't be empty | 122   // Selector shouldn't be empty | 
| 123   seenSpaces |= scanner.skip(u' '); | 123   seenSpaces |= scanner.skip(ABP_TEXT(' ')); | 
| 124   if (scanner.done()) | 124   if (scanner.done()) | 
| 125     return Type::UNKNOWN; | 125     return Type::UNKNOWN; | 
| 126 | 126 | 
| 127   data.mSelectorStart = scanner.position() + 1; | 127   data.mSelectorStart = scanner.position() + 1; | 
| 128 | 128 | 
| 129   // We are done validating, now we can normalize whitespace and the domain part | 129   // We are done validating, now we can normalize whitespace and the domain part | 
| 130   if (seenSpaces) | 130   if (seenSpaces) | 
| 131     NormalizeWhitespace(text, data.mDomainsEnd, data.mSelectorStart); | 131     NormalizeWhitespace(text, data.mDomainsEnd, data.mSelectorStart); | 
| 132   DependentString(text, 0, data.mDomainsEnd).toLower(); | 132   DependentString(text, 0, data.mDomainsEnd).toLower(); | 
| 133 | 133 | 
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 176   auto length = text.length(); | 176   auto length = text.length(); | 
| 177   Range suffix = {at, length}; | 177   Range suffix = {at, length}; | 
| 178   Range properties = { prefix.end + OLD_PROPS_SELECTOR_LEN, 0 }; | 178   Range properties = { prefix.end + OLD_PROPS_SELECTOR_LEN, 0 }; | 
| 179   String::value_type quote = 0; | 179   String::value_type quote = 0; | 
| 180   for (auto index = properties.start; | 180   for (auto index = properties.start; | 
| 181        index < length && (suffix.start == at); index++) | 181        index < length && (suffix.start == at); index++) | 
| 182   { | 182   { | 
| 183     auto c = text[index]; | 183     auto c = text[index]; | 
| 184     switch (c) | 184     switch (c) | 
| 185     { | 185     { | 
| 186     case u'"': | 186     case ABP_TEXT('"'): | 
| 187     case u'\'': | 187     case ABP_TEXT('\''): | 
| 188       if (quote == 0) | 188       if (quote == 0) | 
| 189       { | 189       { | 
| 190         // syntax error: we already have a quoted section. | 190         // syntax error: we already have a quoted section. | 
| 191         if (properties.end) | 191         if (properties.end) | 
| 192           return DependentString(); | 192           return DependentString(); | 
| 193 | 193 | 
| 194         if (properties.start != index) | 194         if (properties.start != index) | 
| 195           return DependentString(); | 195           return DependentString(); | 
| 196 | 196 | 
| 197         quote = c; | 197         quote = c; | 
| 198         properties.start = index + 1; | 198         properties.start = index + 1; | 
| 199       } | 199       } | 
| 200       else if (quote == c) | 200       else if (quote == c) | 
| 201       { | 201       { | 
| 202         // end of quoted. | 202         // end of quoted. | 
| 203         quote = 0; | 203         quote = 0; | 
| 204         properties.end = index; | 204         properties.end = index; | 
| 205       } | 205       } | 
| 206       break; | 206       break; | 
| 207     case u']': | 207     case ABP_TEXT(']'): | 
| 208       if (quote == 0) | 208       if (quote == 0) | 
| 209       { | 209       { | 
| 210         if (properties.end == 0) | 210         if (properties.end == 0) | 
| 211           return DependentString(); | 211           return DependentString(); | 
| 212         if (properties.end + 1 != index) | 212         if (properties.end + 1 != index) | 
| 213           return DependentString(); | 213           return DependentString(); | 
| 214         suffix.start = index + 1; | 214         suffix.start = index + 1; | 
| 215       } | 215       } | 
| 216       break; | 216       break; | 
| 217     default: | 217     default: | 
| 218       break; | 218       break; | 
| 219     } | 219     } | 
| 220   } | 220   } | 
| 221 | 221 | 
| 222   if (suffix.start == at) | 222   if (suffix.start == at) | 
| 223     return DependentString(); | 223     return DependentString(); | 
| 224 | 224 | 
| 225   String::size_type delimiter = text.find(ELEM_HIDE_DELIMITER, 0, | 225   String::size_type delimiter = text.find(ELEM_HIDE_DELIMITER, 0, | 
| 226                                           ELEM_HIDE_DELIMITER_LEN); | 226                                           ELEM_HIDE_DELIMITER_LEN); | 
| 227   // +1 for the replacement of "##" by "#?#" | 227   // +1 for the replacement of "##" by "#?#" | 
| 228   if (delimiter != text.npos) | 228   if (delimiter != text.npos) | 
| 229     at++; | 229     at++; | 
| 230   auto new_len = at + prefix.len() + PROPS_SELECTOR_LEN + properties.len() + 1 /
     * ) */ + suffix.len(); | 230   auto new_len = at + prefix.len() + PROPS_SELECTOR_LEN + properties.len() + 1 /
     * ) */ + suffix.len(); | 
| 231 | 231 | 
| 232   assert2(length == new_len + (delimiter == text.npos ? 2 : 1), u"Inconsistent l
     ength in filter conversion."_str); | 232   assert2(length == new_len + (delimiter == text.npos ? 2 : 1), ABP_TEXT("Incons
     istent length in filter conversion."_str)); | 
| 233 | 233 | 
| 234   DependentString converted(text, 0, new_len); | 234   DependentString converted(text, 0, new_len); | 
| 235 | 235 | 
| 236   if (suffix.len()) | 236   if (suffix.len()) | 
| 237   { | 237   { | 
| 238     new_len -= suffix.len(); | 238     new_len -= suffix.len(); | 
| 239     std::memmove(converted.data() + new_len, | 239     std::memmove(converted.data() + new_len, | 
| 240                  text.data() + suffix.start, | 240                  text.data() + suffix.start, | 
| 241                  suffix.byte_len()); | 241                  suffix.byte_len()); | 
| 242   } | 242   } | 
| 243   new_len--; | 243   new_len--; | 
| 244   // here we need to move the properties before inserting the ')' | 244   // here we need to move the properties before inserting the ')' | 
| 245   auto parens = new_len; | 245   auto parens = new_len; | 
| 246   if (properties.len()) | 246   if (properties.len()) | 
| 247   { | 247   { | 
| 248     new_len -= properties.len(); | 248     new_len -= properties.len(); | 
| 249     std::memmove(converted.data() + new_len, | 249     std::memmove(converted.data() + new_len, | 
| 250                  text.data() + properties.start, properties.byte_len()); | 250                  text.data() + properties.start, properties.byte_len()); | 
| 251   } | 251   } | 
| 252   converted[parens] = u')'; | 252   converted[parens] = ABP_TEXT(')'); | 
| 253 | 253 | 
| 254   new_len -= PROPS_SELECTOR_LEN; | 254   new_len -= PROPS_SELECTOR_LEN; | 
| 255   std::memcpy(converted.data() + new_len, | 255   std::memcpy(converted.data() + new_len, | 
| 256               PROPS_SELECTOR, | 256               PROPS_SELECTOR, | 
| 257               PROPS_SELECTOR_LEN * sizeof(String::value_type)); | 257               PROPS_SELECTOR_LEN * sizeof(String::value_type)); | 
| 258   if (prefix.len()) | 258   if (prefix.len()) | 
| 259   { | 259   { | 
| 260     new_len -= prefix.len(); | 260     new_len -= prefix.len(); | 
| 261     std::memmove(converted.data() + new_len, | 261     std::memmove(converted.data() + new_len, | 
| 262                  text.data() + prefix.start, prefix.byte_len()); | 262                  text.data() + prefix.start, prefix.byte_len()); | 
| 263   } | 263   } | 
| 264 | 264 | 
| 265   if (delimiter != String::npos) | 265   if (delimiter != String::npos) | 
| 266   { | 266   { | 
| 267     std::memcpy(converted.data() + delimiter, ELEM_HIDE_EMULATION_DELIMITER, | 267     std::memcpy(converted.data() + delimiter, ELEM_HIDE_EMULATION_DELIMITER, | 
| 268                 ELEM_HIDE_EMULATION_DELIMITER_LEN * sizeof(String::value_type)); | 268                 ELEM_HIDE_EMULATION_DELIMITER_LEN * sizeof(String::value_type)); | 
| 269   } | 269   } | 
| 270 | 270 | 
| 271   return converted; | 271   return converted; | 
| 272 } | 272 } | 
| 273 | 273 | 
| 274 namespace | 274 namespace | 
| 275 { | 275 { | 
| 276   static constexpr String::value_type OPENING_CURLY_REPLACEMENT[] = u"\\7B "; | 276   static constexpr String::value_type OPENING_CURLY_REPLACEMENT[] = ABP_TEXT("\\
     7B "); | 
| 277   static constexpr String::value_type CLOSING_CURLY_REPLACEMENT[] = u"\\7D "; | 277   static constexpr String::value_type CLOSING_CURLY_REPLACEMENT[] = ABP_TEXT("\\
     7D "); | 
| 278   static constexpr String::size_type CURLY_REPLACEMENT_SIZE = str_length_of(OPEN
     ING_CURLY_REPLACEMENT); | 278   static constexpr String::size_type CURLY_REPLACEMENT_SIZE = str_length_of(OPEN
     ING_CURLY_REPLACEMENT); | 
| 279 | 279 | 
| 280   OwnedString EscapeCurlies(String::size_type replacementCount, | 280   OwnedString EscapeCurlies(String::size_type replacementCount, | 
| 281                             const DependentString& str) | 281                             const DependentString& str) | 
| 282   { | 282   { | 
| 283     OwnedString result(str.length() + replacementCount * (CURLY_REPLACEMENT_SIZE
      - 1)); | 283     OwnedString result(str.length() + replacementCount * (CURLY_REPLACEMENT_SIZE
      - 1)); | 
| 284 | 284 | 
| 285     String::value_type* current = result.data(); | 285     String::value_type* current = result.data(); | 
| 286     for (String::size_type i = 0; i < str.length(); i++) | 286     for (String::size_type i = 0; i < str.length(); i++) | 
| 287     { | 287     { | 
| 288       switch(str[i]) | 288       switch(str[i]) | 
| 289       { | 289       { | 
| 290       case u'}': | 290       case ABP_TEXT('}'): | 
| 291         std::memcpy(current, CLOSING_CURLY_REPLACEMENT, | 291         std::memcpy(current, CLOSING_CURLY_REPLACEMENT, | 
| 292                     sizeof(String::value_type) * CURLY_REPLACEMENT_SIZE); | 292                     sizeof(String::value_type) * CURLY_REPLACEMENT_SIZE); | 
| 293         current += CURLY_REPLACEMENT_SIZE; | 293         current += CURLY_REPLACEMENT_SIZE; | 
| 294         break; | 294         break; | 
| 295       case u'{': | 295       case ABP_TEXT('{'): | 
| 296         std::memcpy(current, OPENING_CURLY_REPLACEMENT, | 296         std::memcpy(current, OPENING_CURLY_REPLACEMENT, | 
| 297                     sizeof(String::value_type) * CURLY_REPLACEMENT_SIZE); | 297                     sizeof(String::value_type) * CURLY_REPLACEMENT_SIZE); | 
| 298         current += CURLY_REPLACEMENT_SIZE; | 298         current += CURLY_REPLACEMENT_SIZE; | 
| 299         break; | 299         break; | 
| 300       default: | 300       default: | 
| 301         *current = str[i]; | 301         *current = str[i]; | 
| 302         current++; | 302         current++; | 
| 303         break; | 303         break; | 
| 304       } | 304       } | 
| 305     } | 305     } | 
| 306 | 306 | 
| 307     return result; | 307     return result; | 
| 308   } | 308   } | 
| 309 } | 309 } | 
| 310 | 310 | 
| 311 OwnedString ElemHideBase::GetSelector() const | 311 OwnedString ElemHideBase::GetSelector() const | 
| 312 { | 312 { | 
| 313   const DependentString selector = mData.GetSelector(mText); | 313   const DependentString selector = mData.GetSelector(mText); | 
| 314   String::size_type replacementCount = 0; | 314   String::size_type replacementCount = 0; | 
| 315   for (String::size_type i = 0; i < selector.length(); i++) | 315   for (String::size_type i = 0; i < selector.length(); i++) | 
| 316     if (selector[i] == '}' || selector[i] == '{') | 316     if (selector[i] == ABP_TEXT('}') || selector[i] == ABP_TEXT('{')) | 
| 317       replacementCount++; | 317       replacementCount++; | 
| 318   if (replacementCount) | 318   if (replacementCount) | 
| 319     return EscapeCurlies(replacementCount, selector); | 319     return EscapeCurlies(replacementCount, selector); | 
| 320 | 320 | 
| 321   return OwnedString(selector); | 321   return OwnedString(selector); | 
| 322 } | 322 } | 
| 323 | 323 | 
| 324 OwnedString ElemHideBase::GetSelectorDomain() const | 324 OwnedString ElemHideBase::GetSelectorDomain() const | 
| 325 { | 325 { | 
| 326   /* TODO this is inefficient */ | 326   /* TODO this is inefficient */ | 
| 327   OwnedString result; | 327   OwnedString result; | 
| 328   if (mDomains) | 328   if (mDomains) | 
| 329   { | 329   { | 
| 330     for (const auto& item : *mDomains) | 330     for (const auto& item : *mDomains) | 
| 331     { | 331     { | 
| 332       if (item.second && !item.first.empty()) | 332       if (item.second && !item.first.empty()) | 
| 333       { | 333       { | 
| 334         if (!result.empty()) | 334         if (!result.empty()) | 
| 335           result.append(u','); | 335           result.append(ABP_TEXT(',')); | 
| 336         result.append(item.first); | 336         result.append(item.first); | 
| 337       } | 337       } | 
| 338     } | 338     } | 
| 339   } | 339   } | 
| 340   return result; | 340   return result; | 
| 341 } | 341 } | 
| OLD | NEW | 
|---|