Firebird Backup "Operation cancelled at user's request."

24.01.2023 - Lesezeit: ~1 Minute

Die Fehlermeldung des Firebird-Servers "Operation cancelled at user's request." tritt zum Beispiel dann auf, wenn versucht wird ein Backup mit einer falschen Client-Library durchzuführen.

Tags: Delphi-Programmierung FirebirdSQL

Delphi - Komponente - TNetHTTPClient und Sonderzeichen

28.04.2021 - Lesezeit: 3 Minuten

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.CreateFormFromStrings() erzeugt:

Deshalb darf bei Abruf eines Token nur eine Post-Anweisung aufgerufen werden, die CreateFormFromStrings() 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;
Tags: Delphi-Programmierung

Delphi - TWebBrowser: Seite mit Javascript anzeigen

12.04.2019 - Lesezeit: ~1 Minute

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 embeddedWebbrowserMode auf 11001

  2. Damit der nachzulandende Code nicht gesperrt wid, die entsprechende Domain in der TrustedZone eintragen

Tags: Delphi-Programmierung

Delphi beliebte Fehler: EConvertError ist kein gültiges Datum

19.03.2019 - Lesezeit: ~1 Minute

Im Projekt ist eine Exception der Klasse EConvertError mit der Meldung "01/01/2018" ist kein gültiges Datum aufgetreten.

 TpFIBDataset.PrepareOptions.pfImportDefaultValues := False;
Tags: Delphi-Programmierung

Für Indy .p12 zu .pem wandeln

20.06.2018 - Lesezeit: 2 Minuten

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;

Tags: Delphi-Programmierung Linux-Scripte

Delphi IDE

02.08.2017 - Lesezeit: ~1 Minute

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?threadID=119380


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.

Tags: Delphi-Programmierung