The Right Way of Intercepting Javascript Function Calls - javascript

I am writing a browser extension for the popular video chatting platform, Omegle.
The extension needs access to internal events of the omegle app. The app uses Mootools for firing events, and creates a new global object (COMETBackend) that inherits the Events class of mootools. I am trying to intercept function calls to the fireEvent function of the COMETBackend object, by injecting this code into the DOM:
let proxy = COMETBackend.prototype.fireEvent;
COMETBackend.prototype.fireEvent = function (...args) {
console.log(...args)
return proxy(...args);
}
Events Class from Mootools.js
var Events = new Class({
$events: {},
addEvent: function(c, b, a) {
c = Events.removeOn(c);
if (b != $empty) {
this.$events[c] = this.$events[c] || [];
this.$events[c].include(b);
if (a) {
b.internal = true;
}
}
return this;
},
addEvents: function(a) {
for (var b in a) {
this.addEvent(b, a[b]);
}
return this;
},
fireEvent: function(c, b, a) {
c = Events.removeOn(c);
if (!this.$events || !this.$events[c]) {
return this;
}
this.$events[c].each(function(d) {
d.create({
bind: this,
delay: a,
"arguments": b
})();
}, this);
return this;
},
removeEvent: function(b, a) {
b = Events.removeOn(b);
if (!this.$events[b]) {
return this;
}
if (!a.internal) {
this.$events[b].erase(a);
}
return this;
},
removeEvents: function(c) {
var d;
if ($type(c) == "object") {
for (d in c) {
this.removeEvent(d, c[d]);
}
return this;
}
if (c) {
c = Events.removeOn(c);
}
for (d in this.$events) {
if (c && c != d) {
continue;
}
var b = this.$events[d];
for (var a = b.length; a--; a) {
this.removeEvent(d, b[a]);
}
}
return this;
}
});
COMETBackend Object from Omegle.js
var COMETBackend = new Class({
Implements: [Options, Events],
initialize: function(a) {
this.setOptions(a),
this.clientID = null,
this.stopped = !1
}....
Now, in the console, the interception seems to have worked as i get the event logs i needed, but omegle for some reason is not responding to those events now, so the interception seems to have broken app's functionality.
Any ideas as to why that happened? am i not intercepting the calls properly?

Related

Javascript Get Selected Text: Incorrect number of lines

I am using the following code
(function(e, t) {
"use strict";
var n = t.selection;
var i = t.getSelection;
var o = i || n;
var r = function(e) {
var t = Object.prototype.toString.call(e);
return typeof e === "object" && /^\[object (HTMLCollection|NodeList|Object)\]$/.test(t) && e.hasOwnProperty("length") && (e.length === 0 || typeof e[0] === "object" && e[0].nodeType > 0)
};
var c = function(e, t) {
var n;
return function() {
var i = this,
o = arguments;
var r = function() {
n = null;
e.apply(i, o)
};
clearTimeout(n);
n = setTimeout(r, t)
}
};
var s = function(t, n) {
this.element = t;
this.callback = n || function() {};
this.isTouch = "ontouchstart" in e;
this.hasLib = e.jQuery && t instanceof e.jQuery || e.Zepto && t instanceof e.Zepto
};
s.prototype = {
events: function() {
var e = this.callback;
var t = this.getText;
this[this.isTouch ? "bindTouch" : "bindMouseUp"](function() {
e(t())
})
},
getText: function() {
var n = "";
if (i) {
n = e.getSelection().toString()
} else if (t.selection && t.selection.type !== "Control") {
n = t.selection.createRange().text
}
return n
},
checkForSelections: function(e, t, n) {
var i;
var o = function(e) {
var n = t();
var i = setInterval(function() {
if (t() !== n) {
e(t());
n = t()
} else if (t() === "") {
clearInterval(i)
}
}, 100)
};
var r = function() {
e.removeEventListener("touchend", c, false);
e.addEventListener("touchend", c, false);
if (i) {
clearInterval(i)
}
i = setInterval(function() {
var e = t();
if (e !== "") {
n(e);
c();
o(n)
}
}, 100)
};
var c = function() {
clearInterval(i);
e.removeEventListener("touchend", c, false)
};
e.addEventListener("touchstart", r, false)
},
bindTouch: function(e) {
var t = this.checkForSelections;
var n = this.getText;
if (this.hasLib) {
this.element.each(function() {
t(this, n, e)
});
return
}
var i = function(i) {
t(i, n, e)
};
if (!r(this.element)) {
i(this.element);
return
} [].forEach.call(this.element, function(e) {
i(e)
})
},
bindMouseUp: function(e) {
if (this.hasLib) {
this.element.on("mouseup", c(e, 150));
return
}
var t = function(t) {
t.addEventListener("mouseup", c(e, 150), false)
};
if (!r(this.element)) {
t(this.element);
return
} [].forEach.call(this.element, function(e) {
t(e)
})
}
};
e.selecting = function(e, t) {
if (!o) {
return
}
new s(e, t).events()
}
})(window, document);
And :
var myElement = document.body;
window.selecting(myElement, function(selector) {
var text = selector;
instance.publishState("text", text);
});
to basically get the selected/highlighted text by the user in the browser. I then use the selected text to work with it, make API calls etc.
Getting the selected text is fine, but unfortunately the number of lines in the returned text is usually incorrect which makes it impossible for me to work with.
Let me give you an example:
The user highlights the following text on the page:
Hello this is a test
Hello this is another test
The returned value from my code however than displays this text but with more line breaks in between. So for example I get returned:
Hello this is a test
Hello this is another test
This completely breaks my functionality, as I have to exactly know how many line breaks there actually are in order to work with the text. Any ideas what could be wrong or how I can access the browsers selected text with the correct number of line breaks?
The code
window.getSelection().toString()
will return the correct selection, which will produce in your case
Hello this is a test\n\nHello this is another test
Notice how you have two \n corresponding to the 2 newlines you have.
So if you do anything like this to display what the user has selected:
console.dir(window.getSelection().toString());
You will see correctly what the user has selected
Hello this is a test
Hello this is another test

javascript decoding webpackJsonp to readable code

there is a way to change this code into a clear and readable code ?
(window.webpackJsonp=window.webpackJsonp||[]).push([[7],{"2wwy":function(n,t,e){n.exports=e("nhzr")},E8gZ:function(n,t,e){var o=e("jmDH"),i=e("w6GO"),r=e("NsO/"),u=e("NV0k").f;n.exports=function(n){return function(t){for(var e,c=r(t),a=i(c),f=a.length,s=0,l=[];f>s;)e=a[s++],o&&!u.call(c,e)||l.push(n?[e,c[e]]:c[e]);return l}}},f0Zw:function(n,t,e){"use strict";e.r(t);var o=e("q1tI"),i=e.n(o),r=e("/MKj"),u=e("2wwy"),c=e.n(u),a=e("G4qV"),f=Object(a.a)((function(n){return n.g_notifications}),(function(n){return c()(n)})),s=e("F7NL"),l=e("kOwS"),p=e("qNsG"),v=e("CnBM"),w=e.n(v)()({loader:function(){return Promise.all([e.e(0),e.e(6)]).then(e.bind(null,"OyQA"))},loading:function(){return null},modules:["Notification"]}),b=i.a.createElement,d=function(n){var t=n.notifications,e=n.onRemove;return b(i.a.Fragment,null,t.map((function(n){var t=n.id,o=Object(p.a)(n,["id"]);return b(w,Object(l.a)({onRemove:e},o,{key:t,id:t}))})))},O=i.a.createElement,m=Object(r.b)((function(n){return{notifications:f(n)}})),j=function(n){var t=n.dataset.id;Object(s.b)(t)},g=m((function(n){var t=n.notifications;return O(d,{onRemove:j,notifications:t})}));t.default=g},fW1p:function(n,t,e){var o=e("Y7ZC"),i=e("E8gZ")(!1);o(o.S,"Object",{values:function(n){return i(n)}})},nhzr:function(n,t,e){e("fW1p"),n.exports=e("WEpk").Object.values}}]);
This looks like output from Webpack 4.
If the site you're looking at exposes source maps, you will see a section under sources in your browser's dev tools labelled "Webpack", which will contain the source for the scripts bundled using Webpack.
If the site doesn't expose source maps, the first step is to format the code. You can then start manually renaming variables as you figure out what they do. In this case, there must be more scripts on the site because there seem to be references to modules not defined in the file.
Passing this code through Prettier gives:
(window.webpackJsonp = window.webpackJsonp || []).push([
[7],
{
"2wwy": function(n, t, e) {
n.exports = e("nhzr");
},
E8gZ: function(n, t, e) {
var o = e("jmDH"),
i = e("w6GO"),
r = e("NsO/"),
u = e("NV0k").f;
n.exports = function(n) {
return function(t) {
for (var e, c = r(t), a = i(c), f = a.length, s = 0, l = []; f > s; )
(e = a[s++]), (o && !u.call(c, e)) || l.push(n ? [e, c[e]] : c[e]);
return l;
};
};
},
f0Zw: function(n, t, e) {
"use strict";
e.r(t);
var o = e("q1tI"),
i = e.n(o),
r = e("/MKj"),
u = e("2wwy"),
c = e.n(u),
a = e("G4qV"),
f = Object(a.a)(
function(n) {
return n.g_notifications;
},
function(n) {
return c()(n);
}
),
s = e("F7NL"),
l = e("kOwS"),
p = e("qNsG"),
v = e("CnBM"),
w = e.n(v)()({
loader: function() {
return Promise.all([e.e(0), e.e(6)]).then(e.bind(null, "OyQA"));
},
loading: function() {
return null;
},
modules: ["Notification"]
}),
b = i.a.createElement,
d = function(n) {
var t = n.notifications,
e = n.onRemove;
return b(
i.a.Fragment,
null,
t.map(function(n) {
var t = n.id,
o = Object(p.a)(n, ["id"]);
return b(w, Object(l.a)({ onRemove: e }, o, { key: t, id: t }));
})
);
},
O = i.a.createElement,
m = Object(r.b)(function(n) {
return { notifications: f(n) };
}),
j = function(n) {
var t = n.dataset.id;
Object(s.b)(t);
},
g = m(function(n) {
var t = n.notifications;
return O(d, { onRemove: j, notifications: t });
});
t.default = g;
},
fW1p: function(n, t, e) {
var o = e("Y7ZC"),
i = e("E8gZ")(!1);
o(o.S, "Object", {
values: function(n) {
return i(n);
}
});
},
nhzr: function(n, t, e) {
e("fW1p"), (n.exports = e("WEpk").Object.values);
}
}
]);
finding yourself in this is almost impossible, I mean that the result of decoding was on this principle:
var func = {
init: function() {
console.log('test');
this.set();
},
set: function(){
$('.body .test').innerHTML = 'test';
}
}
func.init();
easy and legible

What does 'function(){ return this }()' do as an argument?

Taken from nanoajax (https://github.com/yanatan16/nanoajax). Why not just pass in this, what does the self execution function returning this do?
!function(e, t) {
function n() {
if (t.XMLHttpRequest) return new t.XMLHttpRequest;
try {
return new t.ActiveXObject("MSXML2.XMLHTTP.3.0")
} catch (e) {}
}
t.nanoajax = e, e.ajax = function(e, t, r) {
r || (r = t, t = null);
var u = n();
return u ? (u.onreadystatechange = function() {
4 == u.readyState && r(u.status, u.responseText)
}, t ? (u.open("POST", e, !0), u.setRequestHeader("X-Requested-With", "XMLHttpRequest"), u.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")) : u.open("GET", e, !0), void u.send(t)) : r(new Error("no request"))
}
}({}, function() { return this }());
It ensures the argument is really the global object (window in a browser or root on node/iojs), which could be different if this in the external scope weren't.
Example :
function A(){
}
A.prototype.doIt = function(){
!function(a){
console.log(a);
}(function() { return this }()); // passing this would pass the instance of A
};
(new A).doIt();
Here, passing this would not pass the global object.
Note that this code is the product of an automated minification operation.

What is the meaning of e.fn in this code

I am looking at this javascript code from the quojs library:
(function() {
var e;
e = function() {
var e, t, n;
t = [];
e = function(t, r) {
var i;
if (!t) {
return n()
} else if (e.toType(t) === "function") {
return e(document).ready(t)
} else {
i = e.getDOMObject(t, r);
return n(i, t)
}
};
n = function(e, r) {
e = e || t;
e.__proto__ = n.prototype;
e.selector = r || "";
return e
};
e.extend = function(e) {
Array.prototype.slice.call(arguments, 1).forEach(function(t) {
var n, r;
r = [];
for (n in t) {
r.push(e[n] = t[n])
}
return r
});
return e
};
n.prototype = e.fn = {};
return e
}();
which comes before this:
(function () {
(function (e) {
var t, n, r, i, u, a;
r = "parentNode";
t = /^\.([\w-]+)$/;
n = /^#[\w\d-]+$/;
i = /^[\w-]+$/;
e.query = function (e, r) {
var u;
r = r.trim();
if (t.test(r)) {
u = e.getElementsByClassName(r.replace(".", ""))
} else if (i.test(r)) {
u = e.getElementsByTagName(r)
} else if (n.test(r) && e === document) {
u = e.getElementById(r.replace("#", ""));
if (!u) {
u = []
}
} else {
u = e.querySelectorAll(r)
}
if (u.nodeType) {
return [u]
} else {
return Array.prototype.slice.call(u)
}
};
e.fn.find = function (t) {
I am trying to understand the meaning of e.fn.
I see that fn is not a reserved word. I think that e is just the name given to the event object passed as a parameter. So what is the meaning of e.fn? Is the code assuming that whatever is passed as e has a property called fn? Or is fn some kind of abbreviation that references the function?
Whatever is passed as e should have a property called fn. I would search the rest of the code for "fn" and see what you come up with.

What is the best practice to make an object in JS like this: T('isArray')([]) == T.run('isArray')([]) == T().run('isArray')?

What is the best practice to make an object in JavaScript like this, knowing T is the main object:
T('isArray')([])
T.run('isArray')([])
T().run('isArray')([])
T('isArray', [])
T.run('isArray', [])
T().run('isArray', [])
They all must use the same function.
Since the main object can be called it must be a function. The function should decide what to return based on the arguments:
var T = (function() {
var functions = { // define functions that can be run like isArray
isArray: function(a) {
return Array.isArray(a);
},
log: function(a, b) {
console.log(a + b);
}
};
var noop = function() {}; // function doing nothing (no operation)
var T = function(f) {
if(arguments.length >= 2) { // function + args provided
return (functions[f] || noop) // call it
.apply(this, [].slice.call(arguments, 1));
} else if(arguments.length === 1) { // only function provided
return function() { // return function that can be called with args
return (functions[f] || noop)
.apply(this, arguments);
}
} else { // nothing provided, return T itself (so that e.g. T.run === T().run)
return T;
}
}
T.run = function() { // run function
return T.apply(this, arguments);
};
T.getState = function() { // another function
console.log("Not implemented");
};
return T; // actually return T so that it gets stored in 'var T'
})();
// tests
console.log(
T('isArray')([]),
T.run('isArray')([]),
T().run('isArray')([]),
T('isArray', []),
T.run('isArray', []),
T().run('isArray', [])
);
T('log')(1, 2);
T.getState();

Categories

Resources