Index: compiled/subscription/DownloadableSubscription.cpp |
=================================================================== |
--- a/compiled/subscription/DownloadableSubscription.cpp |
+++ b/compiled/subscription/DownloadableSubscription.cpp |
@@ -82,37 +82,112 @@ |
text, beginValue, text.length() - beginValue); |
} |
} |
return param; |
} |
} |
DownloadableSubscription_Parser::DownloadableSubscription_Parser() |
- : mFirstLine(true) |
{ |
annotate_address(this, "DownloadableSubscription_Parser"); |
} |
namespace { |
const DependentString ADBLOCK_HEADER(u"[Adblock"_str); |
+ const DependentString ADBLOCK_PLUS_EXTRA_HEADER(u"Plus"_str); |
+ |
+ const DependentString ERROR_INVALID_DATA(u"synchronize_invalid_data"_str); |
+} |
+ |
+/// Return true if more line expected. |
+bool DownloadableSubscription_Parser::GetNextLine(DependentString& buffer, DependentString& line) |
+{ |
+ StringScanner scanner(buffer); |
+ String::value_type ch = 0; |
+ while (ch != u'\r' && ch != u'\n') |
+ { |
+ ch = scanner.next(); |
+ if (ch == 0) |
+ break; |
+ } |
+ |
+ auto eol = scanner.position(); |
+ line.reset(buffer, 0, eol); |
+ if (eol == 0 || ch == 0) |
+ return false; |
+ while (scanner.skipOne(u'\r') || scanner.skipOne(u'\n')) |
+ ; |
+ buffer.reset(buffer, scanner.position() + 1); |
+ return true; |
} |
-void DownloadableSubscription_Parser::Process(const String& line) |
+bool DownloadableSubscription_Parser::Process(const String& buffer) |
{ |
- bool isHeader = false; |
- isHeader = line.find(ADBLOCK_HEADER) != String::npos; |
- if (!isHeader) |
+ DependentString currentBuffer(buffer); |
+ bool firstLine = true; |
+ |
+ DependentString line; |
+ while (true) |
{ |
- auto param = ParseParam(line); |
- if (param.first.is_invalid()) |
+ bool more = GetNextLine(currentBuffer, line); |
+ if (firstLine) |
+ { |
+ if (!ProcessFirstLine(line)) |
+ { |
+ mError = ERROR_INVALID_DATA; |
+ return false; |
+ } |
+ firstLine = false; |
+ } |
+ else |
+ ProcessLine(line); |
+ if (!more) |
+ break; |
+ } |
+ return true; |
+} |
+ |
+bool DownloadableSubscription_Parser::ProcessFirstLine(const String& line) |
+{ |
+ auto index = line.find(ADBLOCK_HEADER); |
+ if (index == String::npos) |
+ return false; |
+ |
+ DependentString minVersion; |
+ DependentString current(line, index + ADBLOCK_HEADER.length()); |
+ StringScanner scanner(current); |
+ if (scanner.skipWhiteSpace() && scanner.skipString(ADBLOCK_PLUS_EXTRA_HEADER)) |
+ scanner.skipWhiteSpace(); |
+ index = scanner.position() + 1; |
+ String::value_type ch = u'\0'; |
+ while((ch = scanner.next()) && (ch == u'.' || std::iswdigit(ch))) |
+ ; |
+ if (ch) |
+ scanner.back(); |
+ if (scanner.position() + 1 > index) |
+ minVersion.reset(current, index, scanner.position() + 1 - index); |
+ |
+ if (ch != u']') |
+ return false; |
+ |
+ mRequiredVersion = minVersion; |
+ return true; |
+} |
+ |
+void DownloadableSubscription_Parser::ProcessLine(const String& line) |
+{ |
+ auto param = ParseParam(line); |
+ if (param.first.is_invalid()) |
+ { |
+ if (!line.empty()) |
mFiltersText.emplace_back(line); |
- else |
- mParams[param.first] = param.second; |
} |
+ else |
+ mParams[param.first] = param.second; |
} |
int64_t DownloadableSubscription_Parser::ParseExpires(const String& expires) |
{ |
bool isHour = false; |
StringScanner scanner(expires); |
String::size_type numStart = 0; |
String::size_type numLen = 0; |
@@ -160,16 +235,23 @@ |
return 0; |
num *= isHour ? MILLIS_IN_HOUR : MILLIS_IN_DAY; |
return num; |
} |
int64_t DownloadableSubscription_Parser::Finalize(DownloadableSubscription& subscription) |
{ |
+ FilterNotifier::SubscriptionChange( |
+ FilterNotifier::Topic::SUBSCRIPTION_BEFORE_FILTERS_REPLACED, |
+ subscription); |
+ |
+ if (!mRequiredVersion.empty()) |
+ subscription.SetRequiredVersion(mRequiredVersion); |
+ |
auto entry = mParams.find(u"title"_str); |
if (entry) |
{ |
subscription.SetTitle(entry->second); |
subscription.SetFixedTitle(true); |
} |
else |
subscription.SetFixedTitle(false); |
@@ -180,20 +262,16 @@ |
version = lexical_cast<int32_t>(entry->second); |
subscription.SetDataRevision(version); |
int64_t expires = 0; |
entry = mParams.find(u"expires"_str); |
if (entry) |
expires = ParseExpires(entry->second); |
- FilterNotifier::SubscriptionChange( |
- FilterNotifier::Topic::SUBSCRIPTION_BEFORE_FILTERS_REPLACED, |
- subscription); |
- |
Subscription::Filters filters; |
filters.reserve(mFiltersText.size()); |
for (auto text : mFiltersText) |
{ |
DependentString dependent(text); |
filters.emplace_back(Filter::FromText(dependent), false); |
} |