FAQ - Adblock Plus 內部實作

哪裡有全部 Adblock Plus 偏好設定值的用途?

Adblock Plus 有許多可經由 about:config 存取的偏好設定。它們都是以 extensions.adblockplus. 開頭的 (與 Adblock 及 Adblock Plus 0.5 以adblock. 開頭不同)。完整的說明列表可在 這裡 取得。

如何從我的擴充套件存取 Adblock Plus?

要讓其他擴充套件整合 Adblock Plus,可使用 IAdblockPlus 介面。詳細情形請參閱 介面文件

Adblock Plus 是如何過濾網址的?

其實最困難的部份是由 Gecko,也就是 Firefox,Thunderbird 及其他應用程式的最底層引擎完成的。它包含一種稱之為「內容策略」(content policy) 的機制。內容策略簡單地說就是一個 JavaScript (或 C++) 物件,每當瀏覽器需要載入某些東西時就會呼叫。它會觀察網址及其他資料來決定是否允許載入。有許多內容策略是內建的 (當您在 Firefox 或者 SeaMonkey 中定義哪些網站的圖片不該載入時,您也就設定了其中一個內容策略),所有套件也都可以註冊一個自己專用的。所以 Adblock Plus 要做的也就是註冊一個自己的內容策略,剩下的就是建立應用程式邏輯來決定哪些網址應該阻擋,並提供使用者界面來設定過濾條件。

給開發者: 要註冊一個內容策略,您必須 撰寫一個 XPCOM 元件 並以nsIContentPolicy 介面 實作。確保調整模組的 registerSelf 方法來註冊您在 "content-policy" 類別中的元件 (利用 category manager 來實作)。現在您元件裡頭的 shouldLoad 方法將被呼叫,且您可以決定是否該接受指定的請求。

Adblock Plus 如何處理它的過濾條件,以及,哪種過濾條件更快?

所有的過濾條件都會在內部轉換成 正規表示法,即使不屬於這類寫法的條件也是。舉個例子,此條件 ad*banner.gif| 將被轉換成正規表示法 /ad.*banner\.gif$/。然而給予 Adblock Plus 一個網址時,它會針對所有的過濾條件進行檢查,一條接一條地檢查可不是簡單的工作 — 這會不必要地拖慢瀏覽速度。

除了將過濾條件轉換成正規表示法之外,Adblock Plus 也會嘗試從中摘錄出一些文字訊息。它需要一個唯一的,八個字元的字串 (這稱為一個「捷徑」,shortcut),當某網址符合過濾條件時,該字串會被呈遞出來 (其字串長度是隨意的,只是八個字元最合理)。舉個例子,若您有一條過濾條件 |http://ad.*,則 Adblock Plus 會選擇 "http://a","ttp://ad" 及 "tp://ad." 其中之一,這些字串中的任何一個都將在網址符合過濾條件時被呈遞。可惜的是,目前無法為包含星號的八個字元及正規表示法找出捷徑。

所有的捷徑都會被推入一個搜尋表中,Adblock Plus 會經由各自的捷徑快速搜尋到相對應的過濾條件。當某個特定的網址需要檢驗時,Adblock Plus 會先在表中搜尋已知的捷徑 (這個動作相當快速,所需時間幾乎與捷徑多寡無關)。只有在找到捷徑時,才針對這個字串進行相對應的正規表示法檢驗。然而,沒有捷徑的過濾條件將會被一條一條地檢測,這是相當慢的。

總結:使用哪一種過濾條件更快呢?您應該盡可能地少用正規表示法,它們一直都很龜速。然後盡量使用至少八個不間斷字元的簡單條件 (這表示裡頭不能包含像是 * 的特殊字元),否則它們會和正規表示法一樣慢。不過只要是符合簡單條件的規則,不論多寡,處理的速度都是一樣的。這就表示您即使拿 20 條簡單條件來取代一條正規表示法都是值得的。說到這裡 — 推薦使用 將正規表示法轉換成一般規則 這個網頁工具。

配對過濾條件的演算法細節

元素隱藏功能是如何實作的?

元素隱藏規則會被翻譯成 CSS 並套用到所有使用者造訪的網頁。一條像是 example.com#div(evil_ad) 看起來就等同:

@-moz-document domain(example.com)
{
  div#evil_ad, div.evil_ad
  {
    display: none !important;
  }
}

@-moz-document 是一個 CSS 標準的延伸,您可以在 Mozilla Developer Center

那些沒有限制特定網域的規則將會被設定在 http:// 及 https:// 協定下以防它們不小心隱藏瀏覽器的界面 (chrome:// 格式)。舉個例子,條件 #div(evil_ad) 將被翻譯為:

@-moz-document url-prefix(http://),url-prefix(https://)
{
  div#evil_ad, div.evil_ad
  {
    display: none !important;
  }
}

給開發者:Adblock Plus 使用這裡的 樣式服務。此介面自 Gecko 1.8 起允許擴充套件動態加入使用者樣式表 (以前只能修改 userContent.css 並需要重新啟動瀏覽器)。使用者樣式表將複寫所有網站的 CSS 程式碼,它們擁有最高的 優先權

過濾條件集多久下載一次?

預設值是每天更新。不過,條件集作者也可以自行調整,以防不必要的浪費流量等等。任何介於一小時到 21 天的值都是可行的。其中一種設定方式是利用 HTTP Expires 標頭。Apache 的 mod_expires 模組可以讓您這麼做,只需在 .htaccess 檔案中寫入:

ExpiresActive on
ExpiresByType text/plain "access plus 5 days"

這樣就會使條件集在 5 天後過期並重新下載。若您的條件集是由 Perl 腳本產生,您可以使用下列的指令:

$cgi->header(-expires => "+5d");

這也可以在類似 PHP 這樣的腳本語言中執行。若基於某些原因無法調整 HTTP 標頭,您也可以在條件集中加上一行註解。像是:

[Adblock]
! This list expires after 5 days

無論您將註解放在哪都可以。Adblock Plus 會尋找任何有 "expires after" 或 "expires:" 後面緊接著數字的註解。愈社會將數字解釋為天數。若數字後緊接著 "h" 字母則會將該數字解釋為小時,例如 "Expires: 3h" 或 "expires after 3 hours" 將告知 Adblock Plus 3個小時後再次下載列表。

注意這是介於每次下載的最短時間。如果使用者沒有啟動瀏覽器,那就只有在他再次啟動時才會下載。

我的條件集已經移動到別處了,要如何讓每個人都更新訂閱網址?

Adblock Plus 0.7.5 開始完整支援永久轉向。這表示不只會從新的位置下載條件集,還會改變 Adblock Plus 中訂閱的網址。那麼如何使用這項功能呢?

第一選擇:利用 HTTP 標頭轉向。向舊的條件集位址發出的請求會收到 "301 永久轉向" 的回應。Adblock Plus 將在轉向成功後調整條件集的的位置。您可以使用 Apache 的 mod_alias 模組建立轉向設定,將下列幾行加入 .htaccess 檔案:

Redirect permanent /old_list.txt http://example.com/new_list.txt

如果您無法在您的主機建立 HTTP 轉向請求,仍然可以使用特殊的註解來指定一個新的條件即位至。像是這樣:

[Adblock]
! Redirect: http://example.com/new_list.txt

無論您將註解放在哪都可以。Adblock Plus 將掃瞄所有 "redirect:" 及 "redirect to" 後面緊接著網址的註解。如果找到這樣的註解,就會在 一小時後 開始更新新位置的列表。若更新成功,則會調整條件集的訂閱位址。

最後,可能在當您的伺服器無法使用時,使用者每次更新您的條件集都會出現失敗。即使您無法避免這種錯誤發生,仍然有解決辦法。在下載失敗數次後會嘗試 (次數由 extensions.adblockplus.subscriptions_fallbackerrors 設定值定義)Adblock Plus 將聯絡定義在 extensions.adblockplus.subscriptions_fallbackurl 偏好設定中的位置取得進一步的指令。若此問題已知則會給出您條件集新的位置。所以若無法透過一般方式指示新的位置時,請 寫封信給我們

過濾條件集檔案的第一行會是什麼樣子?

通常條件集的第一行都是簡單的 [Adblock]。然而您也許已經注意到最近版本的 Adblock Plus 偶爾會替換成不同文字。這是因為您列表中有些條件需要使用新版 Adblock Plus 才支援的語法,而不被原本的 Adblock 支援。像下面這個例子:

(Adblock Plus 0.6.1.2 or higher required) [Adblock]

這只是一個簡單的註解。Adblock (或 Adblock Plus) 將忽略實際標記前的內容。這裡的需求版本不是強制性的,因為 Adblock Plus 0.6.1.2 也還不支援它。不過,如果您使用更新的過濾條件語法,您也許會需要改是這樣的註解:

[Adblock Plus 0.7.1]

這種標頭的類型從 Adblock Plus 0.7.1 開始支援。較舊的 Adblock Plus 及 Adblock 版本無法開啟這種標頭的檔案。至於目前的版本,會先檢查標頭的版本編號並與自己的版本比較。如果檔案需要更新的 Adblock Plus,則使用者會收到一個要求更新的訊息。條件集仍將為了新版 Adblock Plus 載入,不過會在偏好設定視窗中顯示警告訊息。

最後,如果你只想要求使用 Adblock Plus 而不想指定版本,您可以在檔案開頭寫上 [Adblock Plus]。當然這個檔案只會被 Adblock Plus 0.7.1 及更高版本接受。

要如何保護我的過濾條件集使其不會在下載時損毀?

代理伺服器和防毒軟體以及防火牆都可能會修改下載內容。有時過濾條件 "*/example/*" 會變成 "**",而導致所有東西都被擋光。要避免這種情形,條件集維護者可以在列表開頭插入檢查碼,像是:

[Adblock]
! Checksum: OaopkIiiAl77sSHk/VAWDA
test

Adblock Plus 若發現檢查碼與檔案內容不符則會忽略該次下載。當輸出規則時 Adblock Plus 會自動產生。檢查碼以下列方式計算:

  • 條件列表使用 UTF-8 編碼 (包含 第一行)。
  • 轉換所有換行字元為 UNIX 樣式 (若出現 \r 字元則將其移除)
  • 刪除空白列 (替換多個 \n 字元為單一個 \n)
  • 刪除已存在的檢查碼註解
  • 計算一個 base64 編碼的 MD5 檢查碼文字,若結尾有 = 字元則將其移除

以 Perl 程式碼實作如下 (假設檔案編碼為 UTF-8)

use Digest::MD5 qw(md5_base64);

my $data = readFile($file);

# 正規化資料
$data =~ s/\r//g;
$data =~ s/\n+/\n/g;

# 移除已存在的檢查碼
$data =~ s/^\s*!\s*checksum[\s\-:]+[\w\+\/=]+.*\n//mi;

# 計算新的檢查碼
my $checksum = md5_base64($data);

實作可參考 驗證檢查碼 以及 新增檢查碼至檔案

以 PHP 程式碼計算檢查碼 (再次假設檔案編碼為 UTF-8)

$data = file_get_contents($file);

# 初始化資料
$data = preg_replace('/\r/', '', $data);
$data = preg_replace('/\n+/', "\n", $data);

# 移除已存在的檢查碼
$data = preg_replace('/^\s*!\s*checksum[\s\-:]+([\w\+\/=]+).*\n/mi', '', $data);

# 計算新的檢查碼
$checksum = base64_encode(pack('H*', md5($data)));
$checksum = preg_replace('/=+$/', '', $checksum);
Powered by Anwiki關於 Adblock Plus隱私權政策Impressum