Extending an ActiveXObject in javascript

后端 未结 4 611
遥遥无期
遥遥无期 2020-12-06 06:57

I want to add some functionality track certain calls to ActiveX object methods in javascript.

I usually create my activeX object like this: var tconn = new ActiveXO

相关标签:
4条回答
  • 2020-12-06 07:31

    The problem here is that it seems that IE wont allow saving of the original activXObject constructor and will give a stack overflow (;-) upon creating the ActualActiveXObject. it seems that this is special for the ActivX because it is working when doing that with other javascript objects.

    0 讨论(0)
  • 2020-12-06 07:35

    Thank you very much for your wrapper. With your help I was able to create a xmlrequest detector for IE and FF and the rest.

    I have added a version (combined from another example) that works for FF , IE and the rest of the gang,

    if(window.XMLHttpRequest)
    {
    var XMLHttpRequest = window.XMLHttpRequest;
    
    // mystery: for some reason, doing "var oldSend = XMLHttpRequest.prototype.send;" and 
    //  calling it at the end of "newSend" doesn't work...
    var startTracing = function () {
        XMLHttpRequest.prototype.uniqueID = function() {
            // each XMLHttpRequest gets assigned a unique ID and memorizes it 
            //  in the "uniqueIDMemo" property
            if (!this.uniqueIDMemo) {
                this.uniqueIDMemo = Math.floor(Math.random() * 1000);
            }
            return this.uniqueIDMemo;
        }
    
        // backup original "open" function reference
        XMLHttpRequest.prototype.oldOpen = XMLHttpRequest.prototype.open;
    
        var newOpen = function(method, url, async, user, password) {
            console.log("[" + this.uniqueID() + "] intercepted open (" + 
                        method + " , " + 
                        url + " , " + 
                        async + " , " + 
                        user + " , " + 
                        password + ")");
            this.oldOpen(method, url, async, user, password);
        }
    
        XMLHttpRequest.prototype.open = newOpen;
    
        // backup original "send" function reference
        XMLHttpRequest.prototype.oldSend = XMLHttpRequest.prototype.send;
    
        var newSend = function(a) {
            console.log("[" + this.uniqueID() + "] intercepted send (" + a + ")");
            var xhr = this;
            var onload = function() { 
                console.log("[" + xhr.uniqueID() + "] intercepted load: " + 
                        xhr.status + 
                        " " + xhr.responseText); 
            };
    
            var onerror = function() { 
                console.log("[" + xhr.uniqueID() + "] intercepted error: " + 
                        xhr.status); 
            };
    
            xhr.addEventListener("load", onload, false);
            xhr.addEventListener("error", onerror, false);
    
            this.oldSend(a);
        }
        XMLHttpRequest.prototype.send = newSend;
    }
    
    
    startTracing();
    }
    else if (window.ActiveXObject) {
    var ActualActiveXObject = ActiveXObject;
    
    var ActiveXObject = function(progid) {
        var ax = new ActualActiveXObject(progid);
    
        if (progid.toLowerCase() == "msxml2.xmlhttp") {
    
            var o = {
                _ax: ax,
                _status: "fake",
                responseText: "",
                responseXml: null,
                readyState: 0,
                status: 0,
                statusText: 0,
                onReadyStateChange: null
            };
            o._onReadyStateChange = function() {
                var self = o;
                return function() {
                self.readyState   = self._ax.readyState;
                if (self.readyState == 4) {
                    self.responseText = self._ax.responseText;
                    self.responseXml  = self._ax.responseXml;
                    self.status       = self._ax.status;
                    self.statusText   = self._ax.statusText;
                }
                    if (self.onReadyStateChange) self.onReadyStateChange();
                }
            }();
            o.open = function(bstrMethod, bstrUrl, varAsync, bstrUser, bstrPassword) {
                console.log("intercepted open (" + 
                    bstrMethod + " , " + 
                    bstrUrl + " , " + 
                    varAsync + " , " + 
                    bstrUser + " , " + 
                    bstrPassword + ")");
                varAsync = (varAsync !== false);
                this._ax.onReadyStateChange = this._onReadyStateChange
                return this._ax.open(bstrMethod, bstrUrl, varAsync, bstrUser, bstrPassword);
            };
            o.send = function(varBody) {
                return this._ax.send(varBody);
            };
        }
        else
            var o = ax;
        return o;
    }
    }
    
    0 讨论(0)
  • 2020-12-06 07:43

    A little fix for "The data necessary to complete this operation is not yet available" in IE6 - waiting for completeness before population of reponse properties:

    self.readyState   = self._ax.readyState;
     if (self.readyState == 4) {
      self.responseText = self._ax.responseText;
      self.responseXml  = self._ax.responseXml;
      self.status       = self._ax.status;
      self.statusText   = self._ax.statusText;
     }
     if (self.onReadyStateChange) self.onReadyStateChange();
    
    0 讨论(0)
  • 2020-12-06 07:46

    You can in fact override ActiveXObject().

    This means you can try to build a transparent proxy object around the actual object and hook on method calls. This would mean you'd have to build a proxy around every method and property your ActiveX object has, unless you are absolutely sure there is no code whatsoever calling a particular method or property.

    I've built a small wrapper for the "MSXML2.XMLHTTP" object. There are probably all kinds of problems you can run into, so take that with a grain of salt:

    var ActualActiveXObject = ActiveXObject;
    
    var ActiveXObject = function(progid) {
      var ax = new ActualActiveXObject(progid);
    
      if (progid.toLowerCase() == "msxml2.xmlhttp") {
        var o = {
          _ax: ax,
          _status: "fake",
          responseText: "",
          responseXml: null,
          readyState: 0,
          status: 0,
          statusText: 0,
          onReadyStateChange: null
          // add the other properties...
        };
        o._onReadyStateChange = function() {
          var self = o;
          return function() {
            self.readyState   = self._ax.readyState;
            self.responseText = self._ax.responseText;
            self.responseXml  = self._ax.responseXml;
            self.status       = self._ax.status;
            self.statusText   = self._ax.statusText;
            if (self.onReadyStateChange) self.onReadyStateChange();
          }
        }();
        o.open = function(bstrMethod, bstrUrl, varAsync, bstrUser, bstrPassword) {
          varAsync = (varAsync !== false);
          this._ax.onReadyStateChange = this._onReadyStateChange
          return this._ax.open(bstrMethod, bstrUrl, varAsync, bstrUser, bstrPassword);
        };
        o.send = function(varBody) {
          return this._ax.send(varBody);
        };
        // add the other methods...
      }
      else {
        var o = ax;
      }
    
      return o;
    }
    
    function Test() {
      var r = new ActiveXObject('Msxml2.XMLHTTP');
    
      alert(r._status);  // "fake"
    
      r.onReadyStateChange = function() { alert(this.readyState); };
      r.open("GET", "z.xml");
      r.send();
    
      alert(r.responseText);
    }
    

    Disclaimer: Especially the async/onReadyStateChange handling probably isn't right, and the code may have other issues as well. As I said, it's just an idea. Handle with care.

    P.S.: A COM object is case-insensitive when it comes to method- and property names. This wrapper is (as all JavaScript) case-sensitive. For example, if your code happens to call both "Send()" and "send()", you will need a skeleton "Send()" method in the wrapper as well:

    o.Send = function() { return this.send.apply(this, arguments); };
    
    0 讨论(0)
提交回复
热议问题