/* 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 #include "term.h" #include "types.h" #include "ctypes.h" railfence::railfence(){ *cipher = (char) NULL; period=0; maxraillen=0; length = 0; keylen = 0; clen = NULL; block = NULL; period_set = FALSE; } int railfence::execute_option(char option){ int valid = TRUE; switch(option){ case MOVE: move_stuff(); break; case CHANGEPERIOD: change_rails(); break; default: valid = base_exec_option(option); break; } return valid; } int railfence::period_valid(){ return (period >= 3)?TRUE:FALSE; } void railfence::setup_key(){ keylen = period*2-2; key.init(period*2); set_key(1); } void railfence::change_rails(){ period_set = FALSE; set_period(); init_cipher(); clear_to_prompt(); } void railfence::init_cipher(){ int i; length = strlen(cipher); if(clen != NULL) delete[] clen; if(block != NULL){ for(i = 0; i < keylen; i++) delete block[i]; delete[] block; } /* Allocate the block */ maxraillen = (length%keylen == 0)?length/keylen:length/keylen + 1; clen = new int[keylen]; block = new char *[keylen]; for(i = 0; i < keylen; i++) block[i] = new char[maxraillen]; /* Initilize the column lengths */ for(i = 0; i < keylen; i++){ if(keylen*(maxraillen-1) + i < length) clen[i] = maxraillen; else clen[i] = maxraillen-1; } /* Now fill in the block. */ fill_block(); } void railfence::set_key(int startpos){ static int *cycle; int i; if(cycle != NULL) delete[] cycle; cycle = new int[keylen+1]; /* Set the cycle. The key will be a cyclic permutation of the cycle. */ for(i = 0; i < period; i++) cycle[i] = i; for(i = period; i > 1; i--) cycle[period + period - i] = i; /* Now set the key. */ for(i = 1; i <= keylen; i++){ key.alter((char) cycle[(startpos+i-2)%keylen+1]+'0', i-1); } } void railfence::fill_block(){ int i, maxlen, position; int *cptr, *tptr; char *cipherptr = cipher; /* Loop through each rail */ for(i = 1; i <= period; i++){ /* Find out which columns are associated with that rail */ cptr = find_columns(i); maxlen = 0; /* Find the length of the longest column */ for(tptr = cptr; *tptr >= 0; tptr++){ if(clen[*tptr] > maxlen) maxlen = clen[*tptr]; } /* Loop through each column and fill it */ position = 0; while(position < maxlen){ for(tptr = cptr; *tptr >= 0; tptr++){ if(position < clen[*tptr]){ block[*tptr][position] = *cipherptr; cipherptr++; } } position++; } } } int *railfence::find_columns(int index){ int i, position=0; static int *list; if(list != NULL) delete[] list; list = new int[keylen+1]; /* We are assuming that there is a variable (int *)key that has ** a list of non-negative integers. There is also a variable ** (int)keylen that gives the number of elements in key. */ for(i = 0; i < keylen; i++){ if(key.intval(i) == index){ list[position++] = i; } } list[position] = -1; return list; } void railfence::show_menu(){ menu(1, "(M)ove stuff (C)hange number of rails (W)rite (Q)uit"); } void railfence::show_cipher(){ int i, j, row, column; for(i = 0; i < keylen; i++){ row = key.intval(i); for(j = 0; j < clen[i]; j++){ column = i+keylen*j; put_char(block[i][j], column, row); } } } void railfence::show_key(){ int i; clear_to_prompt(); for(i = 0; i < keylen; i++) put_char(key.intval(i)+'0', i*2+5, period+5); } void railfence::move_stuff(){ move_startpos(); }; void redefence::move_stuff(){ char option; prompt("Move (R)ails or the (S)tarting position? "); option = get_char(); if(option == 'r') interchange_rails(); else if(option == 's') move_startpos(); else msgerror("Bad choice."); } void railfence::move_startpos(){ char temp_str[STRINGLENGTH], dir; int startpos, valid = FALSE; /* All we do here is move to a new starting position. */ prompt("What is the new starting rail? "); read_line(temp_str); if(sscanf(temp_str, "%d", &startpos) != 1) msgerror("Bad input."); else if(startpos > period || startpos < 1) msgerror("Bad starting position."); else{ if(startpos != 1 && startpos != period){ prompt("Start going (U)pwards or (D)ownwards? "); dir = get_char(); if(dir == 'u'){ valid = TRUE; startpos = keylen-startpos+2; } else if(dir != 'd') msgerror("Bad input."); else valid = TRUE; } else valid = TRUE; } if(valid){ set_key(startpos); fill_block(); } } void railfence::decipher(char *string){ int i, j; for(i = 0; i < maxraillen; i++){ for(j = 0; j < keylen; j++){ if(i < clen[j]) *string++ = block[j][i]; } } *string = (char) NULL; } void redefence::interchange_rails(){ char temp_str[STRINGLENGTH]; int rail1, rail2, i; prompt("Interchange which two rails/rows? (ex: 1,2) "); read_line(temp_str); if(sscanf(temp_str, "%d,%d", &rail1, &rail2) != 2); else if(rail1 <= period && rail2 <= period && rail1 > 0 && rail2 > 0){ for(i = 0; i < keylen; i++){ if(key.intval(i) == rail1) key.alter(rail2+'0', i); else if(key.intval(i) == rail2) key.alter(rail1+'0', i); } fill_block(); } else{ msgerror("Bad rail number."); } }