connectcore-demo-example: dashboard: implement file system calls

https://onedigi.atlassian.net/browse/DEL-7742

Signed-off-by: Tatiana Leon <Tatiana.Leon@digi.com>
This commit is contained in:
Tatiana Leon 2022-05-05 17:48:40 +02:00
parent 0943812956
commit e34b7c2c43
5 changed files with 177 additions and 17 deletions

View File

@ -15,6 +15,7 @@
# PERFORMANCE OF THIS SOFTWARE.
import argparse
import cgi
import http.server
import json
import logging
@ -139,6 +140,153 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler):
# Send the JSON value.
self.wfile.write(json.dumps(status).encode(encoding="utf_8"))
elif re.search("/ajax/fs_list_directory", self.path) is not None:
# Set the response headers.
self._set_headers(200)
# Get the JSON data.
data = self.rfile.read(int(self.headers["Content-Length"]))
path = json.loads(data.decode("utf-8")).get("directory", None)
log.debug("List directory: %s", path)
if not path or not os.path.exists(path):
error = "Invalid path" if not path else "No such file or directory"
log.error("Error listing directory '%s': %s", path, error)
self.wfile.write(json.dumps({"error": error}).encode(encoding="utf_8"))
return
work_path = os.path.realpath(path)
content = []
dir_list = {
"current_dir": path,
"files": content,
}
# Add item '..'
if os.path.dirname(work_path) != work_path:
content.append({
"type": "dir",
"name": os.path.join(path, ".."),
"last_modified": os.stat(os.path.join(path, "..")),
})
dir_contents = os.listdir(work_path)
dir_contents.sort()
for item in dir_contents:
item_path = os.path.join(path, item)
item_work_path = os.path.realpath(item_path)
st = os.stat(item_work_path)
item = {
"type": "dir" if os.path.isdir(item_work_path) else "file",
"name": os.path.join(path, item),
"last_modified": st[stat.ST_MTIME],
}
if os.path.isfile(item_work_path):
item["size"] = st[stat.ST_SIZE]
content.append(item)
# Send the JSON value.
self.wfile.write(json.dumps(dir_list).encode(encoding="utf_8"))
elif re.search("/ajax/fs_remove_file", self.path) is not None:
# Set the response headers.
self._set_headers(200)
# Get the JSON data.
data = self.rfile.read(int(self.headers["Content-Length"]))
path = json.loads(data.decode("utf-8")).get("path", None)
log.debug("Remove file: %s", path)
if not path or not os.path.exists(path):
error = "Invalid path" if not path else "No such file or directory"
log.error("Error removing file '%s': %s", path, error)
self.wfile.write(json.dumps({"error": error}).encode(encoding="utf_8"))
return
try:
os.remove(path)
self.wfile.write("{}".encode(encoding="utf_8"))
except OSError as e:
self.wfile.write(json.dumps({"error": e.strerror}).encode(encoding="utf_8"))
log.error("Error removing file '%s': %s", e.filename, e.strerror)
return
elif re.search("/ajax/fs_create_dir", self.path) is not None:
# Set the response headers.
self._set_headers(200)
# Get the JSON data.
data = self.rfile.read(int(self.headers["Content-Length"]))
path = json.loads(data.decode("utf-8")).get("directory", None)
log.debug("Create directory: %s", path)
if not path:
log.error("Error creating directory '%s': Invalid directory", path)
self.wfile.write(json.dumps({"error": "Invalid directory"}).encode(encoding="utf_8"))
return
try:
os.makedirs(path, exist_ok=True)
except OSError as e:
self.wfile.write(json.dumps({"error": e.strerror}).encode(encoding="utf_8"))
log.error("Error creating directory '%s': %s", path, e.strerror)
return
self.wfile.write("{}".encode(encoding="utf_8"))
elif re.search("/ajax/fs_download_file", self.path) is not None:
# Get the JSON data.
data = self.rfile.read(int(self.headers["Content-Length"]))
path = json.loads(data.decode("utf-8")).get("path", None)
log.debug("Download file: %s", path)
if not path:
self._set_headers(200)
log.error("Error downloading file '%s': Invalid path", path)
self.wfile.write(json.dumps({"error": "Invalid path"}).encode(encoding="utf_8"))
return
work_path = os.path.realpath(path)
try:
with open(work_path, "rb") as f:
contents = f.read()
except OSError as e:
self._set_headers(200)
log.error("Error downloading file '%s': %s", path, e.strerror)
self.wfile.write(json.dumps({"error": e.strerror}).encode(encoding="utf_8"))
return
self.send_response(200)
self.send_header("Content-type", "application/octet-stream")
self.end_headers()
self.wfile.write(contents)
elif re.search("/ajax/fs_upload_file", self.path) is not None:
# Set the response headers.
self._set_headers(200)
# Get the data.
ctype, pdict = cgi.parse_header(self.headers['content-type'])
if "boundary" in pdict:
pdict["boundary"] = pdict["boundary"].encode()
data = cgi.parse_multipart(self.rfile, pdict)
path = data.get("path", [None])[0]
f_data = data.get("file", [bytes()])[0]
log.debug("Upload file: %s", path)
if not path or os.path.exists(path):
error = "Invalid path" if not path else "File already exists"
log.error("Error uploading file '%s': %s", path, error)
self.wfile.write(json.dumps({"error": error}).encode(encoding="utf_8"))
return
work_path = os.path.realpath(path)
try:
with open(work_path, "xb") as f:
f.write(f_data)
self.wfile.write("{}".encode(encoding="utf_8"))
except OSError as e:
log.error("Error uploading file '%s': %s", path, e.strerror)
self.wfile.write(json.dumps({"error": e.strerror}).encode(encoding="utf_8"))
else:
# Forbidden.
self._set_headers(403)

View File

@ -425,7 +425,7 @@ Digi Demo - Dashboard
<div class="filesystem-current-directory-label">Current dir:</div>
<div id="current_directory" class="filesystem-current-directory"></div>
</div>
<div class="filesystem-toolbar-buttons-container">
<div id="filesystem_toolbar_buttons_container" class="filesystem-toolbar-buttons-container">
<div id="filesystem_create_directory_button" class="filesystem-button fas fa-folder-plus fa-2x" onclick="openDirectoryNamePanel()" title="Create directory"></div>
<div id="filesystem_upload_file_button" class="filesystem-button fas fa-upload fa-2x" onclick="openFileBrowser()" title="Upload file"></div>
<div id="filesystem_download_file_button" class="filesystem-button fas fa-file-download fa-2x" onclick="downloadSelectedFile()" title="Download file"></div>

View File

@ -136,6 +136,8 @@ const ERROR_UNKNOWN_ERROR = "Unknown error";
const PATH_IMAGES = "../static/images/";
const PORT = "9090";
String.prototype.format = function() {
var formatted = this;
for (var arg in arguments)
@ -143,6 +145,20 @@ String.prototype.format = function() {
return formatted;
};
// Returns the server address.
function getServerAddress() {
var host = window.location.hostname;
if (!Boolean(host))
host = "127.0.0.1";
return host + ":" + PORT;
}
function is_local_access() {
var host = window.location.hostname;
return !Boolean(host) || host == "127.0.0.1" || host == "localhost";
}
// Shows/hides a front popup over the given background element.
function showPopup(backElementID, frontElementID, visible) {
// Initialize variables.

View File

@ -60,8 +60,6 @@ const ID_WIFI_BT_PANEL_AREA = "wifi_bt_panel_area";
const ID_WIFI_BT_PANEL_ARROW = "wifi_bt_panel_arrow";
const ID_WIFI_BT_PANEL_ICON = "wifi_bt_panel_icon";
const PORT = "9090";
const IFACE_BT = "hci0/";
const IFACE_ETHERNET = "eth0/";
const IFACE_WIFI = "wlan0/";
@ -1006,12 +1004,3 @@ function changeSampleRate() {
// Navigate to management page.
window.open("../management/?device_id=" + getDeviceID() + "&device_name=" + getDeviceName(), "_self");
}
// Returns the server address.
function getServerAddress() {
var host = window.location.hostname;
if (!Boolean(host))
host = "127.0.0.1";
return host + ":" + PORT;
}

View File

@ -29,7 +29,9 @@ const ID_FILE_SYSTEM_ITEMS_HEADER = "filesystem_items_header";
const ID_FILE_SYSTEM_LOADING = "filesystem_loading";
const ID_FILE_SYSTEM_PANEL = "filesystem_panel";
const ID_FILE_SYSTEM_REMOVE_FILE_BUTTON = "filesystem_remove_file_button";
const ID_FILE_SYSTEM_UPLOAD_FILE_BUTTON = "filesystem_upload_file_button";
const ID_FILE_SYSTEM_TOOLBAR = "filesystem_toolbar";
const ID_FILE_SYSTEM_TOOLBAR_BUTTONS_CONTAINER = "filesystem_toolbar_buttons_container";
const ID_FILE_TO_UPLOAD = "file_to_upload";
const CLASS_FA_FILE = "fa-file";
@ -98,6 +100,11 @@ function openFileSystem() {
// Show the file system.
var fileSystemContainer = document.getElementById(ID_FILE_SYSTEM_PANEL);
fileSystemContainer.style.visibility = "visible";
if (is_local_access()) {
document.getElementById(ID_FILE_SYSTEM_DOWNLOAD_FILE_BUTTON).style.display = "none";
document.getElementById(ID_FILE_SYSTEM_UPLOAD_FILE_BUTTON).style.display = "none";
document.getElementById(ID_FILE_SYSTEM_TOOLBAR_BUTTONS_CONTAINER).style.width = "90px";
}
// List root directory.
listDirectory(ROOT_DIRECTORY);
}
@ -244,7 +251,7 @@ function listDirectory(directory) {
showFileSystemLoading(true);
// Send request.
$.post(
"../ajax/fs_list_directory",
"http://" + getServerAddress() + "/ajax/fs_list_directory",
JSON.stringify({
"directory": path
}),
@ -333,7 +340,7 @@ function downloadFile(fileName) {
// Send request
$.ajax({
type: 'POST',
url: "../ajax/fs_download_file",
url: "http://" + getServerAddress() + "/ajax/fs_download_file",
data: data,
cache: false,
async: true,
@ -436,7 +443,7 @@ function removeFile(fileName, isFile) {
showFileSystemLoading(true);
// Send request.
$.post(
"../ajax/fs_remove_file",
"http://" + getServerAddress() + "/ajax/fs_remove_file",
JSON.stringify({
"path": path,
"is_file": isFile
@ -489,7 +496,7 @@ function uploadFile(file) {
// Send request.
$.ajax({
type: 'POST',
url: "../ajax/fs_upload_file",
url: "http://" + getServerAddress() + "/ajax/fs_upload_file",
data: formData,
cache: false,
async: true,
@ -613,7 +620,7 @@ function createDirectory(directoryName) {
showFileSystemLoading(true);
// Send request.
$.post(
"../ajax/fs_create_dir",
"http://" + getServerAddress() + "/ajax/fs_create_dir",
JSON.stringify({
"path": path
}),