-
Content Count
2633 -
Joined
-
Last visited
-
Days Won
110
Everything posted by Remy Lebeau
-
Sending Email via GMail Using OAuth 2.0 via Indy
Remy Lebeau replied to Ugochukwu Mmaduekwe's topic in Indy
2FA is a good thing. And no, you don't actually need to authenticate every login. An app-specific password is meant to be used in only 1 location and shouldn't be passed around. You can set Google to remember where the password is being used from so you don't have to re-authenticate every time it is used from that location. I use app-specific passwords when testing Indy with GMail (POP3, SMTP, and IMAP) and don't have to re-authenticate each time. -
Sending Email via GMail Using OAuth 2.0 via Indy
Remy Lebeau replied to Ugochukwu Mmaduekwe's topic in Indy
However, you don't actually need OAuth to access GMail. You can instead go into your Google account settings and generate an Application-specific password, which works just fine with Indy. -
TThread holds an internal reference to itself (in the TThread.CurrentThread property), which under ARC ensures the thread stays alive and continues to run as expected even if all other references to the TThread object get cleared. That internal reference gets cleared when the thread stops running. However, that internal reference does not get assigned until the thread is actually running, which is why you need the extra delay on ARC systems, otherwise if ARC calls the TThread destructor, it will terminate the newly-created thread before it begins to run. Rather than using an arbitrary sleep, you should instead use a waitable event, like TEvent. Have the code that creates the TThread object wait on that event before continuing. Signal the event at the beginning of your thread's Execute(). For example: type TMyThread = class(TThread) private procedure aaaa; FStarted: TEvent; protected procedure Execute; override; public constructor Create; reintroduce; destructor Destroy; override; procedure WaitForStart; end; constructor TMyThread.Create; begin inherited Create(False); FStarted := TEvent.Create; end; destructor TMyThread.Destroy; begin FStarted.Free; inherited; end; procedure TMyThread.Execute; begin FStarted.SetEvent; ... end; procedure TMyThread.WaitForStart; begin FStarted.WaitFor(Infinite); end; procedure TForm1.Button1Click(Sender: TObject); var T: TMyThread; begin T := TMyThread.Create; T.WaitForStart; end;
-
The HTTP 206 Partial Content
Remy Lebeau replied to DarkDucke's topic in ICS - Internet Component Suite
Even though "keep-alive" wasn't standardized until HTTP 1.1, most HTTP 1.0 servers do recognize it. But either way, the "Connection" request header has nothing to do with this issue. Definitely something that should be fixed in the user's code, but again, not the root cause of the issue. The HTTP server will just ignore a "Content-Type" header in a GET request. -
The HTTP 206 Partial Content
Remy Lebeau replied to DarkDucke's topic in ICS - Internet Component Suite
The ONLY time a web server should ever send a 206 response code is if the request contained a "Range" header asking for a specific range of bytes in the response data. That doesn't make sense to do in this situation. So double check that you are not setting up your TSslHttpCli to send such a request header. TIdHTTP does not send a "Range" request header unless you explicitly ask it to, via the TIdHTTP.Request.Range(s) properties. -
Load a String from a file - returns strange char set
Remy Lebeau replied to bernhard_LA's topic in Algorithms, Data Structures and Class Design
Yes, it does: procedure TStrings.LoadFromFile(const FileName: string); var Stream: TStream; begin Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite); try LoadFromStream(Stream); finally Stream.Free; end; end; procedure TStrings.LoadFromFile(const FileName: string; Encoding: TEncoding); var Stream: TStream; begin Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite); try LoadFromStream(Stream, Encoding); finally Stream.Free; end; end; procedure TStrings.LoadFromStream(Stream: TStream); begin LoadFromStream(Stream, nil); end; procedure TStrings.LoadFromStream(Stream: TStream; Encoding: TEncoding); var Size: Integer; Buffer: TBytes; begin BeginUpdate; try Size := Stream.Size - Stream.Position; SetLength(Buffer, Size); Stream.Read(Buffer, 0, Size); Size := TEncoding.GetBufferEncoding(Buffer, Encoding, FDefaultEncoding); SetEncoding(Encoding); // Keep Encoding in case the stream is saved SetTextStr(Encoding.GetString(Buffer, Size, Length(Buffer) - Size)); finally EndUpdate; end; end; You mean TStrings, not TStringList. TMemo.Lines (aka the TMemoStrings class) derives from TStrings directly, not from TStringList. But yes, TStrings.LoadFromStream() behaves the way you describe (see above), TMemoStrings does not override that behavior. Yes, the way TStrings.LoadFromStream() was implemented is really inefficient for large amounts of text. -
Sending Email via GMail Using OAuth 2.0 via Indy
Remy Lebeau replied to Ugochukwu Mmaduekwe's topic in Indy
Indy does not currently support OAuth yet. However, it would be fairly simple to create a TIdSASL-derived component that can be added to the TIdSMTP.SASLMechanisms collection to transmit an OAuth bearer token using the SMTP "AUTH XOAUTH2" command. But getting that token in the first place is the tricky part, and has to be done outside of SMTP. -
There is nothing like FPC's TProcess in Delphi's RTL. I'm sure you can find a 3rd party implementation, though. Or just write your own.
-
Those are the defaults that are established by the Vcl.Graphics.pas unit (see the InitDefFontData() function) during unit initialization, and then applied to the global DefFontData variable, which is used to initialize every TFont object at runtime. Not in the IDE, no. However, the DefFontData variable is publicly accessible, so you can modify it at runtime before creating any of your TForm objects.
-
How to compare msXML nodes
Remy Lebeau replied to Tommi Prami's topic in RTL and Delphi Object Pascal
That makes no sense. If you pass the SAME AChildNode node into both calls, with the same AParentNodeName value (which you didn't show), then they will return the same node on output. Perhaps you meant LNode2 instead of LNode1 in the second call? If you pass in DIFFERENT node pointers on input, then obviously you are going to get DIFFERENT node pointers in output, unless they have a COMMON parent node, in which case you WILL then get the same node pointer on output. Unless, for some reason, Microsoft decided to make the IXMLDOMNode.parentNode property getter allocate a new implementation object every time it is called, which is unlikely (but easy to test). If you can't compare the node pointers directly, then you have to compare the content they represent. There is no getting around that. Can you show an example XML and code demonstrating exactly what you are trying to accomplish? How are you retrieving the IXMLDOMNode pointers that you are trying to compare? -
Patch a private virtual method
Remy Lebeau replied to pyscripter's topic in RTL and Delphi Object Pascal
OK, so the default is to expose only Public and Protected properties and methods, and all available data fields. That is still way more RTTI available than TypInfo.pas provides (only Published properties/methods). Rtti.pas uses TypInfo.pas internally for some of its RTTI, but there is a lot more RTTI made accessible by Rtti.pas than TypInfo.pas ever provided. Much of the RTTI in Rtti.pas does not go through TypInfo.pas at all. -
Why were you using ShellExecute() for that? You should have been using CreateProcess() instead. To detect when the process ends, use WaitForSingleObject() or related function on the returned process handle. On Linux, you can start an external process using the fork(), exec...(), or posix_spawn() functions. To detect when the process ends, use wait() on the returned process ID.
-
Load a String from a file - returns strange char set
Remy Lebeau replied to bernhard_LA's topic in Algorithms, Data Structures and Class Design
Why are you using AnsiString at all? You should be using (Unicode)String instead, since that is what the TMemo expects. In any case, Char is WideChar in D2009+, so SizeOf(Char) is 2 not 1, so you are allocating memory for your AnsiString for only 1/2 of the file data, but then reading the full file into that memory. So you are going to corrupt surrounding memory. Use SizeOf(AnsiChar) instead, which is 1 so you can just drop the SizeOf() altogether. var LoadString: AnsiString; FS: TFileStream; begin FS := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone); try SetLength(LoadString, FS.Size); FS.ReadBuffer(Pointer(LoadString)^, FS.Size); finally FS.Free; end; Memo.Lines.Add(String(LoadString)); end; Alternatively, there are other options, such as TMemoryStream.LoadFromFile(): uses System.Classes; var LoadString: AnsiString; MS: TMemoryStream; begin MS := TMemoryStream.Create; try MS.LoadFromFile(FileName); SetString(LoadString, PAnsiChar(MS.Memory), MS.Size); finally MS.Free; end; Memo.Lines.Add(String(LoadString)); end; Or TStreamReader: uses System.Classes, System.SysUtils; var LoadString: String; Reader: TStreamReader; begin Reader := TStreamReader.Create(FileName, TEncoding.ANSI); try LoadString := Reader.ReadToEnd; finally Reader.Free; end; Memo.Lines.Add(LoadString); end; Or TFile.ReadAllText(): uses System.IOUtils, System.SysUtils; var LoadString: String; begin LoadString := TFile.ReadAllText(FileName, TEncoding.ANSI); Memo.Lines.Add(LoadString); end; -
Patch a private virtual method
Remy Lebeau replied to pyscripter's topic in RTL and Delphi Object Pascal
I can see that being true for Standard RTTI (TypInfo.pas), which is only generated for published members. But that should not be true for Extended RTTI (Rtti.pas), which sees everything, even private/protected stuff. That is why TRttiMember has a Visibility property. -
Patch a private virtual method
Remy Lebeau replied to pyscripter's topic in RTL and Delphi Object Pascal
You can use Extended RTTI for that. TRttiMethod has a VirtualIndex property. -
the return type of CallVoidMethodV does not match void
Remy Lebeau replied to fcknbstrd's topic in Cross-platform
Feel free to file a bug report with Embarcadero. -
TIdHTTPServer.OnCommandGet - Timeout
Remy Lebeau replied to chkaufmann's topic in Network, Cloud and Web
The only way I could see that happening is if either: - the requests are being sent on the same TCP connection (using HTTP keep-alives and maybe HTTP pipelining) and one of the requests is blocking the ones that arrive after it - your requests are arriving on different TCP connections and are accessing some piece of shared data/functionality that is being blocked/deadlocked, thus blocking all requests that try to access it. It is really hard to know what is going on without more details about your code and the requests. The only option is to close the socket that belongs to that TIdContext. But if your code is blocked/deadlocked on something that is not related to the socket itself, then closing the socket is likely to not have any/much effect in this situation. You really need to narrow down WHAT exactly is blocking. You still haven't answered my earlier questions about that. -
FMX TEdit: how to prevent user from pasting a TBitmap ?
Remy Lebeau replied to Gustav Schubert's topic in FMX
Sounds like a bug that you should report to Embarcadero directly. -
RttiContext Create and Free
Remy Lebeau replied to pyscripter's topic in RTL and Delphi Object Pascal
Since Delphi 2010, actually. RTTI data is pooled in memory. There is only 1 ref-counted copy of the RTTI data in memory that all active TRttiContext instances share. That article is old, and not 100% accurate. For instance, the implementation of TRttiContext.Create() shown in the article is how Create() was implemented in D2010, but it was changed in XE. Test1 is creating and destroying the RTTI pool 100 times, because it only has 1 TRttiContext instance alive at a time. The pool's refcount never goes above 1. The pool is recreated each time the refcount is incremented to 1, and destroyed when the refcount is decremented to 0. That is not the case in Test2, which has 2 active TRttiContext instances alive at a time so the pool is not destroyed until after the loop is finished. -
What is the actual problem you are experiencing? You did not provide any details whatsoever about that. Are you getting an error? Corrupted data? Which version of Indy are you using? How is the Java server configured? Which SSL/TLS version(s) does it expect? Please be more specific. With the code you have shown so far, the SSLIOHandler uses only TLS 1.0 by default. Does the server support TLS 1.0? Many servers nowadays no longer support TLS 1.0 and earlier, they expect TLS 1.1 or 1.2 at a minimum. You can enable TLS 1.1 and 1.2 in the SSLIOHandler's SSLOptions.SSLVersions property (only sslvTLSv1 is enabled by default).
-
I think you mean the external DLL uses your jpeg, right? What failure exactly? You need to be more specific. What makes you think TJPEGImage creates invalid JPG files? Perhaps the real problem is an error in how the DLL uses the JPG file.
-
He said the code is running in a thread. Locking a TBitmap's Canvas is required when working with a TBitmap in a thread, otherwise the main VCL thread can swoop in at any time and reclaim the GDI resources being used by the TBitmap behind its back.
-
Nothing has been announced publicly yet.
-
Or email the RAD Studio beta directly: rad.beta@embarcadero.com
-
Oh, that's interesting. I just tried it on my desktop, and sure enough it takes on the mobile look&feel when I shrink my browser window (I always use it full screen, so I never noticed that before).