Symbian编程总结-网络与通信-使用CEComFilter捕获系统HTTP请求
2009-04-23 10:43
681 查看
本文章由杨芹勍原创,如需转载请注明作者及出处,否则保留追究法律责任的权利!
通过代码我们可以分析出以下结论:
第1行,CEComFilter这个ECOM接口类的接口UID(interface_uid)为0x101F446D;
第5行、第11行,该接口提供了能够获得“ECOM实现(指实现了ECOM接口的类)”的两个工厂方法:InstallFilterL的两个重载函数。第一个函数将“ECOM实现”的“实现UID(implementation_uid)”传给默认ECOM决议者,第二个函数将提示参数传给默认ECOM决议者。
注意:两个工厂方法都会将RHTTPSession http会话的指针通过ECOM决议者创建“ECOM实现”时传入“ECOM实现”的构造函数。
系统创建了HTTP会话后,会遍历所有实现了CEComFilter接口的ECOM实现UID(implementation_uid),使用工 厂方法将ECOM实现实例化,同时传入HTTP会话(RHTTPSession);这样,我们的CEComFilter的实现就能够针对此HTTP会话进 行相关监控。
在此,系统只知道interface_uid,如何通过interface_uid知道有哪些implementation_uid的实现呢?很简单,使用如下函数即可获得:
具体流程如下(模拟实现):
SDK中关于RHTTPSession::FilterCollection()方法的解释:
Accessor for the filter collection. Note that the filter collection can't be edited after the first transaction has been created.
注意:如果已经在RHTTPSession上创建了RHTTPTransaction,则不能对Filter Collection进行修改。
此方法返回类型RHTTPFilterCollection,使用RHTTPFilterCollection::AddFilterL的重载函数向RHTTPSession的监视器队列中添加“监视器”,用于捕获HTTP请求信息:
参数说明:
aFilter:类型为MHTTPFilter的引用,MHTTPFilter的定义为:
看到这里大家肯定会想起MHTTPTransactionCallback类,此类用在 RHTTPSession::OpenTransactionL中,为HTTP请求的回调,我们使用 RHTTPSession::OpenTransactionL打开一个连接后,往往会在MHFRunL方法中获取HTTP返回的字节、检查 StatusCode、检查HTTP头信息等。而MHTTPFilter也提供MHFRunL方法,我们可以再此方法中对系统任意一个HTTP请求进行捕 获,做相应的检查和处理;
另外,MHTTPFilter类中的方法都不是纯虚函数,我们的类中可以有选择的进行继承;
aEvent:监视器所监视的HTTP请求事件类型,可以监视所有时间或者只针对Transaction Event、Session Event进行监视,具体请参看SDK中“THTTPEvent”类的文档;
aHeaders:HTTP接收到指定的头将触发事件;
aStatusCode:HTTP接收到指定的状态码将触发事件;
aPosition:监视器所在“位置”,在RHTTPSession完成一个HTTP请求时,会分为几个步骤:处理协议、处理缓存、处理状态 码、处理UA等,aPosition所代表的“位置”指的就是把监视器插入哪个步骤中进行监视,具体数值及详细解释请参看 MHTTPFilter::TPositions枚举值的说明;
aName:自定义的监视器的名字。
根据以上分析,我们可以通过实现CEComFilter接口完成一个Demo:只要系统提交了HTTP进行Url的请求,就弹出一个全局消息框,显示HTTP所请求的Url地址。
1、实现接口的类名叫CFelixHttpFilter,定义如下:
2、关键类代码实现如下:
注意,代码第55行中的0xA00133E9是我们ECOM实现的implementation_uid。
3、我们的程序UID3为0xA00133E8,ECOM资源文件名:A00133E8.rss,内容如下:
以上资源文件第16行,default_data的作用:
HTTP监视器能够“主动的”加载或者“被动的”加载,这取决于你资源文件中IMPLEMENTATION_INFO小节中的“default_data”字段(以上代码第16行)所设定的值,有如下三个加载选项被支持:
HTTP/+FELIXFILTER:监视器总是能自动加载
HTTP/-FELIXFILTER:监视器不会加载,用户只能手动的加载它
HTTP/FELIXFILTER:除非用户从监视器集合中移除,监视器都会加载
按照以上步骤,实现CEComFilter接口,生成基于多态dll的plugin;
重写MHTTPFilter::MHFRunL方法;
因为要做下载软件不可能在MHFRunL方法中简单地通过判断Url来判断文件类型,必须通过判断服务器返回的MIME类型是否为所支持下载文件 类型的MIME,因此得判断aEvent是否为“服务器端Headers返回”的状态,来获取返回头的“Content-Type”字段;
判断MHFRunL方法中的aEvent是否为EGotResponseHeaders;
通过aTransaction.Response().GetHeaderCollection()获取字段“Content-Type”的值,通过“自定义字符串池(将在以后章节介绍)”的技术加快MIME的匹配对比;
如果服务器返回的MIME类型满足下载工具支持的类型,则弹出全局询问框,询问用户是否通过下载工具下载;
用户选择“是”,则将aTransaction.Cancel(),获取请求的Url,启动下载程序并将Url发送过去;
用户选择“否”,什么事都不做。
Writing an HTTP filter plugin
本文章由杨芹勍原创,如需转载请注明作者及出处,否则保留追究法律责任的权利!
一、前言
在IE浏览器中,如果想捕获浏览器的HTTP请求,可以通过BHO或者“异步可插协议”技术实现,类似于“迅雷”之类的下载软件,当用户点击一个下载链接会自动弹出。在Symbian OS中有一种技术与“异步可插协议”非常类似,Symbian OS会在HTTP请求中每一步处理过程都通知用户代码,本文将介绍这种技术的实现,并在文章的最后提供在手机上实现下载软件的具体思路。二、核心ECOM接口类CEComFilter
从类名可以看出,CEComFilter是一个ECOM接口类(关于ECOM方面的编程总结,我会在后面的章节陆续放出),以下列出CEComFilter类的关键代码(SDK中文件cecomfilter.h内):< Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ > 1 const TUid KUidFilterPluginInterface = { 0x101F446D }; 2 class CEComFilter : public CBase 3 { 4 public : 5 static CEComFilter * InstallFilterL(RHTTPSession aSession, const TUid aEComFilterUid) 6 { 7 TAny * filterPlugin = REComSession::CreateImplementationL(aEComFilterUid, _FOFF(CEComFilter,iEcomDtorID), & aSession); 8 return REINTERPRET_CAST(CEComFilter * , filterPlugin); 9 } 10 11 static CEComFilter * InstallFilterL(RHTTPSession aSession, const TDesC8 & aEComFilterDataType) 12 { 13 TEComResolverParams resolverParams; 14 resolverParams.SetDataType(aEComFilterDataType); 15 16 // This will leave if the plugin is not found 17 TAny * filterPlugin = REComSession::CreateImplementationL(KUidFilterPluginInterface, 18 _FOFF(CEComFilter,iEcomDtorID), 19 & aSession, resolverParams); 20 return REINTERPRET_CAST(CEComFilter * , filterPlugin); 21 } 22 23 ~ CEComFilter() 24 { 25 REComSession::DestroyedImplementation(iEcomDtorID); 26 } 27 28 private : 29 TUid iEcomDtorID; 30 };< 本插件原作者为 Steve Dunn,汉化刘建成. http://www.tvwz.com.cn >
通过代码我们可以分析出以下结论:
第1行,CEComFilter这个ECOM接口类的接口UID(interface_uid)为0x101F446D;
第5行、第11行,该接口提供了能够获得“ECOM实现(指实现了ECOM接口的类)”的两个工厂方法:InstallFilterL的两个重载函数。第一个函数将“ECOM实现”的“实现UID(implementation_uid)”传给默认ECOM决议者,第二个函数将提示参数传给默认ECOM决议者。
注意:两个工厂方法都会将RHTTPSession http会话的指针通过ECOM决议者创建“ECOM实现”时传入“ECOM实现”的构造函数。
系统创建了HTTP会话后,会遍历所有实现了CEComFilter接口的ECOM实现UID(implementation_uid),使用工 厂方法将ECOM实现实例化,同时传入HTTP会话(RHTTPSession);这样,我们的CEComFilter的实现就能够针对此HTTP会话进 行相关监控。
在此,系统只知道interface_uid,如何通过interface_uid知道有哪些implementation_uid的实现呢?很简单,使用如下函数即可获得:
< Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ > class REComSession : public RSessionBase { ... IMPORT_C static void ListImplementationsL(TUid aInterfaceUid, RImplInfoPtrArray & aImplInfoArray); ... }< 本插件原作者为 Steve Dunn,汉化刘建成. http://www.tvwz.com.cn >
具体流程如下(模拟实现):
三、如何实现CEComFilter接口
实现CEComFilter,其实就是实现一个普通的ECOM接口,步骤非常简单,在此不再说明具体步骤。重点在第5步:如何对传入的RHTTPSession进行监控。SDK中关于RHTTPSession::FilterCollection()方法的解释:
Accessor for the filter collection. Note that the filter collection can't be edited after the first transaction has been created.
注意:如果已经在RHTTPSession上创建了RHTTPTransaction,则不能对Filter Collection进行修改。
此方法返回类型RHTTPFilterCollection,使用RHTTPFilterCollection::AddFilterL的重载函数向RHTTPSession的监视器队列中添加“监视器”,用于捕获HTTP请求信息:
< Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ > IMPORT_C void AddFilterL(MHTTPFilter & aFilter, THTTPEvent aEvent, RStringF aHeader, TInt aStatusCode, TInt aPosition, RStringF aName);< 本插件原作者为 Steve Dunn,汉化刘建成. http://www.tvwz.com.cn >
参数说明:
aFilter:类型为MHTTPFilter的引用,MHTTPFilter的定义为:
< Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ > 1 class MHTTPFilter 2 { 3 public : 4 IMPORT_C virtual void MHFUnload(RHTTPSession aSession, THTTPFilterHandle aHandle); 5 IMPORT_C virtual void MHFLoad(RHTTPSession aSession, THTTPFilterHandle aHandle); 6 IMPORT_C virtual void MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent & aEvent); 7 IMPORT_C virtual void MHFSessionRunL( const THTTPSessionEvent & aEvent); 8 IMPORT_C virtual TInt MHFRunError(TInt aError, RHTTPTransaction aTransaction, const THTTPEvent & aEvent); 9 IMPORT_C virtual TInt MHFSessionRunError(TInt aError, const THTTPSessionEvent & aEvent); 10 };< 本插件原作者为 Steve Dunn,汉化刘建成. http://www.tvwz.com.cn >
看到这里大家肯定会想起MHTTPTransactionCallback类,此类用在 RHTTPSession::OpenTransactionL中,为HTTP请求的回调,我们使用 RHTTPSession::OpenTransactionL打开一个连接后,往往会在MHFRunL方法中获取HTTP返回的字节、检查 StatusCode、检查HTTP头信息等。而MHTTPFilter也提供MHFRunL方法,我们可以再此方法中对系统任意一个HTTP请求进行捕 获,做相应的检查和处理;
另外,MHTTPFilter类中的方法都不是纯虚函数,我们的类中可以有选择的进行继承;
aEvent:监视器所监视的HTTP请求事件类型,可以监视所有时间或者只针对Transaction Event、Session Event进行监视,具体请参看SDK中“THTTPEvent”类的文档;
aHeaders:HTTP接收到指定的头将触发事件;
aStatusCode:HTTP接收到指定的状态码将触发事件;
aPosition:监视器所在“位置”,在RHTTPSession完成一个HTTP请求时,会分为几个步骤:处理协议、处理缓存、处理状态 码、处理UA等,aPosition所代表的“位置”指的就是把监视器插入哪个步骤中进行监视,具体数值及详细解释请参看 MHTTPFilter::TPositions枚举值的说明;
aName:自定义的监视器的名字。
根据以上分析,我们可以通过实现CEComFilter接口完成一个Demo:只要系统提交了HTTP进行Url的请求,就弹出一个全局消息框,显示HTTP所请求的Url地址。
四、实现CEComFilter接口
完整源代码请点击此处下载1、实现接口的类名叫CFelixHttpFilter,定义如下:
< Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ > 1 class CFelixHttpFilter: public CEComFilter, private MHTTPFilter 2 { 3 public : 4 ~ CFelixHttpFilter(); 5 static CFelixHttpFilter * NewL(TAny * aHttpSession); 6 static CFelixHttpFilter * NewLC(TAny * aHttpSession); 7 8 public : 9 // MHTTPFilter 10 void MHFUnload(RHTTPSession aSession, THTTPFilterHandle aHandle); 11 void MHFLoad(RHTTPSession aSession, THTTPFilterHandle aHandle); 12 void MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent & aEvent); 13 14 private : 15 CFelixHttpFilter(); 16 void ConstructL(TAny * aHttpSession); 17 18 private : 19 RStringF iFilterName; 20 }; 21< 本插件原作者为 Steve Dunn,汉化刘建成. http://www.tvwz.com.cn >
2、关键类代码实现如下:
< Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ > 1 _LIT8(KFilterName, " FelixFilter " ); 2 3 CFelixHttpFilter:: ~ CFelixHttpFilter() 4 { 5 iFilterName.Close(); 6 } 7 8 CFelixHttpFilter * CFelixHttpFilter::NewLC(TAny * aHttpSession) 9 { 10 CFelixHttpFilter * self = new (ELeave) CFelixHttpFilter(); 11 CleanupStack::PushL(self); 12 self -> ConstructL(aHttpSession); 13 return self; 14 } 15 16 CFelixHttpFilter * CFelixHttpFilter::NewL(TAny * aHttpSession) 17 { 18 CFelixHttpFilter * self = CFelixHttpFilter::NewLC(aHttpSession); 19 CleanupStack::Pop(); // self; 20 return self; 21 } 22 23 void CFelixHttpFilter::ConstructL(TAny * aHttpSession) 24 { 25 RHTTPSession & httpSession = * (reinterpret_cast < RHTTPSession *> (aHttpSession)); 26 27 iFilterName = httpSession.StringPool().OpenFStringL(KFilterName); 28 CleanupClosePushL(iFilterName); 29 30 httpSession.FilterCollection().AddFilterL( * this , THTTPEvent::EAnyTransactionEvent, RStringF(), KAnyStatusCode, EClientFilters, iFilterName); 31 CleanupStack::Pop( & iFilterName); 32 } 33 34 void CFelixHttpFilter::MHFUnload(RHTTPSession aSession, THTTPFilterHandle aHandle) 35 { 36 delete this ; 37 } 38 39 void CFelixHttpFilter::MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent & aEvent) 40 { 41 if (aEvent == THTTPEvent::ESubmit) 42 { 43 // 在此处拦截到请求的Url 44 const TDesC8 & url = aTransaction.Request().URI().UriDes(); 45 TBuf < KMaxFileName > url16; 46 url16.Copy(url); 47 48 // 效果:将url打印到屏幕上 49 CEikonEnv::Static() -> InfoWinL(url16, KNullDesC16); 50 } 51 } 52 53 const TImplementationProxy kImplementationTable[] = 54 { 55 IMPLEMENTATION_PROXY_ENTRY( 0xA00133E9 , CFelixHttpFilter::NewL) 56 }; 57 58 EXPORT_C const TImplementationProxy * ImplementationGroupProxy(TInt & aTableCount) 59 { 60 aTableCount = sizeof (kImplementationTable) / sizeof (TImplementationProxy); 61 return kImplementationTable; 62 } 63< 本插件原作者为 Steve Dunn,汉化刘建成. http://www.tvwz.com.cn >
注意,代码第55行中的0xA00133E9是我们ECOM实现的implementation_uid。
3、我们的程序UID3为0xA00133E8,ECOM资源文件名:A00133E8.rss,内容如下:
< Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ > 1 RESOURCE REGISTRY_INFO filterinfo 2 { 3 dll_uid = _UID3; 4 interfaces = 5 { 6 INTERFACE_INFO 7 { 8 interface_uid = 0x101F446D ; 9 implementations = 10 { 11 IMPLEMENTATION_INFO 12 { 13 implementation_uid = 0xA00133E9 ; 14 version_no = 1 ; 15 display_name = " Felix Filter " ; 16 default_data = " HTTP/+FELIXFILTER " ; 17 opaque_data = "" ; 18 } 19 }; 20 } 21 }; 22 } 23< 本插件原作者为 Steve Dunn,汉化刘建成. http://www.tvwz.com.cn >
以上资源文件第16行,default_data的作用:
HTTP监视器能够“主动的”加载或者“被动的”加载,这取决于你资源文件中IMPLEMENTATION_INFO小节中的“default_data”字段(以上代码第16行)所设定的值,有如下三个加载选项被支持:
HTTP/+FELIXFILTER:监视器总是能自动加载
HTTP/-FELIXFILTER:监视器不会加载,用户只能手动的加载它
HTTP/FELIXFILTER:除非用户从监视器集合中移除,监视器都会加载
五、如何实现手机下载软件
基本概念都已经清楚,现在我们来想想如何实现手机上的迅雷。根据以下流程可以容易的做到:按照以上步骤,实现CEComFilter接口,生成基于多态dll的plugin;
重写MHTTPFilter::MHFRunL方法;
因为要做下载软件不可能在MHFRunL方法中简单地通过判断Url来判断文件类型,必须通过判断服务器返回的MIME类型是否为所支持下载文件 类型的MIME,因此得判断aEvent是否为“服务器端Headers返回”的状态,来获取返回头的“Content-Type”字段;
判断MHFRunL方法中的aEvent是否为EGotResponseHeaders;
通过aTransaction.Response().GetHeaderCollection()获取字段“Content-Type”的值,通过“自定义字符串池(将在以后章节介绍)”的技术加快MIME的匹配对比;
如果服务器返回的MIME类型满足下载工具支持的类型,则弹出全局询问框,询问用户是否通过下载工具下载;
用户选择“是”,则将aTransaction.Cancel(),获取请求的Url,启动下载程序并将Url发送过去;
用户选择“否”,什么事都不做。
六、参考文献
how to get your filter loaded automaticallyWriting an HTTP filter plugin
本文章由杨芹勍原创,如需转载请注明作者及出处,否则保留追究法律责任的权利!
相关文章推荐
- Symbian编程总结-网络与通信-使用CEComFilter捕获系统HTTP请求
- Symbian编程总结-网络与通信-使用CEComFilter捕获系统HTTP请求
- Symbian编程总结-网络与通信-套接字(1)-套接字体系结构与相关API
- Symbian编程总结-网络与通信-套接字(1)-套接字体系结构与相关API
- Linux C语言编程-Linux网络通信--Linux上使用curl来发送Http协议的报文---知识点总结+实例d
- Symbian编程总结-网络与通信-套接字(1)-套接字体系结构与相关API
- Linux C语言编程-Linux网络通信--Linux上使用套接字(socket)来发送信息---知识点总结+实例
- Symbian编程总结-文件、流与数据库-文件系统及相关API(1)
- Symbian编程总结-文件、流与数据库-文件系统及相关API(1)
- linux网络编程之慢系统调用被信号中断产生EINTR错误怎么解决总结
- iphone网络编程 http请求 get / post(发送二进制文件) 总结
- Java基础知识强化之网络编程笔记15:Android网络通信之 Android异步任务处理(AsyncTask使用)
- [原]使用Fiddler捕获java的网络通信数据
- Atitit 三种并发编程模型 艾龙 attilax总结 1. 并发系统可以使用不同的并发模型去实现。 1 2. 并行工作者 并行工作者模型。进来的任务分配给不同的工作者 银行模式 2 2.1.
- Linux C语言编程-Linux网络通信--Linux上使用套接字(socket)来处理信息---编写一个单进程非阻塞多客户的套接字客户端
- Symbian 网络编程之使用Socket API
- Java网络编程——使用NIO实现非阻塞Socket通信
- Symbian编程总结-图形图像篇-使用双缓存进行图形的绘制
- Symbian编程总结-图形图像篇-使用双缓存进行图形的绘制
- Java基础知识强化之网络编程笔记16:Android网络通信之 使用Http的Get方式读取网络数据(基于HTTP通信技术)