打印

HG2003: META 标签的 content 属性中使用非 ';' 的符号做数据分割时在某些浏览器中不会被识别

作者:陆远

标准参考

META 标签位于 HTML 文档的头部,可以提供与页面有关的元信息(meta-information)。一个 META 元素的 http-equiv 属性及 content 属性,组成了 "名称/值" 这种键值对,在服务器在发送实际的文档到浏览器端之前,把 "名称/值" 对添加到发送给浏览器的内容头部。

W3C 在规范中特别提到,某些用户端支持通过 META 元素的设置在若干秒内刷新页面,或者使页面跳转到指定的 URI。然而 W3C 并不推荐用户使用这种方式控制页面跳转。这可能导致对于某些用户页面不可访问。应使用服务端控制页面的跳转。

关于 META 元素的详细信息,请参考 HTML 4.01 规范 7.4.4 中的内容。

问题描述

通过 META 元素可以控制页面定时跳转,对于 http-equiv 属性为 refresh 时对应的 content 属性的值中,跳转时间与跳转 URL 之间需要分隔符分开,如果使用非 ';' 的分隔符时,在某些浏览器下将不能达到期望的效果。

造成的影响

META 元素控制页面跳转被广泛用于 BBS 等系统中,若在 content 属性中使用了某些浏览器不支持的分割符可能会导致页面在这些浏览器中无法发送跳转。

受影响的浏览器

IE6 IE7 IE8 Opera 支持 "分号" 和 "空格" 做分隔符。
Firefox 支持 "分号" 、 "逗号" 和 "空格" 做分隔符。
Chrome Safari 支持 "分号" 和 "逗号" 做分隔符。

问题分析

通过 META 元素可以控制页面定时跳转。

分析以下代码:

main.html

<iframe src="metaref1.htm"></iframe><br />
<iframe src="metaref2.htm"></iframe><br />
<iframe src="metaref3.htm"></iframe>

metaref1.htm

<meta http-equiv="refresh" content="3  url=http://www.google.cn/intl/zh-CN/images/logo_cn.gif">

metaref2.htm

<meta http-equiv="refresh" content="3, url=http://www.google.cn/intl/zh-CN/images/logo_cn.gif">

metaref3.htm

<meta http-equiv="refresh" content="3; url=http://www.google.cn/intl/zh-CN/images/logo_cn.gif">

主页面main.html中包含三个 IFRAME 元素,分别引入页面 "metaref1.htm" , "metaref2.htm" 及 "metaref3.htm" 。这三个页面唯一的区别就是 META 元素内的 content 属性中跳转时间及跳转 URL 之间的间隔符。

下面在各浏览器中打开main.html观察3秒后 IFRAME 页是否可以正常的跳转到谷歌 logo 的图片地址:

  IE Opera Chrome Safari Firefox
第一个IFRAME:空格分割 跳转 不跳转 跳转
第二个IFRAME:逗号分割 不跳转 跳转 跳转
第三个IFRAME:分号分割 跳转 跳转 跳转

可以看到,

  • Chrome Safari 对于空格分割跳转时间及跳转 URL 这种写法不予跳转;
  • IE Opera 对于逗号分割跳转时间及跳转 URL 这种写法不予跳转;
  • Firefox 对于这三种的写法均会跳转。

通过 WebKit 内核及 Firefox 源代码我们可以看清楚浏览器对于 content 内容的处理:

WebKit 内核:/WebCore/platform/network/HTTPParsers.cpp

bool parseHTTPRefresh(const String& refresh, bool fromHttpEquivMeta, double& delay, String& url)
{
    int len = refresh.length();
    int pos = 0;

    if (!skipWhiteSpace(refresh, pos, fromHttpEquivMeta))
        return false;

    //',' and ';' is acceptable.
    while (pos != len && refresh[pos] != ',' && refresh[pos] != ';')
        ++pos;
    ...
}

Firefox:/docshell/base/nsDocShell.cpp

nsresult
nsDocShell::SetupRefreshURIFromHeader(nsIURI * aBaseURI,
                                      const nsACString & aHeader)
{
    ...
        // skip any remaining whitespace
        while (iter != doneIterating && nsCRT::IsAsciiSpace(*iter))
            ++iter;

        // skip ';' or ','
        if (iter != doneIterating && (*iter == ';' || *iter == ',')) {
            ++iter;
        }

        // skip whitespace
        while (iter != doneIterating && nsCRT::IsAsciiSpace(*iter))
            ++iter;
    ...
}

解决方案

1. 参照 W3C 的建议,使用服务端进行页面跳转。

2. 使用合法的,所有浏览器均支持的写法:

<meta http-equiv="refresh" content="3; url=http://www.google.cn/intl/zh-CN/images/logo_cn.gif">

参见

知识库

相关问题

测试环境

操作系统版本: Windows 7 Ultimate build 7600
浏览器版本: IE6
IE7
IE8
Firefox 3.6
Chrome 5.0.342.2 dev
Safari 4.0.4
Opera 10.50
测试页面: main.html
本文更新时间: 2010-06-21

关键字

Meta http-equiv refresh URL 跳转