Ok, als ich das mit den Regechsen eben gelesen habe, habe ich mir mal überlegt wie das einfacher geht. Dabei ist mir ein endlicher Automat eingefallen.
Und dann habe ich das einmal schnell umgesetzt. Ich weiß im Moment nicht ob :: am Anfang oder Ende erlaubt sind, bin aber davon ausgegangen, dass beides möglich ist. Die neue Schreibweise für
localhost ist ja ::1, insofern kommt sowas ja vor.
Auch wenn Nullblocks wohl ansonsten kaum am Anfang vorkommen werden, sind es wohl gültige IPs, deshalb akzeptiere ich diese normal.
Delphi-Quellcode:
// Autor: Sebastian Jänicke (jaenicke @ delphipraxis.net)
// [url]http://www.delphipraxis.net/post1011159.html#1011159[/url]
function SJCheckIPv6(Value:
String): Boolean;
type
CheckIPState = (cisNone, cisDelim, cisDelimStart, cisDoubleDelim,
cisHex1, cisHex2, cisHex3, cisHex4);
var
DoubleDelim: Boolean;
i, CurBlock: Integer;
CurState: CheckIPState;
begin
Result := False;
DoubleDelim := False;
CurState := cisNone;
CurBlock := 0;
for i := 1
to Length(Value)
do
case Value[i]
of
'
a'..'
f', '
0'..'
9':
case CurState
of
cisNone, cisDelim:
begin
CurState := cisHex1;
Inc(CurBlock);
if CurBlock > 8
then
Exit;
// :: steht für mind. 2 Blöcke, mehr als 8 geht nicht
end;
cisDelimStart:
Exit;
// ein einzelnes : am Anfang geht nicht
cisDoubleDelim:
begin
CurState := cisHex1;
Inc(CurBlock, 3);
if CurBlock > 8
then
Exit;
// :: steht für mind. 2 Blöcke, mehr als 8 geht nicht
DoubleDelim := True;
end;
cisHex1:
CurState := cisHex2;
cisHex2:
CurState := cisHex3;
cisHex3:
CurState := cisHex4;
cisHex4:
Exit;
// Mehr als 4 hexadezimale Zeichen hintereinander geht nicht
end;
'
:':
case CurState
of
cisNone:
CurState := cisDelimStart;
cisDelim:
if DoubleDelim
or (CurBlock > 6)
then
Exit
// zweimal :: geht nicht,
// außerdem steht :: für mind. 2 Blöcke, mehr als 8 geht nicht
else
CurState := cisDoubleDelim;
cisDelimStart:
CurState := cisDoubleDelim;
cisDoubleDelim:
Exit;
// drittes : hintereinander ist nicht erlaubt
cisHex1, cisHex2, cisHex3, cisHex4:
CurState := cisDelim;
end;
else
Exit;
// ungültiges Zeichen
end;
Result := CurState <> cisDelim;
end;
// EDIT:
Ein paar Kommentare eingestreut.
// EDIT2:
Eine eingebettete IPv4 Adresse kannte ich bis eben gar nicht, das ist nicht drin.
Allerdings sollte das auf diese Art auch ggf. einfach zu ergänzen sein.