// BITE.EXE
// Simple Encryptor
// Oct2009
// Works in Windows!

#include<stdio.h>
#include<string.h>

// NOTE: sizeof -- size in BYTES

void resetbyte(char *binary){
 int i;
 for(i = 0; i < 8; i++){
  binary[i] = 48;
 }
 binary[i] = 0;
}

parse_bytestr(long int decimal, char *binary){
 decimal %= 256;
 resetbyte(binary);
 if(decimal >= 128){ decimal -= 128; binary[0] = '1'; }
 if(decimal >=  64){ decimal -=  64; binary[1] = '1'; }
 if(decimal >=  32){ decimal -=  32; binary[2] = '1'; }
 if(decimal >=  16){ decimal -=  16; binary[3] = '1'; }
 if(decimal >=   8){ decimal -=   8; binary[4] = '1'; }
 if(decimal >=   4){ decimal -=   4; binary[5] = '1'; }
 if(decimal >=   2){ decimal -=   2; binary[6] = '1'; }
 if(decimal >=   1){ decimal -=   1; binary[7] = '1'; }
 binary[8] = '\0';
}

int checkkey(char *flag, char *key){ // returns 0 when key is BAD
 int decimal = 0;
 if(strncmp(flag, "-key", 4)) fwrite("FLAG ERROR.\n", sizeof(char), 11, stderr);
 else if(strlen(key) > 1) fwrite("KEY TOO LONG; MUST BE ONE CHARACTER ONLY.\n", sizeof(char), 41, stderr);
 else decimal = key[0];
 return decimal;
}

int lastperiod(char *string){
 int index = -1;
 int i;
 for(i = 0; i < strlen(string); i++){
  if(string[i] == '.') index = i;
 }
 return index;
}

int checkfile(char *filename){
 int goodfile = 0;
 FILE *fp = fopen(filename, "r");
 if(fp == NULL) fwrite("File does not exist.\n", sizeof(char), 21, stderr);
 else{
  char c = getc(fp);
  if(c == EOF) fwrite("File empty.\n", sizeof(char), 12, stderr);
  else goodfile = 1;
  fclose(fp);
 }
 return goodfile;
}

int initbite(char *source, char *output, char *extension){ // checks length of source, creates name of output file
 if(strlen(source) > 506){ fwrite("DIRECTORY LENGTH EXCEEDS LIMIT.\n", sizeof(char), 32, stderr); return 0; } // NAME TOO LONG
 int period = lastperiod(source);
 if(period > 0){
  int i, j;
  for(i = 0; i < period; i++){ // period is not caught
   output[i] = source[i];
  }
  output[i] = '.';
  output[i + 1] = 'B';
  output[i + 2] = 'I';
  output[i + 3] = 'T';
  output[i + 4] = 'E';
  output[i + 5] = '\0';
  for(i, j = 0; i < strlen(source); i++, j++){ // i = period
   extension[j] = source[i];
  }
  extension[j] = '\n';
  extension[j + 1] = 0;
 }
 else{
  period = strlen(source);
  strcpy(output, source);
  output[period] = '.';
  output[period + 1] = 'B';
  output[period + 2] = 'I';
  output[period + 3] = 'T';
  output[period + 4] = 'E';
  output[period + 5] = '\0';
  extension[0] = '\n';
  extension[1] = 0;
 }
 return 1;
}

void bite(char *source, char *output, char *extension, char key){
 FILE *out = fopen(output, "wb");
 FILE *in = fopen(source, "r");
 char c, byte[9];
 resetbyte(byte);
 int i;
 for(i = 0; i < strlen(extension); i++){ // writes original extension information
  parse_bytestr(extension[i], byte);
  fwrite(byte, sizeof(char), 8, out); // good write
 }
 while(1){
  c = getc(in);
  if(c == EOF) break;
  else{
   // putchar('!');
   parse_bytestr(c + key, byte); // only the text contents has key offset
   fwrite(byte, sizeof(char), 8, out);
  }
 }
 fclose(out);
 fclose(in);
}

void showhelp(){
printf("\nbite.exe\nLow-level encryptor\nWORKS IN WINDOWS\n");
printf("Writes encrypted strings into an output file found in the same directory of the input file.\n");
printf("\n  arguments: [-key] [character] [directory]/[filename].[extension]\n\n");
printf("             -key        : optional flag sets encryption key \n");
printf("             character   : single character key, must come with \"-key\" flag \n");
printf("\noutput file: [directory]/[filename].BITE\n\n");
}

main(int argc, char *argv[]){ // FLAG ONE ONLY: -key [character]
/*
     Windows console has 300 lines.

     argv[0] = "./bite.exe"
     argv[argc] = "(null)"
     argv[argc - 1] = last word entered from console
*/
 char key = 0;
 if((argc == 1) || (argc == 3) || (argc > 4)){ showhelp(); return; }
 if(!strcmp(argv[1], "/?")){ showhelp(); return; }
 if(argc == 4){ if(!(key = checkkey(argv[1], argv[2]))) return; } // KEY WORKS!
 if(checkfile(argv[argc - 1])){ // CHECKS EXISTENCE
  char output[512], extension[256];
  if(initbite(argv[argc - 1], output, extension)){ // output string gets directory of input file, CHECKS LIMIT
   bite(argv[argc - 1], output, extension, key); // output and extension strings are caught
  }
 }
}