-
Content Count
2982 -
Joined
-
Last visited
-
Days Won
134
Everything posted by Remy Lebeau
-
Best way to replace D11 distributed Indy with latest Git Indy?
Remy Lebeau replied to Ian Branch's topic in Indy
Yes, there are some Embarcadero technologies that use Indy internally, and so the installer has included Indy because of that. At one point, the techs were linked directly to the public version of Indy that shipped with the IDE, making it virtually impossible for users to update Indy without breaking those techs. But over the years, Embarcadero has updated their tech to use a private version of Indy instead (or their own libraries), so users can freely update the public version of Indy. But, there have been a few glitches in that process from time to time, causing unwanted linkages to the public Indy again. Nothing in recent years, that I recall, though. -
Best way to replace D11 distributed Indy with latest Git Indy?
Remy Lebeau replied to Ian Branch's topic in Indy
Essentially, yes - with caveats, depending on the IDE version (mostly old ones), which are documented in Indy's install instructions. I rename the pre-installed Indy folders and move the pre-installed Indy binaries to a separate folder (in case I ever need to restore them), and then I compile Indy in my own folder and install the binaries from there. That way, I can make changes to Indy and have them show up in projects/IDE. I install the IDE in the default installation path. Basically, yes. Some caveats similar to that are mentioned in Indy's install instructions, but only in relation to Embarcadero's own technologies that use Indy internally. Yup. And you have to make sure you clean up ONLY the ones that relate to Indy, and not to someone else who might have also used the "Id" prefix (albeit rare)... Cool. -
Best way to replace D11 distributed Indy with latest Git Indy?
Remy Lebeau replied to Ian Branch's topic in Indy
No, it is not optional, it is always pre-installed. Some day, in the future, I would like to get Indy into GetIt (https://github.com/IndySockets/Indy/issues/134) and out of the installer. -
IRichEditOle is the correct way to insert pictures into a RichEdit. The code should have embedded the image's data directly into the RichEdit's content, not create a link to an external file that is launched separately. If you can wrap the image in an IDataObject instead of an IOleObject, then you might try using IRichEditOle.ImportDataObject() instead of IRichEditOle.InsertObject(). I think that approach should work, provided the generated RTF content is accurate. However, in Delphi 2009+, string is UnicodeString, so the BitmapToRTF() function would need to be changed to use AnsiString or TBytes internally when preparing the RTF, since RTF is an 8-bit format. And also, since the TStringStream used to stream the RTF into the RichEdit would be holding Unicode characters, you probably need to include the SF_UNICODE flag when sending the EM_STREAMIN message. Otherwise, use a TMemoryStream instead to hold 8bit data instead of 16bit data. Also, there are 2 memory leaks in that code's Button1Click() method, Unfortunately, there is no "elegant" way, since Microsoft does not provide an "easy" API to handle this task.
-
WinSock (Indy) select() doesn't return on network
Remy Lebeau replied to aehimself's topic in Network, Cloud and Web
That encoding is really meant as just a means of transporting streaming data for a single resource, rather than pushing individual pieces of data. The response would have to be using a media type where the receiver knows each chunk carries a new piece of data that replaces old data. I'm not aware of any standard media types that use chunked encoding in that manner. But custom media types certainly could, I suppose, as long as you are in control of both sender and receiver. Also, the chunked encoding is hop-to-hop, not end-to-end, so it is subject to interference by proxies. -
Can not login to FTP server without password
Remy Lebeau replied to DMX78's topic in ICS - Internet Component Suite
The FTP protocol spec does not allow the password (or the username, or the account) to be empty, it must have at least 1 character. It is generally not a good idea to simply migrate a project from one major IDE version to another. Migrations are not always smooth. It is usually better to just create a new project fresh in the new IDE and then add your existing source files to it as needed. Did you report that issue? I don't recall seeing anything about that recently. -
WinSock (Indy) select() doesn't return on network
Remy Lebeau replied to aehimself's topic in Network, Cloud and Web
Those are certainly ways to handle server pushes, but there are also HTTP-based push models as well: multipart/x-mixed-replace (the original server push, dating all the way back to Netscape, and still supported by most browsers today). text/event-stream (built-in to HTML5). HTTP/2 (which Indy doesn't support at this time) has server pushing built-in at the protocol layer. etc... -
Can not login to FTP server without password
Remy Lebeau replied to DMX78's topic in ICS - Internet Component Suite
Yes, you are explicitly calling PassAsync() after UserAsync() is finished, regardless of its outcome. You need to pay attention the StatusCode of UserAsync() before calling PassAsync(), and make sure your password is not empty if the server requires one. No, I don't. You explicitly (and unconditionally) asked it to send a PASS command, but did not provide it with data to send. Throwing an error sounds logical to me. It is an input error on your part. All that would accomplish is to cause the server to return back a failure StatusCode, as the PASS command can't have an empty value. Well, that is your own fault, for not learning the FTP protocol before making use of it, and not having adequate error handling in your code. If you had been paying attention to the StatusCodes of your commands, you would not have been calling PassAsync() unnecessarily to begin with. -
Can not login to FTP server without password
Remy Lebeau replied to DMX78's topic in ICS - Internet Component Suite
Read RFC 959 Yes. I just checked ICS's latest code, and (while it is a bit difficult to follow) it does appear to send PASS after USER only if USER returns 331. So I don't know why your log shows PASS being sent, unless you are calling the client's Pass/Async() method yourself? It would help if you would show your actual code, and your setup of the client's properties. -
Custom Component : onDestroy delphi creates endless error messages
Remy Lebeau replied to gioma's topic in VCL
Did you make sure the rest of TComponentA's code is checking FComponentB for nil before accessing its members? It is hard to diagnose your problem without a complete example. -
Can not login to FTP server without password
Remy Lebeau replied to DMX78's topic in ICS - Internet Component Suite
Reply code 230 on the USER command means the user is fully logged in, so the PASS command should not have been sent at all. If the server had actually wanted a password, the USER command would have sent back a 331 reply code instead. -
WinSock (Indy) select() doesn't return on network
Remy Lebeau replied to aehimself's topic in Network, Cloud and Web
Under most conditions, yes. I was thinking more along the lines of when server-side pushes are used and there are delays between events, or when a client asks to use HTTP keep-alives and there are delays between requests, etc. Things where the connection is left open but sitting idle for periods of time. -
And? What exactly about the names being viewable to humans is worrisome to your employer, exactly? It is not like users will be able to USE the displayed names to do anything malicious to your code, since the actual classes and fields are converted into memory addresses, function calls, etc during compiling. You are likely just viewing the RTTI or Debug info. What is the actual CONCERN, before you waste your time trying to IMPLEMENT something that, quite frankly, can and will be worked around by anyone who actually intends to be malicious?
-
WinSock (Indy) select() doesn't return on network
Remy Lebeau replied to aehimself's topic in Network, Cloud and Web
Makes me wonder now if I should add a NATKeepAlive property to TIdHTTP, similar to what TIdFTP has. I've opened a ticket for that: https://github.com/IndySockets/Indy/issues/413 -
That would happen only if you are interpreting the actual value of the DWORD. I would just use my own timestamp (that doesn't roll over) to keep track of when the DWORD changes value between successive calls to GetLastInputInfo(), regardless of its actual value, Even if the DWORD rolls over, it is still a change in value. Even the documentation says that the DWORD is "not guaranteed to be incremental".
-
I haven't tried it recently, no. But I have used it in the past without problem.
-
One way is to run a timer that polls GetLastInputInfo() to see if the reported dwTime changes. If it doesn't change for awhile, log out. However, that is a global setting for the entire OS, and it includes keyboard input, not just mouse input. If you just want to monitor mouse activity inside your own app, another option would be to use the TApplication(Events).OnMessage event to look for WM_MOUSE... messages, resetting a timer whenever a mouse event is detected, and log out if the timer elapses.
-
WinSock (Indy) select() doesn't return on network
Remy Lebeau replied to aehimself's topic in Network, Cloud and Web
HTTP is stateless, so it is possible that the TCP connection is closed at the end of the HTTP response, in which case TIdHTTP would close the socket before DoRequest() exits. Check if the Binding.HandleAllocated property is true before calling SetKeepAliveValues(): procedure TCustomActionCallerThread.Execute; begin V_CONNECTION.IndyHttpClient.Socket.Binding.SetKeepAliveValues(True, FTCPKeepAlive, FTCPKeepAlive); Try ... Finally if V_CONNECTION.IndyHTTPClient.Socket.Binding.HandleAllocated then V_CONNECTION.IndyHTTPClient.Socket.Binding.SetKeepAliveValues(False, 0, 0); End; end; In fact, because HTTP is stateless, it is possible that there is no TCP connection yet when DoRequest() is called, in which case TIdHTTP would have to call Connect() internally. So, you will have to account for that, as well: procedure TCustomActionCallerThread.Execute; begin if V_CONNECTION.IndyHTTPClient.Socket.Binding.HandleAllocated then V_CONNECTION.IndyHttpClient.Socket.Binding.SetKeepAliveValues(True, FTCPKeepAlive, FTCPKeepAlive); Try ... Finally if V_CONNECTION.IndyHTTPClient.Socket.Binding.HandleAllocated then V_CONNECTION.IndyHTTPClient.Socket.Binding.SetKeepAliveValues(False, 0, 0); End; end; In case there is no TCP connection yet before DoRequest() is called, you would have to use TIdHTTP's OnSocketAllocated, OnAfterBind, OnConnected, or OnStatus event to know when the Binding has a new socket assigned before you can then call SetKeepAliveValues() on it (there are no events to indicate when each HTTP request is started/finished). That is not a guarantee. An HTTP keep-alive is a request from the client to the server, but the server is not obligated to honor that request. It is the server's decision whether the TCP connection stays open or not after the response is sent. Look at the TIdHTTP.Response.KeepAlive property after DoRequest() exits, if it is false then TIdHTTP would have closed the socket. In recent years, I don't know which Indy revision has gone into each IDE release. When Indy was using SVN, I would tag each revision that Embarcadero released. But after Indy switched to GitHub (consequently losing its build numbers), I haven't been tagging the releases anymore. I do know that there were like a dozen checkins made to Indy between Delphi 10.4.0, 10.4.1, and 10.4.2. But offhand, I don't see anything in the change history that should affect handling of the underlying socket as you describe. However, Indy's source code is included with each IDE release, so you should be able to do a local diff between the versions. -
Delphi does not call that function, so something in your project must be. Depending on where that is, and how it is implemented, you might be able to enable delay-loading for it, and then use a hook to redirect it to a different function that is either a no-op or uses older APIs to simulate similar functionality.
-
Application.CreateForm : Shows Main form before Application.run
Remy Lebeau replied to gioma's topic in VCL
That can be simplified: Application.ShowMainForm := (Pos('-NOSHOW', UpperCase(CmdLine)) = 0); Or: Application.ShowMainForm := not FindCmdLineSwitch('NOSHOW'); I wouldn't even bother calling Terminate() and Run() in that case, just exit immediately instead: begin Application.Initialize; Application.Title := 'Some App'; Application.CreateForm(TfrmMainForm, frmMainForm); if (not frmMainForm.DoLogonScreen) then Exit; Application.Run; end. Or: begin Application.Initialize; Application.Title := 'Some App'; Application.CreateForm(TfrmMainForm, frmMainForm); if frmMainForm.DoLogonScreen then Application.Run; end. Of course, it would be better to not even create the MainForm at all if you are not going to use it, eg: begin Application.Initialize; Application.Title := 'Some App'; if DoLogonScreen then begin Application.CreateForm(TfrmMainForm, frmMainForm); Application.Run; end; end. -
Application.CreateForm : Shows Main form before Application.run
Remy Lebeau replied to gioma's topic in VCL
Just on a side note: the RTL has a FindCmdLineSwitch() function in the SyUtils unit: if FindCmdLineSwitch('NOSHOW') then -
Although that is technically correct, that has no bearing on this issue. Skrim is able to send emails in general, so they already have valid authentication. The issue is just that some of the emails are being rejected while others are not. That has nothing to do with authentication.
-
I've never seen that error before. I can't even find any mention of it online, either. Indy does not generate any MessageIDs of its own (there is a piece of code commented out at the end of TIdMessage.GenerateHeader() for that). The generation of a new MessageID is typically handled by the initial SMTP server that receives the email. However, a client can specify a MessageID if it wants to when sending a new email (ie, via the TIdMessage.MsgId property), but there is no guarantee that the initial SMTP server won't overwrite it (some servers do).
-
Sure, if you use the Form's HWND for sending/posting updates. A better option would be to use a persistent HWND that doesn't get recreated, such as the TApplication::Handle, or the result of calling AllocateHWnd(). Otherwise, don't even use an HWND at all, for instance use TThread::Synchronize() or TThread::Queue() instead.