Bug分析之画蛇添足的htmlEncode

href="file:///C:/DOCUME~1/SULIN~1.ZTG/LOCALS~1/Temp/msohtml1/01/clip_filelist.xml" rel="File-List" />

    在html中,有些字符是用于做特殊标记的,比如“<”。当需要在界面上显示这些字符时,就需要用另外一种方法来表示,比如“<”要表示为“&lt;”。只要知道了html中各个符号替代字符串,写一个这样的函数算不上什么难事,可是有人却偏偏画蛇添足,并把添了足的代码放到了网上,结果使很多网站出错。

 

这段代码被放在一个名为《一些非常有用的Java常用方法》的帖子中。这个帖子被广泛转载,可以在很多技术网站找到它。不过因为很多网站自身可能也使用了帖子中的代码,所以这些网站都无法把这个帖子正确地表现出来。在我找了很久之后,终于找到了这帖子的本来面目。我现在把这帖子的原始内容贴出来,再把那些出错了的网站的中,该帖子的内贴出来,做个对比。希望CSDN没使用这个画蛇添足的htmlEncode,否则就对比出不来原始内容了。

 

原帖中的htmlEncode函数如下(代码1Java语言,下同):

 

String htmlEncode(String txt)

{

   txt = replace(txt,"&","& amp;");

  txt = replace(txt,"& amp;amp;","& amp");

  txt = replace(txt,"& amp;quot;","& quot;");  

  txt = replace(txt,"/"","& quot;"); 

  txt = replace(txt,"& amp;lt;","& lt;"); 

  txt = replace(txt,"<","& lt;"); 

  txt = replace(txt,"& amp; gt;","& gt;"); 

  txt = replace(txt,">","& gt;"); 

  txt = replace(txt,"& amp;nbsp;","& nbsp"); 

  txt = replace(txt," ","& nbsp"); 

  return txt; 

}


 

使用Google搜到的大多网站上的帖子中,该函数的内容如下(代码2):

 

String htmlEncode(String txt){

  txt = replace(txt,"&","&");

  txt = replace(txt,"& amp;","&");

  txt = replace(txt,"& quot;","/"");

  txt = replace(txt,"/"",""");

  txt = replace(txt,"& lt;","<");

  txt = replace(txt,"<","<");

  txt = replace(txt,"& gt;",">");

  txt = replace(txt,">",">");

  txt = replace(txt,"& nbsp;"," ");

  txt = replace(txt," "," ");

  return txt;

}

 

在这两段代码中replace是自定义的字符串内替换函数,这个我们先不管它。且看第二段代码中,有很多第2个参数和第3个参数相同的replace调用,不觉得很奇怪么?

 

在读过了很多这样奇怪代码的帖子之后,终于在一个网站上找到了正确的原始帖子,看到了这个htmlEncode函数的真面目,也就是代码1中的内容。

 

其实看代码1也有奇怪之处。按一般的想法,只要把“& < > / ”等这几个字符逐一替换成相应的替代字符串就可以了,怎么会有如txt = replace(txt,"&amp;amp;","&amp;");这样的语句呢?

 

后来一想,我明白了,作者是想让编码过的字符串不被重复编码。可能作者在程序的很多地方对字符串进行htmlEncode编码操作,他希望第一次编码后,其它的编码操作不再起作用,这样他只进行一次解码就可以还原原来的内容。

 

比如对字符串中的“&”,在进行第一次编码后,它将变为“&amp;”。在第二次编码时,在对“&”进行替换后,将把“&amp;”中的“&”再次换成“&amp;”,于是得到“&amp;amp;”。作者为了不重复编码,就在txt = replace(txt,"&","&amp;");语句之后,又加了一句txt = replace(txt,"&amp;amp;","&amp;");把内容再替换回来。

 

同理,后面的txt = replace(txt,"&amp;quot;","&quot;");等类似语句也是为了达到这个目的加上去的。

 

作者写完这个程序之后一定很得意:看我这个程序多好,不会重复编码,调用100htmlEncode也没关系,总能得到同一个结果!

 

可惜,这个结果并非总是正确的!试想,如果我想在网页上输出字符串"&amp;",正如要显示作者的这个帖子所需要的那样,在内容中直接显示"&amp;",问题来了:我对字符串"&amp;"调用htmlEncode之后,得到的还是"&amp;",我把"&amp;"放到html中时,页面上只会显示一个”&”,而不是"&amp;"。对于其它内容也一样,“&lt;”、“&lg;”、“&gt;”等这样的字符串都无法显示正确显示。

 

呵呵,这也正解释了为什么这么多网站会把作者的代码显示成代码2所示那样,因为他们都用了作者的程序。就拿作者帖子中的代码的第一句为例:

 

原文为:txt = replace(txt,"&","&amp;");

 

使用作者的算法对这段内容进行htmlEncode,得到:

 

txt = replace(txt, &quot;&amp; &quot;, &quot;&amp; &quot;);

 

前一个“&”被替换为“&amp;”,而第二个参数&amp;不变。把这段代码放在html中送到浏览器,正好显示为:

 

txt = replace(txt,"&","&");

 

代码中其它的那些第2、3参数相同的replace调用也都是因为这个原因。

 

一句话,作者想优化html编码的功能,结果画蛇添足。

 

把代码改成如下的形式,去掉那些“足”,就可以正确编码了:

 

String htmlEncode(String txt)

{

   txt = replace(txt,"&","& amp;"); 

  txt = replace(txt,"/"","& quot;"); 

  txt = replace(txt,"<","& lt;");

  txt = replace(txt,">","& gt;");

  txt = replace(txt," ","& nbsp;"); 

  return txt; 

}

 

从编程的角度看,这只是个画蛇添足的问题。如果换个角度,还有一些有意思的事情:

 

一、很多网站都使用了这段代码,并因此而无法正确显示作者的帖子,可见网络上错误信息的危害,并提醒大家在使用网络上的代码时,一定加倍小心。

 

二、这段代码自己的错误导致了网站无法正确显示这段代码本身,这也限制了这段代码的使用。这算是网络自然法则么:正确的事物得以发展,不正确的自取灭亡?

 

希望CSDN没有使用这样的代码,否则我这个文章的内容也无法显示了。如果您转帖了本文,请千万检查一下,贴过去之后,内容还能正确显示否!

 

作者:苏林

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值