unit ArcHelper;

{$mode objfpc}{$H+}

interface

uses
  objects, Classes, SysUtils, FileUtil, zipper, libtar, bzip2, paszlib;

procedure ZipDir(ZipFilename, InputPath, FileFilter:String);
procedure ZipFile(ZipFilename, InputFilename:String);
procedure UnZipFile(ZipFilename, OutputPath:String);
procedure UnGZipFile(GZipFilename, OutputFilename:String);
procedure TarDir(TarFilename, InputPath, FileFilter:String);
procedure UnTarFile(TarFilename, OutputPath:String);
procedure UnBZipFile(BZipFilename, OutputFilename:String);


implementation

{************************************************
              .zip
*************************************************}
//PKZip a complete directory with subdirs
//ZipFilename : Filename of file to create
//Inputpath   : Path to include into zip
//FileFilter  : Filter for files to include e.g. "*.txt"
procedure ZipDir(ZipFilename, InputPath, FileFilter:String);
var FZipper:TZipper;
begin
  FZipper:=TZipper.Create;
  FZipper.ZipFiles(ZipFileName, FindAllFiles(InputPath, FileFilter, True));
  FZipper.Free;
end;

//PKZip a single file
procedure ZipFile(ZipFilename, InputFilename: String);
var FZipper:TZipper;
begin
  FZipper:=TZipper.Create;
  FZipper.FileName:=ZipFileName;
  FZipper.Entries.AddFileEntry(InputFileName);
  FZipper.ZipAllFiles;
  FZipper.Free;
end;

//unzip a PKZip-archive to outputdir
procedure UnZipFile(ZipFilename, OutputPath:String);
var FUnZipper:TUnZipper;
begin
  FUnZipper:=TUnzipper.Create;
  ForceDirectories(OutputPath);
  FUnZipper.OutputPath:=OutputPath;
  FUnzipper.UnZipAllFiles(ZipFileName);
  FUnzipper.Free;
end;

{************************************************
              .gz
*************************************************}
//unzip a gzip-archive to outputdir
procedure UnGZipFile(GZipFilename, OutputFilename: String);
var
  Buf:array[0..4096] of Byte;
  OutStream: TMemoryStream;
  len:Integer;
  gFile:gzFile;
  mode:String;
begin
  mode:='r';
  gFile:=gzopen(PChar(GZipFileName), Pchar(mode));
  OutStream := TMemoryStream.Create;
  try
    len:=gzread(gFile, @buf[0], 4096);
    while (len>0)  do  //0 = EOF, -1 = ERROR
    begin
      OutStream.Write(buf, len);
      len:=gzread(gFile, @buf[0], 4096);
    end;

    OutStream.Position := 0;
    OutStream.SaveToFile(OutputFilename);
  finally
    OutStream.Free;
  end;
end;

{************************************************
              .tar
*************************************************}
//Tar a complete directory with subdirectories
procedure TarDir(TarFilename, InputPath, FileFilter: String);
var TA:TTarWriter;
    sl:TStringList;
    i:Integer;
begin
  TA:=TTarWriter.Create(TarFilename);
  sl:=TStringList.Create;
  sl:=FindAllFiles(InputPath, FileFilter, True);
  for i:=0 to sl.Count-1 do
  begin
    TA.AddFile(sl.Strings[i]);
  end;
  sl.Free;
  TA.Free;
end;

//untar a file to OutputPath
procedure UnTarFile(TarFilename, OutputPath: String);
var TA:TTarArchive;
    DirRec:TTarDirRec;
begin
  TA:=TTarArchive.Create(TarFilename);
  while TA.FindNext(DirRec) do
  begin
    ForceDirectories(OutputPath+PathDelim+ExtractFilePath(DirRec.Name));
    TA.ReadFile(OutputPath+PathDelim+DirRec.Name);
  end;
  TA.Free;
end;

{************************************************
              .bz2
*************************************************}
//unbzip2 a file as OutputFilename
procedure UnBZipFile(BZipFilename, OutputFilename: String);
var InFile,OutFile:TBufStream;
    Decoder:TBzip2_Decode_Stream;
    a:array[1..4096] of Byte;
    ReadSize:Cardinal;
begin
  begin
    InFile.Init(BzipFilename, stOpenRead, 4096);
    OutFile.Init(OutputFilename , stCreate, 4096);
    Decoder.Init(@Infile);
    repeat
      ReadSize:=4096;
      Decoder.Read(a, ReadSize);
      dec(ReadSize, Decoder.Short);
      OutFile.Write(a, ReadSize);
    until Decoder.Status<>0;
    Decoder.Done;
    InFile.Done;
    OutFile.Done;
  end;
end;


end.

