Compare commits

...

2 Commits

Author SHA1 Message Date
e32eb8b2b1 Version v0.2.22 - Added text editor and file manager integration 2025-08-13 10:08:38 -04:00
0aecae0c5e test files 2025-08-12 19:08:14 -04:00
6 changed files with 318 additions and 15 deletions

View File

@@ -1,4 +1,7 @@
When building, use build.sh, not make.
Use it as follows: build.sh -m "useful comment on changes being made"
Use it as follows: build.sh -m "useful comment on changes being made"
When making TUI menus, try to use the first leter of the command and the key to press to execute that command. For example, if the command is "Open file" try to use a keypress of "o" upper or lower case to signal to open the file. Use this instead of number keyed menus when possible. In the command, the letter should be underlined that signifies the command.

319
otp.c
View File

@@ -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());

8
otp.code-workspace Normal file
View File

@@ -0,0 +1,8 @@
{
"folders": [
{
"path": "."
}
],
"settings": {}
}

Binary file not shown.

1
test_file.txt Normal file
View File

@@ -0,0 +1 @@
Hello, this is a test file for encryption!

BIN
test_file.txt.otp Normal file

Binary file not shown.