// UNBITE.EXE
// Simple Decryptor for BITE.EXE
// Oct2009
// Works in Windows!

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

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

parse_charstr(int *decimal, char *binary){ // read successions of 1s and 0s
 long int output = 0;
 if(binary[0] == '1') output += 128;
 if(binary[1] == '1') output +=  64;
 if(binary[2] == '1') output +=  32;
 if(binary[3] == '1') output +=  16;
 if(binary[4] == '1') output +=   8;
 if(binary[5] == '1') output +=   4;
 if(binary[6] == '1') output +=   2;
 if(binary[7] == '1') output +=   1;
 *decimal = output;
}

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

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 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 checkextension(char *source){
 int periodindex = lastperiod(source);
 if(periodindex == -1){ fwrite("INPUT FILE IS NOT A .BITE FILE.\n", sizeof(char), 31, stderr); return 0; }
 else{
  char sample[6]; sample[5] = '\0';
  int i;
  for(i = 0; i < 5; i++){
   sample[i] = toupper(source[periodindex + i]);
   if(sample[i] == '\0') break;
  }
  if(strncmp(sample, ".BITE", 5)){ fwrite("INPUT FILE IS NOT A .BITE FILE.\n", sizeof(char), 31, stderr); return 0; }
 }
 return 1;
}

int initunbite(char *source, char * output, char *extension, FILE *in){ // creates output ile
 if(!checkextension(source)) return 0;
 else if(strlen(source) > 478){ fwrite("DIRECTORY LENGTH EXCEEDS LIMIT.\n", sizeof(char), 32, stderr); return 0; }
 // what kind of file has a 32-character extension?!
 char byte[9]; byte[8] = 0;
 int decimal = 0, i = 0;
 while(!feof(in)){
  fread(byte, sizeof(char), 8, in);
  parse_charstr(&decimal, byte);
  if(decimal == '\n') break;
  extension[i] = decimal;
  i++;
  if(i == 32){ fwrite("EXTENSION LENGTH EXCEEDS LIMIT.\n", sizeof(char), 32, stderr); return 0; }
 }
 extension[i] = 0; // set null character
 int periodindex = lastperiod(source);
 strncpy(output, source, periodindex);
 output[periodindex] = 0; // set null character
 strcat(output, extension);
 return 1;
}

void unbite(char *source, char *output, char key, FILE *in){
 char binary[9];
 int decimal = 0;
 FILE *out = fopen(output, "w"); // block write or a text file
 while(!feof(in)){
  resetbyte(binary);
  fread(binary, sizeof(char), 8, in);
  parse_charstr(&decimal, binary);
  decimal += (256 - key); // if you don't have a key and the .BITE file requires one, you have 255 choices
  decimal %= 256;
  fputc(decimal, out);
  char c = getc(in);
  if(c == EOF) break;
  else ungetc(c, in);
 }
 fclose(in);
 fclose(out);
 printf("output to file: \"%s\"\n", output);
}

void showhelp(){
printf("\nunbite.exe\nDecryptor for bite.exe\nWORKS IN WINDOWS\n");
printf("Writes decrypted strings into an output file found in the same directory of the input file.\n");
printf("\n  arguments: [-key] [character] [directory]/[filename].BITE\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].[extension]\n");
printf("             filename    : output of the same file name, but different extension");
printf("             extension   : already encoded in the input file\n");
}

main(int argc, char *argv[]){
 char key = 0;
 if((argc == 1) || (argc == 3) || (argc > 4)){ showhelp(); return; }
 //if(argc != 2) 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];
  FILE *in = fopen(argv[argc - 1], "rb");
  if(initunbite(argv[argc - 1], output, extension, in)){ // output string gets directory of encrypted file, CHECKS LIMIT
   // printf("%s, \n%s, \n%s, \n", argv[argc - 1], output, extension);
   unbite(argv[argc - 1], output, key, in); // output and extension strings are caught
  }
 }
}