这次原计划写些关于sahi的页面监视的内容,本来我的文章都在百度空间里,现在毕业了,就都搬过来了,前三篇baidu空间wcf1987都有。由于已经毕业了,东西遗失了一些,我就拿我论文中我自己仿造sahi实现的部分讲讲吧。注意:我的原理与sahi基本上一致(其实借鉴了很多。。。),但是sahi考虑了很多,特别是JavaScript在包括了ie与ff的不同,我就只专注了ie。
事件驱动模型的三大要素:事件源:能够接收外部事件的源体。侦听器:能够接收事件源通知的对象。事件处理程序:用于处理事件的对象。若要实现事件监听模块,需要给事件源注册侦听器。通常采用的方法是遍历页面上元素分别按照其类型注册侦听器。这种方法有个缺点:当页面元素很多时,如新浪网站有很多信息。这样页面加载时候就要一一为每个元素注册侦听器,会有所延迟。
在这里选择了一种巧妙的思路:考虑用户并不一定会浏览所有的信息,通常情况下是不会的。所以利用JavaScript里的注册侦听器方法,先给页面注册一个mouseover事件监听器。当用户想查看某条信息时,鼠标滑过时会执行mouseover的事件处理程序,在这个事件处理程序中加入对这个元素的注册函数,这样当用户执行某个动作时,如点击时,就能捕获用户的行为动作。
如图,Web首先调用了注入的JS文件中addHandlers方法,此方法给页面document对象添加了 this.addEvent(doc, "keyup", this.docEventHandler); this.addEvent(doc, "mousemove", this.docEventHandler)方法,同时重载了系统的函数window.alert;window.confirm;window.prompt; 添加了事件监听。
使得当用户执行了keyup或是mouseover动作之后就会产生一个事件(event),根据产生的事件得到触发该事件的元素—事件源,然后给这个元素注册相应的侦听器,即当发生特定类型的事件会触发相应的事件处理程序(在JavaScript中称事件句柄)。
统一的注册事件句柄的函数为attachEvents(t),针对特定文档元素的特定类型的事件如addEvent(el, "click",onEv); 这是给el对象注册了onclick事件,事件句柄为onEv。
当特定事件发生时,比如onclick发生,则可以得到发生事件的页面元素的name,id,value,文本,类型等,将其传递给AccessorInfo,得到处理后的字符串s,利用实现了ActiveXObject异步Post的sendToServer,发送结果到服务器。
最后需要指出的是,本文中采用的2级DOM中的高级事件处理,在该模型中,通过调用方法注册事件句柄,而不是设置HTML属性或JavaScript属性来注册事件句柄,所以可以给一个指定的对象的指定类型的事件注册多个事件句柄。从而不至于影响了页面原始的JavaScript代码。
效果图:
全部JS如下,sahi的我就不贴了。大家可以在sahi的htdocs\spr下找到,共有5个被注入到了网页,但是核心就一个concat.js。
function ice(){
this.real_confirm = window.confirm;
this.real_prompt = window.prompt;
this.real_alert = window.alert;
window.alert = function (s){
return fish.alertMock(s);
};
window.confirm = function (s){
return fish.confirmMock(s);
};
window.prompt = function (s){
return fish.promptMock(s);
};
//window.confirm = function (s){return fish.confirmMock(s)};
//window.prompt = function (s){return fish.promptMock(s)};
// window.print = function (s){return fish.printMock(s)};
}
ice.prototype.alertMock= function (s) {
this.real_alert(s);
var inp=document.getElementById("haha");
//inp.value=s;
var info= new AccessorInfo("null", "null", "alert", "null", "null");
var s=info.createPostString();
// alert(s);
// window.setTimeout("alert('"+s+"')",1000);
window.setTimeout("fish.sendToServer('"+s+"')",0);
// fish.sendToServer(s);
return;
}
ice.prototype.confirmMock= function (s) {
var boo=this.real_confirm(s);
var inp=document.getElementById("haha");
inp.value=boo;
//alert(boo);
var info= new AccessorInfo("null", "null", "confirm", "null", boo);
var s=info.createPostString();
// alert(s);
window.setTimeout("fish.sendToServer('"+s+"')",0);
// fish.sendToServer(s);
return;
}
ice.prototype.promptMock= function (s) {
var boo=this.real_prompt(s);
var inp=document.getElementById("haha");
inp.value=boo;
//alert(boo);
var info= new AccessorInfo("null", "null", "prompt", "null", boo);
var s=info.createPostString();
// alert(s);
window.setTimeout("fish.sendToServer('"+s+"')",0);
// fish.sendToServer(s);
return;
}
ice.prototype.getKnowedTags = function (src){
var el = src;
while (true) {
if (!el) return src;
if (!el.tagName || el.tagName.toLowerCase() == "html" || el.tagName.toLowerCase() == "body") return null;
var tag = el.tagName.toLowerCase();
if (tag == "a" || tag == "select" || tag == "img" || tag == "form" ||
tag == "input" ||
tag == "button" ||
tag == "textarea" ||
tag == "textarea" ||
tag == "td" ||
tag == "table" ||
((tag == "div" || tag == "span")) ||
tag == "label" ||
tag == "li") {
//alert("tag:"+el);
return el;
}
el = el.parentNode;
}
}
ice.prototype.addHandlers = function () {
var doc = document;
this.addEvent(doc, "keyup", this.docEventHandler);
this.addEvent(doc, "mousemove", this.docEventHandler);
}
ice.prototype.addEvent = function (el, ev, fn) {
el.attachEvent("on" + ev, fn);
}
ice.prototype.docEventHandler = function () {
var e = window.event;
var t =fish.getKnowedTags(e.srcElement);
if (t && !t.hasAttached && t.tagName) {
var tag = t.tagName.toLowerCase();
if (tag == "select"||tag == "a" || t.form || tag == "img" || tag == "div" || tag == "span" || tag == "li" || tag == "td" || tag == "table"
|| tag == "input" || tag == "textarea" || tag == "button") {
fish.attachEvents(t);
}
t.hasAttached = true;
}
}
ice.prototype.attachEvents = function (el) {
var tagName = el.tagName.toLowerCase();
if (tagName == "a") {
this.attachLinkEvents(el)
} else if (el.type) {
this.attachFormElementEvents(el);
} else if (tagName == "img" || tagName == "div" || tagName == "span" || tagName == "td" || tagName == "table" || tagName == "li") {
this.attachImageEvents(el);
}
}
ice.prototype.attachLinkEvents = function (el) {
this.addEvent(el, "click", this.onEv);
}
ice.prototype.attachFormElementEvents = function (el) {
var type = el.type;
if (el.onchange == this.onEv || el.onblur == this.onEv || el.onclick == this.onEv) return;
if (type == "text" || type == "file" || type == "textarea" || type == "password") {
this.addEvent(el, "change", this.onEv);
} else if (type == "select-one" || type == "select-multiple") {
fish.addEvent(el, "change", this.onEv);
} else if (type == "button" || type == "submit" || type == "reset" || type == "checkbox" || type == "radio" || type == "image") {
fish.addEvent(el, "click", this.onEv);
}
}
ice.prototype.attachImageEvents = function (el) {
this.addEvent(el, "click", this.onEv);
}
ice.prototype.onEv = function (e) {
e.cancelBubble=true;
var targ = fish.getKnowedTags(e.srcElement);
if (e.type == "click") {
if (targ.type) {
var type = targ.type;
if (type == "text" || type == "textarea" || type == "password"
|| type == "select-one" || type == "select-multiple") return;
}
}
var info = fish.getInfo(targ);
//alert(info.id);
//alert(info.name);
//alert(info.value);
//alert(info.type);
// alert(info.event);
var s=info.createPostString();
//alert(s);
fish.sendToServer(s);
}
ice.prototype.getInfo=function (el){
var type = el.type;
var tagLC = el.tagName.toLowerCase();
if (tagLC == "img") {
return new AccessorInfo(el.id, el.name, "img", "click",el.src);
} else if (type == "text" || type == "textarea" || type == "password") {
return new AccessorInfo(el.id, el.name, type, "setvalue", el.value);
} else if (type == "select-one" || type == "select-multiple") {
return new AccessorInfo(el.id, el.name, type, "setselected", el.value);
} else if (tagLC == "a") {
return new AccessorInfo(el.id, el.innerText, "link", "click" ,el.href);
} else if (type == "button" || type == "reset" || type == "submit" || type == "image") {
return new AccessorInfo(el.id, el.name, type, "click",el.value);
} else if (type == "checkbox" || type == "radio") {
return new AccessorInfo(el.id, el.name, type, "click", el.value);
} else if (type == "file") {
return new AccessorInfo(el.id, el.name, type, "setFile", el.value);
} else if (tagLC == "td") {
// return new AccessorInfo(el.id, el.name, "cell", "click", el.innerText);
} else if (tagLC == "div" || tagLC == "span") {
// return new AccessorInfo(el.id, el.name, "spandiv", "click", el.innerText);
} else if (tagLC == "label") {
// return new AccessorInfo(el.id, el.name, "label", "click", el.innerText);
} else if (tagLC == "li") {
// return new AccessorInfo(el.id, el.name, "listItem", "click", el.innerText);
}
}
var AccessorInfo = function (id, name, type, event, value) {
this.name=name;
this.id=id;
this.type = type;
this.event = event;
this.value = value;
}
function addPostParm(sp,paramname,paramvalue){
if(sp.length>0){
sp+="&icespy&";
}
if(paramvalue==null){
paramvalue="null";
}
if(paramvalue.length==null){
paramvalue="null";
}
if(paramvalue.length==0){
paramvalue="null"
}
//encodeURIComponent;
return sp+encodeURIComponent(paramname)+"="+encodeURIComponent(paramvalue);
}
AccessorInfo.prototype.createPostString=function(){
var s="";
s=addPostParm(s,"type",this.type);
s=addPostParm(s,"name",this.name);
s=addPostParm(s,"id",this.id);
s=addPostParm(s,"value",this.value);
s=addPostParm(s,"event",this.event);
return s;
}
ice.prototype. Create=function(){
var aSignal=("MSXML2.XMLHTTP.5.0");
var oRequest=new ActiveXObject(aSignal);
return oRequest;
}
ice.prototype.sendToServer=function (s){
var http=fish.Create();
http.open("post","icespy.test",false);
http.setRequestHeader("Content-Type","application/x-wwww-form-urlencoded");
http.send(s);
//alert(s);
return "sucess";
}