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+
64121void 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
142205bool archive_scene_info_on_event (void * context , SceneManagerEvent event ) {
0 commit comments