| Index: compiled/ActiveFilter.cpp |
| =================================================================== |
| new file mode 100644 |
| --- /dev/null |
| +++ b/compiled/ActiveFilter.cpp |
| @@ -0,0 +1,147 @@ |
| +#include "ActiveFilter.h" |
| +#include "StringScanner.h" |
| + |
| +namespace |
| +{ |
| + const std::u16string ProcessDomain(const std::u16string& docDomain, |
| + bool ignoreTrailingDot) |
| + { |
| + size_t len = docDomain.length(); |
| + if (ignoreTrailingDot) |
| + { |
| + for (; len > 0; --len) |
| + { |
| + if (docDomain[len - 1] != u'.') |
| + break; |
| + } |
| + } |
| + |
| + std::u16string domain(docDomain.substr(0, len)); |
| + for (size_t i = 0, l = domain.length(); i < l; ++i) |
| + { |
| + char16_t currChar = domain[i]; |
| + // TODO: This needs to work for non-ASCII as well |
| + if (currChar >= u'a' && currChar <= u'z') |
| + domain[i] = currChar + u'A' - u'a'; |
| + } |
| + return domain; |
| + } |
| + |
| + const std::u16string to_u16string(unsigned int i) |
| + { |
| + std::string str(std::to_string(i)); |
| + std::u16string result(str.length(), u'\0'); |
| + |
| + for (size_t i = 0, l = str.length(); i < l; ++i) |
| + result[i] = str[i]; |
| + return result; |
| + } |
| +} |
| + |
| +ActiveFilter::ActiveFilter(const std::u16string& text, bool ignoreTrailingDot) |
| + : Filter(text), disabled(false), hitCount(0), lastHit(0), |
| + ignoreTrailingDot(ignoreTrailingDot) |
| +{ |
| +} |
| + |
| +void ActiveFilter::ParseDomains(const std::u16string& str, char16_t separator) |
| +{ |
| + StringScanner scanner(str + separator); |
| + size_t start = 0; |
| + bool reverse = false; |
| + bool hasIncludes = false; |
| + while (!scanner.done()) |
| + { |
| + char16_t currChar = scanner.next(); |
| + if (currChar == u'~' && scanner.position() == start) |
| + { |
| + start++; |
| + reverse = true; |
| + } |
| + else if (currChar == separator) |
| + { |
| + if (scanner.position() > start) |
| + { |
| + std::u16string domain( |
| + ProcessDomain(str.substr(start, scanner.position() - start), |
| + ignoreTrailingDot) |
| + ); |
| + domains[domain] = !reverse; |
| + if (!reverse) |
| + hasIncludes = true; |
| + } |
| + start = scanner.position() + 1; |
| + reverse = false; |
| + } |
| + } |
| + domains[u""] = !hasIncludes; |
| +} |
| + |
| + |
| +bool ActiveFilter::IsActiveOnDomain(const std::u16string& docDomain, |
| + const std::u16string& sitekey) |
| +{ |
| + if (!sitekeys.empty() && sitekeys.find(sitekey) == sitekeys.end()) |
| + return false; |
| + |
| + // If no domains are set the rule matches everywhere |
| + if (domains.empty()) |
| + return true; |
| + |
| + // If the document has no host name, match only if the filter isn't restricted |
| + // to specific domains |
| + if (docDomain.empty()) |
| + return domains[u""]; |
| + |
| + std::u16string domain(ProcessDomain(docDomain, ignoreTrailingDot)); |
| + while (true) |
| + { |
| + auto it = domains.find(domain); |
| + if (it != domains.end()) |
| + return it->second; |
| + |
| + size_t nextDot = domain.find(u'.'); |
| + if (nextDot == domain.npos) |
| + break; |
| + domain = domain.substr(nextDot + 1); |
| + } |
| + return domains[u""]; |
| +} |
| + |
| +bool ActiveFilter::IsActiveOnlyOnDomain(const std::u16string& docDomain) |
| +{ |
| + if (domains.empty() || docDomain.empty() || domains[u""]) |
| + return false; |
| + |
| + std::u16string domain(ProcessDomain(docDomain, ignoreTrailingDot)); |
| + for (auto it = domains.begin(); it != domains.end(); ++it) |
| + { |
| + if (!it->second || it->first == domain) |
| + continue; |
| + |
| + size_t len1 = it->first.length(); |
| + size_t len2 = domain.length(); |
| + if (len1 > len2 && it->first.rfind(u"." + domain) == len1 - len2 - 1) |
| + continue; |
| + |
| + return false; |
| + } |
| + return true; |
| +} |
| + |
| +bool ActiveFilter::IsGeneric() |
| +{ |
| + return (sitekeys.empty() && (domains.empty() || domains[u""])); |
| +} |
| + |
| +const std::u16string ActiveFilter::Serialize() |
| +{ |
| + std::u16string result(Filter::Serialize()); |
| + if (disabled) |
| + result += u"disabled=true\n"; |
| + if (hitCount) |
| + result += u"hitCount=" + to_u16string(hitCount) + u"\n"; |
| + if (lastHit) |
| + result += u"lastHit=" + to_u16string(lastHit) + u"\n"; |
| + return result; |
| +} |