8
Classes, SysUtils, FileUtil, LResources, HTTPDefs, websession, fpHTTP, fpWeb;
14
TFPWebModule1 = class(TFPWebModule)
15
procedure DataModuleAfterResponse(Sender: TObject; AResponse: TResponse);
16
procedure DataModuleCreate(Sender: TObject);
17
procedure loginRequest(Sender: TObject; ARequest: TRequest;
18
AResponse: TResponse; var Handled: Boolean);
19
procedure logoutRequest(Sender: TObject; ARequest: TRequest;
20
AResponse: TResponse; var Handled: Boolean);
21
procedure someactionRequest(Sender: TObject; ARequest: TRequest;
22
AResponse: TResponse; var Handled: Boolean);
24
{ private declarations }
25
LoggedInLoginName : String;
27
SessionDBFile : String;
29
SessionVariable: String;
30
TimeoutMinutes: Integer;
31
function RemoveExpiredSessions(SL:TStringList; const SIDToDelete:String):Boolean;
32
function NotLoggedIn:Boolean;
33
function CommonTemplateTagReplaces(const TagString:String;
34
TagParams: TStringList; Out ReplaceText: String):Boolean;
36
procedure loginReplaceTag(Sender: TObject; const TagString:String;
37
TagParams: TStringList; Out ReplaceText: String);
38
procedure logoutReplaceTag(Sender: TObject; const TagString:String;
39
TagParams: TStringList; Out ReplaceText: String);
40
procedure welcomeReplaceTag(Sender: TObject; const TagString:String;
41
TagParams: TStringList; Out ReplaceText: String);
42
procedure someactionReplaceTag(Sender: TObject; const TagString:String;
43
TagParams: TStringList; Out ReplaceText: String);
45
{ public declarations }
49
FPWebModule1: TFPWebModule1;
55
procedure TFPWebModule1.DataModuleAfterResponse(Sender: TObject;
56
AResponse: TResponse);
58
sessiondatabase:TStringList;
59
SIDLastRefresh:String;
61
//update the session DB for the current session
62
if (SessionID <> '')and(LoggedinLoginName <> '') then
63
begin//for many concurrent request websites this part needs to be modified to have some kind of locking while writing into the file/relational database
65
sessiondatabase := TStringList.Create;
66
if FileExists(sessiondbfile) then
67
sessiondatabase.LoadFromFile(sessiondbfile);
68
SIDLastRefresh := sessiondatabase.Values[SessionID];
69
if SIDLastRefresh <> '' then
71
sessiondatabase.Values[SessionID] := DateTimeToStr(Now) + LoggedinLoginName;//update the Last refresh time
72
sessiondatabase.SaveToFile(sessiondbfile);
77
//reset global variables for apache modules for the next incoming request
78
LoggedInLoginName := '';
83
procedure TFPWebModule1.DataModuleCreate(Sender: TObject);
85
Template.AllowTagParams := true;
86
Template.StartDelimiter := '{+'; //The default is { and } which is usually not good if we use Javascript in our templates
87
Template.EndDelimiter := '+}';
88
sessiondbfile := 'session-db.txt';//This will contain the sessionID=expiration pairs
89
userdbfile := 'userdb.txt'; //This simulates a user database with passwords
90
TimeOutMinutes := 2; //With a session timeout of 2 minutes
91
SessionVariable := 'sid'; //Query parameter name for the session ID, for all links in the templates
92
LongTimeFormat := 'hh:mm:ss'; //to save on date time conversion code
93
ShortDateFormat := 'YYYY/MM/DD'; //to save on date time conversion code
96
function FindNameInList(const SL:TStrings; const N:String):String;
101
for i := 0 to SL.Count - 1 do
102
if SL.Names[i] = N then
104
Result := SL.Values[SL.Names[i]];
109
function TFPWebModule1.RemoveExpiredSessions(SL:TStringList; const SIDToDelete:String):Boolean;
113
s, SIDLastRefresh: String;
117
if SL.Count <= 0 then Exit;
124
if copy(s, 1, j - 1) = SIDToDelete then
129
SIDLastRefresh := copy(s, j + 1, 19);{YYYY/MM/DD hh:mm:ss}
130
DT := StrToDateTime(SIDLastRefresh);
131
if ((Now - DT) > (TimeOutMinutes/1440)) then
143
function TFPWebModule1.NotLoggedIn:Boolean;
145
sessiondatabase:TStringlist;
146
SIDLastRefresh:String;
150
//check if the current sessionID is valid
151
SessionID := UpperCase(Request.QueryFields.Values[SessionVariable]);
152
if SessionID <> '' then
154
sessiondatabase := TStringList.Create;
155
if FileExists(sessiondbfile) then
156
sessiondatabase.LoadFromFile(sessiondbfile);
157
// if RemoveExpiredSessions(sessiondatabase, '') then //Remove all expired sessions
158
// sessiondatabase.SaveToFile(sessiondbfile); {enough to purge only at logout events}
159
RemoveExpiredSessions(sessiondatabase, ''); { }
160
SIDLastRefresh := sessiondatabase.Values[SessionID];
161
sessiondatabase.Free;
163
if SIDLastRefresh <> '' then
165
LoggedinLoginName := copy(SIDLastRefresh, 20, 1024);
170
//show the login screen again with the expired session message
171
Template.FileName := 'testurllogin.html';
172
Template.OnReplaceTag := @loginReplaceTag;
173
Request.QueryFields.Add('MSG=SESSIONEXPIRED');
174
Response.Content := Template.GetContent;
178
procedure TFPWebModule1.loginRequest(Sender: TObject; ARequest: TRequest;
179
AResponse: TResponse; var Handled: Boolean);
181
loginname, pwd, pwd1 : String;
182
userdatabase, sessiondatabase : TStringlist;
186
Template.FileName := 'testurllogin.html';
187
Template.OnReplaceTag := @loginReplaceTag;
188
AResponse.CustomHeaders.Add('Pragma=no-cache');//do not cache the response in the web browser
190
if FindNameInList(ARequest.ContentFields, 'LoginName') = '' then
191
begin//called the login action without parameters -> display the login page
192
ARequest.QueryFields.Add('MSG=NORMAL');
193
AResponse.Content := Template.GetContent;
197
loginname := Trim(ARequest.ContentFields.Values['LoginName']);
198
pwd := Trim(ARequest.ContentFields.Values['Password']);
199
if (pwd = '') or (loginname = '') then
200
begin//empty login name or password -> return to the login screen
201
ARequest.QueryFields.Add('MSG=MISSING');
202
AResponse.Content := Template.GetContent;
206
//simulate a user database loaded into a stringlist
207
userdatabase := TStringlist.Create;
208
userdatabase.LoadFromFile(userdbfile);
211
if userdatabase.Count <= 0 then
212
begin//cannot find user DB or it is empty
213
ARequest.QueryFields.Add('MSG=NODB');
214
AResponse.Content := Template.GetContent;
217
pwd1 := userdatabase.values[LoginName];
221
begin//either the password or the login name was invalid
222
ARequest.QueryFields.Add('MSG=INVLOGIN');
223
AResponse.Content := Template.GetContent;
228
LoggedInLoginName := loginname;
230
//session starting, need to store it somewhere next to the name of the logged in person
231
sessiondatabase := TStringList.Create;
232
if FileExists(sessiondbfile) then
233
sessiondatabase.LoadFromFile(sessiondbfile);
235
SessionID:=UpperCase(GuiDToString(G));
236
sessiondatabase.Add(SessionID + '=' + DateTimeToStr(Now) + LoggedinLoginName);//create a new entry for this session
237
sessiondatabase.SaveToFile(sessiondbfile);//for many concurrent request websites this part needs to be modified to have some kind of locking while writing into the file/relational database
238
sessiondatabase.Free;
240
//generate the Welcome page content
241
Template.FileName := 'testurlwelcome.html';
242
Template.OnReplaceTag := @welcomeReplaceTag;
243
AResponse.Content := Template.GetContent;
246
procedure TFPWebModule1.loginReplaceTag(Sender: TObject; const TagString:
247
String; TagParams: TStringList; Out ReplaceText: String);
249
{Handle tags used in multiple templates}
250
if CommonTemplateTagReplaces(TagString, TagParams, ReplaceText) then
253
{Handle tags specific to this template if there are any}
254
if AnsiCompareText(TagString, 'MESSAGE') = 0 then
256
ReplaceText := TagParams.Values[Request.QueryFields.Values['MSG']];
259
{Message for tags not handled}
261
ReplaceText := '[Template tag {+' + TagString + '+} is not implemented yet.]';
265
procedure TFPWebModule1.welcomeReplaceTag(Sender: TObject; const TagString:String;
266
TagParams: TStringList; Out ReplaceText: String);
268
{Handle tags used in multiple templates}
269
if CommonTemplateTagReplaces(TagString, TagParams, ReplaceText) then
272
{Handle tags specific to this template if there are any}
275
{Message for tags not handled}
277
ReplaceText := '[Template tag {+' + TagString + '+} is not implemented yet.]';
281
procedure TFPWebModule1.logoutRequest(Sender: TObject; ARequest: TRequest;
282
AResponse: TResponse; var Handled: Boolean);
284
sessiondatabase : TStringList;
288
if NotLoggedIn then Exit;
290
//delete the sessionID from the sessiondb with all expired sessions
291
sessiondatabase := TStringList.Create;
292
if FileExists(sessiondbfile) then
293
sessiondatabase.LoadFromFile(sessiondbfile);
294
RemoveExpiredSessions(sessiondatabase, SessionID);
295
sessiondatabase.SaveToFile(sessiondbfile);//for many concurrent request websites this part needs to be modified to have some kind of locking while writing into the file/relational database
296
sessiondatabase.Free;
299
Template.FileName := 'testurllogout.html';
300
Template.OnReplaceTag := @logoutReplaceTag;
301
AResponse.Content := Template.GetContent;//generate the Logout page content.
304
procedure TFPWebModule1.logoutReplaceTag(Sender: TObject; const TagString:String;
305
TagParams: TStringList; Out ReplaceText: String);
307
{Handle tags used in multiple templates}
308
if CommonTemplateTagReplaces(TagString, TagParams, ReplaceText) then
311
{Handle tags specific to this template if there are any}
314
{Message for tags not handled}
316
ReplaceText := '[Template tag {+' + TagString + '+} is not implemented yet.]';
320
procedure TFPWebModule1.someactionRequest(Sender: TObject; ARequest: TRequest;
321
AResponse: TResponse; var Handled: Boolean);
325
if NotLoggedIn then Exit;
327
Template.FileName := 'testurlsomepage.html';
328
Template.OnReplaceTag := @someactionReplaceTag;
329
AResponse.Content := Template.GetContent;
332
procedure TFPWebModule1.someactionReplaceTag(Sender: TObject; const TagString:
333
String; TagParams: TStringList; Out ReplaceText: String);
335
{Handle tags used in multiple templates}
336
if CommonTemplateTagReplaces(TagString, TagParams, ReplaceText) then
339
{Handle tags specific to this template if there are any}
342
{Message for tags not handled}
344
ReplaceText := '[Template tag {+' + TagString + '+} is not implemented yet.]';
348
function TFPWebModule1.CommonTemplateTagReplaces(const TagString:String;
349
TagParams: TStringList; out ReplaceText: String):Boolean;
353
if AnsiCompareText(TagString, 'SESSION-VARIABLE') = 0 then
355
ReplaceText := SessionVariable + '=' + SessionID;
358
if AnsiCompareText(TagString, 'DATETIME') = 0 then
360
ReplaceText := FormatDateTime(TagParams.Values['FORMAT'], Now);
363
if AnsiCompareText(TagString, 'SESSIONID') = 0 then
365
ReplaceText := SessionID;
368
if AnsiCompareText(TagString, 'MINUTESLEFT') = 0 then
370
ReplaceText := IntToStr(TimeOutMinutes);
373
if AnsiCompareText(TagString, 'LOGINNAME') = 0 then
375
ReplaceText := LoggedInLoginName;
384
RegisterHTTPModule('TFPWebModule1', TFPWebModule1);