mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-13 14:48:35 -07:00
Archive: New info page with md5 hash
This commit is contained in:
@@ -13,6 +13,7 @@
|
|||||||
- GPIO: Pokemon Trading (by @EstebanFuentealba)
|
- GPIO: Pokemon Trading (by @EstebanFuentealba)
|
||||||
- GPIO: Badge (by @jamisonderek)
|
- GPIO: Badge (by @jamisonderek)
|
||||||
- Tools: Tone Generator (by @GEMISIS)
|
- Tools: Tone Generator (by @GEMISIS)
|
||||||
|
- Archive: New info page with md5 hash (by @Willy-JL)
|
||||||
- OFW: NFC: Add Slix capabilities, some bugfixes (by @gornekich)
|
- OFW: NFC: Add Slix capabilities, some bugfixes (by @gornekich)
|
||||||
- OFW: JS: Added `math.is_equal()` and `math.EPSILON` (by @skotopes)
|
- OFW: JS: Added `math.is_equal()` and `math.EPSILON` (by @skotopes)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "../archive_i.h"
|
#include "../archive_i.h"
|
||||||
#include "../helpers/archive_browser.h"
|
#include "../helpers/archive_browser.h"
|
||||||
|
#include <mbedtls/md5.h>
|
||||||
|
|
||||||
#define TAG "Archive"
|
#define TAG "Archive"
|
||||||
|
|
||||||
@@ -13,7 +14,7 @@ void archive_scene_info_widget_callback(GuiButtonType result, InputType type, vo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t archive_scene_info_dirwalk(void* context) {
|
static uint32_t archive_scene_info_dirwalk(void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ArchiveApp* instance = context;
|
ArchiveApp* instance = context;
|
||||||
|
|
||||||
@@ -26,8 +27,7 @@ uint32_t archive_scene_info_dirwalk(void* context) {
|
|||||||
while(scene_manager_get_scene_state(instance->scene_manager, ArchiveAppSceneInfo)) {
|
while(scene_manager_get_scene_state(instance->scene_manager, ArchiveAppSceneInfo)) {
|
||||||
DirWalkResult result = dir_walk_read(dir_walk, NULL, &fileinfo);
|
DirWalkResult result = dir_walk_read(dir_walk, NULL, &fileinfo);
|
||||||
if(result == DirWalkError) {
|
if(result == DirWalkError) {
|
||||||
snprintf(buf, sizeof(buf), "Size: \e#Error\e#");
|
widget_element_text_box_set_text(instance->element, "Size: \e#Error\e#");
|
||||||
widget_element_text_box_set_text(instance->element, buf);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
bool is_last = result == DirWalkLast;
|
bool is_last = result == DirWalkLast;
|
||||||
@@ -51,8 +51,7 @@ uint32_t archive_scene_info_dirwalk(void* context) {
|
|||||||
if(is_last) break;
|
if(is_last) break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
snprintf(buf, sizeof(buf), "Size: \e#Error\e#");
|
widget_element_text_box_set_text(instance->element, "Size: \e#Error\e#");
|
||||||
widget_element_text_box_set_text(instance->element, buf);
|
|
||||||
}
|
}
|
||||||
dir_walk_free(dir_walk);
|
dir_walk_free(dir_walk);
|
||||||
furi_record_close(RECORD_STORAGE);
|
furi_record_close(RECORD_STORAGE);
|
||||||
@@ -61,6 +60,64 @@ uint32_t archive_scene_info_dirwalk(void* context) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t archive_scene_info_md5sum(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
ArchiveApp* instance = context;
|
||||||
|
|
||||||
|
// Based on lib/toolbox/md5_calc.c
|
||||||
|
File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
|
||||||
|
ArchiveFile_t* current = archive_get_current_file(instance->browser);
|
||||||
|
bool result = false;
|
||||||
|
if(storage_file_open(
|
||||||
|
file, furi_string_get_cstr(current->path), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||||
|
uint8_t output[16];
|
||||||
|
const size_t size_to_read = 512;
|
||||||
|
uint8_t* data = malloc(size_to_read);
|
||||||
|
mbedtls_md5_context* md5_ctx = malloc(sizeof(mbedtls_md5_context));
|
||||||
|
mbedtls_md5_init(md5_ctx);
|
||||||
|
mbedtls_md5_starts(md5_ctx);
|
||||||
|
while(scene_manager_get_scene_state(instance->scene_manager, ArchiveAppSceneInfo)) {
|
||||||
|
size_t read_size = storage_file_read(file, data, size_to_read);
|
||||||
|
if(storage_file_get_error(file) != FSE_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(read_size == 0) {
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mbedtls_md5_update(md5_ctx, data, read_size);
|
||||||
|
}
|
||||||
|
mbedtls_md5_finish(md5_ctx, output);
|
||||||
|
if(result) {
|
||||||
|
FuriString* md5 = furi_string_alloc_set("MD5: \e*");
|
||||||
|
for(size_t i = 0; i < sizeof(output); i++) {
|
||||||
|
furi_string_cat_printf(md5, "%02x", output[i]);
|
||||||
|
}
|
||||||
|
furi_string_cat(md5, "\e*");
|
||||||
|
widget_element_text_box_set_text(instance->element, furi_string_get_cstr(md5));
|
||||||
|
}
|
||||||
|
free(md5_ctx);
|
||||||
|
free(data);
|
||||||
|
storage_file_close(file);
|
||||||
|
}
|
||||||
|
storage_file_free(file);
|
||||||
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
|
||||||
|
if(!result) {
|
||||||
|
char buf[64];
|
||||||
|
strlcpy(buf, "MD5: \e*Error", sizeof(buf));
|
||||||
|
uint8_t padding = 32 - strlen("Error");
|
||||||
|
for(uint8_t i = 0; i < padding; i++) {
|
||||||
|
strlcat(buf, " ", sizeof(buf));
|
||||||
|
}
|
||||||
|
strlcat(buf, "\e*", sizeof(buf));
|
||||||
|
widget_element_text_box_set_text(instance->element, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(instance->view_dispatcher, ArchiveViewWidget);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void archive_scene_info_on_enter(void* context) {
|
void archive_scene_info_on_enter(void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ArchiveApp* instance = context;
|
ArchiveApp* instance = context;
|
||||||
@@ -77,21 +134,12 @@ void archive_scene_info_on_enter(void* context) {
|
|||||||
// Filename
|
// Filename
|
||||||
path_extract_filename(current->path, filename, false);
|
path_extract_filename(current->path, filename, false);
|
||||||
snprintf(buf, sizeof(buf), "\e#%s\e#", furi_string_get_cstr(filename));
|
snprintf(buf, sizeof(buf), "\e#%s\e#", furi_string_get_cstr(filename));
|
||||||
widget_add_text_box_element(
|
widget_add_text_box_element(instance->widget, 1, 1, 126, 13, AlignLeft, AlignTop, buf, true);
|
||||||
instance->widget, 0, 0, 128, 24, AlignLeft, AlignCenter, buf, false);
|
|
||||||
|
|
||||||
// Directory path
|
// Directory path
|
||||||
path_extract_dirname(furi_string_get_cstr(current->path), dirname);
|
path_extract_dirname(furi_string_get_cstr(current->path), dirname);
|
||||||
widget_add_text_box_element(
|
widget_add_text_box_element(
|
||||||
instance->widget,
|
instance->widget, 1, 12, 126, 20, AlignLeft, AlignTop, furi_string_get_cstr(dirname), true);
|
||||||
0,
|
|
||||||
42,
|
|
||||||
128,
|
|
||||||
12,
|
|
||||||
AlignLeft,
|
|
||||||
AlignCenter,
|
|
||||||
furi_string_get_cstr(dirname),
|
|
||||||
false);
|
|
||||||
|
|
||||||
// This one to return and cursor select this file
|
// This one to return and cursor select this file
|
||||||
path_extract_filename_no_ext(furi_string_get_cstr(current->path), filename);
|
path_extract_filename_no_ext(furi_string_get_cstr(current->path), filename);
|
||||||
@@ -125,18 +173,33 @@ void archive_scene_info_on_enter(void* context) {
|
|||||||
show,
|
show,
|
||||||
units[unit]);
|
units[unit]);
|
||||||
}
|
}
|
||||||
instance->element = widget_add_text_box_element(
|
WidgetElement* element = widget_add_text_box_element(
|
||||||
instance->widget, 0, 24, 128, 24, AlignLeft, AlignCenter, buf, true);
|
instance->widget, 1, 31, 126, 13, AlignLeft, AlignTop, buf, true);
|
||||||
|
|
||||||
|
// MD5 hash
|
||||||
|
if(!is_dir) {
|
||||||
|
strlcpy(buf, "MD5: \e*Loading...", sizeof(buf));
|
||||||
|
uint8_t padding = 32 - strlen("Loading...");
|
||||||
|
for(uint8_t i = 0; i < padding; i++) {
|
||||||
|
strlcat(buf, " ", sizeof(buf));
|
||||||
|
}
|
||||||
|
strlcat(buf, "\e*", sizeof(buf));
|
||||||
|
element = widget_add_text_box_element(
|
||||||
|
instance->widget, 0, 43, 128, 24, AlignRight, AlignTop, buf, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->element = element;
|
||||||
furi_record_close(RECORD_STORAGE);
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(instance->view_dispatcher, ArchiveViewWidget);
|
view_dispatcher_switch_to_view(instance->view_dispatcher, ArchiveViewWidget);
|
||||||
|
|
||||||
if(is_dir) {
|
scene_manager_set_scene_state(instance->scene_manager, ArchiveAppSceneInfo, true);
|
||||||
scene_manager_set_scene_state(instance->scene_manager, ArchiveAppSceneInfo, true);
|
instance->thread = furi_thread_alloc_ex(
|
||||||
instance->thread = furi_thread_alloc_ex(
|
"ArchiveInfoWorker",
|
||||||
"ArchiveInfoDirWalk", 1024, (FuriThreadCallback)archive_scene_info_dirwalk, instance);
|
1024,
|
||||||
furi_thread_start(instance->thread);
|
(FuriThreadCallback)(is_dir ? archive_scene_info_dirwalk : archive_scene_info_md5sum),
|
||||||
}
|
instance);
|
||||||
|
furi_thread_start(instance->thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool archive_scene_info_on_event(void* context, SceneManagerEvent event) {
|
bool archive_scene_info_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
|||||||
Reference in New Issue
Block a user