Support wwwroot and templates files from application resources

<< Click to Display Table of Contents >>

Navigation:  Forum >

Support wwwroot and templates files from application resources

Forum link

 

 

 


 

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:

 

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.

 

 

 

 

 


 

04-05-2024, 07:00 PM:

 

If you need the templates to be somehow safer and not be touched by end users, yes, that's a good solution