基于异步插件协议的MIME过滤器的原理与实现

基于异步插件协议的MIME过滤器的原理与实现

一觉亮天

 

摘要:

本文介绍了一种在Windows平台下通过异步插件协议来实现内容过滤的方法,说明了其实现的原理,和其间用到的技术。此种方法具有实现和扩展方便,过滤效果稳定的优点。最后给出了一个简单的实现。

关键词:

异步插件协议;COM;连接点;ATL

中图分类号: TP393   文献标识码:A

 

MIME Filter Basedon Asynchronous Pluggable Protocols

YiJiaoLiangTian

 

Abstract:

In thearticle, a way to implement a content filter through Asynchronous PluggableProtocols on Windows operation system is introduced. Its principle andassociated technologies are concerned. It is easy to implement and extend thekind of content filter, and its effect is also stable. At last there is asimple implementation of a content filter.

Key Words:

AsynchronousPluggable Protocols; COM; Connection Point; ATL

 

1.引言

互联网带给我们海量信息的同时,也带来许多不良内容。随着网络安全问题日益严重,广大用户对网络安全产品也越来越关注。在PC机上使用的内容过滤防火墙作为一种网络安全工具,早已受到大家的青睐。Windows下的个人防火墙都是基于对数据报的拦截技术之上。当然在具体的实现方式上它们有很大的不同。如采用NDIS的核心层封包过滤和采用Winsock 2 SPI的应用层封包过滤。本文介绍一种安装比较方便,效果比较理想的基于微软异步插件协议(AsynchronousPluggable Protocols),采用COM技术实现的内容过滤方法。

2COM简介

21 COM规范

COM是微软推出的一种开放的组件技术规范和实现,它提供了一个集成组件的框架。这个框架支持具有互操作性和重用性的分布组件对象。开发者可以通过COM重用不同组件来架构系统。COM具有如下特点:(1)与开发工具和语言无关,是一种二进制标准;(2)通过接口有效保证了组件的复用性;(3)组件运行效率高、 便于使用和管理。在Windows操作系统中,广泛地应用到了COM技术,使得Windows操作系统是便于升级和维护的操作系统。许多扩展WINDOWS功能的接口也都是基于COM技术的,例如COPY HOOK Handler, Browser Helper Object等。

22 COM的事件模型

COM不仅定义了客户调用组件对象的通讯过程,它也定义了反向的通讯过程,这就是COM可连接对象(connectable object)机制。组件对象定义了出接口(outgoinginterface)的所有特征,客户程序实现出接口,当客户程序与对象建立连接之后,客户通过连接点对象建立它与客户端接收器对象之间的反向连接。实际上,这时的连接点对象成了接收器对象的客户方。COM连接点是能够处理事件回调功能的接口。它能够提供更灵活的功能,因为所有的参数和回调函数都使用COM子接口来执行。COM子接口允许各个函数在不同进程之间相互调用,这在普通回调函数中是不允许的。连接点指的是一种逻辑上的反馈机制,这种反馈机制允许对象暴露其调用一个或者多个指定接口的能力。连接点允许客户给予对象一个由客户实现的接口指针。对象使用客户提供的接口指针调用客户所提供的方法。连接点允许客户提供给对象只有对象知道如何调用的接口。一个连接有两个部分:对指定接口的方法产生调用的对象,被称作源或者连接点;以及实现该接口的对象,被称作接收器对象。特定的源对象可以与多个接收器对象连接。在典型的COM程序中,一个COM对象是带有特定接口的服务器,与之相连的客户端执行一定的事件。当触发连接点时,COM服务器就向客户端传递信息,这一信息包括:服务器端已经发生触发事件,哪一个客户端想接受。此时,匹配的客户端即接受相关的事件。所以当提及连接点时,服务器一端称为发送端,而客户端称为接受端。

23实现COMATL

ATL是专门用于开发COM组件的模板库,是一组小巧,灵活,高效的基于C++的模板类。利用ATL可以创建代码量小,运行速度快,可扩展性高的COM组件。ATLCOM的许多特性提供了支持,比如聚合,双接口,连接点,枚举器等。ATL提供了很多工具类,例如智能指针类,来简化开发COM的过程。

3插件MIME过滤器

Windows操作系统提供了对IE内核进行扩展的许多接口,异步插件协议是其中的接口之一,此接口是基于COM技术的。应用程序利用异步插件协议,可以实现插件MIME过滤器,来达到对网络访问内容进行过滤的目的。

31异步插件协议介绍

异步插件协议是微软对Windows操作系统进行扩充的一种接口。开发者可以利用异步插件协议创建插件协议处理器(PluggableProtocol Handler),MIME过滤器,名称空间处理器。可以利用异步插件协议定制URL协议方案或者过滤特定MIME类型的内容。插件MIME过滤器可以用来过滤特定MIME类型的数据。插件MIME过滤器不但能够读取数据,还能够提供数据。插件MIME过滤器通过实现IIntetnetProtocolSink接口来实现读取系统下载的数据。对这些数据进行处理后,插件MIME过滤器通过实现IInternetProtocol接口来允许系统得到处理过后的数据。插件MIME过滤器的内容过滤功能,可以应用在许多领域。例如帮助家长限制孩子浏览互联网的内容。操作系统访问网络过程中,任意符合的MIME类型,都将调用插件MIME过滤器,然后再把过滤后的数据传给用户。

32插件MIME过滤器的原理

插件MIME过滤器本质上是一种实现了IInternetProtocolIInternetProtocolSink接口的异步插件处理器,以流的形式得到数据,对数据进行一些操作,然后返回处理后的数据流。事务处理器通过插件MIME过滤器实现的IInternetProtocolSink来通知过滤器有可用数据等待过滤。插件MIME过滤器的原理就像打乒乓球。事务处理器本身也实现了IInternetProtocolIInternetProtocolSink接口,它和插件MIME过滤器实现的相同的接口相互调用,完成过滤的过程。下面是事务处理器和插件MIME过滤器交互的过程,它的原理如图1

(1)事务处理器调插件MIME过滤器的Start函数。

(2)事务处理器调用插件MIME过滤器ReportProgress函数,告诉插件MIME过滤器下载的缓存文件的名字和存放位置。

(3)当有可用数据的时候,事务处理器调用插件MIME过滤器ReportData函数。

(4)插件MIME过滤器调用事务处理器的Read函数得到内容。

(5)插件MIME过滤器过滤得到的内容,然后调用事务处理器的ReportData,通知事务处理器,数据已经准备好了。

(6)事务处理器调用插件MIME过滤器Read函数得到数据。

(7)循环往复。

 

 基于异步插件协议的MIME过滤器的原理与实现_第1张图片

 

33插件MIME过滤器的接口介绍

插件MIME过滤器需要实现两个COM接口,一个是IInternetProtocol接口,一个是IInternetProtocolSink接口。IInternetProtocol接口用来控制异步插件协议处理器的操作,是异步插件协议暴露的主要接口,它继承自IInternetProtocolRoot。这个接口与IInternetProtocolSink接口在下载过程中紧密结合。IInternetProtocolSink接口可以从异步插件协议处理器得到数据并传递给异步插件协议处理器。他是一个COM连接点的接收器。

34插件MIME过滤器的注册

插件MIME过滤器有两种注册方法,一种永久注册,一种临时注册。永久注册,对系统中所有采用了IE核心的网络应用程序都起作用。永久注册除了一般COM组件的注册过程外,要在Windows注册表HKEY_CLASSES_ROOT/PROTOCOLS/Filter下面以相应MIME类型为名字添加相应注册表项,把此COM组件注册到此位置。临时注册只对当前进程起作用。方法是首先得到IInternetSession的接口指针,然后调用此接口的RegisterMimeFilter来完成注册。这两种注册方法各有不同的适用范围。如果需要对所有网络程序都起作用的过滤器,那么就永久注册。如果只想过滤自身应用程序对网络的访问,那么就可以采用临时注册的方法。另外,如果藉由某种方法进入到所有网络程序的进程空间,那么临时注册的方法也可以起到永久注册的作用。

35插件MIME过滤器的优点

1)易于安装注册,插件MIME过滤器可以采用永久注册和临时注册,满足不同的需要。(2)属于应用层过滤,省去了组包的麻烦和繁琐的解码过程。(3)构建在COM之上,藉由COM的版本机制和包容聚合措施,易于扩充升级和配置。

4主要程序代码

41插件MIME过滤器的实现类的声明




CHttpFilter的声明中继承了


IInternetProtocol


IInternetProtocolSink接口,这是实现插件


MIME过滤器的必需接口。类中还声明了用于指向事务处理器中实现的


IInternetProtocol


IInternetProtocolSink接口的指针。


CComQIPtr


ATL的工具类,是可以自动改变引用计数,释放内存和接口查询的智能指针类。





class CHttpFilter : 


         


public CComObjectRootEx<CComSingleThreadModel>,


         


public CComCoClass<CHttpFilter, &CLSID_HttpFilter>,


         


public IInternetProtocol,


         


public IInternetProtocolSink


{


public:


         


/*


,见类的实现部分


*/


private:


         


/*保存事务处理器实现的


IInternetProtocol接口


*/


         


CComQIPtr<IInternetProtocol>m_pProtocol;


         


/*保存事务处理器实现的


IInternetProtocolSink接口


*/


         


CComQIPtr<IInternetProtocolSink>m_pProtocolSink;


         


IStream m_DataStream;


         


int m_nTotalSize;


         


int m_nWritten;


};


42 Start函数

此函数由事务处理器调用,事务处理器的每一次下载过程都由调用这个函数开始,在这里可以完成一些初始化工作,给指向事务处理器实现的


IInternetProtocol


IInternetProtocolSink接口的指针赋值。事务处理器调用完此函数后将调用插件


MIME过滤器实现的


ReportProgress函数。





STDMETHODIMP CHttpFilter::Start(


         


LPCWSTR szUrl,


         


IInternetProtocolSink *pIProtSink,


         


IInternetBindInfo *pIBindInfo,


         


DWORD grfSTI,


         


DWORD dwReserved)


{


         


m_nTotalSize = 0;


         


m_nWritten = 0;


         


m_pProtocolSink = pIProtSink;


         


m_pProtocol = pIProtSink;


         


return S_OK;


         


/*现在事务处理器将调用


ReportProgress*/


}


4


3


 ReportProgress函数 





此函数也是由事务处理器来调用,通过此函数向插件


MIME过滤器汇报下载的过程。调用完这个函数后,事务处理器将调用插件


MIME过滤器的


ReportData函数。





STDMETHODIMP CHttpFilter::ReportProgress(ULONG ulStatusCode, LPCWSTR szStatusText)


{


         


m_pProtocolSink->ReportProgress(ulStatusCode, szStatusText);


         


/*把所有信息继续传递


*/


         


return S_OK;


         


/*现在事物处理器将调用


ReportData*/


}


44 ReportData函数

此函数由事务处理器来调用,当有可用数据时,事务处理器调用此函数来通知插件


MIME过滤器,在此函数里插件


MIME过滤器可以通过调用事务处理器实现的


IInternetProtocol接口中的


Read函数来读取可用的数据,然后对读取的数据进行过滤处理。过滤处理由函数


FilterData来完成,这里没有给出具体的内容过滤的算法。处理完成后再通知事务处理器,这时事务处理器将会调用由插件


MIME过滤器实现的


IInternetProtocol接口中的


Read函数,来取得处理过后的数据。





STDMETHODIMP CHttpFilter::ReportData(DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)


{


         


/*返回


S_OK代表本次读取数据成功,但是仍然有可用数据。





         


返回


S_FALSE代表所有数据完全下载完毕,所以此处循环





         


读取直到下载完毕或者发生异常。


*/


         


CComBSTR StringStream;


         


HRESULT hr;


         


char buffer[BUFFER_SIZE];


         


ULONG nReadTotal;


         


do{


                 


hr = m_pProtocol->Read( buffer,sizeof(buffer),&nReadTotal);


                 


nReadTotal /= 2;


                 


StringStream.Append( (LPCOLESTR)buffer, nReadTotal ); // 


}while( hr != S_FALSE && hr != INET_E_DOWNLOAD_FAILURE && hr != INET_E_DATA_NOT_AVAILABLE );


         


if ( hr == S_FALSE )


         


{


                  


/*所有数据下载完毕后,在此处可以对其进行处理,


FilterData 


                  


是处理函数,具体处理算法略


*/


                 


FilterData(StringStream);


                 


CreateStreamOnHGlobal(0, TRUE, m_DataStream);


                 


StringStream.WriteToStream(m_DataStream);


                 


m_DataStream.Seek(0,STREAM_SEEK_SET,NULL);


                 


m_nTotalSize = StringStream.Length()*2;


                 


/*此处通知事务处理器所有的数据都已经准备好了,





                 


网络浏览器可以进行显示了


*/


         


m_pProtocolSink->ReportData(BSCF_FIRSTDATANOTIFICATION


|BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE, m_nTotalSize, m_nTotalSize);


                 


/* 把所有数据交给浏览器后汇报结果


S_OK */


                 


m_pProtocolSink->ReportResult(S_OK, S_OK, NULL);


         


}


         


else


         


{


                 


Abort( hr, 0 );


         


}


         


return S_OK;


         


/*现在事务处理器将调用我们的


Read函数


*/


}


45 Read函数

事务处理器通过此函数来读取处理过后的数据,最后交由浏览器显示出来。


STDMETHODIMP CHttpFilter::Read(void *pv, ULONG cb, ULONG *pcbRead)


{


         


/*这里完成读取所有可用数据


*/


         


m_DataStream.Read(pv, cb, pcbRead);


         


m_nWritten += cbread;


         


if (m_nWritten == m_nTotalSize) 


                 


return S_FALSE; 


         


else 


                 


return S_OK;


}


5结束语

本程序在WIN98WIN2000下面测试成功。其中只列出了部分主要的接口函数的实现,还有很多需要完善的地方,比如具体的过滤算法,对于永久注册提供必要的保护措施等。采用COM和异步插件协议实现内容过滤这种方法,简单易实现且效果好,应该具有广阔的应用空间。

 

参考文献:

[1] 杨秀章译


.COM技术内幕


[M]. 北京:清华大学出版社,


1999.


[2] 


王建华译


.Windows核心编程


[M].北京:机械工业出版社,


2000.


[3] 潘爱民,新语译.深入解析ATL[M].北京:中国电力出版社,2001.

 

 

你可能感兴趣的:(windows,网络,buffer,asynchronous,protocols)