From f98f5f1a053f5e8d8e23d613105178c6b565a2cf Mon Sep 17 00:00:00 2001 From: Isaiah Mayerchak Date: Fri, 15 Jul 2016 19:26:07 -0500 Subject: [PATCH 1/2] Try/catch blocks set up for JSON parsing --- runestone/assess/js/fitb.js | 12 +++++-- runestone/assess/js/mchoice.js | 11 ++++-- runestone/assess/js/timed.js | 45 ++++++++++++++++--------- runestone/clickableArea/js/clickable.js | 13 +++++-- runestone/dragndrop/js/dragndrop.js | 13 +++++-- 5 files changed, 71 insertions(+), 23 deletions(-) diff --git a/runestone/assess/js/fitb.js b/runestone/assess/js/fitb.js index f9c9169b2..b996649dc 100644 --- a/runestone/assess/js/fitb.js +++ b/runestone/assess/js/fitb.js @@ -213,8 +213,16 @@ FITB.prototype.checkLocalStorage = function () { if (len > 0) { var ex = localStorage.getItem(eBookConfig.email + ":" + this.divid + "-given"); if (ex !== null) { - var storedData = JSON.parse(ex); - var arr = storedData.answer; + try { + var storedData = JSON.parse(ex); + var arr = storedData.answer; + } catch (err) { + // error while parsing; likely due to bad value stored in storage + console.log(err.message); + localStorage.removeItem(eBookConfig.email + ":" + this.divid + "-given"); + return; + } + for (var i = 0; i < this.blankArray.length; i++) { $(this.blankArray[i]).attr("value", arr[i]); } diff --git a/runestone/assess/js/mchoice.js b/runestone/assess/js/mchoice.js index f030b4f41..60d7a6060 100644 --- a/runestone/assess/js/mchoice.js +++ b/runestone/assess/js/mchoice.js @@ -297,8 +297,15 @@ MultipleChoice.prototype.checkLocalStorage = function () { if (len > 0) { var ex = localStorage.getItem(eBookConfig.email + ":" + this.divid + "-given"); if (ex !== null) { - var storedData = JSON.parse(ex); - var answers = storedData.answer.split(","); + try { + var storedData = JSON.parse(ex); + var answers = storedData.answer.split(","); + } catch (err) { + // error while parsing; likely due to bad value stored in storage + console.log(err.message); + localStorage.removeItem(eBookConfig.email + ":" + this.divid + "-given"); + return; + } for (var a = 0; a < answers.length; a++) { var index = answers[a]; for (var b = 0; b < this.optionArray.length; b++) { diff --git a/runestone/assess/js/timed.js b/runestone/assess/js/timed.js index 6f19ca7b5..8011b20b6 100644 --- a/runestone/assess/js/timed.js +++ b/runestone/assess/js/timed.js @@ -108,7 +108,7 @@ Timed.prototype.renderTimedAssess = function () { Timed.prototype.renderContainer = function () { this.assessDiv = document.createElement("div"); // container for the entire Timed Component - + if (this.fullwidth) { // allow the container to fill the width - barb $(this.assessDiv).attr({ @@ -544,7 +544,7 @@ Timed.prototype.finishAssessment = function () { this.storeScore(); this.logScore(); $(this.pauseBtn).attr("disabled", true); - this.finishButton.disabled = true; + this.finishButton.disabled = true; }; Timed.prototype.submitTimedProblems = function (logFlag) { @@ -621,17 +621,24 @@ Timed.prototype.shouldUseServer = function (data) { var storageObj = localStorage.getItem(eBookConfig.email + ":" + this.divid + "-given"); if (storageObj === null) return true; - var storedData = JSON.parse(storageObj).answer; - if (storedData.length == 4) { - if (data.correct == storedData[0] && data.incorrect == storedData[1] && data.skipped == storedData[2] && data.timeTaken == storedData[3]) - return true; - } else if (storedData.length == 7) { - if (data.correct == storedData[0] && data.incorrect == storedData[2] && data.skipped == storedData[4] && data.timeTaken == storedData[6]) { - this.logScore(); - return false; // In this case, because local storage has more info, we want to use that if it's consistent + try { + var storedData = JSON.parse(storageObj).answer; + if (storedData.length == 4) { + if (data.correct == storedData[0] && data.incorrect == storedData[1] && data.skipped == storedData[2] && data.timeTaken == storedData[3]) + return true; + } else if (storedData.length == 7) { + if (data.correct == storedData[0] && data.incorrect == storedData[2] && data.skipped == storedData[4] && data.timeTaken == storedData[6]) { + this.logScore(); + return false; // In this case, because local storage has more info, we want to use that if it's consistent + } } + var storageDate = new Date(JSON.parse(storageObj[1]).timestamp); + } catch (err) { + // error while parsing; likely due to bad value stored in storage + console.log(err.message); + localStorage.removeItem(eBookConfig.email + ":" + this.divid + "-given"); + return; } - var storageDate = new Date(JSON.parse(storageObj[1]).timestamp); var serverDate = new Date(data.timestamp); if (serverDate < storageDate) { this.logScore(); @@ -656,12 +663,17 @@ Timed.prototype.checkLocalStorage = function () { Timed.prototype.restoreAnswers = function (data) { this.taken = 1; - if (this.taken) { - this.handlePrevAssessment(); - } var tmpArr; if (data === "") { - tmpArr = JSON.parse(localStorage.getItem(eBookConfig.email + ":" + this.divid + "-given")).answer; + try { + tmpArr = JSON.parse(localStorage.getItem(eBookConfig.email + ":" + this.divid + "-given")).answer; + } catch (err) { + // error while parsing; likely due to bad value stored in storage + console.log(err.message); + localStorage.removeItem(eBookConfig.email + ":" + this.divid + "-given"); + this.taken = 0; + return; + } } else { tmpArr = [parseInt(data.correct), parseInt(data.incorrect), parseInt(data.skipped), parseInt(data.timeTaken)]; this.setLocalStorage(data); @@ -689,6 +701,9 @@ Timed.prototype.restoreAnswers = function (data) { this.skipped = this.renderedQuestionArray.length; this.timeTaken = 0; } + if (this.taken) { + this.handlePrevAssessment(); + } this.renderTimedQuestion(); this.displayScore(); this.showTime(); diff --git a/runestone/clickableArea/js/clickable.js b/runestone/clickableArea/js/clickable.js index 885065d85..889426273 100644 --- a/runestone/clickableArea/js/clickable.js +++ b/runestone/clickableArea/js/clickable.js @@ -161,8 +161,17 @@ ClickableArea.prototype.checkLocalStorage = function () { var ex = localStorage.getItem(eBookConfig.email + ":" + this.divid + "-given"); if (ex !== null) { this.hasStoredAnswers = true; - var storageObj = JSON.parse(ex); - this.clickedIndexArray = storageObj.answer.split(";"); + try { + var storageObj = JSON.parse(ex); + this.clickedIndexArray = storageObj.answer.split(";"); + } catch (err) { + // error while parsing; likely due to bad value stored in storage + console.log(err.message); + localStorage.removeItem(eBookConfig.email + ":" + this.divid + "-given"); + this.hasStoredAnswers = false; + this.restoreAnswers({}); + return; + } if (this.useRunestoneServices) { // log answer to server this.givenIndexArray = []; diff --git a/runestone/dragndrop/js/dragndrop.js b/runestone/dragndrop/js/dragndrop.js index 75ef588ec..673e606be 100644 --- a/runestone/dragndrop/js/dragndrop.js +++ b/runestone/dragndrop/js/dragndrop.js @@ -370,8 +370,17 @@ DragNDrop.prototype.checkLocalStorage = function () { var ex = localStorage.getItem(eBookConfig.email + ":" + this.divid + "-given"); if (ex !== null) { this.hasStoredDropzones = true; - var storedObj = JSON.parse(ex); - this.minheight = storedObj.minHeight; + try { + var storedObj = JSON.parse(ex); + this.minheight = storedObj.minHeight; + } catch (err) { + // error while parsing; likely due to bad value stored in storage + console.log(err.message); + localStorage.removeItem(eBookConfig.email + ":" + this.divid + "-given"); + this.hasStoredDropzones = false; + this.finishSettingUp(); + return; + } this.pregnantIndexArray = storedObj.answer.split(";"); if (this.useRunestoneServices) { // store answer in database From 99f69943c90282ec3250cbe793c94f773d68cbdf Mon Sep 17 00:00:00 2001 From: Isaiah Mayerchak Date: Sun, 17 Jul 2016 16:54:26 -0500 Subject: [PATCH 2/2] Added safety checking to runestonebase --- runestone/common/js/runestonebase.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/runestone/common/js/runestonebase.js b/runestone/common/js/runestonebase.js index 703d8538c..108fa92f3 100644 --- a/runestone/common/js/runestonebase.js +++ b/runestone/common/js/runestonebase.js @@ -53,7 +53,16 @@ RunestoneBase.prototype.shouldUseServer = function (data) { var ex = localStorage.getItem(eBookConfig.email + ":" + this.divid + "-given"); if (ex === null) return true; - var storedData = JSON.parse(ex); + var storedData; + try { + storedData = JSON.parse(ex); + } catch (err){ + // error while parsing; likely due to bad value stored in storage + console.log(err.message); + localStorage.removeItem(eBookConfig.email + ":" + this.divid + "-given"); + // definitely don't want to use local storage here + return true; + } if (data.answer == storedData.answer) return true; var storageDate = new Date(storedData.timestamp);