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

Delta Between Two Patch Sets: compiled/subscription/DownloadableSubscription.cpp

Issue 29606600: Issue 5146 - Implement DownloadableSubscription parsing in C++ (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Left Patch Set: Created Nov. 13, 2017, 10:25 p.m.
Right Patch Set: Removed Md5sum and associated code Created Aug. 14, 2018, 12:38 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « compiled/subscription/DownloadableSubscription.h ('k') | compiled/subscription/Subscription.h » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-present eyeo GmbH 3 * Copyright (C) 2006-present eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 #include <cwctype> 18 #include <cwctype>
19 #include <limits>
19 20
20 #include "DownloadableSubscription.h" 21 #include "DownloadableSubscription.h"
21 #include "../FilterNotifier.h" 22 #include "../FilterNotifier.h"
22 #include "../StringScanner.h" 23 #include "../StringScanner.h"
23 #include "../filter/CommentFilter.h" 24 #include "../filter/CommentFilter.h"
24 25
26 ABP_NS_USING
27
25 namespace { 28 namespace {
26 constexpr int MILLIS_IN_HOUR = 60 * 60 * 1000; 29 constexpr int MILLIS_IN_HOUR = 60 * 60 * 1000;
27 constexpr int MILLIS_IN_DAY = 24 * MILLIS_IN_HOUR; 30 constexpr int MILLIS_IN_DAY = 24 * MILLIS_IN_HOUR;
28 } 31 // limits
29 32 constexpr int64_t MAX_HOUR = std::numeric_limits<int64_t>::max() / MILLIS_IN_H OUR;
30 _DownloadableSubscription_Parser::_DownloadableSubscription_Parser(DownloadableS ubscription& sub) 33 constexpr int64_t MAX_DAY = std::numeric_limits<int64_t>::max() / MILLIS_IN_DA Y;
31 : mSubscription(&sub) 34
32 { 35 typedef std::pair<DependentString, DependentString> Param;
33 } 36
34 37 Param ParseParam(const String& text)
35 void _DownloadableSubscription_Parser::Process(DependentString& line) 38 {
36 { 39 Param param;
37 auto filter = FilterPtr(Filter::FromText(line), false); 40
38 if (filter->mType == Filter::Type::COMMENT) 41 if (text[0] == u'!')
39 {
40 auto comment = filter->As<CommentFilter>();
41 if (!comment->GetParam().empty())
42 { 42 {
43 if (comment->GetParam() == u"checksum"_str) 43 bool foundColon = false;
44 String::size_type beginParam = 0;
45 String::size_type endParam = 0;
46 String::size_type beginValue = 0;
47 for (String::size_type i = 1; i < text.length(); i++)
44 { 48 {
45 // XXX we'll have to calculate the checksum. 49 switch (text[i])
hub 2017/11/13 22:35:27 this part will require import a md5sum calculation
50 {
51 case ' ':
52 case '\t':
53 if (beginParam > 0 && !foundColon)
54 {
55 endParam = i;
56 }
57 break;
58 case ':':
59 foundColon = true;
60 endParam = i;
61 break;
62 default:
63 if (foundColon)
64 {
65 beginValue = i;
66 }
67 else
68 {
69 if (beginParam == 0)
70 beginParam = i;
71 }
72 break;
73 }
74 if (beginValue > 0)
75 break;
46 } 76 }
47 mParams[comment->GetParam()] = comment->GetValue(); 77 if (beginValue > 0)
78 {
79 param.first = DependentString(text, beginParam, endParam - beginParam);
80 param.first.toLower();
81 param.second = DependentString(
82 text, beginValue, text.length() - beginValue);
83 }
48 } 84 }
49 } 85 return param;
50 86 }
51 if (filter) 87 }
52 mFilters.push_back(filter); 88
53 } 89 DownloadableSubscription_Parser::DownloadableSubscription_Parser()
54 90 : mFirstLine(true)
55 int _DownloadableSubscription_Parser::ParseExpires(const String& expires) 91 {
92 annotate_address(this, "DownloadableSubscription_Parser");
93 }
94
95 namespace {
96 const DependentString ADBLOCK_HEADER(u"[Adblock"_str);
97 }
98
99 void DownloadableSubscription_Parser::Process(const String& line)
100 {
101 bool isHeader = false;
102 isHeader = line.find(ADBLOCK_HEADER) != String::npos;
103 if (!isHeader)
104 {
105 auto param = ParseParam(line);
106 if (param.first.is_invalid())
107 mFiltersText.emplace_back(line);
108 else
109 mParams[param.first] = param.second;
110 }
111 }
112
113 int64_t DownloadableSubscription_Parser::ParseExpires(const String& expires)
56 { 114 {
57 bool isHour = false; 115 bool isHour = false;
58 StringScanner scanner(expires); 116 StringScanner scanner(expires);
59 String::size_type numStart = 0; 117 String::size_type numStart = 0;
60 String::size_type numLen = 0; 118 String::size_type numLen = 0;
61 while(!scanner.done()) 119 while(!scanner.done())
62 { 120 {
63 auto ch = scanner.next(); 121 auto ch = scanner.next();
64 if (std::iswdigit(ch)) 122 if (std::iswdigit(ch))
65 { 123 {
66 if (numLen == 0) 124 if (numLen == 0)
67 numStart = scanner.position(); 125 numStart = scanner.position();
68 numLen++; 126 numLen++;
69 } 127 }
70 else if (std::iswspace(ch)) 128 else if (std::iswspace(ch))
71 { 129 {
72 if (numLen) 130 if (numLen)
73 break; 131 break;
74 } 132 }
75 else 133 else
76 { 134 {
77 if (numLen) 135 if (numLen)
78 scanner.back(); 136 scanner.back();
79 break; 137 break;
80 } 138 }
81 } 139 }
82 140
83 DependentString numStr(expires, numStart, numLen); 141 DependentString numStr(expires, numStart, numLen);
84 int num = numStr.toInt(); 142 int64_t num = lexical_cast<int64_t>(numStr);
85 if (num == 0) 143 if (num == 0)
86 return 0; 144 return 0;
87 145
88 while (!scanner.done()) 146 while (!scanner.done())
89 { 147 {
90 auto ch = scanner.next(); 148 auto ch = scanner.next();
91 if (std::iswspace(ch)) 149 if (std::iswspace(ch))
92 continue; 150 continue;
151
93 if (ch == u'h') 152 if (ch == u'h')
94 {
95 isHour = true; 153 isHour = true;
96 // assume we are done here. The rest is ignored. 154
97 break; 155 // assume we are done here. The rest is ignored.
98 } 156 break;
99 } 157 }
100 // check for overflow. 158 // check for overflow.
101 if (!isHour && num > 24) 159 if ((isHour && (num > MAX_HOUR)) || (num > MAX_DAY))
hub 2017/11/13 22:35:27 I should check the overflow for the expiration in
102 return 0; 160 return 0;
103 161
104 num *= isHour ? MILLIS_IN_HOUR : MILLIS_IN_DAY; 162 num *= isHour ? MILLIS_IN_HOUR : MILLIS_IN_DAY;
105 return num; 163 return num;
106 } 164 }
107 165
108 int _DownloadableSubscription_Parser::Finalize() 166 int64_t DownloadableSubscription_Parser::Finalize(DownloadableSubscription& subs cription)
109 { 167 {
110 auto entry = mParams.find(u"title"_str); 168 auto entry = mParams.find(u"title"_str);
111 if (entry) 169 if (entry)
112 { 170 {
113 mSubscription->SetTitle(entry->second); 171 subscription.SetTitle(entry->second);
114 mSubscription->SetFixedTitle(true); 172 subscription.SetFixedTitle(true);
115 } 173 }
116 else 174 else
117 mSubscription->SetFixedTitle(false); 175 subscription.SetFixedTitle(false);
118 176
119 int version = 0; 177 int32_t version = 0;
120 entry = mParams.find(u"version"_str); 178 entry = mParams.find(u"version"_str);
121 if (entry) 179 if (entry)
122 version = entry->second.toInt(); 180 version = lexical_cast<int32_t>(entry->second);
123 mSubscription->SetDataRevision(version); 181 subscription.SetDataRevision(version);
124 182
125 int expires = 0; 183 int64_t expires = 0;
126 entry = mParams.find(u"expires"_str); 184 entry = mParams.find(u"expires"_str);
127 if (entry) 185 if (entry)
128 expires = ParseExpires(entry->second); 186 expires = ParseExpires(entry->second);
129 187
130 FilterNotifier::SubscriptionChange( 188 FilterNotifier::SubscriptionChange(
131 FilterNotifier::Topic::SUBSCRIPTION_BEFORE_FILTERS_REPLACED, 189 FilterNotifier::Topic::SUBSCRIPTION_BEFORE_FILTERS_REPLACED,
132 *mSubscription); 190 subscription);
hub 2017/11/13 22:35:28 I'm not if that's the right place to send this not
133 auto oldFilters = std::move(mSubscription->GetFilters()); 191
134 mSubscription->GetFilters() = std::move(mFilters); 192 Subscription::Filters filters;
193 filters.reserve(mFiltersText.size());
194 for (auto text : mFiltersText)
195 {
196 DependentString dependent(text);
197 filters.emplace_back(Filter::FromText(dependent), false);
198 }
199
200 subscription.SetFilters(std::move(filters));
135 FilterNotifier::SubscriptionChange( 201 FilterNotifier::SubscriptionChange(
136 FilterNotifier::Topic::SUBSCRIPTION_FILTERS_REPLACED, *mSubscription); 202 FilterNotifier::Topic::SUBSCRIPTION_FILTERS_REPLACED, subscription);
137 203
138 return expires; 204 return expires;
139 } 205 }
140 206
141 namespace { 207 namespace {
142 DependentString emptyString = u""_str; 208 DependentString emptyString = u""_str;
143 } 209 }
144 210
145 const String& _DownloadableSubscription_Parser::GetRedirect() const 211 const String& DownloadableSubscription_Parser::GetRedirect() const
146 { 212 {
147 auto entry = mParams.find(u"redirect"_str); 213 auto entry = mParams.find(u"redirect"_str);
148 if (entry) 214 if (entry)
149 return entry->second; 215 return entry->second;
150 return emptyString; 216 return emptyString;
151 } 217 }
152 218
153 const String& _DownloadableSubscription_Parser::GetHomepage() const 219 const String& DownloadableSubscription_Parser::GetHomepage() const
154 { 220 {
155 auto entry = mParams.find(u"homepage"_str); 221 auto entry = mParams.find(u"homepage"_str);
156 if (entry) 222 if (entry)
157 return entry->second; 223 return entry->second;
158 return emptyString; 224 return emptyString;
159 } 225 }
226
227 ABP_NS_USING
160 228
161 DownloadableSubscription::DownloadableSubscription(const String& id) 229 DownloadableSubscription::DownloadableSubscription(const String& id)
162 : Subscription(classType, id), mFixedTitle(false), mLastCheck(0), 230 : Subscription(classType, id), mFixedTitle(false), mLastCheck(0),
163 mHardExpiration(0), mSoftExpiration(0), mLastDownload(0), mLastSuccess(0), 231 mHardExpiration(0), mSoftExpiration(0), mLastDownload(0), mLastSuccess(0),
164 mErrorCount(0), mDataRevision(0), mDownloadCount(0) 232 mErrorCount(0), mDataRevision(0), mDownloadCount(0)
165 { 233 {
166 SetTitle(id); 234 SetTitle(id);
167 } 235 }
168 236
169 _DownloadableSubscription_Parser* DownloadableSubscription::ParseDownload() 237 DownloadableSubscription_Parser* DownloadableSubscription::ParseDownload()
170 { 238 {
171 return new _DownloadableSubscription_Parser(*this); 239 return new DownloadableSubscription_Parser();
172 } 240 }
173 241
174 OwnedString DownloadableSubscription::Serialize() const 242 OwnedString DownloadableSubscription::Serialize() const
175 { 243 {
176 OwnedString result(Subscription::Serialize()); 244 OwnedString result(Subscription::Serialize());
177 if (mFixedTitle) 245 if (mFixedTitle)
178 result.append(u"fixedTitle=true\n"_str); 246 result.append(ABP_TEXT("fixedTitle=true\n"_str));
179 if (!mHomepage.empty()) 247 if (!mHomepage.empty())
180 { 248 {
181 result.append(u"homepage="_str); 249 result.append(ABP_TEXT("homepage="_str));
182 result.append(mHomepage); 250 result.append(mHomepage);
183 result.append(u'\n'); 251 result.append(ABP_TEXT('\n'));
184 } 252 }
185 if (mLastCheck) 253 if (mLastCheck)
186 { 254 {
187 result.append(u"lastCheck="_str); 255 result.append(ABP_TEXT("lastCheck="_str));
188 result.append(mLastCheck); 256 result.append(mLastCheck);
189 result.append(u'\n'); 257 result.append(ABP_TEXT('\n'));
190 } 258 }
191 if (mHardExpiration) 259 if (mHardExpiration)
192 { 260 {
193 result.append(u"expires="_str); 261 result.append(ABP_TEXT("expires="_str));
194 result.append(mHardExpiration); 262 result.append(mHardExpiration);
195 result.append(u'\n'); 263 result.append(ABP_TEXT('\n'));
196 } 264 }
197 if (mSoftExpiration) 265 if (mSoftExpiration)
198 { 266 {
199 result.append(u"softExpiration="_str); 267 result.append(ABP_TEXT("softExpiration="_str));
200 result.append(mSoftExpiration); 268 result.append(mSoftExpiration);
201 result.append(u'\n'); 269 result.append(ABP_TEXT('\n'));
202 } 270 }
203 if (mLastDownload) 271 if (mLastDownload)
204 { 272 {
205 result.append(u"lastDownload="_str); 273 result.append(ABP_TEXT("lastDownload="_str));
206 result.append(mLastDownload); 274 result.append(mLastDownload);
207 result.append(u'\n'); 275 result.append(ABP_TEXT('\n'));
208 } 276 }
209 if (!mDownloadStatus.empty()) 277 if (!mDownloadStatus.empty())
210 { 278 {
211 result.append(u"downloadStatus="_str); 279 result.append(ABP_TEXT("downloadStatus="_str));
212 result.append(mDownloadStatus); 280 result.append(mDownloadStatus);
213 result.append(u'\n'); 281 result.append(ABP_TEXT('\n'));
214 } 282 }
215 if (mLastSuccess) 283 if (mLastSuccess)
216 { 284 {
217 result.append(u"lastSuccess="_str); 285 result.append(ABP_TEXT("lastSuccess="_str));
218 result.append(mLastSuccess); 286 result.append(mLastSuccess);
219 result.append(u'\n'); 287 result.append(ABP_TEXT('\n'));
220 } 288 }
221 if (mErrorCount) 289 if (mErrorCount)
222 { 290 {
223 result.append(u"errors="_str); 291 result.append(ABP_TEXT("errors="_str));
224 result.append(mErrorCount); 292 result.append(mErrorCount);
225 result.append(u'\n'); 293 result.append(ABP_TEXT('\n'));
226 } 294 }
227 if (mDataRevision) 295 if (mDataRevision)
228 { 296 {
229 result.append(u"version="_str); 297 result.append(ABP_TEXT("version="_str));
230 result.append(mDataRevision); 298 result.append(mDataRevision);
231 result.append(u'\n'); 299 result.append(ABP_TEXT('\n'));
232 } 300 }
233 if (!mRequiredVersion.empty()) 301 if (!mRequiredVersion.empty())
234 { 302 {
235 result.append(u"requiredVersion="_str); 303 result.append(ABP_TEXT("requiredVersion="_str));
236 result.append(mRequiredVersion); 304 result.append(mRequiredVersion);
237 result.append(u'\n'); 305 result.append(ABP_TEXT('\n'));
238 } 306 }
239 if (mDownloadCount) 307 if (mDownloadCount)
240 { 308 {
241 result.append(u"downloadCount="_str); 309 result.append(ABP_TEXT("downloadCount="_str));
242 result.append(mDownloadCount); 310 result.append(mDownloadCount);
243 result.append(u'\n'); 311 result.append(ABP_TEXT('\n'));
244 } 312 }
245 return result; 313 return result;
246 } 314 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld