Jump to content

Remy Lebeau

Members
  • Content Count

    2892
  • Joined

  • Last visited

  • Days Won

    128

Everything posted by Remy Lebeau

  1. Remy Lebeau

    File Search

    AddStrings() has an overload that takes a TArray<string> instead of a dynamic "array of string" (even in 10.2 Tokyo), eg: type //TMyArrToStoreTheResulted = array of string; TMyArrToStoreTheResulted = TArray<string>;
  2. That is an extremely old version of OpenSSL. You should be using openssl-1.0.2u-i386-win32.zip instead. Or, you can use this SSLIOHandler (work in progress) and then you can use a newer OpenSSL 1.1.x version instead.
  3. Remy Lebeau

    File Search

    If the root path already has a '\' on the end of it, you would be adding another '\' unnecessarily. Better to use IncludeTrailingPathDelimiter() instead, eg: LContinue := FindFirst(IncludeTrailingPathDelimiter(AFolderRoot) + APatternToSearch, faAnyFile, LSearchRecord) = 0; That comparison wont work correctly if the file name begins with any character that is lexicographically less-than '.' (a few of them are reserved, but many of them are not), namely: ! # $ % & ' ( ) + , - You need to check for '.' and '..' specifically instead, eg: if (LSearchRecord.Name = '.') or (LSearchRecord.Name = '..') then
  4. Most servers are phasing out TLS 1.0, or already have, You should enable TLS 1.1 and TLS 1.2 as well: IdSSLIOHandlerSocketOpenSSL1.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2]; If you allow the Port to be configurable, you should also allow the UseTLS value to be configurable as well. There is a functional difference between utUseImplicitTLS vs utUsseExplicitTLS, so you should let your config indicate which to use on a non-default Port. As mentioned earlier, this is wrong. You need to use utUseImplicitTLS on port 465. Use utUseExplicitTLS on port 587 instead.
  5. Remy Lebeau

    Delphi 11.3 - Indy - OpenSSL 3.1

    That zipped code was submitted by another user on a comment to the open PR in Indy's repo. I don't think that code was every merged into the repo where the PR originates from: https://github.com/mezen/Indy/tree/NewOpenSSL_PR (see https://github.com/mezen/Indy/issues/12).
  6. Remy Lebeau

    Assigning UTF-8 to a control

    Makes sense, because by default assigning a raw char* string to a UnicodeString has no way of knowing that the char string is encoded as UTF-8, so it assumes the string is encoded as ANSI instead. You might try using SetMultiByteConversionCodePage(), but it would be better to put the UTF-8 char sequence inside of a UTF8String object instead, eg: Edit1->Text = UTF8String("\xf0\x9f\x98\x82"); More generically, you can use RawByteString for handle any 'char'-based encoding: RawByteString str("\xf0\x9f\x98\x82"); SetCodePage(str, CP_UTF8, false); Edit1->Text = str; The RTL knows how to convert a UTF8String/RawByteString to a UnicodeString, and vice versa.
  7. Remy Lebeau

    Need to convert a string number to an integer

    void __fastcall TForm1::Button1Click(TObject *Sender) { int x = Sysutils::StrToInt(Edit1->Text); // alternatives: // int x = Edit1->Text.ToInt(); // int x = std::stoi(Edit1->Text.c_str()); // int x = CSpinEdit1->Value; (using a TCSpinEdit instead of a TEdit) int y = Sysutils::StrToInt(Edit2->Text); // same as above... int sum = x + y; Label3->Caption = _D("The sum is ") + String(sum); // alternatives: // Label3->Caption = Sysutils::Format(_D("The sum is %d", ARRAYOFCONST((sum)) ); // Label3->Caption = String{}.sprintf(_D("The sum is %d", sum); // Label3->Caption = std::format(L"The sum is {}", sum).c_str(); // Label3->Caption = (std::wostringstring{} << L"The sum is " << sum).str().c_str(); }
  8. Remy Lebeau

    TProcessList issue.

    Yes, it reallocates when its Capacity is exceeded. And, it uses an array internally. But, that reallocation won't happen on every add, since the Capacity grows algorithmically (see SysUtils.GrowCollection()). It is very inefficient to reallocate on every add.
  9. Remy Lebeau

    Community license

    Have you considered setting up a personal VPN on your home network, and then connect to it from your work office?
  10. Remy Lebeau

    TProcessList issue.

    Not really. Your way reallocates the array on every item added. Whereas TList has a Capacity so it doesn't reallocate on every individual add, and then the final array is allocated only 1 time based on the TList's final Count.
  11. Remy Lebeau

    TProcessList issue.

    Use the Length() function. Use this instead: for var i := 0 to Length(Instances)-1 do Memo1.Lines.Add(Instances[i]); Alternatively, you can use the Low()/High() functions to get the first and last indexes of the array: for var i := Low(Instances) to High(Instances) do Memo1.Lines.Add(Instances[i]); Alternatively, you can use a for..in loop instead, no indexes needed: for var elem in Instances do Memo1.Lines.Add(elem); However, in your particular example, the TMemo.Lines property has an overloaded method that accepts a TArray<string> as input, so you don't even need a loop at all: Memo1.Lines.AddStrings(Instances); You don't need that. Dynamic arrays know their own length.
  12. Remy Lebeau

    TProcessList issue.

    Delphi does not have any native classes named TProcess or TProcessList. Your example is clearly based on 3rd party code that you don't have installed, which is why the classes are undefined.
  13. Remy Lebeau

    Why is the TCustomDrawState set empty?

    Whitespace between tokens doesn't matter in C/C++. Thus, "Type* VarName" and "Type *VarName" and "Type * VarName" all mean the same thing.
  14. Remy Lebeau

    Convert line endings on paste?

    Not that I'm aware of. But its funny, because the RTL does have an AdjustLineBreaks() function, so it would have been trivial for the IDE to adjust pasted text to the editor's native format.
  15. Remy Lebeau

    Intercept "WM_COPY" on Windows

    COleDataSource is just a Microsoft C++ helper class that implements the IDataObject interface, which can be put on the clipboard using the OleSetClipboard() function. In Delphi, you would have to implement the IDataObject interface manually (it is declared in the Winapi.Ole2 unit), or use a 3rd party implementation, such as from Melanders' Drag&Drop suite (probably via TDropEmptySource+TDataFormatAdapter).
  16. Remy Lebeau

    Intercept "WM_COPY" on Windows

    All the more reason to try the route I suggested. Application A could send its file list to Application B, then B can immediately put CFSTR_FILEDESCRIPTOR and CFSTR_FILECONTENTS items on its local clipboard for each file, having each CFSTR_FILECONTENTS hold an IStream to access its file data. Then, when the user pastes the clipboard somewhere (or an app reads the clipboard directly), the individual CFSTR_FILECONTENTS streams can/will be read from, which can then transfer the actual file data from machine A to B as needed. You could even go as far as having A transfer the file data to B in the background while waiting for a paste to happen, caching the data locally on B, and when CFSTR_FILECONTENTS is read from it can read from the local cache if available, otherwise initiate/wait-for the transfer to finish (even provide the data while it is begin transferred). When the clipboard gets cleared, the IStream's will be released, and their destructors can cancel any transfers in progress and delete any local caches as needed. There are examples/tutorials online about working with CFSTR_FILEDESCRIPTOR/CFSTR_FILECONTENTS, for instance: https://www.codeproject.com/Articles/15576/How-to-drag-a-virtual-file-from-your-app-into-Wind https://www.codeproject.com/Articles/23139/Transferring-Virtual-Files-to-Windows-Explorer-in I'm sure they have, but it is very specialized work, so you are not likely to see it talked about publicly very much.
  17. Remy Lebeau

    Intercept "WM_COPY" on Windows

    That is the OLD way to monitor the clipboard. Since Vista, the NEW way is using a Clipboard Format Listener instead, registered via AddClipboardFormatListener() and handling WM_CLIPBOARDUPDATE messages. Have you read Microsoft's documentation on Transferring Shell Objects with Drag-and-Drop and the Clipboard and Handling Shell Data Transfer Scenarios yet? Per Shell Clipboard Formats, you will likely want to implement the CFSTR_FILEDESCRIPTOR and CFSTR_FILECONTENTS formats. That way, you can put descriptions of the files onto the clipboard, and when they are pasted then you can stream in the actual file data as needed.
  18. Remy Lebeau

    Error using Indy

    When your code is calling TIdHTTP.Post(), if it catches any non-HTTP exception, it is reading the TIdHTTP.ResponseCode property, which won't have a valid number in that case and so returns -1. Indy does, in fact, raise an exception if the OpenSSL DLLs are missing or otherwise are unable to be loaded - EIdOSSLCouldNotLoadSSLLibrary. After that exception is raised, you can call Indy's WhichFailedToLoad() function in the IdSSLOpenSSLHeaders unit, and it will tell you whether the DLLs themselves could not be loaded, or whether any of the required exports are missing (ie, because the DLLs are the wrong version for what Indy is expecting). There are other exception classes you can catch for other OpenSSL-related errors, too. Most of them derive from either EIdOpenSSLAPISSLError or EIdOpenSSLAPICryptoError, both of which provide error codes. For example: try FidHttp.Post(FURL, Params, FResponse); FResponseCode := FidHttp.ResponseCode; FResponse.Seek(0, soFromBeginning); except on E: EIdHTTPProtocolException do begin FResponseCode := E.ErrorCode; ErrorEvent(Self, 'HTTP Protocol Exception:' + #$D#$A + AdjustLineBreaks(E.ErrorMessage, tlbsCRLF)); ErrorEvent(Self, 'HTTP Protocol RawHeaders=' + #$D#$A + FidHttp.Request.RawHeaders.Text); end; on E: EIdOSSLCouldNotLoadSSLLibrary do begin FResponseCode := -1; // or whatever you want ErrorEvent(Self, 'SSL/TLS Library Exception: ' + E.Message); ErrorEvent(Self, 'SSL/TLS Didnt Load=' + #$D#$A + WhichFailedToLoad); end; on E: EIdOpenSSLAPISSLError do begin FResponseCode := -1; // or whatever you want ErrorEvent(Self, 'SSL/TLS API Exception: [' + E.ClassName + '] ' + E.Message); ErrorEvent(Self, 'SSL/TLS API ErrorCode=' + IntToStr(E.ErrorCode)); ErrorEvent(Self, 'SSL/TLS API RetCode=' + IntToStr(E.RetCode)); end; on E: EIdOpenSSLAPICryptoError do begin FResponseCode := -1; // or whatever you want ErrorEvent(Self, 'SSL/TLS Crypto Exception: [' + E.ClassName + '] ' + E.Message); ErrorEvent(Self, 'SSL/TLS Crypto ErrorCode=' + IntToStr(E.ErrorCode)); end; on E: Exception do begin FResponseCode := -1; // or whatever you want ErrorEvent(Self, 'Unknown Exception: [' + E.ClassName + '] ' + E.Message); end; end;
  19. Remy Lebeau

    Error using Indy

    What exactly is reporting that error? Can you provide the exact and complete error message? And what does your code look like? That is not very helpful. Anything is possible, though you should be getting a different error if that were the case. More likely, those PCs are probably running firewalls that are blocking your connection. The 2 OpenSSL DLLs, libeay32.dll and ssleay32.dll. And make sure they are for OpenSSL 1.0.2u or earlier, as TIdSSLIOHandlerSocketOpenSSL does not support newer versions. You can get those DLLs from https://github.com/IndySockets/OpenSSL-Binaries If you want to use newer DLLs, use this WIP SSLIOHandler instead.
  20. Remy Lebeau

    Question about formatting

    This is entirely a matter of personal choice. The compiler doesn't care one way or the other, it ignores whitespace between language tokens. So use whichever format is easier for you to read/write. Personally, I don't use whitespace around '->'.
  21. Remy Lebeau

    Loop a Delay in a thread??

    Seriously? Can't you just use a standard For loop? I don't understand the issue.
  22. Remy Lebeau

    Feature Request - TIdServerIOHandler.Accept

    It doesn't make sense to derive from TIdListenerThread since it is tied to TIdTCPServer and TIdScheduler. From your earlier description, it sounds like you don't even want to use TIdTCPServer at all, since you have your own threads, you just want Indy's wrappers around socket I/O, right? If that is all you need, you could try creating TIdTCPConnection and TIdSSLIOHandlerSocketOpenSSL objects and assign your own socket to the IOHandler.Binding.Handle property. I'm not saying it can't be. I'm just saying it is a new feature that should be submitted to Indy's issue tracker. On a side note: I will mention that although TIdServerIOHandlerSocket.Accept() does not use the TIdYarn parameter, TIdServerIOHandlerChain.Accept() in the SuperCore package (a dead project) did use it.
  23. Remy Lebeau

    Drawing on canvas

    Clipping is the right solution. But ClipRect() won't work for FMX. In FMX, to clip a drawing to a rectangular area, use the TCanvas.IntersectClipRect() and TCanvas.ExcludeClipRect() methods. To clip in a non-rectangular area, use TCanvas.DrawPath() and TCanvas.FillPath() instead.
  24. Remy Lebeau

    FMX-TTreeview: Intercept click on Expand-button

    Too bad FMX's TTreeViewItem doesn't have a ShowButtons property, like VCL's TTreeNode does. So unfortunately, in FMX you have no choice but to populate the immediate child nodes just for TTreeViewItem to decide for itself whether or not to display its expand button (ie, when its VisibleCount is > 0). You don't need to scan the full 2nd level right away, though. When creating a new TTreeViewItem, just scan enough to discover its 1st subfolder and then stop scanning. You can't accomplish that with any of the TDirectory methods, but you can with FindFirst()/FindNext(). Or, you could just use a dummy child node instead, no scanning needed. Either way, when the TTreeViewItem is then expanded for the first time, you can then (remove the dummy and) do a full scan of the 2nd level to finish populating the TTreeViewItem with all of the child nodes as needed.
  25. Remy Lebeau

    FMX-TTreeview: Intercept click on Expand-button

    Why not Expand() instead? That is the method which calls the OnExpanded event handler after CanExpand() says it is OK to do so. All I see available is TTreeView.ItemExpanded(), but it is not virtual, so you can't override it. Internally, TTreeViewItem has an FButton member of type TCustomButton which it assigns an OnClick handler to. That handler simply toggles the TTreeViewItem.IsExpanded property, which calls TCustomTreeView.ItemExpanded(), which doesn't fire any events about the state change into user code, AFAICS.
×