Skip to content

Commit ea44a04

Browse files
authored
Merge pull request #6 from DarkCoderSc/dev
The Content Reader feature introduces a new capability that allows users to remotely open and view readable files in a dedicated editor. Currently available for files only, this feature enables instant server-side access to any file, regardless of its size. To optimize performance, the remote file is paginated, meaning that only a user-defined portion (chunk) of the file is transmitted and displayed at a time, rather than transferring the entire file. The content is presented as a hexadecimal table, with built-in tools to extract and highlight ANSI and Unicode strings from the streamed data. This approach ensures that even very large files can be opened instantly for view-only access, without requiring a full download or local storage. This feature has been integrated into the file manager for readable files. You can also manually stream a remote file through a dedicated dialog. Finally, this release includes several minor changes and improvements.
2 parents fc0f0aa + 08970ce commit ea44a04

36 files changed

+3633
-449
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<BorlandProject>
33
<Transactions>
4-
<Transaction>2025/08/15 09:04:51.000.443,C:\Users\jples\Desktop\OptixGate\Client GUI\ClientGUIGroup.groupproj=C:\Users\jples\Documents\Embarcadero\Studio\Projects\ProjectGroup1.groupproj</Transaction>
4+
<Transaction>2025/08/15 09:04:51.000.443,C:\Users\jples\Documents\Embarcadero\Studio\Projects\ProjectGroup1.groupproj=C:\Users\jples\Desktop\OptixGate\Client GUI\ClientGUIGroup.groupproj</Transaction>
55
</Transactions>
66
<Default.Personality>
7-
<Projects ActiveProject="C:\Users\jples\Desktop\OptixGate\Client GUI\Client_GUI.dproj"/>
7+
<Projects ActiveProject="C:\Users\jples\Desktop\OptixGate\Client GUI\Client_GUI_OpenSSL.dproj"/>
88
</Default.Personality>
99
</BorlandProject>

Client GUI/Client_GUI.dpr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ uses
9595
Optix.Process.Enum in '..\Shared\Optix.Process.Enum.pas',
9696
Optix.Func.Commands.Registry in '..\Shared\Functions\Optix.Func.Commands.Registry.pas',
9797
Optix.Registry.Helper in '..\Shared\Optix.Registry.Helper.pas',
98-
Optix.Registry.Enum in '..\Shared\Optix.Registry.Enum.pas';
98+
Optix.Registry.Enum in '..\Shared\Optix.Registry.Enum.pas',
99+
Optix.Func.Commands.ContentReader in '..\Shared\Functions\Optix.Func.Commands.ContentReader.pas';
99100

100101
{$R *.res}
101102
{$R ..\Server\data.res}

Client GUI/Client_GUI.dproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@
198198
<DCCReference Include="..\Shared\Functions\Optix.Func.Commands.Registry.pas"/>
199199
<DCCReference Include="..\Shared\Optix.Registry.Helper.pas"/>
200200
<DCCReference Include="..\Shared\Optix.Registry.Enum.pas"/>
201+
<DCCReference Include="..\Shared\Functions\Optix.Func.Commands.ContentReader.pas"/>
201202
<BuildConfiguration Include="Base">
202203
<Key>Base</Key>
203204
</BuildConfiguration>

Client GUI/Client_GUI_OpenSSL.dpr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ uses
106106
Optix.Process.Enum in '..\Shared\Optix.Process.Enum.pas',
107107
Optix.Func.Commands.Registry in '..\Shared\Functions\Optix.Func.Commands.Registry.pas',
108108
Optix.Registry.Helper in '..\Shared\Optix.Registry.Helper.pas',
109-
Optix.Registry.Enum in '..\Shared\Optix.Registry.Enum.pas';
109+
Optix.Registry.Enum in '..\Shared\Optix.Registry.Enum.pas',
110+
Optix.Func.Commands.ContentReader in '..\Shared\Functions\Optix.Func.Commands.ContentReader.pas';
110111

111112
{$R *.res}
112113
{$R ..\Server\data.res}

Client GUI/Client_GUI_OpenSSL.dproj

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<FrameworkType>VCL</FrameworkType>
66
<Base>True</Base>
77
<Config Condition="'$(Config)'==''">Release</Config>
8-
<Platform Condition="'$(Platform)'==''">Win32</Platform>
8+
<Platform Condition="'$(Platform)'==''">Win64</Platform>
99
<ProjectName Condition="'$(ProjectName)'==''">Client_GUI_OpenSSL</ProjectName>
1010
<TargetedPlatforms>3</TargetedPlatforms>
1111
<AppType>Application</AppType>
@@ -85,6 +85,8 @@
8585
<DCC_DcuOutput>.\bins\OpenSSL\$(Platform)\$(Config)</DCC_DcuOutput>
8686
<AppDPIAwarenessMode>none</AppDPIAwarenessMode>
8787
<DCC_Define>CLIENT;CLIENT_GUI;USETLS;$(DCC_Define)</DCC_Define>
88+
<VerInfo_MinorVer>3</VerInfo_MinorVer>
89+
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.3.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
8890
</PropertyGroup>
8991
<PropertyGroup Condition="'$(Base_Win64)'!=''">
9092
<DCC_UsePackage>vclwinx;fmx;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;FireDACCommonODBC;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;bindcompfmx;inetdb;FireDACSqliteDriver;DbxClientDriver;soapmidas;vclactnband;fmxFireDAC;dbexpress;DBXMySQLDriver;VclSmp;inet;vcltouch;fmxase;dbrtl;fmxdae;FireDACMSAccDriver;CustomIPTransport;vcldsnap;DBXInterBaseDriver;IndySystem;Skia.Package.VCL;vcldb;VirtualTreesR;vclFireDAC;bindcomp;FireDACCommon;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;adortl;vclimg;FireDACPgDriver;FireDAC;inetdbxpress;xmlrtl;tethering;bindcompvcl;dsnap;CloudService;fmxobj;bindcompvclsmp;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)</DCC_UsePackage>
@@ -96,6 +98,8 @@
9698
<DCC_DcuOutput>.\bins\OpenSSL\$(Platform)\$(Config)</DCC_DcuOutput>
9799
<AppDPIAwarenessMode>none</AppDPIAwarenessMode>
98100
<DCC_Define>CLIENT;CLIENT_GUI;USETLS;$(DCC_Define)</DCC_Define>
101+
<VerInfo_MinorVer>3</VerInfo_MinorVer>
102+
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.3.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
99103
</PropertyGroup>
100104
<PropertyGroup Condition="'$(Cfg_1)'!=''">
101105
<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
@@ -210,6 +214,7 @@
210214
<DCCReference Include="..\Shared\Functions\Optix.Func.Commands.Registry.pas"/>
211215
<DCCReference Include="..\Shared\Optix.Registry.Helper.pas"/>
212216
<DCCReference Include="..\Shared\Optix.Registry.Enum.pas"/>
217+
<DCCReference Include="..\Shared\Functions\Optix.Func.Commands.ContentReader.pas"/>
213218
<BuildConfiguration Include="Base">
214219
<Key>Base</Key>
215220
</BuildConfiguration>
@@ -231,8 +236,10 @@
231236
<Source Name="MainSource">Client_GUI_OpenSSL.dpr</Source>
232237
</Source>
233238
<Excluded_Packages>
234-
<Excluded_Packages Name="$(BDSBIN)\dcloffice2k290.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
235-
<Excluded_Packages Name="$(BDSBIN)\dclofficexp290.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
239+
<Excluded_Packages Name="$(BDSBIN)\bcboffice2k370.bpl">Embarcadero C++Builder Office 2000 Servers Package</Excluded_Packages>
240+
<Excluded_Packages Name="$(BDSBIN)\bcbofficexp370.bpl">Embarcadero C++Builder Office XP Servers Package</Excluded_Packages>
241+
<Excluded_Packages Name="$(BDSBIN)\dcloffice2k370.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
242+
<Excluded_Packages Name="$(BDSBIN)\dclofficexp370.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
236243
</Excluded_Packages>
237244
</Delphi.Personality>
238245
<Deployment Version="5">

Client/Client.dpr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ uses
9292
Optix.Func.Commands.Shell in '..\Shared\Functions\Optix.Func.Commands.Shell.pas',
9393
Optix.Func.Commands.Registry in '..\Shared\Functions\Optix.Func.Commands.Registry.pas',
9494
Optix.Registry.Helper in '..\Shared\Optix.Registry.Helper.pas',
95-
Optix.Registry.Enum in '..\Shared\Optix.Registry.Enum.pas';
95+
Optix.Registry.Enum in '..\Shared\Optix.Registry.Enum.pas',
96+
Optix.Func.Commands.ContentReader in '..\Shared\Functions\Optix.Func.Commands.ContentReader.pas';
9697

9798
begin
9899
IsMultiThread := True;

Client/Client.dproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@
156156
<DCCReference Include="..\Shared\Functions\Optix.Func.Commands.Registry.pas"/>
157157
<DCCReference Include="..\Shared\Optix.Registry.Helper.pas"/>
158158
<DCCReference Include="..\Shared\Optix.Registry.Enum.pas"/>
159+
<DCCReference Include="..\Shared\Functions\Optix.Func.Commands.ContentReader.pas"/>
159160
<BuildConfiguration Include="Base">
160161
<Key>Base</Key>
161162
</BuildConfiguration>

Client/Client_OpenSSL.dpr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ uses
9898
Optix.Func.Commands.Shell in '..\Shared\Functions\Optix.Func.Commands.Shell.pas',
9999
Optix.Func.Commands.Registry in '..\Shared\Functions\Optix.Func.Commands.Registry.pas',
100100
Optix.Registry.Helper in '..\Shared\Optix.Registry.Helper.pas',
101-
Optix.Registry.Enum in '..\Shared\Optix.Registry.Enum.pas';
101+
Optix.Registry.Enum in '..\Shared\Optix.Registry.Enum.pas',
102+
Optix.Func.Commands.ContentReader in '..\Shared\Functions\Optix.Func.Commands.ContentReader.pas';
102103

103104
begin
104105
IsMultiThread := True;

Client/Client_OpenSSL.dproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@
180180
<DCCReference Include="..\Shared\Functions\Optix.Func.Commands.Registry.pas"/>
181181
<DCCReference Include="..\Shared\Optix.Registry.Helper.pas"/>
182182
<DCCReference Include="..\Shared\Optix.Registry.Enum.pas"/>
183+
<DCCReference Include="..\Shared\Functions\Optix.Func.Commands.ContentReader.pas"/>
183184
<BuildConfiguration Include="Base">
184185
<Key>Base</Key>
185186
</BuildConfiguration>

Client/Units/Threads/Optix.Protocol.SessionHandler.pas

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ interface
5555

5656
Optix.Protocol.Client.Handler, Optix.Protocol.Packet, Optix.Protocol.Preflight, Optix.Protocol.Worker.FileTransfer,
5757
Optix.Func.Commands, Optix.Func.Commands.Base, Optix.Actions.ProcessHandler, Optix.Func.Commands.FileSystem,
58-
Optix.Func.Commands.Shell;
58+
Optix.Func.Commands.Shell, Optix.FileSystem.Helper, Optix.Func.Commands.ContentReader;
5959
// ---------------------------------------------------------------------------------------------------------------------
6060

6161
type
@@ -79,6 +79,7 @@ TOptixSessionHandlerThread = class(TOptixClientHandlerThread)
7979
FTasks : TObjectList<TOptixTask>;
8080
FShellInstances : TObjectList<TProcessHandler>;
8181
FFileTransferOrchestrator : TOptixFileTransferOrchestratorThread;
82+
FContentReaders : TObjectDictionary<TGUID, TContentReader>;
8283

8384
{$IFDEF CLIENT_GUI}
8485
FOnConnectedToServer : TOnConnectedToServer;
@@ -107,6 +108,10 @@ TOptixSessionHandlerThread = class(TOptixClientHandlerThread)
107108
procedure BreakShellInstance(const ACommand : TOptixBreakShellInstance);
108109
procedure StdinToShellInstance(const ACommand : TOptixStdinShellInstance);
109110

111+
procedure BrowseContentReaderPage(const AReaderId : TGUID; const APageNumber : Int64;
112+
const ANewPageSize : UInt64 = 0; const AFirstPage : Boolean = False);
113+
procedure CreateAndRegisterNewContentReader(const ACommand : TOptixCommandCreateFileContentReader);
114+
110115
procedure Connected(); override;
111116
procedure Disconnected(); override;
112117
procedure PacketReceived(const ASerializedPacket : ISuperObject); override;
@@ -138,6 +143,7 @@ procedure TOptixSessionHandlerThread.Initialize();
138143
FFileTransferOrchestrator := nil;
139144
FTasks := TObjectList<TOptixTask>.Create(True);
140145
FShellInstances := TObjectList<TProcessHandler>.Create(True);
146+
FContentReaders := TObjectDictionary<TGUID, TContentReader>.Create([doOwnsValues]);
141147

142148
{$IFDEF CLIENT_GUI}
143149
FOnConnectedToServer := nil;
@@ -164,6 +170,9 @@ procedure TOptixSessionHandlerThread.Finalize();
164170

165171
if Assigned(FShellInstances) then
166172
FreeAndNil(FShellInstances);
173+
174+
if Assigned(FContentReaders) then
175+
FreeAndNil(FContentReaders);
167176
end;
168177

169178
{ TOptixSessionHandlerThread.InitializePreflightRequest }
@@ -349,6 +358,46 @@ procedure TOptixSessionHandlerThread.RegisterNewFileTransfer(const ATransfer : T
349358
FFileTransferOrchestrator.AddTransfer(ATransfer);
350359
end;
351360

361+
{ TOptixSessionHandlerThread.BrowseContentReaderPage }
362+
procedure TOptixSessionHandlerThread.BrowseContentReaderPage(const AReaderId : TGUID; const APageNumber : Int64;
363+
const ANewPageSize : UInt64 = 0; const AFirstPage : Boolean = False);
364+
begin
365+
var AReader := TContentReader(nil);
366+
if not FContentReaders.TryGetValue(AReaderId, AReader) then
367+
Exit();
368+
///
369+
370+
if ANewPageSize > 0 then
371+
AReader.PageSize := ANewPageSize;
372+
373+
var ACommandClass : TOptixCommandContentReaderPageClass;
374+
375+
if AFirstPage then
376+
ACommandClass := TOptixCommandContentReaderFirstPage
377+
else
378+
ACommandClass := TOptixCommandContentReaderPage;
379+
380+
///
381+
AddPacket(ACommandClass.Create(
382+
AReaderId,
383+
AReader,
384+
APageNumber
385+
));
386+
end;
387+
388+
{ TOptixSessionHandlerThread.CreateAndRegisterNewContentReader }
389+
procedure TOptixSessionHandlerThread.CreateAndRegisterNewContentReader(
390+
const ACommand : TOptixCommandCreateFileContentReader);
391+
begin
392+
var AReader := TContentReader.Create(ACommand.FilePath, ACommand.PageSize);
393+
394+
var AReaderId := TGUID.NewGuid;
395+
396+
FContentReaders.Add(AReaderId, AReader);
397+
398+
BrowseContentReaderPage(AReaderId, 0, 0, True);
399+
end;
400+
352401
{ TOptixSessionHandlerThread.Connected }
353402
procedure TOptixSessionHandlerThread.Connected();
354403
begin
@@ -405,10 +454,6 @@ procedure TOptixSessionHandlerThread.PacketReceived(const ASerializedPacket : IS
405454

406455
var AClassName := ASerializedPacket.S['PacketClass'];
407456

408-
var AWindowGUID := TGUID.Empty;
409-
if ASerializedPacket.Contains('FWindowGUID') then
410-
AWindowGUID := TGUID.Create(ASerializedPacket.S['FWindowGUID']);
411-
412457
var AOptixPacket : TOptixPacket := nil;
413458
var AHandleMemory : Boolean := True;
414459
try
@@ -420,7 +465,7 @@ procedure TOptixSessionHandlerThread.PacketReceived(const ASerializedPacket : IS
420465
Exit();
421466
///
422467

423-
// Optix Action Command (& Response)
468+
// Optix Action Command (& Response) -----------------------------------------------------------------------------
424469
if AOptixPacket is TOptixCommandAction then begin
425470
TOptixCommandActionResponse(AOptixPacket).DoAction();
426471

@@ -430,16 +475,16 @@ procedure TOptixSessionHandlerThread.PacketReceived(const ASerializedPacket : IS
430475
///
431476
AddPacket(AOptixPacket);
432477
end;
433-
// Optix Task Command
478+
// Optix Task Command --------------------------------------------------------------------------------------------
434479
end else if AOptixPacket is TOptixCommandTask then begin
435480
var ATask := TOptixCommandTask(AOptixPacket).CreateTask(TOptixCommand(AOptixPacket));
436481

437482
///
438483
RegisterAndStartNewTask(ATask);
439-
// Optix Transfers (Download & Upload)
484+
// Optix Transfers (Download & Upload) ---------------------------------------------------------------------------
440485
end else if AOptixPacket is TOptixCommandTransfer then
441486
RegisterNewFileTransfer(TOptixCommandTransfer(AOptixPacket))
442-
// Shell Commands
487+
// Shell Commands ------------------------------------------------------------------------------------------------
443488
else if AOptixPacket is TOptixCommandShell then begin
444489
if AOptixPacket is TOptixStartShellInstance then
445490
RegisterAndStartNewShellInstance(TOptixStartShellInstance(AOptixPacket))
@@ -449,8 +494,19 @@ procedure TOptixSessionHandlerThread.PacketReceived(const ASerializedPacket : IS
449494
BreakShellInstance(TOptixBreakShellInstance(AOptixPacket))
450495
else if AOptixPacket is TOptixStdinShellInstance then
451496
StdinToShellInstance(TOptixStdinShellInstance(AOptixPacket));
452-
// Simple Commands
453-
end else if AOptixPacket is TOptixSimpleCommand then begin
497+
// Content Reader Commands ---------------------------------------------------------------------------------------
498+
end else if AOptixPacket is TOptixCommandCreateFileContentReader then
499+
CreateAndRegisterNewContentReader(TOptixCommandCreateFileContentReader(AOptixPacket))
500+
else if AOptixPacket is TOptixCommandCloseContentReader then
501+
FContentReaders.Remove(AOptixPacket.WindowGUID)
502+
else if AOptixPacket is TOptixCommandBrowseContentReader then
503+
BrowseContentReaderPage(
504+
AOptixPacket.WindowGUID,
505+
TOptixCommandBrowseContentReader(AOptixPacket).PageNumber,
506+
TOptixCommandBrowseContentReader(AOptixPacket).PageSize
507+
)
508+
// Simple Commands -----------------------------------------------------------------------------------------------
509+
else if AOptixPacket is TOptixSimpleCommand then begin
454510
AHandleMemory := False;
455511
///
456512

0 commit comments

Comments
 (0)