niantic have removed all munging from the network protocol, so update IITC to match

improvements could be made to our version handling (currently we just take their version string and assume it'll work, with no checks for changes - needs some thoughts on sensible handling)
This commit is contained in:
Jon Atkins 2014-05-30 22:42:00 +01:00
parent a05ac61cb4
commit a83688a4c2
7 changed files with 14 additions and 310 deletions

View File

@ -35,7 +35,7 @@ window.artifact.requestData = function() {
if (isIdle()) { if (isIdle()) {
artifact.idle = true; artifact.idle = true;
} else { } else {
window.postAjax('getArtifactInfo', {}, artifact.handleSuccess, artifact.handleError); window.postAjax('artifacts', {}, artifact.handleSuccess, artifact.handleError);
} }
} }

View File

@ -640,17 +640,6 @@ function boot() {
window.iitcLoaded = true; window.iitcLoaded = true;
window.runHooks('iitcLoaded'); window.runHooks('iitcLoaded');
if (!haveDetectedMungeSet()) {
dialog({
title:'IITC unavailable',
html:'<p>IITC failed to detect the appropriate network protocol "munge" parameters from the standard intel site. '
+'This can happen when Niantic make changes to the standard intel site.</p>'
+'<p>The IITC developers are made aware of these problems and will be working on a fix. Please see the following for news/updates.</p>'
+'<ul><li><a href="http://iitc.jonatkins.com/" target="_blank">IITC Home Page</a></li>'
+'<li><a href="https://plus.google.com/105383756361375410867/posts" target="_blank">IITC G+ Page</a></li>'
+'<li><a href="https://plus.google.com/communities/105647403088015055797" target="_blank">IITC G+ Community</a></li></ol>'
});
}
if (typeof android !== 'undefined' && android && android.bootFinished) { if (typeof android !== 'undefined' && android && android.bootFinished) {
android.bootFinished(); android.bootFinished();

View File

@ -79,7 +79,7 @@ window.chat.genPostData = function(isFaction, storageHash, getOlderMsgs) {
maxLngE6: Math.round(ne.lng*1E6), maxLngE6: Math.round(ne.lng*1E6),
minTimestampMs: -1, minTimestampMs: -1,
maxTimestampMs: -1, maxTimestampMs: -1,
chatTabGet: isFaction ? 'faction' : 'all' tab: isFaction ? 'faction' : 'all'
} }
if(getOlderMsgs) { if(getOlderMsgs) {
@ -125,7 +125,7 @@ window.chat.requestFaction = function(getOlderMsgs, isRetry) {
var d = chat.genPostData(true, chat._faction, getOlderMsgs); var d = chat.genPostData(true, chat._faction, getOlderMsgs);
var r = window.postAjax( var r = window.postAjax(
'getPaginatedPlexts', 'getPlexts',
d, d,
function(data, textStatus, jqXHR) { chat.handleFaction(data, getOlderMsgs); }, function(data, textStatus, jqXHR) { chat.handleFaction(data, getOlderMsgs); },
isRetry isRetry
@ -176,7 +176,7 @@ window.chat.requestPublic = function(getOlderMsgs, isRetry) {
var d = chat.genPostData(false, chat._public, getOlderMsgs); var d = chat.genPostData(false, chat._public, getOlderMsgs);
var r = window.postAjax( var r = window.postAjax(
'getPaginatedPlexts', 'getPlexts',
d, d,
function(data, textStatus, jqXHR) { chat.handlePublic(data, getOlderMsgs); }, function(data, textStatus, jqXHR) { chat.handlePublic(data, getOlderMsgs); },
isRetry isRetry
@ -689,10 +689,10 @@ window.chat.postMsg = function() {
var publik = c === 'public'; var publik = c === 'public';
var latlng = map.getCenter(); var latlng = map.getCenter();
var data = {messageSendPlext: msg, var data = {message: msg,
latE6SendPlext: Math.round(latlng.lat*1E6), latE6: Math.round(latlng.lat*1E6),
lngE6SendPlext: Math.round(latlng.lng*1E6), lngE6: Math.round(latlng.lng*1E6),
chatTabSendPlext: publik ? 'all' : 'faction'}; tab: publik ? 'all' : 'faction'};
var errMsg = 'Your message could not be delivered. You can copy&' + var errMsg = 'Your message could not be delivered. You can copy&' +
'paste it here and try again if you want:\n\n' + msg; 'paste it here and try again if you want:\n\n' + msg;

View File

@ -394,14 +394,14 @@ window.MapDataRequest.prototype.sendTileRequest = function(tiles) {
} }
} }
var data = { quadKeys: tilesList }; var data = { tileKeys: tilesList };
this.activeRequestCount += 1; this.activeRequestCount += 1;
var savedThis = this; var savedThis = this;
// NOTE: don't add the request with window.request.add, as we don't want the abort handling to apply to map data any more // NOTE: don't add the request with window.request.add, as we don't want the abort handling to apply to map data any more
window.postAjax('getThinnedEntities', data, window.postAjax('getEntities', data,
function(data, textStatus, jqXHR) { savedThis.handleResponse (data, tiles, true); }, // request successful callback function(data, textStatus, jqXHR) { savedThis.handleResponse (data, tiles, true); }, // request successful callback
function() { savedThis.handleResponse (undefined, tiles, false); } // request failed callback function() { savedThis.handleResponse (undefined, tiles, false); } // request failed callback
); );

View File

@ -1,279 +0,0 @@
// REQUEST PARAMETER MUNGING /////////////////////////////////////////////
//TODO: the double inclusion is planned - but not yet in place
// WARNING: this code is included in IITC twice!
// once within the main body of IITC code, inside the wrapper function
// additionally, outside of the wrapper code - used to detect if the required munging code will work
// before IITC actually starts
// wrap in an anonymous function to limit scope
;(function(){
var requestParameterMunges = [
// all old munge sets deleted - there's no sign that any old ones will become active again
// the current munge set auto-detection code is working very well. as any site update that breaks that detection
// code will also, almost certainly, change the munges in use, it seems pointless keeping this set up to date by hand
// at this time. If that auto-detection breaks, it may be easier to quickly add a munge set by hand than update
// the regular expressions, so the list-based code remains available for the future
// // set 11 - 2013-12-06
// {
// 'dashboard.getArtifactInfo': 'artifacts', // GET_ARTIFACT_INFO
// 'dashboard.getGameScore': '4oid643d9zc168hs', // GET_GAME_SCORE
// 'dashboard.getPaginatedPlexts': 's1msyywq51ntudpe', // GET_PAGINATED_PLEXTS
// 'dashboard.getThinnedEntities': '4467ff9bgxxe4csa', // GET_THINNED_ENTITIES
// 'dashboard.getPortalDetails': 'c00thnhf1yp3z6mn', // GET_PORTAL_DETAILS
// 'dashboard.redeemReward': 'ivshfv9zvyfxyqcd', // REDEEM_REWARD
// 'dashboard.sendInviteEmail': '1rsx15vc0m8wwdax', // SEND_INVITE_EMAIL
// 'dashboard.sendPlext': 'tods2imd0xcfsug6', // SEND_PLEXT
//
// // common parameters
// method: '0wvzluo8av4sk17f',
// version: 'paeh4g353xu06kfg',
// version_parameter: '4acc1e3230c3fd66be3422c0df8dc637336bbd7c',
//
// // GET_THINNED_ENTITIES
// quadKeys: 'ilgv0w4dlldky1yh',
//
// // GET_PORTAL_DETAILS
// guid: '7o8tzmj6oxz1n5w3',
//
// // REDEEM_REWARD
// passcode: 'passcode', // no munging on this parameter
//
// // SEND_INVITE_EMAIL
// inviteeEmailAddress: 'p4rwszdfovuwfdgp',
//
// // GET_PAGINATED_PLEXTS
// desiredNumItems: 'kxsbuvc90l6f40xn',
// minLatE6: 'llizye3i5dbapxac',
// minLngE6: 'w01zpiba1mn5tsab',
// maxLatE6: 'd5phhqzj2tbsq599',
// maxLngE6: 'avq5srnvg431aehn',
// minTimestampMs: 'mhsav5by25wi4s46',
// maxTimestampMs: 'hpu7l8h7eccwytyt',
// chatTab: 'q9343nem7hs1v37b',
// ascendingTimestampOrder: '7pc5c9ggh03pig1b',
//
// // SEND_PLEXT
// message: '8exta9k7y8huhqmc',
// latE6: '7ffwyf3zd2yf8xam',
// lngE6: 'n7ewiach2v22iy20',
//// chatTab: 'q9343nem7hs1v37b', // duplicate from GET_PAGINATED_PLEXTS
//
// },
];
// in the recent stock site updates, their javascript code has been less obfuscated, but also the munge parameters
// change on every release. I can only assume it's now an integrated step in the build/release system, rather
// than continued efforts to block iitc. the lighter obfuscation on the code makes it easier to parse and find
// the munges in the code - so let's attempt that
function extractMungeFromStock() {
try {
var foundMunges = {};
// these are easy - directly available in variables
// NOTE: the .toString() is there so missing variables throw an exception, rather than storing 'undefined'
foundMunges['dashboard.getArtifactInfo'] = nemesis.dashboard.requests.MethodName.GET_ARTIFACT_INFO.toString();
foundMunges['dashboard.getGameScore'] = nemesis.dashboard.requests.MethodName.GET_GAME_SCORE.toString();
foundMunges['dashboard.getPaginatedPlexts'] = nemesis.dashboard.requests.MethodName.GET_PAGINATED_PLEXTS.toString();
foundMunges['dashboard.getThinnedEntities'] = nemesis.dashboard.requests.MethodName.GET_THINNED_ENTITIES.toString();
foundMunges['dashboard.getPortalDetails'] = nemesis.dashboard.requests.MethodName.GET_PORTAL_DETAILS.toString();
// foundMunges['dashboard.redeemReward'] = nemesis.dashboard.requests.MethodName.REDEEM_REWARD.toString();
// foundMunges['dashboard.sendInviteEmail'] = nemesis.dashboard.requests.MethodName.SEND_INVITE_EMAIL.toString();
foundMunges['dashboard.sendPlext'] = nemesis.dashboard.requests.MethodName.SEND_PLEXT.toString();
// the rest are trickier - we need to parse the functions of the stock site. these break very often
// on site updates
// // regular expression - to match either x.abcdef123456wxyz or x["123456abcdefwxyz"] format for property access
// var mungeRegExpProp = '(?:\\.([a-z][a-z0-9]{15})|\\["([0-9][a-z0-9]{15})"\\])';
// // and one to match members of object literal initialisation - {abcdef123456wxyz: or {"123456abcdefwxyz":
// var mungeRegExpLit = '(?:([a-z][a-z0-9]{15})|"([0-9][a-z0-9]{15})"):';
// some cases don't munge now?!?! odd!
var mungeRegExpProp = '(?:\\.([a-z][a-z0-9]{15}|[a-z][a-zA-Z0-9]*)|\\["([0-9][a-z0-9]{15})"\\])';
var mungeRegExpLit = '(?:((?:[a-z][a-z0-9]{15})|[a-z][a-zA-Z0-9]*)|"([0-9][a-z0-9]{15})"):';
// common parameters - method, version, version_parameter - currently found in the
// nemesis.dashboard.network.XhrController.prototype.doSendRequest_ function
// look for something like
// var e = a.getData();
// e["3sld77nsm0tjmkvi"] = c;
// e.xz7q6r3aja5ttvoo = "b121024077de2a0dc6b34119e4440785c9ea5e64";
var reg = new RegExp('getData\\(\\);.*\\n.*'+mungeRegExpProp+' =.*\n.*'+mungeRegExpProp+' *= *"([a-z0-9]{40})','m');
var result = reg.exec(nemesis.dashboard.network.XhrController.prototype.doSendRequest_.toString());
// there's two ways of matching the munge expression, so try both
foundMunges.method = result[1] || result[2];
foundMunges.version = result[3] || result[4];
foundMunges.version_parameter = result[5];
// GET_THINNED_ENTITIES parameters
var reg = new RegExp('GET_THINNED_ENTITIES, nemesis.dashboard.network.XhrController.Priority.[A-Z]+, {'
+mungeRegExpLit+'[a-z]');
var result = reg.exec(nemesis.dashboard.network.DataFetcher.prototype.getGameEntities.toString());
foundMunges.quadKeys = result[1] || result[2];
// GET_PAGINATED_PLEXTS
var reg = new RegExp('[a-z] = {'+mungeRegExpLit+'Math.round\\(1E6 \\* [a-z].bounds.sw.lat\\(\\)\\), '
+mungeRegExpLit+'Math.round\\(1E6 \\* [a-z].bounds.sw.lng\\(\\)\\), '
+mungeRegExpLit+'Math.round\\(1E6 \\* [a-z].bounds.ne.lat\\(\\)\\), '
+mungeRegExpLit+'Math.round\\(1E6 \\* [a-z].bounds.ne.lng\\(\\)\\), '
+mungeRegExpLit+'[a-z], '+mungeRegExpLit+'[a-z]};\n'
+' *[a-z]'+mungeRegExpProp+' = [a-z];\n'
+' *-1 < [a-z] && \\([a-z]'+mungeRegExpProp+' = !0\\);', 'm');
var result = reg.exec(nemesis.dashboard.network.PlextStore.prototype.getPlexts.toString());
// foundMunges.desiredNumItems = result[1] || result[2];
foundMunges.minLatE6 = result[1] || result[2];
foundMunges.minLngE6 = result[3] || result[4];
foundMunges.maxLatE6 = result[5] || result[6];
foundMunges.maxLngE6 = result[7] || result[8];
foundMunges.minTimestampMs = result[9] || result[10];
foundMunges.maxTimestampMs = result[11] || result[12];
foundMunges.chatTabGet = result[13] || result[14]; //guessed parameter name - only seen munged
foundMunges.ascendingTimestampOrder = result[15] || result[16];
// SEND_PLEXT
var reg = new RegExp('SEND_PLEXT, nemesis.dashboard.network.XhrController.Priority.[A-Z]+, {'
+mungeRegExpLit+'[a-z], '
+mungeRegExpLit+'[a-z], '
+mungeRegExpLit+'[a-z], '
+mungeRegExpLit+'[a-z]}');
var result = reg.exec(nemesis.dashboard.network.PlextStore.prototype.sendPlext.toString());
foundMunges.messageSendPlext = result[1] || result[2];
foundMunges.latE6SendPlext = result[3] || result[4];
foundMunges.lngE6SendPlext = result[5] || result[6];
foundMunges.chatTabSendPlext = result[7] || result[8];
// if (chatTab != foundMunges.chatTab) throw 'Error: inconsistent munge parsing for chatTab';
// GET_PORTAL_DETAILS
var reg = new RegExp('GET_PORTAL_DETAILS, nemesis.dashboard.network.XhrController.Priority.[A-Z]+, {'
+mungeRegExpLit+'a}');
var result = reg.exec(nemesis.dashboard.network.DataFetcher.prototype.getPortalDetails.toString());
foundMunges.guid = result[1] || result[2];
// // SEND_INVITE_EMAIL
// var reg = new RegExp('SEND_INVITE_EMAIL, nemesis.dashboard.network.XhrController.Priority.[A-Z]+, {'+mungeRegExpLit+'b}');
// foundMunges.inviteeEmailAddress = result[1] || result[2];
return foundMunges;
} catch(e) {
console.warn('Failed to extract munges from the code: '+e);
}
}
var activeMunge = null;
// attempt to guess the munge set in use, by looking through the functions of the stock intel page for one of the munged params
window.detectActiveMungeSet = function() {
// first, try and parse the stock functions and extract the munges directly
activeMunge = extractMungeFromStock();
if (activeMunge) {
console.log('IITC: Successfully extracted munges from stock javascript - excellent work!');
} else {
console.warn('IITC: failed to detect a munge set from the code - searching our list...');
// try to find a matching munge set from the pre-defined ones. this code remains as in the case of
// things breaking it can be quicker to update the table than to fix the regular expressions used
// above
try {
for (var i in requestParameterMunges) {
if (requestParameterMunges[i]['dashboard.getThinnedEntities'] == nemesis.dashboard.requests.MethodName.GET_THINNED_ENTITIES) {
console.log('IITC: found a match with munge set index '+i);
activeMunge = requestParameterMunges[i];
break;
}
}
} catch(e) {
console.warn('IITC: failed to find matching munge set from supplied list');
}
}
if (!activeMunge) {
console.warn('IITC: Error!! failed to find a parameter munge set - neither extracting from stock, or searching through table. IITC CANNOT WORK');
throw {error:'Failed to find a munge set'};
}
}
window.haveDetectedMungeSet = function() {
try {
if (!activeMunge) detectActiveMungeSet();
} catch(e) {
}
return activeMunge != null;
}
window.mungeOneString = function(str) {
if (!activeMunge) detectActiveMungeSet();
return activeMunge[str];
}
// niantic now add some munging to the request parameters. so far, only two sets of this munging have been seen
window.requestDataMunge = function(data) {
if (!activeMunge) detectActiveMungeSet();
function munge(obj) {
if (Object.prototype.toString.call(obj) === '[object Array]') {
// an array - munge each element of it
var newobj = [];
for (var i in obj) {
newobj[i] = munge(obj[i]);
}
return newobj;
} else if (typeof obj === 'object') {
// an object: munge each property name, and pass the value through the munge process
var newobj = Object();
for (var p in obj) {
var m = activeMunge[p];
if (m === undefined) {
console.error('Error: failed to find munge for object property '+p);
newobj[p] = obj[p];
} else {
// rename the property
newobj[m] = munge(obj[p]);
}
}
return newobj;
} else {
// neither an array or an object - so must be a simple value. return it unmodified
return obj;
}
};
var newdata = munge(data);
try {
newdata = nemesis.dashboard.requests.normalizeParamCount(newdata);
} catch(e) {
if (!window._mungeHaveLoggedError) {
console.warn('Failed to call the stock site normalizeParamCount() function: '+e);
window._mungeHaveLoggedError = true;
}
}
return newdata;
}
//anonymous function end
}());

View File

@ -140,19 +140,13 @@ window.digits = function(d) {
// error: see above. Additionally it is logged if the request failed. // error: see above. Additionally it is logged if the request failed.
window.postAjax = function(action, data, success, error) { window.postAjax = function(action, data, success, error) {
var methodName = 'dashboard.'+action; var versionStr = nemesis.dashboard.config.CURRENT_VERSION;
var versionStr = 'version_parameter'; var post_data = JSON.stringify($.extend({}, data, {v: versionStr}));
// munging of the method name - seen in Set 2 onwards
methodName = mungeOneString(methodName);
// and of the 'version' parameter (we assume it's a version - if missing/wrong that's what the error refers to)
versionStr = mungeOneString(versionStr);
var post_data = JSON.stringify(window.requestDataMunge($.extend({}, data, {method: methodName, version: versionStr})));
var remove = function(data, textStatus, jqXHR) { window.requests.remove(jqXHR); }; var remove = function(data, textStatus, jqXHR) { window.requests.remove(jqXHR); };
var errCnt = function(jqXHR) { window.failedRequestCount++; window.requests.remove(jqXHR); }; var errCnt = function(jqXHR) { window.failedRequestCount++; window.requests.remove(jqXHR); };
var result = $.ajax({ var result = $.ajax({
url: '/r/'+methodName, url: '/r/'+action,
type: 'POST', type: 'POST',
data: post_data, data: post_data,
context: data, context: data,

View File

@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @id ingress-intel-total-conversion@jonatkins // @id ingress-intel-total-conversion@jonatkins
// @name IITC: Ingress intel map total conversion // @name IITC: Ingress intel map total conversion
// @version 0.16.13.@@DATETIMEVERSION@@ // @version 0.17.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@ // @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@ // @downloadURL @@DOWNLOADURL@@