重要要素
1)DLL 入口函式
Extension Manager 外掛程式程式必須被編譯為可執行的程式庫(例如,Windows 系統的動態程式庫 dll 或者是 UNIX 系統的 shared object)。程式庫的結構和命名規則是跟平台相關的,詳細信息請參考 Lotus C API 用戶手冊第十二章第二節:"Platform-Specific Naming Conventions" 。在 DLL 入口函式中,應當完成外掛程式程式實例的創建和釋放,並且負責在外掛程式程式退出之前,註銷向 Notes/Domino 系統註冊的 EM_XX 事件。
2)外掛程式程式入口函式
該函式是定製外掛程式程式的入口函式,EM事件的註冊過程將會在此函式中加以實現。該函式聲明格式如下所示
STATUS LNPUBLIC MainEntryPoint (void);
該入口函式的名字可任意給定,但是必須在模組定義檔案(.def檔案)中將其聲明為導出函式(EXPORTS function),並且導出序號為1。
例子:
LIBRARY nextmngr INITINSTANCE EXPORTS MainEntryPoint@1
在註冊回掉函式之前,推薦使用 EMCreateRecursionID() 函式,這樣可以防止一個外掛程式程式被多次調用。
外掛程式程式回調函式:該函式是 Extension Manager 外掛程式程式的業務處理函式,負責在收到註冊事件通知後進行定製處理。
運行條件
要想運行一個定製的 Extension Manager 程式,需要做兩件事情:
將編譯成功的 DLL檔案放在 Notes/Domino 的主目錄下
修改 notes.ini 檔案,增加一個變數如下所示
EXTMGR_ADDINS=NEXTMNGR
如果有多個外掛程式程式,在外掛程式程式名之間用逗號格開。如果多個外掛程式程式註冊了同一個事件,則按照 notes.ini 檔案中的外掛程式程式的註冊順序來依次進行處理。
在了解了以上基礎知識之後,我們將以 Windows 平台為例,給出一個簡單而典型的 Extension Manager程式結構,本示例程式只是用來說明 Extension Manager 的程式架構和處理邏輯,不能編譯運行,具體的 Extension Manager 示例程式,請參考隨 Lotus C API 一起發布的 Sample。
結構示例
/* Extension Manager程式結構示例*/
/*system header file*/
#include <stdlib.h> ……
/*Notes Domino Header File*/
#include <global.h> ……
/*========================== GLOBAL VARIABLES ==============================*
HEMREGISTRATION hHandler; //外掛程式程式上下文句柄
EMHANDLER gHandlerProc; //外掛程式程式回調函式句柄
WORD gRecursionID; //防止該程式被多次調用
CRITICAL_SECTION gCriticalSection; // 用於多執行緒同步
/*================== LOCAL FUNCTION PROTOTYES ===============================*/
STATUS LNPUBLIC MainEntryPoint( void ); //外掛程式程式入口函式
STATUS LNPUBLIC EMHandlerProc( EMRECORD FAR * pExRecord); // 外掛程式程式回調函式 BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD fdwReason, LPVOID lpReserved ); // DLL入口函式
/*===========================================================================*/
STATUS LNPUBLIC MainEntryPoint( void )
{ STATUS error= NOERROR;
error = EMCreateRecursionID( &gRecursionID );
error = EMRegister(EM_GETPASSWORD, EM_REG_BEFORE | EM_REG_AFTER,(EMHANDLER)gHandlerProc, gRecursionID, &hHandler);
return( error ); }
/*==========================================================================*/
STATUS LNPUBLIC EMHandlerProc( EMRECORD FAR * pExRecord )
{ STATUS error = 0; switch(pExRecord->EId)
{ case EM_GETPASSWORD: { return(ERR_BSAFE_USER_ABORT ); }
return error; }
/*============================================================================*/
BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD fdwReason, LPVOID lpReserved )
{ STATUS error=NOERROR; switch(fdwReason)
{ case DLL_PROCESS_ATTACH: InitializeCriticalSection(&gCriticalSection);
gHandlerProc = (EMHANDLER)MakeProcInstance((FARPROC)EMHandlerProc, hInstance);
break;
case DLL_PROCESS_DETACH:
error = EMDeregister(hHandler);
FreeProcInstance( gHandlerProc );
DeleteCriticalSection(&gCriticalSection);
break; }
return( TRUE );
UNREFERENCED_PARAMETER(lpReserved); }
工程實例
接下來,將介紹 Extension Manager 的一個工程實例,並希冀由這個工程實例對 Lotus C API 應用程式開發者在使用 Extension Manager 實現定製應用程式時給予一定的啟發和指導。
1)工程背景
某客戶為了加強內部辦公環境的管理,需要強制用戶加入 Windows 特定域。客戶希望採取綁定郵件系統訪問的方式:即限制用戶只有登錄 Windows 域後才可以訪問郵件系統。
2)工程設計
為實現客戶需求,我們可以構想在客戶端部署一個 EM 程式。該客戶端 EM 程式註冊 EM_GETPASSWORD 事件,在Notes彈出密碼輸入對話框之前判斷當前 Windows 用戶是否在域中,如果不在域中就返回 ERR_BSAFE_USER_ABORT,這樣可以阻止 Notes 客戶端連線 Domino Server。程式片斷請參考 Extension Manager 程式結構示例。
一切進行的很順利,似乎工作到此已經萬事大吉了。然而且慢,如果仔細考慮一下,這種方案是不可取的,如果客戶端不安裝這個EM程式怎么辦?或者如果用戶卸載這個 EM 程式的話怎么辦?這樣的話客戶端完全可以繞開認證過程。
所以我們必須考慮在伺服器端進行統一的控制,這就需要在伺服器端也部署一個 EM 程式。該伺服器 EM 程式註冊 EM_SECAUTHENTICATION 事件,對每位向郵件伺服器傳送訪問請求的用戶進行實時授權鑑別,只有在客戶端登錄 Windows 域的情況下,伺服器端 EM 進程才開啟該用戶訪問郵件伺服器的限制。
現在的問題是伺服器端 EM 程式如何鑑別來訪客戶端是否在 Windows 域中?答案是 Socket 通信方法:客戶端 EM 程式在經過相關判斷之後,把 Notes 用戶的信息寫入到安裝 Domino Server 的伺服器的某個檔案(如Info.DAT)中,伺服器端 EM 程式在認證來訪 Notes 用戶的時候查詢該檔案,如果發現來訪 Notes 用戶信息在 Info.DAT 檔案中存在,則授權該用戶訪問郵件伺服器,否則則拒絕其訪問。
3)模組設計與實現
系統分為三個組件,分別是:Notes 、客戶端和EM 組件。
Notes 客戶端 EM 組件
功能說明:負責判斷當前 Notes 用戶的 Windows 域信息,並把相關信息傳送給通信伺服器,在接收到通信伺服器的確認信息之後,更新登入時間窗信息。(時間窗是一個時間段,某 Notes 客戶端在域中登入 Domino Server 之後,允許在時間窗內該 Notes 客戶端不登入域也能訪問郵件伺服器)
算法如下:
I. 捕獲 EM_GETPASSWORD 訊息
II. 讀取註冊表的內容,取得當前時間跟註冊表中上一次登記的時間做比較,判斷時間窗是否過期。
III. 如果時間窗未過期,即該 Notes 客戶端已經在指定時間段內向 Server 註冊過了,則直接返回 ERR_EM_CONTINUE. 把控制權交給 Notes,允許其連線郵件伺服器。
IV. 如果時間窗過期,判斷當前 Windows 用戶否在域中,如果在域中,從註冊表中讀取通信伺服器的 IP 和連線埠,把 Notes User 的信息傳送過去,然後等待 Server 的回響。如果收到 Server 的回響,那么更新註冊表中日期表項
V. 如果當前 Windows 用戶不在域中,說明在時間窗之內沒有人在域中登入過 Domino Server,返回 ERR_BSAFE_USER_ABORT 阻止 Notes 連線郵件伺服器。
Domino 伺服器端 EM 組件
功能說明:捕獲當前試圖連線自己的 Notes 用戶,讀取用戶信息檔案,判斷該當前用戶是否為合法用戶,從而決定是否授權該用戶訪問郵件伺服器。
算法如下:
I. 註冊 EM_SECAUTHENTION 事件
II. 在事件發生時獲取當前申請連線的用戶名字
III. 查詢用戶信息檔案,若有跟當前用戶匹配的信息,說明該用戶是合法用戶,返回 ERR_EM_CONTINUE 將控制權交給 Domino Server。否則,返回 ERR_SECURE_FAILED_AUTH,拒絕該用戶的連線請求。
通信伺服器程式
功能說明:負責讀取所有客戶端傳送給自己的用戶名信息,保存在用戶信息檔案中。以備 Domino Server 側的 EM 程式訪問。
該通信伺服器是一個多執行緒並發程式,具備了四個模組,分別是:
a) 處理伺服器模組
功能說明:負責整個通信伺服器程式的啟動和中止,並記錄整個系統的 Log 信息
b) 訊息件模組
功能說明:該模組由處理伺服器模組啟動,在啟動的時候啟動了三個執行緒,分別是:
接收訊息執行緒:該執行緒啟動通信模組,並等待通信模組的訊息,如果通信模組通知該執行緒有訊息到達,那么去獲得該訊息並寫入接收訊息佇列裡面
處理訊息執行緒:該執行緒實時監測接收訊息佇列裡面是否有數據,如果有數據,那么取出該數據,並寫入用戶信息檔案裡面,寫入成功後,傳送一個 UDP 訊息到傳送訊息佇列裡面,UDP 訊息包括某個客戶端的 IP,連線埠以及確認訊息。其定義為: struct UDPDATA{ unsigned longulIPAddr; unsigned short wPort; stringsData; };
傳送訊息執行緒:該執行緒實時監測傳送訊息佇列裡面是否有數據,如果有數據那么取出來進行分析,獲得 IP 和連線埠,然後通過通信模組把數據傳送出去。
c) 通信模組
功能說明:該模組封裝了 Socket 通信的 API,完成網路通信功能。
d) 訊息佇列模組
功能說明:該模組實現了 Message Queue 的功能,是一個雙向鍊表。目的是為了數據的快取,防止用戶數據丟失的可能性。系統有兩個訊息佇列,一個是接收訊息佇列,負責保存接收的訊息;另外一個是傳送訊息佇列,負責保存傳送的訊息。
區別
Adobe Bridge CS4是一款功能強大、易於使用的媒體管理器, 它可以讓您輕鬆地管理、瀏覽、定位和查看創作資源。Adobe Creative Suite® 4 軟體的所有六個版本以及大多數 Adobe 的專業創作應用程式中都包含 Bridge, 它提供了對項目檔案和全局設定的集中訪問以及 XMP 元數據的標記和搜尋能力。我個人認為:簡單的來講他就是個圖片查看器。
Adobe Device Central CS4 軟體為手機和消費電子設備簡化了創新、引人注目的內容的製作。通過測試自動化以及跨動態更新的設備配置檔案庫模擬移動內容的網路性能來節省時間。創建移動項目, 從一個中心位置管理資源、瞄準設備配置檔案並導出選項。在播放內容時記錄它, 並傳送高品質的影片剪輯, 更輕鬆地向客戶傳達構思。與 Adobe Creative Suite® 4 組件智慧型集成, Adobe Device Central CS4 可以幫助創意專業人士和移動開發人員向無數移動訂戶交付引人入勝的體驗。
Adobe Extension Manager CS4使您能夠輕鬆地安裝、管理和刪除功能擴展。