botguard interface: fix IITCs response handling - some minor changes, and a major change in server response processing

also added some additional error checks so changes in this area are less lkikely to send bad data to the niantic servers
This commit is contained in:
Jon Atkins 2015-01-29 14:51:29 +00:00
parent 0fd3fb94b2
commit a2eeedd0c6

View File

@ -4,35 +4,37 @@
iitc_bg = Object();
iitc_bg.init = function() {
// stock site - 'ud.g()' constructor
//function ud() {
// this.lb = {}; //a map, indexed by 'group-[ab]-actions', each entry containing an array of 'yd' objects (simple object, with 'gf' and 'cb' members). a queue of data to process?
// this.ya = {}; //a map, indexed by 'group-[ab]-actions', each entry containing an object with an 'invoke' method
// this.qc = {}; //a map, indexed by group, witn constructors for botguard
// this.cb = ""; // the 'key' - B
// this.gd = []; //the list of methods to protect
// stock site - 'ad.e()' constructor
//function Ad() {
// this.Eb = {}; // a map, indexed by 'group-[ab]-actions', each entry containing an array of 'yd' objects (simple object, with 'gf' and 'cb' members). a queue of data to process?
// this.Oa = {}; // a map, indexed by 'group-[ab]-actions', each entry containing an object with an 'invoke' method
// this.Zc = {}; // a map, indexed by group, witn constructors for botguard
// this.eb = ""; // the 'key' - B
// this.Kh = e; // e is defined in the main web page as "var e = function(w) {eval(w);};"
//}
var botguard_eval = e;
iitc_bg.data_queue = {}; //.lb - indexed by group
iitc_bg.instance_queue = {}; //.ya - indexed by group
iitc_bg.key = ""; //.cb
iitc_bg.botguard = {}; //.qc - indexed by key
iitc_bg.evalFunc = botguard_eval;
// stock site code
//ud.prototype.R = function(a, b, c) {
//// a==B, b==CS, c==window.niantic_params.botguard_protected_methods
// this.gd = c;
// vd(this, a);
// for (var d in b) if ("group-b-actions" == d || "group-a-actions" == d) {
// for (c = 0; c < b[d].length; ++c) xd(this, d, new yd(b[d][c], a));
// zd(this, d);
//Ad.prototype.U = function(a, b) {
// Bd(this, a);
// for (var c in b) if ("group-b-actions" == c || "group-a-actions" == c) {
// for (var d = 0; d < b[c].length; ++d) Dd(this, c, new Ed(b[c][d], a));
// Fd(this, c);
// }
//};
// and... a simple object that just holds onto it's parameters (the data - a - and the key - b)
//function yd(a, b) {
// this.gf = a;
// this.cb = b;
// and.. Ed - a simple object that holds it's parameters and the timestamp it was created
//function Ed(a, b) {
// var c = w();
// this.mg = a;
// this.eb = b;
// this.Ki = c;
//}
@ -67,12 +69,16 @@ iitc_bg.init = function() {
//TODO: better name - will do for now...
iitc_bg.push_queue = function(group, data, key) {
//stock site code
//function xd(a, b, c) {
//// a==this, b=="group-[ab]-actions", c==a 'yd' object (c.gf == botguard data, c.cb == key)
// var d = c.cb && a.qc[c.cb];
// if ("dkxm" == c.gf || d) a.lb[b] || (a.lb[b] = []), a.lb[b].push(c);
//a=='this', b==group-[ab]-actions, c==object with .mg==data, .eb==key, .Ki==current timestamp
//function Dd(a, b, c) {
// var d = c.eb && a.Zc[c.eb];
// if ("dkxm" == c.mg || d) a.Eb[b] || (a.Eb[b] = []), a.Eb[b].push(c);
//}
// Niantic have changed how the server returns data items to the client a few times, which cause
// bad non-string items to come into here. this breaks things badly
if (typeof data !== "string") throw "Error: iitc_bg.process_queue got dodgy data - expected a string";
var botguard_instance = iitc_bg.key && iitc_bg.botguard[iitc_bg.key];
if (data == "dkxm" || botguard_instance) {
@ -87,43 +93,42 @@ iitc_bg.push_queue = function(group, data, key) {
iitc_bg.process_key = function(key,serverEval) {
// stock site code
//function vd(a, b, c) {
//// a == the ud.g() singleton
//// b == the 'b' response from the server, or on init, the key
//// c == the 'a' response from the server (code to eval), or not set on init
// a.cb = b;
// if (!a.qc[b]) {
// var d = !1; //false
//function Bd(a, b, c) {
// if (a.Zc[b]) a.eb = b; else {
// var d = !0;
// if (c) try {
// eval(c);
// } catch (e) {
// d = !0; //true
// a.Kh(c);
// } catch (f) {
// d = !1;
// }
// d || (a.qc[b] = botguard.bg)
// d && (a.Zc[b] = botguard.bg, a.eb = b);
// }
//}
iitc_bg.key = key;
if (iitc_bg.botguard[key]) {
iitc_bg.key = key;
} else {
var noCatch = true;
if (!iitc_bg.botguard[key]) {
var caught = false;
if (serverEval) {
// server wants us to eval some code! risky, and impossible to be certain we can do it safely
// however... reports say that it only interacts with the botguard.bg code, so we might be fine just running it
// (but this is only when we don't send the correct params to the server? no reports of this code triggering yet...)
try {
console.warn('Server-generated javascript eval requested:\n'+serverExec);
debugger;
if (!confirm('The server asked IITC to run (eval) some javascript. This may or may not be safe. Run and continue?\n\nScript:\n'+serverEval)) { console.error('server javascript eval cancelled') } else
eval(serverEval);
iitc_bg.evalFunc(serverEval);
console.log('Server-generated javascript ran OK');
} catch(e) {
console.warn('Server-generated javascript - threw an exception');
console.warn(e);
caught = true;
noCatch = false;
}
}
if (!caught) {
if (noCatch) {
iitc_bg.botguard[key] = botguard.bg;
iitc_bg.key = key;
}
}
};
@ -131,23 +136,18 @@ console.warn(e);
//convert a method name to the group-[ab]-actions value, or return 'undefined' for no group
//NOTE: the stock code separates the 'in any group' and 'which group' test, but it's cleaner to combine them
//UPDATE: the 'not in any group' case was removed from the stock site logic
iitc_bg.get_method_group = function(method) {
//stock site
//function wd(a) {
// return -1 != Rf.indexOf(a) ? "group-a-actions" : "group-b-actions";
//function Cd(a) {
// return -1 != ig.indexOf(a) ? "group-a-actions" : "group-b-actions";
//}
//NOTE: stock site has separate test for 'is any group' - IITC combines it into this one function that returns
// undefined for no group
// if (window.niantic_params.botguard_protected_methods.indexOf(method) != -1) {
if (window.niantic_params.botguard_group_a_methods.indexOf(method) != -1) {
return "group-a-actions";
} else {
return "group-b-actions";
}
// }
// // method is not of any group
// return undefined;
if (window.niantic_params.botguard_group_a_methods.indexOf(method) != -1) {
return "group-a-actions";
} else {
return "group-b-actions";
}
};
@ -164,14 +164,12 @@ iitc_bg.extra_request_params = function(method) {
};
iitc_bg.get_request_data = function(method) {
//function Cd(a, b) {
////a==this, b==method
// if (-1 == a.gd.indexOf(b)) return "";
// var c = "mxkd", d = wd(b); //d==group
// a.ya[d] && 0 < a.ya[d].length && a.ya[d].shift().invoke(function(a) {
//function Id(a, b) {
// var c = "mxkd", d = Cd(b);
// a.Oa[d] && 0 < a.Oa[d].length && a.Oa[d].shift().invoke(function(a) {
// c = a;
// });
// zd(a, d);
// Fd(a, d);
// return c;
//}
@ -181,9 +179,9 @@ iitc_bg.get_request_data = function(method) {
return "";
}
// this seems to be some kind of 'flag' string - and is either "mkxd" or "dkxm". it can be returned from the
// this seems to be some kind of 'flag' string - and is either "mxkd" or "dkxm". it can be returned from the
// server, so we stick with the same string rather than something more sensibly named
var data = "mkxd";
var data = "mxkd";
if (iitc_bg.instance_queue[group] && iitc_bg.instance_queue[group].length > 0) {
var instance = iitc_bg.instance_queue[group].shift();
@ -192,6 +190,15 @@ iitc_bg.get_request_data = function(method) {
iitc_bg.process_queue(group);
if (data.indexOf('undefined is not a function') != -1) {
// there's been cases of something going iffy in the botguard code, or IITC's interface to it. in this case,
// instead of the correct encoded string, the data contains an error message along the lines of
// "E:undefined is not a function:TypeError: undefined is not a function"[...]
// in this case, better to just stop with some kind of error than send the string to the server
debugger;
throw ('Error: iitc_bg.get_request_data got bad data - cannot safely continue');
}
return data;
};
@ -209,16 +216,15 @@ iitc_bg.dummy_botguard.prototype.invoke = function(callback) {
iitc_bg.process_queue = function(group) {
//stock site
//function zd(a, b) {
////a==singleton, b==group
// if (a.lb[b]) for (; 0 < a.lb[b].length; ) {
// var c = a.lb[b].shift(), d = c.gf, e = c.kh + 7195e3, f;
// "dkxm" == d ? f = new Sf : x() < e && (f = new a.qc[c.cb](d));
// if (f) {
//function Fd(a, b) {
// if (a.Eb[b]) for (; 0 < a.Eb[b].length; ) {
// var c = a.Eb[b].shift(), d = c.mg, f = c.Ki + 717e4, g;
// "dkxm" == d ? g = new jg : w() < f && (g = new a.Zc[c.eb](d));
// if (g) {
// c = a;
// d = b;
// c.ya[d] || (c.ya[d] = []);
// c.ya[d].push(f);
// c.Oa[d] || (c.Oa[d] = []);
// c.Oa[d].push(g);
// break;
// }
// }
@ -232,7 +238,7 @@ iitc_bg.process_queue = function(group) {
if (item.data == "dkxm") {
obj = new iitc_bg.dummy_botguard;
} else if (Date.now() < item.time + 7195000) {
} else if (Date.now() < item.time + 7170000) {
obj = new iitc_bg.botguard[item.key](item.data);
}
@ -248,38 +254,49 @@ iitc_bg.process_queue = function(group) {
iitc_bg.process_response_params = function(method,data) {
// stock site: response processing
//rd.prototype.Xg = function(a, b) {
//yd.prototype.vi = function(a, b) {
// var c = b.target;
// if (Yc(c)) {
// this.Rb.reset();
// var d = a.df, e = JSON.parse($c(c)), f = ud.g(), g = a.getMethodName(), k = e.a, l = e.b, q = e.c;
////e==json response, f==singleton, g==method name, k==response.a, l==response.b, q=responce.c
// -1 != f.gd.indexOf(g) && (l && k && vd(f, l, k), g = wd(g), q && l && xd(f, g, new yd(q, l)), f.ya[g] && 0 != f.ya[g].length || zd(f, g));
// "error" in e && "out of date" == e.error ? (d = J.g(), Ad(!1), d.Ne = !0, Bd("Please refresh for the latest version.")) : n.setTimeout(ma(d, e), 0);
// } else this.Rb.ac = !0, d = a.Ze, u(d) && (e = {
// error: Zc(c) || "unknown",
// if (cd(c)) {
// this.Ib.reset();
// var d = a.hg, f = JSON.parse(ed(c));
// if (f.c && 0 < f.c.length) {
// var g = Ad.e(), h = a.getMethodName(), l = f.a, m = f.b, r = f.c[0];
// m && l && Bd(g, m, l);
// h = Cd(h);
// if (r && m && 0 < r.length) for (l = 0; l < r.length; ++l) Dd(g, h, new Ed(r[l], m));
// g.Oa[h] && 0 != g.Oa[h].length || Fd(g, h);
// }
// "error" in f && "out of date" == f.error ? (d = rd.e(), Gd(!1), d.ie = !0, Hd("Please refresh for the latest version.")) : "error" in f && "RETRY" == f.error ? (this.Da.ja(1, a), td(this.Ib)) : n.setTimeout(pa(d, f), 0);
// } else this.Ib.Ec = !0, d = a.cg, ha(d) && (f = {
// error: dd(c) || "unknown",
// respStatus: c.getStatus()
// }, n.setTimeout(ma(d, e), 0));
// d = this.Vd;
// d.oa.remove(c) && d.Wb(c);
// }, n.setTimeout(pa(d, f), 0));
// d = this.Te;
// d.Aa.remove(c) && d.zc(c);
//};
var group = iitc_bg.get_method_group(method);
if (data.c && data.c.length > 0) {
if (group) {
if (data.b && data.a) {
// NOTE: in this case, we *EVAL* the 'data.a' string returned by the server
// there is the risk this is not safe to do in IITC, or will otherwise just fail to run usefully
// in this case, we *EVAL* the 'data.a' string from the server!
// however, it's not a case that's been ever triggered in normal use, as far as I know
iitc_bg.process_key(data.b, data.a);
}
if (data.c && data.b) {
//c is an ARRAY of entries to push. do them all
for (var i=0; i<data.c.length; i++) {
iitc_bg.push_queue(group, data.c[i], data.b);
var group = iitc_bg.get_method_group(method);
//NOTE: I missed a change here a while ago. originally data.c was a single-level array of items to push on the queue,
//but now it's a two-dimensional array, and it's only index zero that's used!
var data_items = data.c[0];
if (data_items && data.b && data_items.length > 0) {
for (var i=0; i<data_items.length; i++) {
iitc_bg.push_queue(group, data_items[i], data.b);
}
}
if (iitc_bg.instance_queue[group].length == 0) {
if (iitc_bg.instance_queue[group] && iitc_bg.instance_queue[group].length == 0) {
iitc_bg.process_queue(group);
}