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

/*
 * This code is a sample implementation of the cryptographic method which is
 * known as "Vigenère cipher", further information can be found at wikipedia:
 * http://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher
 *
 * The names of most variables are way too long, you should shorten them a bit
 * so that the code is better readable(though the long names help to understand
 * it).
 *
 * Well, I also should remind you, that there are no tests of the key, so this
 * implementation might not be a clean one, which works fine with other ones,
 * but as I already said, this is just a sample to help beginners getting an
 * idea, what an implementation could look like. If you want to use it in a
 * productive way, you should write your own one and make sure it works with
 * other ones ;)
 *
 * Feel free to redistribute and modify this code, but do not remove nor modify
 * this comment, if you have changed something, so that this comment is not
 * right anymore, add a comment below, to tell others about that.
 * 
 * Thorsten 'Atsutane' Toepper
 * http://atsutane.freethoughts.de/
 * atsutane@freethoughts.de
 */

char *copyString(char *string)
{
    char *result = NULL;
    result = calloc(strlen(string)+1,sizeof(char));
    if (result == NULL)
    {
        return NULL;
    }
    memcpy(result, string, strlen(string));
    return result;
}

char *vigenereCrypt(char *string, char *key)
{
    char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
                        "0123456789";
    char *crypted = NULL;
    unsigned int stringPosition=0, keyPosition=0, s=0, k=0;
    const unsigned int alphabetLength = strlen(alphabet);

    crypted = copyString(string);

    for (s=0; s < strlen(string); s++)
    {
        if ((crypted[s] >= 'A' && crypted[s] <= 'Z') ||
            (crypted[s] >= 'a' && crypted[s] <= 'z') ||
            (crypted[s] >= '0' && crypted[s] <= '9'))
        {
            for (stringPosition=0; stringPosition < alphabetLength; stringPosition++)
            {
                if (crypted[s] == alphabet[stringPosition])
                {
                    break;
                }
            }
            for (keyPosition=0; keyPosition < alphabetLength; keyPosition++)
            {
                if (key[k] == alphabet[keyPosition])
                {
                    break;
                }
            }

            crypted[s] = alphabet[(stringPosition+keyPosition)%alphabetLength];

            k++;
            if (k == strlen(key))
            {
                k=0;
            }
        }
    }
    //Kill every value which may reveil any Information
    stringPosition=0;
    keyPosition=0;
    k=0;
    return crypted;
}

char *vigenereDecrypt(char *string, char *key)
{
    char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
                        "0123456789";
    char *decrypted = NULL;
    unsigned int stringPosition=0, keyPosition=0, s=0, k=0;
    const unsigned int alphabetLength = strlen(alphabet);
    int check=0;

    decrypted = copyString(string);

    for (s=0; s < strlen(string); s++)
    {
        if ((decrypted[s] >= 'A' && decrypted[s] <= 'Z') ||
            (decrypted[s] >= 'a' && decrypted[s] <= 'z') ||
            (decrypted[s] >= '0' && decrypted[s] <= '9'))
        {
            for (stringPosition=0; stringPosition < alphabetLength; stringPosition++)
            {
                if (decrypted[s] == alphabet[stringPosition])
                {
                    break;
                }
            }
            for (keyPosition=0; keyPosition < alphabetLength; keyPosition++)
            {
                if (key[k] == alphabet[keyPosition])
                {
                    break;
                }
            }

            check = stringPosition-keyPosition;
            if (check < 0)
            {
                decrypted[s] = alphabet[alphabetLength+check];
            }
            else
            {
                decrypted[s] = alphabet[check%alphabetLength];
            }

            k++;
            if (k == strlen(key))
            {
                k=0;
            }
        }
    }
    //Kill every value which may reveil any Information
    stringPosition=0;
    keyPosition=0;
    k=0;
    return decrypted;
}

int main(int argc, char **argv)
{
    if (argc == 2)
    {
        char *p = vigenereCrypt(argv[1], argv[1]);
        printf("Original:\t%s\nCrypted:\t%s\nDecrypted:\t%s\n",
                argv[1], p, vigenereDecrypt(p, argv[1]));
    }
    return 0;
}
