A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/gorhill/uBlock/commit/6acf97bf51 below:

Rewrite cname uncloaking code to account for new `ipaddress=` option · gorhill/uBlock@6acf97b · GitHub

@@ -26,8 +26,10 @@ import {

26 26 27 27

/******************************************************************************/

28 28 29 -

// Canonical name-uncloaking feature.

30 -

let cnameUncloakEnabled = browser.dns instanceof Object;

29 +

const dnsAPI = browser.dns;

30 + 31 +

const isPromise = o => o instanceof Promise;

32 +

const reIPv4 = /^\d+\.\d+\.\d+\.\d+$/

31 33 32 34

// Related issues:

33 35

// - https://github.com/gorhill/uBlock/issues/1327

@@ -40,21 +42,24 @@ vAPI.Net = class extends vAPI.Net {

40 42

constructor() {

41 43

super();

42 44

this.pendingRequests = [];

43 -

this.canUncloakCnames = browser.dns instanceof Object;

44 -

this.cnames = new Map([ [ '', null ] ]);

45 +

this.dnsList = []; // ring buffer

46 +

this.dnsWritePtr = 0; // next write pointer in ring buffer

47 +

this.dnsMaxCount = 256; // max size of ring buffer

48 +

this.dnsDict = new Map(); // hn to index in ring buffer

49 +

this.dnsEntryTTL = 60000; // delay after which an entry is obsolete

50 +

this.canUncloakCnames = true;

51 +

this.cnameUncloakEnabled = true;

45 52

this.cnameIgnoreList = null;

46 53

this.cnameIgnore1stParty = true;

47 54

this.cnameIgnoreExceptions = true;

48 55

this.cnameIgnoreRootDocument = true;

49 -

this.cnameMaxTTL = 120;

50 56

this.cnameReplayFullURL = false;

51 -

this.cnameFlushTime = Date.now() + this.cnameMaxTTL * 60000;

52 57

}

58 + 53 59

setOptions(options) {

54 60

super.setOptions(options);

55 61

if ( 'cnameUncloakEnabled' in options ) {

56 -

cnameUncloakEnabled =

57 -

this.canUncloakCnames &&

62 +

this.cnameUncloakEnabled =

58 63

options.cnameUncloakEnabled !== false;

59 64

}

60 65

if ( 'cnameIgnoreList' in options ) {

@@ -73,15 +78,13 @@ vAPI.Net = class extends vAPI.Net {

73 78

this.cnameIgnoreRootDocument =

74 79

options.cnameIgnoreRootDocument !== false;

75 80

}

76 -

if ( 'cnameMaxTTL' in options ) {

77 -

this.cnameMaxTTL = options.cnameMaxTTL || 120;

78 -

}

79 81

if ( 'cnameReplayFullURL' in options ) {

80 82

this.cnameReplayFullURL = options.cnameReplayFullURL === true;

81 83

}

82 -

this.cnames.clear(); this.cnames.set('', null);

83 -

this.cnameFlushTime = Date.now() + this.cnameMaxTTL * 60000;

84 +

this.dnsList.fill(null);

85 +

this.dnsDict.clear();

84 86

}

87 + 85 88

normalizeDetails(details) {

86 89

const type = details.type;

87 90

@@ -104,6 +107,7 @@ vAPI.Net = class extends vAPI.Net {

104 107

}

105 108

}

106 109

}

110 + 107 111

denormalizeTypes(types) {

108 112

if ( types.length === 0 ) {

109 113

return Array.from(this.validTypes);

@@ -122,75 +126,19 @@ vAPI.Net = class extends vAPI.Net {

122 126

}

123 127

return Array.from(out);

124 128

}

129 + 125 130

canonicalNameFromHostname(hn) {

126 -

const cnRecord = this.cnames.get(hn);

127 -

if ( cnRecord !== undefined && cnRecord !== null ) {

128 -

return cnRecord.cname;

129 -

}

130 -

}

131 -

processCanonicalName(hn, cnRecord, details) {

132 -

if ( cnRecord === null ) { return; }

133 -

if ( cnRecord.isRootDocument ) { return; }

134 -

const hnBeg = details.url.indexOf(hn);

135 -

if ( hnBeg === -1 ) { return; }

136 -

const oldURL = details.url;

137 -

let newURL = oldURL.slice(0, hnBeg) + cnRecord.cname;

138 -

const hnEnd = hnBeg + hn.length;

139 -

if ( this.cnameReplayFullURL ) {

140 -

newURL += oldURL.slice(hnEnd);

141 -

} else {

142 -

const pathBeg = oldURL.indexOf('/', hnEnd);

143 -

if ( pathBeg !== -1 ) {

144 -

newURL += oldURL.slice(hnEnd, pathBeg + 1);

145 -

}

146 -

}

147 -

details.url = newURL;

148 -

details.aliasURL = oldURL;

149 -

return super.onBeforeSuspendableRequest(details);

150 -

}

151 -

recordCanonicalName(hn, record, isRootDocument) {

152 -

if ( (this.cnames.size & 0b111111) === 0 ) {

153 -

const now = Date.now();

154 -

if ( now >= this.cnameFlushTime ) {

155 -

this.cnames.clear(); this.cnames.set('', null);

156 -

this.cnameFlushTime = now + this.cnameMaxTTL * 60000;

157 -

}

158 -

}

159 -

let cname =

160 -

typeof record.canonicalName === 'string' &&

161 -

record.canonicalName !== hn

162 -

? record.canonicalName

163 -

: '';

164 -

if (

165 -

cname !== '' &&

166 -

this.cnameIgnore1stParty &&

167 -

domainFromHostname(cname) === domainFromHostname(hn)

168 -

) {

169 -

cname = '';

170 -

}

171 -

if (

172 -

cname !== '' &&

173 -

this.cnameIgnoreList !== null &&

174 -

this.cnameIgnoreList.test(cname)

175 -

) {

176 -

cname = '';

177 -

}

178 -

const cnRecord = cname !== '' ? { cname, isRootDocument } : null;

179 -

this.cnames.set(hn, cnRecord);

180 -

return cnRecord;

131 +

if ( hn === '' ) { return; }

132 +

const dnsEntry = this.dnsFromCache(hn);

133 +

if ( isPromise(dnsEntry) ) { return; }

134 +

return dnsEntry?.cname;

181 135

}

136 + 182 137

regexFromStrList(list) {

183 -

if (

184 -

typeof list !== 'string' ||

185 -

list.length === 0 ||

186 -

list === 'unset' ||

187 -

browser.dns instanceof Object === false

188 -

) {

138 +

if ( typeof list !== 'string' || list.length === 0 || list === 'unset' ) {

189 139

return null;

190 140

}

191 -

if ( list === '*' ) {

192 -

return /^./;

193 -

}

141 +

if ( list === '*' ) { return /^./; }

194 142

return new RegExp(

195 143

'(?:^|\\.)(?:' +

196 144

list.trim()

@@ -200,9 +148,14 @@ vAPI.Net = class extends vAPI.Net {

200 148

')$'

201 149

);

202 150

}

151 + 203 152

onBeforeSuspendableRequest(details) {

153 +

const hn = hostnameFromNetworkURL(details.url);

154 +

const dnsEntry = this.dnsFromCache(hn);

155 +

if ( dnsEntry?.ip ) {

156 +

details.ip = dnsEntry.ip;

157 +

}

204 158

const r = super.onBeforeSuspendableRequest(details);

205 -

if ( cnameUncloakEnabled === false ) { return r; }

206 159

if ( r !== undefined ) {

207 160

if (

208 161

r.cancel === true ||

@@ -212,25 +165,128 @@ vAPI.Net = class extends vAPI.Net {

212 165

return r;

213 166

}

214 167

}

215 -

const hn = hostnameFromNetworkURL(details.url);

216 -

const cnRecord = this.cnames.get(hn);

217 -

if ( cnRecord !== undefined ) {

218 -

return this.processCanonicalName(hn, cnRecord, details);

168 +

if ( dnsEntry !== undefined ) {

169 +

if ( isPromise(dnsEntry) === false ) {

170 +

return this.onAfterDNSResolution(hn, details, dnsEntry);

171 +

}

219 172

}

220 -

if ( details.proxyInfo && details.proxyInfo.proxyDNS ) { return; }

221 -

const documentUrl = details.documentUrl || details.url;

222 -

const isRootDocument = this.cnameIgnoreRootDocument &&

223 -

hn === hostnameFromNetworkURL(documentUrl);

224 -

return browser.dns.resolve(hn, [ 'canonical_name' ]).then(

225 -

rec => {

226 -

const cnRecord = this.recordCanonicalName(hn, rec, isRootDocument);

227 -

return this.processCanonicalName(hn, cnRecord, details);

228 -

},

229 -

( ) => {

230 -

this.cnames.set(hn, null);

173 +

if ( this.dnsShouldResolve(hn) === false ) { return; }

174 +

if ( details.proxyInfo?.proxyDNS ) { return; }

175 +

const promise = dnsEntry || this.dnsResolve(hn, details);

176 +

return promise.then(( ) => this.onAfterDNSResolution(hn, details));

177 +

}

178 + 179 +

onAfterDNSResolution(hn, details, dnsEntry) {

180 +

if ( dnsEntry === undefined ) {

181 +

dnsEntry = this.dnsFromCache(hn);

182 +

if ( dnsEntry === undefined || isPromise(dnsEntry) ) { return; }

183 +

}

184 +

let proceed = false;

185 +

if ( dnsEntry.cname && this.cnameUncloakEnabled ) {

186 +

const newURL = this.uncloakURL(hn, dnsEntry, details);

187 +

if ( newURL ) {

188 +

details.aliasURL = details.url;

189 +

details.url = newURL;

190 +

proceed = true;

231 191

}

192 +

}

193 +

if ( dnsEntry.ip && details.ip !== dnsEntry.ip ) {

194 +

details.ip = dnsEntry.ip

195 +

proceed = true;

196 +

}

197 +

if ( proceed === false ) { return; }

198 +

// Must call method on base class

199 +

return super.onBeforeSuspendableRequest(details);

200 +

}

201 + 202 +

dnsToCache(hn, record, details) {

203 +

const i = this.dnsDict.get(hn);

204 +

if ( i === undefined ) { return; }

205 +

const dnsEntry = {

206 +

hn,

207 +

until: Date.now() + this.dnsEntryTTL,

208 +

};

209 +

if ( record ) {

210 +

const cname = this.cnameFromRecord(hn, record, details);

211 +

if ( cname ) { dnsEntry.cname = cname; }

212 +

const ip = this.ipFromRecord(record);

213 +

if ( ip ) { dnsEntry.ip = ip; }

214 +

}

215 +

this.dnsList[i] = dnsEntry;

216 +

return dnsEntry;

217 +

}

218 + 219 +

dnsFromCache(hn) {

220 +

const i = this.dnsDict.get(hn);

221 +

if ( i === undefined ) { return; }

222 +

const dnsEntry = this.dnsList[i];

223 +

if ( dnsEntry === null ) { return; }

224 +

if ( isPromise(dnsEntry) ) { return dnsEntry; }

225 +

if ( dnsEntry.hn !== hn ) { return; }

226 +

if ( dnsEntry.until >= Date.now() ) { return dnsEntry; }

227 +

this.dnsList[i] = null;

228 +

this.dnsDict.delete(hn)

229 +

}

230 + 231 +

dnsShouldResolve(hn) {

232 +

if ( hn === '' ) { return false; }

233 +

const c0 = hn.charCodeAt(0);

234 +

if ( c0 === 0x5B /* [ */ ) { return false; }

235 +

if ( c0 > 0x39 /* 9 */ ) { return true; }

236 +

return reIPv4.test(hn) === false;

237 +

}

238 + 239 +

dnsResolve(hn, details) {

240 +

const i = this.dnsWritePtr++;

241 +

this.dnsWritePtr %= this.dnsMaxCount;

242 +

this.dnsDict.set(hn, i);

243 +

const promise = dnsAPI.resolve(hn, [ 'canonical_name' ]).then(

244 +

rec => this.dnsToCache(hn, rec, details),

245 +

( ) => this.dnsToCache(hn)

232 246

);

247 +

return (this.dnsList[i] = promise);

233 248

}

249 + 250 +

cnameFromRecord(hn, record, details) {

251 +

const cn = record.canonicalName;

252 +

if ( cn === undefined ) { return; }

253 +

if ( cn === hn ) { return; }

254 +

if ( this.cnameIgnore1stParty ) {

255 +

if ( domainFromHostname(cn) === domainFromHostname(hn) ) { return; }

256 +

}

257 +

if ( this.cnameIgnoreList !== null ) {

258 +

if ( this.cnameIgnoreList.test(cn) === false ) { return; }

259 +

}

260 +

if ( this.cnameIgnoreRootDocument ) {

261 +

const origin = hostnameFromNetworkURL(details.documentUrl || details.url);

262 +

if ( hn === origin ) { return; }

263 +

}

264 +

return cn;

265 +

}

266 + 267 +

uncloakURL(hn, dnsEntry, details) {

268 +

const hnBeg = details.url.indexOf(hn);

269 +

if ( hnBeg === -1 ) { return; }

270 +

const oldURL = details.url;

271 +

const newURL = oldURL.slice(0, hnBeg) + dnsEntry.cname;

272 +

const hnEnd = hnBeg + hn.length;

273 +

if ( this.cnameReplayFullURL ) {

274 +

return newURL + oldURL.slice(hnEnd);

275 +

}

276 +

const pathBeg = oldURL.indexOf('/', hnEnd);

277 +

if ( pathBeg !== -1 ) {

278 +

return newURL + oldURL.slice(hnEnd, pathBeg + 1);

279 +

}

280 +

return newURL;

281 +

}

282 + 283 +

ipFromRecord(record) {

284 +

const { addresses } = record;

285 +

if ( Array.isArray(addresses) === false ) { return; }

286 +

if ( addresses.length === 0 ) { return; }

287 +

return addresses[0];

288 +

}

289 + 234 290

suspendOneRequest(details) {

235 291

const pending = {

236 292

details: Object.assign({}, details),

@@ -243,6 +299,7 @@ vAPI.Net = class extends vAPI.Net {

243 299

this.pendingRequests.push(pending);

244 300

return pending.promise;

245 301

}

302 + 246 303

unsuspendAllRequests(discard = false) {

247 304

const pendingRequests = this.pendingRequests;

248 305

this.pendingRequests = [];

@@ -254,6 +311,7 @@ vAPI.Net = class extends vAPI.Net {

254 311

);

255 312

}

256 313

}

314 + 257 315

static canSuspend() {

258 316

return true;

259 317

}


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4