adblock plus定義的廣告過濾清單非常好用,這裡分析一下adblock plus的廣告過濾規則
! 開始表示注釋
* 通配符,比對任何字元串
@@ 以此開頭表示白名單,
| 以此開始或者結束表示開始處或者結束處嚴格比對,沒有其他内容了
|| 以此開頭會忽略協定規則進行比對,比如忽略http,https等
^ 分隔符比對除數字,字母,-,.,%以外的其他字元
$ 指明後面的是過濾類型,比如是是image還是script等
按照adblock plus的說法,這些最終都轉換成了正規表達式來處理,具體怎麼實作不是很清楚。
對于大多數情況來說運作最耗時間的就是比對問題,類型,以及協定資訊可以根據url分析出來,很容易分離,
是以這裡重點介紹如何實作最核心的*,^的比對,通過一個patternStep來減小嵌套次數
/*
get a much bigger step for *.
*/
static inline
int patternStep( const char * s,
const char * p)
{
//這裡可以根據下一個字元多跳幾個
char temp[8];
int step=0;
const char * t=p;
while(*t!='*' && *t!='^' &&
*t!='\0')
{
step++;
t++;
}
if(!step) //防止隻有一個通配符的情況比如^,*
return 1;
memset(temp,0,sizeof(temp));
strncpy(temp,p,min(sizeof(temp)-1,step));
printf("temp=%s,step=%d\n",temp,step);
const char * res=strfind(s,temp);
if(!res) //沒有找到
return strlen(s); //移動真整個字元串
else
return max(1,res-s); //找到第一個比對的字元串的位置
}
test if a given string and a pattern
matches use adblock plus rule
give a string s and a pattern p ,
if they match,return 1, then return 0
*/
bool adbMatch(const
char * s, const char *
p,bool caseSensitivie=true) {
for (;;) {
switch(*p++) {
case '*' : // match 0-n of any characters
//這裡可以根據下一個字元多跳幾個
if (!*p) return true; // do
trailing * quickly
while (!adbMatch(s,
p,caseSensitivie))
{
if(!*s) return false;
s+=patternStep(s,p);
}
return true;
case '^':
if(isSeperator(*s))
s++;
break;
}
else
return false;//expect a
sepetor,
case '\0': // end of pattern
return !*s;
default :
if
(getCaseChar(*s++,caseSensitivie) !=
getCaseChar(*(p-1),caseSensitivie)) return false;
break;
}
}