/**
 * BNCSutil
 * Battle.Net Utility Library
 *
 * Copyright (C) 2004-2006 Eric Naeseth
 *
 * CD-Key Decoder Interface
 * September 29, 2004
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * A copy of the GNU Lesser General Public License is included in the BNCSutil
 * distribution in the file COPYING.  If you did not receive this copy,
 * write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA
 */

#ifndef BNCSUTIL_CDKEYDECODER_H
#define BNCSUTIL_CDKEYDECODER_H

#include <bncsutil/mutil.h>

/**
 * Internal key type constants.
 */
#define KEY_STARCRAFT   1
#define KEY_DIABLO2     2
#define KEY_WARCRAFT2   2 /* [sic] */
#define KEY_WARCRAFT3   3

MCEXP(CDKeyDecoder) {
protected:
    char* cdkey;
    int initialized;
    int keyOK;
    size_t keyLen;
    char* keyHash;
    size_t hashLen;
    int keyType;
    unsigned long value1;
    unsigned long value2;
    unsigned long product;
    char* w3value2;

    int processStarCraftKey();
    int processWarCraft2Key();
    int processWarCraft3Key();

    void decodeKeyTable(int* keyTable);

    inline char getHexValue(int v);
    inline int getNumValue(char v);

    inline void mult(int r, int x, int* a, int dcByte);

public:
    /**
     * Creates a new CD-key decoder object.
     * Not really useful unless subclassed.
     */
    CDKeyDecoder();

    CDKeyDecoder(const char* cd_key);

    /**
     * Creates a new CD-key decoder object, using the specified key.
     * keyLength should be the length of the key, NOT INCLUDING the
     * null-terminator.  Applications should use isKeyValid after using
     * this constructor to check the validity of the provided key.
     */
    CDKeyDecoder(const char* cdKey, size_t keyLength);

    virtual ~CDKeyDecoder();

    int isKeyValid();
    int getVal2Length();
    uint32_t getProduct();
    uint32_t getVal1();
    uint32_t getVal2();
    int getLongVal2(char* out);

    /**
     * Calculates the CD-Key hash for use in SID_AUTH_CHECK (0x51)
     * Returns the length of the generated hash; call getHash and pass
     * it a character array that is at least this size.  Returns 0 on failure.
     *
     * Note that clientToken and serverToken will be added to the buffer and
     * hashed as-is, regardless of system endianness.  It is assumed that
     * the program's extraction of the server token does not change its
     * endianness, and since the client token is generated by the client,
     * endianness is not a factor.
     */
    size_t calculateHash(uint32_t clientToken, uint32_t serverToken);

    /**
     * Places the calculated CD-key hash in outputBuffer.  You must call
     * calculateHash before getHash.  Returns the length of the hash
     * that was copied to outputBuffer, or 0 on failure.  The hash is
     * not deleted after getHash is run; subsequent calls to getHash
     * will still function.
     */
    size_t getHash(char* outputBuffer);
};

#endif /* BNCSUTIL_CDKEYDECODER_H */
