537 wiersze
13 KiB
C
537 wiersze
13 KiB
C
|
// mods by James Zahary Dec 28, 2021 https://github.com/jameszah/ESPxWebFlMgr
|
||
|
// based on https://github.com/holgerlembke/ESPxWebFlMgr
|
||
|
|
||
|
// inline guard. Did I mention that c/c++ is broken by design?
|
||
|
#ifndef ESPxWebFlMgrWp_h
|
||
|
#define ESPxWebFlMgrWp_h
|
||
|
|
||
|
// this file has been created by makeESPxWebFlMgrWp\do.cmd
|
||
|
|
||
|
//*****************************************************************************************************
|
||
|
static const char ESPxWebFlMgrWpindexpage[] PROGMEM = R"==x==(
|
||
|
<!DOCTYPE html>
|
||
|
<html lang="en">
|
||
|
<head>
|
||
|
<title>FileManager</title>
|
||
|
<meta charset="utf-8"/>
|
||
|
<link rel="stylesheet" type="text/css" href="/bg.css">
|
||
|
<link rel="stylesheet" type="text/css" href="/fm.css">
|
||
|
<script src="/fm.js"></script>
|
||
|
<script src="/gzipper.js"></script>
|
||
|
</head>
|
||
|
<body class="background">
|
||
|
<div id="gc">
|
||
|
<div class="o1"> </div>
|
||
|
<div class="o2"> </div>
|
||
|
<div class="o3" id="o3"> </div>
|
||
|
<div class="o4"> </div>
|
||
|
|
||
|
<div class="m1">
|
||
|
<div class="s11"> </div>
|
||
|
<div class="s12">
|
||
|
<div class="s13 background"> </div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="m2" ondrop="dropHandler(event);" ondragover="dragOverHandler(event);">
|
||
|
File<br />
|
||
|
Drop<br />
|
||
|
Zone<br />
|
||
|
</div>
|
||
|
<div class="m3">
|
||
|
<div class="s31"> </div>
|
||
|
<div class="s32">
|
||
|
<div class="s33 background"> </div>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<div class="u1"> </div>
|
||
|
<div class="u2" onclick="downloadall();">Download all files</div>
|
||
|
<div class="u3" id="msg">Loading...</div>
|
||
|
<div class="u4"> </div>
|
||
|
<div class="c" id="fi">
|
||
|
File list should appear here.
|
||
|
</div>
|
||
|
</div>
|
||
|
</body>
|
||
|
</html>
|
||
|
|
||
|
)==x==";
|
||
|
|
||
|
static const char ESPxWebFlMgrWpjavascript[] PROGMEM = R"==x==(
|
||
|
|
||
|
function compressurlfile(source) {
|
||
|
msgline("Fetching file...");
|
||
|
var request = new XMLHttpRequest();
|
||
|
request.onreadystatechange = function () {
|
||
|
var DONE = this.DONE || 4;
|
||
|
if (this.readyState === DONE) {
|
||
|
var data = this.responseText;
|
||
|
var gzip = require('gzip-js'), options = { level: 9, name: source, timestamp: parseInt(Date.now() / 1000, 10) };
|
||
|
var out = gzip.zip(data, options);
|
||
|
var bout = new Uint8Array(out); // out is 16 bits...
|
||
|
|
||
|
msgline("Sending compressed file...");
|
||
|
var sendback = new XMLHttpRequest();
|
||
|
sendback.onreadystatechange = function () {
|
||
|
var DONE = this.DONE || 4;
|
||
|
if (this.readyState === DONE) {
|
||
|
getfileinsert();
|
||
|
}
|
||
|
};
|
||
|
sendback.open('POST', '/r');
|
||
|
var formdata = new FormData();
|
||
|
var blob = new Blob([bout], { type: "application/octet-binary" });
|
||
|
formdata.append(source + '.gz', blob, source + '.gz');
|
||
|
sendback.send(formdata);
|
||
|
}
|
||
|
};
|
||
|
request.open('GET', source, true);
|
||
|
request.send(null);
|
||
|
}
|
||
|
|
||
|
var subdir;
|
||
|
|
||
|
function getfileinsert() {
|
||
|
msgline("Fetching files infos...");
|
||
|
subdir = '/';
|
||
|
var request = new XMLHttpRequest();
|
||
|
request.onreadystatechange = function () {
|
||
|
var DONE = this.DONE || 4;
|
||
|
if (this.readyState === DONE) {
|
||
|
var res = this.responseText.split("##");
|
||
|
document.getElementById('fi').innerHTML = res[0];
|
||
|
document.getElementById("o3").innerHTML = res[1];
|
||
|
msgline("");
|
||
|
}
|
||
|
};
|
||
|
request.open('GET', '/i', true);
|
||
|
request.send(null);
|
||
|
}
|
||
|
|
||
|
function getfileinsert2(strddd) {
|
||
|
msgline("Fetching files infos...");
|
||
|
subdir = strddd;
|
||
|
var request = new XMLHttpRequest();
|
||
|
request.onreadystatechange = function () {
|
||
|
var DONE = this.DONE || 4;
|
||
|
if (this.readyState === DONE) {
|
||
|
var res = this.responseText.split("##");
|
||
|
document.getElementById('fi').innerHTML = res[0];
|
||
|
document.getElementById("o3").innerHTML = res[1];
|
||
|
msgline("");
|
||
|
}
|
||
|
};
|
||
|
request.open('GET', '/i?subdir=' + strddd, true); // must send the subdir variable to get that folder //jz
|
||
|
request.send(null);
|
||
|
}
|
||
|
function executecommand(command) {
|
||
|
var xhr = new XMLHttpRequest();
|
||
|
xhr.onreadystatechange = function () {
|
||
|
var DONE = this.DONE || 4;
|
||
|
if (this.readyState === DONE) {
|
||
|
getfileinsert2(subdir);
|
||
|
}
|
||
|
};
|
||
|
xhr.open('GET', '/c?' + command, true);
|
||
|
xhr.send(null);
|
||
|
}
|
||
|
|
||
|
function downloadfile(filename) {
|
||
|
window.location.href = "/c?dwn=" + filename;
|
||
|
}
|
||
|
|
||
|
function opendirectory(filename) {
|
||
|
|
||
|
getfileinsert2(filename);
|
||
|
}
|
||
|
|
||
|
function deletefile(filename) {
|
||
|
if (confirm("Really delete " + filename)) {
|
||
|
msgline("Refresh when done deleting..."); //jz msgline("Please wait. Delete in progress...");
|
||
|
executecommand("del=" + filename);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function renamefile(filename) {
|
||
|
var newname = prompt("new name for " + filename, filename);
|
||
|
if (newname != null) {
|
||
|
msgline("Refresh when done renaming ..."); //jz msgline("Please wait. Rename in progress...");
|
||
|
executecommand("ren=" + filename + "&new=" + newname);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var editxhr;
|
||
|
|
||
|
function editfile(filename) {
|
||
|
msgline("Please wait. Creating editor...");
|
||
|
|
||
|
editxhr = new XMLHttpRequest();
|
||
|
editxhr.onreadystatechange = function () {
|
||
|
var DONE = this.DONE || 4;
|
||
|
if (this.readyState === DONE) {
|
||
|
document.getElementById('fi').innerHTML = editxhr.responseText;
|
||
|
document.getElementById("o3").innerHTML = "Edit " + filename;
|
||
|
msgline("");
|
||
|
}
|
||
|
};
|
||
|
editxhr.open('GET', '/e?edit=' + filename, true);
|
||
|
editxhr.send(null);
|
||
|
}
|
||
|
|
||
|
function sved(filename) {
|
||
|
var content = document.getElementById('tect').value;
|
||
|
// utf-8
|
||
|
content = unescape(encodeURIComponent(content));
|
||
|
|
||
|
var xhr = new XMLHttpRequest();
|
||
|
|
||
|
xhr.open("POST", "/r", true);
|
||
|
|
||
|
var boundary = '-----whatever';
|
||
|
xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
|
||
|
|
||
|
var body = "" +
|
||
|
'--' + boundary + '\r\n' +
|
||
|
'Content-Disposition: form-data; name="uploadfile"; filename="' + filename + '"' + '\r\n' +
|
||
|
'Content-Type: text/plain' + '\r\n' +
|
||
|
'' + '\r\n' +
|
||
|
content + '\r\n' +
|
||
|
'--' + boundary + '--\r\n' + // \r\n fixes upload delay in ESP8266WebServer
|
||
|
'';
|
||
|
|
||
|
// ajax does not do xhr.setRequestHeader("Content-length", body.length);
|
||
|
|
||
|
xhr.onreadystatechange = function () {
|
||
|
var DONE = this.DONE || 4;
|
||
|
if (this.readyState === DONE) {
|
||
|
getfileinsert();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
xhr.send(body);
|
||
|
}
|
||
|
|
||
|
function abed() {
|
||
|
getfileinsert();
|
||
|
}
|
||
|
|
||
|
var uploaddone = true; // hlpr for multiple file uploads
|
||
|
|
||
|
function uploadFile(file, islast) {
|
||
|
uploaddone = false;
|
||
|
var xhr = new XMLHttpRequest();
|
||
|
xhr.onreadystatechange = function () {
|
||
|
// console.log(xhr.status);
|
||
|
var DONE = this.DONE || 4;
|
||
|
if (this.readyState === DONE) {
|
||
|
if (islast) {
|
||
|
getfileinsert2(subdir);
|
||
|
console.log('last file');
|
||
|
}
|
||
|
uploaddone = true;
|
||
|
}
|
||
|
};
|
||
|
xhr.open('POST', '/r');
|
||
|
var formdata = new FormData();
|
||
|
//var newname = subdir + '/' + file.name; //jz didnt work, so do it in c++
|
||
|
//file.name = newname;
|
||
|
formdata.append('uploadfile', file);
|
||
|
// not sure why, but with that the upload to esp32 is stable.
|
||
|
formdata.append('dummy', 'dummy');
|
||
|
xhr.send(formdata);
|
||
|
}
|
||
|
|
||
|
var globaldropfilelisthlpr = null; // read-only-list, no shift()
|
||
|
var transferitem = 0;
|
||
|
var uploadFileProzessorhndlr = null;
|
||
|
|
||
|
function uploadFileProzessor() {
|
||
|
if (uploaddone) {
|
||
|
if (transferitem==globaldropfilelisthlpr.length) {
|
||
|
clearInterval(uploadFileProzessorhndlr);
|
||
|
} else {
|
||
|
var file = globaldropfilelisthlpr[transferitem];
|
||
|
msgline("Please wait. Transferring file "+file.name+"...");
|
||
|
console.log('process file ' + file.name);
|
||
|
transferitem++;
|
||
|
uploadFile(file,transferitem==globaldropfilelisthlpr.length);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
function dropHandlerALT(ev) {
|
||
|
console.log('File(s) dropped');
|
||
|
|
||
|
document.getElementById('msg').innerHTML = "Please wait. Transferring file...";
|
||
|
|
||
|
// Prevent default behavior (Prevent file from being opened)
|
||
|
ev.preventDefault();
|
||
|
|
||
|
if (ev.dataTransfer.items) {
|
||
|
// Use DataTransferItemList interface to access the file(s)
|
||
|
for (var i = 0; i < ev.dataTransfer.items.length; i++) {
|
||
|
// If dropped items aren't files, reject them
|
||
|
if (ev.dataTransfer.items[i].kind === 'file') {
|
||
|
var file = ev.dataTransfer.items[i].getAsFile();
|
||
|
uploadFile(file);
|
||
|
console.log('.1. file[' + i + '].name = ' + file.name);
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
// Use DataTransfer interface to access the file(s)
|
||
|
for (var i = 0; i < ev.dataTransfer.files.length; i++) {
|
||
|
console.log('.2. file[' + i + '].name = ' + ev.dataTransfer.files[i].name);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
function dropHandler(ev) {
|
||
|
console.log('File(s) dropped');
|
||
|
|
||
|
globaldropfilelisthlpr = ev.dataTransfer;
|
||
|
transferitem = 0;
|
||
|
|
||
|
msgline("Please wait. Transferring file...");
|
||
|
|
||
|
// Prevent default behavior (Prevent file from being opened)
|
||
|
ev.preventDefault();
|
||
|
|
||
|
if (ev.dataTransfer.items) {
|
||
|
var data = ev.dataTransfer;
|
||
|
globaldropfilelisthlpr = data.files;
|
||
|
uploadFileProzessorhndlr = setInterval(uploadFileProzessor,1000);
|
||
|
console.log('Init upload list.');
|
||
|
} else {
|
||
|
// Use DataTransfer interface to access the file(s)
|
||
|
for (var i = 0; i < ev.dataTransfer.files.length; i++) {
|
||
|
console.log('.2. file[' + i + '].name = ' + ev.dataTransfer.files[i].name);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function dragOverHandler(ev) {
|
||
|
console.log('File(s) in drop zone');
|
||
|
|
||
|
// Prevent default behavior (Prevent file from being opened)
|
||
|
ev.preventDefault();
|
||
|
}
|
||
|
|
||
|
function msgline(msg) {
|
||
|
document.getElementById('msg').innerHTML = msg;
|
||
|
}
|
||
|
|
||
|
function downloadall() {
|
||
|
msgline("Sending all files in one zip.");
|
||
|
window.location.href = "/c?za=all";
|
||
|
msgline("");
|
||
|
}
|
||
|
|
||
|
//->
|
||
|
window.onload = getfileinsert;
|
||
|
|
||
|
)==x==";
|
||
|
|
||
|
|
||
|
//*****************************************************************************************************
|
||
|
static const char ESPxWebFlMgrWpcss[] PROGMEM = R"==g==(
|
||
|
|
||
|
div {
|
||
|
margin: 1px;
|
||
|
padding: 0px;
|
||
|
font-family: 'Segoe UI', Verdana, sans-serif;
|
||
|
}
|
||
|
|
||
|
#gc {
|
||
|
display: grid;
|
||
|
grid-template-columns: 80px 25% auto 30px;
|
||
|
grid-template-rows: 20px 30px auto 30px 20px;
|
||
|
grid-template-areas: "o1 o2 o3 o4" "m1 c c c" "m2 c c c" "m3 c c c" "u1 u2 u3 u4";
|
||
|
}
|
||
|
|
||
|
.o1 {
|
||
|
grid-area: o1;
|
||
|
background-color: #9999CC;
|
||
|
border-top-left-radius: 20px;
|
||
|
margin-bottom: 0px;
|
||
|
}
|
||
|
|
||
|
.o2 {
|
||
|
grid-area: o2;
|
||
|
background-color: #9999FF;
|
||
|
margin-bottom: 0px;
|
||
|
}
|
||
|
|
||
|
.o3 {
|
||
|
grid-area: o3;
|
||
|
background-color: #CC99CC;
|
||
|
margin-bottom: 0px;
|
||
|
white-space: nowrap;
|
||
|
}
|
||
|
|
||
|
.o4 {
|
||
|
grid-area: o4;
|
||
|
background-color: #CC6699;
|
||
|
border-radius: 0 10px 10px 0;
|
||
|
margin-bottom: 0px;
|
||
|
}
|
||
|
|
||
|
.m1 {
|
||
|
grid-area: m1;
|
||
|
margin-top: 0px;
|
||
|
background-color: #9999CC;
|
||
|
display: grid;
|
||
|
grid-template-columns: 60px 20px;
|
||
|
grid-template-rows: 20px;
|
||
|
grid-template-areas: "s11 s12";
|
||
|
}
|
||
|
|
||
|
.s12 {
|
||
|
margin: 0px;
|
||
|
background-color: #9999CC;
|
||
|
}
|
||
|
|
||
|
.s13 {
|
||
|
margin: 0px;
|
||
|
border-top-left-radius: 20px;
|
||
|
height: 30px;
|
||
|
}
|
||
|
|
||
|
.m2 {
|
||
|
display: flex;
|
||
|
justify-content: center;
|
||
|
align-items: center;
|
||
|
grid-area: m2;
|
||
|
background-color: #CC6699;
|
||
|
width: 60px;
|
||
|
}
|
||
|
|
||
|
.m3 {
|
||
|
grid-area: m3;
|
||
|
margin-bottom: 0px;
|
||
|
background-color: #9999CC;
|
||
|
display: grid;
|
||
|
grid-template-columns: 60px 20px;
|
||
|
grid-template-rows: 20px;
|
||
|
grid-template-areas: "s31 s32";
|
||
|
}
|
||
|
|
||
|
.s32 {
|
||
|
margin: 0px;
|
||
|
background-color: #9999CC;
|
||
|
}
|
||
|
|
||
|
.s33 {
|
||
|
margin: 0px;
|
||
|
border-bottom-left-radius: 20px;
|
||
|
height: 30px;
|
||
|
}
|
||
|
|
||
|
.u1 {
|
||
|
grid-area: u1;
|
||
|
background-color: #9999CC;
|
||
|
border-bottom-left-radius: 20px;
|
||
|
margin-top: 0px;
|
||
|
}
|
||
|
|
||
|
.u2 {
|
||
|
grid-area: u2;
|
||
|
cursor: pointer;
|
||
|
background-color: #CC6666;
|
||
|
margin-top: 0px;
|
||
|
padding-left: 10px;
|
||
|
vertical-align: middle;
|
||
|
font-size: 80%;
|
||
|
}
|
||
|
|
||
|
.u2:hover {
|
||
|
background-color: #9999FF;
|
||
|
color: white;
|
||
|
}
|
||
|
|
||
|
.u3 {
|
||
|
grid-area: u3;
|
||
|
padding-left: 10px;
|
||
|
background-color: #FF9966;
|
||
|
font-size: 80%;
|
||
|
margin-top: 0px;
|
||
|
}
|
||
|
|
||
|
.u4 {
|
||
|
grid-area: u4;
|
||
|
background-color: #FF9900;
|
||
|
border-radius: 0 10px 10px 0;
|
||
|
margin-top: 0px;
|
||
|
}
|
||
|
|
||
|
.c {
|
||
|
grid-area: c;
|
||
|
}
|
||
|
|
||
|
#fi .b {
|
||
|
background-color: Transparent;
|
||
|
border: 1px solid #9999FF;
|
||
|
border-radius: 1px;
|
||
|
padding: 0px;
|
||
|
width: 30px;
|
||
|
cursor: pointer;
|
||
|
}
|
||
|
|
||
|
#fi .b:hover {
|
||
|
background-color: #9999FF;
|
||
|
color: white;
|
||
|
}
|
||
|
|
||
|
.cc {
|
||
|
width: min-content;
|
||
|
margin: 10px 0px;
|
||
|
}
|
||
|
|
||
|
.gc div {
|
||
|
padding: 1px;
|
||
|
}
|
||
|
|
||
|
.ccg {
|
||
|
height: 1.5em;
|
||
|
background-color: #A5A5FF;
|
||
|
}
|
||
|
|
||
|
.ccu {
|
||
|
height: 1.5em;
|
||
|
background-color: #FE9A00;
|
||
|
}
|
||
|
|
||
|
.ccd {
|
||
|
height: 1.5em;
|
||
|
background-color: #e8e2d8;
|
||
|
}
|
||
|
|
||
|
.ccl {
|
||
|
border-radius: 5px 0 0 5px;
|
||
|
cursor: pointer;
|
||
|
}
|
||
|
|
||
|
.ccl:hover {
|
||
|
border-radius: 5px 0 0 5px;
|
||
|
color: white;
|
||
|
cursor: pointer;
|
||
|
}
|
||
|
|
||
|
.ccr {
|
||
|
border-radius: 0 5px 5px 0;
|
||
|
}
|
||
|
|
||
|
.cct {
|
||
|
text-align: right;
|
||
|
}
|
||
|
|
||
|
.gc {
|
||
|
display: grid;
|
||
|
grid-template-columns: repeat(3, max-content);
|
||
|
}
|
||
|
)==g==";
|
||
|
|
||
|
|
||
|
#endif
|