我的第一個翻譯作品 - Acrobat core API中的兩章

第2章 理解插件
這一章提供一個總覽,插件如何被載入,被初始化,被卸載,以及其它與插件和PDF庫應用相關的概念。推薦你在開始開發插件或PDF庫應用之前閱讀本章節。

第1節 關於插件初始化
這部分描述Acrobat或Adobe Reader執行初始化插件的操作順序。

插件載入和初始化:
當Acrobat或Adobe Reader啓動時,自動檢索/Program Files/Adobe/Acrobat/plug_ins目錄,定位和載入插件。另外,Acrobat或Adobe Reader也檢索包含在這個目錄裏的子目錄。這個檢索工作只有一級深度。
Acrobat或Adobe Reader在啓動時在啓動界面最底部一行顯示一個進度消息。當每個插件被載入時,進度消息顯示插件的名字。Acrobat或Adobe Reader啓動時如果SHIFT鍵被按住,沒有插件被載入。同時,如果Acrobat或Adobe Reader運行在被認證模式時,也沒有第三方插件被載入。
當創建一個插件時,在思想裏遵守如下規則:
1. 不要在你的插件初始化時創建對話框,或做其它可能妨礙Acrobat或Adobe Reader成功啓動的工作。應用通過IAC(interapplication communication)被啓動,它不會對響應你的對話框有所表現。
2. 執行一個PluginUnload程序,釋放分配的內存。這個程序通過在初始化程序中返回false被調用。在正常條件下,這個程序不會被調用,直到用戶關閉Acrobat或Adobe Reader。

握手和初始化:
Acrobat或Adobe Reader執行握手動作,在每一個插件被打開和載入時。在握手期間,插件說明自己的名字,幾個初始化程序,和一個可選擇的卸載程序。
一個插件必須執行下面的握手函數:

ACCB1 ASBool ACCB2 PIHandshake(ASUns32 handshakeVersion, void, *hsData)

在握手期間,插件接收一個hsData數據結構 (在PIVersn.h文件中定義)。Acrobat或Adobe Reader用ASCallbackCreateProto方法,把所有的被傳遞到這個數據結構裏的函數指針轉換到回調函數裏。關於這個方法的信息,參考文檔《Acrobat and PDF Library API Reference》。
頭文件DUCallbacks.h聲明瞭所有的回調方法,這些方法必須在你的插件中被定位。下面顯示這些回調方法的函數聲明:
ACCB1 ASBool ACCB2 PluginExportHFTs(void);
ACCB1 ASBool ACCB2 PluginImportReplaceAndRegister(void);
ACCB1 ASBool ACCB2 PluginInit(void);
ACCB1 ASBool ACCB2 PluginUnload(void);
所有的回調函數返回true,如果你的插件的聲明成功地完成,或者回調函數是可選的並且沒有被執行。如果你的插件聲明失敗,返回false。不管是Acrobat, Adobe Reader,還是一個插件中止握手,Acrobat或Adobe Reader都提示一個警告對話框,在載入其它插件之前顯示一個解釋摘要。在最少的情況下,一個插件必須執行PluginInit回調。
注意:握手函數位於PIMain.c文件中。這個文件中的源代碼是官能性的並且絕對不能被修改。

導出HFTs:
HFT(Host Function Table主功能表)是一個機制,藉此插件可以調用Acrobat或Adobe Reader中的方法,其它插件也一樣。Acrobat完成與所有插件的握手後,它調用每個插件的PluginExportHFTs回調函數。
在PluginExportHFTs函數中,一個插件可以導出一些HFTs,打算提供給其它插件使用。這個回調函數應該只導出HFT,不要調用其它Acrobat核心API方法。相關信息請參考第164頁的“Working with Host Function Tables”。
注意:這是一個插件能導出HFT的唯一機會。

導入HFTs和爲notifications註冊:
Acrobat或Adobe Reader完整地調用每一個插件的PluginExportHFTs回調方法後,再調用每個插件的PluginImportReplaceAndRegister回調方法。在這個方法中,插件執行三個任務:
1.導入他們使用的一些制定的HFTs(標準的Acrobat HFTs自動導入)。插件也可以在此之後,在插件運行時的任意時刻導入HFTs。
2.通過調用AVAppRegisterNotification方法,爲notifications註冊。插件也可以在運行時註冊或取消註冊。插件可以在任何時候接收到一個notification,在它已完成註冊以後,甚至插件的初始化回調函數還沒有被調用時。這是可能發生的,如果另一個插件首先初始化並執行了一個操作,比如創建一個PDF文檔,這會引起一個notification被髮送。插件必須準備好正確地抓住notifications,只要爲它們註冊了。
3.重置任意的Acrobat API的可重置HFT方法。相關信息請參考第174頁的“Replacing HFT methods”。
注意:這是一個插件可以導入HFT或重置標準API方法的唯一機會。插件可以在此時爲notifications註冊,或以後的任何時候。

初始化:
Acrobat或Adobe Reader完整地調用每個插件的PluginImportReplaceAndRegister回調方法之後,繼續調用每個插件的PluginInit程序。插件可以使用他們的初始化程序用來鉤住Acrobat的用戶接口,增加菜單條目,工具條按鈕,窗口,等等。也可以在插件運行時修改Acrobat的用戶接口。
如果你的插件需要在所有的插件被初始化後規劃一個任務,它應該爲AVAppDidInitialize通知註冊。這個通知會被調用,當Acrobat已經完成初始化並且將要進入它的事件循環時。

卸載:
插件的PluginUnload程序應該釋放插件分配的所有內存,並移除所有它做的用戶接口改動。Acrobat調用這個程序,當它終止運行或其它任何握手回調返回false時。這個功能應該執行下列任務:
(1)移除並釋放所有的菜單條目和其它用戶接口元素,HFTs,以及HFTServers。
(2)釋放所有內存或所有其他分配的資源。
通常,插件只有在Acrobat退出時卸載。

一個插件的生命週期摘要:
下列步驟描述了一個插件的生命週期:
1. 啓動時,Adobe Reader或Acrobat搜索它的插件目錄,查找插件文件。
2. 對於每個插件文件,Adobe Reader或Acrobat都嘗試載入這個文件。如果插件被成功載入,Adobe Reader或Acrobat調用PIMain.c中的函數,完成握手過程。
3. Adobe Reader或Acrobat按如下順序調用回調函數:
 ●PluginExportHFTs
 ●PluginImportReplaceAndRegister
 ●PluginInit
這個順序建立了關聯,在插件和Adobe Reader或Acrobat之間,也在插件和任何其它插件之間。一旦所有的插件被載入,Adobe Reader或Acrobat繼續它的自載入過程和啓動用戶接口。它把任何插件提供的工具添加到工具條和菜單條目上,然後啓動用戶對話。

第2節 使用回調函數
Acrobat或Adobe Reader調用你定義的用來完成指定任務的回調函數。例如,當用戶點擊一個
位於工具條上的按鈕時,一個回調函數就被調用了。相關信息請參考第105頁的“Creating toolbar button callback functions”。
要創建一個回調函數,你可以調用ASCallbackCreateProto, ASCallbackCreateReplacement, 和ASCallbackCreateNotification方法,把函數轉換成回調函數並執行類型檢查。這樣允許編譯器決定是否爲一個指定的回調函數使用了正確的原型。關於這些方法的信息,參考文檔《Acrobat and PDF Library API Reference》。
類型檢查只在這時發生 --- 如果宏定義DEBUG被設置爲1,當你的插件被編譯時。確定它在你的開發環境中被適當地設置,並且在你建立插件的註冊版本時移除它。
下述代碼例子說明了創建一個回調函數的句法:
 AVExecuteProc ExecProcPtr = NULL;
 ExecProcPtr= ASCallbackCreateProto(AVExecuteProc, &ShowMessage);
宏定義ASCallbackCreateProto返回一個指定類型的回調函數,用來調用用戶自定義的函數,函數的地址作爲第二個參數被傳遞。在這個例子中,函數ShowMessage被轉換爲一個回調函數,ShowMessage是一個指定動作發生時被調用的用戶自定義函數。
宏定義ASCallbackCreateProto返回一個指向函數的指針,此函數能被插件調用或被Acrobat,Adobe Reader調用。如果不再需要,使用ASCallbackDestroy方法除掉回調函數。
所有的回調函數必須用Pascal調用慣例聲明。爲了使你的代碼在平臺間通用,使用ACCB1 和 ACCB2 宏定義聲明你的所有的回調函數:
 static ACCB1 const char* ACCB2 ShowMessage(Thing*?foo);

第3節 Notifications
Acrobat core API 提供一個通知機制,以便插件能夠與Acrobat或Adobe Reader同步動作。Notifications使插件能夠指出自己對一個特定的時間感興趣(比如一個註釋被更改了),並且在每次事件發生的時候,提供一個程序給Acrobat調用。相關信息請參考第151頁“Registering for Event Notifications”。

第4節 Handling events
你可以使用Acrobat core API操作不同類型的事件。
(1)鼠標點擊:
(2)調整光標:
(3)鍵按下:

第5節 使用插件前綴

第6節 修改Acrobat或Adobe Reader用戶接口

第7節 獲取和註冊對象

第8節 調試插件

第9節 頁瀏覽層

第10節 最小化的屏幕重畫

第11節 在PDF文件中存儲私人數據

第12節 從PDF文檔對象中導出數據

 

太累了,略。

 

 

先介紹一下Acrobat的定義:

The Acrobat menu bar --- 菜單條,Windows中的主菜單條。

An Acrobat menu --- 菜單,主菜單條的下一級,就是命令的列表,每個菜單還可以包含子菜單。

A menu command --- 菜單命令,菜單的末級,點擊後執行相應命令。

 

第6章 創建菜單和菜單命令
第2節 給菜單增加菜單命令

你可以使用Acrobat core API給一個已存在的菜單增加一個新的菜單命令。例如,你可以添加一個在Acrobat SDK中已命名的菜單命令給Adobe Reader或Acrobat菜單條中的高級菜單條目。爲了給一個已存在的菜單增加一個新菜單命令,請參照下面的方法:
1. 找到Adobe Reader或Acrobat菜單條(被AVmenubar對象描述),通過調用AVAppGetMenubar方法:

 AVMenubar Themenubar = AVAppGetMenubar();

2. 找到將要包含新菜單命令的菜單,通過調用AVMenubarAcquireMenuByName方法,並傳遞下列參數:
(1)AVmenubar對象 --- 描述菜單條.
(2)menu的名字. 例如, 對於‘File’菜單, 指定‘File’。
本方法返回一個與被指定的菜單名相應的AVMenu對象。

AVMenu FileMenu = AVmenubarAcquireMenuByName (Themenubar, "File");

如果菜單不存在,你可以寫程序創建它(見下一步)。

3. 如果有必要,調用AVMenuNew方法,寫程序創建一個新菜單,調用時傳遞下列參數:
(1)一個字符串 --- 用來描述在Adobe Reader或Acrobat中被顯示的文本。
(2)將要創建的一個唯一的菜單名字(語言獨立)。相關信息請參考第31頁的“使用插件前綴”;
(3)ASExtension --- 用於註冊菜單。與ASExtension相關的信息,請參考文檔Acrobat and PDF Library API Reference。

AVMenuNew方法返回一個AVMenu的入口。

 AVMenu NewMenu = AVMenuNew ("Acrobat SDK", "ADBE:Acrobat_SDK", gExtensionID);
 
創建一個新菜單之後,你必須把它綁定到菜單條。相關信息請參考92頁的“給一個新菜單增加菜單命令”。

4. 通過調用AVMenuItemNew方法創建一個新的菜單命令,並需要傳遞下列參數:
(1)一個描述命令文本的字符串。只有在Windows上,你纔可以通過在標題中包含一個&字符指定一個鍵盤快捷方式。在Acrobat或Adobe Reader中,通過&(char),在字符下面放置一個下劃線(_)。這樣可以允許用戶按alt+<char>去選擇條目。
(2)將要創建的菜單命令的名字(語言獨立)。相關信息請參考第31頁的“使用插件前綴”。
(3)一個AVMenu對象 --- 描述一個子菜單, 這個菜單命令是它的父親。如果這個菜單條目沒有子菜單,傳遞null。
(4)一個布爾值。如果爲true, 只有當用戶選擇了整個菜單後,菜單條目可見。如果爲false,菜單條目既在全菜單下可見,也在快捷菜單模式下可見(Adobe Reader或Acrobat3.0以後版本已忽略)。
(5)關鍵字符 --- 用於菜單命令的快捷方式(一個ASCII字符)。如果沒有快捷方式,使用NO_SHORTCUT。
(6)修正的關鍵字符 --- 如果可能,被用於快捷方式的一部分。必須是一個修正值的OR值,除了AV_COMMAND不能指定的以外。
(7)一個AVIcon對象 --- 用於描述在菜單命令中顯示的圖標,如果沒有圖標顯示,指定爲null。在Windows中,一個有效的圖標是一個24x24像素的單色位圖HBITMAP。在Mac OS中,圖標是一個標準SICN資源的句柄。創建AVIcon對象的相關信息,請參考第100頁的“創建工具條按鈕”。
(8)ASExtension --- 用於註冊這個菜單命令。與ASExtension相關的信息,請參考文檔Acrobat and PDF Library API Reference。

AVMenuItemNew方法返回一個AVMenuItem對象:
 AVMenuItem menuItem = AVMenuItemNew ("Show Message", "ADBE:ExternWin", NULL, true, NO_SHORTCUT, 0, NULL, gExtensionID);

5. 通過調用AVMenuAddMenuItem方法,綁定菜單命令到一個菜單,並傳遞下列參數:
(1)被菜單命令綁定的AVMenu對象。
(2)被綁定的AVMenuItem對象。
(3)菜單中的位置 --- 指定命令增加在哪裏。你可以指定APPEND_MENUITEM,表示把菜單命令增加在菜單的末尾。
如果方法調用成功,菜單命令被增加到指定的菜單上:

AVMenuAddMenuItem (FileMenu, menuItem, APPEND_MENUITEM);

6. 發佈類型定義入口到剩餘內存中。要發佈AVMenu入口,需要調用AVMenuRelease方法並傳遞AVMenu入口參數。要發佈AVMenuItem入口,需要調用AVMenuItemRelease方法並傳遞AVMenuItemRelease入口參數。

增加一個菜單命令到一個已存在的菜單:
下面的代碼示例創建一個新的menu command,用於顯示文本Show Message, 並綁定到File菜單。

Example 6.1 Adding a menu command to an existing menu
 //Declare menu variables
 AVMenubar Themenubar = NULL;
 AVMenu FileMenu = NULL;
 AVMenuItem NewMenuCommand = NULL;
 //Retrieve the menu bar in Adobe Reader or Acrobat
 Themenubar = AVAppGetMenubar();
 //Retrieve the File menu
 FileMenu = AVMenubarAcquireMenuByName(Themenubar, "File");
 //Create a new menu command
 NewMenuCommand = AVMenuItemNew("Show Message", "ADBE:ExternWin", NULL, true, NO_SHORTCUT, 0, NULL, gExtensionID);
 if (NewMenuCommand == NULL)
 {
 AVAlertNote ("Unable to create the menu command");
 AVMenuItemRelease(NewMenuCommand);
 return;
 }
 //Attach the new menu command to the File menu
 AVMenuAddMenuItem (FileMenu, NewMenuCommand, APPEND_MENUITEM);
 //Release the typedef instances
 AVMenuItemRelease(NewMenuCommand);
 AVMenuRelease(FileMenu);

注意:這個代碼示例創建一個新的菜單命令,它在‘File’菜單中顯示 Show Message。 無論如何,在菜單命令執行一個動作之前,你必須創建一個回調菜單函數。相關信息請參考第93頁的“Creating menu callback functions”。

增加一個menu command到一個新菜單:
下面的代碼示例創建一個新的menu command,用於顯示文本Show Message, 並綁定到一個新菜單。通過調用AVmenubarAddMenu方法,這個新菜單被綁定到菜單條。

Example 6.2 Adding a menu command to a new menu
 //Declare menu variables
 AVMenubar Themenubar = NULL;
 AVMenu NewMenu = NULL;
 AVMenuItem NewMenuCommand = NULL;
 //Retrieve the menu bar in Adobe Reader or Acrobat
 Themenubar = AVAppGetMenubar();
 //Create a new menu
 NewMenu = AVMenuNew("New Menu", "ADBE:NewMenu", gExtensionID);
 if (NewMenu == NULL)
 {
 AVAlertNote ("Unable to create the menu");
 AVMenuRelease (NewMenu);
 return ;
 }
 //Create a new menu command
 NewMenuCommand = AVMenuItemNew("Show Message", "ADBE:ExternWin", NULL, true, NO_SHORTCUT, 0, NULL, gExtensionID);
 if (NewMenuCommand == NULL)
 {
 AVAlertNote ("Unable to create the menu command");
 AVMenuItemRelease(NewMenuCommand);
 return;
 }
 //Attach the menu item to the menu and the menu to
 //the menu bar
 AVMenuAddMenuItem (NewMenu, NewMenuCommand, 0);
 AVMenubarAddMenu (Themenubar, NewMenu, APPEND_MENU);
 //Release the typedef instances
 AVMenuItemRelease(NewMenuCommand);
 AVMenuRelease(NewMenu);

 

注意: 如果你打算給一個菜單命令增加一個子菜單,你必須在創建菜單命令之前創建子菜單。

 

 

第3節 創建菜單回調函數

 

當創建菜單時,你必須創建被Acrobat或Adobe Reader調用菜單回調函數。三種類型的回調函數可以被創建:

Execute:被Acrobat或Adobe Reader調用,用於響應用戶選擇了菜單命令。這種回調是必須的。
Compute-enabled:這種可選的回調類型被Acrobat或Adobe Reader調用,當決定是否使菜單命令能夠響應的時候。
Compute-marked:這種可選的回調類型被Acrobat或Adobe Reader調用,當決定菜單命令是否應該被檢查的時候。

爲了達到討論的目的,介紹一個簡單的用戶自定義的函數 --- ShowMessage。這個方法通過調用AVAlertNote方法顯示一個消息框。下面的代碼示例顯示了ShowMessage的函數體:

 ACCB1 void ACCB2 ShowMessage (void* data)
 {
  AVAlertNote ("A menu command was selected.");
 }

參數data(對這個或其它回調函數)可以被用於維持菜單命令的私有數據。注意這個用戶自定義函數是使用宏定義ACCB1和ACCB2聲明的。相關信息,請參考第30頁的“Using callback functions”。

對於你創建的每個回調函數,你需要聲明指針指向被Acrobat core API定義的回調函數:
 AVExecuteProc ExecProcPtr = NULL;
 AVComputeEnabledProc CompEnabledProcPtr = NULL;
 AVComputeMarkedProc CompMarkedProcPtr = NULL;

AVExecuteProc是一個你可以創建的回調函數,當用戶選擇了一個菜單條目後被Acrobat或Adobe Reader調用。AVComputeEnabledProc也是一個你可以創建的回調函數,當決定是否使菜單命令處於使能狀態時,由Acrobat或Adobe Reader調用。AVComputeMarkedProc也是一個你可以創建的回調函數,當決定菜單命令是否應該被檢查時,由Acrobat或Adobe Reader調用。

創建一個指針後,比如一個指向AVExecuteProc的指針,你可以調用宏定義ASCallbackCreateProto(在Acrobat core API中定義)把一個用戶自定義的函數轉換爲一個Acrobat回調函數。例如,你可以調用ASCallbackCreateProto把ShowMessage轉換成一個回調函數。宏定義ASCallbackCreateProto需要下面兩個參數:
(1)回調類型。例如,你可以傳遞AVExecuteProc。
(2)用戶自定義函數的地址。
ASCallbackCreateProto返回指定類型的回調函數。例如下面的代碼:

 AVExecuteProc ExecProcPtr = NULL;
 ExecProcPtr = ASCallbackCreateProto(AVExecuteProc, &ShowMessage);

創建AVExecuteProc回調函數後,調用AVMenuItemSetExecuteProc方法建立菜單命令和回調函數之間的聯繫。這是因爲,當用戶選擇一個指定的菜單時,Acrobat或Adobe Reader會調用用戶自定義函數,其地址就是被傳遞給宏定義ASCallbackCreateProto的地址(老外的廢話怎麼這麼多!!!)。AVMenuItemSetExecuteProc方法需要如下參數:

●An AVMenuItem instance --- 描述菜單命令。
●An AVExecuteProc --- 描述回調函數。
●The address of a user-defined data structure  --- 可以被傳遞給用戶自定義函數的數據結構地址。

當你調用完菜單回調函數後,你可以調用ASCallbackDestroy方法釋放消耗的內存。下面的代碼示例給菜單命令創建了回調函數。

Example 6.3 Creating menu callback functions
 /* Display a message box */
 ACCB1 void ACCB2 ShowMessage (void* data)
 {
 AVAlertNote ("A menu command was selected.");
 }
 ACCB1 ASBool ACCB2 ComputeMarkedProc (void* data)
 {
 ASBool expressionorcondition = true;
 if (expressionorcondition)
 return true;
 else return false;
 }
 ACCB1 ASBool ACCB2 ComputeEnabledProc (void* data)
 {
 if (AVAppGetNumDocs() > 0)
 return true;
 else return false;
 }
 ACCB1 ASBool ACCB2 PluginInit (void)
 {
 //Declare menu callbacks
 AVExecuteProc ExecProcPtr = NULL;
 AVComputeEnabledProc CompEnabledProcPtr = NULL;
 AVComputeMarkedProc CompMarkedProcPtr = NULL;
 //Declare menu variables
 AVMenu FileMenu = NULL;
 AVMenuItem NewItem = NULL;
 //Retrieve the menu bar in Adobe Reader or Acrobat
 AVMenubar Themenubar = AVAppGetMenubar ();
 //Create menu callbacks
 ExecProcPtr = ASCallbackCreateProto (AVExecuteProc, &ShowMessage);
 CompEnabledProcPtr = ASCallbackCreateProto (AVComputeEnabledProc,
 &ComputeEnabledProc);
 CompMarkedProcPtr = ASCallbackCreateProto (AVComputeMarkedProc,
 &ComputeMarkedProc);
 //Retrieve the File menu
 FileMenu = AVmenubarAcquireMenuByName (Themenubar, "File");
 if (FileMenu)
 {
 //Create a new menu item
 NewItem = AVMenuItemNew ("Show Message", "ADBE:ExternWin", NULL, true, NO_SHORTCUT, 0, NULL, gExtensionID);
 if (NewItem == NULL)
 {
 AVAlertNote ("Unable to create a menu item, not loading.");
 return false;
 }
 AVMenuItemSetExecuteProc (NewItem, ExecProcPtr, NULL);
 AVMenuItemSetComputeEnabledProc (NewItem,
 CompEnabledProcPtr,NULL);
 AVMenuItemSetComputeMarkedProc (NewItem,
 CompMarkedProcPtr,NULL);
 AVMenuAddMenuItem (FileMenu, NewItem, 1);
 AVMenuRelease (FileMenu);
 return true;
 }
 else return false;
 }
 ACCB1 ASBool ACCB2 PluginUnload (void)
 {
 ASCallbackDestroy (ExecProcPtr);
 ASCallbackDestroy (CompEnabledProcPtr);
 ASCallbackDestroy (CompMarkedProcPtr);
 return true;
 }

提示:注意應用程序的邏輯,創建菜單命令是位於PluginInit函數之內的。相關信息請參考第27頁“關於插件初始化”。


第4節 決定菜單條目是否可以被執行

在Adobe Reader或Acrobat以前的版本中,一個文檔在應用程序視圖中執行一個菜單條目是可能的,通過使用一個被命名的動作或JavaScript方法app.execMenuItem。這兩個特點,提到就像ExecMenu暴露的,對文檔的所有的菜單條目,潛在地允許一個惡意文檔危及用戶的隱私或系統。例如,使用JavaScript方法app.execMenuItem從文檔得到數據是可能的,通過創建等同於用戶的菜單命令,如全部選擇、複製、粘貼等命令。
Acrobat和Adobe Reader 8.0 包含一個菜單列表,可以通過使用ExecMenu被執行。沒有在這個列表上的菜單條目不能被可編程地執行。
通過調用AVMenuItemIsScriptable方法和傳遞AVMenuItem,你可以決定菜單條目是否可以被可編程地執行。這個方法返回一個布爾值。這是因爲,如果與AVMenuItem參數相符的菜單條目可以被執行,返回true;否則,返回false。

《本章完》

第14章 文檔安全

第1節 關於文檔安全

在PDF文件中,加密由加密字典控制。Acrobat core API 使用RC4算法加密文檔資料,一個標準的私有方法加解密,通過校驗用戶密碼決定是否一個用戶被授權打開文檔。
PDF文件中的每個流對象或字符串對象是分別加密的。這個級別的加密提高了性能,因爲對象可以按需要被分別解密,勝過整個文件解密。所有的對象,除了加密字典(包含了安全句柄的私有資料),使用RC4算法加密,ADOBE已從RSA公司得到授權。插件不可以替代其它的RC4加密方案。
用實現了一個安全句柄的插件來加密位於加密字典中的values是可靠的,並且它可使用任何加密方案。如果安全句柄沒有加密位於加密字典中的values,values以明文表示。
core API提供兩個Cos層的方法用於加解密使用RC4算法的數據。這些方法是CosEncryptData 和 CosDecryptData。關於這些方法的信息,請參考Acrobat and PDF Library API Reference。
安全句柄可以使用這些方法加密數據,當他們想要放入PDF文件的加密字典,以及從字典中讀取並解密的時候。
安全句柄可以更換選擇以忽略這些方法,而使用他們自己的加密算法。
注意:另外,Acrobat提供其它方法保護一個PDF文檔,比如公鑰安全與策略,由Adobe LiveCycle Policy Server創建。相關信息,請參考Acrobat and PDF Library API Reference。

第2節 關於安全句柄
表現用戶認證和設置權限的應用邏輯被稱作安全句柄。Acrobat有三個內置的安全句柄:password, APS (LiveCycle Policy Server) and public key security handler.相關信息,請參考Acrobat and PDF Library API Reference。
一個安全句柄支持兩個密碼:
用戶密碼 --- 允許用戶打開和閱讀一個受保護的文檔,無論所有者選擇了什麼權限。
所有者密碼 --- 允許文檔的所有者改變授予用戶的權限。
你可以使用Acrobat core API的內置安全句柄,或者寫出你自己的安全句柄實現用戶的授權過程(例如,利用已有的特定硬件密鑰或文件,或者利用從磁卡閱讀器中讀取的方法)。
安全句柄對實現下面的任務過程是可靠的:
(1)在一個文件上設置權限
(2)訪問文件授權
(3)設置文件的加密和解密密鑰
(4)維護包含在PDF文件中的加密字典
安全句柄在下列情況下使用:
(1)文檔被打開。安全句柄決定一個用戶是否已被授權允許打開文件設置用於解密PDF文件的解密密鑰。
(2)文檔被保存。安全句柄設置加密密鑰,並把額外的安全相關信息寫入到PDF文件的加密字典裏。
(3)用戶企圖改變文檔的安全設置。
一個文檔可以包含0個,1個或2個與之相關的安全句柄。如果文件沒有使用安全機制,文檔就有0個安全句柄。當安全性被應用到文件後,或者用戶爲一個受保護的文件選擇了其它不同的安全句柄,新選擇的安全句柄並沒有被立即使用。替代的方案是新的安全句柄被簡單地與文檔相關聯。在文檔被保存之前它只是一個未定的安全句柄。
新的安全句柄並沒有被立即使用是因爲它被可靠地用於解密文檔加密字典的內容,並且只有在文檔被保存的時候,這個字典以正確的格式用新的安全句柄重新加密。結果是,一個文檔可能具有一個當前安全句柄和一個新的安全句柄與之相關。
一個安全句柄有兩個名字:一個被放置在每個PDF文件中---這個文件是被句柄保存的,例如ADBE_Crypt,另一個名字Acrobat可以使用在任何出現安全句柄的用戶接口條目中,例如,Acrobat開發人員缺省的加密方法。這與菜單條目的使用的雙名方案類似:一個語言獨立的名字 --- 應用邏輯可以不管用戶接口的語言而提到它,另一個名字出現在用戶接口中。相關信息請參考第6章第2節“給菜單增加菜單命令”。

第1小節 添加安全句柄
你可以通過下面的步驟添加安全句柄:
 (1)寫一系列的回調函數,實現安全相關的功能。
 (2)在PDCryptHandlerRec結構裏指定回調函數。
 (3)註冊句柄,通過把結構傳遞給PDRegisterCryptHandlerEx。

安全句柄數據 --- 下面描述了三種安全句柄使用的數據類型:
 (1)授權數據 --- 是安全句柄需要爲特定文件決定用戶授權級別的數據,例如未被授權地打開文件,被授權以用戶的權限訪問文件,被授權以所有者的權限訪問文件。密碼是一種通用的授權數據類型。
 (2)安全數據 --- 是安全句柄使用的任何內部數據。它包括安全信息,內部標誌的值,種子值,等等。
 (3)安全信息 --- 是安全數據的子系列。很明確地,它是一個標誌的集合 --- 這個標誌包含Acrobat用來顯示當前給用戶的權限的信息。這個信息包括權限和用戶的授權級別(用戶或所有者)。

安全句柄回調函數 --- 安全句柄必須提供實現下列功能的回調函數:
 (1)決定用戶是否被授權打開特定的文件,和一旦文件被打開後用戶有什麼權限(PDCryptAuthorizeExProc)。
 (2)創建和填充授權數據結構,使用用戶接口必須包含的任何東西來獲取數據。例如,顯示一個對話框用於用戶輸入密碼(PDCryptGetAuthDataExProc)。
 (3)創建、填充和校驗一個安全數據結構(PDCryptNewSecurityDataProc)。
 (4)從安全數據結構展開安全信息(PDCryptGetSecurityInfoProc)。
 (5)允許用戶要求不同的安全設置,通常通過顯示對話框的方式(PDCryptDisplaySecurityDataProc)。
 (6)設置加密密鑰,用於加密文件(PDCryptNewCryptDataProc)。
 (7)填充或讀取PDF文件的加密字典(PDCryptFillEncryptDictProc)。
 (8)顯示當前文檔的權限(需要PDCryptAuthorizeExProc 和 PDCryptGetAuthDataExProc)。

在Acrobat 5.0及以後版本中,一個更好的權限粒度已經被預定義,爲了被PDF文檔支持的對象。插件可以調用PDDocPermRequest方法去要求一個特定的操作是否被授權,在一個文檔中的指定對象上執行。
爲了支持PDDocPermRequest方法,這裏有兩個新的回調方法:
PDCryptAuthorizeExProc 和 PDCryptGetAuthDataExProc。爲了批操作(在一個或更多的文件上),Acrobat 5.0及以後版本也包括可選的安全操作。一個安全句柄必須提供許多的回調函數(PDCryptBatch...)給批處理過程。這些回調函數是PDCryptBatchHandler結構的一部分。PDCryptHandlerRec結構包含一個新成員CryptBatchHandler,它指向這個結構。
爲了支持批處理過程,一個安全句柄應該提供一個非空的值給CryptBatchHandler,並且實現批迴調函數。Acrobat 5.0以前,加密密鑰的最大長度是40位。Acrobat 5.0及以後版本,提供128位的密鑰長度。這些長度限制被強制地用來適用於出口約束。

Acrobat的授權程序
Acrobat的內置授權程序按如下方式工作:
1.
Acrobat invokes the security handler’s authorize callback (which is either PDCryptAuthorizeExProc, introduced with Acrobat 5.0, or the older PDCryptAuthorizeProc) to determine whether the user is allowed to open the file. It passes NULL authorization data, to handle the case where no authorization data is needed. Acrobat also passes the following values:
●PDPermReqObjDoc and PDPermReqOprOpen when invoking PDCryptAuthorizeExProc.
●pdPermOpen when calling PDCryptAuthorizeProc.
2.
If the authorize callback returns true, the file is opened. Otherwise, the authorization procedure executes the following steps up to three times, to give the user three chances to enter a password, or whatever authorization the security handler uses.
●It calls the security handler’s get authorization data callback (PDCryptGetAuthDataExProc or the older PDCryptGetAuthDataProc). This callback should obtain the authorization data using whatever user interface (for example, a dialog box used to obtain a password) or other means necessary, and then creates and fills the authorization data structure.
●It calls the security handler’s authorize callback, passing the authorization data returned by the get authorization data callback. If the authorization succeeds, the authorize callback returns the permissions granted to the user, and the authorization procedure returns.

The authorize callback can access the encrypted PDF document, allowing it to encrypt the authorization data using a mechanism that depends on the document’s contents. By doing this, someone who knows a document’s password cannot easily find out which other documents use the same password. The authorize callback can return permissions that depend on the password as well as the permissions specified when encryption was set up. This allows, for example, more rights to be granted to someone who knows a document’s owner password than to someone who knows the document’s user password.


 
第2小節 打開一個受保護的文件

第3小節 保存一個受保護的文件


第3節 爲文檔設置安全

<完>

大約12000字。

 

費時兩個小時 + 四個小時 + 兩個小時,太累了。以後翻不翻另說了。

 

 

發佈了53 篇原創文章 · 獲贊 3 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章