XmlHttpRequest学习笔记 (4) 解析Xml时的安全性

上一次我们说到XmlHttpRequest可以用来解析Xml,这样对解析网络中的Xml数据提供了很大的便利,不过也带来了一些问题。比如当Xml数据规模过大,就可能造成脚本运行速度慢,停止响应等问题……

碰到这种情况,我们可以使用responseXml中的一些属性来解决,比如

MaxElementDepth

这个属性可以控制需要解析的Xml数据的深度,比如形如<a><b/></a>的Xml的深度为2,如果此时MaxElementDepth所设置的值为1,XmlHttpRequest就会拒绝解析这个Xml,以达到防止客户端停止响应的目的。来看下面的代码:

由于设置了MaxElementDepth属性,responseXML会报告parseError: "系统错误: MaxElementDepth"

类似作用的属性还有:

  • ResolveExternals / AllowDocumentFunction:是否允许加载外部的Xml文件
  • AllowXsltScript:是否允许在XSLT运行自定义的Javascript脚本
  • MaxXMLSize:所允许最大的Xml文件的大小
  • ProhibitDTD:是否允许Xml中包含DTD (Document Type Definition)
需要注意的是,这些属性需要在send()之前设置,但是不能在open()之前设置,因为open()方法会在内部创建出responseXML对象;而send()方法被调用之后,就开始加载XML了,那时候再去设置,已经来不及了……

XmlHttpRequest学习笔记 (3) 解析Xml

和其它的http组件不同的是,XmlHttpRequest提供了自动的Xml解析:

responseXML方法

当服务器返回的数据是Xml格式的话,Xmlhttp会自动尝试用其自带的responseXML属性来解析它。responseXML实际上是一个IXMLDOMDocument对象,你可以使用IXMLDOMDocument所提供的方法来操作这个Xml。也就是说,当Xml解析出问题的时候,你可以使用responseXML.parseError来查询错误信息;否则就可以通过比如selectNodes之类的方法来查询Xml的内容。比如,下面的代码演示了如何查询leonax.net的RSS,并且打印出每一条blog的标题和链接:

输出结果如下:

试用传说中的ifttt @ http://leonax.net/p/3022/ifttt-trial/
三国杀——山扩展 @ http://leonax.net/p/3016/sanguosha-shan-ex/
China Joy 2011 @ http://leonax.net/p/3011/china-joy-2011/
在PowerShell中获取当前运行脚本的路径 @ http://leonax.net/p/3005/getting-location-of-executing-script-in-powershell/
美少女特攻队 Sucker Punch 2011 @ http://leonax.net/p/3000/sucker-punch-2011/
个人博客在国内的访问加速 @ http://leonax.net/p/2997/acceleration-of-personal-blog-from-mainland/
iPhone 5,我们能期待些什么? @ http://leonax.net/p/2989/what-can-we-expect-in-iphone-5/
学车笔记 (二) 倒桩 @ http://leonax.net/p/2986/notes-for-driving-study-2/
活埋 Buried 2010 @ http://leonax.net/p/2983/buried-2010/
美少女的谎言 Pretty Little Liars 2010 @ http://leonax.net/p/2979/pretty-little-liars-2010/

在命令行中以管理员权限启用应用程序

自从Vista带来了UAC之后,应用程序就变成了两种,有管理员权限的,和没有管理员权限的。一些老的应用程序会莫名其妙地出错,这时候就要考虑右击应用程序,然后“以管理员身份运行”。这还不是什么大问题,exe文件的右键菜单里都会有这个,但是对于一些脚本文件(cmd, js一类)来说,就没那么方便了。通常需要重新开一个带管理员权限的命令行窗口,然后打很多cd回到刚的文件夹,然后再运行脚本,相当麻烦。

搜了一下,找到一个解决办法。把下面的代码保存为Elevate.js:

以后要以管理员身份运行程序的时候,只要输入“Elevate <exefile> <arguments>”就可以了,比如“Elevate cmd /k”。

当然,这个逃不过UAC的检查,还是会有一个对话框弹出来要点“确定”的。

XmlHttpRequest学习笔记 (2) 基本操作

XmlHttpRequest里面常用的函数和属性无非就这几个:

其中method的值多数为Get或者Post(不区分大小写)用于从服务器获取数据和向服务器发送数据,还有Head, Put, Delete之类的,基本不会用到;url是实际要访问的url地址,比如http://leonax.net;async的值为true或者false,表示是否要以异步模式(即非阻塞模式)进行通信;user和password为访问url所需的用户名和密码,一般都是省略掉的。

open函数只是初始化一下Xmlhttp对象,它并不会向url所对应的服务器发送数据。比较奇怪的是,W3C的规范中async的缺省值为true,也就是说,以下代码会以异步模式运行:

Msxml3和IE的XmlHttpRequest遵循了这一规范,而Msxml6中的缺省值为false。既然缺省值都为true,为什么不把参数名改成sync呢?在Javascript(以及各种脚本语言)中,缺省参数一般为null,而null和false等价,所以把缺省值定为true实在是太令人费解了。

真正把数据发出去的是这个函数。text可以是任何值,它会被当作数据包的正文发给服务器。

在open之前调用send会报错。

以异步模式open之后,send函数会立刻返回;相反,在同步模式的时候,它会等到接收完服务器所有的回应才返回。

responseText

这是一个属性,在收到服务器的回复之后,可以通过它来查看回复的正文部分。如:

将显示出一个很简易的Html :P。在未完全收到回复之前,responseText返回一个空字符串。

XmlHttpRequest学习笔记 (1) 创建

XmlHttpRequest是一个用于在网页中读取服务器数据的组件。最初是由微软开发用来访问Outlook Web Access 2000的。在目前流行的IE版本中都支持(从IE5到IE9),只不过问题是这个东东目前还没有成为标准(W3C正在讨论,只有一个draft可作参考),于是就有了万恶的浏览器兼容性的问题。常见的生成XmlHttpRequest对象的Javascript是这么写的:

在IE7之前,IE中的XmlHttpRequest组件都是由Msxml提供的。尽管Msxml目前有很多版本(从3.0到6.0都是被支持的),但只有3.0是从Win2000到Vista都带的,6.0只在XP SP3和Vista以之后的操作系统中有,而且3.0有个好处是创建的时候只要写"Msxml.Xmlhttp"即可,不用像6.0一样加上后缀的版本号。当然6.0在安全和性能方面都要比3.0好,大有取而代之的趋势。

Javascript 学习心得

这几天做 Ajax,顺便研究了一下 Javascript,发现以前对 Javascript 是完全不了解=.=

总结如下(以下简称 Js):

1、Js 中没有 Class,只有 Function,一个 Function 可以看成一个类的构造函数,new Function 即 new Class。每个 Function 有一个对象prototype,new Function 的时候,自动把这个 Function 的 prototype 复制到新的对象中。

2、Function 中可以使用 this 关键字,指代的是包含这个 Function 的类,不过 this 是动态绑定的,比如

运行结果是 y。这种模式在 Lua 中见过,如果要让运行结果是 x,要对 x.a 做一个 Binder,显示指定 this 为 x,并调用 a.x.apply(obj, ...)。

3、Js 中没有继承,要实现继承的功能,有 N 种比较猥琐的方法。一种是在新的对象中放一个 base 指针,指向它的父类。还有一种是复制 prototype。不过看上去都很恶心。以前看过 Lua 中有一种继承的方法是做一个索引表,调用函数的时候查找它父类的函数,不过 Js 不支持运算符重载=.=

4、Js 中唯一的网络组件是 XMLHttpRequest,在 IE 7 和 Firefox 中可用,IE 6 要用 new ActiveXObject("Msxml2.XMLHTTP")。XMLHttpRequest 可以产生一个异步通讯的线程,是 Ajax 的主要工具之一。线程的管理依赖于浏览器,具体的说明可以看 Ray 的一篇文章

5、Js 中数值 0 等价于 false,也就是 if (0) {} 等价于 if (false) {},在写 Array.Contains 的时候总算明白了为什么 Lua 中 0 不等价于 false,因为 Array.Contains 可以返回 null 表示没有找到,而调用的时候可以写 If (obj.Contains(val)) {},而不用写 if (obj.Contains(val) != null){},但是 Js 中就只有写后一种了 =.=

6、Js 中有 delete 关键字,但不是用来进行垃圾回收的,只能用来在类中删除一个元素。垃圾回收是自动的。

7、Js 中有很多保留字(因为 ECMA 规范的缘故),比如 class,IE 7 会认为 var class = 0 是错误而停止执行。

8、Firefox 中的 String 重载了 [] 运算符,等价于 charAt,但这不是标准。

9、Js 和 Java 同宗,N 多相似的地方,比如 Date 中月份从 0 开始,0 表示一月;String 是不可变类;函数的命名和 Java 几乎完全相同。

10、Firefox 下不允许修改 Object.prototype,而 IE 下可以。

先写到这,以后再补……