Shellexecute equivalent for Linux as target platform - delphi

Does anyone knows the equivalent for Shellexecute command for Linux as active target platform?

procedure ShlOpen( FileName: String ) ;
var prc: TProcess;
begin
prc: = TProcess.Create ( nil ) ;
prc.CommandLine: = 'xdg-open' + FileName;
prc.Execute;
prc.free;
end ;

Ended up wit this:
const
libc = '/usr/lib/libc.dylib';
type
PIOFile = Pointer;
// Create a new stream connected to a pipe running the given command.
function popen(const Command: PAnsiChar; Modes: PAnsiChar): PIOFile; cdecl; external libc name 'popen';
// Close a stream opened by popen and return the status of its child.
function pclose(Stream: PIOFile): Integer; cdecl; external libc name 'pclose';
// Return the EOF indicator for STREAM.
function feof(Stream: PIOFile): Integer; cdecl; external libc name 'feof';
// Read chunks of generic data from STREAM.
function fread(Ptr: Pointer; Size: LongWord; N: LongWord; Stream: PIOFile): LongWord; cdecl; external libc name 'fread';
// Wait for a child to die. When one does, put its status in *STAT_LOC
// and return its process ID. For errors, return (pid_t) -1.
function wait(__stat_loc: PInteger): Integer; cdecl; external libc name 'wait';
procedure TUtils.RunCommand(const CmdLine: string; results: TStrings);
var
Output: PIOFile;
Buffer: PAnsiChar;
TempString: Ansistring;
Line: Ansistring;
BytesRead: Integer;
const
BufferSize: Integer = 1000;
begin
TempString := '';
Output := popen(PAnsiChar(Ansistring(CmdLine)), 'r');
GetMem(Buffer, BufferSize);
if Assigned(Output) then
try
while feof(Output) = 0 do
begin
BytesRead := fread(Buffer, 1, BufferSize, Output);
SetLength(TempString, Length(TempString) + BytesRead);
Move(Buffer^, TempString[Length(TempString) - (BytesRead - 1)], BytesRead);
while Pos(#10, TempString) > 0 do
begin
Line := Copy(TempString, 1, Pos(#10, TempString) - 1);
results.Add(UTF8ToString(Line));
TempString := Copy(TempString, Pos(#10, TempString) + 1, Length(TempString));
end;
end;
finally
pclose(Output);
wait(nil);
FreeMem(Buffer, BufferSize);
end;
end;

Related

Disconnect socket at AcceptExHookProc

i'm trying disconnect a socket at AcceptExHookProc routine.
i hooked AcceptEx at .dll and injected at .exe app who i want disconnect socket if ip connected at socket is same at my if.
the program uses AcceptEx, not WSAAccept (i know about about the callback using CF_REJECT) but isn't the case for this program since him uses AcceptEx from Winsock library (not winsock2).
const WSAID_DISCONNECTEX: TGuid = '{7fda2e11-8630-436f-a031-f536a6eec157}';
type
LPFN_DISCONNECTEX = function(const hSocket : TSocket; AOverlapped:
POverlapped; const dwFlags : DWORD; const dwReserved : DWORD) : BOOL; stdcall;
function GetAddress(ASocket: TSocket; const AName: String; const AGuid: TGUID): Pointer; inline; overload;
var
BytesSend: DWORD;
begin
if WSAIoctl(ASocket, SIO_GET_EXTENSION_FUNCTION_POINTER, #AGuid, DWORD(SizeOf(TGuid)),
#Result, DWORD(SizeOf(FARPROC)), BytesSend, nil, nil) <> 0 then
Result := nil;
end;
function AcceptExHookProc(sListenSocket, sAcceptSocket: TSocket;
lpOutputBuffer: Pointer; dwReceiveDataLength, dwLocalAddressLength,
dwRemoteAddressLength: DWORD; var lpdwBytesReceived: DWORD;
lpOverlapped: POverlapped): BOOL; stdcall;
var
IP : String;
LRet, RRet : Winsock.PSockAddr;
lsize, rsize : Integer;
DisconnectEx : LPFN_DISCONNECTEX;
BytesOut : DWORD;
Res : Integer;
begin
Result := TrampolineAcceptEx(sListenSocket, sAcceptSocket, lpOutputBuffer, dwReceiveDataLength, dwLocalAddressLength, dwRemoteAddressLength, lpdwBytesReceived, lpOverlapped);
lsize := 32;
rsize := 32;
Winsock.GetAcceptExSockaddrs(lpOutputBuffer, dwReceiveDataLength, dwLocalAddressLength, dwRemoteAddressLength, LRet, lsize, RRet, rsize);
IP := Winsock.inet_ntoa(RRet.sin_addr);
if (IP = '177.222.164.65') then
begin
Res := setsockopt(sAcceptSocket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, #sListenSocket, SizeOf(sListenSocket));
WriteLn(Format('Result %d / %d', [Res, GetLastError]));
// Show result - 1 and sock error 10057
DisconnectEx := GetAddress(sAcceptSocket, 'DisconnectEx', WSAID_DISCONNECTEX);
if #DisconnectEx <> nil then
if DisconnectEx(sAcceptSocket, nil, TF_REUSE_SOCKET, 0) then
WriteLn('Disconnect ok')
else
WriteLn('Disconnect falhou + ' + IntToStr(GetLastError));
// Show sock error 10057
WriteLn(Format(' [%s] Connection from IP (%s) DISCONNECT', [TimeToStr(Now), IP]));
end
else
begin
WriteLn(Format('[%s] Connection from IP (%s)', [TimeToStr(Now), IP]));
end;
end;
works but return false and getlasterror show socket error 10057 (Socket is not connected.)
but connection still estabilished (i check at process hacker)

RSA Signature with SHA1 on utf8 strings using JVCL and OpenSSL using Delphi

I need to use RSA for signature but I am weak on SSL thingy so I find some code in internet.
I have find below code which I can used to sign ansistring successfully :
function GenarateRSASign(PrivateKey, Content: AnsiString): AnsiString;
var
buffer: PAnsiChar;
rsa_out, md: array[0..1023] of AnsiChar;
r: PRSA;
rsa_out_len: Cardinal;
key: PBIO;
hIdCrypto: HMODULE;
hash: array[0..SHA_DIGEST_LENGTH - 1] of AnsiChar;
type
Trsa_sign = function(_type: LongInt; const m: PAnsiChar; m_length: LongWord; sigret: PAnsiChar; var siglen: Cardinal; const rsa: PRSA): LongInt; cdecl;
Tsha1 = function(d: PAnsiChar; n: Cardinal; md: PAnsiChar): PAnsiChar; cdecl;
function LoadFunctionCLib(const FceName: string; const ACritical: Boolean = True): Pointer;
begin
Result := GetProcAddress(hIdCrypto, PChar(FceName));
end;
var
rsa_sign: Trsa_sign;
sha1: Tsha1;
bytes: TIdBytes;
begin
LoadOpenSSLLibrary;
hIdCrypto := LoadLibrary('libeay32.dll');
Assert(hIdCrypto <> 0, 'Cannot load libeay32.dll');
try
key := BIO_new_mem_buf(#PrivateKey[1], Length(PrivateKey));
r := PEM_read_bio_RSAPrivateKey(key, nil, nil, nil);
if r = nil then
Exit;
buffer := PAnsiChar(Content);
FillChar(md[0], 1024, 0);
FillChar(hash[0], SHA_DIGEST_LENGTH, 0);
sha1 := LoadFunctionCLib('SHA1');
Assert(#sha1 <> nil, 'Cannot load SHA1');
sha1(buffer, Length(Content), #hash[0]);
rsa_sign := LoadFunctionCLib('RSA_sign');
Assert(#rsa_sign <> nil, 'Cannot load RSA_sign');
FillChar(rsa_out[0], 1024, 0);
rsa_sign(EVP_sha1()._type, #hash[0], SHA_DIGEST_LENGTH, #rsa_out[0], rsa_out_len, r);
SetLength(bytes, rsa_out_len);
if rsa_out_len > 0 then
Move(rsa_out[0], bytes[0], rsa_out_len);
Result := AnsiString(TIdEncoderMIME.EncodeBytes(bytes));
BIO_free(key);
RSA_free(r);
finally
FreeLibrary(hIdCrypto);
UnLoadOpenSSLLibrary;
end;
end;
However, I need to sign utf8 string As I don't know if there is widestring version of 'rsa_sign' and 'sha1' functions inside libeay32.dll and their names, I just don't know how to alter the code to suit for utf8 string signature.
I would like to have some suggestion on how to modify these code or have other alternative to do the same work. Thank you.
Edit 1 :
Based on David's Advice, I had modify the code as below :
function GenarateRSASign(PrivateKey: AnsiString, Content: String): String;
var
buffer : TBytes;
rsa_out, md: array[0..1023] of Byte;
r: PRSA;
rsa_out_len: Cardinal;
key: PBIO;
hIdCrypto: HMODULE;
hash: array[0..SHA_DIGEST_LENGTH - 1] of Byte;
type
Trsa_sign = function(_type: LongInt; const m: PBype; m_length: LongWord; sigret: PBype; var siglen: Cardinal; const rsa: PRSA): LongInt; cdecl;
Tsha1 = function(d: PBype; n: Cardinal; md: PBype): PByte; cdecl;
function LoadFunctionCLib(const FceName: string; const ACritical: Boolean = True): Pointer;
begin
Result := GetProcAddress(hIdCrypto, PChar(FceName));
end;
var
rsa_sign: Trsa_sign;
sha1: Tsha1;
bytes: TIdBytes;
begin
LoadOpenSSLLibrary;
hIdCrypto := LoadLibrary('libeay32.dll');
Assert(hIdCrypto <> 0, 'Cannot load libeay32.dll');
try
key := BIO_new_mem_buf(#PrivateKey[1], Length(PrivateKey));
r := PEM_read_bio_RSAPrivateKey(key, nil, nil, nil);
if r = nil then
Exit;
FillChar(md[0], 1024, 0);
FillChar(hash[0], SHA_DIGEST_LENGTH, 0);
sha1 := LoadFunctionCLib('SHA1');
Assert(#sha1 <> nil, 'Cannot load SHA1');
buffer := TEncoding.UTF8.GetBytes(Content);
sha1(#buffer[0], Length(Buffer), #hash[0]);
rsa_sign := LoadFunctionCLib('RSA_sign');
Assert(#rsa_sign <> nil, 'Cannot load RSA_sign');
FillChar(rsa_out[0], 1024, 0);
rsa_sign(EVP_sha1()._type, #hash[0], SHA_DIGEST_LENGTH, #rsa_out[0], rsa_out_len, r);
SetLength(bytes, rsa_out_len);
if rsa_out_len > 0 then
Move(rsa_out[0], bytes[0], rsa_out_len);
Result := TIdEncoderMIME.EncodeBytes(bytes);
BIO_free(key);
RSA_free(r);
finally
FreeLibrary(hIdCrypto);
UnLoadOpenSSLLibrary;
end;
end;
I get successful result when the content contain only English, which is same as before. However, when there is some Chinese Content, the result is rejected by the other party (Alipay) which reported "Illegal Sign". The input_charset is specified as 'UTF8'. Anythings else which I had done wrong here? Thank you.

Delphi: Capture OSX console output

I am on OSX and I found the following Delphi (Firemonkey) code to write the console output to a Memo. This works fine when I am using normal commands like "ls", but it doesn't capture the output from external terminal apps.
For example, if I run the command line application "youtube-dl", the output shows up only in the PAServer log, but not in the Memo.
Is there a way to do this? Or can someone modify the code to make this work?
const
libc = '/usr/lib/libc.dylib';
type
PIOFile = Pointer;
//Create a new stream connected to a pipe running the given command.
function popen(const Command: PAnsiChar; Modes: PAnsiChar): PIOFile; cdecl;
external libc name '_popen';
//Close a stream opened by popen and return the status of its child.
function pclose(Stream: PIOFile): Integer; cdecl; external libc name '_pclose';
//Return the EOF indicator for STREAM.
function feof(Stream: PIOFile): Integer; cdecl; external libc name '_feof';
//Read chunks of generic data from STREAM.
function fread(Ptr: Pointer; Size: LongWord; N: LongWord;
Stream: PIOFile): LongWord; cdecl; external libc name '_fread';
//Wait for a child to die. When one does, put its status in *STAT_LOC
//and return its process ID. For errors, return (pid_t) -1.
function wait(__stat_loc: PInteger): Integer; cdecl;
external libc name '_wait';
procedure TForm1.ExecCmdine(const CmdLine: string);
var
Output: PIOFile;
Buffer: PAnsiChar;
TempString: Ansistring;
Line: AnsiString;
BytesRead: Integer;
const
BufferSize: Integer = 1000;
begin
TempString := '';
Output := popen(PAnsiChar(Ansistring(CmdLine)), 'r');
GetMem(Buffer, BufferSize);
if Assigned(Output) then
try
while feof(Output) = 0 do
begin
BytesRead := fread(Buffer, 1, BufferSize, Output);
SetLength(TempString, Length(TempString) + BytesRead);
Move(Buffer^, TempString[length(TempString) - (BytesRead - 1)], BytesRead);
while Pos(#10, TempString) > 0 do
begin
Line := Copy(TempString, 1, Pos(#10, TempString) - 1);
Memo1.Lines.Add(UTF8ToString(Line));
TempString := Copy(TempString, Pos(#10, TempString) + 1, Length(TempString));
end;
end;
finally
pclose(output);
wait(nil);
FreeMem(Buffer, BufferSize);
end;
end;
Rob Kennedy had the correct answer, but sadly he didn't post it as answer, so I will do it.
The problem was that the console output of youtube-dl gets printed to stderr and not stdout, so I had to add 2>&1 to the console command when running it.

List all users of an AD group in Delphi

How can I list all users of an AD group in Delphi 7?
One of the options, as I know, is to use a string LDAP. I got a LDAP string, but how to use it?
I tried to use WinAPI, example from internet that i search
function TSequrity.DomainUsers: String;
var
EntiesRead: DWORD;
TotalEntries: DWORD;
UserInfo: lpUSER_INFO_1;
lpBuffer: Pointer;
ResumeHandle: DWORD;
Counter: Integer;
NetApiStatus: LongWord;
w:WideString;
begin
ResumeHandle := 0;
w:=Domain;
NetApiStatus := NetUserEnum(#w[1], 1, 0, lpBuffer, 0, EntiesRead, TotalEntries, ResumeHandle);
NetApiBufferFree(lpBuffer);
NetApiStatus := NetUserEnum(#w[1], 1, 0, lpBuffer, TotalEntries*TotalEntries, EntiesRead, TotalEntries, ResumeHandle);
UserInfo := lpBuffer;
for Counter := 0 to EntiesRead - 1 do
begin
Result:=Result+WideCharToString(UserInfo^.usri1_name)+#13#10;
Inc(UserInfo);
end;
NetApiBufferFree(lpBuffer);
end;
It find local users. But im need to find users of domain group.
Here's an example using "NetGroupGetUsers". Please be aware that this does not work with nested groups (groups containing other groups).
{$WARN SYMBOL_PLATFORM OFF}
program DomainGroupGetUsersTest;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows, Classes;
const
netapi32lib = 'netapi32.dll';
type
PGroupUsersInfo0 = ^TGroupUsersInfo0;
_GROUP_USERS_INFO_0 = record
grui0_name: LPWSTR;
end;
TGroupUsersInfo0 = _GROUP_USERS_INFO_0;
GROUP_USERS_INFO_0 = _GROUP_USERS_INFO_0;
NET_API_STATUS = DWORD;
LPBYTE = ^BYTE;
function NetApiBufferFree (Buffer: Pointer): NET_API_STATUS; stdcall;
external netapi32lib;
function NetGroupGetUsers (servername: LPCWSTR; groupname: LPCWSTR;
level: DWORD; var bufptr: LPBYTE; prefmaxlen: DWORD; var entriesread: DWORD;
var totalentries: DWORD; ResumeHandle: PDWORD): NET_API_STATUS; stdcall;
external netapi32lib;
function DomainGroupGetUsers (const sGroup: WideString;
const UserList: TStrings;
const sLogonServer: WideString) : Boolean;
{ "sLogonServer" must be prefixed with "\\".
"sGroup" must contain the group name only. }
type
TaUserGroup = array of TGroupUsersInfo0;
const
PREF_LEN = 1024;
var
pBuffer : LPBYTE;
i : Integer;
Res : NET_API_STATUS;
dwRead, dwTotal : DWord;
hRes : DWord;
begin
Assert (sGroup <> '');
Assert (sLogonServer <> '');
Assert (UserList <> NIL);
UserList.Clear;
Result := true;
hRes := 0;
repeat
Res := NetGroupGetUsers (PWideChar (sLogonServer), PWideChar (sGroup),
0, pBuffer, PREF_LEN, dwRead, dwTotal,
PDWord (#hRes));
if (Res = Error_Success) or (Res = ERROR_MORE_DATA) then
begin
if (dwRead > 0) then
for i := 0 to dwRead - 1 do
with TaUserGroup (pBuffer) [i] do
UserList.Add (grui0_name);
NetApiBufferFree (pBuffer);
end { if }
else Result := false;
until (Res <> ERROR_MORE_DATA);
end; { DomainGroupGetUsers }
var
UserList : TStringList;
iIndex : Integer;
begin
UserList := TStringList.Create;
try
DomainGroupGetUsers ('Domain Users', UserList,
GetEnvironmentVariable ('LOGONSERVER'));
for iIndex := 0 to UserList.Count - 1 do
WriteLn (UserList [iIndex]);
finally
UserList.Free;
end; { try / finally }
if (DebugHook <> 0) then
begin
WriteLn;
Write ('Press [Enter] to continue ...');
ReadLn;
end; { if }
end.

How can I execute a console/terminal app with Delphi XE5 FireMonkey and capture the output in OSX and Windows

How can I execute a console/terminal app with Delphi XE5 FireMonkey and capture the output in OSX and Windows. I would love to share the same code for both windows based apps.
For OSX:
const
libc = '/usr/lib/libc.dylib';
type
PIOFile = Pointer;
//Create a new stream connected to a pipe running the given command.
function popen(const Command: PAnsiChar; Modes: PAnsiChar): PIOFile; cdecl;
external libc name '_popen';
//Close a stream opened by popen and return the status of its child.
function pclose(Stream: PIOFile): Integer; cdecl; external libc name '_pclose';
//Return the EOF indicator for STREAM.
function feof(Stream: PIOFile): Integer; cdecl; external libc name '_feof';
//Read chunks of generic data from STREAM.
function fread(Ptr: Pointer; Size: LongWord; N: LongWord;
Stream: PIOFile): LongWord; cdecl; external libc name '_fread';
//Wait for a child to die. When one does, put its status in *STAT_LOC
//and return its process ID. For errors, return (pid_t) -1.
function wait(__stat_loc: PInteger): Integer; cdecl;
external libc name '_wait';
procedure ExecCmdine(const CmdLine: string; CmdResult: TStrings);
var
Output: PIOFile;
Buffer: PAnsiChar;
TempString: Ansistring;
Line: AnsiString;
BytesRead: Integer;
const
BufferSize: Integer = 1000;
begin
TempString := '';
Output := popen(PAnsiChar(Ansistring(CmdLine)), 'r');
GetMem(Buffer, BufferSize);
if Assigned(Output) then
try
while feof(Output) = 0 do
begin
BytesRead := fread(Buffer, 1, BufferSize, Output);
SetLength(TempString, Length(TempString) + BytesRead);
Move(Buffer^, TempString[length(TempString) - (BytesRead - 1)], BytesRead);
while Pos(#10, TempString) > 0 do
begin
Line := Copy(TempString, 1, Pos(#10, TempString) - 1);
if CmdResult <> nil then
CmdResult.Add(UTF8ToString(Line));
TempString := Copy(TempString, Pos(#10, TempString) + 1, Length(TempString));
end;
end;
finally
pclose(output);
wait(nil);
FreeMem(Buffer, BufferSize);
end;
end;

Resources