/* This is one of the cipher files for the cipher interface written ** by wart@ugcs.caltech.edu ** ** Please don't steal my code without my permission. ** */ #include #include #include #include "term.h" #include "types.h" #include "ctypes.h" autokey_base::autokey_base(){ period = 0; period_set = FALSE; length = 0; } int autokey_base::execute_option(char option){ int valid = TRUE; switch(option){ case CHANGEPERIOD: change_period(); break; case SUBSTITUTE: substitute(); break; case UNDO: undo(); break; case ALPHFIT: alphfit(); break; default: valid = base_exec_option(option); break; } return valid; } void autokey_base::change_period(){ period_set = FALSE; set_period(); clear_to_prompt(); } void autokey_base::setup_key(){ key.init(period); } void autokey_base::substitute(){ int column; char tmp_str[STRINGLENGTH]; char ct_letter, pt_letter; prompt("What column is the letter in? "); read_line(tmp_str); if(sscanf(tmp_str, "%d", &column) != 1) msgerror("Bad input."); else if(column < 1 || column > period) msgerror("Bad position."); else{ prompt("What is the new letter? (ct,pt) "); read_line(tmp_str); if(sscanf(tmp_str, "%c,%c", &ct_letter, &pt_letter) != 2){ msgerror("Bad format."); } else if(!isalpha(ct_letter) || !isalpha(pt_letter)){ msgerror("Bad letter."); } else{ sub_letter(ct_letter | ' ', pt_letter | ' ', column-1); } } } void autokey_base::alphfit(){ char tmp_str[STRINGLENGTH]; int column; prompt("Fit which column? (* for all) "); read_line(tmp_str); if(*tmp_str == '*'){ /* for(i = 0; i < period; i++){ fit_column(i); } */ fit_all_columns(); } else if(sscanf(tmp_str, "%d", &column) != 1){ msgerror("Bad column."); } else if(column < 1 || column > period){ msgerror("Column out of range."); } else{ fit_column(column-1); } } void autokey_base::fit_all_columns(){ int value, maxval=0, bestval, k, column, totalval; char i, j, temp_str[STRINGLENGTH]; Key maxkey, bestkey; key.clearkey(); key.duplicate(&maxkey); key.duplicate(&bestkey); for(i = 'a', bestval=0; i <= 'z'; i++){ key.clearkey(); key.alter(i, 0); key.duplicate(&maxkey); for(column = 1, totalval=0; column < period; column++){ maxkey.duplicate(&key); for(j='a', maxval=0; j <= 'z'; j++){ key.alter(j, column); decipher(temp_str); for(k = 0, value=0; k < length-1; k++){ value += get_digram_value(temp_str[k],temp_str[k+1]); } if(value > maxval){ maxval = value; key.duplicate(&maxkey); } } } if(maxval > bestval){ bestval = maxval; maxkey.duplicate(&bestkey); } } bestkey.duplicate(&key); } void autokey_base::undo(){ int column, i; prompt("Which column? (* for all) "); column = get_char(); if(column == '*'){ for(i = 0; i < period; i++) key.clearkey(i); } else{ column -= '1'; key.clearkey(column); } } void autokey_base::show_menu(){ menu(2, "Options: (S)ubstitute (A)pply fit (U)ndo (C)hange period"); menu(1, " (W)rite (Q)uit"); } void autokey_base::show_cipher(){ int i, line_length; char tmp_str[STRINGLENGTH]; char ocipher[STRINGLENGTH]; line_length = COLS / (period+1); i = 0; while(i < length){ strncpy(tmp_str, cipher+i, period); tmp_str[period] = (char) NULL; msgprint((i*(period+1)/period)%(line_length*(period+1)), (i/(line_length*period))*3 + 1, tmp_str); i+= period; } i = 0; decipher(ocipher); while(i < length){ strncpy(tmp_str, ocipher+i, period); tmp_str[period] = (char) NULL; msgprint((i*(period+1)/period)%(line_length*(period+1)), (i/(line_length*period))*3 + 0, tmp_str); i += period; } } void autokey_base::show_key(){ int i; for(i = 0; i < period; i++){ if(key.val(i) != BLANK){ msgprint(3*i+4, 15, "%2d", key.val(i) - 'a'); put_char(key.val(i), 3*i + 5, 16); } else{ msgprint(3*i+4, 15, " ."); put_char(BLANK, 3*i + 5, 16); } } } void autokey_base::sub_letter(char ct_letter, char pt_letter, int column){ char key_letter; key_letter = get_key_letter(ct_letter, pt_letter); if(key_letter){ key.alter(key_letter, column); } } void autokey_base::fit_column(int column){ int i, k, fweights[26]; char prev_pt = (char) NULL, maxkey = (char) NULL; static int weights[] = { 1863, 954, 1477, 1644, 2114, 1447, 1204, 1544, 1869, 301, 477, 1544, 1398, 1892, 1869, 1431, 477, 1887, 1799, 1969, 1431, 1114, 1204, 699, 1279, 0}; int maxweight=0; for(i = 0; i < 26; i++) fweights[i] = 0; /* Rotate through the 26 possible keys */ for(k = 0; k < 26; k++){ prev_pt = k + 'a'; /* Rotate each letter in the column */ for(i = column; i < length; i+=period){ fweights[k] += weights[get_pt(cipher[i], prev_pt) - 'a']; prev_pt = get_pt(cipher[i], prev_pt); } if(maxweight < fweights[k]){ maxweight = fweights[k]; maxkey = (char) k + 'a'; } } key.alter(maxkey, column); } void autokey_base::decipher(char *string){ int i=0; char ct_letter, key_letter; for(i = 0; i < length; i++){ if(key.val(i%period) != BLANK){ ct_letter = cipher[i]; key_letter = (i