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 = Object();
iitc_bg.init = function() { iitc_bg.init = function() {
// stock site - 'ud.g()' constructor // stock site - 'ad.e()' constructor
//function ud() { //function Ad() {
// 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.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.ya = {}; //a map, indexed by 'group-[ab]-actions', each entry containing an object with an 'invoke' method // this.Oa = {}; // 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.Zc = {}; // a map, indexed by group, witn constructors for botguard
// this.cb = ""; // the 'key' - B // this.eb = ""; // the 'key' - B
// this.gd = []; //the list of methods to protect // 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.data_queue = {}; //.lb - indexed by group
iitc_bg.instance_queue = {}; //.ya - indexed by group iitc_bg.instance_queue = {}; //.ya - indexed by group
iitc_bg.key = ""; //.cb iitc_bg.key = ""; //.cb
iitc_bg.botguard = {}; //.qc - indexed by key iitc_bg.botguard = {}; //.qc - indexed by key
iitc_bg.evalFunc = botguard_eval;
// stock site code // stock site code
//ud.prototype.R = function(a, b, c) { //Ad.prototype.U = function(a, b) {
//// a==B, b==CS, c==window.niantic_params.botguard_protected_methods // Bd(this, a);
// this.gd = c; // for (var c in b) if ("group-b-actions" == c || "group-a-actions" == c) {
// vd(this, a); // for (var d = 0; d < b[c].length; ++d) Dd(this, c, new Ed(b[c][d], a));
// for (var d in b) if ("group-b-actions" == d || "group-a-actions" == d) { // Fd(this, c);
// for (c = 0; c < b[d].length; ++c) xd(this, d, new yd(b[d][c], a));
// zd(this, d);
// } // }
//}; //};
// and... a simple object that just holds onto it's parameters (the data - a - and the key - b) // and.. Ed - a simple object that holds it's parameters and the timestamp it was created
//function yd(a, b) { //function Ed(a, b) {
// this.gf = a; // var c = w();
// this.cb = b; // this.mg = a;
// this.eb = b;
// this.Ki = c;
//} //}
@ -67,12 +69,16 @@ iitc_bg.init = function() {
//TODO: better name - will do for now... //TODO: better name - will do for now...
iitc_bg.push_queue = function(group, data, key) { iitc_bg.push_queue = function(group, data, key) {
//stock site code //stock site code
//function xd(a, b, c) { //a=='this', b==group-[ab]-actions, c==object with .mg==data, .eb==key, .Ki==current timestamp
//// a==this, b=="group-[ab]-actions", c==a 'yd' object (c.gf == botguard data, c.cb == key) //function Dd(a, b, c) {
// var d = c.cb && a.qc[c.cb]; // var d = c.eb && a.Zc[c.eb];
// if ("dkxm" == c.gf || d) a.lb[b] || (a.lb[b] = []), a.lb[b].push(c); // 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]; var botguard_instance = iitc_bg.key && iitc_bg.botguard[iitc_bg.key];
if (data == "dkxm" || botguard_instance) { if (data == "dkxm" || botguard_instance) {
@ -87,43 +93,42 @@ iitc_bg.push_queue = function(group, data, key) {
iitc_bg.process_key = function(key,serverEval) { iitc_bg.process_key = function(key,serverEval) {
// stock site code // stock site code
//function vd(a, b, c) { //function Bd(a, b, c) {
//// a == the ud.g() singleton // if (a.Zc[b]) a.eb = b; else {
//// b == the 'b' response from the server, or on init, the key // var d = !0;
//// 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
// if (c) try { // if (c) try {
// eval(c); // a.Kh(c);
// } catch (e) { // } catch (f) {
// d = !0; //true // 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) { if (serverEval) {
// server wants us to eval some code! risky, and impossible to be certain we can do it safely // 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 // 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 { try {
console.warn('Server-generated javascript eval requested:\n'+serverExec); console.warn('Server-generated javascript eval requested:\n'+serverExec);
debugger; 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 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'); console.log('Server-generated javascript ran OK');
} catch(e) { } catch(e) {
console.warn('Server-generated javascript - threw an exception'); console.warn('Server-generated javascript - threw an exception');
console.warn(e); console.warn(e);
caught = true; noCatch = false;
} }
} }
if (!caught) { if (noCatch) {
iitc_bg.botguard[key] = botguard.bg; 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 //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 //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) { iitc_bg.get_method_group = function(method) {
//stock site //stock site
//function wd(a) { //function Cd(a) {
// return -1 != Rf.indexOf(a) ? "group-a-actions" : "group-b-actions"; // 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) {
if (window.niantic_params.botguard_group_a_methods.indexOf(method) != -1) { return "group-a-actions";
return "group-a-actions"; } else {
} else { return "group-b-actions";
return "group-b-actions"; }
}
// }
// // method is not of any group
// return undefined;
}; };
@ -164,14 +164,12 @@ iitc_bg.extra_request_params = function(method) {
}; };
iitc_bg.get_request_data = function(method) { iitc_bg.get_request_data = function(method) {
//function Cd(a, b) { //function Id(a, b) {
////a==this, b==method // var c = "mxkd", d = Cd(b);
// if (-1 == a.gd.indexOf(b)) return ""; // a.Oa[d] && 0 < a.Oa[d].length && a.Oa[d].shift().invoke(function(a) {
// var c = "mxkd", d = wd(b); //d==group
// a.ya[d] && 0 < a.ya[d].length && a.ya[d].shift().invoke(function(a) {
// c = a; // c = a;
// }); // });
// zd(a, d); // Fd(a, d);
// return c; // return c;
//} //}
@ -181,9 +179,9 @@ iitc_bg.get_request_data = function(method) {
return ""; 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 // 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) { if (iitc_bg.instance_queue[group] && iitc_bg.instance_queue[group].length > 0) {
var instance = iitc_bg.instance_queue[group].shift(); var instance = iitc_bg.instance_queue[group].shift();
@ -192,6 +190,15 @@ iitc_bg.get_request_data = function(method) {
iitc_bg.process_queue(group); 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; return data;
}; };
@ -209,16 +216,15 @@ iitc_bg.dummy_botguard.prototype.invoke = function(callback) {
iitc_bg.process_queue = function(group) { iitc_bg.process_queue = function(group) {
//stock site //stock site
//function zd(a, b) { //function Fd(a, b) {
////a==singleton, b==group // if (a.Eb[b]) for (; 0 < a.Eb[b].length; ) {
// if (a.lb[b]) for (; 0 < a.lb[b].length; ) { // var c = a.Eb[b].shift(), d = c.mg, f = c.Ki + 717e4, g;
// var c = a.lb[b].shift(), d = c.gf, e = c.kh + 7195e3, f; // "dkxm" == d ? g = new jg : w() < f && (g = new a.Zc[c.eb](d));
// "dkxm" == d ? f = new Sf : x() < e && (f = new a.qc[c.cb](d)); // if (g) {
// if (f) {
// c = a; // c = a;
// d = b; // d = b;
// c.ya[d] || (c.ya[d] = []); // c.Oa[d] || (c.Oa[d] = []);
// c.ya[d].push(f); // c.Oa[d].push(g);
// break; // break;
// } // }
// } // }
@ -232,7 +238,7 @@ iitc_bg.process_queue = function(group) {
if (item.data == "dkxm") { if (item.data == "dkxm") {
obj = new iitc_bg.dummy_botguard; 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); 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) { iitc_bg.process_response_params = function(method,data) {
// stock site: response processing // stock site: response processing
//rd.prototype.Xg = function(a, b) { //yd.prototype.vi = function(a, b) {
// var c = b.target; // var c = b.target;
// if (Yc(c)) { // if (cd(c)) {
// this.Rb.reset(); // this.Ib.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; // var d = a.hg, f = JSON.parse(ed(c));
////e==json response, f==singleton, g==method name, k==response.a, l==response.b, q=responce.c // if (f.c && 0 < f.c.length) {
// -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)); // var g = Ad.e(), h = a.getMethodName(), l = f.a, m = f.b, r = f.c[0];
// "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); // m && l && Bd(g, m, l);
// } else this.Rb.ac = !0, d = a.Ze, u(d) && (e = { // h = Cd(h);
// error: Zc(c) || "unknown", // 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() // respStatus: c.getStatus()
// }, n.setTimeout(ma(d, e), 0)); // }, n.setTimeout(pa(d, f), 0));
// d = this.Vd; // d = this.Te;
// d.oa.remove(c) && d.Wb(c); // 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) { if (data.b && data.a) {
// NOTE: in this case, we *EVAL* the 'data.a' string returned by the server // in this case, we *EVAL* the 'data.a' string from the server!
// there is the risk this is not safe to do in IITC, or will otherwise just fail to run usefully // 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); iitc_bg.process_key(data.b, data.a);
} }
if (data.c && data.b) {
//c is an ARRAY of entries to push. do them all var group = iitc_bg.get_method_group(method);
for (var i=0; i<data.c.length; i++) {
iitc_bg.push_queue(group, data.c[i], data.b); //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); iitc_bg.process_queue(group);
} }