Rev 8373 | Rev 8466 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
8430 | superturbo | 1 | /* Copyright (C) 2019-2020 Logaev Maxim (turbocat2001), GPLv3 */ |
2 | |||
8073 | superturbo | 3 | #include |
8430 | superturbo | 4 | #include |
8073 | superturbo | 5 | #include |
8373 | superturbo | 6 | #include |
8073 | superturbo | 7 | #include |
8 | #include |
||
8373 | superturbo | 9 | #include |
10 | #include |
||
11 | #include |
||
8430 | superturbo | 12 | #include |
8073 | superturbo | 13 | |
14 | #define TRUE 1; |
||
15 | #define FALSE 0; |
||
16 | #define MAX_HASH_LEN 65 // Максимальная длина строки |
||
17 | #define WINDOW_W 665 |
||
8430 | superturbo | 18 | #define VERSION "%s - thashview 2.5" |
8073 | superturbo | 19 | |
20 | struct kolibri_system_colors sys_color_table; |
||
21 | |||
22 | char hex[]={"abcdefABCDEF1234567890"}; //Для проверки вводимых символов |
||
23 | char hash_str_md5[MAX_HASH_LEN]= "Click the 'MD5:' button to show the md5-checksum! "; //Вывод MD5 |
||
24 | char hash_str_sha1[MAX_HASH_LEN]= "Click the 'SHA1:' button to show the sha1-checksum! "; //Вывод SHA1 |
||
25 | char hash_str_sha256[MAX_HASH_LEN]="Click the 'SHA256:' button to show the sha256-checksum!"; //Вывод SHA256 |
||
26 | char edit_box_buff[MAX_HASH_LEN]; // Буффер для ввода |
||
27 | char *filename; // Имя обрабатываемого файла |
||
28 | char *title; // Заголовок окна |
||
29 | |||
30 | enum MYCOLORS // Цвета |
||
31 | { |
||
32 | GREEN = 0x00067D06, |
||
33 | RED = 0x00FF0000, |
||
34 | BLACK = 0x00000000, |
||
35 | WHITE = 0xFFFFFFFF, |
||
36 | GREY = 0x00DDD7CF |
||
37 | }; |
||
38 | |||
39 | unsigned int str_pos=0; // Позиция курсора при печати в строке ввода |
||
40 | int md5_flag=0, sha1_flag=0, sha256_flag=0; // Флаги показывающие была ли уже рассчитана котрольная сумма в функции check_sum() |
||
41 | int edit_box_text_color=BLACK; // Изначальный цвет текста в строке ввода |
||
42 | |||
43 | enum MYKEYS // Коды клавиш |
||
44 | { |
||
45 | CTRL_V=22, |
||
46 | BACKSPACE=8 |
||
47 | }; |
||
48 | |||
49 | enum BUTTONS // Кнопки в интрефейсе |
||
50 | { |
||
51 | BTN_QUIT=1, //Выход |
||
52 | BTN_MD5 = 10, //Рассчитать md5-контрольную сумму |
||
53 | BTN_SHA1 = 20, //Рассчитать sha1-контрольную сумму |
||
54 | BTN_SHA256 = 30, //Рассчитать sha256-контрольную сумму |
||
55 | BTN_COPY_MD5= 11, //Скопировать в буффер обмена |
||
56 | BTN_COPY_SHA1= 21, |
||
57 | BTN_COPY_SHA256=31, |
||
58 | BTN_CMP=40, //Сравнить edit_box и контрольную сумму |
||
59 | BTN_PASTE=50 //Вставить в edit_box(пока в разработке) |
||
60 | }; |
||
61 | |||
8373 | superturbo | 62 | void notify_show(char *text) |
63 | { |
||
64 | start_app("/sys/@notify", text); |
||
65 | } |
||
8073 | superturbo | 66 | |
67 | void* safe_malloc(size_t size) // Безопасный malloc. Показывает уведомление об ошибке и закрывает программу если память не была выделена |
||
68 | { |
||
69 | void *p=malloc(size); |
||
70 | if(p==NULL) |
||
71 | { |
||
72 | notify_show("'Memory allocation error!' -E"); |
||
73 | exit(0); |
||
74 | } |
||
75 | else |
||
76 | { |
||
77 | return p; |
||
78 | } |
||
79 | } |
||
80 | |||
81 | void global_var_init(unsigned int size) // Инициализируются глобальные массивы |
||
82 | { |
||
83 | filename=safe_malloc(size); |
||
84 | title=safe_malloc(size+20); |
||
85 | } |
||
86 | |||
87 | /* Функции генерации контрольных сумм */ |
||
88 | void md5_hash(FILE* input, BYTE* hash ) |
||
89 | { |
||
90 | int input_size; |
||
91 | BYTE *temp_buffer; |
||
92 | temp_buffer=safe_malloc(1024); |
||
93 | MD5_CTX ctx; |
||
94 | md5_init(&ctx); |
||
95 | while((input_size = fread(temp_buffer, 1, 1024, input)) > 0){ |
||
96 | md5_update(&ctx, temp_buffer, input_size); |
||
97 | } |
||
98 | md5_final(&ctx, hash); |
||
99 | free(temp_buffer); |
||
100 | } |
||
101 | |||
102 | void sha1_hash(FILE* input, BYTE* hash ) |
||
103 | { |
||
104 | int input_size; |
||
105 | BYTE *buffer; |
||
106 | buffer=safe_malloc(1024); |
||
107 | SHA1_CTX ctx; |
||
108 | sha1_init(&ctx); |
||
109 | while((input_size = fread(buffer, 1, 1024, input)) > 0){ |
||
110 | sha1_update(&ctx, buffer, input_size); |
||
111 | } |
||
112 | sha1_final(&ctx, hash); |
||
113 | free(buffer); |
||
114 | } |
||
115 | |||
116 | void sha256_hash(FILE* input, BYTE* hash ) |
||
117 | { |
||
118 | int input_size; |
||
119 | BYTE *buffer; |
||
120 | buffer=safe_malloc(1024); |
||
121 | SHA256_CTX ctx; |
||
122 | sha256_init(&ctx); |
||
123 | while((input_size = fread(buffer, 1, 1024, input)) > 0){ |
||
124 | sha256_update(&ctx, buffer, input_size); |
||
125 | } |
||
126 | sha256_final(&ctx, hash); |
||
127 | free(buffer); |
||
128 | } |
||
129 | |||
130 | |||
131 | BYTE* check_sum(int alg) // Генерируем контрольные суммы используя один из алгоритмов |
||
132 | { |
||
133 | FILE* input_file; |
||
134 | BYTE *hash; |
||
135 | input_file=fopen(filename,"rb"); |
||
136 | hash = safe_malloc(alg); |
||
137 | switch (alg) |
||
138 | { |
||
139 | case MD5_BLOCK_SIZE : |
||
140 | md5_hash(input_file, hash); |
||
141 | md5_flag=1; |
||
142 | break; |
||
143 | |||
144 | case SHA1_BLOCK_SIZE : |
||
145 | sha1_hash(input_file, hash); |
||
146 | sha1_flag=1; |
||
147 | break; |
||
148 | |||
149 | case SHA256_BLOCK_SIZE : |
||
150 | sha256_hash(input_file, hash); |
||
151 | sha256_flag=1; |
||
152 | break; |
||
153 | } |
||
154 | fclose(input_file); |
||
155 | return hash; |
||
156 | } |
||
157 | |||
158 | void sprint_hash(BYTE *hash, char* hash_str, int hash_size) //Преобрауем двоичные данные из hash в строку hash_str |
||
159 | { |
||
160 | char block[3]; |
||
161 | memset(hash_str, 0, MAX_HASH_LEN); // Очищаем строку для strcat |
||
162 | for(int i=0; i |
||
163 | { |
||
164 | sprintf(block,"%02x", hash[i]); |
||
165 | strcat(hash_str,block); |
||
166 | } |
||
167 | free(hash); |
||
168 | } |
||
169 | |||
170 | void redraw_window() //Рисуем окно |
||
171 | { |
||
172 | sprintf(title,VERSION, filename); // Устанавливаем заголовок окна |
||
8430 | superturbo | 173 | pos_t win_pos = get_mouse_pos(0); // Получаем координаты курсора |
8073 | superturbo | 174 | begin_draw(); //Начинаем рисование интерфейса ) |
8250 | superturbo | 175 | sys_create_window(win_pos.x, win_pos.y, WINDOW_W, 150, title, sys_color_table.work_area, 0x14); // Создаём окно. |
8073 | superturbo | 176 | |
177 | draw_bar(10, 121, 525,20, WHITE); // Создаём прямоугольник для поля ввода |
||
178 | draw_text_sys(edit_box_buff,15, 125, 0, 0x90000000| edit_box_text_color); // Выводим текст из буффера ввода |
||
8373 | superturbo | 179 | draw_text_sys("|",10+(8*str_pos),125,0,0x90000000 | BLACK); |
8073 | superturbo | 180 | |
181 | define_button((10 << 16) + 60, (30 << 16) + 20, BTN_MD5, GREEN); // Определяем кнопку md5 |
||
182 | define_button((10 << 16) + 60, (60 << 16) + 20, BTN_SHA1, GREEN);// Определяем кнопку sha1 |
||
183 | define_button((10 << 16) + 60, (90 << 16) + 20, BTN_SHA256, GREEN);// Определяем кнопку sha256 |
||
184 | |||
185 | draw_text_sys("MD5:", 15, 34, 0, 0x90000000 | sys_color_table.work_button_text); // Пищем текст на кнопках |
||
186 | draw_text_sys("SHA1:", 15, 64, 0, 0x90000000 | sys_color_table.work_button_text); |
||
187 | draw_text_sys("SHA256:", 15,94, 0, 0x90000000 | sys_color_table.work_button_text); |
||
188 | |||
189 | draw_text_sys(hash_str_md5, 80, 34, 0, 0x90000000 | sys_color_table.work_text); // Выводим контрольные суммы в окно |
||
190 | draw_text_sys(hash_str_sha1, 80, 64, 0, 0x90000000 | sys_color_table.work_text); |
||
191 | draw_text_sys(hash_str_sha256, 80, 94, 0, 0x90000000| sys_color_table.work_text); |
||
192 | |||
193 | define_button((610 << 16) + 42, (30 << 16) + 20, BTN_COPY_MD5, sys_color_table.work_button); // Определяем кнопки для копирования |
||
194 | define_button((610<< 16) + 42, (60 << 16) + 20, BTN_COPY_SHA1, sys_color_table.work_button); |
||
195 | define_button((610<< 16) + 42, (90 << 16) + 20, BTN_COPY_SHA256, sys_color_table.work_button); |
||
196 | |||
197 | draw_text_sys("Copy", 615, 34, 0, 0x90000000 | sys_color_table.work_button_text); // Пишем copy на всех кнопках для копирования |
||
198 | draw_text_sys("Copy", 615, 64, 0, 0x90000000 | sys_color_table.work_button_text); |
||
199 | draw_text_sys("Copy", 615, 94, 0, 0x90000000 | sys_color_table.work_button_text); |
||
200 | |||
201 | define_button((592<< 16) + 60, (120 << 16) + 20, BTN_CMP, GREEN); // Определяем кнопку для сравнения контольных сумм |
||
202 | draw_text_sys("Compare", 595, 124 , 0,0x90000000 | sys_color_table.work_button_text); // Пишем текс на кнопке. |
||
203 | |||
204 | define_button((540 << 16) + 45, (120 << 16) + 20, BTN_PASTE, sys_color_table.work_button); //Кнопка для вставки (неработает) |
||
205 | draw_text_sys("Paste", 543, 124 , 0,0x90000000 | sys_color_table.work_button_text); // Текст paste на кнопке |
||
206 | end_draw(); |
||
207 | } |
||
208 | |||
209 | |||
210 | void paste_to_edit_buffer() // Вставить из буффера обмена |
||
211 | { |
||
8250 | superturbo | 212 | char *temp_buff=NULL; |
213 | if(kol_clip_num()>0) |
||
8073 | superturbo | 214 | { |
8250 | superturbo | 215 | temp_buff=kol_clip_get(kol_clip_num()-1); |
216 | memset(edit_box_buff,0,MAX_HASH_LEN); |
||
8430 | superturbo | 217 | if(DATA(int, temp_buff,0)>0 && DATA(int,temp_buff,4)==TEXT && DATA(int,temp_buff,8)==CP866) |
8250 | superturbo | 218 | { |
219 | strncpy(edit_box_buff,temp_buff+12, MAX_HASH_LEN-1); |
||
220 | str_pos=strlen(edit_box_buff); |
||
221 | notify_show("'Pasted from clipboard!' -I"); |
||
222 | edit_box_text_color=BLACK; |
||
223 | user_free(temp_buff); |
||
224 | } |
||
8073 | superturbo | 225 | } |
226 | } |
||
227 | |||
228 | |||
229 | void copy_to_clipboard(char *text) // Копирлвать в буффер обмена |
||
230 | { |
||
231 | if(55!=strlen(text)) |
||
232 | { |
||
233 | char *temp_buffer=safe_malloc(MAX_HASH_LEN+12); |
||
234 | memset(temp_buffer, 0, MAX_HASH_LEN); |
||
8430 | superturbo | 235 | DATA(char,temp_buffer,4)=TEXT; |
236 | DATA(char,temp_buffer,8)=CP866; |
||
8073 | superturbo | 237 | strncpy(temp_buffer+12, text, MAX_HASH_LEN-1); |
238 | kol_clip_set(strlen(text)+12, temp_buffer); |
||
239 | notify_show("'Copied to clipboard!' -I"); |
||
240 | free(temp_buffer); |
||
241 | } |
||
242 | } |
||
243 | |||
244 | void print_pending_calc(char *str) // Выводим сообщение о том что контрольная суммма вычисляется. |
||
245 | { |
||
246 | strcpy(str, "Please wait! Calculating checksum... "); |
||
247 | redraw_window(); |
||
248 | } |
||
249 | |||
250 | bool calc_and_cmp(char *hash_str_universal,int alg) // Вычисляем контрольную сумму и сравниваем с edit_box_buff. |
||
251 | { |
||
252 | print_pending_calc(hash_str_universal); |
||
253 | sprint_hash(check_sum(alg),hash_str_universal, alg); |
||
254 | return !strcmp(edit_box_buff, hash_str_universal); |
||
255 | } |
||
256 | |||
257 | bool hash_compare() // Главная функция для сравнения |
||
258 | { |
||
259 | int alg=strlen(edit_box_buff)/2; |
||
260 | |||
261 | switch (alg) // Если вычисления ещё небыло |
||
262 | { |
||
263 | case MD5_BLOCK_SIZE: |
||
264 | if(md5_flag) |
||
265 | { |
||
266 | return !strcmp(edit_box_buff,hash_str_md5); |
||
267 | } |
||
268 | else |
||
269 | { |
||
270 | return calc_and_cmp(hash_str_md5,alg); |
||
271 | } |
||
272 | break; |
||
273 | |||
274 | case SHA1_BLOCK_SIZE: |
||
275 | if(sha1_flag) |
||
276 | { |
||
277 | return !strcmp(edit_box_buff,hash_str_sha1); |
||
278 | } |
||
279 | else |
||
280 | { |
||
281 | return calc_and_cmp(hash_str_sha1,alg); |
||
282 | } |
||
283 | break; |
||
284 | |||
285 | case SHA256_BLOCK_SIZE: |
||
286 | |||
287 | if(sha256_flag) |
||
288 | { |
||
289 | return !strcmp(edit_box_buff,hash_str_sha256); |
||
290 | } |
||
291 | else |
||
292 | { |
||
293 | return calc_and_cmp(hash_str_sha256,alg); |
||
294 | } |
||
295 | break; |
||
296 | |||
297 | default: |
||
298 | return FALSE; |
||
299 | break; |
||
300 | } |
||
301 | } |
||
302 | |||
303 | void edit_box(oskey_t key) //Функция реализующая строку ввода |
||
304 | { |
||
8373 | superturbo | 305 | edit_box_text_color=BLACK; |
8073 | superturbo | 306 | if(key.code==CTRL_V) // Если нажато Ctrl+V то вставить из буфера обмена |
307 | { |
||
308 | paste_to_edit_buffer(); |
||
309 | } |
||
310 | if(key.code==BACKSPACE && str_pos>0) // Если backspace то удалить последний символ |
||
311 | { |
||
312 | str_pos--; |
||
313 | edit_box_buff[str_pos]='\0'; |
||
314 | |||
315 | } |
||
316 | else if(str_pos |
||
317 | { |
||
318 | if(strchr(hex,key.code)!=NULL) |
||
319 | { |
||
320 | edit_box_buff[str_pos]=key.code; |
||
321 | str_pos++; |
||
322 | } |
||
323 | } |
||
324 | } |
||
325 | |||
326 | int main(int argc, char** argv) |
||
327 | { |
||
8430 | superturbo | 328 | if(argc<2) // Если аргументов нет, то запускаем диалог выбора файла |
8073 | superturbo | 329 | { |
8430 | superturbo | 330 | kolibri_dialog_init(); // Инициализация библиотеки |
331 | open_dialog* dialog = kolibri_new_open_dialog(OPEN,0, 0, 420, 320); |
||
332 | OpenDialog_init(dialog); |
||
333 | OpenDialog_start(dialog); |
||
334 | if(dialog->status==SUCCESS) // Если файл выбран |
||
335 | { |
||
336 | global_var_init(strlen(dialog->openfile_path)); |
||
337 | strcpy(filename, dialog->openfile_path); |
||
338 | } |
||
339 | else // Если файл не выбран |
||
340 | { |
||
341 | notify_show("'No file selected!' -E"); |
||
342 | exit(0); |
||
343 | } |
||
344 | free(dialog); |
||
8073 | superturbo | 345 | } |
8430 | superturbo | 346 | else |
347 | { |
||
348 | global_var_init(strlen(argv[1])); |
||
349 | strcpy(filename, argv[1]); |
||
350 | } |
||
8073 | superturbo | 351 | |
352 | if(NULL==fopen(filename,"rb")) // Если файла нет или не открывается |
||
353 | { |
||
354 | notify_show("'File not found!' -E"); |
||
355 | exit(0); |
||
356 | } |
||
357 | |||
358 | if(GetScreenSize()/65536 |
||
359 | { |
||
360 | notify_show("'Low screen resolution! Program will not display correctrly!' -W"); |
||
361 | } |
||
362 | |||
8430 | superturbo | 363 | int gui_event; // Переменная для хранения события |
8073 | superturbo | 364 | uint32_t pressed_button = 0; // Код нажатой кнопки в окне |
365 | |||
366 | get_system_colors(&sys_color_table); |
||
8430 | superturbo | 367 | set_event_mask(0xC0000027);// Устанавливаем маску событий |
8073 | superturbo | 368 | do // Цикл обработки событий |
369 | { |
||
370 | gui_event = get_os_event(); // Получаем событие |
||
371 | switch(gui_event) // Обрабатываем события |
||
372 | { |
||
373 | case KOLIBRI_EVENT_NONE: |
||
374 | break; |
||
375 | case KOLIBRI_EVENT_REDRAW: |
||
376 | redraw_window(); |
||
377 | break; |
||
378 | case KOLIBRI_EVENT_KEY: |
||
379 | edit_box(get_key()); // Получаем нажатую клавишу и задействуем строку ввода |
||
380 | redraw_window(); |
||
381 | break; |
||
382 | case KOLIBRI_EVENT_BUTTON: // Событие обработки кнопок |
||
383 | pressed_button = get_os_button(); // Получение кода нажатой кнопки. |
||
384 | switch (pressed_button) // Проверка какая кнопка была нажата |
||
385 | { |
||
386 | case BTN_MD5: |
||
387 | print_pending_calc(hash_str_md5); |
||
388 | sprint_hash(check_sum(MD5_BLOCK_SIZE),hash_str_md5, MD5_BLOCK_SIZE); |
||
389 | redraw_window(); |
||
390 | break; |
||
391 | |||
392 | case BTN_SHA1: |
||
393 | print_pending_calc(hash_str_sha1); |
||
394 | sprint_hash(check_sum(SHA1_BLOCK_SIZE),hash_str_sha1, SHA1_BLOCK_SIZE); |
||
395 | redraw_window(); |
||
396 | break; |
||
397 | |||
398 | case BTN_SHA256: |
||
399 | print_pending_calc(hash_str_sha256); |
||
400 | sprint_hash(check_sum(SHA256_BLOCK_SIZE),hash_str_sha256, SHA256_BLOCK_SIZE); |
||
401 | redraw_window(); |
||
402 | break; |
||
403 | |||
404 | case BTN_COPY_MD5: |
||
405 | redraw_window(); |
||
406 | copy_to_clipboard(hash_str_md5); |
||
407 | break; |
||
408 | |||
409 | case BTN_COPY_SHA1: |
||
410 | redraw_window(); |
||
411 | copy_to_clipboard(hash_str_sha1); |
||
412 | break; |
||
413 | |||
414 | case BTN_COPY_SHA256: |
||
415 | redraw_window(); |
||
416 | copy_to_clipboard(hash_str_sha256); |
||
417 | break; |
||
418 | |||
419 | case BTN_PASTE: |
||
420 | paste_to_edit_buffer(); |
||
421 | redraw_window(); |
||
422 | break; |
||
423 | |||
424 | case BTN_CMP: |
||
425 | if(hash_compare()) |
||
426 | { |
||
427 | notify_show("'The checksum matches :)' -OK"); |
||
428 | edit_box_text_color=GREEN; // Устанавливаем текст ввода зелёным если контрольная сумма совпадает |
||
429 | } |
||
430 | else |
||
431 | { |
||
432 | notify_show("'The checksum does not match! :(' -W"); |
||
433 | edit_box_text_color=RED; // Устанавливаем текст ввода красным если контрольная суммы не совпадает |
||
434 | } |
||
435 | redraw_window(); |
||
436 | break; |
||
437 | |||
438 | case BTN_QUIT: |
||
439 | exit(0); |
||
440 | break; |
||
441 | } |
||
442 | } |
||
443 | }while(1); |
||
8430 | superturbo | 444 | exit(0); |
8073 | superturbo | 445 | } |