/* Copyright (C) 2019-2021 Logaev Maxim (turbocat2001), GPLv2 */ #include #include #include #include #include #include #include #include #include #include #define TRUE 1; #define FALSE 0; #define MAX_HASH_LEN 65 // Максимальная длина строки #define WINDOW_W 665 #define VERSION "%s - thashview 2.6.2" #define EDIT_TEXT_SIZE 0x10000000 #define DATA(type, addr, offset) *((type*)((uint8_t*)addr+offset)) ksys_colors_table_t sys_color_table; char hash_str_md5[MAX_HASH_LEN]= "Click the 'MD5:' button to show the md5-checksum!"; //Вывод MD5 char hash_str_sha1[MAX_HASH_LEN]= "Click the 'SHA1:' button to show the sha1-checksum!"; //Вывод SHA1 char hash_str_sha256[MAX_HASH_LEN]="Click the 'SHA256:' button to show the sha256-checksum!"; //Вывод SHA256 char edit_box_buff[MAX_HASH_LEN]; // Буффер для ввода char *filename; // Имя обрабатываемого файла char *title; // Заголовок окна enum MYCOLORS // Цвета { GREEN = 0x067D06 | EDIT_TEXT_SIZE, RED = 0xFF0000 | EDIT_TEXT_SIZE, BLACK = 0x000000 | EDIT_TEXT_SIZE, WHITE = 0xFFFFFF, GREY = 0x919191 }; edit_box hash_edit_box={WINDOW_W-140,10,121,WHITE,0,0,GREY,EDIT_TEXT_SIZE, MAX_HASH_LEN-1, edit_box_buff,NULL,ed_focus}; // Создаём структуру edit_box int md5_flag=0, sha1_flag=0, sha256_flag=0; // Флаги показывающие была ли уже рассчитана котрольная сумма в функции check_sum() enum BUTTONS // Кнопки в интрефейсе { BTN_QUIT=1, //Выход BTN_MD5 = 10, //Рассчитать md5-контрольную сумму BTN_SHA1 = 20, //Рассчитать sha1-контрольную сумму BTN_SHA256 = 30, //Рассчитать sha256-контрольную сумму BTN_COPY_MD5= 11, //Скопировать в буффер обмена BTN_COPY_SHA1= 21, BTN_COPY_SHA256=31, BTN_CMP=40, //Сравнить edit_box и контрольную сумму BTN_PASTE=50 //Вставить в edit_box(пока в разработке) }; void notify_show(char *text) { _ksys_exec("/sys/@notify", text); } void* safe_malloc(size_t size) // Безопасный malloc. Показывает уведомление об ошибке и закрывает программу если память не была выделена { void *p=malloc(size); if(p==NULL){ notify_show("'Memory allocation error!' -E"); exit(0); }else{ return p; } } void global_var_init(unsigned int size) // Инициализируются глобальные массивы { filename=safe_malloc(size); title=safe_malloc(size+20); } /* Функции генерации контрольных сумм */ void md5_hash(FILE* input, BYTE* hash ) { int input_size; BYTE *temp_buffer; temp_buffer=safe_malloc(1024); MD5_CTX ctx; md5_init(&ctx); while((input_size = fread(temp_buffer, 1, 1024, input)) > 0){ md5_update(&ctx, temp_buffer, input_size); } md5_final(&ctx, hash); free(temp_buffer); } void sha1_hash(FILE* input, BYTE* hash ) { int input_size; BYTE *buffer; buffer=safe_malloc(1024); SHA1_CTX ctx; sha1_init(&ctx); while((input_size = fread(buffer, 1, 1024, input)) > 0){ sha1_update(&ctx, buffer, input_size); } sha1_final(&ctx, hash); free(buffer); } void sha256_hash(FILE* input, BYTE* hash ) { int input_size; BYTE *buffer; buffer=safe_malloc(1024); SHA256_CTX ctx; sha256_init(&ctx); while((input_size = fread(buffer, 1, 1024, input)) > 0){ sha256_update(&ctx, buffer, input_size); } sha256_final(&ctx, hash); free(buffer); } BYTE* check_sum(int alg) // Генерируем контрольные суммы используя один из алгоритмов { FILE* input_file; BYTE *hash; input_file=fopen(filename,"rb"); hash = safe_malloc(alg); switch (alg) { case MD5_BLOCK_SIZE : md5_hash(input_file, hash); md5_flag=1; break; case SHA1_BLOCK_SIZE : sha1_hash(input_file, hash); sha1_flag=1; break; case SHA256_BLOCK_SIZE : sha256_hash(input_file, hash); sha256_flag=1; break; } fclose(input_file); return hash; } void sprint_hash(BYTE *hash, char* hash_str, int hash_size) //Преобрауем двоичные данные из hash в строку hash_str { char block[3]; memset(hash_str, 0, MAX_HASH_LEN); // Очищаем строку для strcat for(int i=0; i0){ temp_buff=_ksys_clip_get(_ksys_clip_num()-1); memset(edit_box_buff,0,MAX_HASH_LEN); if(DATA(int, temp_buff,0)>0 && DATA(int,temp_buff,4)==KSYS_CLIP_TEXT && DATA(int,temp_buff,8)==KSYS_CLIP_CP866){ strncpy(edit_box_buff,temp_buff+12, MAX_HASH_LEN-1); edit_box_set_text(&hash_edit_box,edit_box_buff); notify_show("'Pasted from clipboard!' -I"); hash_edit_box.text_color = BLACK; free(temp_buff); } } } void copy_to_clipboard(char *text) // Копировать в буфер обмена { int text_hash_len = strlen(text)/2; if(text_hash_len==MD5_BLOCK_SIZE || text_hash_len==SHA1_BLOCK_SIZE || text_hash_len==SHA256_BLOCK_SIZE) // Если текст является хэш-строкой { char *temp_buffer=safe_malloc(MAX_HASH_LEN+12); // Выделяем память для времнного буфера memset(temp_buffer, 0, MAX_HASH_LEN); // Зануляем буфер DATA(char,temp_buffer,4)=KSYS_CLIP_TEXT; // Устанавливаем TEXT для буфера(Смещение 4 байта) DATA(char,temp_buffer,8)=KSYS_CLIP_CP866; // Устанавливаем кодировку CP866(Смещение 8 байт) strncpy(temp_buffer+12, text, MAX_HASH_LEN-1); // Копируем данные из text во временный буфер(Смещение 12 байт) _ksys_clip_set(strlen(text)+12, temp_buffer); // Выполняем системный вызов и перемещаем данные из временного буфера в буфер обмена notify_show("'Copied to clipboard!' -I"); free(temp_buffer); // Освобожаем временный буфер. } } void print_pending_calc(char *str) // Выводим сообщение о том что контрольная суммма вычисляется. { strcpy(str, "Please wait! Calculating checksum..."); redraw_window(); } bool calc_and_cmp(char *hash_str_universal,int alg) // Вычисляем контрольную сумму и сравниваем с edit_box_buff. { print_pending_calc(hash_str_universal); sprint_hash(check_sum(alg),hash_str_universal, alg); return !strcmp(edit_box_buff, hash_str_universal); } bool hash_compare() // Главная функция для сравнения { int alg=strlen(edit_box_buff)/2; switch (alg){ // Если вычисления ещё небыло case MD5_BLOCK_SIZE: if(md5_flag){ return !strcmp(edit_box_buff,hash_str_md5); }else{ return calc_and_cmp(hash_str_md5,alg); } break; case SHA1_BLOCK_SIZE: if(sha1_flag){ return !strcmp(edit_box_buff,hash_str_sha1); }else{ return calc_and_cmp(hash_str_sha1,alg); } break; case SHA256_BLOCK_SIZE: if(sha256_flag){ return !strcmp(edit_box_buff,hash_str_sha256); }else{ return calc_and_cmp(hash_str_sha256,alg); } break; default: return FALSE; break; } } int main(int argc, char** argv) { if(argc<2){ // Если аргументов нет, то запускаем диалог выбора фа open_dialog* dialog = kolibri_new_open_dialog(OPEN,0, 0, 420, 320); OpenDialog_init(dialog); OpenDialog_start(dialog); if(dialog->status==SUCCESS){ // Если файл выбран global_var_init(strlen(dialog->openfile_path)); strcpy(filename, dialog->openfile_path); }else{ // Если файл не выбран notify_show("'No file selected!' -E"); exit(0); } free(dialog); }else{ global_var_init(strlen(argv[1])); strcpy(filename, argv[1]); } if(NULL==fopen(filename,"rb")){ // Если файла нет или не открывается notify_show("'File not found!' -E"); exit(0); } if(_ksys_screen_size().x