mirror of
https://github.com/HASwitchPlate/openHASP.git
synced 2025-07-28 13:46:36 +00:00
Add unzip command
This commit is contained in:
parent
098211f0f7
commit
d674d5d52c
@ -40,7 +40,7 @@ dispatch_conf_t dispatch_setings = {.teleperiod = 300};
|
||||
|
||||
uint16_t dispatchSecondsToNextTeleperiod = 0;
|
||||
uint8_t nCommands = 0;
|
||||
haspCommand_t commands[21];
|
||||
haspCommand_t commands[22];
|
||||
|
||||
moodlight_t moodlight = {.brightness = 255};
|
||||
|
||||
@ -1081,6 +1081,9 @@ void dispatchSetup()
|
||||
dispatch_add_command(PSTR("screenshot"), dispatch_screenshot);
|
||||
dispatch_add_command(PSTR("discovery"), dispatch_send_discovery);
|
||||
dispatch_add_command(PSTR("factoryreset"), dispatch_factory_reset);
|
||||
#if HASP_USE_SPIFFS > 0 || HASP_USE_LITTLEFS > 0
|
||||
dispatch_add_command(PSTR("unzip"), filesystemUnzip);
|
||||
#endif
|
||||
#if HASP_USE_CONFIG > 0
|
||||
dispatch_add_command(PSTR("setupap"), oobeFakeSetup);
|
||||
#endif
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "hasp_debug.h"
|
||||
#include "hasp_filesystem.h"
|
||||
#include "rom/crc.h"
|
||||
|
||||
void filesystemInfo()
|
||||
{ // Get all information of your SPIFFS
|
||||
@ -25,6 +26,118 @@ void filesystemInfo()
|
||||
#endif
|
||||
}
|
||||
|
||||
void filesystemUnzip(const char*, const char* filename)
|
||||
{
|
||||
File zipfile = HASP_FS.open(filename, FILE_READ);
|
||||
if(!zipfile) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t head;
|
||||
size_t len;
|
||||
bool done = false;
|
||||
|
||||
zipfile.seek(0);
|
||||
while(!done) {
|
||||
len = zipfile.read((uint8_t*)&head, sizeof(head));
|
||||
if(len != sizeof(head)) {
|
||||
done = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(head) {
|
||||
case 0x04034b50: {
|
||||
zip_file_header_t fh;
|
||||
zipfile.seek(zipfile.position() - 2, SeekSet); // rewind for struct alignment (26-28)
|
||||
len = zipfile.read((uint8_t*)(&fh), sizeof(zip_file_header_t));
|
||||
if(len != sizeof(zip_file_header_t)) {
|
||||
done = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(fh.filename_length >= 31) {
|
||||
LOG_WARNING(TAG_FILE, F("filename length too long %d"), fh.filename_length);
|
||||
zipfile.seek(fh.filename_length + fh.extra_length, SeekCur); // skip extra field
|
||||
continue;
|
||||
// } else {
|
||||
// LOG_WARNING(TAG_FILE, F("min %d - flag %d - len %d - xtra %d"), fh.min_version, fh.flags,
|
||||
// fh.filename_length, fh.extra_length);
|
||||
}
|
||||
char name[32] = {0};
|
||||
name[0] = '/';
|
||||
|
||||
len = zipfile.read((uint8_t*)&name[1], fh.filename_length);
|
||||
if(len != fh.filename_length) {
|
||||
LOG_WARNING(TAG_FILE, F("filename read failed %d != %d"), fh.filename_length, len);
|
||||
done = true;
|
||||
continue;
|
||||
}
|
||||
zipfile.seek(fh.extra_length, SeekCur); // skip extra field
|
||||
|
||||
if(fh.compression_method != ZIP_NO_COMPRESSION) {
|
||||
LOG_WARNING(TAG_FILE, F("Compression is not supported %d"), fh.compression_method);
|
||||
zipfile.seek(fh.compressed_size, SeekCur); // skip compressed file
|
||||
} else {
|
||||
|
||||
if(HASP_FS.exists(name)) HASP_FS.remove(name);
|
||||
|
||||
File f = HASP_FS.open(name, FILE_WRITE);
|
||||
if(f) {
|
||||
uint8_t buffer[512];
|
||||
uint32_t crc32 = 0;
|
||||
|
||||
while(!done && fh.compressed_size >= 512) {
|
||||
len = zipfile.readBytes((char*)&buffer, 512);
|
||||
if(len != 512) done = true;
|
||||
fh.compressed_size -= len;
|
||||
crc32 = crc32_le(crc32, buffer, len);
|
||||
// crc2 = crc32_be(crc2, buffer, len);
|
||||
f.write(buffer, len);
|
||||
}
|
||||
|
||||
if(!done && fh.compressed_size > 0) {
|
||||
len = zipfile.readBytes((char*)&buffer, fh.compressed_size);
|
||||
if(len != fh.compressed_size) done = true;
|
||||
fh.compressed_size -= len;
|
||||
crc32 = crc32_le(crc32, buffer, len);
|
||||
// crc2 = crc32_be(crc2, buffer, len);
|
||||
f.write(buffer, len);
|
||||
}
|
||||
|
||||
if(crc32 != fh.crc) done = true;
|
||||
|
||||
if(!done) {
|
||||
Parser::format_bytes(fh.uncompressed_size, (char*)buffer, sizeof(buffer));
|
||||
LOG_VERBOSE(TAG_FILE, F(D_BULLET "%s (%s)"), name, buffer);
|
||||
} else {
|
||||
LOG_ERROR(TAG_FILE, F(D_FILE_SAVE_FAILED), name);
|
||||
}
|
||||
|
||||
f.close();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x02014b50:
|
||||
done = true;
|
||||
break;
|
||||
case 0x06054b50:
|
||||
// end of file
|
||||
done = true;
|
||||
break;
|
||||
default: {
|
||||
char outputString[9];
|
||||
itoa(head, outputString, 16);
|
||||
LOG_WARNING(TAG_FILE, F("invalid %s"), outputString);
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
zipfile.close();
|
||||
LOG_VERBOSE(TAG_FILE, F("extracting %s complete"), filename);
|
||||
}
|
||||
|
||||
void filesystemList()
|
||||
{
|
||||
#if HASP_USE_SPIFFS > 0
|
||||
|
@ -10,6 +10,25 @@ bool filesystemSetup(void);
|
||||
|
||||
void filesystemList();
|
||||
void filesystemInfo();
|
||||
void filesystemUnzip(const char*, const char* filename);
|
||||
|
||||
enum { ZIP_NO_COMPRESSION = 0, ZIP_DEFLTATE = 8 };
|
||||
typedef uint16_t zip_compression_method_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t dummy_bytes; // total struct needs to be a multiple of 4 bytes
|
||||
uint16_t min_version;
|
||||
uint16_t flags;
|
||||
zip_compression_method_t compression_method;
|
||||
uint16_t time_modified;
|
||||
uint16_t date_modified;
|
||||
uint32_t crc;
|
||||
uint32_t compressed_size;
|
||||
uint32_t uncompressed_size;
|
||||
uint16_t filename_length; // OK
|
||||
uint16_t extra_length;
|
||||
} zip_file_header_t;
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
#if HASP_USE_SPIFFS > 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user