diff --git a/otp.c b/otp.c index 93f8778..8fdfc20 100644 --- a/otp.c +++ b/otp.c @@ -58,6 +58,9 @@ static char current_pads_dir[512] = DEFAULT_PADS_DIR; // Global variable for default pad path from preferences static char default_pad_path[1024] = ""; +// Global variable for pipe mode detection +static int is_pipe_mode = 0; + // Function prototypes int main(int argc, char* argv[]); int interactive_mode(void); @@ -89,7 +92,6 @@ int launch_file_manager(const char* start_directory, char* selected_file, size_t int generate_pad(uint64_t size_bytes, int show_progress); int encrypt_text(const char* pad_identifier, const char* input_text); int decrypt_text(const char* pad_identifier, const char* encrypted_message); -int decrypt_text_silent(const char* pad_identifier, const char* encrypted_message); int encrypt_file(const char* pad_identifier, const char* input_file, const char* output_file, int ascii_armor); int decrypt_file(const char* input_file, const char* output_file); int decrypt_binary_file(FILE* input_fp, const char* output_file); @@ -197,18 +199,18 @@ int main(int argc, char* argv[]) { // Load preferences first load_preferences(); - // Check for piped input first (before any output) - int is_pipe_mode = (argc == 1 && has_stdin_data()); + // Check for all forms of piped input first (before any output) + is_pipe_mode = (argc == 1 && has_stdin_data()) || has_stdin_data(); // Check for decrypt command with piped input - int is_decrypt_pipe = (argc == 2 && - (strcmp(argv[1], "decrypt") == 0 || strcmp(argv[1], "-d") == 0) && + int is_decrypt_pipe = (argc == 2 && + (strcmp(argv[1], "decrypt") == 0 || strcmp(argv[1], "-d") == 0) && has_stdin_data()); // Check for OTP thumb drive on startup char otp_drive_path[512]; if (detect_otp_thumb_drive(otp_drive_path, sizeof(otp_drive_path))) { - // Only show messages in interactive/command mode, not pipe mode + // Only show messages in non-pipe mode if (!is_pipe_mode && !is_decrypt_pipe) { printf("Detected OTP thumb drive: %s\n", otp_drive_path); printf("Using as default pads directory for this session.\n\n"); @@ -218,12 +220,23 @@ int main(int argc, char* argv[]) { } if (is_pipe_mode) { - // No arguments but has piped data - enter pipe mode - char* piped_text = read_stdin_text(); - if (piped_text) { - int result = pipe_mode(argc, argv, piped_text); - free(piped_text); - return result; + // Check if this is a decrypt command with piped input + if (argc == 2 && (strcmp(argv[1], "decrypt") == 0 || strcmp(argv[1], "-d") == 0)) { + // Piped decrypt mode - read stdin and decrypt silently + char* piped_message = read_stdin_text(); + if (piped_message) { + int result = decrypt_text(NULL, piped_message); + free(piped_message); + return result; + } + } else { + // Regular pipe mode for encryption + char* piped_text = read_stdin_text(); + if (piped_text) { + int result = pipe_mode(argc, argv, piped_text); + free(piped_text); + return result; + } } // If reading stdin failed, fall back to interactive mode return interactive_mode(); @@ -244,8 +257,8 @@ int main(int argc, char* argv[]) { int command_line_mode(int argc, char* argv[]) { // Check for help flags first - if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--h") == 0 || - strcmp(argv[1], "-help") == 0 || strcmp(argv[1], "--help") == 0 || + if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--h") == 0 || + strcmp(argv[1], "-help") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "help") == 0) { print_usage(argv[0]); return 0; @@ -334,7 +347,7 @@ int command_line_mode(int argc, char* argv[]) { // Piped decrypt mode - read stdin and decrypt silently char* piped_message = read_stdin_text(); if (piped_message) { - int result = decrypt_text_silent(NULL, piped_message); + int result = decrypt_text(NULL, piped_message); free(piped_message); return result; } @@ -346,7 +359,7 @@ int command_line_mode(int argc, char* argv[]) { // Check if the argument looks like an encrypted message (starts with -----) if (strncmp(argv[2], "-----BEGIN OTP MESSAGE-----", 27) == 0) { // Inline decrypt with message only - use silent mode for command line - return decrypt_text_silent(NULL, argv[2]); + return decrypt_text(NULL, argv[2]); } else { // Check if it's a file (contains . or ends with known extensions) if (strstr(argv[2], ".") != NULL) { @@ -366,7 +379,7 @@ int command_line_mode(int argc, char* argv[]) { } else { // Legacy format: pad_chksum and message, or file with output // Use silent mode for command line when message is provided - return decrypt_text_silent(argv[2], argv[3]); + return decrypt_text(argv[2], argv[3]); } } else if (argc == 5 && strcmp(argv[3], "-o") == 0) { @@ -467,7 +480,7 @@ int interactive_mode(void) { void show_main_menu(void) { - printf("\n=========================== Main Menu - OTP v0.2.106 ===========================\n\n"); + printf("\n=========================== Main Menu - OTP v0.2.107 ===========================\n\n"); printf(" \033[4mT\033[0mext encrypt\n"); //TEXT ENCRYPT printf(" \033[4mF\033[0mile encrypt\n"); //FILE ENCRYPT @@ -1311,23 +1324,29 @@ 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("\nText input options:\n"); - printf(" 1. Type text directly\n"); - printf(" 2. Use text editor\n"); - printf("Enter choice (1-2): "); - - char input_choice[10]; - if (!fgets(input_choice, sizeof(input_choice), stdin)) { - printf("Error: Failed to read input\n"); - free(pad_chksum); - return 1; + if (!is_pipe_mode) { + printf("\nText input options:\n"); + printf(" 1. Type text directly\n"); + printf(" 2. Use text editor\n"); + printf("Enter choice (1-2): "); } - if (atoi(input_choice) == 2) { + char input_choice[10] = "1"; // Default to direct input in pipe mode + if (!is_pipe_mode) { + if (!fgets(input_choice, sizeof(input_choice), stdin)) { + printf("Error: Failed to read input\n"); + free(pad_chksum); + return 1; + } + } + + if (!is_pipe_mode && 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: "); + if (!is_pipe_mode) { + printf("Falling back to direct text input.\n"); + printf("Enter text to encrypt: "); + } fflush(stdout); if (fgets(text_buffer, sizeof(text_buffer), stdin) == NULL) { @@ -1344,8 +1363,10 @@ int encrypt_text(const char* pad_identifier, const char* input_text) { } } else { // Direct text input - printf("Enter text to encrypt: "); - fflush(stdout); + if (!is_pipe_mode) { + printf("Enter text to encrypt: "); + fflush(stdout); + } if (fgets(text_buffer, sizeof(text_buffer), stdin) == NULL) { printf("Error: Failed to read input\n"); @@ -1453,16 +1474,12 @@ int encrypt_text(const char* pad_identifier, const char* input_text) { } int decrypt_text(const char* pad_identifier, const char* encrypted_message) { - // Use universal decrypt function with interactive mode + // Use universal decrypt function with mode based on global pipe detection (void)pad_identifier; // Suppress unused parameter warning - chksum comes from message - return universal_decrypt(encrypted_message, NULL, DECRYPT_MODE_INTERACTIVE); + decrypt_mode_t mode = is_pipe_mode ? DECRYPT_MODE_SILENT : DECRYPT_MODE_INTERACTIVE; + return universal_decrypt(encrypted_message, NULL, mode); } -int decrypt_text_silent(const char* pad_identifier, const char* encrypted_message) { - // Use universal decrypt function with silent mode - (void)pad_identifier; // Suppress unused parameter warning - chksum comes from message - return universal_decrypt(encrypted_message, NULL, DECRYPT_MODE_SILENT); -} int encrypt_file(const char* pad_identifier, const char* input_file, const char* output_file, int ascii_armor) { char* pad_chksum = find_pad_by_prefix(pad_identifier); @@ -2956,8 +2973,8 @@ int load_pad_data(const char* pad_chksum, uint64_t offset, size_t length, unsign return 1; // Error: null pointer } - char pad_path[MAX_HASH_LENGTH + 20]; - char state_path[MAX_HASH_LENGTH + 20]; + char pad_path[1024]; + char state_path[1024]; get_pad_path(pad_chksum, pad_path, state_path); // Check if pad file exists @@ -3036,7 +3053,7 @@ int generate_ascii_armor(const char* chksum, uint64_t offset, const unsigned cha strcpy(*ascii_output, "-----BEGIN OTP MESSAGE-----\n"); char temp_line[256]; - snprintf(temp_line, sizeof(temp_line), "Version: v0.2.106\n"); + snprintf(temp_line, sizeof(temp_line), "Version: v0.2.107\n"); strcat(*ascii_output, temp_line); snprintf(temp_line, sizeof(temp_line), "Pad-ChkSum: %s\n", chksum); @@ -3292,17 +3309,28 @@ int universal_decrypt(const char* input_data, const char* output_target, decrypt printf("Note: ASCII format does not preserve original filename/permissions\n"); } } else { - // Text output to stdout - ciphertext[ciphertext_len] = '\0'; + // Text output to stdout - need to allocate space for null terminator + char* decrypted_text = malloc(ciphertext_len + 1); + if (!decrypted_text) { + printf("Error: Memory allocation failed for output\n"); + free(ciphertext); + free(pad_data); + return 1; + } + + memcpy(decrypted_text, ciphertext, ciphertext_len); + decrypted_text[ciphertext_len] = '\0'; if (mode == DECRYPT_MODE_SILENT) { // Silent mode - just output the text - printf("%s\n", (char*)ciphertext); + printf("%s\n", decrypted_text); fflush(stdout); } else { // Interactive mode - with label - printf("Decrypted: %s\n", (char*)ciphertext); + printf("Decrypted: %s\n", decrypted_text); } + + free(decrypted_text); } // Cleanup @@ -3788,8 +3816,6 @@ int handle_file_encrypt(void) { //////////////////////////////////////////////////////////////////////////////// - - int calculate_checksum(const char* filename, char* checksum_hex) { FILE* file = fopen(filename, "rb"); if (!file) { @@ -3841,8 +3867,6 @@ int calculate_checksum(const char* filename, char* checksum_hex) { return 0; } - - // Unified pad selection function - extracts the best UI from handle_pads_menu() char* select_pad_interactive(const char* title, const char* prompt, pad_filter_type_t filter_type, int allow_cancel) { // Get list of pads from current directory @@ -4586,7 +4610,7 @@ int handle_add_entropy_to_pad(const char* pad_chksum) { } void print_usage(const char* program_name) { - printf("OTP Cipher - One Time Pad Implementation v0.2.106\n"); + printf("OTP Cipher - One Time Pad Implementation v0.2.107\n"); printf("Built for testing entropy system\n"); printf("Usage:\n"); printf(" %s - Interactive mode\n", program_name); diff --git a/test_encrypted.txt b/test_encrypted.txt new file mode 100644 index 0000000..9c2a231 --- /dev/null +++ b/test_encrypted.txt @@ -0,0 +1,8 @@ +-----BEGIN OTP MESSAGE----- +Version: v0.2.107 +Pad-ChkSum: d0aaeb745bfbc62b1ed8c0eca4f8dc016f4fd9ed49130979f2bb25a2a3c8192e +Pad-Offset: 1786 + +rRK8UkPc0t5bybg= +-----END OTP MESSAGE----- +