Jump to content

Remy Lebeau

Members
  • Content Count

    2338
  • Joined

  • Last visited

  • Days Won

    95

Everything posted by Remy Lebeau

  1. Remy Lebeau

    curl-example for POST works, Delphi code throws an 404

    On a side note, you are leaking the SSLIOHandler object. You are not assigning it an Owner, so you need to Free() it. Otherwise, I suggest assigning the TIdHTTP at its Owner, eg: var HTTP := TIdHTTP.Create(nil); try var SSL := TIdSSLIOHandlerSocketOpenSSL.Create(HTTP); SSL.SSLOptions.SSLVersions := [sslvTLSv1_2]; HTTP.IOHandler := SSL; HTTP.Request.CustomHeaders.Values['Authorization'] := 'Bearer ' + bearer; var Params := TIdMultiPartFormDataStream.Create; try filename := StringReplace(Training.filename, '.ictt', '.fit', [rfIgnoreCase]); params.AddFile('file', filename); ResponseStr := HTTP.Post('https://pushinglimits.club/api/oauth/upload_single_fit_file', Params); finally Params.Free; end; finally HTTP.Free; end;
  2. Remy Lebeau

    curl-example for POST works, Delphi code throws an 404

    Did you notice the URL is different in the response HTML? The leading /api was removed. That implies to me (without proof to the contrary - does TNetHTTPClient offer any kind of debug output?) that the server probably didn't like something about the initial request and issued an HTTP redirect to a new URL that happens to not exist. Sounds like a problem with the way the server is processing TNetHTTPClient's reequest, considering the same request in TIdHTTP works.
  3. Remy Lebeau

    Using inline variables inside loops

    You probably nailed it right. It would make sense to have each loop iteration create a separate instance of the anonymous method and let it capture the inline variables that are local to its containing loop body. But as Dalija explained, that is not what happens. Probably a left-over from when anonymous procedures were introduced and inline variables didn't exist yet, so they just captured variables from the top of the containing function. Now inline variables need more stack frame management, and anonymous procedures haven't caught up to that reality yet.
  4. Remy Lebeau

    Using inline variables inside loops

    FYI, the code shown is declaring two separate LPair variables. Get rid of the 1st one, its not being used. The code shown will not work, because of the way anonymous procedures capture variables not values: Anonymous Methods in Delphi: Anonymous Methods Variable Binding Yes, that would be the solution, eg: procedure AddToList(AKey: string); begin FList.Add( procedure begin FDict.Remove(AKey); end); end; for var LPair in FDict do begin AddToList(LPair.Key); end;
  5. And, what if the LAN configuration has to be changed in the future? Why not simply have a field in the app's configuration to specify the location?
  6. Remy Lebeau

    I need a foldable/collapsible panel

    Do you have the source code for TFoldPanel? If so, why not simply update it to support Styles?
  7. Remy Lebeau

    TIdHL7.SynchronousSend does not respect timouts

    I use the "Attach to Process" approach when debugging my services. Also, if I want to debug the service's startup logic, I pass in a particular startup parameter via the SCM, and then add code in the service's OnStart event to look for that parameter and if present then hold the service in csStartPending state until the debugger attaches.
  8. Remy Lebeau

    Load DLL from resource, bypassing a file?

    That is correct. That is simply how Windows operates. Correct, and it would not really be much faster anyway. You can't just use a DLL as-is in memory, as there are fixups and relocations and such that have to be performed during the load process to make sure the DLL can actually function correctly. There are 3rd party DLL loaders that can operate on a memory block, but they are dangerous to use, and can't operate on a read-only resource anyway, so you would have to extract the DLL to writable memory first. So you are better off just using a disk file and letting Windows do its job normally. That is another reason not to use in-memory DLL loaders. Do you really need to store the DLLs in your EXE to begin with? That is just going to bloat the EXE and make more work for Windows when it is loading the EXE. Why can't you just deploy the DLLs alongside your EXE instead? If you need to distribute a single file, use an installer or self-extracting zip archive or similar.
  9. Remy Lebeau

    iOS 17, Delphi 11.3, TidTCPClient, CP1251

    Ok FYI, the whole point of setting the IOHandler.DefStringEncoding property is so you don't need to keep specifying an encoding on every subsequent read/write string operation on the IOHandler, like you are doing. That said, where is your call to Connect()? You don't need to call CreateIOHandler() if you set the DefStringEncoding after Connect() exits successfully. In any case, the code shown is fine as far as encodings are concerned, so the error has to be caused by an underlying failure of the newer OS, or a bug in the RTL. Either way, try using the charset name via IndyTextEncoding('Windows-1251') or GetCharsetEncoding('Windows-1251') instead of using the codepage number via IndyTextEncoding(1251). If those still fail, then the latter one provides a GIdEncodingNeeded event so you can provide Indy with your own class that implements the IIdTextEncoding interface, so you can do your own encoding/decoding of the CP1251 data (which is fairly trivial using a simple lookup table via https://en.m.wikipedia.org/wiki/Windows-1251)
  10. Remy Lebeau

    iOS 17, Delphi 11.3, TidTCPClient, CP1251

    What does the call stack look like when the error occurs? What is your code doing that it is trying to instantiate an Indy encoding that is not working correctly with CP1251?
  11. Remy Lebeau

    iOS 17, Delphi 11.3, TidTCPClient, CP1251

    Clearly it is, since the user is seeing an Indy error message. Which function are you referring to? The failing code is calling LocaleCharsFromUnicode(), which is an RTL system function.
  12. Remy Lebeau

    TIdHL7.SynchronousSend does not respect timouts

    I didn't write TIdHL7 and I'm not familiar with how the HL7 protocol works. I'll have to look into what is going on. I've opened a ticket on Indy's GitHub: https://github.com/IndySockets/Indy/issues/501
  13. Remy Lebeau

    Rad 12 Beta - Link to News

    https://delphiworlds.com/2023/09/yukon-is-coming/ https://dalijap.blogspot.com/2023/09/coming-in-delphi-12-disabled-floating.html https://blog.marcocantu.com/blog/2023-09-yukonbeta-stringliterals.html MVPs were given permission to start blogging just a few days ago, but they have to be approved by Embarcadero before they're published. so I'm sure there will be more blog posts coming soon.
  14. Remy Lebeau

    Indy FTP Server with TLS/SSL

    This approach is incorrect. This forces ALL connections to use SSL/TLS implicitly at connect-time. But clients may want to use SSL/TLS explicitly instead, ie via an AUTH or CCC command. The CORRECT way to handle the PassThrough is to let TIdFTPServer manage it for you. You should not be setting it manually yourself at all. If TIdFTPServer.UseTLS is set to utNoTLSSupport then TIdFTPServer will not touch PassThrough at all, and neither should you. If TIdFTPServer.UseTLS is set to utUseRequireTLS or utUseExplicitTLS then TIdFTPServer will set PassThrough according to client commands. You don't need to do anything extra for this. The difference between them is that utUseExplicitTLS allows the client to decide whether SSL/TLS is used, whereas utUseRequireTLS will reject various operations if the client doesn't use SSL/TLS. If TIdFTPServer.UseTLS is set to utUseImplicitTLS than you need to use the TIdFTPServer.OnQuerySSLPort event to tell the server which port(s) are to use SSL/TLS implicitly (ie, to set PassThrough at connect-time),
  15. Remy Lebeau

    [ EIdTLSClientTLSHandShakeFailed ] SSL negotiation failed

    There are some at https://github.com/IndySockets/OpenSSL-Binaries, though those might be for Android not Linux (though Android runs on top of Linux). Otherwise you'll have to look around. You can simply put them in your app's folder, or anywhere else you want. If needed, Indy has an IdOpenSSLSetLibPath() function in the IdSSLOpenSSLHeaders unit. I don't know at this time. I have discussed this matter with Marco Cantu and others, so they are certainly interested in a resolution, and are aware of the PR on GitHub. They are likely going to ship an up-to-date version of Indy's main code with Delphi 12 (see disclaimer below!), but whether they include the PR code in some form is unclear at this time. It is a pretty big PR, and is not incorporated into the main code. I suggested maybe putting the PR code into a new package. Marco suggested maybe providing it as an optional add-on via GetIt, but that is something they would have to setup on their end, if at all. Disclaimer: This blog post is based on a pre-release version of the RAD Studio software and it has been written with specific permission by Embarcadero. No feature is committed until the product GA release.
  16. Remy Lebeau

    [ EIdTLSClientTLSHandShakeFailed ] SSL negotiation failed

    Hmm, that should say EIdOSSLCouldNotLoadSSLLibrary instead of General Exception. But at least the root cause is now known. Indy dynamically loads OpenSSL at runtime on most platforms, including Linux. You are seeing the error when Indy is not able to load OpenSSL at runtime. In one of those screens, I see libssl.so.3 and libcrypto.so.3 shown. Those are the OpenSSL libs, but are they for OpenSSL v3.0? If so, that version is not compatible with TIdSSLIOHandlerSocketOpenSSL. By default, Indy loads unversioned .so files before loading versioned files. If those unversioned files are symlinks that map to newer versions, you could get the load error. On 'Nix platforms, Indy has IdOpenSSLSetCanLoadSymLinks() and IdOpenSSLSetLoadSymLinksFirst() functions in the IdSSLOpenSSLHeaders unit. You can set them to False at runtime before using Indy, that way it load the versioned .so files first/only, and then you can deploy OpenSSL v1.0.2 .so files with your app that are currently compatible with Indy. If that is not an option, then you can try this WIP SSLIOHandler for newer OpenSSL versions (not sure if it supports v3.0 or Linux, though) instead of TIdSSLIOHandlerSocketOpenSSL. In any case, one way to handle this error condition a little better in TIdSSLIOHandlerSocketOpenSSL is to call Indy's LoadOpenSSLLibrary() function from the IdSSLOpenSSL unit during your app's startup. If it fails, you can use Indy's WhichFailedToLoad() function from the IdSSLOpenSSLHeaders unit to help diagnose why it failed.
  17. Remy Lebeau

    [ EIdTLSClientTLSHandShakeFailed ] SSL negotiation failed

    EIdTLSClientTLSHandShakeFailed is an outer exception raised when an earlier exception is caught during the TLS handshake. What does its InnerException say was the initial error? What are the actual values you are using? In particular, which Port are you TRYING to connect to, and which Port is it ACTUALLY connecting to? I notice that you are assigning the Port first, then assigning the IOHandler and UseTLS after. Depending on the particular Port value, the UseTLS setter MIGHT be changing the Port to a different value. Try setting the Port after setting UseTLS, to make sure you are actually using the Port you are expecting. Aside from that, does the server in question still support TLS 1.1/1.2? Some servers have made the jump to requiring TLS 1.3 nowadays.
  18. Remy Lebeau

    TIdHL7.SynchronousSend does not respect timouts

    XE4 was released 10 years ago. And TIdHL7 specifically got a major revamp from its original author a year ago. So, you should upgrade to the latest Indy (if not to a modern Delphi) and see if the problem still occurs.
  19. Remy Lebeau

    TidTcpSver hangs while Stopping.

    There is quite a lot wrong with the server code you have shown. TIdTCPServer is a multi-threaded component. The listening ports are managed in worker threads. Each connected client is handled in its own worker thread. Your management of your f_CClients list is not thread-safe, or even accurate in places. It is also redundant, as TIdTCPServer already has a thread-safe list of connected clients in its Contexts property. You should just get rid of your f_CClients list altogether and use the Contexts list by itself. You can store your tCClient objects in the TIdContext.Data property, or you can derive it from TIdServerContext and then set it to the TIdTCPServer.ContextClass property before activating the server. You are accessing your TMemo and TListView directly in the context of each client worker thread. Any access to the UI from a worker thread must be synchronized with the main UI thread, which you are not doing at all. Use TThread.Synchronize() or TThread.Queue() (or Indy's TIdSync or TIdNotify) for that purpose. Do be careful with TThread.Synchronize()/TIdSync, though. Since they are synchronous, if you deactivate the server in the main UI thread, and then try to sync with the UI thread, you will deadlock the server. So, don't sync synchronously while deactivating the server, or do the deactivation in a separate thread so the main UI thread remains free to process sync requests. You are directly sending your QUIT commands to clients from the context of the main UI thread. In this example, you are not sending anything else to the clients, but if you were, you would potentially be overlapping any sends those clients' threads may happen to be performing at the same time, which would corrupt your communications. You must serialize access to a client's socket when sending to it across thread boundaries. It is generally best to keep your socket I/O with a given client in that client's worker thread as much as possible. In short, your server code needs a good amount of rewriting to operate safely in a multi-threaded environment.
  20. Remy Lebeau

    Migrate an old app in Delphi 2009 to modren C++

    You should be able to, as it should have the command-line Delphi compiler available, so that 3rd party components can still be compiled and installed into the IDE for C++Builder to use.
  21. Indy uses blocking sockets and synchronous I/O. The client's OnDisconnected event is fired when the *client* disconnects on its end. If the server disconnects first, there is no real-time notification of that. The client will notify your code only when the client tries to access the connection and gets an error from the OS, at which time it will raise an exception to your code, such as EIdConnClosedGracefully, etc. So, if you want timely notification of a remote disconnect, you need to actively send/read data. If your code is not using the connection for lengths of time, use a timer to poll for incoming data periodically. Or use a reading loop in a worker thread.
  22. Remy Lebeau

    End of licence Comunity edition.

    Per the CE FAQ: https://www.embarcadero.com/products/delphi/starter/faq
  23. Remy Lebeau

    Could not load OpenSSL library.

    I don't know, I thought they were done maintaining a copy, but I guess not. The readme on that mirror says:
  24. Remy Lebeau

    String literals more then 255 chars

    Influenced by C# (like several features in Delphi have been): https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-11.0/raw-string-literal
  25. It is working fine for me. Yes. My hosting provider did perform maintenance on my site's server yesterday, so maybe they messed something up, or have already resolved the issue.
×