-
Content Count
3000 -
Joined
-
Last visited
-
Days Won
135
Everything posted by Remy Lebeau
-
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.
-
That is not a good design. You should move the long calculation to a separate worker thread instead, and then exit the OnClick handler. Have the thread post updates to the UI thread if needed. And you can disable your UI while the thread is running, and then re-enable it when the thread is finished. Never block the UI thread, and avoid using Application->ProcessMessages() whenever possible, it causes more problems than it solves. Let the UI thread run normally. By doing that switching, the modal Form likely lost input focus and wasn't the "active" Form anymore at the time when MessageBox() was called, which likely ended up with the MessageBox dialog becoming owned by either another Form's window, or the hidden TApplication window. That would account for why the MessageBox dialog was allowed to go behind your modal Form. The modal Form's window needs to be the owner of the MessageBox dialog in order for the dialog to stay on top of that Form. Which means, you need to either call the Win32 MessageBox() (or TaskDialog/Indirect()) function directly so you can explicitly pass in the desired owner window, or else use the TApplication/Events::OnGetActiveFormHandle event to provide the desired owner window even if the Form is not "active".
-
TDirectory.GetFiles is listing the contents of Packages such as PhotosLibrary
Remy Lebeau replied to Incus J's topic in RTL and Delphi Object Pascal
Unfortunately, I see nothing in Delphi that would allow you to use that flag in this situation. TDirectory.GetFiles() is just a wrapper for a typical SysUtils.FindFirst/Next() loop, so it handles whatever files and directories that loop would normally report. If a Package file is treated as if it were a directory (ie FindFirst/Next() returns TSearchRec.Attr with the faDirectory flag set), then TDirectory.GetFiles() is going to recurse into the Package's content if the SearchOption parameter is set to soAllDirectories (as it is in your example). Also, more importantly, FindFirst/Next() simply don't use the FileManager API to enumerate files, they use the POSIX opendir() and readdir_r() functions instead, which have no such skip-Package flag available. Unfortunately, the TDirectory.GetFiles() predicate is only called for files and not for directories (ie, only for items that do not have the faDirectory attribute). Which makes sense, since TDirectory.GetFiles() is looking for only files to add to its output array, so there is no point in it filtering out directories. To prevent TDirectory.GetFiles() from recursing into Packages automatically, you would have to call it with its SearchOption parameter set to soTopDirectoryOnly (which is its default value), and then manually call TDirectory.GetFiles() for any non-Package sub-directory you are interested in. Of course, TDirectory.GetFiles() won't report directories to you, so you would have to use a separate call to TDirectory.GetDirectories() (with SearchOption=soTopDirectoryOnly) and filter out the Packages as needed. Which means, your enumeration time is going to double from having to scan each directory twice. So, in this case, you will likely have to use the FileManager API directly, and not use TDirectory at all. -
To the Application->OnGetActiveFormHandle event, not to the Application->FOnGetActiveFormHandle data member. But yes, you get the idea. Not set a Form as active, no. The RTL is querying you to choose which Form window should be considered "active" at that moment. So, you would need to enumerate your existing Forms and decide which one you want the MessageBox to be on top of. But you don't actually make that Form window be focused. The RTL is merely establishing a Z-Order relationship between the MesageBox and its Owner window. It is not moving input focus around.
-
Agreed. I never understood why they did that in the first place, and why it was never updated to use String parameters instead.
-
[Solved] Can't build project using TJson
Remy Lebeau replied to Alexander I.'s topic in General Help
Why would it? If all you did was add an #include statement to your code, the IDE is not smart enough to know which library to automatically add to the project to make the code in that header file link correctly. It doesn't even know what code is in that header file until the compiler is invoked, and by then it is too late. The IDE can do automatic linkage of libraries only for components that are dropped on a Form/Frame/DataModule in the Designer. Did you do that for the REST components? I'm guessing no. But this issue is not specific to just REST, it applies to any library. For non-designtime code, you are responsible for setting up your project with any necessary library references as needed. -
[Solved] Can't build project using TJson
Remy Lebeau replied to Alexander I.'s topic in General Help
You are not linking to the BPL library that implements TJson. Try adding a reference to the RESTComponents.bpi file to your project. -
Which *should* be returning the modal Form's window, if the modal Form has focus at the time TApplication.MessageBox() is called. It should be noted that if no *active Form* window is found, then TApplication.MessageBox() uses the hidden TApplication window, which is what allows the MessageBox dialog to appear behind Form windows. You could alternatively just call the Win32 MessageBox() API directly (or TaskDialog/Indirect() instead), specifying the desired Form window as its owner window.