Skip to content

Commit

Permalink
Added new OpenSSL IO Handler for OpenSSL 1.1.1
Browse files Browse the repository at this point in the history
Added new OpenSSL 1.1.1 header translation

Added new OpenSSL IO Handler

Fixed memory corruption

If GetPAnsiChar own created UTF8String will be freed when the method
will be leaved. In that case the string is no longer accessable for
OpenSSL.

No clue what to do with the USE_MARSHALLED_PTRS part, that has the same
problem...

Implemented more compiler macros in x509

Set default values for options

Added virtual methods for context initialization for #224

Fixed small translation error

Fixed small errors found with FixInsight

Added missing empty implementations

Added Header to source files

Removed own definition of size_t and time_t

Added PPIdC_INT definition to fpc

Updated OpenSSL Header translation and Source Generator

Fixed quirk with circular references

Added IdOpenSSLConsts for better x64 support

Improved xml doc

Added missing include

Added some pem functions for read/write

Added translation for objects.h and fixed some other translations

Added missing includes of IdCompilerDefines.inc

Some FPC compability

Added  PPPByte to FPC

Implemented some compiler macros in crypto

Some more OpenSSL translation

Moved TIdOpenSSLPersistent to own unit

Added new TIdC_TM

Added new x509 wrapper and callback for verification

Extracted TIdOpenSSLVersion to own unit

Fixed problem with explicite TLS

Renamed tls version properties

Implemented better way for dynamic loading

Implemented usage of dynamic loading
  • Loading branch information
mezen committed May 24, 2023
1 parent b056f33 commit 2c211e0
Show file tree
Hide file tree
Showing 240 changed files with 87,352 additions and 0 deletions.
378 changes: 378 additions & 0 deletions Lib/Protocols/OpenSSL/GenerateCode/GenerateCode.dpr
Original file line number Diff line number Diff line change
@@ -0,0 +1,378 @@
{******************************************************************************}
{ }
{ Indy (Internet Direct) - Internet Protocols Simplified }
{ }
{ https://www.indyproject.org/ }
{ https://gitter.im/IndySockets/Indy }
{ }
{******************************************************************************}
{ }
{ This file is part of the Indy (Internet Direct) project, and is offered }
{ under the dual-licensing agreement described on the Indy website. }
{ (https://www.indyproject.org/license/) }
{ }
{ Copyright: }
{ (c) 1993-2020, Chad Z. Hower and the Indy Pit Crew. All rights reserved. }
{ }
{******************************************************************************}
{ }
{ Originally written by: Fabian S. Biehn }
{ [email protected] (German & English) }
{ }
{ Contributers: }
{ Here could be your name }
{ }
{******************************************************************************}

program GenerateCode;

{$APPTYPE CONSOLE}

{$R *.res}

uses
System.Classes,
System.IOUtils,
System.StrUtils,
System.SysUtils,
System.Types,
Winapi.Windows;

type
TGenerateMode = (gmDynamic, gmStatic);

function ExpandEnvironmentVariables(const AValue: string): string;
const
MAX_LENGTH = 32767;
begin
SetLength(Result, MAX_LENGTH);
SetLength(Result, ExpandEnvironmentStrings(@AValue[1], @Result[1], MAX_LENGTH)-1);
end;

function ReplaceStatic(const ALine: string; const AShouldUseLibSSL: Boolean): string;
const
CSemicolon: string = ';';
var
i: Integer;
begin
Result := ALine;
i := Result.LastIndexOf(CSemicolon);
if i = -1 then
Exit;
Result := Result.Remove(i, CSemicolon.Length);
Result := Result.Insert(i, Format(' cdecl; external %s;', [IfThen(AShouldUseLibSSL, 'CLibSSL', 'CLibCrypto')]));
end;

function ReplaceDynamic(const ALine: string; const AMethodList: TStringList): string;
var
i: Integer;
LMethodPrefix: string;
LMethod: string;
begin
Result := ALine;

if not Result.TrimLeft.StartsWith('function') and not Result.TrimLeft.StartsWith('procedure') then
Exit;

LMethodPrefix := 'function';
i := Result.IndexOf(LMethodPrefix);
if i = -1 then
begin
LMethodPrefix := 'procedure';
i := Result.IndexOf(LMethodPrefix);
if i = -1 then
Exit;
end;

// Remove LMethodPrefix
Result := Result.Remove(i, LMethodPrefix.Length + string(' ').Length);
// Keep Result for method name extracting later
LMethod := Result.TrimLeft();
// Add LMethodPrefix after parameters
if Result.Contains(')') then
Result := Result.Replace('(', ': ' + LMethodPrefix + '(')
// No Params? Add LMethodPrefix after before return type
else if Result.Contains(': ') then
Result := Result.Replace(': ', ': ' + LMethodPrefix + ': ')
// Also no return type? Add LMethodPrefix before semi colon
else
Result := Result.Replace(';', ': ' + LMethodPrefix + ';');

if Result[Result.Length] = ';' then
Result := Result.Remove(Result.Length-1) + ' cdecl = nil;';

// Ignore comments
i := LMethod.IndexOf('}');
if i > -1 then
// +1 for including } and Trim for removing whitespace of intendation
LMethod := LMethod.Substring(i + 1{, LMethod.Length - i}).TrimLeft;
i := LMethod.IndexOf(';');
if i > -1 then
LMethod := LMethod.Remove(i);
i := LMethod.IndexOf(' ');
if i > -1 then
LMethod := LMethod.Remove(i);
i := LMethod.IndexOf(':');
if i > -1 then
LMethod := LMethod.Remove(i);
i := LMethod.IndexOf('(');
if i > -1 then
LMethod := LMethod.Remove(i);
AMethodList.Add(LMethod);
end;

procedure AddDynamicLoadingMethods(
const AFile: TStringList;
const AMethods: TStringList;
const AUsesIndex: Integer;
const AVarIndex: Integer;
const AImplementationIndex: Integer);

procedure Insert(const AList: TStringList; const s: string; var Index: Integer);
begin
AList.Insert(Index, s);
Inc(Index);
end;

function Find(const AList: TStringList; const s: string; var Index: Integer; const AOffset: Integer = 0): Boolean;
var
i: Integer;
begin
Result := False;
for i := AOffset to AList.Count - 1 do
begin
if AList[i].Contains(s) then
begin
Index := i;
Exit(True);
end;
end;
end;

var
LOffset: Integer;
LMethod: string;
begin
if AImplementationIndex = -1 then
Exit;
LOffset := AImplementationIndex + 1;

if Find(AFile, 'uses', LOffset, LOffset) then
if Find(AFile, ';', LOffset, LOffset) then
Inc(LOffset);

Insert(AFile, '', LOffset);
Insert(AFile, '{$REGION ''Generated loading and unloading methods''}', LOffSet);
Insert(AFile, 'procedure Load(const ADllHandle: TIdLibHandle; const AFailed: TStringList);', LOffset);
Insert(AFile, '', LOffset);
Insert(AFile, ' function LoadFunction(const AMethodName: string; const AFailed: TStringList): Pointer;', LOffset);
Insert(AFile, ' begin', LOffset);
Insert(AFile, ' Result := LoadLibFunction(ADllHandle, AMethodName);', LOffset);
Insert(AFile, ' if not Assigned(Result) then', LOffset);
Insert(AFile, ' AFailed.Add(AMethodName);', LOffset);
Insert(AFile, ' end;', LOffset);
Insert(AFile, '', LOffset);
Insert(AFile, 'begin', LOffset);
for LMethod in AMethods do
Insert(AFile, Format(' %0:s := LoadFunction(''%0:s'', AFailed);', [LMethod]), LOffset);
Insert(AFile, 'end;', LOffset);
Insert(AFile, '', LOffset);


Insert(AFile, 'procedure UnLoad;', LOffset);
Insert(AFile, 'begin', LOffset);
for LMethod in AMethods do
Insert(AFile, Format(' %s := nil;', [LMethod]), LOffset);
Insert(AFile, 'end;', LOffset);
Insert(AFile, '{$ENDREGION}', LOffSet);

if AVarIndex = -1 then
Exit;
LOffSet := Pred(AVarIndex);
Insert(AFile, '', LOffSet);
Insert(AFile, '{$REGION ''Generated loading and unloading methods''}', LOffSet);
Insert(AFile, 'procedure Load(const ADllHandle: TIdLibHandle; const AFailed: TStringList);', LOffSet);
Insert(AFile, 'procedure UnLoad;', LOffSet);
Insert(AFile, '{$ENDREGION}', LOffSet);

LOffSet := Succ(AUsesIndex);
Insert(AFile, ' Classes,', LOffset);
// AFile.Insert(Pred(AVarIndex), 'function Load(const ADllHandle: THandle): TArray<string>;');
end;

function ShouldSkipLine(ALine: string): Boolean;
begin
ALine := ALine.Trim;
Result := ALine.IsEmpty;
Result := Result or ALine.StartsWith('//');
Result := Result or ALine.StartsWith('(*');
Result := Result or ALine.StartsWith('*');
end;

function ReadParameters(out ASource: string; out ATarget: string; out AMode: TGenerateMode): Boolean;
var
LMode: string;
begin
Result := True;
if not FindCmdLineSwitch('Source', ASource) then
begin
Writeln('No source folder!');
Exit(False);
end;
ASource := ExpandEnvironmentVariables(ASource);

if not FindCmdLineSwitch('Target', ATarget) then
begin
Writeln('No target folder!');
Exit(False);
end;
ATarget := ExpandEnvironmentVariables(ATarget);

if not FindCmdLineSwitch('Mode', LMode) then
begin
Writeln('No mode!');
Exit(False);
end;

if LMode = 'dynamic' then
AMode := gmDynamic
else if LMode = 'static' then
AMode := gmStatic
else
begin
Writeln('Invalid mode! Use "dynamic" or "static"!');
Exit(False);
end;
end;

procedure AddGeneratedHeader(const AFile: TStringList);

function Find(const AList: TStringList; const s: string; var Index: Integer): Boolean;
var
i: Integer;
begin
Index := -1;
Result := False;
for i := 0 to AList.Count-1 do
if AList[i].Contains(s) then
begin
Index := i;
Exit(True);
end;
end;

const
CHeader: array[0..4] of string =
(
'',
'// This File is auto generated!',
'// Any change to this file should be made in the',
'// corresponding unit in the folder "intermediate"!',
''
);
var
i: Integer;
LOffset: Integer;
begin
if not Find(AFile, 'unit ', LOffset) then
Exit;
// Keep a empty line before "unit"
Dec(LOffset);
for i := Low(CHeader) to High(CHeader) do
AFile.Insert(i + LOffset, CHeader[i]);
AFile.Insert(Length(CHeader) + LOffset, '// Generation date: ' + DateTimeToStr(Now()));
end;

procedure Main;
var
LFile: string;
LStringListFile: TStringList;
i: Integer;
LVarIndex: Integer;
LUsesIndex: Integer;
LImplementationIndex: Integer;
LSource: string;
LTarget: string;
LMode: TGenerateMode;
LStringListMethods: TStringList;
LFileName: string;
LShouldUseLibSSL: Boolean;
begin
if not ReadParameters(LSource, LTarget, LMode) then
begin
Readln;
Exit;
end;

for LFile in TDirectory.GetFiles(LSource, '*.pas') do
begin
Writeln('Converting ' + LFile);
LFileName := TPath.GetFileName(LFile);
LStringListFile := TStringList.Create();
LStringListMethods := TStringList.Create();
try
LStringListFile.LoadFromFile(LFile);
LUsesIndex := -1;
LVarIndex := -1;
LImplementationIndex := -1;
LShouldUseLibSSL := MatchText(LFileName,
['IdOpenSSLHeaders_ssl.pas', 'IdOpenSSLHeaders_sslerr.pas', 'IdOpenSSLHeaders_tls1.pas']);
for i := 0 to LStringListFile.Count - 1 do
begin
// Find fist uses
if (LVarIndex = -1) and (LUsesIndex = -1) then
if LStringListFile[i].StartsWith('uses') then
LUsesIndex := i;

// var block found?
if (LVarIndex = -1) and LStringListFile[i].StartsWith('var') then
LVarIndex := i;
// Skip until we find the var block
if (LVarIndex = -1) or ShouldSkipLine(LStringListFile[i]) then
Continue;

// No need to go further than "implementation"
if LStringListFile[i] = 'implementation' then
begin
LImplementationIndex := i;
Break;
end;

case LMode of
gmDynamic:
LStringListFile[i] := ReplaceDynamic(LStringListFile[i], LStringListMethods);
gmStatic:
LStringListFile[i] := ReplaceStatic(LStringListFile[i], LShouldUseLibSSL);
end;
end;

case LMode of
gmDynamic:
AddDynamicLoadingMethods(LStringListFile, LStringListMethods, LUsesIndex, LVarIndex, LImplementationIndex);
gmStatic:
if LVarIndex > -1 then
LStringListFile.Delete(LVarIndex);
end;

AddGeneratedHeader(LStringListFile);

LStringListFile.SaveToFile(TPath.Combine(LTarget, LFileName));
finally
LStringListMethods.Free();
LStringListFile.Free();
end;
end;
end;

begin
try
Main;
Writeln('done');
except
on E: Exception do
begin
Writeln(E.ClassName, ': ', E.Message);
end;
end;
// Readln;
end.
Loading

0 comments on commit 2c211e0

Please sign in to comment.