include "encoding.s7i";
const string: PEM_HEADER_START is "-----BEGIN ";
const string: PEM_HEADER_END is "-----";
const string: PEM_FOOTER_START is "-----END ";
const type: pemHeaderHash is hash[string] string;
const type: pemObject is new struct
var string: pemType is "";
var string: content is "";
var pemHeaderHash: headers is pemHeaderHash.value;
end struct;
const func pemObject: pemObject (in string: pemType, in string: content) is func
result
var pemObject: pemObj is pemObject.value;
begin
pemObj.pemType := pemType;
pemObj.content := content;
end func;
const func string: str (in pemObject: pemObj) is
return PEM_HEADER_START & pemObj.pemType & PEM_HEADER_END & "\n" &
toBase64(pemObj.content) & "\n" &
PEM_FOOTER_START & pemObj.pemType & PEM_HEADER_END & "\n";
const func pemObject: pemObject (in string: pemData) is func
result
var pemObject: pemObj is pemObject.value;
local
var integer: pos1 is 0;
var integer: pos2 is 0;
var string: pemType is "";
var string: footer is "";
begin
if startsWith(pemData, PEM_HEADER_START) then
pos1 := succ(length(PEM_HEADER_START));
pos2 := pos(pemData, PEM_HEADER_END, pos1);
if pos2 <> 0 then
pemType := pemData[pos1 .. pred(pos2)];
pos1 := pos2 + length(PEM_HEADER_END);
footer := PEM_FOOTER_START & pemType & PEM_HEADER_END;
pos2 := pos(pemData, footer, pos1);
if pos2 <> 0 then
repeat
decr(pos2);
until pos2 = 0 or (pemData[pos2] <> '\n' and pemData[pos2] <> '\r');
pemObj.pemType := pemType;
pemObj.content := fromBase64(pemData[pos1 .. pos2]);
else
raise RANGE_ERROR;
end if;
else
raise RANGE_ERROR;
end if;
else
raise RANGE_ERROR;
end if;
end func;
const func pemObject: readPemObject (inout file: pemFile) is func
result
var pemObject: pemObj is pemObject.value;
local
var string: line is "";
var string: pemType is "";
var string: base64 is "";
var integer: colonPos is 0;
var string: headerKey is "";
var string: headerValue is "";
begin
repeat
line := getln(pemFile);
until (startsWith(line, PEM_HEADER_START) and
endsWith(line, PEM_HEADER_END)) or eof(pemFile);
if not eof(pemFile) then
pemType := line[succ(length(PEM_HEADER_START)) .. length(line) - length(PEM_HEADER_END)];
line := getln(pemFile);
colonPos := pos(line, ':');
while not (startsWith(line, PEM_FOOTER_START) or eof(pemFile)) and
colonPos <> 0 do
headerKey := line[.. pred(colonPos)];
headerValue := line[succ(colonPos) ..];
line := getln(pemFile);
while startsWith(line, " ") do
headerValue &:= "\n" & line[2 ..];
line := getln(pemFile);
end while;
pemObj.headers @:= [headerKey] headerValue;
colonPos := pos(line, ':');
end while;
if line = "" then
line := getln(pemFile);
end if;
while not (startsWith(line, PEM_FOOTER_START) or eof(pemFile)) do
base64 &:= line;
line := getln(pemFile);
end while;
if line = PEM_FOOTER_START & pemType & PEM_HEADER_END then
pemObj.pemType := pemType;
pemObj.content := fromBase64(base64);
end if;
end if;
end func;