| OLD | NEW | 
|---|
| 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 | 
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 79         param.first.toLower(); | 79         param.first.toLower(); | 
| 80         param.second = DependentString( | 80         param.second = DependentString( | 
| 81           text, beginValue, text.length() - beginValue); | 81           text, beginValue, text.length() - beginValue); | 
| 82       } | 82       } | 
| 83     } | 83     } | 
| 84     return param; | 84     return param; | 
| 85   } | 85   } | 
| 86 } | 86 } | 
| 87 | 87 | 
| 88 DownloadableSubscription_Parser::DownloadableSubscription_Parser() | 88 DownloadableSubscription_Parser::DownloadableSubscription_Parser() | 
| 89   : mFirstLine(true) |  | 
| 90 { | 89 { | 
| 91   annotate_address(this, "DownloadableSubscription_Parser"); | 90   annotate_address(this, "DownloadableSubscription_Parser"); | 
| 92 } | 91 } | 
| 93 | 92 | 
| 94 namespace { | 93 namespace { | 
| 95   const DependentString ADBLOCK_HEADER(u"[Adblock"_str); | 94   const DependentString ADBLOCK_HEADER(u"[Adblock"_str); | 
|  | 95   const DependentString ADBLOCK_PLUS_EXTRA_HEADER(u"Plus"_str); | 
|  | 96 | 
|  | 97   const DependentString ERROR_INVALID_DATA(u"synchronize_invalid_data"_str); | 
| 96 | 98 | 
| 97   // Only check for trailing base64 padding. There should be at most 2 '='. | 99   // Only check for trailing base64 padding. There should be at most 2 '='. | 
| 98   // In that case return a truncated string. | 100   // In that case return a truncated string. | 
| 99   DependentString CleanUpChecksum(const String& checksum) | 101   DependentString CleanUpChecksum(const String& checksum) | 
| 100   { | 102   { | 
| 101     const auto len = checksum.length(); | 103     const auto len = checksum.length(); | 
| 102     if ((len > 22 && len <= 24) && | 104     if ((len > 22 && len <= 24) && | 
| 103         (checksum[22] == u'=' && (len == 23 || checksum[23] == u'='))) | 105         (checksum[22] == u'=' && (len == 23 || checksum[23] == u'='))) | 
| 104       return DependentString(checksum, 0, 22); | 106       return DependentString(checksum, 0, 22); | 
| 105     return DependentString(checksum); | 107     return DependentString(checksum); | 
| 106   } | 108   } | 
| 107 } | 109 } | 
| 108 | 110 | 
| 109 void DownloadableSubscription_Parser::Process(const String& line) | 111 /// Return true if more line expected. | 
|  | 112 bool DownloadableSubscription_Parser::GetNextLine(DependentString& buffer, Depen
     dentString& line) | 
| 110 { | 113 { | 
| 111   bool isHeader = false; | 114   StringScanner scanner(buffer); | 
| 112   isHeader = line.find(ADBLOCK_HEADER) != String::npos; | 115   String::value_type ch = 0; | 
| 113   if (!isHeader) | 116   while (ch != u'\r' && ch != u'\n') | 
| 114   { | 117   { | 
| 115     auto param = ParseParam(line); | 118     ch = scanner.next(); | 
| 116     if (param.first.is_invalid()) | 119     if (ch == 0) | 
| 117       mFiltersText.emplace_back(line); | 120       break; | 
| 118     else if (param.first == u"checksum"_str) | 121   } | 
|  | 122 | 
|  | 123   auto eol = scanner.position(); | 
|  | 124   line.reset(buffer, 0, eol); | 
|  | 125   if (eol == 0 || ch == 0) | 
|  | 126     return false; | 
|  | 127   while (scanner.skipOne(u'\r') || scanner.skipOne(u'\n')) | 
|  | 128     ; | 
|  | 129   buffer.reset(buffer, scanner.position() + 1); | 
|  | 130   return true; | 
|  | 131 } | 
|  | 132 | 
|  | 133 bool DownloadableSubscription_Parser::Process(const String& buffer) | 
|  | 134 { | 
|  | 135   DependentString currentBuffer(buffer); | 
|  | 136   bool firstLine = true; | 
|  | 137 | 
|  | 138   DependentString line; | 
|  | 139   while (true) | 
|  | 140   { | 
|  | 141     bool more = GetNextLine(currentBuffer, line); | 
|  | 142     if (firstLine) | 
| 119     { | 143     { | 
| 120       mParams[param.first] = CleanUpChecksum(param.second); | 144       if (!ProcessFirstLine(line)) | 
| 121       return; | 145       { | 
|  | 146         mError = ERROR_INVALID_DATA; | 
|  | 147         return false; | 
|  | 148       } | 
|  | 149       firstLine = false; | 
| 122     } | 150     } | 
| 123     else | 151     else | 
| 124       mParams[param.first] = param.second; | 152       ProcessLine(line); | 
|  | 153     if (!more) | 
|  | 154       break; | 
| 125   } | 155   } | 
|  | 156   return true; | 
|  | 157 } | 
|  | 158 | 
|  | 159 bool DownloadableSubscription_Parser::ProcessFirstLine(const String& line) | 
|  | 160 { | 
|  | 161   auto index = line.find(ADBLOCK_HEADER); | 
|  | 162   if (index == String::npos) | 
|  | 163     return false; | 
|  | 164 | 
|  | 165   DependentString minVersion; | 
|  | 166   DependentString current(line, index + ADBLOCK_HEADER.length()); | 
|  | 167   StringScanner scanner(current); | 
|  | 168   if (scanner.skipWhiteSpace() && scanner.skipString(ADBLOCK_PLUS_EXTRA_HEADER)) | 
|  | 169     scanner.skipWhiteSpace(); | 
|  | 170   index = scanner.position() + 1; | 
|  | 171   String::value_type ch = u'\0'; | 
|  | 172   while((ch = scanner.next()) && (ch == u'.' || std::iswdigit(ch))) | 
|  | 173     ; | 
|  | 174   if (ch) | 
|  | 175     scanner.back(); | 
|  | 176   if (scanner.position() + 1 > index) | 
|  | 177     minVersion.reset(current, index, scanner.position() + 1 - index); | 
|  | 178 | 
|  | 179   if (ch != u']') | 
|  | 180     return false; | 
|  | 181 | 
|  | 182   mRequiredVersion = minVersion; | 
|  | 183   mChecksum.Update(line); | 
|  | 184   return true; | 
|  | 185 } | 
|  | 186 | 
|  | 187 void DownloadableSubscription_Parser::ProcessLine(const String& line) | 
|  | 188 { | 
|  | 189   auto param = ParseParam(line); | 
|  | 190   if (param.first.is_invalid()) | 
|  | 191   { | 
|  | 192     if (!line.empty()) | 
|  | 193       mFiltersText.emplace_back(line); | 
|  | 194   } | 
|  | 195   else if (param.first == u"checksum"_str) | 
|  | 196   { | 
|  | 197     mParams[param.first] = CleanUpChecksum(param.second); | 
|  | 198     return; | 
|  | 199   } | 
|  | 200   else | 
|  | 201     mParams[param.first] = param.second; | 
|  | 202 | 
| 126   // Checksum is an MD5 checksum (base64-encoded without the trailing "=") of | 203   // Checksum is an MD5 checksum (base64-encoded without the trailing "=") of | 
| 127   // all lines in UTF-8 without the checksum line, joined with "\n". | 204   // all lines in UTF-8 without the checksum line, joined with "\n". | 
| 128   if (!mFirstLine) | 205   mChecksum.Update((const uint8_t*)"\n", 1); | 
| 129     mChecksum.Update((const uint8_t*)"\n", 1); |  | 
| 130   else |  | 
| 131     mFirstLine = false; |  | 
| 132   mChecksum.Update(line); | 206   mChecksum.Update(line); | 
| 133 } | 207 } | 
| 134 | 208 | 
| 135 int64_t DownloadableSubscription_Parser::ParseExpires(const String& expires) | 209 int64_t DownloadableSubscription_Parser::ParseExpires(const String& expires) | 
| 136 { | 210 { | 
| 137   bool isHour = false; | 211   bool isHour = false; | 
| 138   StringScanner scanner(expires); | 212   StringScanner scanner(expires); | 
| 139   String::size_type numStart = 0; | 213   String::size_type numStart = 0; | 
| 140   String::size_type numLen = 0; | 214   String::size_type numLen = 0; | 
| 141   while(!scanner.done()) | 215   while(!scanner.done()) | 
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 197     mB64Checksum = ToBase64(checksum, MD5::CHECKSUM_LENGTH); | 271     mB64Checksum = ToBase64(checksum, MD5::CHECKSUM_LENGTH); | 
| 198   } | 272   } | 
| 199   return (mParams[u"checksum"_str] == mB64Checksum); | 273   return (mParams[u"checksum"_str] == mB64Checksum); | 
| 200 } | 274 } | 
| 201 | 275 | 
| 202 int64_t DownloadableSubscription_Parser::Finalize(DownloadableSubscription& subs
     cription) | 276 int64_t DownloadableSubscription_Parser::Finalize(DownloadableSubscription& subs
     cription) | 
| 203 { | 277 { | 
| 204   if (mB64Checksum.is_invalid()) | 278   if (mB64Checksum.is_invalid()) | 
| 205     VerifyChecksum(); // here we ignore the checksum, but we calculate it. | 279     VerifyChecksum(); // here we ignore the checksum, but we calculate it. | 
| 206 | 280 | 
|  | 281   FilterNotifier::SubscriptionChange( | 
|  | 282     FilterNotifier::Topic::SUBSCRIPTION_BEFORE_FILTERS_REPLACED, | 
|  | 283     subscription); | 
|  | 284 | 
|  | 285   if (!mRequiredVersion.empty()) | 
|  | 286     subscription.SetRequiredVersion(mRequiredVersion); | 
|  | 287 | 
| 207   auto entry = mParams.find(u"title"_str); | 288   auto entry = mParams.find(u"title"_str); | 
| 208   if (entry) | 289   if (entry) | 
| 209   { | 290   { | 
| 210     subscription.SetTitle(entry->second); | 291     subscription.SetTitle(entry->second); | 
| 211     subscription.SetFixedTitle(true); | 292     subscription.SetFixedTitle(true); | 
| 212   } | 293   } | 
| 213   else | 294   else | 
| 214     subscription.SetFixedTitle(false); | 295     subscription.SetFixedTitle(false); | 
| 215 | 296 | 
| 216   int32_t version = 0; | 297   int32_t version = 0; | 
| 217   entry = mParams.find(u"version"_str); | 298   entry = mParams.find(u"version"_str); | 
| 218   if (entry) | 299   if (entry) | 
| 219     version = entry->second.toInt<int32_t>(); | 300     version = entry->second.toInt<int32_t>(); | 
| 220   subscription.SetDataRevision(version); | 301   subscription.SetDataRevision(version); | 
| 221 | 302 | 
| 222   int64_t expires = 0; | 303   int64_t expires = 0; | 
| 223   entry = mParams.find(u"expires"_str); | 304   entry = mParams.find(u"expires"_str); | 
| 224   if (entry) | 305   if (entry) | 
| 225     expires = ParseExpires(entry->second); | 306     expires = ParseExpires(entry->second); | 
| 226 | 307 | 
| 227   FilterNotifier::SubscriptionChange( |  | 
| 228     FilterNotifier::Topic::SUBSCRIPTION_BEFORE_FILTERS_REPLACED, |  | 
| 229     subscription); |  | 
| 230 |  | 
| 231   Subscription::Filters filters; | 308   Subscription::Filters filters; | 
| 232   filters.reserve(mFiltersText.size()); | 309   filters.reserve(mFiltersText.size()); | 
| 233   for (auto text : mFiltersText) | 310   for (auto text : mFiltersText) | 
| 234   { | 311   { | 
| 235     DependentString dependent(text); | 312     DependentString dependent(text); | 
| 236     filters.emplace_back(Filter::FromText(dependent), false); | 313     filters.emplace_back(Filter::FromText(dependent), false); | 
| 237   } | 314   } | 
| 238 | 315 | 
| 239   subscription.SetFilters(std::move(filters)); | 316   subscription.SetFilters(std::move(filters)); | 
| 240   FilterNotifier::SubscriptionChange( | 317   FilterNotifier::SubscriptionChange( | 
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 342     result.append(u'\n'); | 419     result.append(u'\n'); | 
| 343   } | 420   } | 
| 344   if (mDownloadCount) | 421   if (mDownloadCount) | 
| 345   { | 422   { | 
| 346     result.append(u"downloadCount="_str); | 423     result.append(u"downloadCount="_str); | 
| 347     result.append(mDownloadCount); | 424     result.append(mDownloadCount); | 
| 348     result.append(u'\n'); | 425     result.append(u'\n'); | 
| 349   } | 426   } | 
| 350   return result; | 427   return result; | 
| 351 } | 428 } | 
| OLD | NEW | 
|---|