{****************************************************************** JEDI-VCL Demo Copyright (C) 2002 Project JEDI Original author: Contributor(s): You may retrieve the latest version of this file at the JEDI-JVCL home page, located at http://jvcl.sourceforge.net The contents of this file are used with permission, subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/MPL-1_1Final.html Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. ******************************************************************} unit ClassScript; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ClassUtils, ClassQueryDisplay, ClassUrlParser, jpeg, ExtCtrls; type TScriptHandler = class private FResult: TStream; FScript: TStream; FCurrentPath: string; FParams: TUrlParser; FHeaders: TStringList; FCurrentUser: Integer; protected procedure AnalyseScript(var AScript: string); procedure ReadData; procedure ReadScript; procedure DoResizeImage(AParams: string); function GetPath(ACurrentPath, ANewPath: string): string; public procedure Request(AFileName, AParams: string; AResult: TStream; AHeaders: TStringList); function GetParam(const AName: string): string; property CurrentUser: Integer read FCurrentUser write FCurrentUser; end; implementation uses ClassHospital, JvXmlDatabase; { TScriptHandler } {**********************************************************************} procedure TScriptHandler.AnalyseScript(var AScript: string); var lToken, st: string; lQuery: TJvXmlQuery; i: Integer; lStream: TFileStream; function ReadParam: string; begin result := ''; if (i} lToken := ''; i := 1; lQuery := nil; FParams.AddVariable('curuser', IntToStr(CurrentUser)); while i <= Length(AScript) do begin case AScript[i] of 'a'..'z', 'A'..'Z': lToken := lToken + AScript[i]; '(': begin lToken := LowerCase(lToken); if lToken = 'request' then begin st := ReadParam; st := ParseParams(st); if lQuery<>nil then lQuery.Free; lQuery := GHospital.Database.Query(st); FParams.AddVariable('lastid', IntToStr(lQuery.LastId)); end else if lToken = 'display' then begin st := GetPath(FCurrentPath, ReadParam); with TQueryDisplayer.Create(self) do try Generate(lQuery, st, FResult); finally Free; end; end else if lToken = 'echo' then begin st := ReadParam; st := ParseParams(st); FResult.Write(st[1], Length(st)); end else if lToken = 'displayempty' then begin if lQuery.Results.Items.Count = 0 then begin st := GetPath(FCurrentPath, ReadParam); with TStringList.Create do try LoadFromFile(st); st := ParseParams(Text); FResult.Write(st[1], Length(st)); finally Free; end; end; end else if lToken = 'displaynonempty' then begin if lQuery.Results.Items.Count > 0 then begin st := GetPath(FCurrentPath, ReadParam); with TStringList.Create do try LoadFromFile(st); st := ParseParams(Text); FResult.Write(st[1], Length(st)); finally Free; end; end; end else if lToken = 'include' then begin st := ReadParam; st := GetPath(FCurrentPath, st); if FileExists(st) then begin lStream := TFileStream.Create(st, fmOpenRead); try FResult.CopyFrom(lStream, 0); finally lStream.Free; end; end; end else if lToken = 'resizeimage' then begin st := ReadParam; DoResizeImage(st); end else if lToken = 'redirect' then begin st := ReadParam; FHeaders.Add('Location: ' + ParseParams(st)); end else raise Exception.Create('Unknown token '+lToken); lToken := ''; end; ' ',#9,#10,#13,')',';': begin //Just ignore them for the lightness of the parser end; end; inc(i); end; if lQuery<>nil then lQuery.Free; end; {**********************************************************************} procedure TScriptHandler.DoResizeImage(AParams: string); var lFile: string; lWidth, lHeight, i: integer; lJpeg: TJPEGImage; lBmp: TBitmap; begin //Limited to jpeg/bmp images try i := pos(',', AParams); lWidth := -1; lHeight := -1; if i<>0 then begin lFile := Copy(AParams, 1, i-1); AParams := Copy(AParams, i+1, MAXINT); for i:=0 to FParams.Count-1 do if FParams.Variable[i].Name = lFile then begin lFile := FParams.Variable[i].Value; Break; end; lFile := GetPath(FCurrentPath, lFile); i := pos(',', AParams); if i<>0 then begin lWidth := StrToIntDef(Copy(AParams, 1, i-1), -1); lHeight := StrToIntDef(Copy(AParams, i+1, MAXINT), -1); end else lWidth := StrToIntDef(AParams, -1); end else lFile := AParams; lJpeg := TJPEGImage.Create; lBmp := TBitmap.Create; with TImage.Create(nil) do try Picture.LoadFromFile(lFile); Proportional := true; Width := lWidth; Height := lHeight; lBmp.Width := lWidth; lBmp.Height := lHeight; lBmp.Canvas.StretchDraw(Rect(0,0,lWidth,lHeight),Picture.Graphic); lJpeg.Assign(lBmp); lJpeg.SaveToStream(FResult); finally lJpeg.Free; lBmp.Free; Free; end; except end; end; {**********************************************************************} function TScriptHandler.GetParam(const AName: string): string; var i: Integer; begin result := ''; for i:=0 to FParams.Count-1 do if FParams.Variable[i].Name = AName then begin result := FParams.Variable[i].Value; Exit; end; end; {**********************************************************************} function TScriptHandler.GetPath(ACurrentPath, ANewPath: string): string; var st: string; begin {$IFDEF MSWINDOWS} ACurrentPath := StringReplace(ACurrentPath,'/','\',[rfReplaceAll]); ANewPath := StringReplace(ANewPath,'/','\',[rfReplaceAll]); {$ENDIF} if FileExists(ANewPath) then result := ANewPath else begin st := GetCurrentDir; SetCurrentDir(ExtractFilePath(ACurrentPath)); result := ExpandFileName(ANewPath); SetCurrentDir(st); end; end; {**********************************************************************} procedure TScriptHandler.ReadData; var lBuffer: array[0..1024] of char; lCount, i, lPos: Integer; begin lPos := 0; while FScript.Position < FScript.Size do begin lCount := FScript.Read(lBuffer, SizeOf(lBuffer)); for i:=0 to lCount-1 do case lBuffer[i] of '<': lPos := 1; '%': if lPos = 1 then begin FResult.Write(lBuffer, i - 1); FScript.Seek(-(lCount - (i + 1)),soFromCurrent); Exit; end; else lPos := 0; end; FResult.Write(lBuffer, lCount); end; end; {**********************************************************************} procedure TScriptHandler.ReadScript; var lBuffer: array[0..1024] of char; lCount, i, lPos: Integer; lScript: string; begin lPos := 0; lScript := ''; while FScript.Position < FScript.Size do begin lCount := FScript.Read(lBuffer, SizeOf(lBuffer)); for i:=0 to lCount-1 do case lBuffer[i] of '%': lPos := 1; '>': if lPos = 1 then begin FScript.Seek(-(lCount - (i + 1)),soFromCurrent); AnalyseScript(lScript); Exit; end else lScript := lScript + lBuffer[i]; else begin if lPos = 1 then lScript := lScript + '%'; lScript := lScript + lBuffer[i]; lPos := 0; end; end; end; end; {**********************************************************************} procedure TScriptHandler.Request(AFileName, AParams: string; AResult: TStream; AHeaders: TStringList); begin FScript := TFileStream.Create(AFileName, fmOpenRead and fmShareDenyWrite); FParams := TUrlParser.Create('?' + AParams); FCurrentPath := ExtractFilePath(AFileName); FResult := AResult; FHeaders := AHeaders; try while FScript.Position < FScript.Size do begin ReadData; ReadScript; end; finally FScript.Free; FParams.Free; end; end; {**********************************************************************} end.