Version v0.2.22 - Added text editor and file manager integration
This commit is contained in:
319
otp.c
319
otp.c
@@ -47,6 +47,12 @@ int main(int argc, char* argv[]);
|
||||
int interactive_mode(void);
|
||||
int command_line_mode(int argc, char* argv[]);
|
||||
|
||||
// Editor and file manager functions
|
||||
char* get_preferred_editor(void);
|
||||
char* get_preferred_file_manager(void);
|
||||
int launch_text_editor(const char* initial_content, char* result_buffer, size_t buffer_size);
|
||||
int launch_file_manager(const char* start_directory, char* selected_file, size_t buffer_size);
|
||||
|
||||
// Core functions
|
||||
int generate_pad(uint64_t size_bytes, int show_progress);
|
||||
int generate_pad_with_entropy(uint64_t size_bytes, int show_progress, int use_keyboard_entropy);
|
||||
@@ -329,25 +335,92 @@ int handle_encrypt_menu(void) {
|
||||
|
||||
if (choice == 1) {
|
||||
// Text encryption
|
||||
printf("\nEnter pad selection (number, chksum, or prefix): ");
|
||||
char input[MAX_HASH_LENGTH];
|
||||
if (!fgets(input, sizeof(input), stdin)) {
|
||||
printf("\nPad selection options:\n");
|
||||
printf("1. Select from numbered list\n");
|
||||
printf("2. Enter checksum/prefix manually\n");
|
||||
printf("3. Browse pad files\n");
|
||||
printf("Enter choice (1-3): ");
|
||||
|
||||
char pad_choice[10];
|
||||
if (!fgets(pad_choice, sizeof(pad_choice), stdin)) {
|
||||
printf("Error: Failed to read input\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
input[strcspn(input, "\n")] = 0;
|
||||
char input[MAX_HASH_LENGTH];
|
||||
if (atoi(pad_choice) == 3) {
|
||||
// Use file manager to browse pads directory
|
||||
char selected_pad[512];
|
||||
if (launch_file_manager("pads", selected_pad, sizeof(selected_pad)) == 0) {
|
||||
// Extract checksum from selected .pad file
|
||||
char* filename = strrchr(selected_pad, '/');
|
||||
if (!filename) filename = selected_pad;
|
||||
else filename++; // Skip the '/'
|
||||
|
||||
// Remove .pad extension to get checksum
|
||||
if (strlen(filename) == 68 && strstr(filename, ".pad")) {
|
||||
strncpy(input, filename, 64);
|
||||
input[64] = '\0';
|
||||
} else {
|
||||
printf("Invalid pad file selected.\n");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
printf("Falling back to manual pad selection.\n");
|
||||
printf("Enter pad selection (number, chksum, or prefix): ");
|
||||
if (!fgets(input, sizeof(input), stdin)) {
|
||||
printf("Error: Failed to read input\n");
|
||||
return 1;
|
||||
}
|
||||
input[strcspn(input, "\n")] = 0;
|
||||
}
|
||||
} else {
|
||||
// Manual pad selection
|
||||
printf("Enter pad selection (number, chksum, or prefix): ");
|
||||
if (!fgets(input, sizeof(input), stdin)) {
|
||||
printf("Error: Failed to read input\n");
|
||||
return 1;
|
||||
}
|
||||
input[strcspn(input, "\n")] = 0;
|
||||
}
|
||||
|
||||
return encrypt_text(input, NULL); // NULL for interactive mode
|
||||
}
|
||||
else if (choice == 2) {
|
||||
// File encryption
|
||||
printf("\nEnter input file path: ");
|
||||
printf("\nFile selection options:\n");
|
||||
printf("1. Type file path directly\n");
|
||||
printf("2. Use file manager\n");
|
||||
printf("Enter choice (1-2): ");
|
||||
|
||||
char file_choice[10];
|
||||
char input_file[512];
|
||||
if (!fgets(input_file, sizeof(input_file), stdin)) {
|
||||
|
||||
if (!fgets(file_choice, sizeof(file_choice), stdin)) {
|
||||
printf("Error: Failed to read input\n");
|
||||
return 1;
|
||||
}
|
||||
input_file[strcspn(input_file, "\n")] = 0;
|
||||
|
||||
if (atoi(file_choice) == 2) {
|
||||
// Use file manager
|
||||
if (launch_file_manager(".", input_file, sizeof(input_file)) != 0) {
|
||||
printf("Falling back to manual file path entry.\n");
|
||||
printf("Enter input file path: ");
|
||||
if (!fgets(input_file, sizeof(input_file), stdin)) {
|
||||
printf("Error: Failed to read input\n");
|
||||
return 1;
|
||||
}
|
||||
input_file[strcspn(input_file, "\n")] = 0;
|
||||
}
|
||||
} else {
|
||||
// Direct file path input
|
||||
printf("Enter input file path: ");
|
||||
if (!fgets(input_file, sizeof(input_file), stdin)) {
|
||||
printf("Error: Failed to read input\n");
|
||||
return 1;
|
||||
}
|
||||
input_file[strcspn(input_file, "\n")] = 0;
|
||||
}
|
||||
|
||||
// Check if file exists
|
||||
if (access(input_file, R_OK) != 0) {
|
||||
@@ -1076,19 +1149,53 @@ int encrypt_text(const char* pad_identifier, const char* input_text) {
|
||||
text_buffer[sizeof(text_buffer) - 1] = '\0';
|
||||
} else {
|
||||
// Get input text from user (interactive mode)
|
||||
printf("Enter text to encrypt: ");
|
||||
fflush(stdout);
|
||||
printf("\nText input options:\n");
|
||||
printf("1. Type text directly\n");
|
||||
printf("2. Use text editor\n");
|
||||
printf("Enter choice (1-2): ");
|
||||
|
||||
if (fgets(text_buffer, sizeof(text_buffer), stdin) == NULL) {
|
||||
char input_choice[10];
|
||||
if (!fgets(input_choice, sizeof(input_choice), stdin)) {
|
||||
printf("Error: Failed to read input\n");
|
||||
free(pad_chksum);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Remove newline if present
|
||||
size_t len = strlen(text_buffer);
|
||||
if (len > 0 && text_buffer[len - 1] == '\n') {
|
||||
text_buffer[len - 1] = '\0';
|
||||
if (atoi(input_choice) == 2) {
|
||||
// Use text editor
|
||||
if (launch_text_editor(NULL, text_buffer, sizeof(text_buffer)) != 0) {
|
||||
printf("Falling back to direct text input.\n");
|
||||
printf("Enter text to encrypt: ");
|
||||
fflush(stdout);
|
||||
|
||||
if (fgets(text_buffer, sizeof(text_buffer), stdin) == NULL) {
|
||||
printf("Error: Failed to read input\n");
|
||||
free(pad_chksum);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Remove newline if present
|
||||
size_t len = strlen(text_buffer);
|
||||
if (len > 0 && text_buffer[len - 1] == '\n') {
|
||||
text_buffer[len - 1] = '\0';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Direct text input
|
||||
printf("Enter text to encrypt: ");
|
||||
fflush(stdout);
|
||||
|
||||
if (fgets(text_buffer, sizeof(text_buffer), stdin) == NULL) {
|
||||
printf("Error: Failed to read input\n");
|
||||
free(pad_chksum);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Remove newline if present
|
||||
size_t len = strlen(text_buffer);
|
||||
if (len > 0 && text_buffer[len - 1] == '\n') {
|
||||
text_buffer[len - 1] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2182,6 +2289,190 @@ void simple_entropy_mix(unsigned char* urandom_buffer, size_t buffer_size,
|
||||
}
|
||||
}
|
||||
|
||||
// Editor and file manager implementations
|
||||
|
||||
char* get_preferred_editor(void) {
|
||||
// Check EDITOR environment variable first
|
||||
char* editor = getenv("EDITOR");
|
||||
if (editor && strlen(editor) > 0) {
|
||||
// Verify the editor exists
|
||||
char command[512];
|
||||
snprintf(command, sizeof(command), "which %s >/dev/null 2>&1", editor);
|
||||
if (system(command) == 0) {
|
||||
return strdup(editor);
|
||||
}
|
||||
}
|
||||
|
||||
// Check VISUAL environment variable
|
||||
editor = getenv("VISUAL");
|
||||
if (editor && strlen(editor) > 0) {
|
||||
char command[512];
|
||||
snprintf(command, sizeof(command), "which %s >/dev/null 2>&1", editor);
|
||||
if (system(command) == 0) {
|
||||
return strdup(editor);
|
||||
}
|
||||
}
|
||||
|
||||
// Try common editors in order of preference
|
||||
const char* common_editors[] = {"vim", "vi", "nano", "emacs", "gedit", NULL};
|
||||
for (int i = 0; common_editors[i] != NULL; i++) {
|
||||
char command[512];
|
||||
snprintf(command, sizeof(command), "which %s >/dev/null 2>&1", common_editors[i]);
|
||||
if (system(command) == 0) {
|
||||
return strdup(common_editors[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL; // No editor found
|
||||
}
|
||||
|
||||
char* get_preferred_file_manager(void) {
|
||||
// Try file managers in order of preference
|
||||
const char* file_managers[] = {"ranger", "fzf", "nnn", "lf", NULL};
|
||||
|
||||
for (int i = 0; file_managers[i] != NULL; i++) {
|
||||
char command[512];
|
||||
snprintf(command, sizeof(command), "which %s >/dev/null 2>&1", file_managers[i]);
|
||||
if (system(command) == 0) {
|
||||
return strdup(file_managers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL; // No file manager found
|
||||
}
|
||||
|
||||
int launch_text_editor(const char* initial_content, char* result_buffer, size_t buffer_size) {
|
||||
char* editor = get_preferred_editor();
|
||||
if (!editor) {
|
||||
printf("Error: No text editor found. Set EDITOR environment variable or install vim/nano.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create temporary file
|
||||
char temp_filename[64];
|
||||
snprintf(temp_filename, sizeof(temp_filename), "/tmp/otp_edit_%ld.tmp", time(NULL));
|
||||
|
||||
// Write initial content to temp file if provided
|
||||
if (initial_content && strlen(initial_content) > 0) {
|
||||
FILE* temp_file = fopen(temp_filename, "w");
|
||||
if (temp_file) {
|
||||
fputs(initial_content, temp_file);
|
||||
fclose(temp_file);
|
||||
}
|
||||
} else {
|
||||
// Create empty temp file
|
||||
FILE* temp_file = fopen(temp_filename, "w");
|
||||
if (temp_file) {
|
||||
fclose(temp_file);
|
||||
}
|
||||
}
|
||||
|
||||
// Launch editor
|
||||
printf("Opening %s for text editing...\n", editor);
|
||||
char command[512];
|
||||
snprintf(command, sizeof(command), "%s %s", editor, temp_filename);
|
||||
|
||||
int result = system(command);
|
||||
|
||||
if (result == 0) {
|
||||
// Read the edited content back
|
||||
FILE* temp_file = fopen(temp_filename, "r");
|
||||
if (temp_file) {
|
||||
size_t bytes_read = fread(result_buffer, 1, buffer_size - 1, temp_file);
|
||||
result_buffer[bytes_read] = '\0';
|
||||
|
||||
// Remove trailing newline if present
|
||||
if (bytes_read > 0 && result_buffer[bytes_read - 1] == '\n') {
|
||||
result_buffer[bytes_read - 1] = '\0';
|
||||
}
|
||||
|
||||
fclose(temp_file);
|
||||
} else {
|
||||
printf("Error: Cannot read edited content\n");
|
||||
free(editor);
|
||||
unlink(temp_filename);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
printf("Editor exited with error or was cancelled\n");
|
||||
free(editor);
|
||||
unlink(temp_filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Clean up
|
||||
unlink(temp_filename);
|
||||
free(editor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int launch_file_manager(const char* start_directory, char* selected_file, size_t buffer_size) {
|
||||
char* fm = get_preferred_file_manager();
|
||||
if (!fm) {
|
||||
printf("No file manager found. Please install ranger, fzf, nnn, or lf.\n");
|
||||
printf("Falling back to manual file path entry.\n");
|
||||
return 1; // Fall back to manual entry
|
||||
}
|
||||
|
||||
char temp_filename[64];
|
||||
snprintf(temp_filename, sizeof(temp_filename), "/tmp/otp_file_%ld.tmp", time(NULL));
|
||||
|
||||
char command[512];
|
||||
int result = 1;
|
||||
|
||||
printf("Opening %s for file selection...\n", fm);
|
||||
|
||||
if (strcmp(fm, "ranger") == 0) {
|
||||
snprintf(command, sizeof(command), "cd '%s' && ranger --choosefile=%s",
|
||||
start_directory ? start_directory : ".", temp_filename);
|
||||
} else if (strcmp(fm, "fzf") == 0) {
|
||||
snprintf(command, sizeof(command), "cd '%s' && find . -type f | fzf > %s",
|
||||
start_directory ? start_directory : ".", temp_filename);
|
||||
} else if (strcmp(fm, "nnn") == 0) {
|
||||
snprintf(command, sizeof(command), "cd '%s' && nnn -p %s",
|
||||
start_directory ? start_directory : ".", temp_filename);
|
||||
} else if (strcmp(fm, "lf") == 0) {
|
||||
snprintf(command, sizeof(command), "cd '%s' && lf -selection-path=%s",
|
||||
start_directory ? start_directory : ".", temp_filename);
|
||||
}
|
||||
|
||||
result = system(command);
|
||||
|
||||
if (result == 0 || result == 256) { // Some file managers return 256 on success
|
||||
// Read selected file from temp file
|
||||
FILE* temp_file = fopen(temp_filename, "r");
|
||||
if (temp_file) {
|
||||
if (fgets(selected_file, buffer_size, temp_file)) {
|
||||
// Remove trailing newline
|
||||
selected_file[strcspn(selected_file, "\n\r")] = 0;
|
||||
|
||||
// For relative paths from fzf, make absolute if needed
|
||||
if (selected_file[0] == '.' && selected_file[1] == '/') {
|
||||
char current_dir[512];
|
||||
if (getcwd(current_dir, sizeof(current_dir))) {
|
||||
char abs_path[1024];
|
||||
snprintf(abs_path, sizeof(abs_path), "%s/%s", current_dir, selected_file + 2);
|
||||
strncpy(selected_file, abs_path, buffer_size - 1);
|
||||
selected_file[buffer_size - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
fclose(temp_file);
|
||||
unlink(temp_filename);
|
||||
free(fm);
|
||||
return 0; // Success
|
||||
}
|
||||
fclose(temp_file);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up and indicate failure
|
||||
unlink(temp_filename);
|
||||
free(fm);
|
||||
return 1; // Fall back to manual entry
|
||||
}
|
||||
|
||||
void print_usage(const char* program_name) {
|
||||
printf("OTP Cipher - One Time Pad Implementation %s\n", get_version());
|
||||
printf("%s\n", get_build_info());
|
||||
|
||||
Reference in New Issue
Block a user