#include "stdafx.h"
#pragma hdrstop
/*

  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.

  See the accompanying file LICENSE, version 2007-Mar-4 or later
  (the contents of which are also included in zip.h) for terms of use.
  If, for some reason, all these files are missing, the Info-ZIP license
  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html

  parts Copyright (C) 1997 Mike White, Eric W. Engler
************************************************************************
 Copyright (C) 2009, 2010  by Russell J. Peters, Roger Aelbrecht

   This file is part of TZipMaster Version 1.9.

    TZipMaster 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 3 of the License, or
    (at your option) any later version.

    TZipMaster 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.

    You should have received a copy of the GNU Lesser General Public License
    along with TZipMaster.  If not, see <http://www.gnu.org/licenses/>.

    contact: problems@delphizip.org (include ZipMaster in the subject).
    updates: http://www.delphizip.org
    DelphiZip maillist subscribe at http://www.freelists.org/list/delphizip 
************************************************************************/
#include "ZipDflt.h"
#include "crypt.h"

#include <stdlib.h>
#include <process.h>                /* For prototype of getpid()      */
#include "dz_errs.h"

#undef _DZ_FILE_
#define _DZ_FILE_ DZ_ZCRYPT_CPP

#define ZCR_SEED2 getpid()          /* RCV Added; see note in Crypt.c */

#define zencode(c, t, k)  (t = decrypt_byte(k), update_keys(c, k), t^(c))

// Write encryption header to file zfile using the password passwd and the
//   cyclic redundancy check crc. passwd :: Password string. crc :: Crc of file
//   being encrypted. zfile :: Where to write header.
#define Putc(c, f)  (temp[tcnt++] = (c))
//void ZipDflt::crypthead(/*HANDLE zfile,*/ const char *passwd, ulg crc)
void ZipDflt::crypthead(const char* passwd, ulg crc)
{
    int           n;      // Index in random header.
    int           t;      // Temporary.
    int           c;      // Random byte.
    int           ztemp;  // Temporary for zencoded value.
    uch           header[RAND_HEAD_LEN - 2];  // Random header.
    uch           temp[RAND_HEAD_LEN + 2];
    int           tcnt = 0;
    unsigned long k;

    // First generate RAND_HEAD_LEN - 2 random bytes. We encrypt the output of
    //   rand() to get less predictability, since rand() is often poorly
    //   implemented.

    if (++fcalls == 1)
    {
        srand((unsigned)time(NULL) ^ ZCR_SEED2);
    }

    init_keys(passwd, fkeys);

    for (n = 0; n < RAND_HEAD_LEN - 2; n++)
    {
        c = (rand() >> 7) & 0xFF;
        header[n] = (uch) zencode(c, t, fkeys);
    }

    // Encrypt random header (last two bytes is high word of crc)
    init_keys(passwd, fkeys);

    for (n = 0; n < RAND_HEAD_LEN - 2; n++)
    {
        ztemp = zencode(header[n], t, fkeys);
        Putc((uch) ztemp, zfile);             // V1.5 Added (uch)
    }

    ztemp = zencode((int)(crc >> 16) & 0xFF, t, fkeys);

    Putc((uch) ztemp, zfile);               // V1.5 Added (uch)
    ztemp = zencode((int)(crc >> 24) & 0xFF, t, fkeys);
    Putc((uch) ztemp, zfile);               // V1.5 Added (uch)
    fZipOutfile->Write(temp, tcnt, &k);
    //  Assert(k < (RAND_HEAD_LEN + 2), "temp buffer overflow");
    fBytesWritten += k;
}

#define BUF_SIZE (1024 * 16)
// If requested, encrypt the data in buf, and in any case call fwrite() with
//   the arguments to zfwrite(). Return what fwrite() returns. buf :: Data
//   buffer. item_size :: Size of each item in bytes. nb :: Number of items. f
//   :: File to write to.
unsigned __fastcall ZipDflt::zfwrite(const uch *buf, ::extent nb)
{
    unsigned long k;
    int           t;            // temporary
    unsigned      r;

    if (fkey)
    {
        // key is the global password pointer
        ulg   size;               // buffer size
        char  *p = (char *)buf; // steps through buffer
        DZStrA bf;
        char * bfr = bf.GetBuffer(BUF_SIZE);
        while (nb)
        {
            ulg tw = BUF_SIZE;// sizeof(fewetmp);
            char *d = bfr;//fewetmp;

            if (tw > nb)
                tw = nb;

            // Encrypt data in buffer
            for (size = tw; size != 0; p++, size--)
            {
                *d++ = (char)zencode(*p, t, fkeys);
            }

            r = fZipOutfile->Write(bfr, tw, &k);
//            r = fZipOutfile->Write(fewetmp, tw, &k);

            fBytesWritten += k;
            nb -= k;

            if (!r)
            {
                diag(_T("zfwrite failed"));
                return r;
            }
        }

        return 1;
    }

    // Write the buffer out
    r = fZipOutfile->Write(buf, nb, &k);
    if (!r)                            
        Notify(IDIAG, _T("zfwrite failed [%s]"), SysMsg().c_str());
//        diag(_T("zfwrite failed"));

    fBytesWritten += k;
    return r;
}

/* 30/1/07 */


