/* Demonstration of how to implement a 30 day limited trial application
 *
 * (c) 2007 by Lazarus Internet Development
 * Written by Clay Dowling <clay@lazarusid.com>
 *
 * $Id: 30-day-demo.c 16 2005-08-17 23:30:15Z  $
 */

#include <windows.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include "registration.h"
#include "serial.h"
#include "config.h"
#include "regsanity.h"
#include "md5.h"

#define ONEDAY 86400
#define TRIALDAYS 30

const char *CONFIGFILE = "trialreg.conf";
const char *SECRET = "30 Day Trial";

const char* getmd5(const char*);

void getregistration();
void checkregistration();

/* Make these global because all portions of the app need to know about this */
int g_trialdays = -1;
int g_valid = 0;

int main(int argc, char** argv)
{
    const char* regmd5 = NULL;
    g_trialdays = TRIALDAYS + 1;

    regmd5 = getmd5("registration.dll");
    if (strcmp(regmd5, REGISTRATION_MD5) != 0)
    {
        fputs("Registration DLL failed sanity check.\n", stderr);
        fprintf(stderr, "Actual MD5: %s\nTarget MD5: %s\n", regmd5, REGISTRATION_MD5);
        return EXIT_FAILURE;
    }

    checkregistration();

    if (g_trialdays >= 0 && g_trialdays <= TRIALDAYS)
        printf("You have %d days remaining in this trial.\n", g_trialdays);
    if (g_trialdays < 0)
        printf("This trial copy has expired.\n");
    if (g_valid)
        puts("This copy is valid.");
    else
        puts("*** INVALID COPY ***");

    return EXIT_SUCCESS;
}


const char* getmd5(const char* filename)
{

    FILE* in;
    char* buffer;
    md5_state_t pms;
    md5_byte_t digest[16];
    static char key[33];
    int i;
    struct stat sb;
    char *pos;

    if (stat(filename, &sb))
    {
        perror(filename);
        return NULL;
    }

    buffer = (char*)calloc(1, sb.st_size + 1);
    memset(key, 0, 33);
    in = fopen(filename, "rb");
    fread((void*)buffer, 1, sb.st_size, in);
    fclose(in);

    md5_init(&pms);
    md5_append(&pms, (const md5_byte_t *)buffer, sb.st_size);
    md5_finish(&pms, digest);

    pos = key;
    for (i=0; i < 16; ++i)
    {
        sprintf(pos, "%2.2x", digest[i]);
        pos += 2;
    }

    return key;

}

void cleanstring(char* victim)
{
    char *work;
    int i=0;
    int j=0;

    if (victim == NULL) return;

    work = (char*)calloc(1, strlen(victim) + 1);
    for (i=0; victim[i]; ++i)
        if (!isspace(victim[i]))
            work[j++] = victim[i];

    for (i=0; work[i]; ++i)
        victim[i] = work[i];
    victim[i] = 0;
}

void getregistration()
{
    char serial[33];
    char key[33];
    FILE *cfile;

    memset(serial, 0, 33);
    memset(key, 0, 33);
    printf("Enter serial number (ENTER for 30 day trial): ");
    fgets(serial, 33, stdin);
    cleanstring(serial);

    if (serial[0] != 0)
    {
        printf("Enter registration key: ");
        fgets(key, 33, stdin);
        cleanstring(key);
    }
    else
    {
        serial_t ser;
        char* regkey;
        time_t now;
        int backdate = 0;

        printf("Days to backdate the installation: ");
        scanf("%d", &backdate);

        ser = serial_create(2);
        now = time(0);

        serial_set_int(ser, 0, 0); /* Customer ID of 0 indicates a trial */
        serial_set_date(ser, 1, now - (backdate * ONEDAY)); /* Date application was first run */

        strncpy(serial, serial_encode(ser), 32);
        regkey = gen_key(serial, SECRET);
        strncpy(key, key_as_string(regkey), 32);
        free(regkey);

    }

    cfile = fopen(CONFIGFILE, "w");
    if (!cfile)
    {
        perror(CONFIGFILE);
        return;
    }

    fprintf(cfile, "serial = %s\n", serial);
    fprintf(cfile, "key = %s\n", key);
    fclose(cfile);

    return;
}

void checkregistration()
{
    FILE* cfile;
    serial_t ser;

    cfile = fopen(CONFIGFILE, "r");
    if (cfile)
    {
        config_t config;
        char* regkey = NULL;
        char* regserial = NULL;

        config = config_read(cfile);
        fclose(cfile);

        regserial = config_get_string(config, "serial");
        regkey = config_get_string(config, "key");
        ser = serial_decode(regserial);

        if (regserial && regkey && isregistered(regserial, regkey, SECRET))
            g_valid = 1;

        /* This is a trial version.  Check g_valid to ensure that somebody hasn't been
         * manually updating the registration file
         */
        if (serial_get_int(ser, 0) == 0 && g_valid == 1)
        {
            time_t now;
            time_t regdate;

            now = time(0);
            regdate = serial_get_date(ser, 1);

            g_trialdays = TRIALDAYS - ((now - regdate) / ONEDAY);
            if (g_trialdays < 0)
                g_valid = 0;
        }

        config_destroy(config);
        serial_destroy(ser);
    }
    else
        getregistration();

}

