03-13-2024, 10:21 AM
When deploy intraweb application using wwwroot and templates, 2 extra folders wwwroot and templates shall deploy to same folder stored the application executable file.
Windows or Delphi application support resources stored in .EXE or .DLL / .BPL, it would be nice if IntraWeb can support loading those files from application resource to avoid deploy extra files at runtime.
I submitted a patch to support loading the templates from TResourceStream for your reference:
Windows or Delphi application support resources stored in .EXE or .DLL / .BPL, it would be nice if IntraWeb can support loading those files from application resource to avoid deploy extra files at runtime.
I submitted a patch to support loading the templates from TResourceStream for your reference:
Code:
unit IWTemplateProcessorHTML.ResourcePatch;
interface
uses
System.Classes, System.SysUtils;
var LoadTemplateEx: TFunc<string, TStream>;
implementation
uses
System.Types,
DDetours, IW.Common.StrLists, IW.Common.Stream, IW.Common.Strings,
IW.Common.Threads, IWFilePath, IWGlobal, IWTemplateProcessorHTML;
type
TIWTemplateCacheAccess = class
private
mFiles: TIWStringList;
mLock: TIWSlimReaderWriter;
end;
TIWTemplateCacheHelper = class helper for TIWTemplateCache
class function FindItem_Address: Pointer;
class function Load_Address: Pointer;
function Load_Patch(const aFileName: string; aRefreshFromFile: Boolean): TStream;
end;
TIWTemplateProcessorHTMLHelper = class helper for TIWTemplateProcessorHTML
function Able_Patch: Boolean;
function TemplatePathname_Patch: string;
end;
var TIWTemplateProcessorHTML_Able: function(Self: TIWTemplateProcessorHTML): Boolean;
var TIWTemplateProcessorHTML_TemplatePathname: function(Self: TIWTemplateProcessorHTML): string;
var TIWTemplateCache_FindItem: function(Self: TIWTemplateCache;
const aFileName: string): TIWTemplateCacheItem = nil;
var TIWTemplateCache_Load: function(Self: TIWTemplateCache;
const aFileName: string; aRefreshFromFile: Boolean): TStream;
class function TIWTemplateCacheHelper.FindItem_Address: Pointer;
begin
Result := @TIWTemplateCache.FindItem;
end;
class function TIWTemplateCacheHelper.Load_Address: Pointer;
begin
Result := @TIWTemplateCache.Load;
end;
function TIWTemplateCacheHelper.Load_Patch(const aFileName: string;
aRefreshFromFile: Boolean): TStream;
var
LStream: TIWMemoryStream;
Item: TIWTemplateCacheItem;
begin
Result := nil;
(* patched: if FileExists(aFilename) then*) begin
(* patched: LStream := TIWMemoryStream.Create;
try
TIWMemoryStream(LStream).LoadFromFile(aFileName);
except
FreeAndNil(LStream);
raise;
end;*)
var sFileName := ExtractFileName(aFileName);
var o := LoadTemplateEx(sFileName);
try
LStream := TIWMemoryStream.CreateCopy(o, 0);
finally
o.Free;
end;
if aRefreshFromFile or not Able then Exit(LStream);
Item := TIWTemplateCacheItem.Create(LStream);
try
// we are going to return a copy of the stream
Result := LStream.Clone;
// the original LStream is going to be stored in our cache
TIWTemplateCacheAccess(Self).mLock.BeginWrite;
try
TIWTemplateCacheAccess(Self).mFiles.AddObject(aFileName, Item); // add the stream to the cache
finally
TIWTemplateCacheAccess(Self).mLock.EndWrite;
end;
except
FreeAndNil(Item);
raise;
end;
end;
end;
function TIWTemplateProcessorHTMLHelper.Able_Patch: Boolean;
begin
(* patched
Result := False;
if Enabled then begin
Result := Assigned(FOnBeforeProcess) or FileExists(TemplatePathname);
end;
*)
Result := True;
end;
function TIWTemplateProcessorHTMLHelper.TemplatePathname_Patch: string;
var
S: string;
begin
if Templates.Default = '' then begin
// This is for subtemplates of regions. Right now containername returns:
// formName.regionName. We rename it to formNameRegionName and that way
// if no name is specified for the templates for regions, it uses this as
// the default one
if Assigned(Container) then begin
// Remove the T from subclass name (AFTER the .)
if (s <> '') and (Pos('.T', UpperCase(s)) > 0) then begin
s := IWStringReplace(UpperCase(Container.ContainerClassName), '.T', '', []);
end;
s := IWStringReplace(Container.ContainerClassName, '.', '', []);
// Remove T from it
if IWStartsText('T', s) then begin
Delete(s, 1, 1);
end;
s := s + '.html';
end else begin
s := '';
end;
(* patched if Assigned(gSC) and FileExists(gSC.TemplateDir + s) then *)begin
FTemplates.Default := s;
end;
end;
if Templates.Default <> '' then begin
Result := Templates.Default;
end;
Result := TFilePath.Concat(gSC.TemplateDir, Result);
end;
initialization
TIWTemplateProcessorHTML_Able := InterceptCreate(@TIWTemplateProcessorHTML.Able, @TIWTemplateProcessorHTML.Able_Patch);
TIWTemplateProcessorHTML_TemplatePathname := InterceptCreate(@TIWTemplateProcessorHTML.TemplatePathname, @TIWTemplateProcessorHTML.TemplatePathname_Patch);
TIWTemplateCache_Load := InterceptCreate(TIWTemplateCache.Load_Address, @TIWTemplateCache.Load_Patch);
finalization
InterceptRemove(@TIWTemplateProcessorHTML_Able);
InterceptRemove(@TIWTemplateProcessorHTML_TemplatePathname);
InterceptRemove(@TIWTemplateCache_Load);
end.