Thursday, January 06, 2005

 

Filter IE

IE的广告过滤(包括弹出窗口和Flash等多种广告)这个话题很多人都详细分析过,我这里也说说自己的感受。

1.
首先,POP Killer不是一个好方法。

这个方面的一个完整例子参见
Popup Window Blocker
By John Osborn
http://www.codeproject.com/atl/popupblocker.asp

Popup Blocker is a Browser Helper Object (BHO) that eliminates all popup and popunder windows, including those opened automatically by script.

其核心是

Once we have the pointer to IWebBrowser2 we can hook up to the DWebBrowserEvents2 connection point in order to receive the NewWindow2 event. This event is sent every time a new window is about to open and allows you to cancel the operation -- exactly what we want for a popup window blocker.

这种方法已经比那种最土的先让其打开,然后Enumerate Windows,找出无标题的窗口杀之,找出以IE为父窗口的杀之的方法好上不少。可是这只能杀弹出窗口,不行,我们还要更绝的。

2.
于是有了彻底监视Internet Explorer的下载一文。

[quote]
原作:111222
出处:http://blog.csdn.net/111222/archive/2002/02/09/7255.aspx

你是否想过类似下面的一些问题?

l 如何过滤IE中的flash?
l 如何过滤在网页中嵌入email的尼姆达病毒?
l 如何实现像netants、flashget那样的下载监视呢?

看到上面问题,你会很快认为这很简单:

“对IE的下载进行监视不就得了?发现后缀是”.swf”的文件就不进行下载。这样就过滤了flash.同理,发现后缀是”.eml”的下载也做同样处理……”

那么,话说回来,如何彻底监视IE的下载呢?你不会为了这个写一个驱动程序吧?

如果你熟悉IE编程的话,会马上意识到---使用BHO(Browser Helper Object)。但,仅仅使用BHO是不够的。

BHO类似钩子(hook),特别的地方是:它钩的是IE的事件。

如果你还不熟悉BHO,请到MSDN网站看下面的文章:
http://www.microsoft.com/Mind/0598/browhelp.htm

通过上面文章你会发现,BHO可以”hook”到IE的所有事件:

Navigate->NavigateComplete->DownloadBegin->DownloadComplete->DocumentComplete等等。

但它hook不到IE的整个下载事件!比如:

www.csdn.net首页里包含了大量的gif文件,BHO面对着它们变成了盲人……

说了这么多废话~~~~下面拿出克敌法宝吧!

先了解一下IinternetProtocolRoot 的Start方法:

HRESULT Start(
LPCWSTR szUrl,//
IInternetProtocolSink *pOIProtSink,
IInternetBindInfo *pOIBindInfo,
DWORD grfPI,
HANDLE_PTR dwReserved
);

只要实现了IE的这个IinternetProtocolRoot接口,在其Start方法中检查szUrl,就做到了监视IE的下载。

那么,怎么过滤呢?再看看IinternetProtocolSink接口的ReportResult方法!
HRESULT ReportResult(
HRESULT hrResult,
DWORD dwError,
LPCWSTR szResult
);

只需要在Start中调用其第二个参数pOIProtSink的ReportResult方法就可以实现过滤。实际上就是在IE下载文件之前欺骗IE说文件已经下载完毕了。

比方说我们要过滤IE中的gif文件,那么只需要实现以下代码:

STDMETHODIMP CQUrl::Start(//这里,我的类名叫CQUrl,大家不必理会
LPCWSTR szUrl, IInternetProtocolSink *pIProtSink,
IInternetBindInfo *pIBindInfo, DWORD grfSTI,
DWORD dwReserved)

{
USES_CONVERSION;

char *str=OLE2A(szUrl);

if(strlen(str) > 4)

{

str = str + strlen(str) - 4; //取资源的最后四个字符,用来比较文件后缀

if(_strnicmp(str,".gif",4) == 0)//后缀是gif

{

pIProtSink->ReportResult(S_OK, 0, 0);//告诉IE:下载已经结束了! return S_OK;//返回,如果你返回INET_E_DOWNLOAD_FAILURE将看到另外一幅景象……

}
}

return INET_E_USE_DEFAULT_PROTOCOLHANDLER;

}

熟悉了监视过滤的一般方法,下面开始把监视过滤工作深入到IE之中吧!拿上面MIND杂志的iehelper的实例说起。

我们在IEHelper的基础上填加一个ATL对象,在其中继承IinternetProtocol

并实现IinternetProtocolRoot的Start方法就可以了!

剩下所需的工作仅仅是在IEHelper的构造函数中实现上面填加的atl对象。

在IEHelper类里加两个接口的指针:

IInternetSession* m_pSession;
IClassFactory* m_pFactory;

然后创建对象:

CIEHlprObj()
{
HRESULT hr = CoGetClassObject(CLSID_FiltUrl, CLSCTX_SERVER, NULL, IID_IClassFactory, (void**)&m_pFactory);

if(hr==S_OK)

{
if(CoInternetGetSession(0, &m_pSession, 0)==S_OK)

m_pSession->RegisterNameSpace(m_pFactory, CLSID_FiltUrl, L"http", 0, NULL, 0); //监视HTTP服务

}

}

必要的时候析构:

CIEHlprObj::~CIEHlprObj()
{

if(m_pSession!=NULL)
{
m_pSession->UnregisterNameSpace(m_pFactory, L"http");
m_pSession->Release();
m_pSession = NULL;
}

if(m_pFactory!=NULL)
{

m_pFactory->Release();
m_pFactory = NULL;
}
}

唉,好累,不写了,烦,颠三倒四的。
[/quote]

3.
上文的一个错误是直接判断文件后缀名,这是不太可靠的。好的方法是MIME filter,下文说的已经非常清楚,不赘述
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q260840

对了,忘了说一句,如果要同以前blog里面谈到的实现IE文件的实时编辑。必须设置CHTMLCtrl的属性为编辑状态,才能最方便的block javascipt广告。两年前在CP和一帮牛腿(尚不够牛)们讨论了半天,还是一牛突然杀到,半句话点醒,惭愧惭愧。

4.
补充:
By JiangSheng
From http://blog.csdn.net/jiangsheng/archive/2004/11/07/170742.aspx

信息栏(New!)

Windows XP SP2 中的Internet Explorer 6 引入了一个新的安全用户界面元素,称为信息栏。在特定操作被阻止的时候,信息栏给用户显示一个用户界面元素。特别的,它会在以下操作被阻止的时候显示。
弹出窗口初始化(参见 弹出窗口杀手)
文件下载 (see 文件下载的限制)
安装ActiveX 控件(see ActiveX 的限制)
ActiveX控件安全提示的原因是用户安全设置或者是控件未标记为脚本安全的。
文件的扩展名和多用途因特网邮件扩展类型(MIME)不符的(参见 MIME 处理)
网络协议锁死的内容(参见 协议)

信息栏是Windows XP SP2 中的Internet Explorer 6引入的安全特性之一。和其他安全特性控制一样,可以通过一个注册表键来控制:(FEATURE_SECURITYBAND). 默认情况下IE(iexplorer.exe) 和Windows 资源管理器(explorer.exe) 在这个安全特性控制下。下面显示注册表键和启用过程:

HKEY_LOCAL_MACHINE (or HKEY_CURRENT_USER)
SOFTWARE
Microsoft
Internet Explorer
Main
FeatureControl
FEATURE_SECURITYBAND
iexplorer.exe= 0x00000001
explorer.exe= 0x00000001
process name.exe=0x00000001

这个FEATURE_SECURITYBAND 安全特性控制影响IE是否显示信息栏,信息栏在一个操作被阻止的时候提示用户。它不控制操作的阻止过程。
一个集成浏览器控件的程序可以通过将其进程添加到这个注册表键来启用信息栏。这可以通过调用CoInternetSetFeatureEnabled函数来在运行时执行。如果一个应用程序并未在这个安全特性控制下,那么浏览器控件的行为和Internet Explorer 6 SP1b中的一样.
没有方法通过脚本来访问这个特性。
在FEATURE_SECURITYBAND及相关安全特性控制下的应用程序可以使用信息栏应用程序编程接口(API)来在一个URL 操作被禁止时自定义显示的用户界面。为信息栏引入了很多新的OLECMDID命令。头三个是属于CGID_DocHostCommandHandler组。宿主应用程序应该在它们的IDocHostUIHandler实现的同一个对象中实现IOleCommandTarget ,以接受来自浏览器控件的IOleCommandTarget::Exec调用。
OLECMDID_PAGEACTIONBLOCKED
OLECMDID_PAGEACTIONUIQUERY
OLECMDID_FOCUSVIEWCONTROLS
宿主应用程序可以使用下面两个新的OLECMDID 命令来执行浏览器控件的IOleCommandTarget::Exec调用。
OLECMDID_FOCUSVIEWCONTROLSQUERY
OLECMDID_SHOWPAGEACTIONMENU这个示例使用IWebBrowser2::ExecWB 来执行OLECMDID_SHOWPAGEACTIONMENU 命令。 POINT pt = { 0 };
GetCursorPos(&pt);
CComVariant varHwnd((LONG)hwnd);
CComVariant varX(pt.x);
CComVariant varY(pt.y);
SAFEARRAY* psa = SafeArrayCreateVector(VT_VARIANT, 0, 3);
LONG lIndex = 0;
SafeArrayPutElement(psa, &lIndex, &varHwnd);
lIndex++;
SafeArrayPutElement(psa, &lIndex, &varX);
lIndex++;
SafeArrayPutElement(psa, &lIndex, &varY);
CComVariant varArgIn;
V_VT(&varArgIn) = VT_ARRAY VT_I4;
V_ARRAY(&varArgIn) = psa;
pBrowser->ExecWB(OLECMDID_SHOWPAGEACTIONMENU, (OLECMDEXECOPT)dwPageActionFlags, &varArgIn, NULL);
另外,应用程序可以实现IInternetSecurityManager来重载默认的安全区域设置,参见创建一个自定义URL安全管理器以获得更多信息.

5.
不过矛与盾总是在发展中
From http://blog.csdn.net/feng_sundy/archive/2004/11/03/165376.aspx

现在网络弹出窗口乱七八糟,很多人不愿意看到弹出广告窗口,可是有的有用的窗口又想让别人看到,用window.opne方法打开窗口都被拦截了,一下方法可以解决让你的窗口不被诸如Google工具条拦截。就算开启了拦截功能也不会拦截。
一下代码在IE6SP1,GOOGLE工具条(开启拦截弹出窗口),测试通过
default.htm

script language="javascript">
var test = window.showModalDialog('openwindow.htm','OpenWindow','');
window.opener = null;
window.close();
/script>

openwindow.htm
script language="javascript">
function openFullScreen(){
window.open("default1.htm","full","fullscreen");//Default1.htm文件为你要弹出的窗口文件
window.returnValue = "TEST";
window.close();
}
openFullScreen();
/script>



<< Home

This page is powered by Blogger. Isn't yours?