web: Don't allow arbitrary upload of save files for technical reasons

This commit is contained in:
Daniel Jacobs 2023-03-13 12:59:59 -04:00 committed by Nathan Adams
parent 54ad95beb3
commit 94ff2891e9
3 changed files with 25 additions and 32 deletions

View File

@ -23,7 +23,6 @@ overrides:
- plugin:@typescript-eslint/recommended
rules:
'@typescript-eslint/no-non-null-assertion': 'off'
'no-control-regex': 0
'@typescript-eslint/no-unused-vars':
- error
- argsIgnorePattern: ^_

View File

@ -243,10 +243,6 @@ export class RufflePlayer extends HTMLElement {
if (backupSaves) {
backupSaves.addEventListener("click", this.backupSaves.bind(this));
}
const restoreSave = this.saveManager.querySelector("#restore-save");
if (restoreSave) {
restoreSave.addEventListener("change", this.restoreSave.bind(this));
}
this.contextMenuElement = this.shadow.getElementById("context-menu")!;
window.addEventListener("pointerdown", this.pointerDown.bind(this));
@ -874,40 +870,20 @@ export class RufflePlayer extends HTMLElement {
}
/**
* Restore save from SOL file.
* Replace save from SOL file.
*
* @param event The change event fired
* @param solKey The localStorage save file key
*/
async restoreSave(event: Event): Promise<void> {
async replaceSOL(event: Event, solKey: string): Promise<void> {
const fileInput = <HTMLInputElement>event.target;
const reader = new FileReader();
reader.addEventListener("load", () => {
if (reader.result && typeof reader.result === "string") {
const b64Regex = new RegExp("data:.*;base64,");
const unprintable = new RegExp("[\u0000-\u001f]*");
const nullChar = "\u0000";
const b64SolData = reader.result.replace(b64Regex, "");
const solDataNamePlus = atob(b64SolData)
.slice(10)
.replace(unprintable, "");
const solName = solDataNamePlus.substring(
0,
solDataNamePlus.indexOf(nullChar)
);
const solKey = this.swfUrl
? this.swfUrl.hostname +
this.swfUrl.pathname +
"/" +
solName
: document.location.hostname + "//" + solName;
if (this.isB64SOL(b64SolData)) {
if (localStorage[solKey]) {
alert(
"Save data with key " +
solKey +
" already exists. Delete it first."
);
} else {
this.saveManager.close();
localStorage.setItem(solKey, b64SolData);
this.populateSaves();
@ -962,12 +938,31 @@ export class RufflePlayer extends HTMLElement {
solName + ".sol"
)
);
const replaceCol = document.createElement("TD");
const replaceInput = <HTMLInputElement>(
document.createElement("INPUT")
);
replaceInput.type = "file";
replaceInput.className = "replace-save";
replaceInput.id = "replace-save-" + key;
const replaceLabel = <HTMLLabelElement>(
document.createElement("LABEL")
);
replaceLabel.htmlFor = "replace-save-" + key;
replaceLabel.textContent = "Replace";
replaceLabel.className = "save-option";
replaceInput.addEventListener("change", (event) =>
this.replaceSOL(event, key)
);
replaceCol.appendChild(replaceInput);
replaceCol.appendChild(replaceLabel);
const deleteCol = document.createElement("TD");
deleteCol.textContent = "Delete";
deleteCol.className = "save-option";
deleteCol.addEventListener("click", () => this.deleteSave(key));
row.appendChild(keyCol);
row.appendChild(downloadCol);
row.appendChild(replaceCol);
row.appendChild(deleteCol);
saveTable.appendChild(row);
}

View File

@ -285,6 +285,9 @@ ruffleShadowTemplate.innerHTML = `
#restore-save {
display: none;
}
.replace-save {
display: none;
}
.save-option {
display: inline-block;
padding: 3px 10px;
@ -324,10 +327,6 @@ ruffleShadowTemplate.innerHTML = `
<span id="close-modal">&times;</span>
<div class="general-save-options">
<span class="save-option" id="backup-saves">Backup all saves (download all sols)</span>
<span id="restore-save-paragraph">
<input type="file" accept=".sol" id="restore-save">
<label class="save-option" for="restore-save" id="restore-save-label">Restore save (upload sol)</label>
</span>
</div>
<table id="local-saves"></table>
</dialog>