javascript - 如何将基于 Msxml2.XMLHTTP 的仅适用于 IE 的网站转换为也能在 Firefox 上运行?
这是一个仅限 IE 的网站,我想用其他浏览器访问,比如 Firefox:
https://golestan.sbu.ac.ir/Forms/AuthenticateUser/login.htm
我被迫为我的大学使用这个网站。它使用 Msxml2.XMLHTTP,这是一个仅限 IE 的功能。我尝试将其转换为 XMLHttpRequest,这样它只在 Firefox 上工作。这是我创建的 Greasemonkey 脚本。现在它不再报错,但也无法运行。所有函数都来自网站的原始脚本,但它们已更改以便与 XMLHttpRequest 一起使用。如果弹出登录脚本,我可以接受。我该如何调试这个 JavaScript?
// ==UserScript==
// @name Golestan Login
// @namespace sbu.ac.ir
// @include https://golestan.sbu.ac.ir/Forms/AuthenticateUser/login.htm
// @version 1
// @grant none
// ==/UserScript==
var isInternetExplorer = 0;
function check(){
var x;
if (window.XMLHttpRequest) {
x = new XMLHttpRequest();
} else {
try {
x = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
x = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
x = false;
}
}
}
x.open("HEAD",document.location,true);
x.send();
var sd=new Date(x.getResponseHeader('Last-Modified'));
var cd=new Date(document.lastModified);
if(sd-cd>3660000){
document.cookie = "reloading=1";
window.location.reload(true);
return false;
}
return true;
}
function a(){
for (k = 0; k < nall; k++) {
td = document.createElement('TD');
td.className = 'e';
Pr.appendChild(td);
}
if (!check()) {
//window.open("/_Templates/howtoclearcache.htm","_blank");
//top.close();
return;
}
var aCookie = document.cookie.split("; ");
var cook=0;
for (var i=0; i < aCookie.length; i++)
{
var aCrumb = aCookie[i].split("=");
if ("reloading" == aCrumb[0]) {
cook=unescape(aCrumb[1]);
break;
}
}
var ind=0;
for( i=0;i<all.length;i=i+2){
if(all[i+1]==1)
for(j=0;j<4;j++){
var r;
if (window.XMLHttpRequest) {
r = new XMLHttpRequest();
} else {
try {
r = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
r = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
r = false;
}
}
}
r.open("GET", all[i]+imstat[j]+".gif", true);
if(cook==1) r.setRequestHeader('If-Modified-Since','Sat,01 Jan 2000 00:00:00 GMT');
getobj(r,ind++);
}
else{
var r;
if (window.XMLHttpRequest) {
r = new XMLHttpRequest();
} else {
try {
r = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
r = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
r = false;
}
}
} r.open("GET", all[i], true);
if(cook==1) r.setRequestHeader('If-Modified-Since','Sat,01 Jan 2000 00:00:00 GMT');
getobj(r,ind++);
}
}
document.cookie = "reloading=0; expires=Fri, 31 Dec 1999 23:59:59 GMT;";
}
function main_DoFSCommand(command, args) {
var mainObj = document.all.main;
//
// Place your code here.
//
document.getElementById("rdir").style.visibility = "hidden";
if(command != "showmenu")
if(command == "Animation_Complete")
{
var x = 0;
var y = 0;
x = main.clientHeight/2 - 300;
y = main.clientWidth/2 - 400;
document.getElementById("iframeNews").style.top = x + 120;
document.getElementById("iframeNews").style.left = y + 264;
modifySrc();
document.getElementById("iframeNews").style.visibility = "visible";
}
else
{
if(command == "Enter")
{
bal('main');
}
else if(command == "Education")
{
bal('test');
}
else
document.getElementById("iframeNews").style.visibility = "hidden";
}
}
// http://stackoverflow.com/questions/21271997
addJS_Node (check);
addJS_Node (a);
addJS_Node (main_DoFSCommand);
isInternetExplorer=true;
function addJS_Node (text, s_URL, funcToRun, runOnLoad) {
var D = document;
var scriptNode = D.createElement ('script');
if (runOnLoad) {
scriptNode.addEventListener ("load", runOnLoad, false);
}
scriptNode.type = "text/javascript";
if (text) scriptNode.textContent = text;
if (s_URL) scriptNode.src = s_URL;
if (funcToRun) scriptNode.textContent = '(' + funcToRun.toString() + ')()';
var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
targ.appendChild (scriptNode);
}
我认为这项工作值得做,因为成千上万的用户,即大学生,会受到影响。
更新:我们可能能够更进一步,访问 main.htm。所以,我为这个页面写了另一个脚本。但是,最后我得到了 ReferenceError: element is not defined[了解更多]。
// ==UserScript==
// @name Golestan Main
// @namespace sbu.ac.ir
// @include https://golestan.sbu.ac.ir/Forms/AuthenticateUser/main.htm
// @version 1
// @grant none
// ==/UserScript==
// Microsoft WebService Behavior (Predecessor of modern AJAX)
// Information: https://web.archive.org/web/20060101200359/https://msdn.microsoft.com/workshop/author/webservice/webservice.asp
// JavaScript version: https://raw.githubusercontent.com/nzakas/professional-javascript/master/edition1/ch17/webservice.htc
// NOTE: You should paste the Javascript code from the above URL here
// end Microsoft WebService Behavior
function l(){
useService("../f0241_process_authexit/authexit.asmx?WSDL", "get");
// useService("authuser.asmx?WSDL", "get");
mt = new MainTit(document,titH);
mt.Maxi();
t = new Tab(document,titH,0,document.body.clientWidth,document.body.clientHeight-titH);
t.maintitle=mt;
OpenFaci('صفحه اصلي','nav.htm?fid=0;1&tck='+'&'+location.search.replace('?',''));
mt.HideGTit();
KeysValues = location.search.split(/[\?&]+/);
for (i = 0; i < KeysValues.length; i++) {
KeyValue = KeysValues[i].split("=");
if (KeyValue[0] == "CSURL") {
CSURL = KeyValue[1];
break;
}
}
}
function ex(ltck,tck,u,si,ft,fid,sess){
var co = createCallOptions();
co.funcName = "ex";
co.async = false;
// callService(function(result){if(result.error){/*alert(result.errorDetail.string);*/}},"ex",ltck,tck,u,si,ft,fid,sess);
callService(co,ltck,tck,u,si,ft,fid,sess);
}
addJS_Node (l);
addJS_Node (ex);
addJS_Node(ErrDetail);
addJS_Node(postError);
addJS_Node(returnError);
addJS_Node(createCallOptions);
addJS_Node(createUseOptions);
addJS_Node(cloneObject);
addJS_Node(ensureVBArray);
addJS_Node(encb64hlp);
addJS_Node(decb64hlp);
addJS_Node(encb64);
addJS_Node(decb64);
addJS_Node(ensureWsdlUrl);
addJS_Node(allocCall);
addJS_Node(fnShowProgress);
addJS_Node(isSimpleType);
addJS_Node(isPrimitive);
addJS_Node(getSdl);
addJS_Node(processService);
addJS_Node(onImportLoaded);
addJS_Node(loadImports);
addJS_Node(invokeNext);
addJS_Node(callNext);
addJS_Node(getAttrib);
addJS_Node(getBaseName);
addJS_Node(getQualifier);
addJS_Node(getNextNsq);
addJS_Node(getUniqueNsq);
addJS_Node(parseSimpleType);
addJS_Node(parseType);
addJS_Node(parseArrayType);
addJS_Node(parseComplexType);
addJS_Node(parseAttrib);
addJS_Node(parseElem);
addJS_Node(parseSoapHeader);
addJS_Node(expBase);
addJS_Node(parseSchemas);
addJS_Node(parseSdl);
addJS_Node(ensureXmlHttp);
addJS_Node(encodeHeader);
addJS_Node(_invoke);
addJS_Node(callService);
addJS_Node(useService);
addJS_Node(getMsg);
addJS_Node(fixupDT);
addJS_Node(encTZ);
addJS_Node(encodePrimitive);
addJS_Node(bldJsAry);
addJS_Node(getNextIndexAry);
addJS_Node(vbArrayToJs);
addJS_Node(encodeArray);
addJS_Node(encodeVar);
addJS_Node(getArySize);
addJS_Node(get1stAryItem);
addJS_Node(getAryItemFromIndex);
addJS_Node(getSchema);
addJS_Node(getArySizeInfo);
addJS_Node(encodeAttrib);
addJS_Node(serPart);
addJS_Node(getWrap);
addJS_Node(encodeArgs);
addJS_Node(returnResult);
addJS_Node(decTZ);
addJS_Node(applyTZ);
addJS_Node(decDate);
addJS_Node(decTime);
addJS_Node(decodePrimitive);
addJS_Node(getAryInfo);
addJS_Node(decodeArray);
addJS_Node(decodeAryItem);
addJS_Node(getAryElem);
addJS_Node(decodeElem);
addJS_Node(decodeType);
addJS_Node(processResult);
addJS_Node(hideProgress);
addJS_Node(getResult);
function addJS_Node (text, s_URL, funcToRun, runOnLoad) {
var D = document;
var scriptNode = D.createElement ('script');
if (runOnLoad) {
scriptNode.addEventListener ("load", runOnLoad, false);
}
scriptNode.type = "text/javascript";
if (text) scriptNode.textContent = text;
if (s_URL) scriptNode.src = s_URL;
if (funcToRun) scriptNode.textContent = '(' + funcToRun.toString() + ')()';
var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
targ.appendChild (scriptNode);
}
答案#1
需要关心的事情
该网站在 HEAD 请求中使用了 xhr(async:false)。这是已弃用的
你可以在这里阅读更多关于这个的内容 https://xhr.spec.whatwg.org/
主要声明是
在工作线程之外的同步 XMLHttpRequest 正在从网络平台中被逐步移除,因为它对最终用户的体验有不利影响。(这是一个需要多年的长期过程。)当前全局对象为 Window 对象时,开发者不得为 async 参数传递 false。强烈建议用户代理在开发者工具中对这种用法发出警告,并且在发生时可能尝试抛出 InvalidAccessError 异常。
所以,把它改为 true。
然后使用 @run-at document-end。
我创建了一个可以为你完成这项工作的脚本。
我使用的方法,
从网站复制了整个脚本代码并进行了必要的修改。
在用户脚本中,移除 script 元素并将更改后的脚本注入到网页中。
它将如下面所示更改页面。但似乎所有来自服务器的 td 元素都是空的。
你可以在这里看到网络传输
这是用户脚本
// ==UserScript==
// @name golestan
// @namespace Sagar V
// @author Sagar V
// @include https://golestan.sbu.ac.ir/Forms/AuthenticateUser/login.htm
// @version 1
// @grant none
// @run-at document-end
// ==/UserScript==
(function(){
var script=document.createElement('script');
script.innerHTML=`c=0;
Ip="/_Images/";ip="/_images/";tp="/_Templates/";scp="/_Scripts/";stp="/_styles/";Stp="/_Styles/";ap="/Forms/AuthenticateUser/";
all =new Array(
'/blank.htm',0,
scp+'printTemplate.htm?tck=r',0,
stp+'comm_butt2.htc',0,
stp+'select.htc',0,
stp+'simplegrid.htc',0,
stp+'validation.htc',0,
stp+'webservice.htc',0,
Stp+'helpStyle.css',0,
Stp+'winlessmovable.htc',0,
stp+'main.css',0,
stp+'MenuStyle.css',0,
stp+'Toolb.htc',0,
stp+'npui.css',0,
ap+'Message.XSLT',0,
ap+'Golestan.htm',0,
ap+'NewsPage.htm',0,
ap+'LoginPage.htm',0,
ap+'TopPage.htm',0,
ap+'main.htm',0,
tp+'Commander.htm',0,
tp+'Message_Page.htm',0,
tp+'help.htm',0,
scp+'Commander.js',0,
scp + 'npobj.js', 0,
scp + 'faci.js', 0,
scp+'Forms1_5.js',0,
scp+'help.js',0,
scp + 'Message.js', 0,
scp + 'npnfwin.js', 0,
'/_scripts/jqnpsrv.js', 0,
'/_scripts/npgrd.js', 0,
scp + 'Forms1_5_npgrid.js', 0,
Ip+'Status_OK.gif',0,
ip+'tabs.png',0,
ip+'ftabs.png',0,
ip+'corner.png',0,
ip+'c1.png',0,
ip+'jqnpgridicons.png',0,
'/Forms/F0202_PROCESS_REP_FILTER/command.htm',0);
nall=0;
for(k=0;k<all.length;k=k+2){
if(all[k+1]==1)nall=nall+4;
else nall++;
}
imstat=new Array('','_clicked','_focus','_disable');
function check(){
var x=new XMLHttpRequest() || new ActiveXObject("MSXML2.XMLHTTP");
x.open("HEAD",document.location,true);
x.send();
var sd=new Date(x.getResponseHeader('Last-Modified'));
var cd=new Date(document.lastModified);
if(sd-cd>3660000){
//alert('با توجه به تغييرات جديد سيستم ، جهت مشاهده کامل صفحات لطفا فايل هاي ذخيره شده در مرورگر خودرا حذف کنيد');
document.cookie = "reloading=1";
window.location.reload(true);
return false;
}
return true;
}
function a(){
for (k = 0; k < nall; k++) {
td = document.createElement('TD');
td.className = 'e';
Pr.appendChild(td);
}
if (!check()) {
//window.open("/_Templates/howtoclearcache.htm","_blank");
//top.close();
return;
}
var aCookie = document.cookie.split("; ");
var cook=0;
for (var i=0; i < aCookie.length; i++)
{
var aCrumb = aCookie[i].split("=");
if ("reloading" == aCrumb[0]) {
cook=unescape(aCrumb[1]);
break;
}
}
var ind=0;
for( i=0;i<all.length;i=i+2){
if(all[i+1]==1)
for(j=0;j<4;j++){
var r=new XMLHttpRequest() || new ActiveXObject("MSXML2.XMLHTTP");
r.open("GET", all[i]+imstat[j]+".gif", true);
if(cook==1) r.setRequestHeader('If-Modified-Since','Sat,01 Jan 2000 00:00:00 GMT');
getobj(r,ind++);
}
else{
var r=new XMLHttpRequest() || new ActiveXObject("MSXML2.XMLHTTP");
r.open("GET", all[i], true);
if(cook==1) r.setRequestHeader('If-Modified-Since','Sat,01 Jan 2000 00:00:00 GMT');
getobj(r,ind++);
}
}
document.cookie = "reloading=0; expires=Fri, 31 Dec 1999 23:59:59 GMT;";
}
function getobj(o,ind){
o.onreadystatechange=function(){
if(o.readystate==4){
Pr.cells(c).className="f";
c++;
if(c==nall){
if (location.search){
top.location = "main.htm" + location.search ;
}
else
top.location="main.htm";
}
}
}
o.send();
}`;
//alert(script);
document.getElementsByTagName('script')[0].parentNode.removeChild(document.getElementsByTagName('script')[0]);
document.head.appendChild(script);
})();
或者
直接从Github安装它
答案#2
遗憾的是,为 IE 构建的 JavaScript 重型 Web 应用程序很可能包含的不仅仅是用于 XMLHttpRequests 的 IE 特定内容。使用 ActiveXObject 来发起 XMLHttpRequests 也意味着 JavaScript 是为非常旧版本的 IE 编写的,因为标准的 XmlHttpRequest 对象自 IE7 起就存在。因此,做好最坏的准备!
对于在 Firefox 中使所有对 new ActiveXObject("MSXML.HttpRequest") 的调用都能工作的特定问题,你可以在你的 Greasemonkey 脚本中使用以下内容:
window.ActiveXObject = function(type) {
switch(type.toUpperCase()) {
case "MSXML2.XMLHTTP":
case "MICROSOFT.XMLHTTP":
return new XMLHttpRequest();
break;
default:
console.log("Unknown ActiveXObject type: ", type);
}
}
我用你提供的例子测试了这个,我注意到 JavaScript 测试的是 .readystate,而不是 .readyState!
进一步的 Greasemonkey 修补可以绕过这个问题:
Object.defineProperty(XMLHttpRequest.prototype, "readystate", {
get: function() { return this.readyState; }
});
下一个问题是 JavaScript 将 TableRow 的 cells 集合作为函数来使用……因此:
Object.defineProperty(HTMLTableRowElement.prototype, "cells", {
get: function() { return function(index) {
return this.querySelectorAll('td')[index];
};
}
})
如果事情还没有感觉失控,页面就会完成并跳转到“main.html”,在那里事情会变得更加有趣。
因为,它包含了这个非常麻烦的过去的回声:
<div id="service" style="display:none" style="behavior:url(/_styles/webservice.htc)"></div>
微软 CSS 行为!!! 大约在 15 年前,这些非常流行。
如果你认为达到这一点已经很糟糕,那么要进一步下去,将需要比我有时间更多的耐心。我确实看了一下 webservice.htc 文件,里面有大量需要逆向工程来编写脚本的内容,仅针对一个 Stack Overflow 问题就是如此。
我很抱歉我没能为你解决这个问题!
与其将时间投入到那上面,我个人宁愿接受通过 VirtualBox 在 Linux 上运行 IE,并使用 IE 虚拟机。

