Merge pull request #50 from xperia64/master

Add SHA1 Context Menu Item
This commit is contained in:
TheOfficialFloW 2016-09-07 13:20:36 +02:00 committed by GitHub
commit 0e7ad6cef4
9 changed files with 201 additions and 2 deletions

54
file.c
View File

@ -20,6 +20,7 @@
#include "archive.h"
#include "file.h"
#include "utils.h"
#include "sha1.h"
static char *mount_points[] = {
"app0:",
@ -94,6 +95,59 @@ int getFileSize(char *pInputFileName)
return fileSize;
}
int getFileSha1(char *pInputFileName, uint8_t *pSha1Out, uint64_t *value, uint64_t max, void (* SetProgress)(uint64_t value, uint64_t max), int (* cancelHandler)()) {
// Set up SHA1 context
SHA1_CTX ctx;
sha1_init(&ctx);
// Open the file to read, else return the error
SceUID fd = sceIoOpen(pInputFileName, SCE_O_RDONLY, 0);
if (fd < 0)
return fd;
// Open up the buffer for copying data into
void *buf = malloc(TRANSFER_SIZE);
int read;
// Actually take the SHA1 sum
while ((read = sceIoRead(fd, buf, TRANSFER_SIZE)) > 0)
{
sha1_update(&ctx, buf, read);
// Defined in io_process.c, check to make sure pointer isn't null before incrementing
if(value)
(*value)++; // Note: Max value is filesize/TRANSFER_SIZE
if(SetProgress)
SetProgress(value ? *value : 0, max);
// Check to see if cancelHandler exists, if so call it and free memory if cancelled
if(cancelHandler && cancelHandler()) {
free(buf);
sceIoClose(fd);
return 0;
}
// This is CPU intensive so the progress bar won't refresh unless we sleep
// DIALOG_WAIT seemed too long for this application
// so I set it to 1/2 of a second every 8192 TRANSFER_SIZE blocks
if((*value)%8192 == 0)
sceKernelDelayThread(500000);
}
// Final iteration of SHA1 sum, dump final value into pSha1Out buffer
sha1_final(&ctx, pSha1Out);
// Free up file buffer
free(buf);
// Close file proper
sceIoClose(fd);
return 1;
}
int getPathInfo(char *path, uint64_t *size, uint32_t *folders, uint32_t *files) {
SceUID dfd = sceIoDopen(path);
if (dfd >= 0) {

1
file.h
View File

@ -79,6 +79,7 @@ int ReadFile(char *file, void *buf, int size);
int WriteFile(char *file, void *buf, int size);
int getFileSize(char *pInputFileName);
int getFileSha1(char *pInputFileName, uint8_t *pSha1Out, uint64_t *value, uint64_t max, void (*SetProgress)(uint64_t value, uint64_t max), int (* cancelHandler)());
int getPathInfo(char *path, uint64_t *size, uint32_t *folders, uint32_t *files);
int removePath(char *path, uint64_t *value, uint64_t max, void (* SetProgress)(uint64_t value, uint64_t max), int (* cancelHandler)());
int copyFile(char *src_path, char *dst_path, uint64_t *value, uint64_t max, void (* SetProgress)(uint64_t value, uint64_t max), int (* cancelHandler)());

View File

@ -319,4 +319,72 @@ EXIT:
powerUnlock();
return sceKernelExitDeleteThread(0);
}
}
int hash_thread(SceSize args_size, HashArguments *args) {
SceUID thid = -1;
// Lock power timers
powerLock();
// Set progress to 0%
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 0);
sceKernelDelayThread(DIALOG_WAIT); // Needed to see the percentage
uint64_t max = (uint64_t) (getFileSize(args->file_path)/(TRANSFER_SIZE));
// SHA1 process
uint64_t value = 0;
// Spin off a thread to update the progress dialog
thid = createStartUpdateThread(max);
uint8_t sha1out[20];
int res = getFileSha1(args->file_path, sha1out, &value, max, SetProgress, cancelHandler);
if (res <= 0) {
// SHA1 Didn't complete successfully, or was cancelled
closeWaitDialog();
dialog_step = DIALOG_STEP_CANCELLED;
errorDialog(res);
goto EXIT;
}
// Since we hit here, we're done. Set progress to 100%
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 100);
sceKernelDelayThread(COUNTUP_WAIT);
// Close
closeWaitDialog();
char sha1msg[41];
int i;
// Construct SHA1 sum string
for (i = 0; i < 20; i++) {
sprintf(sha1msg + (2*i), "%02x ", sha1out[i]);
}
sha1msg[40] = '\0';
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_OK, sha1msg);
dialog_step = DIALOG_STEP_HASH_DISPLAY;
// Wait for response
while (dialog_step == DIALOG_STEP_HASH_DISPLAY) {
sceKernelDelayThread(1000);
}
closeWaitDialog();
sceMsgDialogClose();
EXIT:
// Ensure the update thread ends gracefully
if(thid>=0)
sceKernelWaitThreadEnd(thid, NULL, NULL);
powerUnlock();
// Kill current thread
return sceKernelExitDeleteThread(0);
}

View File

@ -45,6 +45,10 @@ typedef struct {
int copy_mode;
} CopyArguments;
typedef struct {
char *file_path;
} HashArguments;
void closeWaitDialog();
int cancelHandler();
void SetProgress(uint64_t value, uint64_t max);
@ -52,5 +56,6 @@ SceUID createStartUpdateThread(uint64_t max);
int delete_thread(SceSize args_size, DeleteArguments *args);
int copy_thread(SceSize args_size, CopyArguments *args);
int hash_thread(SceSize args_size, HashArguments *args);
#endif
#endif

View File

@ -98,6 +98,9 @@ void loadLanguage(int id) {
LANGUAGE_ENTRY(SYS_INFO),
LANGUAGE_ENTRY(INSTALL_ALL),
LANGUAGE_ENTRY(UPDATE_QUESTION),
LANGUAGE_ENTRY(SHA1),
LANGUAGE_ENTRY(HASHING),
LANGUAGE_ENTRY(HASH_FILE_QUESTION),
};
// Load default config file

View File

@ -56,6 +56,9 @@ enum LanguageContainer {
SYS_INFO,
INSTALL_ALL,
UPDATE_QUESTION,
SHA1,
HASHING,
HASH_FILE_QUESTION,
LANGUAGE_CONTRAINER_SIZE,
};

57
main.c
View File

@ -450,6 +450,7 @@ enum MenuEntrys {
MENU_ENTRY_RENAME,
MENU_ENTRY_EMPTY_4,
MENU_ENTRY_NEW_FOLDER,
MENU_ENTRY_SHA1,
};
enum MenuVisibilities {
@ -475,6 +476,7 @@ MenuEntry menu_entries[] = {
{ RENAME, VISIBILITY_INVISIBLE },
{ -1, VISIBILITY_UNUSED },
{ NEW_FOLDER, VISIBILITY_INVISIBLE },
{ SHA1, VISIBILITY_INVISIBLE }
};
#define N_MENU_ENTRIES (sizeof(menu_entries) / sizeof(MenuEntry))
@ -497,6 +499,7 @@ void initContextMenu() {
menu_entries[MENU_ENTRY_COPY].visibility = VISIBILITY_INVISIBLE;
menu_entries[MENU_ENTRY_DELETE].visibility = VISIBILITY_INVISIBLE;
menu_entries[MENU_ENTRY_RENAME].visibility = VISIBILITY_INVISIBLE;
menu_entries[MENU_ENTRY_SHA1].visibility = VISIBILITY_INVISIBLE;
}
// Invisible 'Paste' if nothing is copied yet
@ -510,6 +513,11 @@ void initContextMenu() {
menu_entries[MENU_ENTRY_DELETE].visibility = VISIBILITY_INVISIBLE;
menu_entries[MENU_ENTRY_RENAME].visibility = VISIBILITY_INVISIBLE;
menu_entries[MENU_ENTRY_NEW_FOLDER].visibility = VISIBILITY_INVISIBLE;
menu_entries[MENU_ENTRY_SHA1].visibility = VISIBILITY_INVISIBLE;
}
if(file_entry->is_folder) {
menu_entries[MENU_ENTRY_SHA1].visibility = VISIBILITY_INVISIBLE;
}
if(file_entry->type != FILE_TYPE_VPK) {
@ -790,6 +798,14 @@ void contextMenuCtrl() {
dialog_step = DIALOG_STEP_NEW_FOLDER;
break;
}
case MENU_ENTRY_SHA1:
{
// Ensure user wants to actually take the hash
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_YESNO, language_container[HASH_FILE_QUESTION]);
dialog_step = DIALOG_STEP_HASH_QUESTION;
break;
}
case MENU_ENTRY_INSTALL_ALL:
{
@ -982,7 +998,48 @@ int dialogSteps() {
}
break;
case DIALOG_STEP_HASH_QUESTION:
if (msg_result == MESSAGE_DIALOG_RESULT_YES) {
// Throw up the progress bar, enter hashing state
initMessageDialog(MESSAGE_DIALOG_PROGRESS_BAR, language_container[HASHING]);
dialog_step = DIALOG_STEP_HASH_CONFIRMED;
} else if (msg_result == MESSAGE_DIALOG_RESULT_NO) {
// Quit
dialog_step = DIALOG_STEP_NONE;
}
break;
case DIALOG_STEP_HASH_CONFIRMED:
if (msg_result == MESSAGE_DIALOG_RESULT_RUNNING) {
// User has confirmed desire to hash, get requested file entry
FileListEntry *file_entry = fileListGetNthEntry(&file_list, base_pos + rel_pos);
// Place the full file path in cur_file
snprintf(cur_file, MAX_PATH_LENGTH, "%s%s", file_list.path, file_entry->name);
HashArguments args;
args.file_path = cur_file;
// Create a thread to run out actual sum
SceUID thid = sceKernelCreateThread("hash_thread", (SceKernelThreadEntry)hash_thread, 0x40, 0x10000, 0, 0, NULL);
if (thid >= 0)
sceKernelStartThread(thid, sizeof(HashArguments), &args);
dialog_step = DIALOG_STEP_HASHING;
}
break;
case DIALOG_STEP_HASH_DISPLAY:
// Reset dialog state when user selects yes/no
if (msg_result == MESSAGE_DIALOG_RESULT_NONE || msg_result == MESSAGE_DIALOG_RESULT_FINISHED) {
dialog_step = DIALOG_STEP_NONE;
}
break;
case DIALOG_STEP_INSTALL_QUESTION:
if (msg_result == MESSAGE_DIALOG_RESULT_YES) {
initMessageDialog(MESSAGE_DIALOG_PROGRESS_BAR, language_container[INSTALLING]);

5
main.h
View File

@ -179,6 +179,11 @@ enum DialogSteps {
DIALOG_STEP_DOWNLOADED,
DIALOG_STEP_EXTRACTING,
DIALOG_STEP_EXTRACTED,
DIALOG_STEP_HASH_QUESTION,
DIALOG_STEP_HASH_CONFIRMED,
DIALOG_STEP_HASHING,
DIALOG_STEP_HASH_DISPLAY,
};
extern vita2d_pgf *font;

View File

@ -15,6 +15,9 @@ DELETE = "Delete"
RENAME = "Rename"
NEW_FOLDER = "New folder"
FOLDER = "Folder"
SHA1 = "SHA1 checksum"
HASHING = "Hashing..."
HASH_FILE_QUESTION = "SHA1 hashing may take a long time. Continue?"
COPIED_FILE = "Copied %d file."
COPIED_FOLDER = "Copied %d folder."
COPIED_FILES_FOLDERS = "Copied %d files/folders."