Jump to content

rvk

Members
  • Content Count

    146
  • Joined

  • Last visited

  • Days Won

    2

rvk last won the day on December 5

rvk had the most liked content!

Community Reputation

44 Excellent

1 Follower

Technical Information

  • Delphi-Version
    Delphi 10.2 Tokyo

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. I've just tested with a server which can't do HTTP/2 (but only does HTTP 1.1) and it always returns OK inside the service. So I think the problem is that, when running as local system account. the HTTP/2 is requested. If it's not available, you'll get the OK. If HTTP/2 is available, there is no OK. Maybe you can test it with a server where you always get a HTTP1.1 result (and never a HTTP/2 result). You can also test this yourself by logging res.Version. I didn't test it but I'll bet you'll get version 2 back for no OK, and 1.1 for OK. THTTPProtocolVersion = (UNKNOWN_HTTP, HTTP_1_0, HTTP_1_1, HTTP_2_0); Grrr. Nope. Also not it: I give up 🙂
  2. Your welcome. BTW. I just tested curl on a Linux machine (just for fun): Notice the absence of OK on the HTTPS result. HTTP did give OK 😉 HTTPS is HTTP/2 (not 1.1) so maybe we are getting HTTP/2 back. Forcing curl to do http 1.1 will give OK. sudo curl --http1.1 -I https://www.google.com But yes... you don't need to worry about the reason-phrase. It should be ignored anyway.
  3. Only start the timer during the start service sequence. But that's besides the point for this problem. BTW. The reason-phrase is optional in the http-protocol. See https://datatracker.ietf.org/doc/html/rfc9112#name-status-line Also it says that you should ignore it.
  4. Fun part is that if you do "project /install" (from an admin console) it momentarily runs as administrator. It then also runs the TTimer function and does give the OK correctly. (running in a user console also gives OK but then the service doesn't get installed obviously) You didn't put the TTimer.Enabled only for running the service but for every run, so also for the /install and /uninstall runs. After actually starting the service, it'll run as limited local system account, the TTimer function runs again but now the OK is not shown 😉 So I can confirm this on Windows 10, Delphi 10.2 (object pascal). So it's really the local system account in a service that's the problem here. Might limit the search.
  5. Oops. Hadn't noticed this was C++. Because this was posted in "RTL and Delphi Object Pascal" But I'm sure someone can test and confirm this. But am I understanding it correctly that it now always runs correctly as App and only fails as Service? Does the service run as user or admin? Did you test it the other way around?
  6. Could be that it's only a problem in service. Try to create a simple test project. If you can consistently let it fail, we can test it too. And if it's only in service that's also an indicator for which you can search.
  7. Have you tried a smaller (or simpler) POST to that page? Have you tried other URLs? Do you only have this (no OK) with that URL? Do you also have this only with POST or also with GET to that URL?
  8. Without knowing what it actually returns, this is hard to diagnose. You said the LSize was 274. So what's in Buf when the second call to WinHttpQueryHeaders returns?
  9. Because the resulting string only needs (LSize div 2) - 1 characters. LSize is the size in bytes. Result is an array of widechars/unicodechars which contain 2 bytes. So if LSize is 6 bytes (OK#0#0 in unicode) you only need 2 character string. 6 div 2 = 3 - 1 is 2 for OK. https://learn.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpqueryheaders
  10. But what is the result of that call? Is it ERROR_WINHTTP_HEADER_NOT_FOUND or something else?
  11. So, what happens if you (debug)trace into that ReadHeader? On what line does it 'crap' out? Do you get a ERROR_WINHTTP_HEADER_NOT_FOUND in that function? Do your response-headers contain a Content-Length? If not... is your input/response chunked? (that could be the cause of HEADER_NOT_FOUND) Is this happening with one certain URL or with all/more URLs?
  12. rvk

    Sending Email VIA Google.

    Well... Type in Oauth 2.0 communication in Google (or similar search terms), then select Images... and there you go... Lots of flow diagrams
  13. rvk

    Sending Email VIA Google.

    BTW. You can still use app-passwords with Google. So if you are only doing this for you own account, creating an app password is easiest. If you need to allow your users to use their own account, then you need OAuth2.
  14. rvk

    Sending Email VIA Google.

    No no, because you want to catch that URL it's easiest to create your own listening thread. I have an example for OAuth2 in combination with Lazarus/FPC and Synpase. (You can also use Synapse on Delphi but you could also use Indy) https://github.com/rvk01/google-oauth2 Relevant snippet: This is a minimalistic http server which server a string saying your program now has access and you can close the window. type THTTPServerThread = class(TThread) private ListenerSocket: TTCPBlockSocket; ConnectionSocket: TTCPBlockSocket; public Authorize_token: string; procedure Execute; override; procedure CancelThread(Sender: TObject; var CanClose: boolean); end; procedure THTTPServerThread.CancelThread(Sender: TObject; var CanClose: boolean); begin Terminate; end; procedure THTTPServerThread.Execute; var S: string; method, uri, protocol: string; OutputDataString: string; SendDataString: string; begin Authorize_token := ''; FreeOnTerminate := False; ListenerSocket := TTCPBlockSocket.Create; ConnectionSocket := TTCPBlockSocket.Create; try ListenerSocket.CreateSocket; ListenerSocket.setLinger(True, 10); ListenerSocket.Bind('localhost', '1500'); ListenerSocket.Listen; while not terminated do begin Sleep(1000); // Application.ProcessMessages; if ListenerSocket.CanRead(1000) and not terminated then begin ConnectionSocket.Socket := ListenerSocket.Accept; // read request line S := string(ConnectionSocket.RecvString(1000)); method := fetch(S, ' '); uri := fetch(S, ' '); protocol := fetch(S, ' '); // read request headers repeat S := string(ConnectionSocket.RecvString(1000)); until S = ''; // /?code=4/fegArZQDUJqFdoCw-1DU16ohYsoA5116feRuCW0LiuQ // /?error=access_denied Authorize_token := ''; if Pos('code=', uri) > 0 then begin Authorize_token := Copy(uri, Pos('code=', uri) + 5); end; if Authorize_token = '' then begin SendDataString := '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' + ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' + CRLF + '<html><center><h1>Something went wrong.<br><br>Application does not have access.<br><br>You can close this page.</h1></center></html>' + CRLF; end else begin SendDataString := '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' + ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' + CRLF + '<html><center><h1>Application now has access.<br><br>You can close this page.</h1></center></html>' + CRLF; end; OutputDataString := 'HTTP/1.0 200' + CRLF; OutputDataString := OutputDataString + 'Content-type: Text/Html' + CRLF; OutputDataString := OutputDataString + 'Content-length: ' + IntToStr(Length(SendDataString)) + CRLF; OutputDataString := OutputDataString + 'Connection: close' + CRLF; OutputDataString := OutputDataString + 'Date: ' + Rfc822DateTime(now) + CRLF; OutputDataString := OutputDataString + 'Server: Synapse' + CRLF; OutputDataString := OutputDataString + '' + CRLF; ConnectionSocket.SendString(ansistring(OutputDataString)); ConnectionSocket.SendString(ansistring(SendDataString)); ConnectionSocket.CloseSocket; Terminate; end; end; finally ConnectionSocket.Free; ListenerSocket.Free; end; end;
  15. rvk

    Sending Email VIA Google.

    This error page seems to be a step further in the normal OAuth2 process. You accepted the non-verified app, accepted the terms and now you end up on localhost with the desired code for getting the access token in the url parameters. You need to catch that url with a small http server. After getting that code from the url you can go ahead with the process of getting the access and refresh token.
×