From b1cc87d24f9eb8f5dfd7836307cc040038d11d12 Mon Sep 17 00:00:00 2001
From: btsimonh
%s: %s
"; + +#ifndef D_CURR_DIR + #define D_CURR_DIR "Folder" +#endif const char UFS_FORM_FILE_UPLOAD[] PROGMEM = "%s"; const char UFS_FORM_SDC_DIRb[] PROGMEM = - "
%s %s %8d %s %s"; + "
%s %19s %8d %s %s"; const char UFS_FORM_SDC_HREF[] PROGMEM = "ufsd?download=%s/%s"; #ifdef GUI_TRASH_FILE const char UFS_FORM_SDC_HREFdel[] PROGMEM = //"🗑"; // 🗑️ - "🔥"; // 🔥 + "🔥"; // 🔥 #endif // GUI_TRASH_FILE #ifdef GUI_EDIT_FILE @@ -684,38 +851,50 @@ void UfsDirectory(void) { AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_MANAGE_FILE_SYSTEM)); uint8_t depth = 0; + uint8_t isdir = 0; strcpy(ufs_path, "/"); + if (Webserver->hasArg(F("dir"))) { + String stmp = Webserver->arg(F("dir")); + ufs_dir = atoi(stmp.c_str()); + } + + if (ufs_dir == 1) { + dfsp = ufsp; + } else { + if (ffsp) { + dfsp = ffsp; + } + } + + if (Webserver->hasArg(F("delete"))) { + String stmp = Webserver->arg(F("delete")); + char *cp = (char*)stmp.c_str(); + File download_file = dfsp->open(cp, UFS_FILE_READ); + if (download_file) { + if (download_file.isDirectory()) { + download_file.close(); + dfsp->rmdir(cp); + } else { + download_file.close(); + dfsp->remove(cp); + } + } + } + if (Webserver->hasArg(F("download"))) { String stmp = Webserver->arg(F("download")); char *cp = (char*)stmp.c_str(); if (UfsDownloadFile(cp)) { // is directory strcpy(ufs_path, cp); + isdir = 1; } else { return; } } - if (Webserver->hasArg(F("dir"))) { - String stmp = Webserver->arg(F("dir")); - ufs_dir = atoi(stmp.c_str()); - if (ufs_dir == 1) { - dfsp = ufsp; - } else { - if (ffsp) { - dfsp = ffsp; - } - } - } - - if (Webserver->hasArg(F("delete"))) { - String stmp = Webserver->arg(F("delete")); - char *cp = (char*)stmp.c_str(); - dfsp->remove(cp); - } - WSContentStart_P(PSTR(D_MANAGE_FILE_SYSTEM)); WSContentSendStyle(); WSContentSend_P(UFS_FORM_FILE_UPLOAD); @@ -733,13 +912,20 @@ void UfsDirectory(void) { WSContentSend_P(UFS_FORM_FILE_UPG, PSTR(D_SCRIPT_UPLOAD)); + if (isdir){ + // if a folder, show 'folder: xxx' if not '/' + if (ufs_path[0] != '/' || strlen(ufs_path) != 1){ + WSContentSend_P(UFS_CURRDIR, PSTR(D_CURR_DIR), ufs_path); + } + } + WSContentSend_P(UFS_FORM_SDC_DIRa); if (ufs_type) { UfsListDir(ufs_path, depth); } WSContentSend_P(UFS_FORM_SDC_DIRc); #ifdef GUI_EDIT_FILE - WSContentSend_P(UFS_FORM_FILE_UPGb); + WSContentSend_P(UFS_FORM_FILE_UPGb, ufs_path); #endif if (!isSDC()) { WSContentSend_P(UFS_FORM_FILE_UPGb1); @@ -788,6 +974,13 @@ void UfsListDir(char *path, uint8_t depth) { } char *ep; while (true) { + WiFiClient client = Webserver->client(); + // abort if the client disconnected + // if there is a huge folder, then this gives a way out by refresh of browser + if (!client.connected()){ + break; + } + File entry = dir.openNextFile(); if (!entry) { break; @@ -820,9 +1013,19 @@ void UfsListDir(char *path, uint8_t depth) { const char* ppe = pp_escaped_string.c_str(); // this can't be merged on a single line otherwise the String object can be freed const char* epe = ep_escaped_string.c_str(); sprintf(cp, format, ep); +#ifdef GUI_TRASH_FILE + char delpath[128+UFS_FILENAME_SIZE]; + ext_snprintf_P(delpath, sizeof(delpath), UFS_FORM_SDC_HREFdel, ppe, epe, ppe[0]?ppe:"/"); +#else + char delpath[2] = " "; +#endif // GUI_TRASH_FILE if (entry.isDirectory()) { ext_snprintf_P(npath, sizeof(npath), UFS_FORM_SDC_HREF, ppe, epe); - WSContentSend_P(UFS_FORM_SDC_DIRd, npath, ep, name); + + WSContentSend_P(UFS_FORM_SDC_DIRb, hiddable ? UFS_FORM_SDC_DIR_HIDDABLE : UFS_FORM_SDC_DIR_NORMAL, npath, epe, + HtmlEscape(name).c_str(), "", 0, delpath, " "); + //WSContentSend_P(UFS_FORM_SDC_DIRd, npath, ep, name); +#ifdef UFILESYS_RECURSEFOLDERS_GUI uint8_t plen = strlen(path); if (plen > 1) { strcat(path, "/"); @@ -830,14 +1033,8 @@ void UfsListDir(char *path, uint8_t depth) { strcat(path, ep); UfsListDir(path, depth + 4); path[plen] = 0; +#endif } else { - #ifdef GUI_TRASH_FILE - char delpath[128]; - ext_snprintf_P(delpath, sizeof(delpath), UFS_FORM_SDC_HREFdel, ppe, epe); - #else - char delpath[2]; - delpath[0]=0; - #endif // GUI_TRASH_FILE #ifdef GUI_EDIT_FILE char editpath[128]; ext_snprintf_P(editpath, sizeof(editpath), UFS_FORM_SDC_HREFedit, ppe, epe); @@ -857,12 +1054,16 @@ void UfsListDir(char *path, uint8_t depth) { } #ifdef ESP32 -#define ESP32_DOWNLOAD_TASK +// this actually does not work reliably, as the +// webserver can close the connection before the download task completes +//#define ESP32_DOWNLOAD_TASK #endif // ESP32 uint8_t UfsDownloadFile(char *file) { File download_file; + AddLog(LOG_LEVEL_INFO, PSTR("UFS: File '%s' download"), file); + if (!dfsp->exists(file)) { AddLog(LOG_LEVEL_INFO, PSTR("UFS: File '%s' not found"), file); return 0; @@ -875,6 +1076,7 @@ uint8_t UfsDownloadFile(char *file) { } if (download_file.isDirectory()) { + AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: File '%s' to download is directory"), file); download_file.close(); return 1; } @@ -887,13 +1089,7 @@ uint8_t UfsDownloadFile(char *file) { Webserver->setContentLength(flen); char attachment[100]; - char *cp; - for (uint32_t cnt = strlen(file); cnt >= 0; cnt--) { - if (file[cnt] == '/') { - cp = &file[cnt + 1]; - break; - } - } + char *cp = fileOnly(file); snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"), cp); Webserver->sendHeader(F("Content-Disposition"), attachment); WSSend(200, CT_APP_STREAM, ""); @@ -922,6 +1118,10 @@ uint8_t UfsDownloadFile(char *file) { #endif // ESP32_DOWNLOAD_TASK + +// to make this work I thing you wouold need to duplicate the client +// BEFORE starting the task, so that the webserver does not close it's +// copy of the client. #ifdef ESP32_DOWNLOAD_TASK download_file.close(); @@ -952,20 +1152,18 @@ void download_task(void *path) { WiFiClient download_Client; char *file = (char*) path; + AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: ESP32 File '%s' to download"), file); + download_file = dfsp->open(file, UFS_FILE_READ); uint32_t flen = download_file.size(); + AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: len %d to download"), flen); + download_Client = Webserver->client(); Webserver->setContentLength(flen); char attachment[100]; - char *cp; - for (uint32_t cnt = strlen(file); cnt >= 0; cnt--) { - if (file[cnt] == '/') { - cp = &file[cnt + 1]; - break; - } - } + char *cp = fileOnly(file); //snprintf_P(attachment, sizeof(attachment), PSTR("download file '%s' as '%s'"), file, cp); //Webserver->sendHeader(F("X-Tasmota-Debug"), attachment); snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"), cp); @@ -987,6 +1185,7 @@ void download_task(void *path) { UfsData.download_busy = false; vTaskDelete( NULL ); free(path); + AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: esp32 sent file")); } #endif // ESP32_DOWNLOAD_TASK @@ -1065,7 +1264,8 @@ void UfsEditor(void) { } WSContentSend_P(HTTP_EDITOR_FORM_END); - WSContentSend_P(UFS_WEB_DIR, PSTR(D_MANAGE_FILE_SYSTEM)); + folderOnly(fname); + WSContentSend_P(UFS_WEB_DIR, fname, PSTR(D_MANAGE_FILE_SYSTEM)); WSContentStop(); } @@ -1100,6 +1300,23 @@ void UfsEditorUpload(void) { return; } + // recursively create folder(s) + char tmp[UFS_FILENAME_SIZE]; + char folder[UFS_FILENAME_SIZE] = ""; + strcpy(tmp, fname); + // zap file name off the end + folderOnly(tmp); + char *tf = strtok(tmp, "/"); + while(tf){ + if (*tf){ + strcat(folder, "/"); + strcat(folder, tf); + } + // we don;t care if it fails - it may already exist. + dfsp->mkdir(folder); + tf = strtok(nullptr, "/"); + } + File fp = dfsp->open(fname, "w"); if (!fp) { Web.upload_error = 1; @@ -1119,7 +1336,11 @@ void UfsEditorUpload(void) { fp.close(); - Webserver->sendHeader(F("Location"),F("/ufsu")); + // zap file name off the end + folderOnly(fname); + char t[20+UFS_FILENAME_SIZE] = "/ufsu?download="; + strcat(t, fname); + Webserver->sendHeader(F("Location"), t); Webserver->send(303); } @@ -1160,7 +1381,7 @@ bool Xdrv50(uint32_t function) { if (XdrvMailbox.index) { XdrvMailbox.index++; } else { - WSContentSend_PD(UFS_WEB_DIR, PSTR(D_MANAGE_FILE_SYSTEM)); + WSContentSend_PD(UFS_WEB_DIR, "/", PSTR(D_MANAGE_FILE_SYSTEM)); } } break;