Index: compiled/Filter.cpp |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/compiled/Filter.cpp |
@@ -0,0 +1,154 @@ |
+#include "Filter.h" |
+#include "CommentFilter.h" |
+#include "InvalidFilter.h" |
+#include "RegExpFilter.h" |
+#include "BlockingFilter.h" |
+#include "WhitelistFilter.h" |
+#include "ElemHideBase.h" |
+#include "ElemHideFilter.h" |
+#include "ElemHideException.h" |
+#include "CSSPropertyFilter.h" |
+#include "StringMap.h" |
+ |
+namespace |
+{ |
+ StringMap<Filter*> knownFilters(8192); |
+ |
+ void NormalizeWhitespace(DependentString& text) |
+ { |
+ String::size_type start = 0; |
+ String::size_type end = text.length(); |
+ |
+ // Remove leading spaces and special characters like line breaks |
+ for (; start < end; start++) |
+ if (text[start] > ' ') |
+ break; |
+ |
+ // Now look for invalid characters inside the string |
+ String::size_type pos; |
+ for (pos = start; pos < end; pos++) |
+ if (text[pos] < ' ') |
+ break; |
+ |
+ if (pos < end) |
+ { |
+ // Found invalid characters, copy all the valid characters while skipping |
+ // the invalid ones. |
+ String::size_type delta = 1; |
+ for (pos = pos + 1; pos < end; pos++) |
+ { |
+ if (text[pos] < ' ') |
+ delta++; |
+ else |
+ text[pos - delta] = text[pos]; |
+ } |
+ end -= delta; |
+ } |
+ |
+ // Remove trailing spaces |
+ for (; end > 0; end--) |
+ if (text[end - 1] != ' ') |
+ break; |
+ |
+ // Set new string boundaries |
+ text.reset(text, start, end - start); |
+ } |
+} |
+ |
+Filter::Filter(const String& text) |
+ : mText(text) |
+{ |
+ annotate_address(this, "Filter"); |
+} |
+ |
+Filter::~Filter() |
+{ |
+ // TODO: This should be removing from knownFilters |
+} |
+ |
+OwnedString Filter::Serialize() const |
+{ |
+ OwnedString result(u"[Filter]\ntext="_str); |
+ result.append(mText); |
+ result.append(u'\n'); |
+ return result; |
+} |
+ |
+Filter* Filter::FromText(DependentString& text) |
+{ |
+ NormalizeWhitespace(text); |
+ if (text.empty()) |
+ return nullptr; |
+ |
+ // Parsing also normalizes the filter text, so it has to be done before the |
+ // lookup in knownFilters. |
+ union |
+ { |
+ RegExpFilterData regexp; |
+ ElemHideData elemhide; |
+ } data; |
+ DependentString error; |
+ |
+ Filter::Type type = CommentFilter::Parse(text); |
+ if (type == Filter::Type::UNKNOWN) |
+ type = ElemHideBase::Parse(text, data.elemhide); |
+ if (type == Filter::Type::UNKNOWN) |
+ type = RegExpFilter::Parse(text, error, data.regexp); |
+ |
+ auto knownFilter = knownFilters.find(text); |
+ if (knownFilter) |
+ return knownFilter->second; |
+ |
+ FilterPtr filter; |
+ switch (type) |
+ { |
+ case Filter::Type::COMMENT: |
+ filter = new CommentFilter(text); |
+ break; |
+ case Filter::Type::INVALID: |
+ filter = new InvalidFilter(text, error); |
+ break; |
+ case Filter::Type::BLOCKING: |
+ filter = new BlockingFilter(text, data.regexp); |
+ break; |
+ case Filter::Type::WHITELIST: |
+ filter = new WhitelistFilter(text, data.regexp); |
+ break; |
+ case Filter::Type::ELEMHIDE: |
+ filter = new ElemHideFilter(text, data.elemhide); |
+ break; |
+ case Filter::Type::ELEMHIDEEXCEPTION: |
+ filter = new ElemHideException(text, data.elemhide); |
+ break; |
+ case Filter::Type::CSSPROPERTY: |
+ filter = new CSSPropertyFilter(text, data.elemhide); |
+ if (static_cast<CSSPropertyFilter*>(filter.get())->IsGeneric()) |
+ filter = new InvalidFilter(text, u"filter_cssproperty_nodomain"_str); |
+ break; |
+ default: |
+ // This should never happen but just in case |
+ return nullptr; |
+ } |
+ |
+ // This is a hack: we looked up the entry using text but create it using |
+ // filter->mText. This works because both are equal at this point. However, |
+ // text refers to a temporary buffer which will go away. |
+ enter_context("Adding to known filters"); |
+ knownFilter.assign(filter->mText, filter.get()); |
+ exit_context(); |
+ |
+ // TODO: We intentionally leak the filter here - currently it won't be used |
+ // for anything and would be deleted immediately. |
+ filter->AddRef(); |
+ |
+ return filter; |
+} |
+ |
+Filter* Filter::GetKnownFilter(const String& text) |
+{ |
+ auto it = knownFilters.find(text); |
+ if (it) |
+ return it->second; |
+ else |
+ return nullptr; |
+} |