-
Content Count
2914 -
Joined
-
Last visited
-
Days Won
130
Everything posted by Remy Lebeau
-
The native VCL TComboBox does not support a custom drop down. There is nothing like that for the native VCL TComboBox, so you will have to use a 3rd party solution (for instance, TMS has a TAdvTreeComboBox component, and there is (an older) TreeComboBox available on Torry.net). Otherwise, you would have to write your own component. No.
-
MARS running as Indy standalone Windows Service, correct cert locations
Remy Lebeau replied to marcovaldo's topic in MARS-Curiosity REST Library
Indy doesn't care where the certificate files are stored, as long as the paths you supply to them are valid. Using absolute paths should have worked fine. Unless Indy is not the one using the certificate files to begin with...- 7 replies
-
- indy service
- mars
-
(and 1 more)
Tagged with:
-
update indy to use tls 1.2 in c++builder 6?
Remy Lebeau replied to JeanCremers's topic in General Help
Not like it used to be. A few members are still lingering around the various forums. Several members have transitioned into MVPs, though some members (like me) haven't but are still recognized by a few Embarcadero employees to keep getting old TeamB perks (free versions, beta access, etc). Thanks, fixed. -
exception message : Error connecting with SSL. EOF was observed that violates the protocol.
Remy Lebeau replied to david_navigator's topic in Indy
Yes, I do, and that is a VERY old version of OpenSSL, you need to upgrade. Indy currently supports up to 1.0.2u dated 21/12/2019, which you can find at https://github.com/IndySockets/OpenSSL-Binaries/ Work on supporting 1.1.x is in progress: https://github.com/IndySockets/Indy/pull/299 The Method property is deprecated, you should be using the SSLVersions property instead. TLS 1.0 has been (almost) completely phased out of modern servers. Most modern servers support, if not require, TLS 1.2, so that really should be your minimum going forward nowadays. You should also have TLS 1.1 enabled as a fallback, just in case, but even that is being phased out as well. To enable multiple TLS versions with the Method property, you would have to set it to sslvSSLv23, which will set the SSLVersions property to all SSL/TLS versions supported by Indy (including SSL 2.0, SSL 3.0, and TLS 1.x), but it is better to use the SSLVersions property directly (ie, don't enable SSL 2.0 and 3.0 anymore), eg: SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2]; Having multiple TLS versions enabled at a time will allow OpenSSL to negotiate the highest version that both client and server support. That being said, on a side note, you do not need to assign ANY of the following SSLIOHandler properties, as Indy handles them internally for you: Setup the necessary Host/Port only in the client component, ie TIdIMAP4. The Connect() method will then copy them into the IOHandler as needed. -
MARS running as Indy standalone Windows Service, correct cert locations
Remy Lebeau replied to marcovaldo's topic in MARS-Curiosity REST Library
Why? What is the actual problem with having them in an application folder?- 7 replies
-
- indy service
- mars
-
(and 1 more)
Tagged with:
-
exception message : Error connecting with SSL. EOF was observed that violates the protocol.
Remy Lebeau replied to david_navigator's topic in Indy
I'm assuming you are using OpenSSL, which version? Also, what version of the SSL/TLS protocol are you using? Then you should be able to debug it. For instance, using Wireshark, you can see the details of the actual SSL/TLS handshake (at least until the connection is encrypted. It takes a few back-and-forths to get that far). At what stage in the handshake is the server disconnecting? The error means that the IMAP server is closing its end of the TCP connection while the SSL/TLS handshake is still in progress. Typically, this happens if the server encounters something it doesn't like in the client's SSL/TLS handshake, and the server decides to bail out without first sending a TLS alert to explain what is wrong. -
update indy to use tls 1.2 in c++builder 6?
Remy Lebeau replied to JeanCremers's topic in General Help
<sigh> Fine, then let's go the long way around, using a full wrapper class, forget TMethod (even though it will technically work at runtime, despite the compiler warnings): // SOURCE #define BUILDING_DLL #include "mydll.h" class eventHandlers { public: OnWorkBeginFunc onWorkBegin; OnWorkEndFunc onWorkEnd; OnWorkFunc onWork; void __fastcall OnWorkBeginHandler(TObject *ASender, TWorkMode AWorkMode, __int64 AWorkCountMax) { if (onWorkBegin) onWorkBegin((OnWorkMode)AWorkMode, AWorkCountMax); } void __fastcall OnWorkEndHandler(TObject *ASender, TWorkMode AWorkMode) { if (onWorkEnd) onWorkEnd((OnWorkMode)AWorkMode); } void __fastcall OnWorkHandler(TObject *ASender, TWorkMode AWorkMode, __int64 AWorkCount) { if (onWork) onWork((OnWorkMode)AWorkMode, AWorkCount); } }; static bool sslPathSet = false; char* getdata(const char *url, OnWorkBeginFunc onWorkBegin, OnWorkEndFunc onWorkEnd, OnWorkFunc onWork) { char *result = NULL; try { if (!sslPathSet) { sslPathSet = true; IdOpenSSLSetLibPath(ExtractFilePath(ParamStr(0))); } TIdHTTP *http = new TIdHTTP; try { eventHandlers events; events.onWorkBegin = onWorkBegin; events.onWorkEnd = onWorkEnd; events.onWork = onWork; http->OnWorkBegin = &events.OnWorkBeginHandler; http->OnWorkEnd = &events.OnWorkEndHandler; http->OnWork = &events.OnWorkHandler; TIdSSLIOHandlerSocketOpenSSL *SSL = new TIdSSLIOHandlerSocketOpenSSL(http); SSL->SSLOptions->SSLVersions = TIdSSLVersions() << sslvTLSv1 << sslvTLSv1_1 << sslvTLSv1_2; http->IOHandler = SSL; http->ReadTimeout = 10000; UTF8String s = http->Get(url); result = new char[s.Length()+1]; memcpy(result, s.c_str(), s.Length()+1); } __finally { delete http; } } catch (...) { return NULL; } return result; } void freedata(char *data) { delete[] data; } Odd, they should be. Especially since OnWorkEnd can't be called if OnWorkBegin is not called first. No. Correct, because the event is expecting a class method, not a standalone procedure. Using TMethod is the way to get around that. -
update indy to use tls 1.2 in c++builder 6?
Remy Lebeau replied to JeanCremers's topic in General Help
<sigh> Try this: // SOURCE #define BUILDING_DLL #include "mydll.h" struct userFunctions { OnWorkBeginFunc onWorkBegin; OnWorkEndFunc onWorkEnd; OnWorkFunc onWork; }; static void __fastcall MyOnWorkBeginHandler(void *AData, TObject *ASender, TWorkMode AWorkMode, __int64 AWorkCountMax) { userFunctions *funcs = static_cast<userFunctions*>(AData); funcs->onWorkBegin((OnWorkMode)AWorkMode, AWorkCountMax); } static void __fastcall MyOnWorkEndHandler(void *AData, TObject *ASender, TWorkMode AWorkMode) { userFunctions *funcs = static_cast<userFunctions*>(AData); funcs->onWorkEnd((OnWorkMode)AWorkMode); } static void __fastcall MyOnWorkHandler(void *AData, TObject *ASender, TWorkMode AWorkMode, __int64 AWorkCount) { userFunctions *funcs = static_cast<userFunctions*>(AData); funcs->onWork((OnWorkMode)AWorkMode, AWorkCount); } template <typename EventType, typename HandlerType> static EventType makeEventHandler(void *data, HandlerType *handler) { TMethod m; m.Data = data; m.Code = handler; return reinterpret_cast<EventType&>(m); /* alternatively: EventType evt; TMethod &m = reinterpret_cast<TMethod&>(evt); m.Data = data; m.Code = handler; return evt; */ } static bool sslPathSet = false; char* getdata(const char *url, OnWorkBeginFunc onWorkBegin, OnWorkEndFunc onWorkEnd, OnWorkFunc onWork) { char *result = NULL; try { if (!sslPathSet) { sslPathSet = true; IdOpenSSLSetLibPath(ExtractFilePath(ParamStr(0))); } TIdHTTP *http = new TIdHTTP; try { userFunctions funcs; if (onWorkBegin) { funcs.onWorkBegin = onWorkBegin; http->OnWorkBegin = makeEventHandler<TWorkBeginEvent>(&funcs, &MyOnWorkBeginHandler); } if (onWorkEnd) { funcs.onWorkEnd = onWorkEnd; http->OnWorkEnd = makeEventHandler<TWorkEndEvent>(&funcs, &MyOnWorkEndHandler); } if (onWork) { funcs.onWork = onWork; http->OnWork = makeEventHandler<TWorkEvent>(&funcs, &MyOnWorkHandler); } TIdSSLIOHandlerSocketOpenSSL *SSL = new TIdSSLIOHandlerSocketOpenSSL(http); SSL->SSLOptions->SSLVersions = TIdSSLVersions() << sslvTLSv1 << sslvTLSv1_1 << sslvTLSv1_2; http->IOHandler = SSL; http->ReadTimeout = 10000; UTF8String s = http->Get(url); result = new char[s.Length()+1]; memcpy(result, s.c_str(), s.Length()+1); } __finally { delete http; } } catch (...) { return NULL; } return result; } void freedata(char *data) { delete[] data; } -
update indy to use tls 1.2 in c++builder 6?
Remy Lebeau replied to JeanCremers's topic in General Help
My bad, too many *s in the DLL's event handlers. Try this instead: static void __fastcall MyOnWorkBeginHandler(void *AData, TObject *ASender, TWorkMode AWorkMode, __int64 AWorkCountMax) { OnWorkBeginFunc func = static_cast<OnWorkBeginFunc>(AData); func(AWorkMode, AWorkCountMax); } static void __fastcall MyOnWorkEndHandler(void *AData, TObject *ASender, TWorkMode AWorkMode) { OnWorkEndFunc func = static_cast<OnWorkEndFunc>(AData); func(AWorkMode); } static void __fastcall MyOnWorkHandler(void *AData, TObject *ASender, TWorkMode AWorkMode, __int64 AWorkCount) { OnWorkFunc func = static_cast<OnWorkFunc>(AData); func(AWorkMode, AWorkCount); } -
update indy to use tls 1.2 in c++builder 6?
Remy Lebeau replied to JeanCremers's topic in General Help
Why not just install the latest Indy in C++Builder 6? No, not directly. Nor should you be trying to. What you should do instead is let the caller pass in its own function pointer(s), which your DLL then remembers, and can then call from inside its own OnWork event handler(s). For example, the following uses a little-known trick for assigning a standalone procedure as a VCL event handler, while also passing a user-defined parameter to it. There are other ways this could be implemented, but this is the most straight-forward way I can think of right now for your scenario: // HEADER #ifndef MY_DLL_H #define MY_DLL_H #ifdef __cplusplus extern "C" { #endif #ifdef BUILDING_DLL #define EXPORT __declspec(dllexport) #else #define EXPORT __declspec(dllimport) #endif enum OnWorkMode { WorkReading, WorkWriting }; typedef void (*OnWorkBeginFunc)(OnWorkMode AWorkMode, __int64 AWorkCountMax); typedef void (*OnWorkEndFunc)(OnWorkMode AWorkMode); typedef void (*OnWorkFunc)(OnWorkMode AWorkMode, __int64 AWorkCount); EXPORT char* getdata(const char *url, OnWorkBeginFunc onWorkBegin, OnWorkEndFunc onWorkEnd, OnWorkFunc onWork); EXPORT void freedata(char *data); #ifdef __cplusplus } #endif #endif // SOURCE #define BUILDING_DLL #include "mydll.h" static void __fastcall MyOnWorkBeginHandler(void *ASelf, TObject *ASender, TWorkMode AWorkMode, __int64 AWorkCountMax) { OnWorkBeginFunc func = static_cast<OnWorkBeginFunc*>(ASelf); func(AWorkMode, AWorkCountMax); } static void __fastcall MyOnWorkEndHandler(void *ASelf, TObject *ASender, TWorkMode AWorkMode) { OnWorkEndFunc *func = static_cast<OnWorkEndFunc*>(ASelf); func(AWorkMode); } static void __fastcall MyOnWorkHandler(void *ASelf, TObject *ASender, TWorkMode AWorkMode, __int64 AWorkCount) { OnWorkFunc *func = static_cast<OnWorkFunc*>(ASelf); func(AWorkMode, AWorkCount); } template <typename EventType, typename FuncType, typename HandlerType> static EventType makeEventHandler(FuncType *func, HandlerType *handler) { TMethod m; m.Data = func; m.Code = handler; return reinterpret_cast<EventType&>(m); /* alternatively: EventType evt; TMethod &m = reinterpret_cast<TMethod&>(evt); m.Data = func; m.Code = handler; return evt; */ } static bool sslPathSet = false; char* getdata(const char *url, OnWorkBeginFunc onWorkBegin, OnWorkEndFunc onWorkEnd, OnWorkFunc onWork) { char *result = NULL; try { if (!sslPathSet) { sslPathSet = true; IdOpenSSLSetLibPath(ExtractFilePath(ParamStr(0))); } TIdHTTP *http = new TIdHTTP; try { if (onWorkBegin) http->OnWorkBegin = makeEventHandler<TWorkBeginEvent>(onWorkBegin, &MyOnWorkBeginHandler); if (onWorkEnd) http->OnWorkEnd = makeEventHandler<TWorkEndEvent>(onWorkEnd, &MyOnWorkEndHandler); if (onWork) http->OnWork = makeEventHandler<TWorkEvent>(onWork, &MyOnWorkHandler); TIdSSLIOHandlerSocketOpenSSL *SSL = new TIdSSLIOHandlerSocketOpenSSL(http); SSL->SSLOptions->SSLVersions = TIdSSLVersions() << sslvTLSv1 << sslvTLSv1_1 << sslvTLSv1_2; http->IOHandler = SSL; http->ReadTimeout = 10000; UTF8String s = http->Get(url); result = new char[s.Length()+1]; memcpy(result, s.c_str(), s.Length()+1); } __finally { delete http; } } catch (...) { return NULL; } return result; } void freedata(char *data) { delete[] data; } And then you C++Builder 6 code can use it like this: #include "mydll.h" #pragma comment(lib, "mydll.lib") // or add the .lib file to your project void OnWorkBegin(OnWorkMode AWorkMode, __int64 AWorkCountMax) { //... } void OnWorkEnd(OnWorkMode AWorkMode) { //... } void OnWork(OnWorkMode AWorkMode, __int64 AWorkCount) { //... } char *data = getdata("url", &OnWorkBegin, &OnWorkEnd, &OnWork); if (data) { // ... freedata(data); } Yes, because System::String is an alias for System::UnicodeString in CB10.3, but is an alias for System::AnsiString in BCB6. Thus, you were indeed trying to pass a wchar_t* pointer to strcpy() rather than a char* pointer. -
Or you can use {$WARN SYMBOL_DEPRECATED OFF} in the code.
-
Actually, several new ComponentPlatform enum values were introduced and old values were deprecated:
-
update indy to use tls 1.2 in c++builder 6?
Remy Lebeau replied to JeanCremers's topic in General Help
That means the DLL itself failed to load into memory, before Indy could even try to access any of its functions. Such a failure is most commonly because the DLL itself, or one of its dependent DLLs or imports, can't be found by the OS. OpenSSL build numbers are represented as letters in the English alphabet. So, 1.0.2q is build 1.0.2.17, 1.0.2u is build 1.0.2.21, etc. -
Yes. Delphi 11 shipped with the latest Indy that was available 3 months ago.
-
Actually, about 8 months ago, TIdHTTPServer was updated to now default to parsing input parameters using UTF-8 if no charset is specified in the Content-Type header. I have added that note to the StackOverflow post you linked to.
-
Please write to Embarcadero to get a free Delphi 11 edition for Andreas Hausladen
Remy Lebeau replied to PeterPanettone's topic in Delphi IDE and APIs
I have no idea, I don't use CrossVcl myself. I'm just going off of what the website say: -
Please write to Embarcadero to get a free Delphi 11 edition for Andreas Hausladen
Remy Lebeau replied to PeterPanettone's topic in Delphi IDE and APIs
Sure, by basically providing a compatibility layer that simulates the Win32 API on OSX/Linux. -
Best way to replace D11 distributed Indy with latest Git Indy?
Remy Lebeau replied to Ian Branch's topic in Indy
Not yet, because I don't have D11 installed to generate them. But anyone is more than welcome to submit a Pull Request to contribute them. Agreed (or at least rename the folder, in case you need to recover it later). That is usually the first thing I do when I install a new IDE version, and then have my projects point to the latest Indy repo source. -
Please write to Embarcadero to get a free Delphi 11 edition for Andreas Hausladen
Remy Lebeau replied to PeterPanettone's topic in Delphi IDE and APIs
Borland tried that once, with Kylix in Delphi 6. It was basically VCL for Linux, and it was a big failure, so it got dropped. VCL is just too dependent on Windows to go cross-platform. Hence why we have FireMonkey now for that task, which has no real relation to VCL, other than a few shared class names and public interfaces, but ultimately based on different architectures. -
update indy to use tls 1.2 in c++builder 6?
Remy Lebeau replied to JeanCremers's topic in General Help
The latest version of Indy 10 (https://github.com/IndySockets/Indy/) supports back to C++Builder 5, and can officially use OpenSSL DLLs up to 1.0.2u (for OpenSSL 1.1.x+, use this WIP code). TLS 1.2 has been available in OpenSSL since 1.0.1, and Indy 10 has supported TLS 1.2 for a long time. OpenSSL DLLs are available at https://github.com/IndySockets/OpenSSL-Binaries (https://indy.fulgan.com/SSL/ is retired). If you are getting errors from Indy's standard TIdSSLIOHandlerSocketOpenSSL component when it tries to load the DLLs, then you are likely using DLLs that are not compatible with your version of Indy. You can call Indy's WhichFailedToLoad() function in the IdSSLOpenSSLHeaders unit to find out why the DLLs are failing to load. -
ExtractHeaderFields with special characters
Remy Lebeau replied to chkaufmann's topic in Network, Cloud and Web
Which version of Delphi is that other app written in, and what version of Indy is it using? TIdMultipartFormDataStream encodes non-ASCII characters in all field names and filenames according to RFC 2047, which your earlier example is NOT encoded as, so I doubt the example is coming from Indy, unless maybe it is a really old version. On Windows, depending on what the OS system language is set to, TIdMultipartFormDataStream uses either UTF-8 or the OS language as the charset to encode characters to bytes. And then depending on the charset used, it uses either Quoted-Printable or Base64 to encode those bytes in the Content-Disposition header. These values are reflected in the HeaderCharSet and HeaderEncoding properties of each TIdFormDataField object that the TIdMultipartFormDataStream.Add(...) methods create. Double-check what these values are actually being set to on your system, but you can also set them yourself as needed. I would suggest using HeaderCharSet='utf-8' and HeaderEncoding='B', eg: var mPartStream := TIdMultiPartFormDataStream; field: TIdFormDataField; ... mPartStream := TIdMultiPartFormDataStream.Create; FHttp.Request.ContentType := mPartStream.RequestContentType; for ix := 0 to FPostNames.Count -1 do begin if FPostFiles[ix].IsNull then begin field := mPartStream.AddFormField(FPostNames[ix], FPostValues[ix], 'UTF-8'); field.ContentTransfer := '8bit'; end else begin field := mPartStream.AddFile(FPostNames[ix], FPostFiles[ix].PathName, FPostContentTypes[ix]); end; field.HeaderCharSet := 'UTF-8'; field.HeaderEncoding := 'B'; end; Though, I suspect even this will not give you the end result you are looking for with ExtractHeaderFields(), if it is really trying to url-decode fields that are not url-encoded to begin with. HTTP does not use url-encoding in header content, so what you are experiencing really sounds like a logic bug in the HttpApp framework. But at least this should give your code access to the stream's encoded Base64 data, which you can then decode manually to a Unicode string, such as with Indy's DecodeHeader() function in the IdCoderHeader unit. -
Interfaces defined in base classes
Remy Lebeau replied to santiago's topic in RTL and Delphi Object Pascal
No, it is not a valid cast, in this case. Obj is declared as IInterface, so it is pointing at the IInterface portion of the TMyClass object. But the object also has other portions in it, for TMyBaseClass, TInterfacedObject, IMyInterface, etc (not drawn exactly as the compiler lays it out, but you should get the idea): ------------------- | TMyClass | | ---------------- | <- Obj points here | | IInterface | | | ---------------- | | ---------------- | | | IMyInterface | | | ---------------- | | ... | ------------------- You are type-casting Obj AS-IS from IInterface to IMyInterface, which tells the compiler to MIS-interpret Obj as pointing to the IMyInterface portion of the object EVEN-THOUGH it is actually pointing at the IInterface portion of the object. Whereas the 'as' operator and Support() function, which use QueryInterface() internally, will return a pointer that properly points to the IMyInterface portion of the object, eg: ------------------- | TMyClass | | ---------------- | <- IMyInterface(Obj) points here | | IInterface | | | ---------------- | | ---------------- | <- (Obj as IMyInterface) points here! | | IMyInterface | | | ---------------- | | ... | ------------------- So, when you call IMyInterface(Obj).DoesNothing(), you are calling DoesNothing() on an invalid IMyInterface, so it does not access the correct area of the TMyClass object. In order for the compiler to access the members of a TMyClass object through an IInterface pointer, an IMyInterface pointer, a TMyBaseClass pointer, etc, the pointer has to be ADJUSTED according to the offset of the pointer's dereferenced type in relation to the implementation class. The compiler knows the offset of the IInterface portion of TMyClass, so given an IInterface pointer it knows how to adjust that pointer to reach TMyClass. Same with IMyInterface, etc. Thus, it adjusts a pointer according to the pointer's DECLARED type. So, if you start out with an invalid pointer to begin with, those adjustments are not performed correctly, and you end up with bad behaviors, such as crashes, corrupted data, etc. That works only if SomeVariable is pointing at the memory address where a valid IWhatever exists. Because you altered the layout of the object in memory, but didn't update your pointer usage accordingly. -
The only way that can happen is if the HTTP server is closing its end of the TCP connection prematurely before the end of the response has been sent. If the server wants to use a disconnect to signal end-of-response (which is a valid use-case), it has to indicate that up-front in the HTTP response headers, in which case TIdHTTP would simply handle the disconnect internally and your code would not see this error. So, the only way this error can reach your code is if the disconnect is unexpected. No, you don't need to do that in this case, since you are destroying the TIdHTTP object after sending a single HTTP request. That earlier advice only applies if you were reusing the TIdHTTP object for sending multiple HTTP requests. And even then, under ideal conditions, you still should not need to manually disconnect and clear the buffer, TIdHTTP should be handling that internally for you. Also, your CheckUrl() appears to be unnecessary. Just request the URL unconditionally, and handle any errors it may raise.
-
ExtractHeaderFields with special characters
Remy Lebeau replied to chkaufmann's topic in Network, Cloud and Web
That header is malformed. HTTP headers simply can't have un-encoded non-ASCII characters like that. There are competing standards for how they need to be encoded, though. There is RFC 2183, RFC 2047, RFC 7578, RFC 8187, HTML5, etc. TURLEncoding decodes %HH sequences into bytes, and then charset-decodes those bytes into Unicode. IIRC, it expects the bytes to be UTF-8 encoded by default. -
Mixing of VCL and FMX together in the same project is NOT officially supported. There are 3rd party solutions to make it work, but out of the box this is a fluke if it actually works.