How to use OnGetPassword send password for establishing SSL connection in Delphi 7 - delphi-7

I'm trying to establish a SSL connection from Delphi to a Webservice. But to send the password, I could find that OnGetPassword function must be used. But I couldn't get any information on how to use this function. Saw the below function. But this just gives undeclared indentifier during compilation
procedure TForm1.IdSSLIOHandlerSocketOpenSSL1GetPassword(var Password: string);
begin
Password := 'thepassword';
end;
Can anyone please shed some light on how should I use this function to send the password. Below is my code (just the SSL part)
Id_HandlerSocket := TIdSSLIOHandlerSocketOpenSSL.create(nil);
Id_HandlerSocket.SSLOptions.Mode := sslmClient;
Id_HandlerSocket.SSLOptions.Method := sslvTLSv1_2;
Id_HandlerSocket.SSLOptions.RootCertFile := 'CARootcert.pem';
Id_HandlerSocket.SSLOptions.CertFile := 'clicert.pem';
Id_HandlerSocket.SSLOptions.KeyFile := 'clikey.pem';
Id_HandlerSocket.OnGetPassword := GetPassword; // Needs to be corrected
This is what I have tried so far.
type
TForm1 = Class(TForm)
function GetPassword : String;
end;
function TForm1.GetPassword : String;
begin
Result := 'Thepassword';
end;
Id_HandlerSocket.OnGetPassword := GetPassword; //Just the part calling the proc
But on compiling, I get the error - Undeclared identifier - GetPassword.
How should I access the function GetPassword ?

Related

Retrieve Delphi runtime application version and application build information for OSX in fire monkey (FMX)

I try to find an example on how to retrieve the application version and build nr so I can display it in the help box of an OSX application.
Trivial on Windows but on Mac its not.
Hope you can help!
Edward
I use this code that I have written. Simply call:
osxNSBundle.BundleVersion()
Here is the code:
uses
Macapi.Foundation,
Macapi.Helpers;
osxNSBundle = class
private
class function MainBundle: NSBundle;
public
class function BundlePath: string;
class function BundleVersionStr: string;
class procedure BundleVersion(var aMajor,aMinor,aBuild: integer);
end;
implementation
class function osxNSBundle.MainBundle: NSBundle;
begin
result := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
end;
class function osxNSBundle.BundlePath: string;
begin
result := NSStrToStr(MainBundle.bundlePath);
end;
class function osxNSBundle.BundleVersionStr: string;
begin
Result := NSStrToStr(TNSString.Wrap(MainBundle.objectForInfoDictionaryKey(StrToNSStr('CFBundleVersion'))));
end;
class procedure osxNSBundle.BundleVersion(var aMajor,aMinor,aBuild: integer);
var lStrArray: TArray<string>;
i: Integer;
begin
aMajor := 0; aMinor := 0; aBuild := 0;
lStrArray := BundleVersionStr.Split(['.']);
if Length(lStrArray)>=3 then
begin
aMajor := lStrArray[0].ToInteger;
aMinor := lStrArray[1].ToInteger;
aBuild := lStrArray[2].ToInteger;
end;
end;

Delphi Firemonkey LockBox3 AES-CBC, PC and Android result are different?

I need a AES library for devolop Firemonkey Moblie App. I tested ElAES and LockBox3, everything works fine complie to PC, But on FMX Android both library return wrong ciphertext.
Test Data (AES128CBC PKCS5Padding):
plainText: 'plainText' - edtPlaintext.Text
key: '0000000000000000' - edtKey.Text
IV: '0000000000000000' - edtIV.Text
cipherText: hex - 'DD0A2A20616162697B8B4DF53483F1D2',
base64 - '3QoqIGFhYml7i031NIPx0g=='
Test Code:
This is test code reley on LockBox3, related: https://github.com/TurboPack/LockBox3, function 'EncryptMemory' return unfixed ciphertext each time on Android, something need to notice?
uses uTPLb_Codec, uTPLb_CryptographicLibrary, uTPLb_Constants, uTPLb_StreamUtils;
type
TCustomPadder = class(TObject)
private
FIV: TBytes;
public
constructor Create(const AIV: TBytes);
procedure OnSetIV(Value: TMemoryStream);
end;
constructor TCustomPadder.Create(const AIV: TBytes);
begin
FIV := AIV
end;
procedure TCustomPadder.OnSetIV(Value: TMemoryStream);
begin
Value.Size := Length(FIV);
Value.Position := 0;
Value.WriteBuffer(FIV, Length(FIV))
end;
function NewCodec(key: TBytes): TCodec;
var
codec: TCodec;
cryptographicLibrary: TCryptographicLibrary;
keyStream: TStream;
padder: TCustomPadder;
begin
cryptographicLibrary := TCryptographicLibrary.Create(nil);
// basic
codec := TCodec.Create(nil);
codec.BlockCipherId := Format(AES_ProgId, [128]);
codec.ChainModeId := CBC_ProgId;
codec.CryptoLibrary := cryptographicLibrary;
codec.StreamCipherId := BlockCipher_ProgId;
// extend
padder := TCustomPadder.Create(bytesof('0000000000000000'));
keyStream := TMemoryStream.Create;
keyStream.WriteBuffer(key, Length(key));
keyStream.Position := 0;
codec.OnSetIV := padder.OnSetIV;
codec.InitFromStream(keyStream);
result := codec;
end;
function PKCS5Padding(ciphertext: string; blocksize: integer): string;
var
builder: TStringBuilder;
padding: integer;
i: integer;
begin
builder := TStringBuilder.Create(ciphertext);
padding := blocksize - (builder.Length mod blocksize);
for i := 1 to padding do
begin
builder.Append(Char(padding));
end;
result := builder.ToString;
builder.DisposeOf;
end;
function BytesToHexStr(bytes: TBytes): string;
var
i: integer;
begin
result := '';
for i := 0 to Length(bytes) - 1 do
result := result + bytes[i].ToHexString(2);
end;
procedure TformAEST.btnEncryptClick(Sender: TObject);
var
codec: TCodec;
plainBytes, cipherBytes: TBytes;
cipherMemory: TStream;
cipherBytesLen: integer;
begin
cipherMemory := TMemoryStream.Create;
plainBytes := bytesof(PKCS5Padding(edtPlaintext.Text, 16));
codec := NewCodec(bytesof(edtKey.Text));
codec.Begin_EncryptMemory(cipherMemory);
codec.EncryptMemory(plainBytes, Length(plainBytes));
codec.End_EncryptMemory;
cipherMemory.Position := 8;
cipherBytesLen := cipherMemory.Size - 8;
SetLength(cipherBytes, cipherBytesLen);
cipherMemory.ReadBuffer(cipherBytes, cipherBytesLen);
edtCiphertext.Text := BytesToHexStr(cipherBytes);
end;
Encryption and decryption operate on raw bytes, not on characters.
When encrypting Unicode strings, especially across platforms, you have to encode the characters to bytes using a consistent byte encoding before then encrypting those bytes.
And when decrypting Unicode strings, make sure to use that same byte encoding when converting the decrypted bytes back into characters.
In your code, you are using BytesOf() to encode Unicode characters to bytes. Internally, BytesOf() uses TEncoding.Default as the encoding, which is TEncoding.ANSI on Windows PCs but is TEncoding.UTF8 on other platforms. So, if your input strings contain any non-ASCII characters, you will end up with different results.
I suggest replacing BytesOf() with TEncoding.UTF8.GetBytes() on all platforms:
plainBytes := TEncoding.UTF8.GetBytes(PKCS5Padding(edtPlaintext.Text, 16));
codec := NewCodec(TEncoding.UTF8.GetBytes(edtKey.Text));
As your requirement, I need to create a mobile app with Delphi in recent weeks, and try to figure out how to encrypt in Delphi, and decrypt in server side application.
I choose Laravel 8 as my server side application framework, Delphi Alaxandria as client RAD tool.
With some tests, I found that Laravel used openssl_decrypt function to decrypt cipher, and padding byte is under special rule.
Hence, I use DEC (Delphi Encryption Compendium, you can download it free with Delphi GitIt package manager or from GitHub, the link I attached) to generate the cipher, with the APP_Key generated in Laravel (or you can generate 32 bytes key by yourself), the generated cipher can be decrypted by Laravel successfully.
I also upload my sample project to my GitHub repository, if you need to use AES-256-CBC in your Delphi FireMonkey project, please enjoy it.

Is there any simple way to use the FTP function in Lazarus code

I am a couple of months new to Lazarus. I have been trying to create a small FTP program that will send a small file after logging in. I have all the gooey stuff done and my only concern is the FTP part. I am getting a whole lot of errors and I have struggled to install the correct packages
My FTP code looks like this
function TModel.Send(LocalFile : string; remoteFile : string; RemoteDir : string) : boolean;
//===========================================================================
// **********************************************************************
// * Send a file to the FTP server *
// **********************************************************************
//---------------------------------------------------------------------------
var
rc : boolean;
begin
// Create the FTP Client object and set the FTP parameters
FTPClient := TFTPSend.Create;
with FTPClient do begin
TargetPort := cFtpProtocol;
TargetHost := fHost; // these were properties set somewhere else
UserName := fUserID;
Password := fPassword;
//-----------------------------------------------------------------------
// bail out if the FTP connect fails
if not LogIn then exit;
//------------------------------------------------------------------------
// Set filename to FTP
DirectFileName := LocalFile;
DirectFile := True;
//------------------------------------------------------------------------
// change directory if requested
if RemoteDir <> '' then ChangeWorkingDir(RemoteDir);
//------------------------------------------------------------------------
// STOR file to FTP server.
rc := StoreFile(RemoteFile,false);
//------------------------------------------------------------------------
// close the connection
LogOut;
//------------------------------------------------------------------------
// free the FTP client object
free;
//------------------------------------------------------------------------
end;
Result := rc;
//===========================================================================
end;
Thanks for your help.
Oh Lazarus XD. I'm not sure if there is any easy way though. I tried to do something similar a while back but i didn't get round to finishing it though.... But i did get the FTP to work take a look at my code below
begin
IdSMTP := TIdSMTP.Create(nil);
try
IdSMTP.Host := 'smtp.jonas.com';
IdSMTP.Port := 587;
IdSMTP.AuthType := satDefault;
IdSMTP.Username := 'server#jonas.com';
IdSMTP.Password := 'TeCat#!';
IdSMTP.Connect;
if IdSMTP.Authenticate then;
begin
IdMessage := TIdMessage.Create(nil);
try
IdMessage.From.Name := 'Jonas Server';
IdMessage.From.Address := 'server#jonas.com';
IdMessage.Subject := subject;
IdMessage.Body.AddStrings(message);
IdEmailAddressItem := IdMessage.Recipients.Add;
IdEmailAddressItem.Address := 'server#jonas.com';
IdSMTP.Send(IdMessage);
finally
IdMessage.Free;
end;
end;
IdSMTP.Disconnect;
finally
IdSMTP.Free;
end;
end;
I see you are using Synapse I can't remember what I used.... Its between indy, lnet or synapse. Just let me know if you need these packages I got them saved on my dropbox :) also check out THIS website it's a whole site dedicated to Laz.....GREAT ( ͡° ͜ʖ ͡°)

Downloading a file in Delphi

A google search shows a few examples on how to download a file in Delphi but most are buggy and half of the time don't work in my experience.
I'm looking for a simple robust solution which will let me download a single exe (for updating my app) and will hold the execution of the current update thread until the download is done or errors out. The process is already threaded so the download code should hold execution until it's done (hopefully).
Here's two implementations, both seem very complicated
1. http://www.scalabium.com/faq/dct0116.htm
2. http://delphi.about.com/od/internetintranet/a/get_file_net.htm
Why not make use of Indy? If you use the TIdHTTP component, it's simple:
procedure TMyForm.DownloadFile;
var
IdHTTP1: TIdHTTP;
Stream: TMemoryStream;
Url, FileName: String;
begin
Url := 'http://www.rejbrand.se';
Filename := 'download.htm';
IdHTTP1 := TIdHTTP.Create(Self);
Stream := TMemoryStream.Create;
try
IdHTTP1.Get(Url, Stream);
Stream.SaveToFile(FileName);
finally
Stream.Free;
IdHTTP1.Free;
end;
end;
You can even add a progress bar by using the OnWork and OnWorkBegin events:
procedure TMyForm.IdHTTPWorkBegin(ASender: TObject; AWorkMode: TWorkMode;AWorkCountMax: Int64);
begin
ProgressBar.Max := AWorkCountMax;
ProgressBar.Position := 0;
end;
procedure TMyForm.IdHTTPWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
begin
ProgressBar.Position := AWorkCount;
end;
procedure TMyForm.DownloadFile;
var
IdHTTP1: TIdHTTP;
Stream: TMemoryStream;
Url, FileName: String;
begin
Url := 'http://www.rejbrand.se';
Filename := 'download.htm';
IdHTTP1 := TIdHTTP.Create(Self);
Stream := TMemoryStream.Create;
try
IdHTTP1.OnWorkBegin := IdHTTPWorkBegin;
IdHTTP1.OnWork := IdHTTPWork;
IdHTTP1.Get(Url, Stream);
Stream.SaveToFile(FileName);
finally
Stream.Free;
IdHTTP1.Free;
end;
end;
I'm not sure if these events fire in the context of the main thread, so any updates done to VCL components may have to be done using the TIdNotify component to avoid threading issues. Maybe someone else can check that.
The second approach is the standard way of using Internet resources using WinINet, a part of Windows API. I have used it a lot, and it has always worked well. The first approach I have never tried. (Neither is "very complicated". There will always be a few additional steps when using the Windows API.)
If you want a very simple method, you could simply call UrlMon.URLDownloadToFile. You will not get any fine control (at all!) about the download, but it is very simple.
Example:
URLDownloadToFile(nil,
'http://www.rejbrand.se',
PChar(ExtractFilePath(Application.ExeName) + 'download.htm'),
0,
nil);
For people that has later version of delphi, you can use this:
var
http : TNetHTTPClient;
url : string;
stream: TMemoryStream;
begin
http := TNetHTTPClient.Create(nil);
stream := TMemoryStream.Create;
try
url := YOUR_URL_TO_DOWNLOAD;
http.Get(url, stream);
stream.SaveToFile('D:\Temporary\1.zip');
finally
stream.Free;
http.Free;
end;
end;
Using URLMon.
errcode := URLMon.URLDownloadToFile(nil,
PChar('http://www.vbforums.com/showthread.php?345726-DELPHI-Download-Files'),
PChar( 'a:\download.htm'),
0,
nil);
if errcode > 0 then
showmessage('Error while downloading: ' + inttostr(errcode));

create windows user using Delphi

I need to create new windows user as administrator using Delphi
Thanks
you can use the NetUserAdd and NetUserSetGroups functions declarated in the JEDI Headers.
see this simple sample.
program ProjectAddNewUser;
{$APPTYPE CONSOLE}
uses
JclWin32,//Jedi Library
Windows,
SysUtils;
function CreateWinUser(const wServer, wUsername, wPassword, wGroup:WideString): Boolean;
var
Buf : USER_INFO_2;//Buf for the new user info
Err : NET_API_STATUS;
ParmErr : DWORD;
GrpUsrInfo: USER_INFO_0;//Buf for the group
wDummyStr : WideString;
begin
wDummyStr:='';
FillChar (Buf, SizeOf(USER_INFO_2), 0);
with Buf do
begin
usri2_name := PWideChar(wUsername);
usri2_full_name := PWideChar(wUsername);//You can add a more descriptive name here
usri2_password := PWideChar(wPassword);
usri2_comment := PWideChar(wDummyStr);
usri2_priv := USER_PRIV_USER;
usri2_flags := UF_SCRIPT OR UF_DONT_EXPIRE_PASSWD;
usri2_script_path := PWideChar(wDummyStr);
usri2_home_dir := PWideChar(wDummyStr);
usri2_acct_expires:= TIMEQ_FOREVER;
end;
GrpUsrInfo.usri0_name:=PWideChar(wGroup);
Err := NetUserAdd(PWideChar(wServer), 1, #Buf, #ParmErr);
Result := (Err = NERR_SUCCESS);
if Result then //NOw you must set the group for the new user
begin
Err := NetUserSetGroups(PWideChar(wServer),PWideChar(wGroup),0,#GrpUsrInfo,1);
Result := (Err = NERR_SUCCESS);
end;
end;
begin
if CreateWinUser('localhost', 'MyNewUser','ThePassword','MyWindowsGroup') then
Writeln('Ok')
else
Writeln('False');
Readln;
end.
I think the API call you need is NetUserAdd.
First, check if Delphi provides a wrapper for this call. If not, you'll have to write your own. If you don't know how to make Windows API calls from Delphi, you have some more research to do.

Resources