//============================================================================ // Name : xor.cpp // Author : bbertka@mss.icics.ubc.ca // Version : // Copyright : Written by Benjamin Bertka SID #23306103 // Description : Homework Problem 3, XOR Operations //============================================================================ #include #include #include #include using namespace std; /* * DATA data structure for keeping track of encoded/decoded * bytes from the input file * * data - the byte_ref array representing the file * size - the number of bytes in the file * key - the key string used to decode the file */ typedef unsigned int byte_ref; typedef struct DATA_ref { byte_ref *data; size_t size; const char *key; } DATA_ref; /** * Reads a file name to load the DATA structure with * @param *filename The file to load * @param *DATA The struct to fill */ int loadData(char *filename, struct DATA_ref *DATA) { FILE *file; char *buffer; size_t result; long numChars; //open the file for reading file = fopen(filename, "rb"); if(file == NULL){ printf("Unable to open %s for reading\n", filename); return EXIT_FAILURE; } //go to end of file to get number of chars fseek(file, 0, SEEK_END); numChars = ftell(file); rewind(file); //allocate memory for the DATA buffer = (char *)malloc(sizeof(char)*numChars); if(buffer == NULL){ printf("Could not allocate memory for %s\n", filename); fclose(file); return EXIT_FAILURE; } //check that the correct number of bytes are read result = fread(buffer, 1, numChars, file); if(result != (unsigned int)numChars){ printf("Incomplete loading of %s\n", filename); fclose(file); return EXIT_FAILURE; } fclose(file); //load the DATA with the file contents DATA->size = result; DATA->data = (byte_ref *) malloc( result* sizeof( byte_ref) ); for(unsigned int i = 0; i < DATA->size; ++i){ DATA->data[i] = buffer[i]; } return 0; } /** * Writes the encoded bytes to file * @param filename - The name of file to save * @param DATA - the filled struct holding encoded data */ int saveData(char *filename, struct DATA_ref *DATA) { FILE *file_ref; //open file for writing if((file_ref = fopen(filename, "w")) == NULL) { printf("Error opening %s for writing\n", filename); return -1; } //write to file one byte at a time char byte[1]; byte_ref *bitBuff = DATA->data; for(unsigned int i = 0; i < DATA->size; i++, bitBuff++){ byte[0] = (*bitBuff); fwrite(byte, 1, 1, file_ref); } fclose(file_ref); return 0; } /** * Iterate over the contents of the file, performing * the XOR operation using a data and key. * data = data^key * @param DATA the data to operate on */ int XOR(struct DATA_ref *DATA){ size_t keyLen = strlen(DATA->key); for(unsigned int i = 0; i < DATA->size; i++){ for(unsigned int k = 0; k < keyLen; k++ ){ DATA->data[i] ^= DATA->key[k]; i++; if(i == DATA->size){ break; } } } return 0; } /** * The main entry to the program. * * @param argv[1] The input file name * @param argv[2] the outputfile name */ int main(int argc, char** argv) { if(argc != 3){ printf("Error, bad number of arguments.\n"); printf("Usage:\n./XOR infile outfile\n"); return EXIT_FAILURE; } DATA_ref DATA; char keyBuff[256]; printf("Please input a maximum 256 byte key: \n"); if(cin.getline(keyBuff, 256) < 0){ printf("Error! Badly formatted key\n"); return EXIT_FAILURE; } if(strlen(keyBuff) > 0){ DATA.key = keyBuff; }else{ printf("Error! Key must have at least one byte!\n"); return EXIT_FAILURE; } //load data from file printf("Loading data from: %s\n", argv[1]); if(loadData(argv[1], &DATA) < 0){ return EXIT_FAILURE; } //perform XOR operation on DATA printf("Performing XOR operations\n"); XOR(&DATA); //save data to file printf("Saving data to: %s\n", argv[2]); if(saveData(argv[2], &DATA) < 0){ return EXIT_FAILURE; } return EXIT_SUCCESS; }