File indexing completed on 2024-11-17 04:55:16

0001 /*
0002     SPDX-License-Identifier: MPL-2.0
0003 */
0004 
0005 /* Copyright (c) 2015 Brian R. Bondy. Distributed under the MPL2 license.
0006  * This Source Code Form is subject to the terms of the Mozilla Public
0007  * License, v. 2.0. If a copy of the MPL was not distributed with this
0008  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
0009 
0010 #include "./ad_block_client_wrap.h"
0011 #include <node_buffer.h>
0012 #include <algorithm>
0013 #include <fstream>
0014 #include "./bad_fingerprint.h"
0015 #include "./data_file_version.h"
0016 #include "./filter.h"
0017 #include "./filter_list.h"
0018 #include "./lists/regions.h"
0019 #include "./lists/malware.h"
0020 #include "./lists/default.h"
0021 
0022 namespace ad_block_client_wrap {
0023 
0024 using v8::Array;
0025 using v8::Function;
0026 using v8::FunctionCallbackInfo;
0027 using v8::FunctionTemplate;
0028 using v8::Isolate;
0029 using v8::Local;
0030 using v8::MaybeLocal;
0031 using v8::Int32;
0032 using v8::Object;
0033 using v8::Persistent;
0034 using v8::String;
0035 using v8::Boolean;
0036 using v8::Value;
0037 using v8::Exception;
0038 using v8::NewStringType;
0039 
0040 #if V8_MAJOR_VERSION >= 7
0041 #define CHECK_SET(X) X.Check()
0042 #else
0043 #define CHECK_SET(X) (void)X
0044 #endif
0045 
0046 Persistent<Function> AdBlockClientWrap::constructor;
0047 
0048 AdBlockClientWrap::AdBlockClientWrap() {
0049 }
0050 
0051 AdBlockClientWrap::~AdBlockClientWrap() {
0052 }
0053 
0054 Local<Object> ToLocalObject(Isolate* isolate, const FilterList& filter_list) {
0055   Local<Object> list = Object::New(isolate);
0056   CHECK_SET(list->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "uuid", NewStringType::kNormal).ToLocalChecked(),
0057     String::NewFromUtf8(isolate, filter_list.uuid.c_str(), NewStringType::kNormal).ToLocalChecked()));
0058   CHECK_SET(list->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "listURL", NewStringType::kNormal).ToLocalChecked(),
0059     String::NewFromUtf8(isolate, filter_list.url.c_str(), NewStringType::kNormal).ToLocalChecked()));
0060   CHECK_SET(list->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "title", NewStringType::kNormal).ToLocalChecked(),
0061     String::NewFromUtf8(isolate, filter_list.title.c_str(), NewStringType::kNormal).ToLocalChecked()));
0062   CHECK_SET(list->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "supportURL", NewStringType::kNormal).ToLocalChecked(),
0063     String::NewFromUtf8(isolate, filter_list.support_url.c_str(), NewStringType::kNormal).ToLocalChecked()));
0064   CHECK_SET(list->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "componentID", NewStringType::kNormal).ToLocalChecked(),
0065     String::NewFromUtf8(isolate, filter_list.component_id.c_str(), NewStringType::kNormal).ToLocalChecked()));
0066   CHECK_SET(list->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "base64PublicKey", NewStringType::kNormal).ToLocalChecked(),
0067     String::NewFromUtf8(isolate, filter_list.base64_public_key.c_str(), NewStringType::kNormal).ToLocalChecked()));
0068   Local<Array> langs = Array::New(isolate);
0069   int j = 0;
0070   std::for_each(filter_list.langs.begin(), filter_list.langs.end(),
0071     [&isolate, &langs, &j](const std::string &lang) {
0072     CHECK_SET(langs->Set(isolate->GetCurrentContext(), j++,
0073       String::NewFromUtf8(isolate, lang.c_str(), NewStringType::kNormal).ToLocalChecked()));
0074   });
0075   if (filter_list.langs.size() > 0) {
0076     CHECK_SET(list->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "langs", NewStringType::kNormal).ToLocalChecked(), langs));
0077   }
0078   return list;
0079 }
0080 
0081 Local<Array> ToLocalObject(Isolate* isolate,
0082     const std::vector<FilterList> &list) {
0083   Local<Array> lists = Array::New(isolate);
0084   int j = 0;
0085   std::for_each(list.begin(), list.end(),
0086     [&isolate, &lists, &j](const FilterList &filter_list) {
0087     CHECK_SET(lists->Set(isolate->GetCurrentContext(), j++, ToLocalObject(isolate, filter_list)));
0088   });
0089   return lists;
0090 }
0091 
0092 void GenerateManifestFile(const std::string &name,
0093                           const std::string &base64_public_key,
0094                           const std::string &filename) {
0095   std::ofstream outFile(filename);
0096   if (outFile.is_open()) {
0097     outFile << "{" << std::endl;
0098     outFile << "  \"description\": \"Brave Ad Block Updater extension\","
0099       << std::endl;
0100     outFile << "  \"key\": \"" << base64_public_key << "\"," << std::endl;
0101     outFile << "  \"manifest_version\": 2," << std::endl;
0102     outFile << "  \"name\": \"Brave Ad Block Updater (" << name << ")\","
0103       << std::endl;
0104     outFile << "  \"version\": \"0.0.0\"" << std::endl;
0105     outFile << "}" << std::endl;
0106   }
0107 }
0108 
0109 void AdBlockClientWrap::Init(Local<Object> exports) {
0110   Isolate* isolate = exports->GetIsolate();
0111 
0112   // Prepare constructor template
0113   Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New);
0114   tpl->SetClassName(String::NewFromUtf8(isolate, "AdBlockClient", NewStringType::kNormal).ToLocalChecked());
0115   tpl->InstanceTemplate()->SetInternalFieldCount(1);
0116 
0117   // Prototype
0118   NODE_SET_PROTOTYPE_METHOD(tpl, "clear", AdBlockClientWrap::Clear);
0119   NODE_SET_PROTOTYPE_METHOD(tpl, "parse", AdBlockClientWrap::Parse);
0120   NODE_SET_PROTOTYPE_METHOD(tpl, "matches", AdBlockClientWrap::Matches);
0121   NODE_SET_PROTOTYPE_METHOD(tpl, "findMatchingFilters",
0122       AdBlockClientWrap::FindMatchingFilters);
0123   NODE_SET_PROTOTYPE_METHOD(tpl, "serialize", AdBlockClientWrap::Serialize);
0124   NODE_SET_PROTOTYPE_METHOD(tpl, "deserialize",
0125     AdBlockClientWrap::Deserialize);
0126   NODE_SET_PROTOTYPE_METHOD(tpl, "getParsingStats",
0127     AdBlockClientWrap::GetParsingStats);
0128   NODE_SET_PROTOTYPE_METHOD(tpl, "getFilters",
0129     AdBlockClientWrap::GetFilters);
0130   NODE_SET_PROTOTYPE_METHOD(tpl, "getFingerprint",
0131     AdBlockClientWrap::GetFingerprint);
0132   NODE_SET_PROTOTYPE_METHOD(tpl, "getMatchingStats",
0133     AdBlockClientWrap::GetMatchingStats);
0134   NODE_SET_PROTOTYPE_METHOD(tpl, "enableBadFingerprintDetection",
0135     AdBlockClientWrap::EnableBadFingerprintDetection);
0136   NODE_SET_PROTOTYPE_METHOD(tpl, "generateBadFingerprintsHeader",
0137     AdBlockClientWrap::GenerateBadFingerprintsHeader);
0138   NODE_SET_PROTOTYPE_METHOD(tpl, "generateDefaultManifestFile",
0139     AdBlockClientWrap::GenerateDefaultManifestFile);
0140   NODE_SET_PROTOTYPE_METHOD(tpl, "generateRegionalManifestFiles",
0141     AdBlockClientWrap::GenerateRegionalManifestFiles);
0142   NODE_SET_PROTOTYPE_METHOD(tpl, "cleanup", AdBlockClientWrap::Cleanup);
0143   NODE_SET_PROTOTYPE_METHOD(tpl, "addTag", AdBlockClientWrap::AddTag);
0144   NODE_SET_PROTOTYPE_METHOD(tpl, "removeTag", AdBlockClientWrap::RemoveTag);
0145 
0146   // filter options
0147   Local<Object> filterOptions = Object::New(isolate);
0148   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "noFilterOption", NewStringType::kNormal).ToLocalChecked(),
0149     Int32::New(isolate, FONoFilterOption)));
0150   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "script", NewStringType::kNormal).ToLocalChecked(),
0151     Int32::New(isolate, FOScript)));
0152   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "image", NewStringType::kNormal).ToLocalChecked(),
0153     Int32::New(isolate, FOImage)));
0154   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "stylesheet", NewStringType::kNormal).ToLocalChecked(),
0155     Int32::New(isolate, FOStylesheet)));
0156   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "object", NewStringType::kNormal).ToLocalChecked(),
0157     Int32::New(isolate, FOObject)));
0158   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "xmlHttpRequest", NewStringType::kNormal).ToLocalChecked(),
0159     Int32::New(isolate, FOXmlHttpRequest)));
0160   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "objectSubrequest", NewStringType::kNormal).ToLocalChecked(),
0161     Int32::New(isolate, FOObjectSubrequest)));
0162   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "subdocument", NewStringType::kNormal).ToLocalChecked(),
0163     Int32::New(isolate, FOSubdocument)));
0164   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "document", NewStringType::kNormal).ToLocalChecked(),
0165     Int32::New(isolate, FODocument)));
0166   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "other", NewStringType::kNormal).ToLocalChecked(),
0167     Int32::New(isolate, FOOther)));
0168   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "xbl", NewStringType::kNormal).ToLocalChecked(),
0169     Int32::New(isolate, FOXBL)));
0170   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "collapse", NewStringType::kNormal).ToLocalChecked(),
0171     Int32::New(isolate, FOCollapse)));
0172   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "doNotTrack", NewStringType::kNormal).ToLocalChecked(),
0173     Int32::New(isolate, FODoNotTrack)));
0174   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "elemHide", NewStringType::kNormal).ToLocalChecked(),
0175     Int32::New(isolate, FOElemHide)));
0176   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "thirdParty", NewStringType::kNormal).ToLocalChecked(),
0177     Int32::New(isolate, FOThirdParty)));
0178   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "notThirdParty", NewStringType::kNormal).ToLocalChecked(),
0179     Int32::New(isolate, FONotThirdParty)));
0180   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "ping", NewStringType::kNormal).ToLocalChecked(),
0181     Int32::New(isolate, FOPing)));
0182   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "popup", NewStringType::kNormal).ToLocalChecked(),
0183     Int32::New(isolate, FOPopup)));
0184   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "redirect", NewStringType::kNormal).ToLocalChecked(),
0185     Int32::New(isolate, FORedirect)));
0186   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "csp", NewStringType::kNormal).ToLocalChecked(),
0187     Int32::New(isolate, FOCSP)));
0188   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "font", NewStringType::kNormal).ToLocalChecked(),
0189     Int32::New(isolate, FOFont)));
0190   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "media", NewStringType::kNormal).ToLocalChecked(),
0191     Int32::New(isolate, FOMedia)));
0192   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "webrtc", NewStringType::kNormal).ToLocalChecked(),
0193     Int32::New(isolate, FOWebRTC)));
0194   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "genericblock", NewStringType::kNormal).ToLocalChecked(),
0195     Int32::New(isolate, FOGenericBlock)));
0196   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "generichide", NewStringType::kNormal).ToLocalChecked(),
0197     Int32::New(isolate, FOGenericHide)));
0198   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "empty", NewStringType::kNormal).ToLocalChecked(),
0199     Int32::New(isolate, FOEmpty)));
0200   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "websocket", NewStringType::kNormal).ToLocalChecked(),
0201     Int32::New(isolate, FOWebsocket)));
0202   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "important", NewStringType::kNormal).ToLocalChecked(),
0203     Int32::New(isolate, FOImportant)));
0204   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "explicitcancel", NewStringType::kNormal).ToLocalChecked(),
0205     Int32::New(isolate, FOExplicitCancel)));
0206   CHECK_SET(filterOptions->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "unknown", NewStringType::kNormal).ToLocalChecked(),
0207     Int32::New(isolate, FOUnknown)));
0208 
0209   // Adblock lists
0210   Local<Object> lists = Object::New(isolate);
0211   CHECK_SET(lists->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "default", NewStringType::kNormal).ToLocalChecked(),
0212     ToLocalObject(isolate, default_lists)));
0213   CHECK_SET(lists->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "malware", NewStringType::kNormal).ToLocalChecked(),
0214     ToLocalObject(isolate, malware_lists)));
0215   CHECK_SET(lists->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "regions", NewStringType::kNormal).ToLocalChecked(),
0216     ToLocalObject(isolate, region_lists)));
0217   constructor.Reset(isolate,
0218       tpl->GetFunction(isolate->GetCurrentContext()).ToLocalChecked());
0219   CHECK_SET(exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "AdBlockClient", NewStringType::kNormal).ToLocalChecked(),
0220       tpl->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()));
0221   CHECK_SET(exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "FilterOptions", NewStringType::kNormal).ToLocalChecked(), filterOptions));
0222   CHECK_SET(exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "adBlockLists", NewStringType::kNormal).ToLocalChecked(), lists));
0223   CHECK_SET(exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "adBlockDataFileVersion", NewStringType::kNormal).ToLocalChecked(),
0224                Int32::New(isolate, DATA_FILE_VERSION)));
0225 }
0226 
0227 void AdBlockClientWrap::New(const FunctionCallbackInfo<Value>& args) {
0228   Isolate* isolate = args.GetIsolate();
0229 
0230   if (args.IsConstructCall()) {
0231     // Invoked as constructor: `new AdBlockClient(...)`
0232     AdBlockClientWrap* obj = new AdBlockClientWrap();
0233     obj->Wrap(args.This());
0234     args.GetReturnValue().Set(args.This());
0235   } else {
0236     // Invoked as plain function `AdBlockClient(...)`,
0237     // turn into construct call.
0238     const int argc = 1;
0239     Local<Value> argv[argc] = { args[0] };
0240     Local<Function> cons = Local<Function>::New(isolate, constructor);
0241     args.GetReturnValue().Set(
0242         cons->NewInstance(isolate->GetCurrentContext(), argc, argv).ToLocalChecked());
0243   }
0244 }
0245 
0246 void AdBlockClientWrap::Clear(const FunctionCallbackInfo<Value>& args) {
0247   AdBlockClientWrap* obj =
0248     ObjectWrap::Unwrap<AdBlockClientWrap>(args.Holder());
0249   obj->clear();
0250 }
0251 
0252 void AdBlockClientWrap::Parse(const FunctionCallbackInfo<Value>& args) {
0253   Isolate* isolate = args.GetIsolate();
0254   String::Utf8Value str(isolate, args[0]->ToString(isolate->GetCurrentContext())
0255       .FromMaybe(Local<String>()));
0256 #if V8_MAJOR_VERSION >= 7
0257   bool preserveRules(args[1]->BooleanValue(isolate));
0258 #else
0259   bool preserveRules(args[1]->BooleanValue());
0260 #endif
0261   const char * buffer = *str;
0262 
0263   AdBlockClientWrap* obj =
0264     ObjectWrap::Unwrap<AdBlockClientWrap>(args.Holder());
0265   obj->parse(buffer, preserveRules);
0266 }
0267 
0268 void AdBlockClientWrap::Matches(const FunctionCallbackInfo<Value>& args) {
0269   Isolate* isolate = args.GetIsolate();
0270   String::Utf8Value str(isolate, args[0]->ToString(isolate->GetCurrentContext())
0271       .FromMaybe(Local<String>()));
0272   const char * buffer = *str;
0273   int32_t filterOption =
0274     static_cast<FilterOption>(args[1]->Int32Value(isolate->GetCurrentContext()).FromMaybe(0));
0275   String::Utf8Value currentPageDomain(isolate, args[2]->ToString(isolate->GetCurrentContext())
0276       .FromMaybe(Local<String>()));
0277   const char * currentPageDomainBuffer = *currentPageDomain;
0278 
0279   AdBlockClientWrap* obj =
0280     ObjectWrap::Unwrap<AdBlockClientWrap>(args.Holder());
0281   bool matches = obj->matches(buffer,
0282     static_cast<FilterOption>(filterOption),
0283     currentPageDomainBuffer);
0284 
0285   args.GetReturnValue().Set(Boolean::New(isolate, matches));
0286 }
0287 
0288 void AdBlockClientWrap::FindMatchingFilters(
0289     const FunctionCallbackInfo<Value>& args) {
0290   Isolate* isolate = args.GetIsolate();
0291   String::Utf8Value str(isolate, args[0]->ToString(isolate->GetCurrentContext())
0292       .FromMaybe(Local<String>()));
0293   const char * buffer = *str;
0294   int32_t filterOption =
0295       static_cast<FilterOption>(args[1]->Int32Value(isolate->GetCurrentContext()).FromMaybe(0));
0296   String::Utf8Value currentPageDomain(isolate, args[2]->ToString(isolate->GetCurrentContext())
0297       .FromMaybe(Local<String>()));
0298   const char * currentPageDomainBuffer = *currentPageDomain;
0299 
0300   Filter *matchingFilter;
0301   Filter *matchingExceptionFilter;
0302   AdBlockClientWrap* obj =
0303     ObjectWrap::Unwrap<AdBlockClientWrap>(args.Holder());
0304   bool matches = obj->findMatchingFilters(buffer,
0305     static_cast<FilterOption>(filterOption),
0306     currentPageDomainBuffer, &matchingFilter, &matchingExceptionFilter);
0307 
0308   Local<Object> foundData = Object::New(isolate);
0309   CHECK_SET(foundData->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "matches", NewStringType::kNormal).ToLocalChecked(),
0310     Boolean::New(isolate, matches)));
0311   if (matchingFilter) {
0312     CHECK_SET(foundData->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "matchingFilter", NewStringType::kNormal).ToLocalChecked(),
0313       String::NewFromUtf8(isolate, matchingFilter->data, NewStringType::kNormal).ToLocalChecked()));
0314     if (matchingFilter->ruleDefinition != nullptr) {
0315       CHECK_SET(foundData->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "matchingOrigRule", NewStringType::kNormal).ToLocalChecked(),
0316         String::NewFromUtf8(isolate, matchingFilter->ruleDefinition, NewStringType::kNormal).ToLocalChecked()));
0317     }
0318   }
0319   if (matchingExceptionFilter) {
0320     CHECK_SET(foundData->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "matchingExceptionFilter", NewStringType::kNormal).ToLocalChecked(),
0321       String::NewFromUtf8(isolate, matchingExceptionFilter->data, NewStringType::kNormal).ToLocalChecked()));
0322     if (matchingExceptionFilter->ruleDefinition != nullptr) {
0323       CHECK_SET(foundData->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "matchingExceptionOrigRule", NewStringType::kNormal).ToLocalChecked(),
0324         String::NewFromUtf8(isolate, matchingExceptionFilter->ruleDefinition, NewStringType::kNormal).ToLocalChecked()));
0325     }
0326   }
0327   args.GetReturnValue().Set(foundData);
0328 }
0329 
0330 void AdBlockClientWrap::Serialize(const FunctionCallbackInfo<Value>& args) {
0331   Isolate* isolate = args.GetIsolate();
0332   AdBlockClientWrap* obj =
0333     ObjectWrap::Unwrap<AdBlockClientWrap>(args.Holder());
0334 
0335   int totalSize = 0;
0336   // Serialize data
0337   char* data = obj->serialize(&totalSize);
0338   if (nullptr == data) {
0339     isolate->ThrowException(Exception::TypeError(
0340       String::NewFromUtf8(isolate, "Could not serialize", NewStringType::kNormal).ToLocalChecked()));
0341     return;
0342   }
0343 
0344   MaybeLocal<Object> buffer = node::Buffer::New(isolate, totalSize);
0345   Local<Object> localBuffer;
0346   if (!buffer.ToLocal(&localBuffer)) {
0347     isolate->ThrowException(Exception::TypeError(
0348       String::NewFromUtf8(isolate, "Could not convert MaybeLocal to Local", NewStringType::kNormal).ToLocalChecked()));
0349     return;
0350   }
0351   memcpy(node::Buffer::Data(localBuffer), data, totalSize);
0352   delete[] data;
0353   args.GetReturnValue().Set(localBuffer);
0354 }
0355 void AdBlockClientWrap::Deserialize(const FunctionCallbackInfo<Value>& args) {
0356   Isolate* isolate = args.GetIsolate();
0357   AdBlockClientWrap* obj =
0358     ObjectWrap::Unwrap<AdBlockClientWrap>(args.Holder());
0359 
0360   if (args.Length() < 1) {
0361     isolate->ThrowException(Exception::TypeError(
0362       String::NewFromUtf8(isolate, "Wrong number of arguments", NewStringType::kNormal).ToLocalChecked()));
0363     return;
0364   }
0365 
0366   if (!args[0]->IsArrayBufferView()) {
0367     isolate->ThrowException(Exception::Error(
0368       String::NewFromUtf8(isolate,
0369         "Provided string is not valid, serialized DAT data", NewStringType::kNormal).ToLocalChecked()));
0370     return;
0371   }
0372 
0373   unsigned char *buf = (unsigned char *)node::Buffer::Data(args[0]);
0374   size_t length = node::Buffer::Length(args[0]);
0375   const char *oldDeserializedData = obj->getDeserializedBuffer();
0376   if (nullptr != oldDeserializedData) {
0377     delete []oldDeserializedData;
0378   }
0379   char *deserializedData = new char[length];
0380   memcpy(deserializedData, buf, length);
0381   args.GetReturnValue().Set(Boolean::New(isolate,
0382     obj->deserialize(deserializedData)));
0383 }
0384 
0385 void AdBlockClientWrap::AddTag(const FunctionCallbackInfo<Value>& args) {
0386   Isolate* isolate = args.GetIsolate();
0387   String::Utf8Value str(isolate, args[0]->ToString(isolate->GetCurrentContext())
0388       .FromMaybe(Local<String>()));
0389   const char * buffer = *str;
0390 
0391   AdBlockClientWrap* obj =
0392     ObjectWrap::Unwrap<AdBlockClientWrap>(args.Holder());
0393   obj->addTag(buffer);
0394 }
0395 
0396 void AdBlockClientWrap::RemoveTag(const FunctionCallbackInfo<Value>& args) {
0397   Isolate* isolate = args.GetIsolate();
0398   String::Utf8Value str(isolate, args[0]->ToString(isolate->GetCurrentContext())
0399       .FromMaybe(Local<String>()));
0400   const char * buffer = *str;
0401 
0402   AdBlockClientWrap* obj =
0403     ObjectWrap::Unwrap<AdBlockClientWrap>(args.Holder());
0404   obj->removeTag(buffer);
0405 }
0406 
0407 void AdBlockClientWrap::GetParsingStats(
0408     const FunctionCallbackInfo<Value>& args) {
0409   Isolate* isolate = args.GetIsolate();
0410   AdBlockClientWrap* obj =
0411     ObjectWrap::Unwrap<AdBlockClientWrap>(args.Holder());
0412   Local<Object> stats = Object::New(isolate);
0413   CHECK_SET(stats->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "numFilters", NewStringType::kNormal).ToLocalChecked(),
0414     Int32::New(isolate, obj->numFilters)));
0415   CHECK_SET(stats->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "numCosmeticFilters", NewStringType::kNormal).ToLocalChecked(),
0416     Int32::New(isolate, obj->numCosmeticFilters)));
0417   CHECK_SET(stats->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "numExceptionFilters", NewStringType::kNormal).ToLocalChecked(),
0418     Int32::New(isolate, obj->numExceptionFilters)));
0419   CHECK_SET(stats->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "numNoFingerprintFilters", NewStringType::kNormal).ToLocalChecked(),
0420     Int32::New(isolate, obj->numNoFingerprintFilters)));
0421   CHECK_SET(stats->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "numNoFingerprintDomainOnlyFilters", NewStringType::kNormal).ToLocalChecked(),
0422     Int32::New(isolate, obj->numNoFingerprintDomainOnlyFilters)));
0423   CHECK_SET(stats->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate,
0424         "numNoFingerprintAntiDomainOnlyFilters", NewStringType::kNormal).ToLocalChecked(),
0425     Int32::New(isolate, obj->numNoFingerprintAntiDomainOnlyFilters)));
0426   CHECK_SET(stats->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "numNoFingerprintExceptionFilters", NewStringType::kNormal).ToLocalChecked(),
0427     Int32::New(isolate, obj->numNoFingerprintExceptionFilters)));
0428   CHECK_SET(stats->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate,
0429         "numNoFingerprintDomainOnlyExceptionFilters", NewStringType::kNormal).ToLocalChecked(),
0430     Int32::New(isolate, obj->numNoFingerprintDomainOnlyExceptionFilters)));
0431   CHECK_SET(stats->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate,
0432         "numNoFingerprintAntiDomainOnlyExceptionFilters", NewStringType::kNormal).ToLocalChecked(),
0433     Int32::New(isolate, obj->numNoFingerprintAntiDomainOnlyExceptionFilters)));
0434   CHECK_SET(stats->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "numHostAnchoredFilters", NewStringType::kNormal).ToLocalChecked(),
0435     Int32::New(isolate, obj->numHostAnchoredFilters)));
0436   CHECK_SET(stats->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "numHostAnchoredExceptionFilters", NewStringType::kNormal).ToLocalChecked(),
0437     Int32::New(isolate, obj->numHostAnchoredExceptionFilters)));
0438   args.GetReturnValue().Set(stats);
0439 }
0440 
0441 void AdBlockClientWrap::GetFilters(
0442     const FunctionCallbackInfo<Value>& args) {
0443   Isolate* isolate = args.GetIsolate();
0444   AdBlockClientWrap* obj =
0445     ObjectWrap::Unwrap<AdBlockClientWrap>(args.Holder());
0446 
0447   String::Utf8Value str(isolate, args[0]->ToString(isolate->GetCurrentContext())
0448       .FromMaybe(Local<String>()));
0449   const char * filterType = *str;
0450 
0451   Local<Array> result_list = Array::New(isolate);
0452   Filter *filter;
0453   int numFilters = 0;
0454 
0455   if (!strcmp(filterType, "filters")) {
0456     filter = obj->filters;
0457     numFilters = obj->numFilters;
0458   } else if (!strcmp(filterType, "cosmeticFilters")) {
0459     filter = obj->cosmeticFilters;
0460     numFilters = obj->numCosmeticFilters;
0461   } else if (!strcmp(filterType, "htmlFilters")) {
0462     filter = obj->htmlFilters;
0463     numFilters = obj->numHtmlFilters;
0464   } else if (!strcmp(filterType, "exceptionFilters")) {
0465     filter = obj->exceptionFilters;
0466     numFilters = obj->numExceptionFilters;
0467   } else if (!strcmp(filterType, "noFingerprintFilters")) {
0468     filter = obj->noFingerprintFilters;
0469     numFilters = obj->numNoFingerprintFilters;
0470   } else if (!strcmp(filterType, "noFingerprintExceptionFilters")) {
0471     filter = obj->noFingerprintExceptionFilters;
0472     numFilters = obj->numNoFingerprintExceptionFilters;
0473   } else if (!strcmp(filterType, "noFingerprintDomainOnlyFilters")) {
0474     filter = obj->noFingerprintDomainOnlyFilters;
0475     numFilters = obj->numNoFingerprintDomainOnlyFilters;
0476   } else if (!strcmp(filterType, "noFingerprintAntiDomainOnlyFilters")) {
0477     filter = obj->noFingerprintAntiDomainOnlyFilters;
0478     numFilters = obj->numNoFingerprintAntiDomainOnlyFilters;
0479   } else if (!strcmp(filterType, "noFingerprintDomainOnlyExceptionFilters")) {
0480     filter = obj->noFingerprintDomainOnlyExceptionFilters;
0481     numFilters = obj->numNoFingerprintDomainOnlyExceptionFilters;
0482   } else if (!strcmp(filterType,
0483         "noFingerprintAntiDomainOnlyExceptionFilters")) {
0484     filter = obj->noFingerprintAntiDomainOnlyExceptionFilters;
0485     numFilters = obj->numNoFingerprintAntiDomainOnlyExceptionFilters;
0486   }
0487 
0488   for (int i = 0; i < numFilters; i++) {
0489     Local<Object> result = Object::New(isolate);
0490     if (filter->data && filter->dataLen) {
0491       if (filter->dataLen == -1) {
0492         filter->dataLen = static_cast<int>(strlen(filter->data));
0493       }
0494       char * data = new char[filter->dataLen + 1];
0495       data[filter->dataLen] = '\0';
0496       memcpy(data, filter->data, filter->dataLen);
0497       CHECK_SET(result->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "data", NewStringType::kNormal).ToLocalChecked(),
0498         String::NewFromUtf8(isolate, data, NewStringType::kNormal).ToLocalChecked()));
0499       delete[] data;
0500     }
0501     if (filter->host && filter->hostLen) {
0502       if (filter->hostLen == -1) {
0503         filter->hostLen = static_cast<int>(strlen(filter->host));
0504       }
0505       char * host = new char[filter->hostLen + 1];
0506       host[filter->hostLen] = '\0';
0507       memcpy(host, filter->host, filter->hostLen);
0508       CHECK_SET(result->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "host", NewStringType::kNormal).ToLocalChecked(),
0509         String::NewFromUtf8(isolate, host, NewStringType::kNormal).ToLocalChecked()));
0510       delete[] host;
0511     }
0512 
0513     Local<Array> domain_list = Array::New(isolate);
0514     Local<Array> anti_domain_list = Array::New(isolate);
0515     if (filter->domainList) {
0516       char * filter_domain_list = filter->domainList;
0517       size_t domain_list_len = strlen(filter_domain_list);
0518       // Setup a buffer the max size of a domain, we'll use it for each domain
0519       // which is less or the same length.
0520       char * dest_buffer = new char[domain_list_len + 1];
0521       memset(dest_buffer, 0, domain_list_len + 1);
0522       int start_offset = 0;
0523       int len = 0;
0524       int domain_list_count = 0;
0525       int anti_domain_list_count = 0;
0526       const char *p = filter_domain_list;
0527       while (true) {
0528         if (*p == '|' || *p == '\0') {
0529           const char *domain = filter_domain_list + start_offset;
0530           if (len > 0 && *domain != '~') {
0531             memcpy(dest_buffer, domain, len);
0532             CHECK_SET(domain_list->Set(isolate->GetCurrentContext(), domain_list_count++,
0533               String::NewFromUtf8(isolate, dest_buffer, NewStringType::kNormal).ToLocalChecked()));
0534           } else if (len > 0 && *domain == '~') {
0535             memcpy(dest_buffer, domain + 1, len - 1);
0536             CHECK_SET(anti_domain_list->Set(isolate->GetCurrentContext(), anti_domain_list_count++,
0537               String::NewFromUtf8(isolate, dest_buffer, NewStringType::kNormal).ToLocalChecked()));
0538           }
0539 
0540           start_offset += len + 1;
0541           len = -1;
0542           memset(dest_buffer, 0, domain_list_len + 1);
0543         }
0544         if (*p == '\0') {
0545           break;
0546         }
0547         p++;
0548         len++;
0549       }
0550       delete[] dest_buffer;
0551     }
0552     CHECK_SET(result->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "isDomainOnlyFilter", NewStringType::kNormal).ToLocalChecked(),
0553         Boolean::New(isolate, filter->isDomainOnlyFilter() &&
0554           ((~filter->filterType) & FTException))));
0555     CHECK_SET(result->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "isAntiDomainOnlyFilter", NewStringType::kNormal).ToLocalChecked(),
0556         Boolean::New(isolate, filter->isAntiDomainOnlyFilter() &&
0557           ((~filter->filterType) & FTException))));
0558     CHECK_SET(result->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "isDomainOnlyExceptionFilter", NewStringType::kNormal).ToLocalChecked(),
0559         Boolean::New(isolate, filter->isDomainOnlyFilter() &&
0560           (filter->filterType & FTException))));
0561     CHECK_SET(result->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate,
0562           "isAntiDomainOnlyExceptionFilter", NewStringType::kNormal).ToLocalChecked(),
0563         Boolean::New(isolate, filter->isAntiDomainOnlyFilter() &&
0564           (filter->filterType & FTException))));
0565     CHECK_SET(result->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "domainList", NewStringType::kNormal).ToLocalChecked(), domain_list));
0566     CHECK_SET(result->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate,
0567           "antiDomainList", NewStringType::kNormal).ToLocalChecked(), anti_domain_list));
0568     CHECK_SET(result->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "tag", NewStringType::kNormal).ToLocalChecked(),
0569         String::NewFromUtf8(isolate,
0570           std::string(filter->tagLen > 0 ? filter->tag : "",
0571             filter->tagLen).c_str(), NewStringType::kNormal).ToLocalChecked()));
0572     CHECK_SET(result_list->Set(isolate->GetCurrentContext(), i, result));
0573     filter++;
0574   }
0575   args.GetReturnValue().Set(result_list);
0576 }
0577 
0578 void AdBlockClientWrap::GetFingerprint(
0579     const FunctionCallbackInfo<Value>& args) {
0580   Isolate* isolate = args.GetIsolate();
0581   AdBlockClientWrap* obj =
0582     ObjectWrap::Unwrap<AdBlockClientWrap>(args.Holder());
0583   String::Utf8Value str(isolate, args[0]->ToString(isolate->GetCurrentContext())
0584       .FromMaybe(Local<String>()));
0585   const char * inputBuffer = *str;
0586 
0587   char * fingerprintBuffer = new char[AdBlockClient::kFingerprintSize + 1];
0588   if (obj->getFingerprint(fingerprintBuffer, inputBuffer)) {
0589     args.GetReturnValue().Set(String::NewFromUtf8(isolate, fingerprintBuffer, NewStringType::kNormal).ToLocalChecked());
0590   }
0591   delete[] fingerprintBuffer;
0592 }
0593 
0594 void AdBlockClientWrap::GetMatchingStats(
0595     const FunctionCallbackInfo<Value>& args) {
0596   Isolate* isolate = args.GetIsolate();
0597   AdBlockClientWrap* obj =
0598     ObjectWrap::Unwrap<AdBlockClientWrap>(args.Holder());
0599   Local<Object> stats = Object::New(isolate);
0600   CHECK_SET(stats->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "numFalsePositives", NewStringType::kNormal).ToLocalChecked(),
0601     Int32::New(isolate, obj->numFalsePositives)));
0602   CHECK_SET(stats->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "numExceptionFalsePositives", NewStringType::kNormal).ToLocalChecked(),
0603     Int32::New(isolate, obj->numExceptionFalsePositives)));
0604   CHECK_SET(stats->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "numBloomFilterSaves", NewStringType::kNormal).ToLocalChecked(),
0605     Int32::New(isolate, obj->numBloomFilterSaves)));
0606   CHECK_SET(stats->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "numExceptionBloomFilterSaves", NewStringType::kNormal).ToLocalChecked(),
0607     Int32::New(isolate, obj->numExceptionBloomFilterSaves)));
0608   CHECK_SET(stats->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "numHashSetSaves", NewStringType::kNormal).ToLocalChecked(),
0609     Int32::New(isolate, obj->numHashSetSaves)));
0610   CHECK_SET(stats->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "numExceptionHashSetSaves", NewStringType::kNormal).ToLocalChecked(),
0611     Int32::New(isolate, obj->numExceptionHashSetSaves)));
0612   args.GetReturnValue().Set(stats);
0613 }
0614 
0615 void AdBlockClientWrap::EnableBadFingerprintDetection(
0616     const FunctionCallbackInfo<Value>& args) {
0617   AdBlockClientWrap* obj =
0618     ObjectWrap::Unwrap<AdBlockClientWrap>(args.Holder());
0619   obj->enableBadFingerprintDetection();
0620 }
0621 
0622 void AdBlockClientWrap::GenerateBadFingerprintsHeader(
0623     const FunctionCallbackInfo<Value>& args) {
0624   Isolate* isolate = args.GetIsolate();
0625   String::Utf8Value str(isolate, args[0]->ToString(isolate->GetCurrentContext())
0626       .FromMaybe(Local<String>()));
0627   const char * filename = *str;
0628   AdBlockClientWrap* obj =
0629     ObjectWrap::Unwrap<AdBlockClientWrap>(args.Holder());
0630   obj->badFingerprintsHashSet->generateHeader(filename);
0631 }
0632 
0633 void AdBlockClientWrap::GenerateDefaultManifestFile(
0634     const FunctionCallbackInfo<Value>& args) {
0635   Isolate* isolate = args.GetIsolate();
0636   String::Utf8Value str(isolate, args[0]->ToString(isolate->GetCurrentContext())
0637       .FromMaybe(Local<String>()));
0638   const char * dir = *str;
0639   std::string filename = dir + std::string("/default-manifest.json");
0640   GenerateManifestFile("Default", kAdBlockDefaultBase64PublicKey, filename);
0641 }
0642 
0643 void AdBlockClientWrap::GenerateRegionalManifestFiles(
0644     const FunctionCallbackInfo<Value>& args) {
0645   Isolate* isolate = args.GetIsolate();
0646   String::Utf8Value str(isolate, args[0]->ToString(isolate->GetCurrentContext())
0647       .FromMaybe(Local<String>()));
0648   const char * dir = *str;
0649   for (auto& entry : region_lists) {
0650     const std::string filename = (
0651       dir +
0652       std::string("/") +
0653       entry.uuid +
0654       std::string("-manifest.json"));
0655     GenerateManifestFile(entry.title, entry.base64_public_key, filename);
0656   }
0657 }
0658 
0659 void AdBlockClientWrap::Cleanup(const FunctionCallbackInfo<Value>& args) {
0660   AdBlockClientWrap* obj =
0661     ObjectWrap::Unwrap<AdBlockClientWrap>(args.Holder());
0662   const char *deserializedData = obj->getDeserializedBuffer();
0663   if (nullptr != deserializedData) {
0664     delete []deserializedData;
0665     deserializedData = nullptr;
0666   }
0667   delete obj;
0668 }
0669 
0670 }  // namespace ad_block_client_wrap
0671