Skip to content

Commit 70db616

Browse files
committed
Archive: New info page with md5 hash
1 parent 5067291 commit 70db616

File tree

2 files changed

+88
-24
lines changed

2 files changed

+88
-24
lines changed

ChangeLog.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
- GPIO: Pokemon Trading (by @EstebanFuentealba)
1414
- GPIO: Badge (by @jamisonderek)
1515
- Tools: Tone Generator (by @GEMISIS)
16+
- Archive: New info page with md5 hash (by @Willy-JL)
1617
- OFW: NFC: Add Slix capabilities, some bugfixes (by @gornekich)
1718
- OFW: JS: Added `math.is_equal()` and `math.EPSILON` (by @skotopes)
1819

applications/main/archive/scenes/archive_scene_info.c

+87-24
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "../archive_i.h"
22
#include "../helpers/archive_browser.h"
3+
#include <mbedtls/md5.h>
34

45
#define TAG "Archive"
56

@@ -13,7 +14,7 @@ void archive_scene_info_widget_callback(GuiButtonType result, InputType type, vo
1314
}
1415
}
1516

16-
uint32_t archive_scene_info_dirwalk(void* context) {
17+
static uint32_t archive_scene_info_dirwalk(void* context) {
1718
furi_assert(context);
1819
ArchiveApp* instance = context;
1920

@@ -26,8 +27,7 @@ uint32_t archive_scene_info_dirwalk(void* context) {
2627
while(scene_manager_get_scene_state(instance->scene_manager, ArchiveAppSceneInfo)) {
2728
DirWalkResult result = dir_walk_read(dir_walk, NULL, &fileinfo);
2829
if(result == DirWalkError) {
29-
snprintf(buf, sizeof(buf), "Size: \e#Error\e#");
30-
widget_element_text_box_set_text(instance->element, buf);
30+
widget_element_text_box_set_text(instance->element, "Size: \e#Error\e#");
3131
break;
3232
}
3333
bool is_last = result == DirWalkLast;
@@ -51,8 +51,7 @@ uint32_t archive_scene_info_dirwalk(void* context) {
5151
if(is_last) break;
5252
}
5353
} else {
54-
snprintf(buf, sizeof(buf), "Size: \e#Error\e#");
55-
widget_element_text_box_set_text(instance->element, buf);
54+
widget_element_text_box_set_text(instance->element, "Size: \e#Error\e#");
5655
}
5756
dir_walk_free(dir_walk);
5857
furi_record_close(RECORD_STORAGE);
@@ -61,6 +60,64 @@ uint32_t archive_scene_info_dirwalk(void* context) {
6160
return 0;
6261
}
6362

63+
static uint32_t archive_scene_info_md5sum(void* context) {
64+
furi_assert(context);
65+
ArchiveApp* instance = context;
66+
67+
// Based on lib/toolbox/md5_calc.c
68+
File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
69+
ArchiveFile_t* current = archive_get_current_file(instance->browser);
70+
bool result = false;
71+
if(storage_file_open(
72+
file, furi_string_get_cstr(current->path), FSAM_READ, FSOM_OPEN_EXISTING)) {
73+
uint8_t output[16];
74+
const size_t size_to_read = 512;
75+
uint8_t* data = malloc(size_to_read);
76+
mbedtls_md5_context* md5_ctx = malloc(sizeof(mbedtls_md5_context));
77+
mbedtls_md5_init(md5_ctx);
78+
mbedtls_md5_starts(md5_ctx);
79+
while(scene_manager_get_scene_state(instance->scene_manager, ArchiveAppSceneInfo)) {
80+
size_t read_size = storage_file_read(file, data, size_to_read);
81+
if(storage_file_get_error(file) != FSE_OK) {
82+
break;
83+
}
84+
if(read_size == 0) {
85+
result = true;
86+
break;
87+
}
88+
mbedtls_md5_update(md5_ctx, data, read_size);
89+
}
90+
mbedtls_md5_finish(md5_ctx, output);
91+
if(result) {
92+
FuriString* md5 = furi_string_alloc_set("MD5: \e*");
93+
for(size_t i = 0; i < sizeof(output); i++) {
94+
furi_string_cat_printf(md5, "%02x", output[i]);
95+
}
96+
furi_string_cat(md5, "\e*");
97+
widget_element_text_box_set_text(instance->element, furi_string_get_cstr(md5));
98+
}
99+
free(md5_ctx);
100+
free(data);
101+
storage_file_close(file);
102+
}
103+
storage_file_free(file);
104+
furi_record_close(RECORD_STORAGE);
105+
106+
if(!result) {
107+
char buf[64];
108+
strlcpy(buf, "MD5: \e*Error", sizeof(buf));
109+
uint8_t padding = 32 - strlen("Error");
110+
for(uint8_t i = 0; i < padding; i++) {
111+
strlcat(buf, " ", sizeof(buf));
112+
}
113+
strlcat(buf, "\e*", sizeof(buf));
114+
widget_element_text_box_set_text(instance->element, buf);
115+
}
116+
117+
view_dispatcher_switch_to_view(instance->view_dispatcher, ArchiveViewWidget);
118+
return 0;
119+
}
120+
64121
void archive_scene_info_on_enter(void* context) {
65122
furi_assert(context);
66123
ArchiveApp* instance = context;
@@ -77,21 +134,12 @@ void archive_scene_info_on_enter(void* context) {
77134
// Filename
78135
path_extract_filename(current->path, filename, false);
79136
snprintf(buf, sizeof(buf), "\e#%s\e#", furi_string_get_cstr(filename));
80-
widget_add_text_box_element(
81-
instance->widget, 0, 0, 128, 24, AlignLeft, AlignCenter, buf, false);
137+
widget_add_text_box_element(instance->widget, 1, 1, 126, 13, AlignLeft, AlignTop, buf, true);
82138

83139
// Directory path
84140
path_extract_dirname(furi_string_get_cstr(current->path), dirname);
85141
widget_add_text_box_element(
86-
instance->widget,
87-
0,
88-
42,
89-
128,
90-
12,
91-
AlignLeft,
92-
AlignCenter,
93-
furi_string_get_cstr(dirname),
94-
false);
142+
instance->widget, 1, 12, 126, 20, AlignLeft, AlignTop, furi_string_get_cstr(dirname), true);
95143

96144
// This one to return and cursor select this file
97145
path_extract_filename_no_ext(furi_string_get_cstr(current->path), filename);
@@ -125,18 +173,33 @@ void archive_scene_info_on_enter(void* context) {
125173
show,
126174
units[unit]);
127175
}
128-
instance->element = widget_add_text_box_element(
129-
instance->widget, 0, 24, 128, 24, AlignLeft, AlignCenter, buf, true);
176+
WidgetElement* element = widget_add_text_box_element(
177+
instance->widget, 1, 31, 126, 13, AlignLeft, AlignTop, buf, true);
178+
179+
// MD5 hash
180+
if(!is_dir) {
181+
strlcpy(buf, "MD5: \e*Loading...", sizeof(buf));
182+
uint8_t padding = 32 - strlen("Loading...");
183+
for(uint8_t i = 0; i < padding; i++) {
184+
strlcat(buf, " ", sizeof(buf));
185+
}
186+
strlcat(buf, "\e*", sizeof(buf));
187+
element = widget_add_text_box_element(
188+
instance->widget, 0, 43, 128, 24, AlignRight, AlignTop, buf, false);
189+
}
190+
191+
instance->element = element;
130192
furi_record_close(RECORD_STORAGE);
131193

132194
view_dispatcher_switch_to_view(instance->view_dispatcher, ArchiveViewWidget);
133195

134-
if(is_dir) {
135-
scene_manager_set_scene_state(instance->scene_manager, ArchiveAppSceneInfo, true);
136-
instance->thread = furi_thread_alloc_ex(
137-
"ArchiveInfoDirWalk", 1024, (FuriThreadCallback)archive_scene_info_dirwalk, instance);
138-
furi_thread_start(instance->thread);
139-
}
196+
scene_manager_set_scene_state(instance->scene_manager, ArchiveAppSceneInfo, true);
197+
instance->thread = furi_thread_alloc_ex(
198+
"ArchiveInfoWorker",
199+
1024,
200+
(FuriThreadCallback)(is_dir ? archive_scene_info_dirwalk : archive_scene_info_md5sum),
201+
instance);
202+
furi_thread_start(instance->thread);
140203
}
141204

142205
bool archive_scene_info_on_event(void* context, SceneManagerEvent event) {

0 commit comments

Comments
 (0)