将字符串解码为有效的JSON

时间:2016-06-01 13:27:47

标签: javascript firefox-addon decoding

我正在为Firefox编写附加组件。我正在捕获一个JSON文件,其中应包含我需要的一般用户数据。为了澄清这一点,可以在没有任何安全边界的情况下访问数据。有时捕获的字符串是有效的JSON(根本没有任何编码)。

有时它看起来像这样: enter image description here
有没有人知道如何用JavaScript解码这个,或者至少知道这是哪种编码?

编辑:

正确的数据如下:

{"type":"success","message":"OK","data":{"myPersonas":[{"picture":"","personaId":"382046730","games":{"1":"3078"},"personaName":"Feirell","updatedAt":1423573314,"userId":"2832659177456727338","clanTag":"","originalPersona":{"picture":"","userId":"2832659177456727338","user":null,"updatedAt":1423573314,"firstPartyId":"","personaId":"382046730","personaName":"Feirell","gamesLegacy":"0","namespace":"cem_ea_id","gamesJson":"{\"1\":\"3078\"}","games":{"1":"3078"},"clanTag":""},"namespace":"cem_ea_id"}],"currentRankNeeded":{"name":"WARSAW_ID_P_RANK127_NAME","level":127,"pointsNeeded":20260000,"texture":"UI\/Art\/Persistence\/Ranks\/Rank127","iconImageConfig":{"category":"rank_icon","slug":"r127","texture":"UI\/Art\/Persistence\/ranks\/IconsScoreboard\/r127","versions":{"small":{"path":"warsaw\/gamedata\/rank_icon\/small.png","isSprite":true,"height":23,"name":"small","width":29},"smallns":{"path":"warsaw\/gamedata\/rank_icon\/smallns\/r127.png","isSprite":false,"height":23,"name":"smallns","width":29}}},"guid":"384D858D-8288-4B60-9C35-234B65157873","imageConfig":{"category":"rank","slug":"r127","texture":"UI\/Art\/Persistence\/Ranks\/Rank127","versions":{"large":{"path":"warsaw\/gamedata\/rank\/large\/r127.png","isSprite":false,"height":256,"name":"large","width":256},"smallinv":{"path":"warsaw\/gamedata\/rank\/smallinv.png","isSprite":true,"height":64,"name":"smallinv","width":64},"medium":{"path":"warsaw\/gamedata\/rank\/medium.png","isSprite":true,"height":128,"name":"medium","width":128},"tiny":{"path":"warsaw\/gamedata\/rank\/tiny.png","isSprite":true,"height":29,"name":"tiny","width":29},"tinyinv":{"path":"warsaw\/gamedata\/rank\/tinyinv.png","isSprite":true,"height":29,"name":"tinyinv","width":29},"small":{"path":"warsaw\/gamedata\/rank\/small.png","isSprite":true,"height":64,"name":"small","width":64},"mediumns":{"path":"warsaw\/gamedata\/rank\/mediumns\/r127.png","isSprite":false,"height":128,"name":"mediumns","width":128},"smallns":{"path":"warsaw\/gamedata\/rank\/smallns\/r127.png","isSprite":false,"height":64,"name":"smallns","width":64}}}},"generalPersonaStats":{"PDWHeadshots":0.0,"serviceStarsProgress":{"8":9.1730769231,"1":81.6516129032,"2":13.7603053435,"2048":38.81,"32":93.2388059701},"vehiclesDestroyed":2229,"mortarUser":null,"cs_kills":null,"rsScore":0,"PDWKills":0.0,"gameModesScore":{"32":"32800","1":"5274720","2":"184170","67108864":"12635","64":"5274720","68719476736":"5274720","524288":"21675","34359738368":"21410","2097152":"21675","8":"32800","8388608":"5790","512":0,"134217728":"12635","1024":"33840","33554432":"12635","16777216":"17000","137438953472":"21675"},"sc_hotwire":null,"gameModeServiceStarsGold":{},"rank":127,"rushWins":null,"sc_enforcer":null,"sc_vehicle":3337250,"cp_kills":null,"kitMaxMeleeKillsInRound":{},"cp_deaths":null,"motionSensorSpots":null,"cp_wins":null,"sniperRifleAccuracy":0.282155948,"sc_heist":null,"sc_team":532411,"skill":248,"nemesisKills":429,"heals":13978,"sc_operator":null,"kitMeleeKills":{},"longestHeadshot":694.02,"kills_assault":12436,"conquestWlr":null,"elo":0,"longestWinStreak":null,"sc_unlock":109000,"mcomDefendKills":9,"wlRatio":0.0,"sc_award":7289700,"cp_skill":null,"vehiclesDestroyedAssists":null,"revives":3866,"kitLosses":{},"squadDMWins":null,"rushWlr":null,"LMGKills":1494,"cashEarned":null,"kitKills":{},"rocketLauncherAccuracy":0.0,"kitMaxScoreInRound":{},"kills":23207,"sc_capturetheflag":null,"kdRatio":1.5,"sc_bonus":344311,"assaultRifleAccuracy":0.1521077163,"kitDeaths":{},"squadRushLosses":null,"PDWAccuracy":0.0,"flagDefend":3535,"LMGHeadshots":332,"kitWins":{},"nemesisStreak":18,"numWins":726,"flagrunner":null,"conquestWins":null,"scorePerMinuteDelta":0,"kitHeadshots":{},"rsKills":0,"sc_objective":0,"kitDeployments":{},"rsTimePlayed":0,"vehicleScores":{"32":"206936","1":0,"2":"1957700","4":"153005","8":"20374","16":"727908"},"antiGroundSoldier":162.0,"timeDead":null,"sc_bloodmoney":null,"kdRatioDelta":null,"quitPercentage":23.0852211435,"rsNumLosses":0,"sc_squad":1855100,"vehicleDamage":2523,"rsShotsHit":0,"sc_bountyhunter":null,"spm_engineer":null,"flagCaptures":5521,"kitKillStreak":{},"serviceStars":{"8":10,"1":42,"2":6,"2048":10,"32":7},"dogtagsTaken":185,"sc_turfwar":null,"scoreMultiplier":0,"kitLongestHeadshot":{},"deaths":15470,"reDeploys":null,"sc_professional":null,"clubRepution":null,"sniperRifleHeadshots":855,"killAssists":2259,"LMGAccuracy":0.120160849,"rsDeaths":0,"maxMeleeKillsInRound":null,"tdmWins":null,"gameModeServiceStarsSilver":{},"cashPerMinute":null,"rushLosses":null,"resupplies":2476,"totalScore":20500085,"sc_hacker":null,"headshots":4532,"repairs":618,"shotsFired":1099510,"avengerKills":2075,"squadRushWlr":null,"conquestLosses":null,"cs_deaths":null,"rsNumWins":0,"gameModeServiceStarsBronze":{},"squadDmWlr":null,"spm_support":null,"maxHeadshotsInRound":null,"score":20500085,"kills_recon":2451,"kitTimes":{"8":"210746","1":"708950","2":"118946","2048":"46278","32":"171331"},"timePlayedDelta":0,"squadRushWins":null,"sc_hit":null,"kitTimesInPercentage":{"8":16.7757876412,"1":56.4337859234,"2":9.4683307715,"2048":3.6838179631,"32":13.6382777009},"rankScore":20495300,"kitMaxKillsInRound":{},"accuracy":15.6488799556,"timePlayed":2171290,"sc_squadheist":null,"assaultRifleHeadshots":2450,"kitScores":{"8":"1049540","1":"6636560","2":"804026","2048":"207762","32":"1062940"},"suppressionAssists":1660,"scoreDelta":0,"kills_support":2848,"kitMaxHeadshotsInRound":{},"kills_engineer":1562,"cs_wins":null,"killsPerMinute":0.64,"sniperRifleKills":1880,"scorePerMinute":566,"timePlayedSinceLastReset":0,"winPercentage":null,"tdmWlr":null,"rsScorePerMinute":0.0,"combatScore":13098078,"tdmLosses":null,"sc_mechanic":null,"numRounds":1854,"antiAirSoldier":10.0,"sc_hostage":null,"sc_commander":null,"maxKillsInRound":null,"killStreakBonus":58,"lastReset":0,"sc_deathmatch":null,"cs_skill":null,"spm_recon":null,"rsShotsFired":0,"mcomDestroy":0.0,"shotsHit":172061,"serviceStarsGameModes":[{"serviceStars":251,"serviceStarsProgress":17.7142857143,"progressCodeNeeded":null,"actualValue":5274720,"codeNeeded":"sc_conquest","tier":null,"valueNeeded":5292000,"name":null},{"serviceStars":12,"serviceStarsProgress":27.8,"progressCodeNeeded":null,"actualValue":184170,"codeNeeded":"sc_rush","tier":null,"valueNeeded":195000,"name":null},{"serviceStars":5,"serviceStarsProgress":46.6666666667,"progressCodeNeeded":null,"actualValue":32800,"codeNeeded":"sc_deathmatch","tier":null,"valueNeeded":36000,"name":null},{"serviceStars":3,"serviceStarsProgress":77.7777777778,"progressCodeNeeded":null,"actualValue":17000,"codeNeeded":"sc_elimination","tier":null,"valueNeeded":18000,"name":null}],"numLosses":700,"spm_assault":null,"cp_loses":null,"sc_general":4577110,"saviorKills":1813,"cs_loses":null,"squadDMLosses":null,"maxScoreInRound":null,"meleeKills":null,"assaultRifleKills":11309},"rankNeeded":{"name":"WARSAW_ID_P_RANK128_NAME","level":128,"pointsNeeded":21030000,"texture":"UI\/Art\/Persistence\/Ranks\/Rank128","iconImageConfig":{"category":"rank_icon","slug":"r128","texture":"UI\/Art\/Persistence\/ranks\/IconsScoreboard\/r128","versions":{"small":{"path":"warsaw\/gamedata\/rank_icon\/small.png","isSprite":true,"height":23,"name":"small","width":29},"smallns":{"path":"warsaw\/gamedata\/rank_icon\/smallns\/r128.png","isSprite":false,"height":23,"name":"smallns","width":29}}},"guid":"9AC7B2DF-C736-4721-BE14-61F75A4AB816","imageConfig":{"category":"rank","slug":"r128","texture":"UI\/Art\/Persistence\/Ranks\/Rank128","versions":{"large":{"path":"warsaw\/gamedata\/rank\/large\/r128.png","isSprite":false,"height":256,"name":"large","width":256},"smallinv":{"path":"warsaw\/gamedata\/rank\/smallinv.png","isSprite":true,"height":64,"name":"smallinv","width":64},"medium":{"path":"warsaw\/gamedata\/rank\/medium.png","isSprite":true,"height":128,"name":"medium","width":128},"tiny":{"path":"warsaw\/gamedata\/rank\/tiny.png","isSprite":true,"height":29,"name":"tiny","width":29},"tinyinv":{"path":"warsaw\/gamedata\/rank\/tinyinv.png","isSprite":true,"height":29,"name":"tinyinv","width":29},"small":{"path":"warsaw\/gamedata\/rank\/small.png","isSprite":true,"height":64,"name":"small","width":64},"mediumns":{"path":"warsaw\/gamedata\/rank\/mediumns\/r128.png","isSprite":false,"height":128,"name":"mediumns","width":128},"smallns":{"path":"warsaw\/gamedata\/rank\/smallns\/r128.png","isSprite":false,"height":64,"name":"smallns","width":64}}}}}}

捕捉的代码:

//CODE FROM: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/NsITraceableChannel#Example
let { CC, Ci, Cu } = require("chrome");
Cu.import('resource://gre/modules/Services.jsm');

var BinaryInputStream = CC('@mozilla.org/binaryinputstream;1', 'nsIBinaryInputStream', 'setInputStream');
var BinaryOutputStream = CC('@mozilla.org/binaryoutputstream;1', 'nsIBinaryOutputStream', 'setOutputStream');
var StorageStream = CC('@mozilla.org/storagestream;1', 'nsIStorageStream', 'init');

function TracingListener() {
    this.receivedChunks = []; // array for incoming data. holds chunks as they come, onStopRequest we join these junks to get the full source
    this.responseBody; // we'll set this to the 
    this.responseStatusCode;

    this.deferredDone = {
        promise: null,
        resolve: null,
        reject: null
    };
    this.deferredDone.promise = new Promise(function(resolve, reject) {
        this.resolve = resolve;
        this.reject = reject;
    }.bind(this.deferredDone));
    Object.freeze(this.deferredDone);
    this.promiseDone = this.deferredDone.promise;
}
TracingListener.prototype = {
    onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
        var iStream = new BinaryInputStream(aInputStream) // binaryaInputStream
        var sStream = new StorageStream(8192, aCount, null); // storageStream // not sure why its 8192 but thats how eveyrone is doing it, we should ask why
        var oStream = new BinaryOutputStream(sStream.getOutputStream(0)); // binaryOutputStream

        // Copy received data as they come.
        var data = iStream.readBytes(aCount);
        this.receivedChunks.push(data);

        oStream.writeBytes(data, aCount);

        this.originalListener.onDataAvailable(aRequest, aContext, sStream.newInputStream(0), aOffset, aCount);
    },
    onStartRequest: function(aRequest, aContext) {
        this.originalListener.onStartRequest(aRequest, aContext);
    },
    onStopRequest: function(aRequest, aContext, aStatusCode) {
        this.responseBody = this.receivedChunks.join("");
        delete this.receivedChunks;
        this.responseStatus = aStatusCode;
        this.originalListener.onStopRequest(aRequest, aContext, aStatusCode);

        this.deferredDone.resolve();
    },
    QueryInterface: function(aIID) {
        if (aIID.equals(Ci.nsIStreamListener) || aIID.equals(Ci.nsISupports)) {
            return this;
        }
        throw Cr.NS_NOINTERFACE;
    }
};


//my Battlereport Listener


function battlereportListener(callback){
    got_battlereport = callback
}

battlereportListener.prototype.httpResponseObserver = {
    observe: function(aSubject, aTopic, aData) {
        aSubject.QueryInterface(Ci.nsIHttpChannel);
        let url = aSubject.URI.spec;
        if(url.indexOf("http://battlelog.battlefield.com/bf4/indexstats") != -1){
            //console.log('Found a battlereport !!')
            var newListener = new TracingListener();
            aSubject.QueryInterface(Ci.nsITraceableChannel);
            newListener.originalListener = aSubject.setNewListener(newListener);
            newListener.promiseDone.then(
                function() {
                    // no error happened
                    got_battlereport(newListener.responseBody)
                },
                function(aReason){
                    // promise was rejected, right now i didnt set up rejection, but i should listen to on abort or bad status code then reject maybe
                }
            ).catch(
                function(aCatch) {
                    console.error('something went wrong, a typo by dev probably:', aCatch);
                }
            );
        }
    }
};
battlereportListener.prototype.state = false

battlereportListener.prototype.start = function(){
    if(this.state == false){
        Services.obs.addObserver(this.httpResponseObserver, 'http-on-examine-response', false);
        this.state = true;
    }
};
battlereportListener.prototype.stop = function(){
    if(this.state == true){
        Services.obs.removeObserver(this.httpResponseObserver, 'http-on-examine-response');
        this.state = false;
    }
};

exports.battlereportListener = battlereportListener

我刚用Firefox测试过,它运行正常。但是,在Firefox Developer Edition中,它涉及到这个二进制代码。

0 个答案:

没有答案