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. # PERFORMANCE OF THIS SOFTWARE.
import argparse import argparse
import cgi
import http.server import http.server
import json import json
import logging import logging
@ -139,6 +140,153 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler):
# Send the JSON value. # Send the JSON value.
self.wfile.write(json.dumps(status).encode(encoding="utf_8")) 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: else:
# Forbidden. # Forbidden.
self._set_headers(403) self._set_headers(403)

View File

@ -425,7 +425,7 @@ Digi Demo - Dashboard
<div class="filesystem-current-directory-label">Current dir:</div> <div class="filesystem-current-directory-label">Current dir:</div>
<div id="current_directory" class="filesystem-current-directory"></div> <div id="current_directory" class="filesystem-current-directory"></div>
</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_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_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> <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 PATH_IMAGES = "../static/images/";
const PORT = "9090";
String.prototype.format = function() { String.prototype.format = function() {
var formatted = this; var formatted = this;
for (var arg in arguments) for (var arg in arguments)
@ -143,6 +145,20 @@ String.prototype.format = function() {
return formatted; 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. // Shows/hides a front popup over the given background element.
function showPopup(backElementID, frontElementID, visible) { function showPopup(backElementID, frontElementID, visible) {
// Initialize variables. // 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_ARROW = "wifi_bt_panel_arrow";
const ID_WIFI_BT_PANEL_ICON = "wifi_bt_panel_icon"; const ID_WIFI_BT_PANEL_ICON = "wifi_bt_panel_icon";
const PORT = "9090";
const IFACE_BT = "hci0/"; const IFACE_BT = "hci0/";
const IFACE_ETHERNET = "eth0/"; const IFACE_ETHERNET = "eth0/";
const IFACE_WIFI = "wlan0/"; const IFACE_WIFI = "wlan0/";
@ -1006,12 +1004,3 @@ function changeSampleRate() {
// Navigate to management page. // Navigate to management page.
window.open("../management/?device_id=" + getDeviceID() + "&device_name=" + getDeviceName(), "_self"); 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_LOADING = "filesystem_loading";
const ID_FILE_SYSTEM_PANEL = "filesystem_panel"; const ID_FILE_SYSTEM_PANEL = "filesystem_panel";
const ID_FILE_SYSTEM_REMOVE_FILE_BUTTON = "filesystem_remove_file_button"; 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 = "filesystem_toolbar";
const ID_FILE_SYSTEM_TOOLBAR_BUTTONS_CONTAINER = "filesystem_toolbar_buttons_container";
const ID_FILE_TO_UPLOAD = "file_to_upload"; const ID_FILE_TO_UPLOAD = "file_to_upload";
const CLASS_FA_FILE = "fa-file"; const CLASS_FA_FILE = "fa-file";
@ -98,6 +100,11 @@ function openFileSystem() {
// Show the file system. // Show the file system.
var fileSystemContainer = document.getElementById(ID_FILE_SYSTEM_PANEL); var fileSystemContainer = document.getElementById(ID_FILE_SYSTEM_PANEL);
fileSystemContainer.style.visibility = "visible"; 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. // List root directory.
listDirectory(ROOT_DIRECTORY); listDirectory(ROOT_DIRECTORY);
} }
@ -244,7 +251,7 @@ function listDirectory(directory) {
showFileSystemLoading(true); showFileSystemLoading(true);
// Send request. // Send request.
$.post( $.post(
"../ajax/fs_list_directory", "http://" + getServerAddress() + "/ajax/fs_list_directory",
JSON.stringify({ JSON.stringify({
"directory": path "directory": path
}), }),
@ -333,7 +340,7 @@ function downloadFile(fileName) {
// Send request // Send request
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
url: "../ajax/fs_download_file", url: "http://" + getServerAddress() + "/ajax/fs_download_file",
data: data, data: data,
cache: false, cache: false,
async: true, async: true,
@ -436,7 +443,7 @@ function removeFile(fileName, isFile) {
showFileSystemLoading(true); showFileSystemLoading(true);
// Send request. // Send request.
$.post( $.post(
"../ajax/fs_remove_file", "http://" + getServerAddress() + "/ajax/fs_remove_file",
JSON.stringify({ JSON.stringify({
"path": path, "path": path,
"is_file": isFile "is_file": isFile
@ -489,7 +496,7 @@ function uploadFile(file) {
// Send request. // Send request.
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
url: "../ajax/fs_upload_file", url: "http://" + getServerAddress() + "/ajax/fs_upload_file",
data: formData, data: formData,
cache: false, cache: false,
async: true, async: true,
@ -613,7 +620,7 @@ function createDirectory(directoryName) {
showFileSystemLoading(true); showFileSystemLoading(true);
// Send request. // Send request.
$.post( $.post(
"../ajax/fs_create_dir", "http://" + getServerAddress() + "/ajax/fs_create_dir",
JSON.stringify({ JSON.stringify({
"path": path "path": path
}), }),