Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: compiled/subscription/DownloadableSubscription.cpp

Issue 29630576: Issue 5146 - Part 2: Process http response in C++ (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Patch Set: Rebased Created Dec. 5, 2017, 6:09 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « compiled/subscription/DownloadableSubscription.h ('k') | lib/synchronizer.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: compiled/subscription/DownloadableSubscription.cpp
===================================================================
--- a/compiled/subscription/DownloadableSubscription.cpp
+++ b/compiled/subscription/DownloadableSubscription.cpp
@@ -81,59 +81,133 @@
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);
// Only check for trailing base64 padding. There should be at most 2 '='.
// In that case return a truncated string.
DependentString CleanUpChecksum(const String& checksum)
{
const auto len = checksum.length();
if ((len > 22 && len <= 24) &&
(checksum[22] == u'=' && (len == 23 || checksum[23] == u'=')))
return DependentString(checksum, 0, 22);
return DependentString(checksum);
}
}
-void DownloadableSubscription_Parser::Process(const String& line)
+/// Return true if more line expected.
+bool DownloadableSubscription_Parser::GetNextLine(DependentString& buffer, DependentString& line)
{
- bool isHeader = false;
- isHeader = line.find(ADBLOCK_HEADER) != String::npos;
- if (!isHeader)
+ StringScanner scanner(buffer);
+ String::value_type ch = 0;
+ while (ch != u'\r' && ch != u'\n')
{
- auto param = ParseParam(line);
- if (param.first.is_invalid())
- mFiltersText.emplace_back(line);
- else if (param.first == u"checksum"_str)
+ 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;
+}
+
+bool DownloadableSubscription_Parser::Process(const String& buffer)
+{
+ DependentString currentBuffer(buffer);
+ bool firstLine = true;
+
+ DependentString line;
+ while (true)
+ {
+ bool more = GetNextLine(currentBuffer, line);
+ if (firstLine)
{
- mParams[param.first] = CleanUpChecksum(param.second);
- return;
+ if (!ProcessFirstLine(line))
+ {
+ mError = ERROR_INVALID_DATA;
+ return false;
+ }
+ firstLine = false;
}
else
- mParams[param.first] = param.second;
+ 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;
+ mChecksum.Update(line);
+ 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 if (param.first == u"checksum"_str)
+ {
+ mParams[param.first] = CleanUpChecksum(param.second);
+ return;
+ }
+ else
+ mParams[param.first] = param.second;
+
// Checksum is an MD5 checksum (base64-encoded without the trailing "=") of
// all lines in UTF-8 without the checksum line, joined with "\n".
- if (!mFirstLine)
- mChecksum.Update((const uint8_t*)"\n", 1);
- else
- mFirstLine = false;
+ mChecksum.Update((const uint8_t*)"\n", 1);
mChecksum.Update(line);
}
int64_t DownloadableSubscription_Parser::ParseExpires(const String& expires)
{
bool isHour = false;
StringScanner scanner(expires);
String::size_type numStart = 0;
@@ -199,16 +273,23 @@
return (mParams[u"checksum"_str] == mB64Checksum);
}
int64_t DownloadableSubscription_Parser::Finalize(DownloadableSubscription& subscription)
{
if (mB64Checksum.is_invalid())
VerifyChecksum(); // here we ignore the checksum, but we calculate it.
+ 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);
@@ -219,20 +300,16 @@
version = entry->second.toInt<int32_t>();
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);
}
« no previous file with comments | « compiled/subscription/DownloadableSubscription.h ('k') | lib/synchronizer.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld