Delphi-Programmierung

Delphi - Komponente - TNetHTTPClient und Sonderzeichen

Beim Zugriff auf die Keycloak-API zum Abruf eines Tokens kommt die Fehlermeldung 401 Not Authorized wenn das Passwort ein Sonderzeichen enthält.

In einer Python-Testumgebung kann der Token ohne Probleme abgerufen werden.

Mit Wireshark kann man sich die erzeugten Abfragen anzeigen (damit man in Wireshark die unverschlüsselten Daten angezeigt bekommt muss man zum Debuggen die URL von https:// auf http:// umstellen):

Python erzeugt:

POST /keycloak/rest/v1/token/generate HTTP/1.1
Host: demo.wlsoft.de
User-Agent: python-requests/2.22.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Authorization: Basic xxxx:yyyyyyyyyyyyyyyy
Content-Length: 70

grant_type=password&username=xxxxx@xxxxxx.xx&password=123456789%C3%840

Delphi erzeugt

POST /keycloak/rest/v1/token/generate HTTP/1.1
Host: demo.wlsoft.de
User-Agent: Embarcadero URI Client/1.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Authorization: Basic xxxx:yyyyyyyyyyyyyyyy
Content-Length: 70

grant_type=password&username=xxxxx@xxxxxx.xx&password=123456789%C3%840

Der Unterschied steckt im Content-Type

Python: Content-Type: application/x-www-form-urlencoded;
Delphi: Content-Type: application/x-www-form-urlencoded; charset=utf-8

Der falsche Eintrag in Delphi wird durch die Funktion THTTPClient.Cre­ateFormFromStrin­gs() erzeugt:

Deshalb darf bei Abruf eines Token nur eine Post-Anweisung aufgerufen werden, die CreateFormFrom­Strings() nicht aufruft.

Das wäre zum Beispiel ein solcher Aufruf:

function TNetHTTPClient.Post(
  const AURL: string;
  const ASource, AResponseContent: TStream;
  const AHeaders: TNetHeaders): IHTTPResponse;
type
  THCloudZugangsdaten = record
    User: string;
    Pass: string;
    Token:string;
    TokenResponseCode: integer;
    TokenResponseText: string;
  end;

function getToken(var aZugangsdaten: TZugangsdaten): boolean;
var
  s, aURL: string;
  j: TJSONObject;
  aSource: TStringStream;
  m: TMemoryStream;
  sl: TStringlist;
  Response: IHTTPResponse;
  HTTP: TNetHTTPClient;
  aHeaders: TNetHeaders;
begin
  Result := False;
  sl := TStringlist.Create;
  aSource := TStringStream.Create(
    'grant_type=password' +
    '&username=' + EncodeURIComponent(aZugangsdaten.User) +
    '&password=' + EncodeURIComponent(aZugangsdaten.Pass));
  m := TMemoryStream.Create;
  HTTP := TNetHTTPClient.Create(nil);
  try
    try
      HTTP.ContentType := cContentType_x_www_form_urlencoded;
      HTTP.AcceptEncoding := 'gzip, deflate';
      HTTP.CustomHeaders['Accept'] := '*/*';
      HTTP.CustomHeaders['Authorization'] := 'Basic xxxx:yyyyyyyyyyyyyyyy';
      aURL := 'https://demo.wlsoft.de/keycloak/rest/v1/token/generate';
      Response := HTTP.Post(aURL, aSource, m, aHeaders);
      if Response.StatusCode = 200 then begin
        m.Position := 0;
        sl.LoadFromStream(m);
        s := sl.Text;
        j := TJSONObject.ParseJSONValue(s) as TJSONObject;
        try
          if Assigned(j) then begin
            if j.TryGetValue('access_token', aZugangsdaten.Token) then begin
            end;
          end;
        finally
          FreeAndNil(j);
        end;
      end;
      aZugangsdaten.TokenResponseCode := Response.StatusCode;
      aZugangsdaten.TokenResponseText := Response.StatusText;
      Result := not aZugangsdaten.Token.IsEmpty;
    except
      on E: Exception do begin
        aZugangsdaten.TokenResponseCode := Response.StatusCode;
        aZugangsdaten.TokenResponseText := E.Message;
        // kein raise;
      end;
    end;
  finally
    m.Free;
    aSource.Free;
    FreeAndNil(sl);
    FreeNetHttp(HTTP);
  end;
end;

Delphi - TWebBrowser: Seite mit Javascript anzeigen

Eine einfache Seite lässt sich mit dem von Delphi mitgelieferten TWebBrowser anzeigen, aber bei einer Seite die Javascript nachlädt, wurde nur die Überschrift angezeigt.

  1. Umstellen der embeddedWebbrow­serMode auf 11001
  2. Damit der nachzulandende Code nicht gesperrt wid, die entsprechende Domain in der TrustedZone eintragen

Für Indy .p12 zu .pem wandeln

Literatur

Zur Beachtung Unter Delphi 2009 funktioniert die unten angegebene Funktion testCert zwar, aber der Zugriff auf einen anderen Server lieferte nur 403 Forbidden. Unter Delphi 10 Tokyo funktioniert der Zugriff immer.

  • Delphi 2009: Indy version: 10.2.5
  • Delphi 10.2: Indy version: 10.6.2.5366

Convert a PKCS#12 file (.pfx .p12) containing a private key and certificates to PEM

openssl pkcs12 -in zugang.p12 -out zugang.pem -nodes

in Delphi

  • me ist vom Typ TMemo
uses
  SysUtils, Classes, Forms, IdHTTP, IdSSLOpenSSL, idGlobal,
   Controls, ComCtrls, ToolWin, StdCtrls;

function TForm1.testCert: boolean;
var IdHTTP1 : TIdHTTP;
    Id_HandlerSocket : TIdSSLIOHandlerSocketOpenSSL;
    cert:string;
    s : string;
begin
    try
      me.Clear;
      IdHTTP1 := TIdHTTP.Create( self );
      IdHTTP1.Request.BasicAuthentication := False;
      IdHTTP1.Request.UserAgent := 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0';
      Id_HandlerSocket := TIdSSLIOHandlerSocketOpenSSL.Create( IdHTTP1 );
      cert := 'zugang.pem';
      Id_HandlerSocket.SSLOptions.CertFile := cert; (* PEM contain both CERT and Key *)
      Id_HandlerSocket.SSLOptions.KeyFile := cert;

      Id_HandlerSocket.SSLOptions.Mode := sslmClient;
      Id_HandlerSocket.SSLOptions.Method := sslvSSLv23;
      IdHTTP1.IOHandler := Id_HandlerSocket;

      me.Add( Id_HandlerSocket.SSLOptions.CertFile );

      s := IdHTTP1.Get( 'https://www.scriptjunkie.us/auth/verifycert' );

      me.Add( s );
      Result:=True;

    finally
      Id_HandlerSocket.Free;
      IdHTTP1.Free;
    end;
end;

Delphi IDE

Bei mir sind in der Delphi IDE (Delphi Seattle) seit einiger Zeit die Funktionalitäten von Datei/Öffnen und Datei/Beenden vertauscht.

Hier fand ich eine Erklärung des Phänomen

https://forums.embarcadero.com/thread.jspa?…


The File/Open and File/Exit actions have been swapped. That is a known issue related to the IDE's copy protection:

Action event handlers for the File|Open and File|Exit menu handlers are swapped

This happens when any non-Embarcadero files have been placed in the IDE's \bin folder, where they do not belong. Only official Embarcadero files are allowed in that folder.

This issue has existed since at least XE6, and someone always manages to encounter it in each new release.


Die Borland Dlls haben bei mir den Zeitstempel 27.08.2015 00:55 Eine Fremd-Dll habe ich gefunden und entfernt. Jetzt funktioniert die Delphi-IDE wieder.

Delphi beliebte Fehler: TfrxReport -TfrxMasterData

In meinem Programm erstelle iche eine TfrxMasterData und trage dazu einige TfrxMemoView ein. Obwohl im Workspace alles richtig angezeigt wurde, waren die TfrxMemoView nicht dem TfrxMasterData zugeordnet,

Falsch default alt. text

Der Fehler lag darin, dass ich der TfrxMasterData keine Weite zugeodnet hatte. So wurde die TfrxMasterData zwar im Workspace richtig angezeigt, aber die TfrxMemoView konnten einer TfrxMasterData nicht zugeordnet werden.

function TfmEinfacherFastReportDesigner.EinfacheTabelle_Masterdata(
  aPage: TfrxReportPage; var aTop, aHeight: extended): TfrxMasterData;
begin
  Result := TfrxMasterData.Create(aPage);
  Result.CreateUniqueName;
  Result.Left:=0;
  Result.Width := 750; //Width darf nicht 0 sein.
  Result.Top := aTop;
  Result.Height := aHeight;
  Result.DataSet := dsTabelle;
end;

Richtig default alt. text

Delphi 10 - Icon fehlt

Mein Projekt konnte ich (fast) ohne Schwierigkeiten von Delphi 2009 nach Delphi 10 umsetzen. Nur fehlten plötzlich in den Formularen das Icon in der oberen linken Ecke.

default alt. text

Die Fehlersuche war aufwändig aber von Erfolg gekrönt.

In einer RES-Datei einer meiner selbst geschriebenen Komponenten war neben den BITMAPs auch ein verstümmelter Eintrag für ein ICON.

Mit Hilfe des Tools Resourcehacker konnte ich die RES-Datei reparieren.

  • Action – „Save Bitmap-Group to a RES-File“
default alt. text

Delphi beliebte Fehler: Delphi 10 - Debugging funktioniert nicht

Das ist aber eine böse Falle für Umsteiger von Delphi 2009 auf Delphi 10 Seattle:

Wenn das Programm in der IDE mit dem grünen Pfeil gestartet wird, sollte man vorher den Hinweis lesen „Ohne Debugger ausführen“.

Um das Programm in der IDE mit Debugger zu starten die Taste F9 benutzen oder diesen Schalter

default alt. text

Delphi beliebte Fehler: Grid auf einem Formular erhält nicht den Focus

Das Problem:

Ein Eingabedialog wird mit Showmodal aufgerufen und das Grid im Eingabedialog erhält nicht den Fokus und ist auch mit der Maus nicht anklickbar.

Die Lösung

Schuld war der Aufruf des Eingabedialogs im Hauptformular der Anwendung bereits im OnFormActivate Ereignis, ohne der Anwendung Zeit zu geben alle bis dahin anstehenden Ereignisse abzuarbeiten.

procedure Tam_Main.FormActivate(Sender: TObject);
begin
  // Der Anwendung Zeit geben, alle bisher anstehenden Ereignisse abzuarbeiten.
  Application.ProcessMessages;
  am_Eingabe.Execute;
end;

Seiten