@@ -107,6 +107,24 @@ FilterPlainMore.prototype.retrieve = function(s, out) {
107107
108108/******************************************************************************/
109109
110+ // HTML tag specific to a hostname
111+ // Examples:
112+ // lindaikeji.blogspot.com##a > img[height="600"]
113+ // japantimes.co.jp##table[align="right"][width="250"]
114+
115+ var FilterElementHostname = function ( s , hostname ) {
116+ this . s = s ;
117+ this . hostname = hostname ;
118+ } ;
119+
120+ FilterElementHostname . prototype . retrieve = function ( s , out ) {
121+ if ( pageHostname . slice ( - this . hostname . length ) === this . hostname ) {
122+ out . push ( this . s ) ;
123+ }
124+ } ;
125+
126+ /******************************************************************************/
127+
110128// Pure id- and class-based filters specific to a hostname
111129// Examples:
112130// search.snapdo.com###ABottomD
@@ -164,25 +182,30 @@ FilterBucket.prototype.retrieve = function(s, out) {
164182/******************************************************************************/
165183
166184var FilterParser = function ( ) {
167- this . f = '' ;
185+ this . s = '' ;
186+ this . prefix = '' ;
187+ this . suffix = '' ;
168188 this . anchor = 0 ;
169189 this . filterType = '#' ;
170190 this . hostnames = [ ] ;
171191 this . invalid = false ;
172192 this . unsupported = false ;
193+ this . reParser = / ^ \s * ( [ ^ # ] * ) ( # [ # @ ] ) ( .+ ) \s * $ / ;
173194 this . rePlain = / ^ ( [ # . ] [ \w - ] + ) / ;
174195 this . rePlainMore = / ^ [ # . ] [ \w - ] + [ ^ \w - ] / ;
196+ this . reElement = / ^ [ a - z ] / i;
175197} ;
176198
177199/******************************************************************************/
178200
179201FilterParser . prototype . reset = function ( ) {
180- this . f = '' ;
181- this . anchor = 0 ;
202+ this . s = '' ;
203+ this . prefix = '' ;
204+ this . suffix = '' ;
205+ this . anchor = '' ;
182206 this . filterType = '#' ;
183207 this . hostnames = [ ] ;
184208 this . invalid = false ;
185- this . unsupported = false ;
186209 return this ;
187210} ;
188211
@@ -192,45 +215,41 @@ FilterParser.prototype.parse = function(s) {
192215 // important!
193216 this . reset ( ) ;
194217
195- this . anchor = s . indexOf ( '##' ) ;
196- if ( this . anchor < 0 ) {
197- this . anchor = s . indexOf ( '#@#' ) ;
198- if ( this . anchor < 0 ) {
199- this . invalid = true ;
200- return this ;
201- }
202- }
203- this . filterType = s . charAt ( this . anchor + 1 ) ;
204- if ( this . anchor > 0 ) {
205- this . hostnames = s . slice ( 0 , this . anchor ) . split ( / \s * , \s * / ) ;
206- }
207- if ( this . filterType === '@' ) {
208- this . f = s . slice ( this . anchor + 3 ) ;
209- } else {
210- this . f = s . slice ( this . anchor + 2 ) ;
211- }
212-
213- // selector
214- var selectorType = this . f . charAt ( 0 ) ;
215- if ( selectorType === '#' || selectorType === '.' ) {
218+ var matches = this . reParser . exec ( s ) ;
219+ if ( matches === null || matches . length !== 4 ) {
220+ this . invalid = true ;
216221 return this ;
217222 }
218223
219- this . unspported = true ;
224+ // Remember original string
225+ this . s = s ;
226+ this . prefix = matches [ 1 ] ;
227+ this . anchor = matches [ 2 ] ;
228+ this . suffix = matches [ 3 ] ;
220229
230+ this . filterType = this . anchor . charAt ( 1 ) ;
231+ if ( this . prefix !== '' ) {
232+ this . hostnames = this . prefix . split ( / \s * , \s * / ) ;
233+ }
221234 return this ;
222235} ;
223236
224237/******************************************************************************/
225238
226239FilterParser . prototype . isPlainMore = function ( ) {
227- return this . rePlainMore . test ( this . f ) ;
240+ return this . rePlainMore . test ( this . suffix ) ;
241+ } ;
242+
243+ /******************************************************************************/
244+
245+ FilterParser . prototype . isElement = function ( ) {
246+ return this . reElement . test ( this . suffix ) ;
228247} ;
229248
230249/******************************************************************************/
231250
232251FilterParser . prototype . extractPlain = function ( ) {
233- var matches = this . rePlain . exec ( this . f ) ;
252+ var matches = this . rePlain . exec ( this . suffix ) ;
234253 if ( matches && matches . length === 2 ) {
235254 return matches [ 1 ] ;
236255 }
@@ -242,7 +261,7 @@ FilterParser.prototype.extractPlain = function() {
242261var FilterContainer = function ( ) {
243262 this . filterParser = new FilterParser ( ) ;
244263 this . acceptedCount = 0 ;
245- this . rejectedCount = 0 ;
264+ this . processedCount = 0 ;
246265 this . filters = { } ;
247266} ;
248267
@@ -252,55 +271,71 @@ var FilterContainer = function() {
252271
253272FilterContainer . prototype . reset = function ( ) {
254273 this . acceptedCount = 0 ;
255- this . rejectedCount = 0 ;
274+ this . processedCount = 0 ;
256275 this . filters = { } ;
257276} ;
258277
259278/******************************************************************************/
260279
261280FilterContainer . prototype . add = function ( s ) {
262281 var parsed = this . filterParser . parse ( s ) ;
282+ if ( parsed . invalid ) {
283+ return false ;
284+ }
285+
286+ this . processedCount += 1 ;
263287
264288 //if ( s === 'mail.google.com##.nH.adC > .nH > .nH > .u5 > .azN' ) {
265289 // debugger;
266290 //}
267291
268- if ( parsed . invalid ) {
269- return false ;
270- }
271-
272- var selectorType = parsed . f . charAt ( 0 ) ;
292+ var selectorType = parsed . suffix . charAt ( 0 ) ;
273293 if ( selectorType === '#' || selectorType === '.' ) {
274- this . acceptedCount += 1 ;
275294 return this . addPlainFilter ( parsed ) ;
276295 }
277296
278- this . rejectedCount += 1 ;
297+ if ( parsed . isElement ( ) ) {
298+ return this . addElementFilter ( parsed ) ;
299+ }
300+
279301 return false ;
280302} ;
281303
282304/******************************************************************************/
283305
284306FilterContainer . prototype . freeze = function ( ) {
285307 console . log ( 'HTTPSB> adp-hide-filters.js: %d filters accepted' , this . acceptedCount ) ;
286- console . log ( 'HTTPSB> adp-hide-filters.js: %d filters rejected ' , this . rejectedCount ) ;
287- console . log ( 'HTTPSB> adp-hide-filters.js: coverage is %s%' , ( this . acceptedCount * 100 / ( this . acceptedCount + this . rejectedCount ) ) . toFixed ( 1 ) ) ;
308+ console . log ( 'HTTPSB> adp-hide-filters.js: %d filters processed ' , this . processedCount ) ;
309+ console . log ( 'HTTPSB> adp-hide-filters.js: coverage is %s%' , ( this . acceptedCount * 100 / this . processedCount ) . toFixed ( 1 ) ) ;
288310
289311 // histogram('allFilters', this.filters);
290312} ;
291313
292314/******************************************************************************/
293315
316+ // TSSSDD
317+ // | | |
318+ // | | |
319+ // | | +---- domain (can be nil)
320+ // | +---- suffix (can be bil)
321+ // +---- type (# or @)
322+
294323FilterContainer . prototype . makeHash = function ( filterType , selector , domain ) {
295- var i = ( selector . length - 1 ) >> 2 ;
296- var hash = String . fromCharCode (
297- filterType . charCodeAt ( 0 ) << 8 |
298- selector . charCodeAt ( 0 ) ,
299- ( selector . charCodeAt ( 1 ) & 0xF ) << 12 |
300- ( selector . charCodeAt ( 1 + i ) & 0xF ) << 8 |
301- ( selector . charCodeAt ( 1 + i + i ) & 0xF ) << 4 |
302- ( selector . charCodeAt ( 1 + i + i + i ) & 0xF )
303- ) ;
324+ var i ;
325+ var hash ;
326+
327+ if ( selector === '' ) {
328+ hash = String . fromCharCode ( filterType . charCodeAt ( 0 ) << 8 ) ;
329+ } else {
330+ i = ( selector . length - 1 ) >> 2 ;
331+ hash = String . fromCharCode (
332+ filterType . charCodeAt ( 0 ) << 8 | selector . charCodeAt ( 0 ) ,
333+ ( selector . charCodeAt ( 1 ) & 0xF ) << 12 |
334+ ( selector . charCodeAt ( 1 + i ) & 0xF ) << 8 |
335+ ( selector . charCodeAt ( 1 + i + i ) & 0xF ) << 4 |
336+ ( selector . charCodeAt ( 1 + i + i + i ) & 0xF )
337+ ) ;
338+ }
304339 if ( ! domain ) {
305340 return hash ;
306341 }
@@ -323,9 +358,10 @@ FilterContainer.prototype.addPlainFilter = function(parsed) {
323358 if ( parsed . hostnames . length ) {
324359 return this . addPlainHostnameFilter ( parsed ) ;
325360 }
326- var f = new FilterPlain ( parsed . f ) ;
327- var hash = this . makeHash ( parsed . filterType , parsed . f ) ;
361+ var f = new FilterPlain ( parsed . suffix ) ;
362+ var hash = this . makeHash ( parsed . filterType , parsed . suffix ) ;
328363 this . addFilterEntry ( hash , f ) ;
364+ this . acceptedCount += 1 ;
329365} ;
330366
331367/******************************************************************************/
@@ -334,17 +370,17 @@ FilterContainer.prototype.addPlainHostnameFilter = function(parsed) {
334370 var httpsburi = HTTPSB . URI ;
335371 var f , hash ;
336372 var hostnames = parsed . hostnames ;
337- var i = hostnames . length ;
338- var hostname ;
373+ var i = hostnames . length , hostname ;
339374 while ( i -- ) {
340375 hostname = hostnames [ i ] ;
341376 if ( ! hostname ) {
342377 continue ;
343378 }
344- f = new FilterPlainHostname ( parsed . f , hostname ) ;
345- hash = this . makeHash ( parsed . filterType , parsed . f , httpsburi . domainFromHostname ( hostname ) ) ;
379+ f = new FilterPlainHostname ( parsed . suffix , hostname ) ;
380+ hash = this . makeHash ( parsed . filterType , parsed . suffix , httpsburi . domainFromHostname ( hostname ) ) ;
346381 this . addFilterEntry ( hash , f ) ;
347382 }
383+ this . acceptedCount += 1 ;
348384} ;
349385
350386/******************************************************************************/
@@ -357,9 +393,10 @@ FilterContainer.prototype.addPlainMoreFilter = function(parsed) {
357393 if ( plainSelector === '' ) {
358394 return ;
359395 }
360- var f = new FilterPlainMore ( parsed . f ) ;
396+ var f = new FilterPlainMore ( parsed . suffix ) ;
361397 var hash = this . makeHash ( parsed . filterType , plainSelector ) ;
362398 this . addFilterEntry ( hash , f ) ;
399+ this . acceptedCount += 1 ;
363400} ;
364401
365402/******************************************************************************/
@@ -372,17 +409,44 @@ FilterContainer.prototype.addPlainMoreHostnameFilter = function(parsed) {
372409 var httpsburi = HTTPSB . URI ;
373410 var f , hash ;
374411 var hostnames = parsed . hostnames ;
375- var i = hostnames . length ;
376- var hostname ;
412+ var i = hostnames . length , hostname ;
377413 while ( i -- ) {
378414 hostname = hostnames [ i ] ;
379415 if ( ! hostname ) {
380416 continue ;
381417 }
382- f = new FilterPlainMoreHostname ( parsed . f , hostname ) ;
418+ f = new FilterPlainMoreHostname ( parsed . suffix , hostname ) ;
383419 hash = this . makeHash ( parsed . filterType , plainSelector , httpsburi . domainFromHostname ( hostname ) ) ;
384420 this . addFilterEntry ( hash , f ) ;
385421 }
422+ this . acceptedCount += 1 ;
423+ } ;
424+
425+ /******************************************************************************/
426+
427+ FilterContainer . prototype . addElementFilter = function ( parsed ) {
428+ if ( parsed . hostnames . length ) {
429+ return this . addElementHostnameFilter ( parsed ) ;
430+ }
431+ } ;
432+
433+ /******************************************************************************/
434+
435+ FilterContainer . prototype . addElementHostnameFilter = function ( parsed ) {
436+ var httpsburi = HTTPSB . URI ;
437+ var f , hash ;
438+ var hostnames = parsed . hostnames ;
439+ var i = hostnames . length , hostname ;
440+ while ( i -- ) {
441+ hostname = hostnames [ i ] ;
442+ if ( ! hostname ) {
443+ continue ;
444+ }
445+ f = new FilterElementHostname ( parsed . suffix , hostname ) ;
446+ hash = this . makeHash ( parsed . filterType , '' , httpsburi . domainFromHostname ( hostname ) ) ;
447+ this . addFilterEntry ( hash , f ) ;
448+ }
449+ this . acceptedCount += 1 ;
386450} ;
387451
388452/******************************************************************************/
@@ -428,6 +492,15 @@ FilterContainer.prototype.retrieve = function(url, inSelectors) {
428492 bucket . retrieve ( selector , donthideSelectors ) ;
429493 }
430494 }
495+ // Generic elements for a specific domain
496+ hash = this . makeHash ( '#' , '' , domain ) ;
497+ if ( bucket = this . filters [ hash ] ) {
498+ bucket . retrieve ( selector , hideSelectors ) ;
499+ }
500+ hash = this . makeHash ( '@' , '' , domain ) ;
501+ if ( bucket = this . filters [ hash ] ) {
502+ bucket . retrieve ( selector , donthideSelectors ) ;
503+ }
431504 return {
432505 hide : hideSelectors . join ( ',' ) ,
433506 donthide : donthideSelectors . join ( ',' )
0 commit comments