| 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); |
| } |