Skip to content

Instantly share code, notes, and snippets.

@ixs
Created September 5, 2019 10:23
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ixs/58381ed5f8109b6a988a2eb06036b348 to your computer and use it in GitHub Desktop.
Save ixs/58381ed5f8109b6a988a2eb06036b348 to your computer and use it in GitHub Desktop.
userscript adding the document.load() function in order to make legacy webinterfaces such as the Avocent PM3000 webinterface work again.
// ==UserScript==
// @name document.load client injection
// @namespace http://tampermonkey.net/
// @version 0.1
// @description The Avocent PM1000/2000/3000 PDU runs an old JavaScript interface that relies on the XMLDocument.fetch() function that has been removed. Emulate this.
// @description inject the document.load implementation into real page context.
// @author Andreas Thienemann <andreas@bawue.net>, based on a script from jnd@chromium.org, based on idea from gurreiro_fabio@yahoo.com.br
// @match http://172.16.10.64/*
// @match http://172.16.10.65/*
// @run-at document-start
// ==/UserScript==
var script_payload = `
// This script is for document.load client implementation
// The basic idea is that we write a load method for document object since
// WebKit based browser do not provide the document.load support.
// Author: jnd@chromium.org, based on idea from gurreiro_fabio@yahoo.com.br
// See crbug.com/988 for more details.
// window.chromeCompatUtils is the namespace of all utilities for
// Chrome compatibility
if (!window.chromeCompatUtils)
window.chromeCompatUtils = { };
chromeCompatUtils.UserMethodObject = function(targetObject,
userMethodName,
userMethod) {
this.userMethodName_ = userMethodName;
// This target object in which the user method will be installed.
this.installTargetObject_ = targetObject;
this.userMethod_ = userMethod;
this.oldMethod_ = null;
}
chromeCompatUtils.UserMethodObject.prototype.install = function() {
this.oldMethod_ = this.installTargetObject_[this.userMethodName_];
this.installTargetObject_[this.userMethodName_] = this.userMethod_;
}
chromeCompatUtils.UserMethodObject.prototype.uninstall = function() {
this.installTargetObject_[this.userMethodName_] = this.oldMethod_;
}
var loadMethod = new chromeCompatUtils.UserMethodObject(
window.Document.prototype,
"load",
function(url) {
var xhr = new window.XMLHttpRequest();
var currentLoadDoc = this;
var loadMethodEvents = { };
function processEvents(obj, events, isInstall) {
for (var eventName in events) {
if (isInstall)
obj.addEventListener(eventName, events[eventName], false);
else
obj.removeEventListener(eventName, events[eventName], false);
}
}
var internalOnLoad = function(isSync){
if (xhr && xhr.responseXML) {
var xhrDoc = xhr.responseXML;
// Copy and append new dom tree into current document.
var clonedNode = xhrDoc.documentElement.cloneNode(true);
var rootElement = currentLoadDoc.documentElement ?
currentLoadDoc.documentElement : currentLoadDoc;
rootElement.appendChild(clonedNode, true);
currentLoadDoc.parseError = false;
} else {
currentLoadDoc.parseError = true;
}
if (!isSync) {
processEvents(xhr, loadMethodEvents, false);
// Call document.onload if it exists.
if (currentLoadDoc.onload && typeof currentLoadDoc.onload == "function")
currentLoadDoc.onload();
}
};
var internalOnError = function(isSync) {
currentLoadDoc.parseError = true;
if (!isSync) {
processEvents(xhr, loadMethodEvents, false);
// Call document.onerror if it exists.
if (currentLoadDoc.onerror &&
typeof currentLoadDoc.onerror == "function")
currentLoadDoc.onerror();
}
};
loadMethodEvents["load"] = internalOnLoad;
loadMethodEvents["error"] = internalOnError;
try {
this.async = !!this.async;
if (this.async)
processEvents(xhr, loadMethodEvents, true);
xhr.open("GET", url, this.async);
xhr.send(null);
// For synchronous call, directly call internalOnLoad.
if (this.async)
this.parseError = false;
else
internalOnLoad(true);
} catch (e) {
internalOnError(!this.async);
}
return !this.parseError;
});
loadMethod.install();
`;
// At first, we need to get head tag, then we will inject the script under
// head tag.
(function() {
var injected_ = false;
function InjectDocLoad(head) {
if (injected_)
return;
injected_ = true;
var script = document.createElement("script");
script.type = "text/javascript";
script.charset = "utf-8";
// script.src = "http://repository.sys.bawue.net/tt/doc_load_impl.js";
script.appendChild(document.createTextNode(script_payload));
head.appendChild(script);
}
function GetHeadTag() {
var head = null;
try {
head = document.getElementsByTagName('head')[0];
} catch (e) {
head = null;
}
return head;
}
function headInsertedChecker() {
var head = GetHeadTag();
if (head) {
InjectDocLoad(head);
document.documentElement.removeEventListener("DOMNodeInserted",
headInsertedChecker,
false);
}
}
if (!document.documentElement) {
// should not happen.
return;
}
var head = GetHeadTag();
if (!head) {
document.documentElement.addEventListener("DOMNodeInserted",
headInsertedChecker,
false);
} else {
InjectDocLoad(head);
}
})();
@tjcomserv
Copy link

thank you sooooooo much.

@ixs
Copy link
Author

ixs commented Feb 25, 2024

@tjcomserv glad it helped. ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment