web: Don't allow arbitrary upload of save files for technical reasons
This commit is contained in:
parent
54ad95beb3
commit
94ff2891e9
|
@ -23,7 +23,6 @@ overrides:
|
||||||
- plugin:@typescript-eslint/recommended
|
- plugin:@typescript-eslint/recommended
|
||||||
rules:
|
rules:
|
||||||
'@typescript-eslint/no-non-null-assertion': 'off'
|
'@typescript-eslint/no-non-null-assertion': 'off'
|
||||||
'no-control-regex': 0
|
|
||||||
'@typescript-eslint/no-unused-vars':
|
'@typescript-eslint/no-unused-vars':
|
||||||
- error
|
- error
|
||||||
- argsIgnorePattern: ^_
|
- argsIgnorePattern: ^_
|
||||||
|
|
|
@ -243,10 +243,6 @@ export class RufflePlayer extends HTMLElement {
|
||||||
if (backupSaves) {
|
if (backupSaves) {
|
||||||
backupSaves.addEventListener("click", this.backupSaves.bind(this));
|
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")!;
|
this.contextMenuElement = this.shadow.getElementById("context-menu")!;
|
||||||
window.addEventListener("pointerdown", this.pointerDown.bind(this));
|
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 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 fileInput = <HTMLInputElement>event.target;
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.addEventListener("load", () => {
|
reader.addEventListener("load", () => {
|
||||||
if (reader.result && typeof reader.result === "string") {
|
if (reader.result && typeof reader.result === "string") {
|
||||||
const b64Regex = new RegExp("data:.*;base64,");
|
const b64Regex = new RegExp("data:.*;base64,");
|
||||||
const unprintable = new RegExp("[\u0000-\u001f]*");
|
|
||||||
const nullChar = "\u0000";
|
|
||||||
const b64SolData = reader.result.replace(b64Regex, "");
|
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 (this.isB64SOL(b64SolData)) {
|
||||||
if (localStorage[solKey]) {
|
if (localStorage[solKey]) {
|
||||||
alert(
|
|
||||||
"Save data with key " +
|
|
||||||
solKey +
|
|
||||||
" already exists. Delete it first."
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
this.saveManager.close();
|
this.saveManager.close();
|
||||||
localStorage.setItem(solKey, b64SolData);
|
localStorage.setItem(solKey, b64SolData);
|
||||||
this.populateSaves();
|
this.populateSaves();
|
||||||
|
@ -962,12 +938,31 @@ export class RufflePlayer extends HTMLElement {
|
||||||
solName + ".sol"
|
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");
|
const deleteCol = document.createElement("TD");
|
||||||
deleteCol.textContent = "Delete";
|
deleteCol.textContent = "Delete";
|
||||||
deleteCol.className = "save-option";
|
deleteCol.className = "save-option";
|
||||||
deleteCol.addEventListener("click", () => this.deleteSave(key));
|
deleteCol.addEventListener("click", () => this.deleteSave(key));
|
||||||
row.appendChild(keyCol);
|
row.appendChild(keyCol);
|
||||||
row.appendChild(downloadCol);
|
row.appendChild(downloadCol);
|
||||||
|
row.appendChild(replaceCol);
|
||||||
row.appendChild(deleteCol);
|
row.appendChild(deleteCol);
|
||||||
saveTable.appendChild(row);
|
saveTable.appendChild(row);
|
||||||
}
|
}
|
||||||
|
|
|
@ -285,6 +285,9 @@ ruffleShadowTemplate.innerHTML = `
|
||||||
#restore-save {
|
#restore-save {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
.replace-save {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
.save-option {
|
.save-option {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 3px 10px;
|
padding: 3px 10px;
|
||||||
|
@ -324,10 +327,6 @@ ruffleShadowTemplate.innerHTML = `
|
||||||
<span id="close-modal">×</span>
|
<span id="close-modal">×</span>
|
||||||
<div class="general-save-options">
|
<div class="general-save-options">
|
||||||
<span class="save-option" id="backup-saves">Backup all saves (download all sols)</span>
|
<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>
|
</div>
|
||||||
<table id="local-saves"></table>
|
<table id="local-saves"></table>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
Loading…
Reference in New Issue