【问题标题】:Detecting external content with TEmbeddedWB or TWebBrowser使用 TEmbeddedWB 或 TWebBrowser 检测外部内容
【发布时间】:2012-05-25 03:18:33
【问题描述】:

我试图阻止由 TEmbeddedWB 或 TWebBrowser(或 TCppWebBrowser)加载的任何外部内容。我想阻止从 Internet 加载的任何内容,包括图像、javascript、外部 CSS、外部 [embed] 或 [object] 或 [applet] 或 [frame] 或 [iframe],执行可以加载外部内容的 JavaScript 等。

这个问题由两部分组成:

  • 将网络浏览器设置为“全部限制”(除了没有图像的基本 HTML)并检测是否存在此类内容
  • 如果外部内容不存在,如果存在,则显示“下载栏”,点击后将网络浏览器置于“全部下载”模式并获取所有内容。

第一项有问题。在 TEmbeddedWB 中,您可以使用 DownloadOptions 开关阻止几乎任何东西,最重要的是 ForceOffline 开关,但即使所有这些都关闭,它仍然会通过一些东西,如 [object][iframe] 标签。我知道是这种情况,因为我实现了 OnBeforeNavigate2 事件,它触发了这些标签中包含的 URL,并且它还在本地服务器的日志中创建了一个条目。在 TEmbeddedWB 中设置 OfflineModeForceOfflineMode 对这些项目没有帮助。

那么我怎样才能真正阻止所有?因此,它需要从包含脚本和 CSS 在内的被阻止的外部元素的基本 HTML 开始。有没有办法在每次想要下载任何内容时触发事件,以便可以阻止它或通过阻止所有外部下载来避免首先触发此类事件?我需要摆弄 Internet Explorer 区域和安全性吗?任何指向正确方向的指针都会有所帮助。

第二项也很棘手,因为我需要检测是否存在有问题的标签(例如“applet”、“script”、“link”等。这种检测不需要完美,但至少必须是好的足以覆盖大部分此类标签。我是这样做的:

//----------------------------------------------------------------------
// Check for external content (images, scripts, ActiveX, frames...)
//----------------------------------------------------------------------
try
    {    
    bool                                HasExternalContent = false;
    DelphiInterface<IHTMLDocument2>     diDoc;                              // Smart pointer wrapper - should automatically call release() and do reference counting
    diDoc = TEmbeddedWB->Document;

    DelphiInterface<IHTMLElementCollection>     diColApplets;           DelphiInterface<IDispatch>          diDispApplets;      DelphiInterface<IHTMLObjectElement> diObj;
    DelphiInterface<IHTMLElementCollection>     diColEmbeds;            DelphiInterface<IDispatch>          diDispEmbeds;
    DelphiInterface<IHTMLFramesCollection2>     diColFrames;            DelphiInterface<IDispatch>          diDispFrames;
    DelphiInterface<IHTMLElementCollection>     diColImages;            DelphiInterface<IDispatch>          diDispImages;       DelphiInterface<IHTMLImgElement>    diImg;
    DelphiInterface<IHTMLElementCollection>     diColLinks;             DelphiInterface<IDispatch>          diDispLinks;
    DelphiInterface<IHTMLElementCollection>     diColPlugins;           DelphiInterface<IDispatch>          diDispPlugins;
    DelphiInterface<IHTMLElementCollection>     diColScripts;           DelphiInterface<IDispatch>          diDispScripts;
    DelphiInterface<IHTMLStyleSheetsCollection> diColStyleSheets;       DelphiInterface<IDispatch>          diDispStyleSheets;

    OleCheck(diDoc->Get_applets     (diColApplets));
    OleCheck(diDoc->Get_embeds      (diColEmbeds));
    OleCheck(diDoc->Get_frames      (diColFrames));
    OleCheck(diDoc->Get_images      (diColImages));
    OleCheck(diDoc->Get_links       (diColLinks));
    OleCheck(diDoc->Get_plugins     (diColPlugins));
    OleCheck(diDoc->Get_scripts     (diColScripts));
    OleCheck(diDoc->Get_styleSheets (diColStyleSheets));

    // Scan for applets external links
    for (int i = 0; i < diColApplets->length; i++)
        {
        OleCheck(diColApplets->item(i,i,diDispApplets));
        if (diDispApplets != NULL)
            {
            diDispApplets->QueryInterface(IID_IHTMLObjectElement, (void**)&diObj);
            if (diObj != NULL)
                {
                UnicodeString s1 = Sysutils::Trim(diObj->data),
                              s2 = Sysutils::Trim(diObj->codeBase),
                              s3 = Sysutils::Trim(diObj->classid);

                if (StartsText("http", s1) || StartsText("http", s2) || StartsText("http", s3))
                    {
                    HasExternalContent = true;
                    break;                                                  // At least 1 found, bar will be shown, no further search needed
                    }
                }
            }
        }

    // Scan for images external links
    for (int i = 0; i < diColImages->length; i++)
        {
        OleCheck(diColImages->item(i,i,diDispImages));
        if (diDispImages != NULL)                                           // Unnecessary? OleCheck throws exception if this applies?
            {
            diDispImages->QueryInterface(IID_IHTMLImgElement, (void**)&diImg);
            if (diImg != NULL)
                {
                UnicodeString s1 = Sysutils::Trim(diImg->src);

                // Case insensitive check
                if (StartsText("http", s1))
                    {
                    HasExternalContent = true;
                    break;                                                  // At least 1 found, bar will be shown, no further search needed
                    }
                }
            }
        }
    }
catch (Exception &e)
    {
    // triggered by OleCheck
    ShowMessage(e.Message);
    }

有没有更简单的方法来扫描这个,或者唯一的方法是使用其他接口函数运行几个循环,例如Get_appletsGet_embedsGet_stylesheets 等,类似于上面的代码?到目前为止,我发现我必须调用以下函数来涵盖所有这些:

    OleCheck(diDoc->Get_applets     (diColApplets));
    OleCheck(diDoc->Get_embeds      (diColEmbeds));
    OleCheck(diDoc->Get_frames      (diColFrames));
    OleCheck(diDoc->Get_images      (diColImages));
    OleCheck(diDoc->Get_links       (diColLinks));
    OleCheck(diDoc->Get_plugins     (diColPlugins));
    OleCheck(diDoc->Get_scripts     (diColScripts));
    OleCheck(diDoc->Get_styleSheets (diColStyleSheets));

但如果可以更轻松地处理,我宁愿不实现那么多循环。可以吗?

【问题讨论】:

  • 句子我想阻止从互联网加载的任何内容是否意味着您想要离线模式?如果是这样,只需将 TWebBrowser.Offline 设置为 True ;-)
  • 如果这么简单就好了。我设置了 Offline 和 ForceOffline 标志,但它仍然加载一些外部内容,例如[object] 标签或一些框架。
  • 你的 HTML 有多复杂?您需要 Internet Explorer 吗?
  • 是的,我需要 IE - HTML 不是微不足道的。我虽然已经使用 RegEx 和类似的解决方案过滤 HTML。问题还在于,这也被记录得非常糟糕,而且例子很少(除非我想进入完整的 C++ 模式——然后我有相对详细的 MSDN 文档)。上面的代码是来自各种来源的大量谷歌搜索的结果,我什至不确定它在内存泄漏等方面是否正确,尽管它有效:)
  • 其他想法/选项...您说的是 IE... IE=IE,还是 IE=Web 浏览器?你试过TChromium吗?

标签: delphi webbrowser-control c++builder twebbrowser


【解决方案1】:

我建议你这个解决方案:

#include "html.h"
THTMLDocument doc;
void __fastcall TForm1::CppWebBrowser1DocumentComplete(TObject *Sender, LPDISPATCH pDisp,
          Variant *URL)
{
    doc.documentFromVariant(CppWebBrowser1->Document);

    bool HasExternalContent = false;
    for (int i=0; i<doc.images.length; i++) {
        if(doc.images[i].src.SubString(1, 4) == "http")
        {
            HasExternalContent = true;
            break;
        }
    }
    for (int i=0; i<doc.applets.length; i++) {
        THTMLObjectElement obj = doc.applets[i];
        if(obj.data.SubString(1, 4) == "http")
            HasExternalContent = true;
        if(obj.codeBase.SubString(1, 4) == "http")
            HasExternalContent = true;
        if(obj.classid.SubString(1, 4) == "http")
            HasExternalContent = true;
    }
}

这个很棒的包装类可以从here下载。

【讨论】:

  • 这看起来真的很有用。这个包装是干什么用的?该网站或课程本身没有太多信息。
  • 这个wapper是我自己写的,适用于具有html UI或任何与HTML相关的porpose的应用程序。使用此包装器,您还可以在 C++ Builder 中处理 html 事件,例如“onmouseclick”;欲了解更多信息,请参阅this
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多