mirror of
https://github.com/0xFEEDC0DE64/arduino-esp32.git
synced 2025-06-29 03:50:58 +02:00
Update IDF to aaf1239 (#1539)
* fix sdmmc config * Fix warnings in EEPROM from @Curclamas * remove leftover TAG in EEPROM * Initial add of @stickbreaker i2c * Add log_n * fix warnings when log is off * i2c code clean up and reorganization * add flags to interrupt allocator * fix sdmmc config * Fix warnings in EEPROM from @Curclamas * remove leftover TAG in EEPROM * fix errors with latest IDF * fix debug optimization (#1365) incorrect optimization for debugging tick markers. * Fix some missing BT header * Change BTSerial log calls * Update BLE lib * Arduino-ESP32 release management scripted (#1515) * Calculate an absolute path for a custom partitions table (#1452) * * Arduino-ESP32 release management scripted (ready-to-merge) * * secure env for espressif/arduino-esp32 * * build tests enabled * gitter webhook enabled * * gitter room link fixed * better comment * * filepaths fixed * BT Serial adjustments * * don't run sketch builds & tests for tagged builds * Return false from WiFi.hostByName() if hostname is not resolved * Free BT Memory when BT is not used * WIFI_MODE_NULL is not supported anymore * Select some key examples to build with PlatformIO to save some time * Update BLE lib * Fixed BLE lib * Major WiFi overhaul - auto reconnect on connection loss now works - moved to event groups - some code clean up and procedure optimizations - new methods to get a more elaborate system ststus * Add cmake tests to travis * Add initial AsyncUDP * Add NetBIOS lib and fix CMake includes * Add Initial WebServer * Fix WebServer and examples * travis not quiting on build fail * Try different travis build * Update IDF to aaf1239 * Fix WPS Example * fix script permission and add some fail tests to sketch builder * Add missing space in WiFiClient::write(Stream &stream)
This commit is contained in:
313
libraries/WebServer/examples/SDWebServer/SDWebServer.ino
Normal file
313
libraries/WebServer/examples/SDWebServer/SDWebServer.ino
Normal file
@ -0,0 +1,313 @@
|
||||
/*
|
||||
SDWebServer - Example WebServer with SD Card backend for esp8266
|
||||
|
||||
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
|
||||
This file is part of the WebServer library for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Have a FAT Formatted SD Card connected to the SPI port of the ESP8266
|
||||
The web root is the SD Card root folder
|
||||
File extensions with more than 3 charecters are not supported by the SD Library
|
||||
File Names longer than 8 charecters will be truncated by the SD library, so keep filenames shorter
|
||||
index.htm is the default index (works on subfolders as well)
|
||||
|
||||
upload the contents of SdRoot to the root of the SDcard and access the editor by going to http://esp8266sd.local/edit
|
||||
|
||||
*/
|
||||
#include <WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <WebServer.h>
|
||||
#include <ESPmDNS.h>
|
||||
#include <SPI.h>
|
||||
#include <SD.h>
|
||||
|
||||
#define DBG_OUTPUT_PORT Serial
|
||||
|
||||
const char* ssid = "**********";
|
||||
const char* password = "**********";
|
||||
const char* host = "esp32sd";
|
||||
|
||||
WebServer server(80);
|
||||
|
||||
static bool hasSD = false;
|
||||
File uploadFile;
|
||||
|
||||
|
||||
void returnOK() {
|
||||
server.send(200, "text/plain", "");
|
||||
}
|
||||
|
||||
void returnFail(String msg) {
|
||||
server.send(500, "text/plain", msg + "\r\n");
|
||||
}
|
||||
|
||||
bool loadFromSdCard(String path) {
|
||||
String dataType = "text/plain";
|
||||
if (path.endsWith("/")) {
|
||||
path += "index.htm";
|
||||
}
|
||||
|
||||
if (path.endsWith(".src")) {
|
||||
path = path.substring(0, path.lastIndexOf("."));
|
||||
} else if (path.endsWith(".htm")) {
|
||||
dataType = "text/html";
|
||||
} else if (path.endsWith(".css")) {
|
||||
dataType = "text/css";
|
||||
} else if (path.endsWith(".js")) {
|
||||
dataType = "application/javascript";
|
||||
} else if (path.endsWith(".png")) {
|
||||
dataType = "image/png";
|
||||
} else if (path.endsWith(".gif")) {
|
||||
dataType = "image/gif";
|
||||
} else if (path.endsWith(".jpg")) {
|
||||
dataType = "image/jpeg";
|
||||
} else if (path.endsWith(".ico")) {
|
||||
dataType = "image/x-icon";
|
||||
} else if (path.endsWith(".xml")) {
|
||||
dataType = "text/xml";
|
||||
} else if (path.endsWith(".pdf")) {
|
||||
dataType = "application/pdf";
|
||||
} else if (path.endsWith(".zip")) {
|
||||
dataType = "application/zip";
|
||||
}
|
||||
|
||||
File dataFile = SD.open(path.c_str());
|
||||
if (dataFile.isDirectory()) {
|
||||
path += "/index.htm";
|
||||
dataType = "text/html";
|
||||
dataFile = SD.open(path.c_str());
|
||||
}
|
||||
|
||||
if (!dataFile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (server.hasArg("download")) {
|
||||
dataType = "application/octet-stream";
|
||||
}
|
||||
|
||||
if (server.streamFile(dataFile, dataType) != dataFile.size()) {
|
||||
DBG_OUTPUT_PORT.println("Sent less data than expected!");
|
||||
}
|
||||
|
||||
dataFile.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
void handleFileUpload() {
|
||||
if (server.uri() != "/edit") {
|
||||
return;
|
||||
}
|
||||
HTTPUpload& upload = server.upload();
|
||||
if (upload.status == UPLOAD_FILE_START) {
|
||||
if (SD.exists((char *)upload.filename.c_str())) {
|
||||
SD.remove((char *)upload.filename.c_str());
|
||||
}
|
||||
uploadFile = SD.open(upload.filename.c_str(), FILE_WRITE);
|
||||
DBG_OUTPUT_PORT.print("Upload: START, filename: "); DBG_OUTPUT_PORT.println(upload.filename);
|
||||
} else if (upload.status == UPLOAD_FILE_WRITE) {
|
||||
if (uploadFile) {
|
||||
uploadFile.write(upload.buf, upload.currentSize);
|
||||
}
|
||||
DBG_OUTPUT_PORT.print("Upload: WRITE, Bytes: "); DBG_OUTPUT_PORT.println(upload.currentSize);
|
||||
} else if (upload.status == UPLOAD_FILE_END) {
|
||||
if (uploadFile) {
|
||||
uploadFile.close();
|
||||
}
|
||||
DBG_OUTPUT_PORT.print("Upload: END, Size: "); DBG_OUTPUT_PORT.println(upload.totalSize);
|
||||
}
|
||||
}
|
||||
|
||||
void deleteRecursive(String path) {
|
||||
File file = SD.open((char *)path.c_str());
|
||||
if (!file.isDirectory()) {
|
||||
file.close();
|
||||
SD.remove((char *)path.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
file.rewindDirectory();
|
||||
while (true) {
|
||||
File entry = file.openNextFile();
|
||||
if (!entry) {
|
||||
break;
|
||||
}
|
||||
String entryPath = path + "/" + entry.name();
|
||||
if (entry.isDirectory()) {
|
||||
entry.close();
|
||||
deleteRecursive(entryPath);
|
||||
} else {
|
||||
entry.close();
|
||||
SD.remove((char *)entryPath.c_str());
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
SD.rmdir((char *)path.c_str());
|
||||
file.close();
|
||||
}
|
||||
|
||||
void handleDelete() {
|
||||
if (server.args() == 0) {
|
||||
return returnFail("BAD ARGS");
|
||||
}
|
||||
String path = server.arg(0);
|
||||
if (path == "/" || !SD.exists((char *)path.c_str())) {
|
||||
returnFail("BAD PATH");
|
||||
return;
|
||||
}
|
||||
deleteRecursive(path);
|
||||
returnOK();
|
||||
}
|
||||
|
||||
void handleCreate() {
|
||||
if (server.args() == 0) {
|
||||
return returnFail("BAD ARGS");
|
||||
}
|
||||
String path = server.arg(0);
|
||||
if (path == "/" || SD.exists((char *)path.c_str())) {
|
||||
returnFail("BAD PATH");
|
||||
return;
|
||||
}
|
||||
|
||||
if (path.indexOf('.') > 0) {
|
||||
File file = SD.open((char *)path.c_str(), FILE_WRITE);
|
||||
if (file) {
|
||||
file.write(0);
|
||||
file.close();
|
||||
}
|
||||
} else {
|
||||
SD.mkdir((char *)path.c_str());
|
||||
}
|
||||
returnOK();
|
||||
}
|
||||
|
||||
void printDirectory() {
|
||||
if (!server.hasArg("dir")) {
|
||||
return returnFail("BAD ARGS");
|
||||
}
|
||||
String path = server.arg("dir");
|
||||
if (path != "/" && !SD.exists((char *)path.c_str())) {
|
||||
return returnFail("BAD PATH");
|
||||
}
|
||||
File dir = SD.open((char *)path.c_str());
|
||||
path = String();
|
||||
if (!dir.isDirectory()) {
|
||||
dir.close();
|
||||
return returnFail("NOT DIR");
|
||||
}
|
||||
dir.rewindDirectory();
|
||||
server.setContentLength(CONTENT_LENGTH_UNKNOWN);
|
||||
server.send(200, "text/json", "");
|
||||
WiFiClient client = server.client();
|
||||
|
||||
server.sendContent("[");
|
||||
for (int cnt = 0; true; ++cnt) {
|
||||
File entry = dir.openNextFile();
|
||||
if (!entry) {
|
||||
break;
|
||||
}
|
||||
|
||||
String output;
|
||||
if (cnt > 0) {
|
||||
output = ',';
|
||||
}
|
||||
|
||||
output += "{\"type\":\"";
|
||||
output += (entry.isDirectory()) ? "dir" : "file";
|
||||
output += "\",\"name\":\"";
|
||||
output += entry.name();
|
||||
output += "\"";
|
||||
output += "}";
|
||||
server.sendContent(output);
|
||||
entry.close();
|
||||
}
|
||||
server.sendContent("]");
|
||||
dir.close();
|
||||
}
|
||||
|
||||
void handleNotFound() {
|
||||
if (hasSD && loadFromSdCard(server.uri())) {
|
||||
return;
|
||||
}
|
||||
String message = "SDCARD Not Detected\n\n";
|
||||
message += "URI: ";
|
||||
message += server.uri();
|
||||
message += "\nMethod: ";
|
||||
message += (server.method() == HTTP_GET) ? "GET" : "POST";
|
||||
message += "\nArguments: ";
|
||||
message += server.args();
|
||||
message += "\n";
|
||||
for (uint8_t i = 0; i < server.args(); i++) {
|
||||
message += " NAME:" + server.argName(i) + "\n VALUE:" + server.arg(i) + "\n";
|
||||
}
|
||||
server.send(404, "text/plain", message);
|
||||
DBG_OUTPUT_PORT.print(message);
|
||||
}
|
||||
|
||||
void setup(void) {
|
||||
DBG_OUTPUT_PORT.begin(115200);
|
||||
DBG_OUTPUT_PORT.setDebugOutput(true);
|
||||
DBG_OUTPUT_PORT.print("\n");
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(ssid, password);
|
||||
DBG_OUTPUT_PORT.print("Connecting to ");
|
||||
DBG_OUTPUT_PORT.println(ssid);
|
||||
|
||||
// Wait for connection
|
||||
uint8_t i = 0;
|
||||
while (WiFi.status() != WL_CONNECTED && i++ < 20) {//wait 10 seconds
|
||||
delay(500);
|
||||
}
|
||||
if (i == 21) {
|
||||
DBG_OUTPUT_PORT.print("Could not connect to");
|
||||
DBG_OUTPUT_PORT.println(ssid);
|
||||
while (1) {
|
||||
delay(500);
|
||||
}
|
||||
}
|
||||
DBG_OUTPUT_PORT.print("Connected! IP address: ");
|
||||
DBG_OUTPUT_PORT.println(WiFi.localIP());
|
||||
|
||||
if (MDNS.begin(host)) {
|
||||
MDNS.addService("http", "tcp", 80);
|
||||
DBG_OUTPUT_PORT.println("MDNS responder started");
|
||||
DBG_OUTPUT_PORT.print("You can now connect to http://");
|
||||
DBG_OUTPUT_PORT.print(host);
|
||||
DBG_OUTPUT_PORT.println(".local");
|
||||
}
|
||||
|
||||
|
||||
server.on("/list", HTTP_GET, printDirectory);
|
||||
server.on("/edit", HTTP_DELETE, handleDelete);
|
||||
server.on("/edit", HTTP_PUT, handleCreate);
|
||||
server.on("/edit", HTTP_POST, []() {
|
||||
returnOK();
|
||||
}, handleFileUpload);
|
||||
server.onNotFound(handleNotFound);
|
||||
|
||||
server.begin();
|
||||
DBG_OUTPUT_PORT.println("HTTP server started");
|
||||
|
||||
if (SD.begin(SS)) {
|
||||
DBG_OUTPUT_PORT.println("SD Card initialized.");
|
||||
hasSD = true;
|
||||
}
|
||||
}
|
||||
|
||||
void loop(void) {
|
||||
server.handleClient();
|
||||
}
|
674
libraries/WebServer/examples/SDWebServer/SdRoot/edit/index.htm
Normal file
674
libraries/WebServer/examples/SDWebServer/SdRoot/edit/index.htm
Normal file
@ -0,0 +1,674 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>SD Editor</title>
|
||||
<style type="text/css" media="screen">
|
||||
.contextMenu {
|
||||
z-index: 300;
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
border: 1px solid #444;
|
||||
background-color: #F5F5F5;
|
||||
display: none;
|
||||
box-shadow: 0 0 10px rgba( 0, 0, 0, .4 );
|
||||
font-size: 12px;
|
||||
font-family: sans-serif;
|
||||
font-weight:bold;
|
||||
}
|
||||
.contextMenu ul {
|
||||
list-style: none;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.contextMenu li {
|
||||
position: relative;
|
||||
min-width: 60px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.contextMenu span {
|
||||
color: #444;
|
||||
display: inline-block;
|
||||
padding: 6px;
|
||||
}
|
||||
.contextMenu li:hover { background: #444; }
|
||||
.contextMenu li:hover span { color: #EEE; }
|
||||
|
||||
.css-treeview ul, .css-treeview li {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.css-treeview input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.css-treeview {
|
||||
font: normal 11px Verdana, Arial, Sans-serif;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.css-treeview span {
|
||||
color: #00f;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.css-treeview span:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.css-treeview input + label + ul {
|
||||
margin: 0 0 0 22px;
|
||||
}
|
||||
|
||||
.css-treeview input ~ ul {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.css-treeview label, .css-treeview label::before {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.css-treeview input:disabled + label {
|
||||
cursor: default;
|
||||
opacity: .6;
|
||||
}
|
||||
|
||||
.css-treeview input:checked:not(:disabled) ~ ul {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.css-treeview label, .css-treeview label::before {
|
||||
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAACgCAYAAAAFOewUAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAApxJREFUeNrslM1u00AQgGdthyalFFOK+ClIIKQKyqUVQvTEE3DmAhLwAhU8QZoH4A2Q2gMSFace4MCtJ8SPBFwAkRuiHKpA6sRN/Lu7zG5i14kctaUqRGhGXnu9O/Pt7MzsMiklvF+9t2kWTDvyIrAsA0aKRRi1T0C/hJ4LUbt5/8rNpWVlp8RSr9J40b48fxFaTQ9+ft8EZ6MJYb0Ok+dnYGpmPgXwKIAvLx8vYXc5GdMAQJgQEkpjRTh36TS2U+DWW/D17WuYgm8pwJyY1npZsZKOxImOV1I/h4+O6vEg5GCZBpgmA6hX8wHKUHDRBXQYicQ4rlc3Tf0VMs8DHBS864F2YFspjgUYjKX/Az3gsdQd2eeBHwmdGWXHcgBGSkZXOXohcEXebRoQcAgjqediNY+AVyu3Z3sAKqfKoGMsewBeEIOPgQxxPJIjcGH6qtL/0AdADzKGnuuD+2tLK7Q8DhHHbOBW+KEzcHLuYc82MkEUekLiwuvVH+guQBQzOG4XdAb8EOcRcqQvDkY2iCLuxECJ43JobMXoutqGgDa2T7UqLKwt9KRyuxKVByqVXXqIoCCUCAqhUOioTWC7G4TQEOD0APy2/7G2Xpu1J4+lxeQ4TXBbITDpoVelRN/BVFbwu5oMMJUBhoXy5tmdRcMwymP2OLQaLjx9/vnBo6V3K6izATmSnMa0Dq7ferIohJhr1p01zrlz49rZF4OMs8JkX23vVQzYp+wbYGV/KpXKjvspl8tsIKCrMNAYFxj2GKS5ZWxg4ewKsJfaGMIY5KXqPz8LBBj6+yDvVP79+yDp/9F9oIx3OisHWwe7Oal0HxCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgwD8E/BZgAP0qhKj3rXO7AAAAAElFTkSuQmCC") no-repeat;
|
||||
}
|
||||
|
||||
.css-treeview label, .css-treeview span, .css-treeview label::before {
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.css-treeview label {
|
||||
background-position: 18px 0;
|
||||
}
|
||||
|
||||
.css-treeview label::before {
|
||||
content: "";
|
||||
width: 16px;
|
||||
margin: 0 22px 0 0;
|
||||
vertical-align: middle;
|
||||
background-position: 0 -32px;
|
||||
}
|
||||
|
||||
.css-treeview input:checked + label::before {
|
||||
background-position: 0 -16px;
|
||||
}
|
||||
|
||||
/* webkit adjacent element selector bugfix */
|
||||
@media screen and (-webkit-min-device-pixel-ratio:0)
|
||||
{
|
||||
.css-treeview{
|
||||
-webkit-animation: webkit-adjacent-element-selector-bugfix infinite 1s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes webkit-adjacent-element-selector-bugfix
|
||||
{
|
||||
from {
|
||||
padding: 0;
|
||||
}
|
||||
to {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#uploader {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
height:28px;
|
||||
line-height: 24px;
|
||||
padding-left: 10px;
|
||||
background-color: #444;
|
||||
color:#EEE;
|
||||
}
|
||||
#tree {
|
||||
position: absolute;
|
||||
top: 28px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width:200px;
|
||||
padding: 8px;
|
||||
}
|
||||
#editor, #preview {
|
||||
position: absolute;
|
||||
top: 28px;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 200px;
|
||||
}
|
||||
#preview {
|
||||
background-color: #EEE;
|
||||
padding:5px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function createFileUploader(element, tree, editor){
|
||||
var xmlHttp;
|
||||
var input = document.createElement("input");
|
||||
input.type = "file";
|
||||
input.multiple = false;
|
||||
input.name = "data";
|
||||
document.getElementById(element).appendChild(input);
|
||||
var path = document.createElement("input");
|
||||
path.id = "upload-path";
|
||||
path.type = "text";
|
||||
path.name = "path";
|
||||
path.defaultValue = "/";
|
||||
document.getElementById(element).appendChild(path);
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = 'Upload';
|
||||
document.getElementById(element).appendChild(button);
|
||||
var mkdir = document.createElement("button");
|
||||
mkdir.innerHTML = 'MkDir';
|
||||
document.getElementById(element).appendChild(mkdir);
|
||||
var mkfile = document.createElement("button");
|
||||
mkfile.innerHTML = 'MkFile';
|
||||
document.getElementById(element).appendChild(mkfile);
|
||||
|
||||
function httpPostProcessRequest(){
|
||||
if (xmlHttp.readyState == 4){
|
||||
if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
|
||||
else {
|
||||
tree.refreshPath(path.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
function createPath(p){
|
||||
xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.onreadystatechange = httpPostProcessRequest;
|
||||
var formData = new FormData();
|
||||
formData.append("path", p);
|
||||
xmlHttp.open("PUT", "/edit");
|
||||
xmlHttp.send(formData);
|
||||
}
|
||||
|
||||
mkfile.onclick = function(e){
|
||||
if(path.value.indexOf(".") === -1) return;
|
||||
createPath(path.value);
|
||||
editor.loadUrl(path.value);
|
||||
};
|
||||
mkdir.onclick = function(e){
|
||||
if(path.value.length < 2) return;
|
||||
var dir = path.value
|
||||
if(dir.indexOf(".") !== -1){
|
||||
if(dir.lastIndexOf("/") === 0) return;
|
||||
dir = dir.substring(0, dir.lastIndexOf("/"));
|
||||
}
|
||||
createPath(dir);
|
||||
};
|
||||
button.onclick = function(e){
|
||||
if(input.files.length === 0){
|
||||
return;
|
||||
}
|
||||
xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.onreadystatechange = httpPostProcessRequest;
|
||||
var formData = new FormData();
|
||||
formData.append("data", input.files[0], path.value);
|
||||
xmlHttp.open("POST", "/edit");
|
||||
xmlHttp.send(formData);
|
||||
}
|
||||
input.onchange = function(e){
|
||||
if(input.files.length === 0) return;
|
||||
var filename = input.files[0].name;
|
||||
var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
|
||||
var name = /(.*)\.[^.]+$/.exec(filename)[1];
|
||||
if(typeof name !== undefined){
|
||||
if(name.length > 8) name = name.substring(0, 8);
|
||||
filename = name;
|
||||
}
|
||||
if(typeof ext !== undefined){
|
||||
if(ext === "html") ext = "htm";
|
||||
else if(ext === "jpeg") ext = "jpg";
|
||||
filename = filename + "." + ext;
|
||||
}
|
||||
if(path.value === "/" || path.value.lastIndexOf("/") === 0){
|
||||
path.value = "/"+filename;
|
||||
} else {
|
||||
path.value = path.value.substring(0, path.value.lastIndexOf("/")+1)+filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createTree(element, editor){
|
||||
var preview = document.getElementById("preview");
|
||||
var treeRoot = document.createElement("div");
|
||||
treeRoot.className = "css-treeview";
|
||||
document.getElementById(element).appendChild(treeRoot);
|
||||
|
||||
function loadDownload(path){
|
||||
document.getElementById('download-frame').src = path+"?download=true";
|
||||
}
|
||||
|
||||
function loadPreview(path){
|
||||
document.getElementById("editor").style.display = "none";
|
||||
preview.style.display = "block";
|
||||
preview.innerHTML = '<img src="'+path+'" style="max-width:100%; max-height:100%; margin:auto; display:block;" />';
|
||||
}
|
||||
|
||||
function fillFolderMenu(el, path){
|
||||
var list = document.createElement("ul");
|
||||
el.appendChild(list);
|
||||
var action = document.createElement("li");
|
||||
list.appendChild(action);
|
||||
var isChecked = document.getElementById(path).checked;
|
||||
var expnd = document.createElement("li");
|
||||
list.appendChild(expnd);
|
||||
if(isChecked){
|
||||
expnd.innerHTML = "<span>Collapse</span>";
|
||||
expnd.onclick = function(e){
|
||||
document.getElementById(path).checked = false;
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
var refrsh = document.createElement("li");
|
||||
list.appendChild(refrsh);
|
||||
refrsh.innerHTML = "<span>Refresh</span>";
|
||||
refrsh.onclick = function(e){
|
||||
var leaf = document.getElementById(path).parentNode;
|
||||
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||
httpGet(leaf, path);
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
} else {
|
||||
expnd.innerHTML = "<span>Expand</span>";
|
||||
expnd.onclick = function(e){
|
||||
document.getElementById(path).checked = true;
|
||||
var leaf = document.getElementById(path).parentNode;
|
||||
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||
httpGet(leaf, path);
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
}
|
||||
var upload = document.createElement("li");
|
||||
list.appendChild(upload);
|
||||
upload.innerHTML = "<span>Upload</span>";
|
||||
upload.onclick = function(e){
|
||||
var pathEl = document.getElementById("upload-path");
|
||||
if(pathEl){
|
||||
var subPath = pathEl.value;
|
||||
if(subPath.lastIndexOf("/") < 1) pathEl.value = path+subPath;
|
||||
else pathEl.value = path.substring(subPath.lastIndexOf("/"))+subPath;
|
||||
}
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
var delFile = document.createElement("li");
|
||||
list.appendChild(delFile);
|
||||
delFile.innerHTML = "<span>Delete</span>";
|
||||
delFile.onclick = function(e){
|
||||
httpDelete(path);
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
}
|
||||
|
||||
function fillFileMenu(el, path){
|
||||
var list = document.createElement("ul");
|
||||
el.appendChild(list);
|
||||
var action = document.createElement("li");
|
||||
list.appendChild(action);
|
||||
if(isTextFile(path)){
|
||||
action.innerHTML = "<span>Edit</span>";
|
||||
action.onclick = function(e){
|
||||
editor.loadUrl(path);
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
} else if(isImageFile(path)){
|
||||
action.innerHTML = "<span>Preview</span>";
|
||||
action.onclick = function(e){
|
||||
loadPreview(path);
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
}
|
||||
var download = document.createElement("li");
|
||||
list.appendChild(download);
|
||||
download.innerHTML = "<span>Download</span>";
|
||||
download.onclick = function(e){
|
||||
loadDownload(path);
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
var delFile = document.createElement("li");
|
||||
list.appendChild(delFile);
|
||||
delFile.innerHTML = "<span>Delete</span>";
|
||||
delFile.onclick = function(e){
|
||||
httpDelete(path);
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
}
|
||||
|
||||
function showContextMenu(e, path, isfile){
|
||||
var divContext = document.createElement("div");
|
||||
var scrollTop = document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop;
|
||||
var scrollLeft = document.body.scrollLeft ? document.body.scrollLeft : document.documentElement.scrollLeft;
|
||||
var left = e.clientX + scrollLeft;
|
||||
var top = e.clientY + scrollTop;
|
||||
divContext.className = 'contextMenu';
|
||||
divContext.style.display = 'block';
|
||||
divContext.style.left = left + 'px';
|
||||
divContext.style.top = top + 'px';
|
||||
if(isfile) fillFileMenu(divContext, path);
|
||||
else fillFolderMenu(divContext, path);
|
||||
document.body.appendChild(divContext);
|
||||
var width = divContext.offsetWidth;
|
||||
var height = divContext.offsetHeight;
|
||||
divContext.onmouseout = function(e){
|
||||
if(e.clientX < left || e.clientX > (left + width) || e.clientY < top || e.clientY > (top + height)){
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(divContext);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function createTreeLeaf(path, name, size){
|
||||
var leaf = document.createElement("li");
|
||||
leaf.id = (((path == "/")?"":path)+"/"+name).toLowerCase();
|
||||
var label = document.createElement("span");
|
||||
label.textContent = name.toLowerCase();
|
||||
leaf.appendChild(label);
|
||||
leaf.onclick = function(e){
|
||||
if(isTextFile(leaf.id)){
|
||||
editor.loadUrl(leaf.id);
|
||||
} else if(isImageFile(leaf.id)){
|
||||
loadPreview(leaf.id);
|
||||
}
|
||||
};
|
||||
leaf.oncontextmenu = function(e){
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
showContextMenu(e, leaf.id, true);
|
||||
};
|
||||
return leaf;
|
||||
}
|
||||
|
||||
function createTreeBranch(path, name, disabled){
|
||||
var leaf = document.createElement("li");
|
||||
var check = document.createElement("input");
|
||||
check.type = "checkbox";
|
||||
check.id = (((path == "/")?"":path)+"/"+name).toLowerCase();
|
||||
if(typeof disabled !== "undefined" && disabled) check.disabled = "disabled";
|
||||
leaf.appendChild(check);
|
||||
var label = document.createElement("label");
|
||||
label.for = check.id;
|
||||
label.textContent = name.toLowerCase();
|
||||
leaf.appendChild(label);
|
||||
check.onchange = function(e){
|
||||
if(check.checked){
|
||||
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||
httpGet(leaf, check.id);
|
||||
}
|
||||
};
|
||||
label.onclick = function(e){
|
||||
if(!check.checked){
|
||||
check.checked = true;
|
||||
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||
httpGet(leaf, check.id);
|
||||
} else {
|
||||
check.checked = false;
|
||||
}
|
||||
};
|
||||
leaf.oncontextmenu = function(e){
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
showContextMenu(e, check.id, false);
|
||||
}
|
||||
return leaf;
|
||||
}
|
||||
|
||||
function addList(parent, path, items){
|
||||
var list = document.createElement("ul");
|
||||
parent.appendChild(list);
|
||||
var ll = items.length;
|
||||
for(var i = 0; i < ll; i++){
|
||||
var item = items[i];
|
||||
var itemEl;
|
||||
if(item.type === "file"){
|
||||
itemEl = createTreeLeaf(path, item.name, item.size);
|
||||
} else {
|
||||
itemEl = createTreeBranch(path, item.name);
|
||||
}
|
||||
list.appendChild(itemEl);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function isTextFile(path){
|
||||
var ext = /(?:\.([^.]+))?$/.exec(path)[1];
|
||||
if(typeof ext !== undefined){
|
||||
switch(ext){
|
||||
case "txt":
|
||||
case "htm":
|
||||
case "html":
|
||||
case "js":
|
||||
case "json":
|
||||
case "c":
|
||||
case "h":
|
||||
case "cpp":
|
||||
case "css":
|
||||
case "xml":
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isImageFile(path){
|
||||
var ext = /(?:\.([^.]+))?$/.exec(path)[1];
|
||||
if(typeof ext !== undefined){
|
||||
switch(ext){
|
||||
case "png":
|
||||
case "jpg":
|
||||
case "gif":
|
||||
case "ico":
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.refreshPath = function(path){
|
||||
if(path.lastIndexOf('/') < 1){
|
||||
path = '/';
|
||||
treeRoot.removeChild(treeRoot.childNodes[0]);
|
||||
httpGet(treeRoot, "/");
|
||||
} else {
|
||||
path = path.substring(0, path.lastIndexOf('/'));
|
||||
var leaf = document.getElementById(path).parentNode;
|
||||
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||
httpGet(leaf, path);
|
||||
}
|
||||
};
|
||||
|
||||
function delCb(path){
|
||||
return function(){
|
||||
if (xmlHttp.readyState == 4){
|
||||
if(xmlHttp.status != 200){
|
||||
alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
|
||||
} else {
|
||||
if(path.lastIndexOf('/') < 1){
|
||||
path = '/';
|
||||
treeRoot.removeChild(treeRoot.childNodes[0]);
|
||||
httpGet(treeRoot, "/");
|
||||
} else {
|
||||
path = path.substring(0, path.lastIndexOf('/'));
|
||||
var leaf = document.getElementById(path).parentNode;
|
||||
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||
httpGet(leaf, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function httpDelete(filename){
|
||||
xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.onreadystatechange = delCb(filename);
|
||||
var formData = new FormData();
|
||||
formData.append("path", filename);
|
||||
xmlHttp.open("DELETE", "/edit");
|
||||
xmlHttp.send(formData);
|
||||
}
|
||||
|
||||
function getCb(parent, path){
|
||||
return function(){
|
||||
if (xmlHttp.readyState == 4){
|
||||
//clear loading
|
||||
if(xmlHttp.status == 200) addList(parent, path, JSON.parse(xmlHttp.responseText));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function httpGet(parent, path){
|
||||
xmlHttp = new XMLHttpRequest(parent, path);
|
||||
xmlHttp.onreadystatechange = getCb(parent, path);
|
||||
xmlHttp.open("GET", "/list?dir="+path, true);
|
||||
xmlHttp.send(null);
|
||||
//start loading
|
||||
}
|
||||
|
||||
httpGet(treeRoot, "/");
|
||||
return this;
|
||||
}
|
||||
|
||||
function createEditor(element, file, lang, theme, type){
|
||||
function getLangFromFilename(filename){
|
||||
var lang = "plain";
|
||||
var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
|
||||
if(typeof ext !== undefined){
|
||||
switch(ext){
|
||||
case "txt": lang = "plain"; break;
|
||||
case "htm": lang = "html"; break;
|
||||
case "js": lang = "javascript"; break;
|
||||
case "c": lang = "c_cpp"; break;
|
||||
case "cpp": lang = "c_cpp"; break;
|
||||
case "css":
|
||||
case "scss":
|
||||
case "php":
|
||||
case "html":
|
||||
case "json":
|
||||
case "xml":
|
||||
lang = ext;
|
||||
}
|
||||
}
|
||||
return lang;
|
||||
}
|
||||
|
||||
if(typeof file === "undefined") file = "/index.htm";
|
||||
|
||||
if(typeof lang === "undefined"){
|
||||
lang = getLangFromFilename(file);
|
||||
}
|
||||
|
||||
if(typeof theme === "undefined") theme = "textmate";
|
||||
|
||||
if(typeof type === "undefined"){
|
||||
type = "text/"+lang;
|
||||
if(lang === "c_cpp") type = "text/plain";
|
||||
}
|
||||
|
||||
var xmlHttp = null;
|
||||
var editor = ace.edit(element);
|
||||
|
||||
//post
|
||||
function httpPostProcessRequest(){
|
||||
if (xmlHttp.readyState == 4){
|
||||
if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
|
||||
}
|
||||
}
|
||||
function httpPost(filename, data, type){
|
||||
xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.onreadystatechange = httpPostProcessRequest;
|
||||
var formData = new FormData();
|
||||
formData.append("data", new Blob([data], { type: type }), filename);
|
||||
xmlHttp.open("POST", "/edit");
|
||||
xmlHttp.send(formData);
|
||||
}
|
||||
//get
|
||||
function httpGetProcessRequest(){
|
||||
if (xmlHttp.readyState == 4){
|
||||
document.getElementById("preview").style.display = "none";
|
||||
document.getElementById("editor").style.display = "block";
|
||||
if(xmlHttp.status == 200) editor.setValue(xmlHttp.responseText);
|
||||
else editor.setValue("");
|
||||
editor.clearSelection();
|
||||
}
|
||||
}
|
||||
function httpGet(theUrl){
|
||||
xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.onreadystatechange = httpGetProcessRequest;
|
||||
xmlHttp.open("GET", theUrl, true);
|
||||
xmlHttp.send(null);
|
||||
}
|
||||
|
||||
if(lang !== "plain") editor.getSession().setMode("ace/mode/"+lang);
|
||||
editor.setTheme("ace/theme/"+theme);
|
||||
editor.$blockScrolling = Infinity;
|
||||
editor.getSession().setUseSoftTabs(true);
|
||||
editor.getSession().setTabSize(2);
|
||||
editor.setHighlightActiveLine(true);
|
||||
editor.setShowPrintMargin(false);
|
||||
editor.commands.addCommand({
|
||||
name: 'saveCommand',
|
||||
bindKey: {win: 'Ctrl-S', mac: 'Command-S'},
|
||||
exec: function(editor) {
|
||||
httpPost(file, editor.getValue()+"", type);
|
||||
},
|
||||
readOnly: false
|
||||
});
|
||||
editor.commands.addCommand({
|
||||
name: 'undoCommand',
|
||||
bindKey: {win: 'Ctrl-Z', mac: 'Command-Z'},
|
||||
exec: function(editor) {
|
||||
editor.getSession().getUndoManager().undo(false);
|
||||
},
|
||||
readOnly: false
|
||||
});
|
||||
editor.commands.addCommand({
|
||||
name: 'redoCommand',
|
||||
bindKey: {win: 'Ctrl-Shift-Z', mac: 'Command-Shift-Z'},
|
||||
exec: function(editor) {
|
||||
editor.getSession().getUndoManager().redo(false);
|
||||
},
|
||||
readOnly: false
|
||||
});
|
||||
httpGet(file);
|
||||
editor.loadUrl = function(filename){
|
||||
file = filename;
|
||||
lang = getLangFromFilename(file);
|
||||
type = "text/"+lang;
|
||||
if(lang !== "plain") editor.getSession().setMode("ace/mode/"+lang);
|
||||
httpGet(file);
|
||||
}
|
||||
return editor;
|
||||
}
|
||||
function onBodyLoad(){
|
||||
var vars = {};
|
||||
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) { vars[key] = value; });
|
||||
var editor = createEditor("editor", vars.file, vars.lang, vars.theme);
|
||||
var tree = createTree("tree", editor);
|
||||
createFileUploader("uploader", tree, editor);
|
||||
};
|
||||
</script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.9/ace.js" type="text/javascript" charset="utf-8"></script>
|
||||
</head>
|
||||
<body onload="onBodyLoad();">
|
||||
<div id="uploader"></div>
|
||||
<div id="tree"></div>
|
||||
<div id="editor"></div>
|
||||
<div id="preview" style="display:none;"></div>
|
||||
<iframe id=download-frame style='display:none;'></iframe>
|
||||
</body>
|
||||
</html>
|
22
libraries/WebServer/examples/SDWebServer/SdRoot/index.htm
Normal file
22
libraries/WebServer/examples/SDWebServer/SdRoot/index.htm
Normal file
@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||
<title>ESP Index</title>
|
||||
<style>
|
||||
body {
|
||||
background-color:black;
|
||||
color:white;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
function onBodyLoad(){
|
||||
console.log("we are loaded!!");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body id="index" onload="onBodyLoad()">
|
||||
<h1>ESP8266 Pin Functions</h1>
|
||||
<img src="pins.png" />
|
||||
</body>
|
||||
</html>
|
BIN
libraries/WebServer/examples/SDWebServer/SdRoot/pins.png
Normal file
BIN
libraries/WebServer/examples/SDWebServer/SdRoot/pins.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 174 KiB |
Reference in New Issue
Block a user