I am using Delphi 10.2 Tokyo, trying to download some information from a web server.
I pass the command URL https://poloniex.com/public?command=returnCurrencies through this function using Indy 10.6.2.5366 (the command works if I paste it in a browser):
function ReadHTTPS(const url: string): string;
var
IdHTTP: TIdHTTP;
IdSSL: TIdSSLIOHandlerSocketOpenSSL;
begin
IdHTTP := TIdHTTP.Create;
try
IdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP);
IdHTTP.IOHandler := IdSSL;
result := IdHTTP.Get(url);
if IdHTTP.ResponseText <> '' then
OutputDebugString(PWideChar('ReadHTTPS: ' + IdHTTP.ResponseText));
finally
IdHTTP.Free;
end;
end{ ReadHTTPS};
That gives the following error:
Error connecting with SSL.
error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version
I have tried installing the latest DLLs for OpenSSL in the same directory as the exe, but that didn't solve it.
Any ideas?
Make sure you are using an up-to-date version of the OpenSSL DLLs that support TLS v1.2 (the latest version that Indy currently supports is 1.0.2u), and then you need to enable the sslvTLSv1_2 flag in the SSLIOHandler's SSLOptions.SSLVersions property:
IdSSL.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
Or:
IdSSL.SSLOptions.SSLVersions := [sslvTLSv1_2];
Indy enables only TLS v1.0 by default, and apparently https://poloniex.com does not allow TLS versions prior to TLS v1.2.
Related
I am trying to make an interface to FreshDesk API
Here is my source code for the call:
procedure TForm1.Button1Click(Sender: TObject);
var
IdSSLIOHandlerSocket1: TIdSSLIOHandlerSocketOpenSSL;
idhttp: TIdHttp;
begin
idhttp := TIdHttp.Create(self);
idhttp.Request.ContentType := 'application/json';
IdHTTP.Request.BasicAuthentication:= True;
IdHTTP.Request.Username := 'marks#mytestcompany.com';
IdHTTP.Request.Password := 'XYZ';
idhttp.Request.Connection:='keep-alive';
IdSSLIOHandlerSocket1 := TIdSSLIOHandlerSocketOpenSSL.create(nil);
with IdSSLIOHandlerSocket1 do begin
SSLOptions.Method := sslvTLSv1_2;
SSLOptions.SSLVersions := [sslvTLSv1_2];
SSLOptions.VerifyMode := [];
SSLOptions.VerifyDepth := 2;
end;
idhttp.IOHandler := IdSSLIOHandlerSocket1;
idhttp.Request.Accept := '*/*';
idhttp.HandleRedirects := True;
if usefiddler.checked then begin
idhttp.ProxyParams.ProxyServer := '127.0.0.1';
idhttp.ProxyParams.ProxyPort := 8888 ;
end;
showMessage(idhttp.get('https://mytestcompany.freshdesk.com/api/v2/contacts'));
end;
When I run using Fiddler it shows it is using Version: 3.1 (TLS/1.0):
Here is successful curl call (it seems to be using Version: 3.3 (TLS/1.2):
curl -v -u marks#mytestcompnay:XYZ -H "Content-Type: application/json" -X GET "https://mytestcompany.freshdesk.com/api/v2/contacts"
Here is Fiddler results when using curl:
Is my problem that I am using the wrong version of TLS?
You are using an outdated version of OpenSSL.
Per comments, you say that you are using OpenSSL 1.0.0q. That version is several years old and does not support TLS v1.2 (which was added to OpenSSL in 1.0.1, which is still an old version). Indy silently falls back to TLS v1.0 when it cannot use TLS v1.1 or v1.2.
You need to update your OpenSSL. The latest version of OpenSSL that Indy currently supports is 1.0.2.
Here's my program
ftp := TIdFTp.Create();
IdSSLIOHandlerSocketOpenSSL1 := TIdSSLIOHandlerSocketOpenSSL.Create(ftp);
with IdSSLIOHandlerSocketOpenSSL1 do
begin
host := fhost;
MaxLineAction := maException;
port := 2111;
ReadTimeout := 60000;
SSLOptions.Method := sslvSSLv3;
SSLOptions.Mode := sslmUnassigned;
end;
ftp := TIdFTp.Create();
with ftp do
begin
Host := fHost;
password := fpass;
Username := fuser;
IOHandler :=IdSSLIOHandlerSocketOpenSSL1;
UseTLS := utUseExplicitTLS;
DataPortProtection := ftpdpsPrivate;
port := 2111;
end;
ftp.Connect;
I'm using TIdFTP component in Delphi 2007 and Delphi 10.2 Berlin.
For Delphi 2007, the program connects to FTP. However, for the Delphi 10.2 the program gives an error 'Could not load SSL library.'
In both cases, to the exe file directory I include the ssleay32.dll and libeay32.dll files
How do I set a global environment variable in Inno Setup?
Background: I am using the Inno install utility and need to set a global environment variable before I do the actual install.
Try this:
[Registry]
Root: HKCU; Subkey: "Environment"; ValueType:string; ValueName: "VARIABLE_NAME"; \
ValueData: "new_value"; Flags: preservestringtype
You might need to add this:
[Setup]
; Tell Windows Explorer to reload the environment
ChangesEnvironment=yes
Alternatively try:
[Run]
Filename: "{app}\MyProg.exe"; BeforeInstall: SetEnvPath
[Code]
#ifdef UNICODE
#define AW "W"
#else
#define AW "A"
#endif
function SetEnvironmentVariable(lpName: string; lpValue: string): BOOL;
external 'SetEnvironmentVariable{#AW}#kernel32.dll stdcall';
procedure SetEnvPath;
begin
if not SetEnvironmentVariable('VARIABLE_NAME', 'new_value') then
MsgBox(SysErrorMessage(DLLGetLastError), mbError, MB_OK);
end;
Reference: Inno Setup Frequently Asked Questions - Setting Environment Variables
If the variable change is not propagated (see Environment variable not recognized [not available] for [Run] programs in Inno Setup)
[Run]
...; AfterInstall: RefreshEnvironment
[Code]
const
SMTO_ABORTIFHUNG = 2;
WM_WININICHANGE = $001A;
WM_SETTINGCHANGE = WM_WININICHANGE;
type
WPARAM = UINT_PTR;
LPARAM = INT_PTR;
LRESULT = INT_PTR;
function SendTextMessageTimeout(hWnd: HWND; Msg: UINT;
wParam: WPARAM; lParam: PAnsiChar; fuFlags: UINT;
uTimeout: UINT; out lpdwResult: DWORD): LRESULT;
external 'SendMessageTimeoutA#user32.dll stdcall';
procedure RefreshEnvironment;
var
S: AnsiString;
MsgResult: DWORD;
begin
S := 'Environment';
SendTextMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
PAnsiChar(S), SMTO_ABORTIFHUNG, 5000, MsgResult);
end;
More details:
Inno Setup: Setting a System Environment Variable
Under more modern (in other words, proper) operating systems, such as
Windows 2000, XP, and Windows 2003 Server, environment variables are
stored in the Registry under the following key:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\
Environment
Variables are added by creating a new value under this key or by
modifying a value if it already exists. To delete a variable, you
simply delete its Registry value, unless you are removing part of an
expanded value, such as PATH, in which case you only remove the part
you want.
At this point, Windows will not be aware of your changes unless you
log off or reboot. To get around this, SetEnv will broadcast a
WM_SETTINGCHANGE to all of the windows in the system. This allows
other running applications—for example, Explorer.exe—to be notified of
your change. If you run SetEnv from a command prompt, this will not
update the environment variable for the current DOS window. This is
mainly due to the fact that a process (SetEnv) cannot change the
environment of its parent (The Command Prompt). However, any new
DOS/Command Prompts that you open will show the new variable/value.
The solutions in #Adrian's answer (actually copied from #TLama's answer to similar question) are correct for many situations.
But it won't work for [Run] tasks with runasoriginaluser flag (what is implied by postinstall flag). I.e. the variable won't be propagated to an application run with common "Run My Program" check box on the "Finished" page.
The reason is that the tasks with runasoriginaluser are executed by a un-elevated hidden parent process of the Inno Setup installer. The SetEnvironmentVariable will change environment for the installer, but not for its parent process. Unfortunately, the parent process of the installer cannot be controlled (imo).
As a workaround, to set the variable for the runasoriginaluser tasks, you have to inject an intermediate process between the installer parent process and the task, and have the intermediate process set the variable.
Such an intermediate process can easily be the cmd.exe with its set command:
[Run]
Filename: "{cmd}"; Parameters: "/C set MYVAR=MyValue & ""{app}\MyProg.exe"""; \
Description: "Run My Program"; Flags: postinstall runhidden
The runhidden flag hides the cmd.exe console window, not the application (assuming it's a GUI application). If it's a console application, use start to start it in its own (visible) console window.
What would be wrong with running two setup.exe with the first one doing the setting of the environment variables, and the second doing the things needed for the true setup. The first one would be run with setup.exe /VERYSILENT
I am doing to add an system wide environment variable:
[Setup]
; Tell Windows Explorer to reload the environment
ChangesEnvironment=True
[Registry]
Root: "HKLM"; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: string; ValueName: "EGPL_GeoLibrarian_Drive"; ValueData: "L"; Flags: createvalueifdoesntexist preservestringtype
I am using indy client to make tcp ip connection with a server(IP address and port). I have written following code on the click of a button. I trying to send Hello msg to server and then trying to read the message from server.
procedure TForm1.Button1Click(Sender: TObject);
var
sMsg : string;
begin
try
IdTCPClient1.Port := xxxx; //Set port to connect to
IdTCPClient1.Host := 'xxx.xxx.x.xxxx'; //Set host to connect to
IdTCPClient1.Connect; //Make connection
sMsg := IdTCPClient1.Socket.ReadLn; //Read the response from the server
ShowMessage(sMsg);
except
on E : Exception do
begin
ShowMessage('Connection Error: ' + E.Message);
exit;
end;
end;
end;
But I am getting socket error 10061 connection refused while debugging at the line
IdTCPClient1.Connect; //Make connection
I tried to make tcp connection with server on given port and ip using telnet command on cmd (telnet ip port) and I got the following message
"Connection established to xxx.xxx.xx.xxx, there could be no connection made with the host, on port xxxx: connection errors"
Please suggest me the solution for this...
Thanks all. Now I am able to use the port. So no error at IdTCPClient1.Connect; //Make connection. But now nothing is happening at the next line where I am trying to read data from the server (sMsg := IdTCPClient1.Socket.ReadLn;) When I try from telnet, some miscellaneous characters are read from server. What could be the reason for this?
Im working on software that required psqlodbc drivers and postgresSQl 9.0 database,
we have a installer designed using delphi 7 to install both psqlodbc and postgreSQl 9 silently
one after the other on click of a single button, here everything runs fine,
but the problem is during uninstall,
i first want to unistall psqlodbc and then postgreSQl 9 also on a sinlge button click,
i want to run the postgreSQl 9 unistaller using shellpApi only after psqlodbc has been unstalled,
as of now im checking for 'cmd.exe' is running or not to start postgreSQl uninstaller, but sometimes after unstalling psqlodbc the 'cmd.exe' remain n the postgreSQl unistaller cannot be executed,
so any please tell me
how to check if psqlodbc uninstall process is completely.
the files are
1.psqlodbc.msi
2.postgresql-9.0.2-1-windows.exe
install/uninstall is handled wit bat file
thanks in advanced:)
You can check registry if driver is available. When it is installed you will get:
c:\tmp\pg>reg query "hklm\SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL ANSI"
! REG.EXE VERSION 3.0
HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL ANSI
APILevel REG_SZ 1
ConnectFunctions REG_SZ YYN
Driver REG_SZ C:\Program Files\psqlODBC\0900\bin\psqlodbc30a.dll
DriverODBCVer REG_SZ 03.00
FileUsage REG_SZ 0
Setup REG_SZ C:\Program Files\psqlODBC\0900\bin\psqlodbc30a.dll
SQLLevel REG_SZ 1
UsageCount REG_DWORD 0x1
And when you unistall it you will get (localized version):
c:\tmp\pg>reg query "hklm\SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL ANSI"
Błąd: system nie może odnaleźć określonego klucza rejestru lub wartości.
c:\tmp\pg>
(this menas: Error: system cannot find key or value in registry)
See: reg /? on how to use it and for return code you can use in batch.
You can also search registry uninstall information under HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall
I got how to check if psqlodbc has been uninstalled completely so that i can start unistalling postgres
For that i found the solution
On stackoverflow itself
function TForm1.ExecAndWait(const CommandLine: string) : Boolean;
var
StartupInfo: Windows.TStartupInfo; // start-up info passed to process
ProcessInfo: Windows.TProcessInformation; // info about the process
ProcessExitCode: Windows.DWord; // process's exit code
begin
// Set default error result
Result := False;
// Initialise startup info structure to 0, and record length
FillChar(StartupInfo, SizeOf(StartupInfo), 0);
StartupInfo.cb := SizeOf(StartupInfo);
// Execute application commandline
if Windows.CreateProcess(nil, PChar(CommandLine),
nil, nil, False, 0, nil, nil,
StartupInfo, ProcessInfo) then
begin
try
// Now wait for application to complete
if Windows.WaitForSingleObject(ProcessInfo.hProcess, INFINITE)
= WAIT_OBJECT_0 then
// It's completed - get its exit code
if Windows.GetExitCodeProcess(ProcessInfo.hProcess,
ProcessExitCode) then
// Check exit code is zero => successful completion
if ProcessExitCode = 0 then
Result := True;
finally
// Tidy up
Windows.CloseHandle(ProcessInfo.hProcess);
Windows.CloseHandle(ProcessInfo.hThread);
end;
end;
end;
so step # 1
if ExecAndWait('msiexec /x C:\psqlodbc09\psqlodbc.msi') then
begin
//uninstall postgresNow...!!
end;