|
![]() |
Registriert seit: 19. Apr 2008 30 Beiträge |
#1
Hallo INDY-Anwender;
Kann jemand von euch hier folgendes unten in der Weiterleitung auf die Indy-Seite per ![]() Das wäre klasse. Gerne mit Rückmeldung. Danke! ![]() Nach einem Server-Update seitens Hoster konnten wir mit INDY10 nicht mehr die Gültigkeit des Certs einer FTPES-Verbindung auslesen. Dabei hat sich herausgestellt, dass der ftp-Server nun das NotAfter-Datum mit einer vierstelligen Jahreszahl sendet. Damit kann INDY10 nicht umgehen und schmeisst ein EConvertError. Da das Cert-Datum gültig bis 2051 ist - wird ggf. wahrscheinlich dieses mit dem Y2K38-Problem zusammen hängen. Mit dem unten angehängten Workaround funktioniert INDY10 wieder wie gehabt. Datum mit zweistelliger und vierstelliger Jahreszahl werden korrekt konvertiert; ![]() Indy10 (D7)
TIdX509.notBefore with four digits for the year has failed. GoDaddy / Domainfactory (DE) new self-signed certificate has date "Not after" > 2038 and the ftp server sends new date format with four digits for the year.
Code:
The ftp server send the data-format:
(TIdX509.DisplayInfo.Text)
Certificate: Data: Version: 3 (0x2) Serial Number: Signature Algorithm: sha256WithRSAEncryption Issuer: C=DE, ST=Bayern, L=Muenchen, O=ispgateway, CN=webserver.ispgateway.de Validity Not Before: Dec 12 05:43:54 2023 GMT Not After : Apr 29 05:43:54 2051 GMT ... Not Before: 231212054354Z Not After : 20510429054354Z TIdX509.notBefore can only decode two digits for the year YYMMDDHHMMSS. TIdX509.notAfter can only decode two digits for the year YYMMDDHHMMSS. TIdX509.notBefore: OK = 12.12.2023 05:43:54 TIdX509.notAfter: FAIL = EConvertError and excepted. in IdSSLOpenSSL.pas: -> TIdX509 property notAfter -> call function RnotAfter -> call function UTCTime2DateTime() -> call function UTC_Time_Decode() ! failed; In IdSSLOpenSSLHeader.pas the function UTC_Time_Decode() give missmatch back. The workaround can now decode both four-digit and two-digit years. TIdX509.notBefore now can decode two and four digits for the year YYMMDDHHMMSS / YYYYMMDDHHMMSS. TIdX509.notAfter now can decode two and four digits for the year YYMMDDHHMMSS / YYYYMMDDHHMMSS. TIdX509.notBefore: OK = 12.12.2023 05:43:54 TIdX509.notAfter: OK = 29.04.2051 05:43:54 -----------
Delphi-Quellcode:
-----------
// Author : Gregor Ibich (gregor.ibic@intelicom.si)
// Pascal translation: Doychin Bondzhev (doichin@5group.com) // 20240206 modified: Harald E. Sommermeyer (hes) // Converts the following string representation into corresponding parts // YYMMDDHHMMSS(+|-)HH( )MM // and // YYYYMMDDHHMMSS(+|-)HH( )MM (20240206: hes - Y2K38-Fix) function UTC_Time_Decode(UCTtime : PASN1_UTCTIME; var year, month, day, hour, min, sec: Word; var tz_hour, tz_min: Integer): Integer; var i, tz_dir: Integer; idx_add, idx_from: Integer; time_str: string; {$IFNDEF USE_MARSHALLED_PTRS} {$IFNDEF STRING_IS_ANSI} LTemp: AnsiString; {$ENDIF} {$ENDIF} begin Result := 1; if UCTtime^.length < 12 then begin Exit; end; {$IFDEF USE_MARSHALLED_PTRS} time_str := TMarshal.ReadStringAsAnsi(TPtrWrapper.Create(UCTtime^.data), UCTtime^.length); {$ELSE} {$IFDEF STRING_IS_ANSI} SetString(time_str, UCTtime^.data, UCTtime^.length); {$ELSE} SetString(LTemp, UCTtime^.data, UCTtime^.length); time_str := String(LTemp); // explicit convert to Unicode {$ENDIF} {$ENDIF} // Check if first 12 chars are numbers // YYMMDDHHMMSS(+|-)HH( )MM idx_from := 0; idx_add := 0; if not IsNumeric(time_str, 12) then begin Exit; end; // Convert time from string to number // Y2K38 Fix: If the year has four digits, check if first 14 characters are number. idx_from := 1; if IsNumeric(time_str, 14) then begin // YYYYMMDDHHMMSS(+|-)HH( )MM idx_add := 4; year := IndyStrToInt(Copy(time_str, idx_from, idx_add)); end else begin // YYMMDDHHMMSS(+|-)HH( )MM idx_add := 2; year := IndyStrToInt(Copy(time_str, idx_from, idx_add)) + 1900; end; inc(idx_from, idx_add); idx_add := 2; month := IndyStrToInt(Copy(time_str, idx_from, idx_add)); inc(idx_from, idx_add); day := IndyStrToInt(Copy(time_str, idx_from, idx_add)); inc(idx_from, idx_add); hour := IndyStrToInt(Copy(time_str, idx_from, idx_add)); inc(idx_from, idx_add); min := IndyStrToInt(Copy(time_str, idx_from, idx_add)); inc(idx_from, idx_add); sec := IndyStrToInt(Copy(time_str, idx_from, idx_add)); inc(idx_from, idx_add); // Fix year. This function is Y2k but isn't compatible with Y2k5 :-( {Do not Localize} if year < 1950 then begin Inc(year, 100); end; // Check TZ tz_hour := 0; tz_min := 0; if CharIsInSet(time_str, idx_from, '-+') then begin {Do not Localize} tz_dir := iif(CharEquals(time_str, idx_from, '-'), -1, 1); {Do not Localize} inc(idx_from, 1); for i := idx_from to idx_from + 4 do begin // Check if numbers are numbers if i = idx_from + 2 then begin Continue; end; if not IsNumeric(time_str[i]) then begin Exit; end; end; tz_hour := IndyStrToInt(Copy(time_str, idx_from, idx_from + 1)) * tz_dir; inc(idx_from, 2); tz_min := IndyStrToInt(Copy(time_str, idx_from, idx_from + 1)) * tz_dir; end; end; |
![]() |
Registriert seit: 12. Jan 2019 Ort: Hessen 688 Beiträge Delphi 11 Alexandria |
#2
Poste das doch mal auf dem
![]()
Peter Below
|
![]() |
Registriert seit: 10. Jan 2006 Ort: Offenbach 3.791 Beiträge Delphi 12 Athens |
#3
Das kann ich nur unterstreichen.
Oliver
Geändert von Sherlock (Morgen um 16:78 Uhr) Grund: Weil ich es kann |
![]() |
Registriert seit: 19. Apr 2008 30 Beiträge |
#4
Hallo,
OK, danke für eure Rückmeldung. Boha - ich komme mit der englischen Forum-Software auf die schnelle gar nicht zurecht. ![]() Wir haben uns in dieses Problem nun noch etwas weiter eingelesen. Alles hier ist gefährliches Halbwissen. Es kann gut möglich sein, dass ich komplett falsch liege. Eine mögliche grundlegende Ursache des Problems kann sein, dass bis 2049 UTC-Time und ab 2050 Generalized-Time verwendet wird. Darauf müsste wohl INDY10 angepasst werden. ![]() 4.1.2.5. Validity The certificate validity period is the time interval during which the CA warrants that it will maintain information about the status of the certificate. The field is represented as a SEQUENCE of two dates: the date on which the certificate validity period begins (notBefore) and the date on which the certificate validity period ends (notAfter). Both notBefore and notAfter may be encoded as UTCTime or GeneralizedTime. CAs conforming to this profile MUST always encode certificate validity dates through the year 2049 as UTCTime; certificate validity dates in 2050 or later MUST be encoded as GeneralizedTime. Conforming applications MUST be able to process validity dates that are encoded in either UTCTime or GeneralizedTime. ![]() Laut dem Author soll der TZ-Syntax angeblich "[+|-]HH( )MM" sein; Woher diese Spezifikation stammt - keine Ahnung. Im RFC zur UTC-Time zumindest habe ich nur ein optionales "[+|-]HHMM" rauslesen können. Es kann aber gut möglich sein, dass aus den Functionen von OpenSSL diese UTC-Time-Muster zurück gegeben werden. Keine Ahnung. Ich vermute aber eher, dass TZ nie gesendet wird und daher dieses Problem hier nie ein Thema gewesen ist. Fehler 1: -------------
Delphi-Quellcode:
Das "optionale" Space in der TZ Uhrzeit wird in der Funktion hartkodiert als "bedingtes" Space überprüft. Bei einem fehlenden Space läuft bei der TZ-decodieren die For-Schleife über die Stringlänge hinaus, da der finalValue der For-Schleife nicht mit length(time_str) -1
angegeben wird, sondern der String immer fest bis 18 Zeichen überprüft wird.
Lib\Protocols\IdSSLOpenSSLHeaders.pas
// Converts the following string representation into corresponding parts // YYMMDDHHMMSS(+|-)HH( )MM function UTC_Time_Decode(...) ... // Check TZ ... for i := 14 to 18 do begin // Check if numbers are numbers if i = 16 then begin Continue; end; if not IsNumeric(time_str[i]) then begin Exit; end; end; ... end; Ohne einem Space ist die Variable "time_str" daher nur 18 Zeichen lang time_str[0..17] , und erhalten einen Abbruch der For-Schleifen bzgl. "Bereichsprüfung". Mit einem Space ist die Variable "time_str" zwar 19 Zeichen lang time_str[0..18] , hier würde die For-Schleife durchlaufen, dann führt im Anschluss eine fehlerhafte copy-Implementierung (siehe Fehler 2) zu einem Abbruch der TZ-Schleife - also es wird m.M.n immer TZ als 00:00 zurück gegeben (werden müssen) ![]() Fehler 2: -------------
Delphi-Quellcode:
Beim Copy() muss ein Start-Offset sowie ein Counter mit Anzahl an Zeichen angegeben werden (z.B. ab Zeichen 14 weitere 2 Zeichen = Zeichen 14 + 15); Im Source werden aber hartkodiert Start-Offset sowie ein End-Offset (von Zeichen 14 bis Zeichen 15) angegeben und somit werden laut copy() ab Zeichen 14 weiter 15 Zeichen kopiert und damit über das Stringende hinweg bzw. alles bis String-Ende kopiert wie z.B. "03 00"; Das Space in der Uhrzeit kann dann nicht zum Integer konvertiert werden und es wird ein Exception ausgelöst;
function UTC_Time_Decode(...)
... // Check TZ ... tz_hour := IndyStrToInt(Copy(time_str, 14, 15)) * tz_dir; tz_min := IndyStrToInt(Copy(time_str, 17, 18)) * tz_dir; ... end;
Code:
<kopfkratz>Delphi7: function UTC_Time_Decode() INDY10 (#520) utc_1901 011224181920Z = 24.12.2001 18:19:20 = UTC year bad, but OK (RFC-konform) 011224181920+0300 = error = FAIL: Fehler bei Bereichsprüfung 011224181920+03 00 = error = FAIL: '03 00' ist kein gültiger Integerwert 011224181920-0300 = error = FAIL: Fehler bei Bereichsprüfung 011224181920-03 00 = error = FAIL: '03 00' ist kein gültiger Integerwert 011224181920+1122 = error = FAIL: Fehler bei Bereichsprüfung 011224181920+11 22 = error = FAIL: '11 22' ist kein gültiger Integerwert 011224181920-1122 = error = FAIL: Fehler bei Bereichsprüfung 011224181920-11 22 = error = FAIL: '11 22' ist kein gültiger Integerwert - utc_1950 501224181920Z = 24.12.1950 18:19:20 = OK 501224181920+0300 = error = FAIL: Fehler bei Bereichsprüfung 501224181920+03 00 = error = FAIL: '03 00' ist kein gültiger Integerwert 501224181920-0300 = error = FAIL: Fehler bei Bereichsprüfung 501224181920-03 00 = error = FAIL: '03 00' ist kein gültiger Integerwert 501224181920+1122 = error = FAIL: Fehler bei Bereichsprüfung 501224181920+11 22 = error = FAIL: '11 22' ist kein gültiger Integerwert 501224181920-1122 = error = FAIL: Fehler bei Bereichsprüfung 501224181920-11 22 = error = FAIL: '11 22' ist kein gültiger Integerwert - utc_1999 991224181920Z = 24.12.1999 18:19:20 = OK 991224181920+0300 = error = FAIL: Fehler bei Bereichsprüfung 991224181920+03 00 = error = FAIL: '03 00' ist kein gültiger Integerwert 991224181920-0300 = error = FAIL: Fehler bei Bereichsprüfung 991224181920-03 00 = error = FAIL: '03 00' ist kein gültiger Integerwert 991224181920+1122 = error = FAIL: Fehler bei Bereichsprüfung 991224181920+11 22 = error = FAIL: '11 22' ist kein gültiger Integerwert 991224181920-1122 = error = FAIL: Fehler bei Bereichsprüfung 991224181920-11 22 = error = FAIL: '11 22' ist kein gültiger Integerwert - utc_2000 001224181920Z = 24.12.2000 18:19:20 = OK 001224181920+0300 = error = FAIL: Fehler bei Bereichsprüfung 001224181920+03 00 = error = FAIL: '03 00' ist kein gültiger Integerwert 001224181920-0300 = error = FAIL: Fehler bei Bereichsprüfung 001224181920-03 00 = error = FAIL: '03 00' ist kein gültiger Integerwert 001224181920+1122 = error = FAIL: Fehler bei Bereichsprüfung 001224181920+11 22 = error = FAIL: '11 22' ist kein gültiger Integerwert 001224181920-1122 = error = FAIL: Fehler bei Bereichsprüfung 001224181920-11 22 = error = FAIL: '11 22' ist kein gültiger Integerwert - utc_2025 251224181920Z = 24.12.2025 18:19:20 = OK 251224181920+0300 = error = FAIL: Fehler bei Bereichsprüfung 251224181920+03 00 = error = FAIL: '03 00' ist kein gültiger Integerwert 251224181920-0300 = error = FAIL: Fehler bei Bereichsprüfung 251224181920-03 00 = error = FAIL: '03 00' ist kein gültiger Integerwert 251224181920+1122 = error = FAIL: Fehler bei Bereichsprüfung 251224181920+11 22 = error = FAIL: '11 22' ist kein gültiger Integerwert 251224181920-1122 = error = FAIL: Fehler bei Bereichsprüfung 251224181920-11 22 = error = FAIL: '11 22' ist kein gültiger Integerwert - utc_2049 491224181920Z = 24.12.2049 18:19:20 = OK 491224181920+0300 = error = FAIL: Fehler bei Bereichsprüfung 491224181920+03 00 = error = FAIL: '03 00' ist kein gültiger Integerwert 491224181920-0300 = error = FAIL: Fehler bei Bereichsprüfung 491224181920-03 00 = error = FAIL: '03 00' ist kein gültiger Integerwert 491224181920+1122 = error = FAIL: Fehler bei Bereichsprüfung 491224181920+11 22 = error = FAIL: '11 22' ist kein gültiger Integerwert 491224181920-1122 = error = FAIL: Fehler bei Bereichsprüfung 491224181920-11 22 = error = FAIL: '11 22' ist kein gültiger Integerwert - utc_2050 501224181920Z = 24.12.1950 18:19:20 = UTC year bad, but OK (RFC-konform) 501224181920+0300 = error = FAIL: Fehler bei Bereichsprüfung 501224181920+03 00 = error = FAIL: '03 00' ist kein gültiger Integerwert 501224181920-0300 = error = FAIL: Fehler bei Bereichsprüfung 501224181920-03 00 = error = FAIL: '03 00' ist kein gültiger Integerwert 501224181920+1122 = error = FAIL: Fehler bei Bereichsprüfung 501224181920+11 22 = error = FAIL: '11 22' ist kein gültiger Integerwert 501224181920-1122 = error = FAIL: Fehler bei Bereichsprüfung 501224181920-11 22 = error = FAIL: '11 22' ist kein gültiger Integerwert - utc_2099 991224181920Z = 24.12.1999 18:19:20 = UTC year bad, but OK (RFC-konform) 991224181920+0300 = error = FAIL: Fehler bei Bereichsprüfung 991224181920+03 00 = error = FAIL: '03 00' ist kein gültiger Integerwert 991224181920-0300 = error = FAIL: Fehler bei Bereichsprüfung 991224181920-03 00 = error = FAIL: '03 00' ist kein gültiger Integerwert 991224181920+1122 = error = FAIL: Fehler bei Bereichsprüfung 991224181920+11 22 = error = FAIL: '11 22' ist kein gültiger Integerwert 991224181920-1122 = error = FAIL: Fehler bei Bereichsprüfung 991224181920-11 22 = error = FAIL: '11 22' ist kein gültiger Integerwert - general_1901 19011224181920Z = error = FAIL: Ungültiges Argument zum Codieren der Uhrzeit 19011224181920+0300 = error = FAIL: Ungültiges Argument zum Codieren der Uhrzeit 19011224181920+03 00 = error = FAIL: Ungültiges Argument zum Codieren der Uhrzeit 19011224181920-0300 = error = FAIL: Ungültiges Argument zum Codieren der Uhrzeit 19011224181920-03 00 = error = FAIL: Ungültiges Argument zum Codieren der Uhrzeit 19011224181920+1122 = error = FAIL: Ungültiges Argument zum Codieren der Uhrzeit 19011224181920+11 22 = error = FAIL: Ungültiges Argument zum Codieren der Uhrzeit 19011224181920-1122 = error = FAIL: Ungültiges Argument zum Codieren der Uhrzeit 19011224181920-11 22 = error = FAIL: Ungültiges Argument zum Codieren der Uhrzeit - general_1950 19501224181920Z = error = FAIL: Ungültiges Argument zum Codieren des Datums 19501224181920+0300 = error = FAIL: Ungültiges Argument zum Codieren des Datums 19501224181920+03 00 = error = FAIL: Ungültiges Argument zum Codieren des Datums 19501224181920-0300 = error = FAIL: Ungültiges Argument zum Codieren des Datums 19501224181920-03 00 = error = FAIL: Ungültiges Argument zum Codieren des Datums 19501224181920+1122 = error = FAIL: Ungültiges Argument zum Codieren des Datums 19501224181920+11 22 = error = FAIL: Ungültiges Argument zum Codieren des Datums 19501224181920-1122 = error = FAIL: Ungültiges Argument zum Codieren des Datums 19501224181920-11 22 = error = FAIL: Ungültiges Argument zum Codieren des Datums - general_1999 19991224181920Z = error = FAIL: Ungültiges Argument zum Codieren des Datums 19991224181920+0300 = error = FAIL: Ungültiges Argument zum Codieren des Datums 19991224181920+03 00 = error = FAIL: Ungültiges Argument zum Codieren des Datums 19991224181920-0300 = error = FAIL: Ungültiges Argument zum Codieren des Datums 19991224181920-03 00 = error = FAIL: Ungültiges Argument zum Codieren des Datums 19991224181920+1122 = error = FAIL: Ungültiges Argument zum Codieren des Datums 19991224181920+11 22 = error = FAIL: Ungültiges Argument zum Codieren des Datums 19991224181920-1122 = error = FAIL: Ungültiges Argument zum Codieren des Datums 19991224181920-11 22 = error = FAIL: Ungültiges Argument zum Codieren des Datums - general_2000 20001224181920Z = error = FAIL: Ungültiges Argument zum Codieren des Datums 20001224181920+0300 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20001224181920+03 00 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20001224181920-0300 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20001224181920-03 00 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20001224181920+1122 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20001224181920+11 22 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20001224181920-1122 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20001224181920-11 22 = error = FAIL: Ungültiges Argument zum Codieren des Datums - general_2025 20251224181920Z = error = FAIL: Ungültiges Argument zum Codieren des Datums 20251224181920+0300 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20251224181920+03 00 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20251224181920-0300 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20251224181920-03 00 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20251224181920+1122 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20251224181920+11 22 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20251224181920-1122 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20251224181920-11 22 = error = FAIL: Ungültiges Argument zum Codieren des Datums - general_2049 20491224181920Z = error = FAIL: Ungültiges Argument zum Codieren des Datums 20491224181920+0300 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20491224181920+03 00 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20491224181920-0300 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20491224181920-03 00 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20491224181920+1122 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20491224181920+11 22 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20491224181920-1122 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20491224181920-11 22 = error = FAIL: Ungültiges Argument zum Codieren des Datums - general_2050 20501224181920Z = error = FAIL: Ungültiges Argument zum Codieren des Datums 20501224181920+0300 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20501224181920+03 00 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20501224181920-0300 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20501224181920-03 00 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20501224181920+1122 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20501224181920+11 22 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20501224181920-1122 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20501224181920-11 22 = error = FAIL: Ungültiges Argument zum Codieren des Datums - general_2099 20991224181920Z = error = FAIL: Ungültiges Argument zum Codieren des Datums 20991224181920+0300 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20991224181920+03 00 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20991224181920-0300 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20991224181920-03 00 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20991224181920+1122 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20991224181920+11 22 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20991224181920-1122 = error = FAIL: Ungültiges Argument zum Codieren des Datums 20991224181920-11 22 = error = FAIL: Ungültiges Argument zum Codieren des Datums - Ich habe "für mich" die Funktion erst einmal wie folgt angepasst/modifiziert, damit "unsere" Software erst einmal mit den neuen Zertifikaten beim Hoster weiter arbeitet; Ich habe nur D7 getestet, keine Ahnung was bei Lazarus, BCB oder anderen Delphi-Versionen (32/64bit, Unicode/Widestring etc.pp) passiert! Ich habe keine Rücksicht auf {Do not Localize} genommen, dass muss ggf. noch jemand mit INDY10- Fachwissen übernehmen ![]() Sollten Fehler zu erkennen sein oder Cleancode-Hinweise in den Finger gribbeln - bitte sehr gerne aufschreiben. Danke.
Delphi-Quellcode:
und noch der passende Test dazu. Ich finde, das sieht doch schon einmal ganz gut aus.
{
This file is part of the Indy (Internet Direct) project, and is offered under the dual-licensing agreement described on the Indy website. (http://www.indyproject.org/) Copyright: (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved. } ... // Author : Gregor Ibich (gregor.ibic@intelicom.si) // Pascal translation: Doychin Bondzhev (doichin@5group.com) // 02/10/2024 modified: Harald E. Sommermeyer (hes) - UTC-Time and Generalized-Time with tow and four digit years in dates (Y2K50) // Converts the following string representation into corresponding parts // UTC-Time: YYMMDDHHMMSS(+|-)HH( )MM // Indy10 old version; // and // (hes) RFC 5280, May 2008 (Internet X.509) 4.1.2.5.1. UTCTime // UTC-Time: YYMMDDHHMMSS(Z|(+|-)HHMM) // and // (hes) RFC 5280, May 2008 (Internet X.509) Section 4.1.2.5.2. GeneralizedTime // Generalized-Time: YYYYMMDDHHMMSS(Z|(+|-)HHMM) // Note: // hes: According to RFC 5280, May 2008 (Internet X.509) Section 4.1.2.5.1. UTCTime // The universal time type, UTCTime, is a standard ASN.1 type intended // for representation of dates and time. UTCTime specifies the year // through the two low-order digits and time is specified to the // precision of one minute or one second. UTCTime includes either Z // (for Zulu, or Greenwich Mean Time) or a time differential. // For the purposes of this profile, UTCTime values MUST be expressed in // Greenwich Mean Time (Zulu) and MUST include seconds (i.e., times are // YYMMDDHHMMSSZ), even where the number of seconds is zero. Conforming // systems MUST interpret the year field (YY) as follows: // Where YY is greater than or equal to 50, the year SHALL be // interpreted as 19YY; and // Where YY is less than 50, the year SHALL be interpreted as 20YY. // hes: According to RFC 5280, May 2008 (Internet X.509) Section 4.1.2.5: // Validity: The certificate validity period is the time interval during which the // CA warrants that it will maintain information about the status of the // certificate. The field is represented as a SEQUENCE of two dates: // the date on which the certificate validity period begins (notBefore) // and the date on which the certificate validity period ends // (notAfter). Both notBefore and notAfter may be encoded as UTCTime or // GeneralizedTime. // CAs conforming to this profile MUST always encode certificate // validity dates through the year 2049 as UTCTime; certificate validity // dates in 2050 or later MUST be encoded as GeneralizedTime. // Conforming applications MUST be able to process validity dates that // are encoded in either UTCTime or GeneralizedTime." function UTC_Time_Decode(UCTtime : PASN1_UTCTIME; var year, month, day, hour, min, sec: Word; var tz_hour, tz_min: Integer): Integer; var i, tz_dir: Integer; time_str: string; {$IFNDEF USE_MARSHALLED_PTRS} {$IFNDEF STRING_IS_ANSI} LTemp: AnsiString; {$ENDIF} {$ENDIF} LOffset: Integer; Ltz_space: Integer; const LDigit = 1; LDigit2 = 2; LDigit4 = 4; LShortDate = 12; // length('YYMMDDHHMMSS') LFullDate = 14; // length('YYYYMMDDHHMMSS') LShortYear = LDigit2; // YY LFullYear = LDigit4; // YYYY LMonth = LDigit2; // MM LDay = LDigit2; // DD LHour = LDigit2; // HH LMinute = LDigit2; // MM LSecond = LDigit2; // SS LMonthDays : array[1..12] of byte = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); LMonthDaysLeapYear : array[1..12] of byte = (31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); // LeapYear begin Result := 1; year := 0; month := 0; day := 0; hour := 0; min := 0; sec := 0; tz_hour := 0; tz_min := 0; try if UCTtime^.length < LShortDate then begin Abort; end; {$IFDEF USE_MARSHALLED_PTRS} time_str := TMarshal.ReadStringAsAnsi(TPtrWrapper.Create(UCTtime^.data), UCTtime^.length); {$ELSE} {$IFDEF STRING_IS_ANSI} SetString(time_str, UCTtime^.data, UCTtime^.length); {$ELSE} SetString(LTemp, UCTtime^.data, UCTtime^.length); time_str := String(LTemp); // explicit convert to Unicode {$ENDIF} {$ENDIF} // Check if first 12 chars are numbers // YYMMDDHHMMSS(Z|(+|-)HH( )MM) if not IsNumeric(time_str, LShortDate) then begin Abort; end; // Convert time from string to number LOffset := 1; // CHOICE {GeneralizedTime, UTCTime} // If the year has four Digits, check if first 14 characters are number. if IsNumeric(time_str, LFullDate) then begin // GeneralizedTime: YYYYMMDDHHMMSS(Z|(+|-)HHMM) year := IndyStrToInt(Copy(time_str, LOffset, LFullYear)); inc(LOffset, LFullYear); end else begin // UTCTime: YYMMDDHHMMSS(Z|(+|-)HH( )MM) year := IndyStrToInt(Copy(time_str, LOffset, LShortYear)) + 1900; inc(LOffset, LShortYear); // Fix year. This function is Y2k but isn't compatible with Y2k5 :-( {Do not Localize} // Note: 20240209 (hes) - dates >=2050 MUST as GeneralizedTime with four digit year if year < 1950 then begin // RFC 2822, Section 3.3 and 4.3 Inc(year, 100); end; end; if not ((year >= 1) and (year <= 9999)) then Abort; month := IndyStrToInt(Copy(time_str, LOffset, LMonth)); if not (month in [1..12]) then Abort; inc(LOffset, LMonth); day := IndyStrToInt(Copy(time_str, LOffset, LDay)); // Is function IsLeapYear() in SysUtils cross-platform? if IsLeapYear(Year) then begin // if (Year mod 4 = 0) and ((Year mod 100 <> 0) or (Year mod 400 = 0)) then begin if not (day in [0..LMonthDaysLeapYear[month]]) then Abort; // LeapYear end else begin if not (day in [0..LMonthDays[month]]) then Abort; // no LeapYear end; inc(LOffset, LDay); hour := IndyStrToInt(Copy(time_str, LOffset, LHour)); if not (hour in [0..23]) then Abort; inc(LOffset, LHour); min := IndyStrToInt(Copy(time_str, LOffset, LMinute)); if not (min in [0..59]) then Abort; inc(LOffset, LMinute); sec := IndyStrToInt(Copy(time_str, LOffset, LSecond)); if not (sec in [0..59]) then Abort; inc(LOffset, LSecond); // Check TZ if CharIsInSet(time_str, LOffset, '-+') then begin {Do not Localize} tz_dir := iif(CharEquals(time_str, LOffset, '-'), -1, 1); {Do not Localize} inc(LOffset, LDigit); if IsNumeric(time_str[LOffset + LDigit2]) then begin // optional space Ltz_space := 0; end else begin Ltz_space := 1; end; for i := LOffset to (LOffset + LDigit4 + Ltz_space) -1 do begin // Check if numbers are numbers if (i = LOffset + LDigit2) and (Ltz_space = 1) then begin // optional space Continue; end; if not IsNumeric(time_str[i]) then begin exit; end; end; tz_hour := IndyStrToInt(Copy(time_str, LOffset, LHour)) * tz_dir; if not ((tz_hour >= -12) and (tz_hour <= 14)) then tz_hour := 0; // check UTC offsets inc(LOffset, LHour + Ltz_space); // and add optional blank tz_min := IndyStrToInt(Copy(time_str, LOffset, LMinute)) * tz_dir; if not ((tz_min >= -59) and (tz_min <= 59)) then tz_min := 0; end; except Result := 0; end; end;
Code:
Meine Test-Schleife dazu.Delphi7: function UTC_Time_Decode() INDY10 (#520) hes - modifiziert utc_1901 011224181920Z = 24.12.2001 18:19:20 = UTC year bad, but OK (RFC-konform) 011224181920+0300 = 24.12.2001 21:19:20 = UTC year bad, but OK (RFC-konform) 011224181920+03 00 = 24.12.2001 21:19:20 = UTC year bad, but OK (RFC-konform) 011224181920-0300 = 24.12.2001 15:19:20 = UTC year bad, but OK (RFC-konform) 011224181920-03 00 = 24.12.2001 15:19:20 = UTC year bad, but OK (RFC-konform) 011224181920+1122 = 25.12.2001 05:41:20 = UTC year bad, but OK (RFC-konform) 011224181920+11 22 = 25.12.2001 05:41:20 = UTC year bad, but OK (RFC-konform) 011224181920-1122 = 24.12.2001 06:57:20 = UTC year bad, but OK (RFC-konform) 011224181920-11 22 = 24.12.2001 06:57:20 = UTC year bad, but OK (RFC-konform) - utc_1950 501224181920Z = 24.12.1950 18:19:20 = OK 501224181920+0300 = 24.12.1950 21:19:20 = OK 501224181920+03 00 = 24.12.1950 21:19:20 = OK 501224181920-0300 = 24.12.1950 15:19:20 = OK 501224181920-03 00 = 24.12.1950 15:19:20 = OK 501224181920+1122 = 25.12.1950 05:41:20 = OK 501224181920+11 22 = 25.12.1950 05:41:20 = OK 501224181920-1122 = 24.12.1950 06:57:20 = OK 501224181920-11 22 = 24.12.1950 06:57:20 = OK - utc_1999 991224181920Z = 24.12.1999 18:19:20 = OK 991224181920+0300 = 24.12.1999 21:19:20 = OK 991224181920+03 00 = 24.12.1999 21:19:20 = OK 991224181920-0300 = 24.12.1999 15:19:20 = OK 991224181920-03 00 = 24.12.1999 15:19:20 = OK 991224181920+1122 = 25.12.1999 05:41:20 = OK 991224181920+11 22 = 25.12.1999 05:41:20 = OK 991224181920-1122 = 24.12.1999 06:57:20 = OK 991224181920-11 22 = 24.12.1999 06:57:20 = OK - utc_2000 001224181920Z = 24.12.2000 18:19:20 = OK 001224181920+0300 = 24.12.2000 21:19:20 = OK 001224181920+03 00 = 24.12.2000 21:19:20 = OK 001224181920-0300 = 24.12.2000 15:19:20 = OK 001224181920-03 00 = 24.12.2000 15:19:20 = OK 001224181920+1122 = 25.12.2000 05:41:20 = OK 001224181920+11 22 = 25.12.2000 05:41:20 = OK 001224181920-1122 = 24.12.2000 06:57:20 = OK 001224181920-11 22 = 24.12.2000 06:57:20 = OK - utc_2025 251224181920Z = 24.12.2025 18:19:20 = OK 251224181920+0300 = 24.12.2025 21:19:20 = OK 251224181920+03 00 = 24.12.2025 21:19:20 = OK 251224181920-0300 = 24.12.2025 15:19:20 = OK 251224181920-03 00 = 24.12.2025 15:19:20 = OK 251224181920+1122 = 25.12.2025 05:41:20 = OK 251224181920+11 22 = 25.12.2025 05:41:20 = OK 251224181920-1122 = 24.12.2025 06:57:20 = OK 251224181920-11 22 = 24.12.2025 06:57:20 = OK - utc_2049 491224181920Z = 24.12.2049 18:19:20 = OK 491224181920+0300 = 24.12.2049 21:19:20 = OK 491224181920+03 00 = 24.12.2049 21:19:20 = OK 491224181920-0300 = 24.12.2049 15:19:20 = OK 491224181920-03 00 = 24.12.2049 15:19:20 = OK 491224181920+1122 = 25.12.2049 05:41:20 = OK 491224181920+11 22 = 25.12.2049 05:41:20 = OK 491224181920-1122 = 24.12.2049 06:57:20 = OK 491224181920-11 22 = 24.12.2049 06:57:20 = OK - utc_2050 501224181920Z = 24.12.1950 18:19:20 = UTC year bad, but OK (RFC-konform) 501224181920+0300 = 24.12.1950 21:19:20 = UTC year bad, but OK (RFC-konform) 501224181920+03 00 = 24.12.1950 21:19:20 = UTC year bad, but OK (RFC-konform) 501224181920-0300 = 24.12.1950 15:19:20 = UTC year bad, but OK (RFC-konform) 501224181920-03 00 = 24.12.1950 15:19:20 = UTC year bad, but OK (RFC-konform) 501224181920+1122 = 25.12.1950 05:41:20 = UTC year bad, but OK (RFC-konform) 501224181920+11 22 = 25.12.1950 05:41:20 = UTC year bad, but OK (RFC-konform) 501224181920-1122 = 24.12.1950 06:57:20 = UTC year bad, but OK (RFC-konform) 501224181920-11 22 = 24.12.1950 06:57:20 = UTC year bad, but OK (RFC-konform) - utc_2099 991224181920Z = 24.12.1999 18:19:20 = UTC year bad, but OK (RFC-konform) 991224181920+0300 = 24.12.1999 21:19:20 = UTC year bad, but OK (RFC-konform) 991224181920+03 00 = 24.12.1999 21:19:20 = UTC year bad, but OK (RFC-konform) 991224181920-0300 = 24.12.1999 15:19:20 = UTC year bad, but OK (RFC-konform) 991224181920-03 00 = 24.12.1999 15:19:20 = UTC year bad, but OK (RFC-konform) 991224181920+1122 = 25.12.1999 05:41:20 = UTC year bad, but OK (RFC-konform) 991224181920+11 22 = 25.12.1999 05:41:20 = UTC year bad, but OK (RFC-konform) 991224181920-1122 = 24.12.1999 06:57:20 = UTC year bad, but OK (RFC-konform) 991224181920-11 22 = 24.12.1999 06:57:20 = UTC year bad, but OK (RFC-konform) - general_1901 19011224181920Z = 24.12.1901 18:19:20 = OK 19011224181920+0300 = 24.12.1901 21:19:20 = OK 19011224181920+03 00 = 24.12.1901 21:19:20 = OK 19011224181920-0300 = 24.12.1901 15:19:20 = OK 19011224181920-03 00 = 24.12.1901 15:19:20 = OK 19011224181920+1122 = 25.12.1901 05:41:20 = OK 19011224181920+11 22 = 25.12.1901 05:41:20 = OK 19011224181920-1122 = 24.12.1901 06:57:20 = OK 19011224181920-11 22 = 24.12.1901 06:57:20 = OK - general_1950 19501224181920Z = 24.12.1950 18:19:20 = OK 19501224181920+0300 = 24.12.1950 21:19:20 = OK 19501224181920+03 00 = 24.12.1950 21:19:20 = OK 19501224181920-0300 = 24.12.1950 15:19:20 = OK 19501224181920-03 00 = 24.12.1950 15:19:20 = OK 19501224181920+1122 = 25.12.1950 05:41:20 = OK 19501224181920+11 22 = 25.12.1950 05:41:20 = OK 19501224181920-1122 = 24.12.1950 06:57:20 = OK 19501224181920-11 22 = 24.12.1950 06:57:20 = OK - general_1999 19991224181920Z = 24.12.1999 18:19:20 = OK 19991224181920+0300 = 24.12.1999 21:19:20 = OK 19991224181920+03 00 = 24.12.1999 21:19:20 = OK 19991224181920-0300 = 24.12.1999 15:19:20 = OK 19991224181920-03 00 = 24.12.1999 15:19:20 = OK 19991224181920+1122 = 25.12.1999 05:41:20 = OK 19991224181920+11 22 = 25.12.1999 05:41:20 = OK 19991224181920-1122 = 24.12.1999 06:57:20 = OK 19991224181920-11 22 = 24.12.1999 06:57:20 = OK - general_2000 20001224181920Z = 24.12.2000 18:19:20 = OK 20001224181920+0300 = 24.12.2000 21:19:20 = OK 20001224181920+03 00 = 24.12.2000 21:19:20 = OK 20001224181920-0300 = 24.12.2000 15:19:20 = OK 20001224181920-03 00 = 24.12.2000 15:19:20 = OK 20001224181920+1122 = 25.12.2000 05:41:20 = OK 20001224181920+11 22 = 25.12.2000 05:41:20 = OK 20001224181920-1122 = 24.12.2000 06:57:20 = OK 20001224181920-11 22 = 24.12.2000 06:57:20 = OK - general_2025 20251224181920Z = 24.12.2025 18:19:20 = OK 20251224181920+0300 = 24.12.2025 21:19:20 = OK 20251224181920+03 00 = 24.12.2025 21:19:20 = OK 20251224181920-0300 = 24.12.2025 15:19:20 = OK 20251224181920-03 00 = 24.12.2025 15:19:20 = OK 20251224181920+1122 = 25.12.2025 05:41:20 = OK 20251224181920+11 22 = 25.12.2025 05:41:20 = OK 20251224181920-1122 = 24.12.2025 06:57:20 = OK 20251224181920-11 22 = 24.12.2025 06:57:20 = OK - general_2049 20491224181920Z = 24.12.2049 18:19:20 = OK 20491224181920+0300 = 24.12.2049 21:19:20 = OK 20491224181920+03 00 = 24.12.2049 21:19:20 = OK 20491224181920-0300 = 24.12.2049 15:19:20 = OK 20491224181920-03 00 = 24.12.2049 15:19:20 = OK 20491224181920+1122 = 25.12.2049 05:41:20 = OK 20491224181920+11 22 = 25.12.2049 05:41:20 = OK 20491224181920-1122 = 24.12.2049 06:57:20 = OK 20491224181920-11 22 = 24.12.2049 06:57:20 = OK - general_2050 20501224181920Z = 24.12.2050 18:19:20 = OK 20501224181920+0300 = 24.12.2050 21:19:20 = OK 20501224181920+03 00 = 24.12.2050 21:19:20 = OK 20501224181920-0300 = 24.12.2050 15:19:20 = OK 20501224181920-03 00 = 24.12.2050 15:19:20 = OK 20501224181920+1122 = 25.12.2050 05:41:20 = OK 20501224181920+11 22 = 25.12.2050 05:41:20 = OK 20501224181920-1122 = 24.12.2050 06:57:20 = OK 20501224181920-11 22 = 24.12.2050 06:57:20 = OK - general_2099 20991224181920Z = 24.12.2099 18:19:20 = OK 20991224181920+0300 = 24.12.2099 21:19:20 = OK 20991224181920+03 00 = 24.12.2099 21:19:20 = OK 20991224181920-0300 = 24.12.2099 15:19:20 = OK 20991224181920-03 00 = 24.12.2099 15:19:20 = OK 20991224181920+1122 = 25.12.2099 05:41:20 = OK 20991224181920+11 22 = 25.12.2099 05:41:20 = OK 20991224181920-1122 = 24.12.2099 06:57:20 = OK 20991224181920-11 22 = 24.12.2099 06:57:20 = OK -
Delphi-Quellcode:
Weiter ist nun der Funktionname nicht mehr ganz stimmig ... keine Ahnung wie damit im INDY-Projekt umgegangen wird ... die Function müsste nun eher ggf. UTC_Generalized_Time_Decode() oder so heissen ... die Funktion in UTC-Time und Generalized-Time splitten ist irgendwie auch blöd, da 90% des Source ggf. gleich bleibt.
uses
... IdSSLOpenSSL, IdSSLOpenSSLHeaders ... // 20240207: hes - only Datum Test Indy UTC_Time_Decode() BugFix; procedure UTC_Time_Decode; var year: Word; month: Word; day: Word; hour: Word; min: Word; sec: Word; tz_h: Integer; tz_m: Integer; UCTTime: PASN1_UTCTIME; dt : TDateTime; s, s1 : String; sl, sl2: TStringList; i, j: Integer; value: String; begin sl := TStringList.Create; sl2 := TStringList.Create; try sl.Append('utc_1901=011224181920'); sl.Append('utc_1950=501224181920'); sl.Append('utc_1999=991224181920'); sl.Append('utc_2000=001224181920'); sl.Append('utc_2025=251224181920'); sl.Append('utc_2049=491224181920'); sl.Append('utc_2050=501224181920'); sl.Append('utc_2099=991224181920'); // Generalied sl.Append('general_1901=19011224181920'); sl.Append('general_1950=19501224181920'); sl.Append('general_1999=19991224181920'); sl.Append('general_2000=20001224181920'); sl.Append('general_2025=20251224181920'); sl.Append('general_2049=20491224181920'); sl.Append('general_2050=20501224181920'); sl.Append('general_2099=20991224181920'); sl2.Append('Z'); sl2.Append('+0300'); sl2.Append('+03 00'); sl2.Append('-0300'); sl2.Append('-03 00'); sl2.Append('+1122'); sl2.Append('+11 22'); sl2.Append('-1122'); sl2.Append('-11 22'); new(UCTTime); try for i := 0 to sl.Count -1 do begin self.MemoLog.Lines.Append(format('%s', [sl.Names[i]])); for j := 0 to sl2.Count -1 do begin UCTTime^.data := PAnsiChar(sl.ValueFromIndex[i]+sl2.Strings[j]); UCTTime^.length := length(sl.ValueFromIndex[i]+sl2.Strings[j]); try s1 := ''; dt := UTC_Time_Decode(UCTTime, year, month, day, hour, min, sec, tz_h, tz_m); UCTTime^.length := 0; UCTTime^.data := nil; dt := EncodeDate(year, month, day) + EncodeTime(hour, min, sec, 0); dt := dt + tz_m / (60 * 24); dt := dt + tz_h / 24.0; s1 := DateTimeToStr(dt); value := 'OK'; except on E: Exception do value := 'FAIL: ' + E.Message; end; if s1 <> '' then begin self.MemoLog.Lines.Append(format('%-20s = %-20s = %s', [sl.ValueFromIndex[i]+sl2.Strings[j], s1, value])); end else begin self.MemoLog.Lines.Append(format('%-20s = %-20s = %s', [sl.ValueFromIndex[i]+sl2.Strings[j], 'error', value])); end; end; self.MemoLog.Lines.Append('-'); end; finally dispose(UCTTime); end; finally sl.Free; sl2.Free; end; end; weiter geht's ggf. dann im englischen Forum; ![]() Herzliche Grüße qwerter Geändert von querter (11. Feb 2024 um 18:12 Uhr) Grund: URL ins EN Forum eingefügt |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |