Add unzip command

This commit is contained in:
fvanroie 2021-06-20 00:31:34 +02:00
parent 098211f0f7
commit d674d5d52c
3 changed files with 136 additions and 1 deletions

View File

@ -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

View File

@ -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

View File

@ -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