AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Cross-Platform-Entwicklung Delphi (Android) Fehler in DateUtils behoben // TTimezone.Local.ID // Ich bitte um Prüfung
Thema durchsuchen
Ansicht
Themen-Optionen

(Android) Fehler in DateUtils behoben // TTimezone.Local.ID // Ich bitte um Prüfung

Ein Thema von QuickAndDirty · begonnen am 20. Jul 2020 · letzter Beitrag vom 24. Dez 2020
Antwort Antwort
Seite 1 von 3  1 23      
QuickAndDirty

Registriert seit: 13. Jan 2004
Ort: Hamm(Westf)
1.944 Beiträge
 
Delphi 12 Athens
 
#1

(Android) Fehler in DateUtils behoben // TTimezone.Local.ID // Ich bitte um Prüfung

  Alt 20. Jul 2020, 15:39
Wenn man
TTimezone.Local.ID innerhalb einer 64Bit Android App abruft,
dann meldet die APP in Deutschland als Zeitzonen-ID "ET" .
Das ist "Eastern Time" alias "Eastern Standard Time" alias "EST".

Korrekt wäre es, wenn als Zeitzone "CET"(deprecated) oder "Europe/Berlin" gemeldet würde
Selbst wenn ich die Zeitzone nach Portugal verlege, meldet die App dann nicht "WET" was korrekt wäre, sondern auch "ET" als Zeitzone.
Sprich der erste Buchstabe geht verloren! *ARRRGH*
Die App denkt also immer sie wäre in einer US-Zeitzone, weil es "ET" in meiner Datenbank tatsächlich gibt....

Ich habe also die Codestellen in der unit DateUtils.pas die diesen Code benutzen:
Einstring := Utf8ToString(LChars) In folgenden Code geändert:
Einstring := Trim(TEncoding.UTF8.GetString(LChars)) ;

Das Trim ist notwendig sonst funktionieren die Vergleiche nicht...
Vermutlich wäre es besser gewesen Utf8ToString zu fixen, aber ich habe mich das nicht getraut und ich habe die Typen rawstring usw. nicht auf Anhieb verstanden.

Bitte sagt mir ob die Anpassung in Ordnung ist. Soll ich das über meine Firma an die QC weitergeben oder ist das Problem schon von Emba gelöst?


Listing der ganzen Funktion in der 3 Stellen geöndert wurden.
(nach "Korrektur" ohne Gänsefüßchen suchen)
Delphi-Quellcode:
function TLocalTimeZone.GetChangesForYear(const AYear: Word): PYearlyChanges;
{$IF defined(MSWINDOWS)}
  function GetAbsoluteDateFromRule(const AYear, AMonth, ADoW, ADoWIndex: Word; AToD: TTime): TDateTime;
  const
    CReDoW: array [0 .. 6] of Integer = (7, 1, 2, 3, 4, 5, 6);

  var
    LExpDayOfWeek, LActualDayOfWeek: Word;

  begin
    { No actual rule }
    if (AMonth = 0) and (ADoW = 0) and (ADoWIndex = 0) then
      Exit(0);

    { Transform into ISO 8601 day of week }
    LExpDayOfWeek := CReDoW[ADoW];

    { Generate a date in the form of: Year/Month/1st of month }
    Result := EncodeDate(AYear, AMonth, 1);

    { Get the day of week for this newly crafted date }
    LActualDayOfWeek := DayOfTheWeek(Result);

    { We're too far off now, let's decrease the number of days till we get to the desired one }
    if LActualDayOfWeek > LExpDayOfWeek then
      Result := IncDay(Result, DaysPerWeek - LActualDayOfWeek + LExpDayOfWeek)
    else if (LActualDayOfWeek < LExpDayOfWeek) Then
      Result := IncDay(Result, LExpDayOfWeek - LActualDayOfWeek);

    { Skip the required number of weeks }
    Result := IncDay(Result, DaysPerWeek * (ADoWIndex - 1));

    { If we've skipped the day in this moth, go back a few weeks until we get it right again }
    while (MonthOf(Result) > AMonth) do
      Result := IncDay(Result, -DaysPerWeek);

    { Add the time part }
    Result := Result + AToD;
  end;

var
  LTZ: TTimeZoneInformation;
  LResult: Cardinal;

begin
  Result := AllocMem(SizeOf(TYearlyChanges));
  LTZ := Default(TTimeZoneInformation);

  { Win32 can't handle dates outside this range }
  if (AYear <= 1601) or (AYear > 30827) then
    exit;

  { Use either Vista of lower APIs. If Vista one fails, also use the lower API. }
  if TOSVersion.Check(6, 1, 1) and GetTimeZoneInformationForYear(AYear, nil, LTZ) then
    LResult := TIME_ZONE_ID_STANDARD
  else
    LResult := GetTimeZoneInformation(LTZ); { Try with the old API }

  { Exit on error }
  if LResult = TIME_ZONE_ID_INVALID then
    exit;

  { Try to obtain the daylight adjustment for the specified year }
  if LResult <> TIME_ZONE_ID_UNKNOWN then
  begin
    with LTZ.StandardDate do
      Result.FEndOfDST := GetAbsoluteDateFromRule(AYear, wMonth, wDayOfWeek,
        wDay, EncodeTime(wHour, wMinute, wSecond, 0));

    with LTZ.DaylightDate do
      Result.FStartOfDST := GetAbsoluteDateFromRule(AYear, wMonth, wDayOfWeek,
        wDay, EncodeTime(wHour, wMinute, wSecond, 0));
  end;

  Result.FBias := -SecsPerMin * (LTZ.StandardBias + LTZ.Bias);
  Result.FBiasWithDST := -SecsPerMin * (LTZ.DaylightBias + LTZ.Bias);
  Result.FName := LTZ.StandardName;
  Result.FDSTName := LTZ.DaylightName;
end;
{$ELSEIF defined(MACOS)}
function MacToDateTime(const AbsTime: CFAbsoluteTime; const ATZ: CFTimeZoneRef): TDateTime;
var
  LDate: CFGregorianDate;
begin
  { Decompose the object }
  LDate := CFAbsoluteTimeGetGregorianDate(AbsTime, ATZ);

  { Generate a TDateTime now }
  with LDate do
    Result := EncodeDateTime(year, month, day, hour, minute, Round(second), 0);
end;

procedure CopyInfo(const ATZ: CFTimeZoneRef; const AStartBT: CFAbsoluteTime; out LPt1DT, LPt2DT: TDateTime;
  out LPt1Off, LPt2Off: Int64);
var
  L1stTrans, L2ndTrans: CFAbsoluteTime;
begin
  { Calculate the first and the last transition times }
  L1stTrans := CFTimeZoneGetNextDaylightSavingTimeTransition(ATZ, AStartBT);
  L2ndTrans := CFTimeZoneGetNextDaylightSavingTimeTransition(ATZ, L1stTrans);

  { Obtain the GMT offset before first transition }
  LPt1Off := Round(CFTimeZoneGetSecondsFromGMT(ATZ, AStartBT));

  if (L1stTrans <> 0) or (L2ndTrans > L1stTrans) then
  begin
    { Convert the first transition to TDateTime }
    LPt1DT := MacToDateTime(L1stTrans, ATZ);

    { Convert the second transition to TDateTime }
    LPt2DT := MacToDateTime(L2ndTrans, ATZ);

    { Obtain the GMT offset before second transition }
    LPt2Off := Round(CFTimeZoneGetSecondsFromGMT(ATZ, L1stTrans));
  end else
  begin
    { There were no transitions. Use the base data }
    LPt2Off := LPt1Off;
    LPt1DT := MacToDateTime(AStartBT, ATZ);
    LPt2DT := LPt1DT;
  end;
end;

var
  LLocaleRef: CFLocaleRef;
  L1stJan: CFAbsoluteTime;
  LDate: CFGregorianDate;

  { What we expect }
  LStart, LEnd: TDateTime;
begin
  { Create the changes block. Keep it clean so far. }
  Result := AllocMem(SizeOf(TYearlyChanges));

  if FTZ <> nil then
  begin
    { Encode 1st Jan of the given year into Absolute time }
    with LDate do
    begin
      year := AYear;
      month := MonthJanuary;
      day := 1;
      hour := 0;
      minute := 0;
      second := 0;
    end;

    { Generate an absolute time (1st Jan Year) }
    L1stJan := CFGregorianDateGetAbsoluteTime(LDate, FTZ);

    { Use CopyInfo but reverse the variables depending on the Northern/Southern hemispheres }
    if not CFTimeZoneIsDaylightSavingTime(FTZ, L1stJan) then
      CopyInfo(FTZ, L1stJan, LStart, LEnd, Result.FBias, Result.FBiasWithDST)
    else
      CopyInfo(FTZ, L1stJan, LEnd, LStart, Result.FBiasWithDST, Result.FBias);

    { Fill the remaining parts of the structure }
    LLocaleRef := CFLocaleCopyCurrent();

    if LLocaleRef <> nil then
    begin
      { Obtain localized names of the locale (normal and DST) }
      try
        Result.FName := TCFString(CFTimeZoneCopyLocalizedName(FTZ,
          kCFTimeZoneNameStyleStandard, LLocaleRef)).AsString(True);

        Result.FDSTName := TCFString(CFTimeZoneCopyLocalizedName(FTZ,
          kCFTimeZoneNameStyleDaylightSaving, LLocaleRef)).AsString(True);
      finally
        CFRelease(LLocaleRef);
      end;
    end else
    begin
      { Fall back to std info }
      Result.FName := TCFString(CFTimeZoneGetName(FTZ));
      Result.FDSTName := Result.FName;
    end;

    Result.FStartOfDST := IncSecond(LStart, Result.FBias - Result.FBiasWithDST); // Remove the save time from result
    Result.FEndOfDST := IncSecond(LEnd, Result.FBiasWithDST - Result.FBias); // Add the save time to result
  end;
end;
{$ELSEIF defined(POSIX)}
var
  LComp: tm;
  LTime: time_t;
  LLastOffset, LDay: Integer;
  LIsSecondCycle, LIsStandard: Boolean;
  LChars: TBytes;
begin
  SetLength(LChars, 256);
  { Create the changes block. Keep it clean so far. }
  Result := AllocMem(SizeOf(TYearlyChanges));

  if (SizeOf(LongInt) = 4) and ((AYear < 1970) or (AYear > 2037)) then
    Exit; // Not supported

  { Generate a value that starts with 1st of the current year }
  FillChar(LComp, SizeOf(LComp), 0);
  LComp.tm_mday := 1;
  LComp.tm_year := AYear - 1900;
  LTime := mktime(LComp);

  if LTime = -1 then
    Exit; // Some error occured!

  { Unknown DST information. Quit. }
  if LComp.tm_isdst < -1 then
    Exit;

  { Check if the DST or STD time was in effect at 1st Jan }
  LIsStandard := LComp.tm_isdst = 0;

  { Prepare to iterate over the year }
  LLastOffset := LComp.tm_gmtoff;
  LIsSecondCycle := false;

  { Initialize info, in some locales like Russia and in some years the clock is not changed for daylight saving }
  Result.FStartOfDST := IncSecond(FileDateToDateTime(LTime), LLastOffset - LComp.tm_gmtoff);
  Result.FEndOfDST := Result.FStartOfDST;
  Result.FBias := LLastOffset;
  Result.FDSTName := '';
  Result.FBiasWithDST := LLastOffset;
  strftime(MarshaledAString(LChars), Length(LChars), '%Z', LComp); // DO NOT LOCALIZE
  Result.FName := Trim(TEncoding.UTF8.GetString(LChars));//<----- Korrektur Alter Code----> // Result.FName := Utf8ToString(LChars);

  for LDay := 0 to DaysInAYear(AYear) - 1 do
  begin
    { Skip to next day }
    Inc(LTime, SecsPerDay);

    { Decompose the time }
    if localtime_r(LTime, LComp) <> @LComp then
      Exit;

    if LComp.tm_gmtoff <> LLastOffset then
    begin
      { We found the day when the time change occured. Serach the hour now. }

      repeat
        Dec(LTime, SecsPerHour);

        { Decompose the time }
        if localtime_r(LTime, LComp) <> @LComp then
          Exit;
      until LComp.tm_gmtoff = LLastOffset;

      { Search for the minute }
      repeat
        Inc(LTime, SecsPerMin);

        { Decompose the time }
        if localtime_r(LTime, LComp) <> @LComp then
          Exit;
      until LComp.tm_gmtoff <> LLastOffset;

      { Generate the time zone abbreviation }
      strftime(MarshaledAString(LChars), Length(LChars), '%Z', LComp); // DO NOT LOCALIZE
      if LIsStandard then
      begin
        { We were in the standard period }
        Result.FStartOfDST := IncSecond(FileDateToDateTime(LTime), LLastOffset - LComp.tm_gmtoff);
        Result.FBias := LLastOffset;
        Result.FDSTName := Trim(TEncoding.UTF8.GetString(LChars));//<----- Korrektur Alter Code----> //Result.FDSTName := Utf8ToString(LChars);
      end else
      begin
        { We were in the DST period }
        Result.FEndOfDST := IncSecond(FileDateToDateTime(LTime), LLastOffset - LComp.tm_gmtoff);
        Result.FBiasWithDST := LLastOffset;
        Result.FName := Trim(TEncoding.UTF8.GetString(LChars));//<----- Korrektur Alter Code----> //Result.FName := Utf8ToString(LChars);
      end;

      { Set the last offset }
      LLastOffset := LComp.tm_gmtoff;
      LIsStandard := not LIsStandard;

      { Die if this is the second cycle }
      if LIsSecondCycle then
        Exit
      else
        LIsSecondCycle := true;
    end;
  end;
end;
{$ENDIF}
Andreas
Monads? Wtf are Monads?

Geändert von QuickAndDirty (20. Jul 2020 um 15:53 Uhr)
  Mit Zitat antworten Zitat
QuickAndDirty

Registriert seit: 13. Jan 2004
Ort: Hamm(Westf)
1.944 Beiträge
 
Delphi 12 Athens
 
#2

AW: (Android) Fehler in DateUtils behoben // TTimezone.Local.ID // Ich bitte um Prüfu

  Alt 21. Jul 2020, 09:04
Sorry, aber gibts grundsätzlich etwas gegen diese Lösung einzuwenden?
Ich will nicht wie ein Idiot dastehen wenn ich das bei QC posten sollte.
Andreas
Monads? Wtf are Monads?
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
4.116 Beiträge
 
Delphi 12 Athens
 
#3

AW: (Android) Fehler in DateUtils behoben // TTimezone.Local.ID // Ich bitte um Prüfu

  Alt 21. Jul 2020, 11:25
Man kann das nur Aufwendig mit den Lokalisierungen Testen.

Du schreibst ja dass das Problem ursächlich beim UTF8 konvertieren liegt,
gibt es dafür vielleicht einen kleinen Testcode der den Fehler, ohne das ganze Android/Language Gewusel ?

Ich verstehe Dich so, dass
Utf8ToString(LChars) // mit LChars: TBytes; aus z.B. 'CET' nur 'ET' macht, und das erste Zeichen verschluckt.

Es könnte sein das UTF8ToString wirklich zwingend ein BOM für UTF8 benötigt,
und dadurch das erste Zeichen verschluckt.
Kann ich mir aber eigentlich nicht wirklich vorstellen, das müsste ja an zig. Stellen auftauchen.

Die Frage wäre was in LChars wirkliich drinsteht, ist das ein ANSI-String ?
https://android.developreference.com...+in+Rad+Studio

Ein Mini-Beispiel dazu wäre auf jeden Fall sinnvoll.

Geändert von Rollo62 (21. Jul 2020 um 11:31 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#4

AW: (Android) Fehler in DateUtils behoben // TTimezone.Local.ID // Ich bitte um Prüfu

  Alt 21. Jul 2020, 11:37
Zitat:
Delphi-Quellcode:
Result.FName := Trim(TEncoding.UTF8.GetString(LChars));
Result.FName := Utf8ToString(LChars);
OK, abgesehn vom TRIM sollte, UTF8.GetString und Utf8ToString doch eigentlich gleiche Ergebnisse liefern,
und wenn sie das nicht tun, dann sollte man besser auch gleich mit prüfen was dort schief läuft.


Ansonsten:

Warum gibt die Funktion einen Pointer zurück, anstatt des Records?
Gerade hier ist das eine Liebslingsstelle für Speicherlecks und dazumal es absolot sinnlos ist, weil immer was zurückgegeben wird im Delphi (XE) ist/war das auch noch ein Record.

Und an ein paar gewissen Stellen würde ich noch eine Bereichsprüfung einfügen.
Zitat:
ExpDayOfWeek := CReDoW[ADoW];
entweder die {$RANGECHECKS ON} aktiv,
oder mit Fehlermelduing if ADoW > 6 then raise ...
oder zumindestens wildlaufende Speicherzugriffe abfangen ExpDayOfWeek := CReDoW[ADoW mod 7]; , was hier möglich ist, also einfach den Überstand in die nachfolgenden Wochen verschieben.

Und sonst erstmal noch nicht weiter gesucht. (war so das "Schlimmste", was gleich auf den ersten Blick brutal ins Auge stach)
$2B or not $2B

Geändert von himitsu (21. Jul 2020 um 11:40 Uhr)
  Mit Zitat antworten Zitat
QuickAndDirty

Registriert seit: 13. Jan 2004
Ort: Hamm(Westf)
1.944 Beiträge
 
Delphi 12 Athens
 
#5

AW: (Android) Fehler in DateUtils behoben // TTimezone.Local.ID // Ich bitte um Prüfu

  Alt 21. Jul 2020, 15:15
@himitsu
Ich habe wirklich nur 3 Zeilen in dem Listing verändert. "Korrektur" steht neben dran. Der rest ist original code aus dateutils.pas.
Ich habe quasi in der Funktion aus der Dateutils.pas einfach 3 stellen gepatcht.
Ich wollte möglichst wenig EmbarcaderoCode anfassen um mein Problem zu lösen.

@Rollo62
Ich habe jetzt mal die Funktion angesehen die den Fehler macht.
Liegst in der "System.pas"
Leider bin ich nicht gut bewandert in "codierung". Ich bin darauf angewiesen das die Convertierungsmethoden funktionieren.
UTF8ToUnicode gibt es in etlichen überladenen methoden...


unit System.pas
Delphi-Quellcode:
function UTF8ToString(const S: array of Byte): string; overload;
var
  Dest: array[0..511] of Char;
begin
  SetString(Result, Dest, UTF8ToUnicode(Dest, Length(Dest), _PAnsiChr(@S[1]), S[0])-1);
end;

{$IFDEF USE_LIBICU}
{$IFDEF LINUX}
function Utf8ToUnicodeICU(Dest: PWideChar; MaxDestChars: Cardinal; Source: _PAnsiChr; SourceBytes: Cardinal): Cardinal;
{$ELSE !LINUX}
function Utf8ToUnicode(Dest: PWideChar; MaxDestChars: Cardinal; Source: _PAnsiChr; SourceBytes: Cardinal): Cardinal;
{$ENDIF LINUX}
var
  DestLen: Int32;
  ErrorConv: UErrorCode;
begin
  Result := 0;
  if Source = nil then Exit;
  ErrorConv := 0;
  DestLen := 0;
  u_strFromUTF8(PUChar(Dest), MaxDestChars, DestLen, MarshaledAString(Source), SourceBytes, ErrorConv);
  Result := DestLen;
  if Dest <> nil then
  begin
    if (Result > 0) and (Result <= MaxDestChars) then
    begin
      if Result = MaxDestChars then
      begin
        if (Result > 1) and (Word(Dest[Result - 1]) >= $DC00) and (Word(Dest[Result - 1]) <= $DFFF) then
          Dec(Result);
      end else
        Inc(Result);
      Dest[Result - 1] := #0;
    end;
  end;
end;

Edit:
!!!!!!!!!!!!!!HOLY COW!!!!!!!!!!
Delphi-Quellcode:
function UTF8ToString(const S: array of Byte): string; overload;
var
  Dest: array[0..511] of Char;
begin
  SetString(Result, Dest, UTF8ToUnicode(Dest, Length(Dest), _PAnsiChr(@S[1]), S[0])-1); // _PAnsiChr(@S[1]) ist "ET" _PAnsiChr(@S[0]) müsste dann "CET" sein???
end;
Andreas
Monads? Wtf are Monads?

Geändert von QuickAndDirty (21. Jul 2020 um 15:48 Uhr)
  Mit Zitat antworten Zitat
QuickAndDirty

Registriert seit: 13. Jan 2004
Ort: Hamm(Westf)
1.944 Beiträge
 
Delphi 12 Athens
 
#6

AW: (Android) Fehler in DateUtils behoben // TTimezone.Local.ID // Ich bitte um Prüfu

  Alt 21. Jul 2020, 15:48
OK, Was nun???
Andreas
Monads? Wtf are Monads?
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#7

AW: (Android) Fehler in DateUtils behoben // TTimezone.Local.ID // Ich bitte um Prüfu

  Alt 21. Jul 2020, 16:39
Nun: Bugmeldung im Quality-Portal

S[Low(string)] statt S[1]
oder gleich den Mist mit dem @ lassen, also PAnsiChr(S) statt PAnsiChr(@S[1]) .

Grund: $ZeroBasedStrings sind im NextGen (Android/iOS) aktiv.
http://docwiki.embarcadero.com/RADSt...rings_(Delphi)
$2B or not $2B
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
4.116 Beiträge
 
Delphi 12 Athens
 
#8

AW: (Android) Fehler in DateUtils behoben // TTimezone.Local.ID // Ich bitte um Prüfu

  Alt 21. Jul 2020, 16:56
Nur mal gerade in den Delphi-Sourcen gesucht, es gibt allein ca. 34-40 Units die das benutzen.
Das würde ja an allen möglichen Stellen abrauchen, kann ich gar nicht glauben
Ganz zu schweigen von externen Libraries und Code.
Macht Emba keine Unit-Tests ?

Was ist jetzt besser, nur bei DateUtils zu fixen oder direkt das Übel an der Wurzel ? Gute Frage.

Ich muss wohl mal bei mir checken ob und wo ich das nutze.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#9

AW: (Android) Fehler in DateUtils behoben // TTimezone.Local.ID // Ich bitte um Prüfu

  Alt 21. Jul 2020, 17:07
Besser ist es immer das grundlegende Problem, anstatt nur die Symptome zu beheben.
Rein funktionell geht es auch den "Fehler" an beiden Stellen zu beheben, wobei TEncoding da einen größeren Overhead hat.


Wenn du über den String-Helper gehst, dann ist es dort auch überall 0-basiered und in jeder Platform einheitlich.
S.Chars(0) = S[1] {im Windows} ... abgesehn von dem nutzlosen Funktionsaufruf bei .Chars .

Auch beim Copy-Befehl seh ich zu oft, dass es bei 0 beginnt (Copy(S, 0, ...) ), was "oft" funktioniert, da es nach unten abgefangen wird, aber mit höheren Indize wird dann natürlich auch falsch zugegriffen, wenn der Entwickler das immer falsch macht.
$2B or not $2B
  Mit Zitat antworten Zitat
samso

Registriert seit: 29. Mär 2009
439 Beiträge
 
#10

AW: (Android) Fehler in DateUtils behoben // TTimezone.Local.ID // Ich bitte um Prüfu

  Alt 21. Jul 2020, 18:07

Delphi-Quellcode:
function UTF8ToString(const S: array of Byte): string; overload;
var
  Dest: array[0..511] of Char;
begin
  SetString(Result, Dest, UTF8ToUnicode(Dest, Length(Dest), _PAnsiChr(@S[1]), S[0])-1); // _PAnsiChr(@S[1]) ist "ET" _PAnsiChr(@S[0]) müsste dann "CET" sein???
end;


Diese Funktion ist anscheinend von ShortString nach "array of bytes" adaptiert worden. Man beachte das S[0]. Das soll ja wohl die Länge sein..
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es 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

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:50 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz