/*
encoder.cpp

	Programa que cifra una archivo mediante una frase (clave),
	misma que sirve para descifrarlo. Se usa XOR a nivel de bits.
	Esta es una manera sencilla de cifrar archivos, aunque es débil ante los ataques, pero puede ser mejorada.

	encoder <fuente> <destino> <"frase">

						Autor: Ariel Medina
*/

#include <iostream>
#include <fstream>
#include <cstring>

using namespace std;

bool encode(char *sourcefile,char *targetfile, char *phrase)
{
unsigned long fileSize;
unsigned char *buffer;
int blockSize=4096, phraseSize=strlen(phrase);

ifstream is(sourcefile,ios::binary | ios::in);
if(!is)
	{
	cout<<"No existe el archivo...";

	return false;
	}
is.seekg(0,ios::end);
fileSize=is.tellg();
is.seekg(0,ios::beg);
ofstream os(targetfile, ios::binary | ios::out);
if(!os)
	{
	cout<<"No existe el archivo...";

	return false;
	}

int i, j=0;
if(fileSize>blockSize)
	{
	do
		{

		buffer=new unsigned char [blockSize];
		is.read((char *)buffer,blockSize);
		for(i=0; i<blockSize; i++)
			{
			buffer[i]^=phrase[j];
			++j;
			if(j==phraseSize)
				j=0;
			}
		os.write((const char *) buffer,blockSize);
		delete [] buffer;
		fileSize-=blockSize;
		if(fileSize<blockSize)
			blockSize=fileSize;
		}while(fileSize);
	}
else
	{
	buffer=new unsigned char [fileSize];
	is.read((char *)buffer,fileSize);
	for(i=0; i<fileSize; i++)
		{
		buffer[i]^=phrase[j];
		++j;
		if(j==phraseSize)
			j=0;
		}
	os.write((const char *) buffer,fileSize);
	delete [] buffer;
	}

return true;
}

int main(int argc, char *argv[])
{
if(argc<2)
	cout<<"Intente de nuevo: encoder <archivo fuente> <archivo destino> <\"frase\">...";
else if(argc==2)
	cout<<"Falta el nombre del archivo destino y la frase...";
else if(argc==3)
	cout<<"Falta la frase...";
else if(argc==4)
	encode(argv[1],argv[2],argv[3]);
else
	cout<<"Demasiados parámetros...";

return 0;
}