mirror of
https://github.com/danieleteti/delphimvcframework.git
synced 2024-11-15 15:55:54 +01:00
Automated support to avoid "mid-air collisions". New methods SetETag
and CheckIfMatch
allows a better security without adding complexity to the controller code - check avoid_mid_air_collisions_sample.dproj
sample and see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag#avoiding_mid-air_collisions for more info about mid-air collisions.
This commit is contained in:
parent
3998c1288b
commit
0f3bae84b9
@ -683,6 +683,11 @@ The current beta release is named 3.2.2-nitrogen. If you want to stay on the-edg
|
|||||||
end;
|
end;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- ✅ Improved! While not strictly required nor defined, DMVCFramework supports sending body data for all HTTP VERBS - see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET
|
||||||
|
|
||||||
|
- ⚡ New! Automated support to avoid "mid-air collisions". New methods `SetETag` and `CheckIfMatch` allows a better security without adding complexity to the controller code - check `avoid_mid_air_collisions_sample.dproj` sample and see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag#avoiding_mid-air_collisions for more info about mid-air collisions.
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes in 3.2.2-nitrogen
|
### Bug Fixes in 3.2.2-nitrogen
|
||||||
|
|
||||||
- Fix https://github.com/danieleteti/delphimvcframework/issues/484 (thanks to [João Antônio Duarte](https://github.com/joaoduarte19))
|
- Fix https://github.com/danieleteti/delphimvcframework/issues/484 (thanks to [João Antônio Duarte](https://github.com/joaoduarte19))
|
||||||
|
@ -89,7 +89,7 @@ resourcestring
|
|||||||
// ' WriteLn(''Write "quit" or "exit" to shutdown the server'');' + sLineBreak +
|
// ' WriteLn(''Write "quit" or "exit" to shutdown the server'');' + sLineBreak +
|
||||||
' LServer.Active := True;' + sLineBreak +
|
' LServer.Active := True;' + sLineBreak +
|
||||||
' WriteLn(''Listening on port '', APort);' + sLineBreak +
|
' WriteLn(''Listening on port '', APort);' + sLineBreak +
|
||||||
' WriteLn(''CTRL+C to shutdown the server'');' + sLineBreak +
|
' Write(''CTRL+C to shutdown the server'');' + sLineBreak +
|
||||||
' WaitForTerminationSignal; ' + sLineBreak +
|
' WaitForTerminationSignal; ' + sLineBreak +
|
||||||
' EnterInShutdownState; ' + sLineBreak +
|
' EnterInShutdownState; ' + sLineBreak +
|
||||||
' LServer.Active := False; ' + sLineBreak +
|
' LServer.Active := False; ' + sLineBreak +
|
||||||
@ -126,7 +126,6 @@ resourcestring
|
|||||||
' MVCFramework, MVCFramework.Commons, MVCFramework.Serializer.Commons;' + sLineBreak +
|
' MVCFramework, MVCFramework.Commons, MVCFramework.Serializer.Commons;' + sLineBreak +
|
||||||
sLineBreak +
|
sLineBreak +
|
||||||
'type' + sLineBreak +
|
'type' + sLineBreak +
|
||||||
sLineBreak +
|
|
||||||
' [MVCPath(''/api'')]' + sLineBreak +
|
' [MVCPath(''/api'')]' + sLineBreak +
|
||||||
' %1:s = class(TMVCController) ' + sLineBreak +
|
' %1:s = class(TMVCController) ' + sLineBreak +
|
||||||
' public' + sLineBreak +
|
' public' + sLineBreak +
|
||||||
@ -195,7 +194,7 @@ resourcestring
|
|||||||
'begin' + sLineBreak +
|
'begin' + sLineBreak +
|
||||||
' //todo: render the customer by id' + sLineBreak +
|
' //todo: render the customer by id' + sLineBreak +
|
||||||
'end;' + sLineBreak + sLineBreak +
|
'end;' + sLineBreak + sLineBreak +
|
||||||
'procedure %0:s.CreateCustomer;' + sLineBreak + sLineBreak +
|
'procedure %0:s.CreateCustomer;' + sLineBreak +
|
||||||
'begin' + sLineBreak +
|
'begin' + sLineBreak +
|
||||||
' //todo: create a new customer' + sLineBreak +
|
' //todo: create a new customer' + sLineBreak +
|
||||||
'end;' + sLineBreak + sLineBreak +
|
'end;' + sLineBreak + sLineBreak +
|
||||||
|
@ -4,7 +4,7 @@ object frmDMVCNewProject: TfrmDMVCNewProject
|
|||||||
BorderStyle = bsDialog
|
BorderStyle = bsDialog
|
||||||
Caption = 'DelphiMVCFramework :: New Project Wizard'
|
Caption = 'DelphiMVCFramework :: New Project Wizard'
|
||||||
ClientHeight = 518
|
ClientHeight = 518
|
||||||
ClientWidth = 676
|
ClientWidth = 700
|
||||||
Color = clBtnFace
|
Color = clBtnFace
|
||||||
Constraints.MinHeight = 145
|
Constraints.MinHeight = 145
|
||||||
Constraints.MinWidth = 250
|
Constraints.MinWidth = 250
|
||||||
@ -16,13 +16,13 @@ object frmDMVCNewProject: TfrmDMVCNewProject
|
|||||||
Position = poMainFormCenter
|
Position = poMainFormCenter
|
||||||
OnCreate = FormCreate
|
OnCreate = FormCreate
|
||||||
DesignSize = (
|
DesignSize = (
|
||||||
676
|
700
|
||||||
518)
|
518)
|
||||||
TextHeight = 13
|
TextHeight = 13
|
||||||
object Shape1: TShape
|
object Shape1: TShape
|
||||||
Left = 0
|
Left = 0
|
||||||
Top = 0
|
Top = 0
|
||||||
Width = 676
|
Width = 700
|
||||||
Height = 121
|
Height = 121
|
||||||
Align = alTop
|
Align = alTop
|
||||||
Pen.Color = clWhite
|
Pen.Color = clWhite
|
||||||
@ -398,7 +398,7 @@ object frmDMVCNewProject: TfrmDMVCNewProject
|
|||||||
end
|
end
|
||||||
object lblBook: TLabel
|
object lblBook: TLabel
|
||||||
AlignWithMargins = True
|
AlignWithMargins = True
|
||||||
Left = 8
|
Left = 13
|
||||||
Top = 487
|
Top = 487
|
||||||
Width = 259
|
Width = 259
|
||||||
Height = 16
|
Height = 16
|
||||||
@ -418,9 +418,10 @@ object frmDMVCNewProject: TfrmDMVCNewProject
|
|||||||
OnClick = lblBookClick
|
OnClick = lblBookClick
|
||||||
OnMouseEnter = lblBookMouseEnter
|
OnMouseEnter = lblBookMouseEnter
|
||||||
OnMouseLeave = lblBookMouseLeave
|
OnMouseLeave = lblBookMouseLeave
|
||||||
|
ExplicitLeft = 8
|
||||||
end
|
end
|
||||||
object btnOK: TButton
|
object btnOK: TButton
|
||||||
Left = 508
|
Left = 532
|
||||||
Top = 483
|
Top = 483
|
||||||
Width = 77
|
Width = 77
|
||||||
Height = 27
|
Height = 27
|
||||||
@ -430,9 +431,10 @@ object frmDMVCNewProject: TfrmDMVCNewProject
|
|||||||
ModalResult = 1
|
ModalResult = 1
|
||||||
TabOrder = 3
|
TabOrder = 3
|
||||||
OnClick = btnOKClick
|
OnClick = btnOKClick
|
||||||
|
ExplicitLeft = 508
|
||||||
end
|
end
|
||||||
object btnCancel: TButton
|
object btnCancel: TButton
|
||||||
Left = 591
|
Left = 615
|
||||||
Top = 483
|
Top = 483
|
||||||
Width = 77
|
Width = 77
|
||||||
Height = 27
|
Height = 27
|
||||||
@ -441,6 +443,7 @@ object frmDMVCNewProject: TfrmDMVCNewProject
|
|||||||
Caption = 'Cancel'
|
Caption = 'Cancel'
|
||||||
ModalResult = 2
|
ModalResult = 2
|
||||||
TabOrder = 4
|
TabOrder = 4
|
||||||
|
ExplicitLeft = 591
|
||||||
end
|
end
|
||||||
object chkAddToProjectGroup: TCheckBox
|
object chkAddToProjectGroup: TCheckBox
|
||||||
Left = 24
|
Left = 24
|
||||||
@ -565,12 +568,12 @@ object frmDMVCNewProject: TfrmDMVCNewProject
|
|||||||
object GroupBox1: TGroupBox
|
object GroupBox1: TGroupBox
|
||||||
Left = 287
|
Left = 287
|
||||||
Top = 135
|
Top = 135
|
||||||
Width = 381
|
Width = 405
|
||||||
Height = 214
|
Height = 214
|
||||||
Caption = 'Middlewares'
|
Caption = 'Middlewares'
|
||||||
TabOrder = 6
|
TabOrder = 6
|
||||||
DesignSize = (
|
DesignSize = (
|
||||||
381
|
405
|
||||||
214)
|
214)
|
||||||
object Label4: TLabel
|
object Label4: TLabel
|
||||||
Left = 161
|
Left = 161
|
||||||
@ -582,7 +585,7 @@ object frmDMVCNewProject: TfrmDMVCNewProject
|
|||||||
object Bevel1: TBevel
|
object Bevel1: TBevel
|
||||||
Left = 11
|
Left = 11
|
||||||
Top = 102
|
Top = 102
|
||||||
Width = 358
|
Width = 383
|
||||||
Height = 3
|
Height = 3
|
||||||
Shape = bsTopLine
|
Shape = bsTopLine
|
||||||
end
|
end
|
||||||
@ -594,43 +597,47 @@ object frmDMVCNewProject: TfrmDMVCNewProject
|
|||||||
Caption = 'ConnectionDef Name'
|
Caption = 'ConnectionDef Name'
|
||||||
end
|
end
|
||||||
object chkAnalyticsMiddleware: TCheckBox
|
object chkAnalyticsMiddleware: TCheckBox
|
||||||
Left = 21
|
Left = 27
|
||||||
Top = 50
|
Top = 50
|
||||||
Width = 135
|
Width = 135
|
||||||
Height = 17
|
Height = 17
|
||||||
Anchors = [akTop]
|
Anchors = [akTop]
|
||||||
Caption = 'Analytics'
|
Caption = 'Analytics'
|
||||||
TabOrder = 0
|
TabOrder = 0
|
||||||
|
ExplicitLeft = 21
|
||||||
end
|
end
|
||||||
object chkCompression: TCheckBox
|
object chkCompression: TCheckBox
|
||||||
Left = 21
|
Left = 27
|
||||||
Top = 24
|
Top = 24
|
||||||
Width = 153
|
Width = 153
|
||||||
Height = 17
|
Height = 17
|
||||||
Anchors = [akTop]
|
Anchors = [akTop]
|
||||||
Caption = 'Compression'
|
Caption = 'Compression'
|
||||||
TabOrder = 1
|
TabOrder = 1
|
||||||
|
ExplicitLeft = 21
|
||||||
end
|
end
|
||||||
object chkStaticFiles: TCheckBox
|
object chkStaticFiles: TCheckBox
|
||||||
Left = 21
|
Left = 27
|
||||||
Top = 76
|
Top = 76
|
||||||
Width = 135
|
Width = 135
|
||||||
Height = 17
|
Height = 17
|
||||||
Anchors = [akTop]
|
Anchors = [akTop]
|
||||||
Caption = 'Static Files'
|
Caption = 'Static Files'
|
||||||
TabOrder = 2
|
TabOrder = 2
|
||||||
|
ExplicitLeft = 21
|
||||||
end
|
end
|
||||||
object chkTrace: TCheckBox
|
object chkTrace: TCheckBox
|
||||||
Left = 215
|
Left = 192
|
||||||
Top = 50
|
Top = 50
|
||||||
Width = 135
|
Width = 150
|
||||||
Height = 17
|
Height = 17
|
||||||
|
Hint = 'Debug purposes'
|
||||||
Anchors = [akTop]
|
Anchors = [akTop]
|
||||||
Caption = 'Tracing'
|
Caption = 'Tracing (debug purposes)'
|
||||||
TabOrder = 3
|
TabOrder = 3
|
||||||
end
|
end
|
||||||
object chkCORS: TCheckBox
|
object chkCORS: TCheckBox
|
||||||
Left = 215
|
Left = 192
|
||||||
Top = 24
|
Top = 24
|
||||||
Width = 135
|
Width = 135
|
||||||
Height = 17
|
Height = 17
|
||||||
@ -639,27 +646,29 @@ object frmDMVCNewProject: TfrmDMVCNewProject
|
|||||||
TabOrder = 4
|
TabOrder = 4
|
||||||
end
|
end
|
||||||
object chkETAG: TCheckBox
|
object chkETAG: TCheckBox
|
||||||
Left = 215
|
Left = 192
|
||||||
Top = 76
|
Top = 76
|
||||||
Width = 135
|
Width = 202
|
||||||
Height = 17
|
Height = 17
|
||||||
Anchors = [akTop]
|
Anchors = [akTop]
|
||||||
Caption = 'ETag'
|
Caption = 'ETag (Cache of unchanged resources)'
|
||||||
TabOrder = 5
|
TabOrder = 5
|
||||||
|
ExplicitLeft = 175
|
||||||
end
|
end
|
||||||
object chkActiveRecord: TCheckBox
|
object chkActiveRecord: TCheckBox
|
||||||
Left = 21
|
Left = 27
|
||||||
Top = 111
|
Top = 111
|
||||||
Width = 135
|
Width = 135
|
||||||
Height = 17
|
Height = 17
|
||||||
Anchors = [akTop]
|
Anchors = [akTop]
|
||||||
Caption = 'ActiveRecord'
|
Caption = 'ActiveRecord'
|
||||||
TabOrder = 6
|
TabOrder = 6
|
||||||
|
ExplicitLeft = 21
|
||||||
end
|
end
|
||||||
object EdtFDConnDefFileName: TEdit
|
object EdtFDConnDefFileName: TEdit
|
||||||
Left = 161
|
Left = 161
|
||||||
Top = 129
|
Top = 129
|
||||||
Width = 204
|
Width = 228
|
||||||
Height = 21
|
Height = 21
|
||||||
Anchors = [akLeft, akTop, akRight]
|
Anchors = [akLeft, akTop, akRight]
|
||||||
TabOrder = 7
|
TabOrder = 7
|
||||||
@ -668,23 +677,25 @@ object frmDMVCNewProject: TfrmDMVCNewProject
|
|||||||
object EdtConnDefName: TEdit
|
object EdtConnDefName: TEdit
|
||||||
Left = 161
|
Left = 161
|
||||||
Top = 175
|
Top = 175
|
||||||
Width = 204
|
Width = 228
|
||||||
Height = 21
|
Height = 21
|
||||||
Anchors = [akLeft, akTop, akRight]
|
Anchors = [akLeft, akTop, akRight]
|
||||||
TabOrder = 8
|
TabOrder = 8
|
||||||
TextHint = 'MyConnDef'
|
TextHint = 'MyConnDef'
|
||||||
|
ExplicitWidth = 204
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
object GroupBoxJSONRPC: TGroupBox
|
object GroupBoxJSONRPC: TGroupBox
|
||||||
Left = 287
|
Left = 287
|
||||||
Top = 360
|
Top = 360
|
||||||
Width = 381
|
Width = 405
|
||||||
Height = 105
|
Height = 105
|
||||||
Anchors = [akLeft, akTop, akRight]
|
Anchors = [akLeft, akTop, akRight]
|
||||||
Caption = 'JSON-RPC 2.0'
|
Caption = 'JSON-RPC 2.0'
|
||||||
TabOrder = 7
|
TabOrder = 7
|
||||||
|
ExplicitWidth = 381
|
||||||
DesignSize = (
|
DesignSize = (
|
||||||
381
|
405
|
||||||
105)
|
105)
|
||||||
object Label3: TLabel
|
object Label3: TLabel
|
||||||
Left = 16
|
Left = 16
|
||||||
@ -696,22 +707,24 @@ object frmDMVCNewProject: TfrmDMVCNewProject
|
|||||||
object EdtJSONRPCClassName: TEdit
|
object EdtJSONRPCClassName: TEdit
|
||||||
Left = 16
|
Left = 16
|
||||||
Top = 72
|
Top = 72
|
||||||
Width = 350
|
Width = 374
|
||||||
Height = 21
|
Height = 21
|
||||||
Anchors = [akLeft, akTop, akRight]
|
Anchors = [akLeft, akTop, akRight]
|
||||||
TabOrder = 0
|
TabOrder = 0
|
||||||
TextHint = 'TMyJSONRPCObject'
|
TextHint = 'TMyJSONRPCObject'
|
||||||
|
ExplicitWidth = 350
|
||||||
end
|
end
|
||||||
object chkJSONRPC: TCheckBox
|
object chkJSONRPC: TCheckBox
|
||||||
Left = 16
|
Left = 16
|
||||||
Top = 22
|
Top = 22
|
||||||
Width = 343
|
Width = 367
|
||||||
Height = 17
|
Height = 17
|
||||||
Anchors = [akLeft, akTop, akRight]
|
Anchors = [akLeft, akTop, akRight]
|
||||||
Caption = 'Create JSONRPC 2.0 end-point'
|
Caption = 'Create JSONRPC 2.0 end-point'
|
||||||
Checked = True
|
Checked = True
|
||||||
State = cbChecked
|
State = cbChecked
|
||||||
TabOrder = 1
|
TabOrder = 1
|
||||||
|
ExplicitWidth = 343
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
object ApplicationEvents: TApplicationEvents
|
object ApplicationEvents: TApplicationEvents
|
||||||
|
167
samples/avoid_mid_air_collisions_sample/MainControllerU.pas
Normal file
167
samples/avoid_mid_air_collisions_sample/MainControllerU.pas
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
unit MainControllerU;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
MVCFramework, MVCFramework.Commons, MVCFramework.Serializer.Commons;
|
||||||
|
|
||||||
|
type
|
||||||
|
[MVCNameCase(ncCamelCase)]
|
||||||
|
TPerson = class
|
||||||
|
private
|
||||||
|
fName: String;
|
||||||
|
fSurname: String;
|
||||||
|
fID: Integer;
|
||||||
|
public
|
||||||
|
function GetHash: String;
|
||||||
|
class function GetNew(const id: Integer; const Name, Surname: String): TPerson;
|
||||||
|
property ID: Integer read fID write fID;
|
||||||
|
property Name: String read fName write fName;
|
||||||
|
property Surname: String read fSurname write fSurname;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
[MVCPath('/api/people')]
|
||||||
|
TMyController = class(TMVCController)
|
||||||
|
private
|
||||||
|
function GetPersonByID(const ID: Integer): TPerson;
|
||||||
|
procedure UpdatePersonByID(const ID: Integer; const Person: TPerson);
|
||||||
|
public
|
||||||
|
[MVCPath]
|
||||||
|
[MVCHTTPMethod([httpGET])]
|
||||||
|
procedure Index;
|
||||||
|
public
|
||||||
|
// Sample CRUD Actions for a "person" entity
|
||||||
|
[MVCPath('/($id)')]
|
||||||
|
[MVCHTTPMethod([httpGET])]
|
||||||
|
procedure Getperson(id: Integer);
|
||||||
|
|
||||||
|
[MVCPath]
|
||||||
|
[MVCHTTPMethod([httpPOST])]
|
||||||
|
procedure Createperson([MVCFromBody] const Person: TPerson);
|
||||||
|
|
||||||
|
[MVCPath('/($id)')]
|
||||||
|
[MVCHTTPMethod([httpPUT])]
|
||||||
|
procedure UpdatePerson(id: Integer; [MVCFromBody] const Person: TPerson);
|
||||||
|
|
||||||
|
[MVCPath('/($id)')]
|
||||||
|
[MVCHTTPMethod([httpDELETE])]
|
||||||
|
procedure DeletePerson(id: Integer);
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
uses
|
||||||
|
System.SysUtils, MVCFramework.Logger, System.StrUtils, MVCFramework.Cache,
|
||||||
|
System.Rtti, MVCFramework.Rtti.Utils;
|
||||||
|
|
||||||
|
procedure TMyController.Index;
|
||||||
|
begin
|
||||||
|
// use Context property to access to the HTTP request and response
|
||||||
|
Render('Hello DelphiMVCFramework World');
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TMyController.GetPersonByID(const ID: Integer): TPerson;
|
||||||
|
var
|
||||||
|
lPerson: TPerson;
|
||||||
|
begin
|
||||||
|
lPerson := nil;
|
||||||
|
if not TMVCCacheSingleton.Instance.ExecOnItemWithWriteLock(id.ToString,
|
||||||
|
procedure(Value: TValue)
|
||||||
|
begin
|
||||||
|
lPerson := TRttiUtils.Clone(Value.AsObject) as TPerson;
|
||||||
|
end) then
|
||||||
|
begin
|
||||||
|
raise EMVCException.Create(HTTP_STATUS.NotFound, 'Person not found');
|
||||||
|
end;
|
||||||
|
Result := lPerson;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMyController.Getperson(id: Integer);
|
||||||
|
var
|
||||||
|
lItem: TMVCCacheItem;
|
||||||
|
lPerson: TPerson;
|
||||||
|
begin
|
||||||
|
lPerson := GetPersonByID(id);
|
||||||
|
SetETag(lPerson.GetHash);
|
||||||
|
Render(lPerson, True);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMyController.Createperson([MVCFromBody] const Person: TPerson);
|
||||||
|
var
|
||||||
|
lValue: TValue;
|
||||||
|
begin
|
||||||
|
TMVCCacheSingleton.Instance.BeginWrite;
|
||||||
|
try
|
||||||
|
if not TMVCCacheSingleton.Instance.Contains(Person.ID.ToString, lValue) then
|
||||||
|
begin
|
||||||
|
TMVCCacheSingleton.Instance.SetValue(Person.ID.ToString, TRttiUtils.Clone(Person));
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
raise EMVCException.Create(HTTP_STATUS.NotAcceptable, 'Duplicate ID for person');
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
TMVCCacheSingleton.Instance.EndWrite;
|
||||||
|
end;
|
||||||
|
Render201Created();
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMyController.UpdatePerson(id: Integer; [MVCFromBody] const Person: TPerson);
|
||||||
|
var
|
||||||
|
lItem: TMVCCacheItem;
|
||||||
|
lPerson: TPerson;
|
||||||
|
begin
|
||||||
|
// retrieve data from storage
|
||||||
|
lPerson := GetPersonByID(id);
|
||||||
|
|
||||||
|
//check if the client modified the current version (a.k.a. mid-air collisions)
|
||||||
|
//raises an exception if client send a wrong If-Match header value
|
||||||
|
CheckIfMatch(lPerson.GetHash);
|
||||||
|
|
||||||
|
//perform the actual update and save to the storage
|
||||||
|
lPerson.Name := Person.Name;
|
||||||
|
lPerson.Surname := Person.Surname;
|
||||||
|
UpdatePersonByID(lPerson.ID, lPerson);
|
||||||
|
|
||||||
|
//set the new ETag value base on the data status
|
||||||
|
SetETag(lPerson.GetHash);
|
||||||
|
|
||||||
|
//reply with a 200 OK
|
||||||
|
Render(HTTP_STATUS.OK);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMyController.UpdatePersonByID(const ID: Integer;
|
||||||
|
const Person: TPerson);
|
||||||
|
begin
|
||||||
|
TMVCCacheSingleton.Instance.SetValue(ID.ToString, Person);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMyController.DeletePerson(id: Integer);
|
||||||
|
var
|
||||||
|
lPerson: TPerson;
|
||||||
|
begin
|
||||||
|
lPerson := GetPersonByID(ID);
|
||||||
|
CheckIfMatch(lPerson.GetHash);
|
||||||
|
TMVCCacheSingleton.Instance.RemoveItem(ID.ToString);
|
||||||
|
Render204NoContent();
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TPerson }
|
||||||
|
|
||||||
|
function TPerson.GetHash: String;
|
||||||
|
begin
|
||||||
|
Result := Format('%d|%s|%s', [fID, fName, fSurname]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function TPerson.GetNew(const id: Integer; const Name, Surname: String): TPerson;
|
||||||
|
begin
|
||||||
|
Result := TPerson.Create;
|
||||||
|
Result.fID := id;
|
||||||
|
Result.fName := Name;
|
||||||
|
Result.fSurname := Surname;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
7
samples/avoid_mid_air_collisions_sample/WebModuleU.dfm
Normal file
7
samples/avoid_mid_air_collisions_sample/WebModuleU.dfm
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
object MyWebModule: TMyWebModule
|
||||||
|
OnCreate = WebModuleCreate
|
||||||
|
OnDestroy = WebModuleDestroy
|
||||||
|
Actions = <>
|
||||||
|
Height = 230
|
||||||
|
Width = 415
|
||||||
|
end
|
102
samples/avoid_mid_air_collisions_sample/WebModuleU.pas
Normal file
102
samples/avoid_mid_air_collisions_sample/WebModuleU.pas
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
unit WebModuleU;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
System.SysUtils,
|
||||||
|
System.Classes,
|
||||||
|
Web.HTTPApp,
|
||||||
|
MVCFramework;
|
||||||
|
|
||||||
|
type
|
||||||
|
TMyWebModule = class(TWebModule)
|
||||||
|
procedure WebModuleCreate(Sender: TObject);
|
||||||
|
procedure WebModuleDestroy(Sender: TObject);
|
||||||
|
private
|
||||||
|
FMVC: TMVCEngine;
|
||||||
|
public
|
||||||
|
{ Public declarations }
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
WebModuleClass: TComponentClass = TMyWebModule;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
{$R *.dfm}
|
||||||
|
|
||||||
|
uses
|
||||||
|
MainControllerU,
|
||||||
|
|
||||||
|
System.IOUtils,
|
||||||
|
MVCFramework.Commons,
|
||||||
|
MVCFramework.Middleware.ActiveRecord,
|
||||||
|
MVCFramework.Middleware.StaticFiles,
|
||||||
|
MVCFramework.Middleware.Analytics,
|
||||||
|
MVCFramework.Middleware.Trace,
|
||||||
|
MVCFramework.Middleware.CORS,
|
||||||
|
MVCFramework.Middleware.ETag,
|
||||||
|
MVCFramework.Middleware.Compression;
|
||||||
|
|
||||||
|
procedure TMyWebModule.WebModuleCreate(Sender: TObject);
|
||||||
|
begin
|
||||||
|
FMVC := TMVCEngine.Create(Self,
|
||||||
|
procedure(Config: TMVCConfig)
|
||||||
|
begin
|
||||||
|
// session timeout (0 means session cookie)
|
||||||
|
Config[TMVCConfigKey.SessionTimeout] := '0';
|
||||||
|
//default content-type
|
||||||
|
Config[TMVCConfigKey.DefaultContentType] := TMVCConstants.DEFAULT_CONTENT_TYPE;
|
||||||
|
//default content charset
|
||||||
|
Config[TMVCConfigKey.DefaultContentCharset] := TMVCConstants.DEFAULT_CONTENT_CHARSET;
|
||||||
|
//unhandled actions are permitted?
|
||||||
|
Config[TMVCConfigKey.AllowUnhandledAction] := 'false';
|
||||||
|
//enables or not system controllers loading (available only from localhost requests)
|
||||||
|
Config[TMVCConfigKey.LoadSystemControllers] := 'true';
|
||||||
|
//default view file extension
|
||||||
|
Config[TMVCConfigKey.DefaultViewFileExtension] := 'html';
|
||||||
|
//view path
|
||||||
|
Config[TMVCConfigKey.ViewPath] := 'templates';
|
||||||
|
//Max Record Count for automatic Entities CRUD
|
||||||
|
Config[TMVCConfigKey.MaxEntitiesRecordCount] := '20';
|
||||||
|
//Enable Server Signature in response
|
||||||
|
Config[TMVCConfigKey.ExposeServerSignature] := 'true';
|
||||||
|
//Enable X-Powered-By Header in response
|
||||||
|
Config[TMVCConfigKey.ExposeXPoweredBy] := 'true';
|
||||||
|
// Max request size in bytes
|
||||||
|
Config[TMVCConfigKey.MaxRequestSize] := IntToStr(TMVCConstants.DEFAULT_MAX_REQUEST_SIZE);
|
||||||
|
end);
|
||||||
|
FMVC.AddController(TMyController);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Analytics middleware generates a csv log, useful to do trafic analysis
|
||||||
|
//FMVC.AddMiddleware(TMVCAnalyticsMiddleware.Create(GetAnalyticsDefaultLogger));
|
||||||
|
|
||||||
|
// The folder mapped as documentroot for TMVCStaticFilesMiddleware must exists!
|
||||||
|
//FMVC.AddMiddleware(TMVCStaticFilesMiddleware.Create('/static', TPath.Combine(ExtractFilePath(GetModuleName(HInstance)), 'www')));
|
||||||
|
|
||||||
|
// Trace middlewares produces a much detailed log for debug purposes
|
||||||
|
FMVC.AddMiddleware(TMVCTraceMiddleware.Create);
|
||||||
|
|
||||||
|
// CORS middleware handles... well, CORS
|
||||||
|
//FMVC.AddMiddleware(TMVCCORSMiddleware.Create);
|
||||||
|
|
||||||
|
// Simplifies TMVCActiveRecord connection definition
|
||||||
|
//FMVC.AddMiddleware(TMVCActiveRecordMiddleware.Create('MyConnDef','FDConnectionDefs.ini'));
|
||||||
|
|
||||||
|
// Compression middleware must be the last in the chain, just before the ETag, if present.
|
||||||
|
//FMVC.AddMiddleware(TMVCCompressionMiddleware.Create);
|
||||||
|
|
||||||
|
// ETag middleware must be the latest in the chain
|
||||||
|
//FMVC.AddMiddleware(TMVCETagMiddleware.Create);
|
||||||
|
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMyWebModule.WebModuleDestroy(Sender: TObject);
|
||||||
|
begin
|
||||||
|
FMVC.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
@ -0,0 +1,76 @@
|
|||||||
|
program avoid_mid_air_collisions_sample;
|
||||||
|
|
||||||
|
{$APPTYPE CONSOLE}
|
||||||
|
|
||||||
|
uses
|
||||||
|
System.SysUtils,
|
||||||
|
MVCFramework,
|
||||||
|
MVCFramework.Logger,
|
||||||
|
MVCFramework.Commons,
|
||||||
|
MVCFramework.Signal,
|
||||||
|
MVCFramework.Cache,
|
||||||
|
Web.ReqMulti,
|
||||||
|
Web.WebReq,
|
||||||
|
Web.WebBroker,
|
||||||
|
IdContext,
|
||||||
|
IdHTTPWebBrokerBridge,
|
||||||
|
MainControllerU in 'MainControllerU.pas',
|
||||||
|
WebModuleU in 'WebModuleU.pas' {MyWebModule: TWebModule},
|
||||||
|
MVCFramework.Utils in '..\..\sources\MVCFramework.Utils.pas';
|
||||||
|
|
||||||
|
{$R *.res}
|
||||||
|
|
||||||
|
|
||||||
|
procedure RunServer(APort: Integer);
|
||||||
|
var
|
||||||
|
LServer: TIdHTTPWebBrokerBridge;
|
||||||
|
begin
|
||||||
|
Writeln('** DMVCFramework Server ** build ' + DMVCFRAMEWORK_VERSION);
|
||||||
|
LServer := TIdHTTPWebBrokerBridge.Create(nil);
|
||||||
|
try
|
||||||
|
LServer.OnParseAuthentication := TMVCParseAuthentication.OnParseAuthentication;
|
||||||
|
LServer.DefaultPort := APort;
|
||||||
|
LServer.KeepAlive := True;
|
||||||
|
|
||||||
|
{ more info about MaxConnections
|
||||||
|
http://ww2.indyproject.org/docsite/html/frames.html?frmname=topic&frmfile=index.html }
|
||||||
|
LServer.MaxConnections := 0;
|
||||||
|
|
||||||
|
{ more info about ListenQueue
|
||||||
|
http://ww2.indyproject.org/docsite/html/frames.html?frmname=topic&frmfile=index.html }
|
||||||
|
LServer.ListenQueue := 200;
|
||||||
|
|
||||||
|
LServer.Active := True;
|
||||||
|
WriteLn('Listening on port ', APort);
|
||||||
|
WriteLn('CTRL+C to shutdown the server');
|
||||||
|
WaitForTerminationSignal;
|
||||||
|
EnterInShutdownState;
|
||||||
|
LServer.Active := False;
|
||||||
|
finally
|
||||||
|
LServer.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure LoadFakeData;
|
||||||
|
begin
|
||||||
|
TMVCCacheSingleton.Instance.SetValue('1', TPerson.GetNew(1, 'Daniele','Teti'));
|
||||||
|
TMVCCacheSingleton.Instance.SetValue('2', TPerson.GetNew(2, 'Peter','Parker'));
|
||||||
|
TMVCCacheSingleton.Instance.SetValue('3', TPerson.GetNew(3, 'Bruce','Banner'));
|
||||||
|
TMVCCacheSingleton.Instance.SetValue('4', TPerson.GetNew(4, 'Sue','Storm'));
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
ReportMemoryLeaksOnShutdown := True;
|
||||||
|
IsMultiThread := True;
|
||||||
|
try
|
||||||
|
if WebRequestHandler <> nil then
|
||||||
|
WebRequestHandler.WebModuleClass := WebModuleClass;
|
||||||
|
WebRequestHandlerProc.MaxConnections := 1024;
|
||||||
|
LoadFakeData;
|
||||||
|
RunServer(8080);
|
||||||
|
except
|
||||||
|
on E: Exception do
|
||||||
|
Writeln(E.ClassName, ': ', E.Message);
|
||||||
|
end;
|
||||||
|
end.
|
||||||
|
|
@ -0,0 +1,907 @@
|
|||||||
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ProjectGuid>{03D8066E-D767-4E59-8D05-7C3341BECDFC}</ProjectGuid>
|
||||||
|
<ProjectVersion>19.4</ProjectVersion>
|
||||||
|
<FrameworkType>None</FrameworkType>
|
||||||
|
<Base>True</Base>
|
||||||
|
<Config Condition="'$(Config)'==''">Debug</Config>
|
||||||
|
<Platform Condition="'$(Platform)'==''">Win32</Platform>
|
||||||
|
<TargetedPlatforms>1</TargetedPlatforms>
|
||||||
|
<AppType>Console</AppType>
|
||||||
|
<MainSource>avoid_mid_air_collisions_sample.dpr</MainSource>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
|
||||||
|
<Base>true</Base>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="('$(Platform)'=='Android' and '$(Base)'=='true') or '$(Base_Android)'!=''">
|
||||||
|
<Base_Android>true</Base_Android>
|
||||||
|
<CfgParent>Base</CfgParent>
|
||||||
|
<Base>true</Base>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="('$(Platform)'=='Android64' and '$(Base)'=='true') or '$(Base_Android64)'!=''">
|
||||||
|
<Base_Android64>true</Base_Android64>
|
||||||
|
<CfgParent>Base</CfgParent>
|
||||||
|
<Base>true</Base>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="('$(Platform)'=='Linux64' and '$(Base)'=='true') or '$(Base_Linux64)'!=''">
|
||||||
|
<Base_Linux64>true</Base_Linux64>
|
||||||
|
<CfgParent>Base</CfgParent>
|
||||||
|
<Base>true</Base>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
|
||||||
|
<Base_Win32>true</Base_Win32>
|
||||||
|
<CfgParent>Base</CfgParent>
|
||||||
|
<Base>true</Base>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Base)'=='true') or '$(Base_Win64)'!=''">
|
||||||
|
<Base_Win64>true</Base_Win64>
|
||||||
|
<CfgParent>Base</CfgParent>
|
||||||
|
<Base>true</Base>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
|
||||||
|
<Cfg_1>true</Cfg_1>
|
||||||
|
<CfgParent>Base</CfgParent>
|
||||||
|
<Base>true</Base>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win32)'!=''">
|
||||||
|
<Cfg_1_Win32>true</Cfg_1_Win32>
|
||||||
|
<CfgParent>Cfg_1</CfgParent>
|
||||||
|
<Cfg_1>true</Cfg_1>
|
||||||
|
<Base>true</Base>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
|
||||||
|
<Cfg_2>true</Cfg_2>
|
||||||
|
<CfgParent>Base</CfgParent>
|
||||||
|
<Base>true</Base>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Base)'!=''">
|
||||||
|
<DCC_DcuOutput>.\$(Platform)\$(Config)</DCC_DcuOutput>
|
||||||
|
<DCC_ExeOutput>.\$(Platform)\$(Config)</DCC_ExeOutput>
|
||||||
|
<DCC_E>false</DCC_E>
|
||||||
|
<DCC_N>false</DCC_N>
|
||||||
|
<DCC_S>false</DCC_S>
|
||||||
|
<DCC_F>false</DCC_F>
|
||||||
|
<DCC_K>false</DCC_K>
|
||||||
|
<DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)</DCC_Namespace>
|
||||||
|
<UsingDelphiRTL>true</UsingDelphiRTL>
|
||||||
|
<Icon_MainIcon>$(BDS)\bin\delphi_PROJECTICON.ico</Icon_MainIcon>
|
||||||
|
<Icns_MainIcns>$(BDS)\bin\delphi_PROJECTICNS.icns</Icns_MainIcns>
|
||||||
|
<DCC_UnitSearchPath>$(DMVC);$(DCC_UnitSearchPath)</DCC_UnitSearchPath>
|
||||||
|
<DCC_Framework>VCL;$(DCC_Framework)</DCC_Framework>
|
||||||
|
<SanitizedProjectName>avoid_mid_air_collisions_sample</SanitizedProjectName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Base_Android)'!=''">
|
||||||
|
<DCC_UsePackage>fmx;DbxCommonDriver;bindengine;IndyIPCommon;emsclient;FireDACCommonDriver;IndyProtocols;Skia.Package.RTL;RadiantShapesFmx_Design;IndyIPClient;dbxcds;FmxTeeUI;bindcompfmx;ibmonitor;FireDACSqliteDriver;DbxClientDriver;soapmidas;fmxFireDAC;dbexpress;Python;inet;DataSnapCommon;dbrtl;FireDACDBXDriver;Skia.Package.FMX;CustomIPTransport;DBXInterBaseDriver;IndySystem;RadiantShapesFmx;ibxbindings;bindcomp;FireDACCommon;IndyCore;RESTBackendComponents;bindcompdbx;rtl;RESTComponents;DBXSqliteDriver;IndyIPServer;dsnapxml;DataSnapClient;DataSnapProviderClient;DataSnapFireDAC;emsclientfiredac;FireDAC;FireDACDSDriver;xmlrtl;tethering;ibxpress;dsnap;CloudService;FMXTee;DataSnapNativeClient;PythonFmx;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)</DCC_UsePackage>
|
||||||
|
<EnabledSysJars>annotation-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.0.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.0.1.dex.jar;core-runtime-2.0.1.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.0.0.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.0.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.0.0.dex.jar;lifecycle-runtime-2.0.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.0.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar</EnabledSysJars>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Base_Android64)'!=''">
|
||||||
|
<DCC_UsePackage>fmx;DbxCommonDriver;bindengine;IndyIPCommon;emsclient;FireDACCommonDriver;IndyProtocols;Skia.Package.RTL;RadiantShapesFmx_Design;IndyIPClient;dbxcds;FmxTeeUI;bindcompfmx;ibmonitor;FireDACSqliteDriver;DbxClientDriver;soapmidas;fmxFireDAC;dbexpress;Python;inet;DataSnapCommon;dbrtl;FireDACDBXDriver;Skia.Package.FMX;CustomIPTransport;DBXInterBaseDriver;IndySystem;RadiantShapesFmx;ibxbindings;bindcomp;FireDACCommon;IndyCore;RESTBackendComponents;bindcompdbx;rtl;RESTComponents;DBXSqliteDriver;IndyIPServer;dsnapxml;DataSnapClient;DataSnapProviderClient;DataSnapFireDAC;emsclientfiredac;FireDAC;FireDACDSDriver;xmlrtl;tethering;ibxpress;dsnap;CloudService;FMXTee;DataSnapNativeClient;PythonFmx;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)</DCC_UsePackage>
|
||||||
|
<EnabledSysJars>annotation-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.0.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.0.1.dex.jar;core-runtime-2.0.1.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.0.0.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.0.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.0.0.dex.jar;lifecycle-runtime-2.0.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.0.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar</EnabledSysJars>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Base_Linux64)'!=''">
|
||||||
|
<DCC_UsePackage>DataSnapServer;fmx;emshosting;DbxCommonDriver;bindengine;FireDACCommonODBC;emsclient;FireDACCommonDriver;IndyProtocols;Skia.Package.RTL;dbxcds;emsedge;inetdb;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;soapmidas;dbexpress;Python;FireDACInfxDriver;inet;DataSnapCommon;dbrtl;FireDACOracleDriver;Skia.Package.FMX;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DataSnapConnectors;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;dsnapxml;DataSnapClient;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;xmlrtl;dsnap;CloudService;FireDACDb2Driver;DataSnapNativeClient;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)</DCC_UsePackage>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Base_Win32)'!=''">
|
||||||
|
<DCC_UsePackage>RaizeComponentsVcl;vclwinx;DataSnapServer;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;Skia.Package.RTL;RadiantShapesFmx_Design;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;FmxTeeUI;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;ibmonitor;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;Tee;soapmidas;vclactnband;TeeUI;fmxFireDAC;dbexpress;Python;FireDACInfxDriver;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;PythonVcl;vcltouch;fmxase;DBXOdbcDriver;dbrtl;FireDACDBXDriver;FireDACOracleDriver;Skia.Package.FMX;fmxdae;TeeDB;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;RadiantShapesFmx;FireDACTDataDriver;Skia.Package.VCL;vcldb;ibxbindings;GPNative_d11;SynEditDR;VirtualTreesR;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;SpkToolbarR;DOSCommandDR;dmvcframeworkDT;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RaizeComponentsVclDb;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;DBXSybaseASEDriver;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;dmvcframeworkRT;ibxpress;bindcompvcl;dsnap;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;vclib;fmxobj;bindcompvclsmp;FMXTee;DataSnapNativeClient;PythonFmx;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)</DCC_UsePackage>
|
||||||
|
<DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
|
||||||
|
<BT_BuildType>Debug</BT_BuildType>
|
||||||
|
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
|
||||||
|
<VerInfo_Locale>1033</VerInfo_Locale>
|
||||||
|
<DCC_ExeOutput>.\bin</DCC_ExeOutput>
|
||||||
|
<Manifest_File>(None)</Manifest_File>
|
||||||
|
<AppDPIAwarenessMode>none</AppDPIAwarenessMode>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Base_Win64)'!=''">
|
||||||
|
<DCC_UsePackage>RaizeComponentsVcl;vclwinx;DataSnapServer;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;Skia.Package.RTL;RadiantShapesFmx_Design;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;FmxTeeUI;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;ibmonitor;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;Tee;soapmidas;vclactnband;TeeUI;fmxFireDAC;dbexpress;Python;FireDACInfxDriver;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;PythonVcl;vcltouch;fmxase;DBXOdbcDriver;dbrtl;FireDACDBXDriver;FireDACOracleDriver;Skia.Package.FMX;fmxdae;TeeDB;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;RadiantShapesFmx;FireDACTDataDriver;Skia.Package.VCL;vcldb;ibxbindings;SynEditDR;VirtualTreesR;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;DOSCommandDR;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RaizeComponentsVclDb;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;DBXSybaseASEDriver;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;ibxpress;bindcompvcl;dsnap;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;vclib;fmxobj;bindcompvclsmp;FMXTee;DataSnapNativeClient;PythonFmx;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)</DCC_UsePackage>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Cfg_1)'!=''">
|
||||||
|
<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
|
||||||
|
<DCC_DebugDCUs>true</DCC_DebugDCUs>
|
||||||
|
<DCC_Optimize>false</DCC_Optimize>
|
||||||
|
<DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
|
||||||
|
<DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
|
||||||
|
<DCC_RemoteDebug>true</DCC_RemoteDebug>
|
||||||
|
<DCC_IntegerOverflowCheck>true</DCC_IntegerOverflowCheck>
|
||||||
|
<DCC_RangeChecking>true</DCC_RangeChecking>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
|
||||||
|
<DCC_RemoteDebug>false</DCC_RemoteDebug>
|
||||||
|
<VerInfo_Locale>1033</VerInfo_Locale>
|
||||||
|
<Manifest_File>(None)</Manifest_File>
|
||||||
|
<AppDPIAwarenessMode>none</AppDPIAwarenessMode>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Cfg_2)'!=''">
|
||||||
|
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
|
||||||
|
<DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
|
||||||
|
<DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
|
||||||
|
<DCC_DebugInformation>0</DCC_DebugInformation>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<DelphiCompile Include="$(MainSource)">
|
||||||
|
<MainSource>MainSource</MainSource>
|
||||||
|
</DelphiCompile>
|
||||||
|
<DCCReference Include="MainControllerU.pas"/>
|
||||||
|
<DCCReference Include="WebModuleU.pas">
|
||||||
|
<Form>MyWebModule</Form>
|
||||||
|
<DesignClass>TWebModule</DesignClass>
|
||||||
|
</DCCReference>
|
||||||
|
<DCCReference Include="..\..\sources\MVCFramework.Utils.pas"/>
|
||||||
|
<BuildConfiguration Include="Base">
|
||||||
|
<Key>Base</Key>
|
||||||
|
</BuildConfiguration>
|
||||||
|
<BuildConfiguration Include="Debug">
|
||||||
|
<Key>Cfg_1</Key>
|
||||||
|
<CfgParent>Base</CfgParent>
|
||||||
|
</BuildConfiguration>
|
||||||
|
<BuildConfiguration Include="Release">
|
||||||
|
<Key>Cfg_2</Key>
|
||||||
|
<CfgParent>Base</CfgParent>
|
||||||
|
</BuildConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<ProjectExtensions>
|
||||||
|
<Borland.Personality>Delphi.Personality.12</Borland.Personality>
|
||||||
|
<Borland.ProjectType>Console</Borland.ProjectType>
|
||||||
|
<BorlandProject>
|
||||||
|
<Delphi.Personality>
|
||||||
|
<Source>
|
||||||
|
<Source Name="MainSource">avoid_mid_air_collisions_sample.dpr</Source>
|
||||||
|
</Source>
|
||||||
|
<Excluded_Packages>
|
||||||
|
<Excluded_Packages Name="$(BDSBIN)\dcloffice2k280.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
|
||||||
|
<Excluded_Packages Name="$(BDSBIN)\dclofficexp280.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
|
||||||
|
<Excluded_Packages Name="$(BDSBIN)\bcboffice2k280.bpl">Embarcadero C++Builder Office 2000 Servers Package</Excluded_Packages>
|
||||||
|
<Excluded_Packages Name="$(BDSBIN)\bcbofficexp280.bpl">Embarcadero C++Builder Office XP Servers Package</Excluded_Packages>
|
||||||
|
</Excluded_Packages>
|
||||||
|
</Delphi.Personality>
|
||||||
|
<Deployment Version="3">
|
||||||
|
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libcgunwind.1.0.dylib" Class="DependencyModule">
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<Overwrite>true</Overwrite>
|
||||||
|
</Platform>
|
||||||
|
</DeployFile>
|
||||||
|
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libpcre.dylib" Class="DependencyModule">
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<Overwrite>true</Overwrite>
|
||||||
|
</Platform>
|
||||||
|
</DeployFile>
|
||||||
|
<DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib" Class="DependencyModule">
|
||||||
|
<Platform Name="OSX32">
|
||||||
|
<Overwrite>true</Overwrite>
|
||||||
|
</Platform>
|
||||||
|
</DeployFile>
|
||||||
|
<DeployFile LocalName="bin\avoid_mid_air_collisions_sample.exe" Configuration="Debug" Class="ProjectOutput">
|
||||||
|
<Platform Name="Win32">
|
||||||
|
<RemoteName>avoid_mid_air_collisions_sample.exe</RemoteName>
|
||||||
|
<Overwrite>true</Overwrite>
|
||||||
|
</Platform>
|
||||||
|
</DeployFile>
|
||||||
|
<DeployClass Name="AdditionalDebugSymbols">
|
||||||
|
<Platform Name="OSX32">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Win32">
|
||||||
|
<Operation>0</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="AndroidClasses">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>classes</RemoteDir>
|
||||||
|
<Operation>64</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>classes</RemoteDir>
|
||||||
|
<Operation>64</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="AndroidFileProvider">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\xml</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\xml</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="AndroidGDBServer">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="AndroidLibnativeArmeabiFile">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>library\lib\armeabi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>library\lib\armeabi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="AndroidLibnativeArmeabiv7aFile">
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="AndroidLibnativeMipsFile">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>library\lib\mips</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>library\lib\mips</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="AndroidServiceOutput">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>library\lib\arm64-v8a</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="AndroidServiceOutput_Android32">
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="AndroidSplashImageDef">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\drawable</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\drawable</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="AndroidSplashStyles">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\values</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\values</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="AndroidSplashStylesV21">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\values-v21</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\values-v21</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="Android_Colors">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\values</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\values</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="Android_DefaultAppIcon">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\drawable</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\drawable</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="Android_LauncherIcon144">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="Android_LauncherIcon192">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="Android_LauncherIcon36">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\drawable-ldpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\drawable-ldpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="Android_LauncherIcon48">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\drawable-mdpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\drawable-mdpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="Android_LauncherIcon72">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\drawable-hdpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\drawable-hdpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="Android_LauncherIcon96">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\drawable-xhdpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\drawable-xhdpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="Android_NotificationIcon24">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\drawable-mdpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\drawable-mdpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="Android_NotificationIcon36">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\drawable-hdpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\drawable-hdpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="Android_NotificationIcon48">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\drawable-xhdpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\drawable-xhdpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="Android_NotificationIcon72">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="Android_NotificationIcon96">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="Android_SplashImage426">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\drawable-small</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\drawable-small</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="Android_SplashImage470">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\drawable-normal</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\drawable-normal</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="Android_SplashImage640">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\drawable-large</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\drawable-large</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="Android_SplashImage960">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\drawable-xlarge</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\drawable-xlarge</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="Android_Strings">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\values</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>res\values</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="DebugSymbols">
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="OSX32">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Win32">
|
||||||
|
<Operation>0</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="DependencyFramework">
|
||||||
|
<Platform Name="OSX32">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
<Extensions>.framework</Extensions>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="OSX64">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
<Extensions>.framework</Extensions>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="OSXARM64">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
<Extensions>.framework</Extensions>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Win32">
|
||||||
|
<Operation>0</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="DependencyModule">
|
||||||
|
<Platform Name="OSX32">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
<Extensions>.dylib</Extensions>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="OSX64">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
<Extensions>.dylib</Extensions>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="OSXARM64">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
<Extensions>.dylib</Extensions>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Win32">
|
||||||
|
<Operation>0</Operation>
|
||||||
|
<Extensions>.dll;.bpl</Extensions>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Required="true" Name="DependencyPackage">
|
||||||
|
<Platform Name="iOSDevice32">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
<Extensions>.dylib</Extensions>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
<Extensions>.dylib</Extensions>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
<Extensions>.dylib</Extensions>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="OSX32">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
<Extensions>.dylib</Extensions>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="OSX64">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
<Extensions>.dylib</Extensions>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="OSXARM64">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
<Extensions>.dylib</Extensions>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Win32">
|
||||||
|
<Operation>0</Operation>
|
||||||
|
<Extensions>.bpl</Extensions>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="File">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<Operation>0</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<Operation>0</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSDevice32">
|
||||||
|
<Operation>0</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<Operation>0</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<Operation>0</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="OSX32">
|
||||||
|
<Operation>0</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="OSX64">
|
||||||
|
<Operation>0</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="OSXARM64">
|
||||||
|
<Operation>0</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Win32">
|
||||||
|
<Operation>0</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="iOS_AppStore1024">
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="iPad_AppIcon152">
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="iPad_AppIcon167">
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="iPad_Launch2x">
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="iPad_LaunchDark2x">
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="iPad_Notification40">
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="iPad_Setting58">
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="iPad_SpotLight80">
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="iPhone_AppIcon120">
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="iPhone_AppIcon180">
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="iPhone_Launch2x">
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="iPhone_Launch3x">
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="iPhone_LaunchDark2x">
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="iPhone_LaunchDark3x">
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="iPhone_Notification40">
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="iPhone_Notification60">
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="iPhone_Setting58">
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="iPhone_Setting87">
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="iPhone_Spotlight120">
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="iPhone_Spotlight80">
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="ProjectAndroidManifest">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="ProjectiOSDeviceDebug">
|
||||||
|
<Platform Name="iOSDevice32">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="ProjectiOSEntitlements"/>
|
||||||
|
<DeployClass Name="ProjectiOSInfoPList"/>
|
||||||
|
<DeployClass Name="ProjectiOSLaunchScreen"/>
|
||||||
|
<DeployClass Name="ProjectiOSResource">
|
||||||
|
<Platform Name="iOSDevice32">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="ProjectOSXDebug"/>
|
||||||
|
<DeployClass Name="ProjectOSXEntitlements"/>
|
||||||
|
<DeployClass Name="ProjectOSXInfoPList"/>
|
||||||
|
<DeployClass Name="ProjectOSXResource">
|
||||||
|
<Platform Name="OSX32">
|
||||||
|
<RemoteDir>Contents\Resources</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="OSX64">
|
||||||
|
<RemoteDir>Contents\Resources</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="OSXARM64">
|
||||||
|
<RemoteDir>Contents\Resources</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Required="true" Name="ProjectOutput">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>library\lib\arm64-v8a</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSDevice32">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSDevice64">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Linux64">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="OSX32">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="OSX64">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="OSXARM64">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Win32">
|
||||||
|
<Operation>0</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="ProjectOutput_Android32">
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="ProjectUWPManifest">
|
||||||
|
<Platform Name="Win32">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Win64">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="UWP_DelphiLogo150">
|
||||||
|
<Platform Name="Win32">
|
||||||
|
<RemoteDir>Assets</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Win64">
|
||||||
|
<RemoteDir>Assets</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<DeployClass Name="UWP_DelphiLogo44">
|
||||||
|
<Platform Name="Win32">
|
||||||
|
<RemoteDir>Assets</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Win64">
|
||||||
|
<RemoteDir>Assets</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
|
<ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
|
||||||
|
<ProjectRoot Platform="Android64" Name="$(PROJECTNAME)"/>
|
||||||
|
<ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
|
||||||
|
<ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>
|
||||||
|
<ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
|
||||||
|
<ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/>
|
||||||
|
<ProjectRoot Platform="OSX32" Name="$(PROJECTNAME)"/>
|
||||||
|
<ProjectRoot Platform="OSX64" Name="$(PROJECTNAME)"/>
|
||||||
|
<ProjectRoot Platform="OSXARM64" Name="$(PROJECTNAME)"/>
|
||||||
|
<ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
|
||||||
|
<ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
|
||||||
|
</Deployment>
|
||||||
|
<Platforms>
|
||||||
|
<Platform value="Android">False</Platform>
|
||||||
|
<Platform value="Android64">False</Platform>
|
||||||
|
<Platform value="Linux64">False</Platform>
|
||||||
|
<Platform value="Win32">True</Platform>
|
||||||
|
<Platform value="Win64">False</Platform>
|
||||||
|
</Platforms>
|
||||||
|
</BorlandProject>
|
||||||
|
<ProjectFileVersion>12</ProjectFileVersion>
|
||||||
|
</ProjectExtensions>
|
||||||
|
<Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
|
||||||
|
<Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj" Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/>
|
||||||
|
<Import Project="$(MSBuildProjectName).deployproj" Condition="Exists('$(MSBuildProjectName).deployproj')"/>
|
||||||
|
</Project>
|
@ -8,11 +8,13 @@ uses
|
|||||||
Web.WebReq,
|
Web.WebReq,
|
||||||
Web.WebBroker,
|
Web.WebBroker,
|
||||||
IdHTTPWebBrokerBridge,
|
IdHTTPWebBrokerBridge,
|
||||||
MVCFramework.REPLCommandsHandlerU,
|
MVCFramework,
|
||||||
|
MVCFramework.Signal,
|
||||||
MVCFramework.Logger,
|
MVCFramework.Logger,
|
||||||
WebModuleUnit1 in 'WebModuleUnit1.pas' {WebModule1: TWebModule},
|
WebModuleUnit1 in 'WebModuleUnit1.pas' {WebModule1: TWebModule},
|
||||||
App1MainControllerU in 'App1MainControllerU.pas',
|
App1MainControllerU in 'App1MainControllerU.pas',
|
||||||
MVCFramework.Middleware.ETag in '..\..\sources\MVCFramework.Middleware.ETag.pas';
|
MVCFramework.Middleware.ETag in '..\..\sources\MVCFramework.Middleware.ETag.pas',
|
||||||
|
MVCFramework.Commons;
|
||||||
|
|
||||||
{$R *.res}
|
{$R *.res}
|
||||||
|
|
||||||
@ -20,37 +22,9 @@ uses
|
|||||||
procedure RunServer(APort: Integer);
|
procedure RunServer(APort: Integer);
|
||||||
var
|
var
|
||||||
lServer: TIdHTTPWebBrokerBridge;
|
lServer: TIdHTTPWebBrokerBridge;
|
||||||
lCustomHandler: TMVCCustomREPLCommandsHandler;
|
|
||||||
lCmd, lStartupCommand: string;
|
|
||||||
begin
|
begin
|
||||||
if ParamCount >= 1 then
|
Writeln('** DMVCFramework Server ** build ' + DMVCFRAMEWORK_VERSION);
|
||||||
lStartupCommand := ParamStr(1)
|
Writeln(Format('Starting HTTP Server or port %d', [APort]));
|
||||||
else
|
|
||||||
lStartupCommand := 'start';
|
|
||||||
|
|
||||||
lCustomHandler := function(const Value: String; const Server: TIdHTTPWebBrokerBridge; out Handled: Boolean): THandleCommandResult
|
|
||||||
begin
|
|
||||||
Handled := False;
|
|
||||||
Result := THandleCommandResult.Unknown;
|
|
||||||
|
|
||||||
// Write here your custom command for the REPL using the following form...
|
|
||||||
// ***
|
|
||||||
// Handled := False;
|
|
||||||
// if (Value = 'apiversion') then
|
|
||||||
// begin
|
|
||||||
// REPLEmit('Print my API version number');
|
|
||||||
// Result := THandleCommandResult.Continue;
|
|
||||||
// Handled := True;
|
|
||||||
// end
|
|
||||||
// else if (Value = 'datetime') then
|
|
||||||
// begin
|
|
||||||
// REPLEmit(DateTimeToStr(Now));
|
|
||||||
// Result := THandleCommandResult.Continue;
|
|
||||||
// Handled := True;
|
|
||||||
// end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// Writeln(Format('Starting HTTP Server or port %d', [APort]));
|
|
||||||
LServer := TIdHTTPWebBrokerBridge.Create(nil);
|
LServer := TIdHTTPWebBrokerBridge.Create(nil);
|
||||||
try
|
try
|
||||||
LServer.DefaultPort := APort;
|
LServer.DefaultPort := APort;
|
||||||
@ -64,37 +38,11 @@ begin
|
|||||||
http://www.indyproject.org/docsite/html/frames.html?frmname=topic&frmfile=TIdCustomTCPServer_ListenQueue.html }
|
http://www.indyproject.org/docsite/html/frames.html?frmname=topic&frmfile=TIdCustomTCPServer_ListenQueue.html }
|
||||||
LServer.ListenQueue := 200;
|
LServer.ListenQueue := 200;
|
||||||
|
|
||||||
WriteLn('Write "quit" or "exit" to shutdown the server');
|
lServer.Active := True;
|
||||||
repeat
|
Write('CTRL+C to shutdown the server');
|
||||||
// TextColor(RED);
|
WaitForTerminationSignal;
|
||||||
// TextColor(LightRed);
|
EnterInShutdownState;
|
||||||
Write('-> ');
|
lServer.Active := False;
|
||||||
// TextColor(White);
|
|
||||||
if lStartupCommand.IsEmpty then
|
|
||||||
ReadLn(lCmd)
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
lCmd := lStartupCommand;
|
|
||||||
lStartupCommand := '';
|
|
||||||
WriteLn(lCmd);
|
|
||||||
end;
|
|
||||||
|
|
||||||
case HandleCommand(lCmd.ToLower, LServer, lCustomHandler) of
|
|
||||||
THandleCommandResult.Continue:
|
|
||||||
begin
|
|
||||||
Continue;
|
|
||||||
end;
|
|
||||||
THandleCommandResult.Break:
|
|
||||||
begin
|
|
||||||
Break;
|
|
||||||
end;
|
|
||||||
THandleCommandResult.Unknown:
|
|
||||||
begin
|
|
||||||
REPLEmit('Unknown command: ' + lCmd);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
until false;
|
|
||||||
|
|
||||||
finally
|
finally
|
||||||
LServer.Free;
|
LServer.Free;
|
||||||
end;
|
end;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ProjectGuid>{BCE38CEB-AE61-49C6-8C51-8D6776B45034}</ProjectGuid>
|
<ProjectGuid>{BCE38CEB-AE61-49C6-8C51-8D6776B45034}</ProjectGuid>
|
||||||
<ProjectVersion>19.2</ProjectVersion>
|
<ProjectVersion>19.4</ProjectVersion>
|
||||||
<FrameworkType>None</FrameworkType>
|
<FrameworkType>None</FrameworkType>
|
||||||
<MainSource>middleware_etag.dpr</MainSource>
|
<MainSource>middleware_etag.dpr</MainSource>
|
||||||
<Base>True</Base>
|
<Base>True</Base>
|
||||||
@ -13,6 +13,16 @@
|
|||||||
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
|
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
|
||||||
<Base>true</Base>
|
<Base>true</Base>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="('$(Platform)'=='Android' and '$(Base)'=='true') or '$(Base_Android)'!=''">
|
||||||
|
<Base_Android>true</Base_Android>
|
||||||
|
<CfgParent>Base</CfgParent>
|
||||||
|
<Base>true</Base>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="('$(Platform)'=='Android64' and '$(Base)'=='true') or '$(Base_Android64)'!=''">
|
||||||
|
<Base_Android64>true</Base_Android64>
|
||||||
|
<CfgParent>Base</CfgParent>
|
||||||
|
<Base>true</Base>
|
||||||
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
|
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
|
||||||
<Base_Win32>true</Base_Win32>
|
<Base_Win32>true</Base_Win32>
|
||||||
<CfgParent>Base</CfgParent>
|
<CfgParent>Base</CfgParent>
|
||||||
@ -67,6 +77,16 @@
|
|||||||
<DCC_F>false</DCC_F>
|
<DCC_F>false</DCC_F>
|
||||||
<DCC_K>false</DCC_K>
|
<DCC_K>false</DCC_K>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Base_Android)'!=''">
|
||||||
|
<VerInfo_Keys>package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=</VerInfo_Keys>
|
||||||
|
<BT_BuildType>Debug</BT_BuildType>
|
||||||
|
<EnabledSysJars>annotation-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.0.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.0.1.dex.jar;core-runtime-2.0.1.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.0.0.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.0.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.0.0.dex.jar;lifecycle-runtime-2.0.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.0.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar</EnabledSysJars>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Base_Android64)'!=''">
|
||||||
|
<VerInfo_Keys>package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=</VerInfo_Keys>
|
||||||
|
<BT_BuildType>Debug</BT_BuildType>
|
||||||
|
<EnabledSysJars>annotation-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.0.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.0.1.dex.jar;core-runtime-2.0.1.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.0.0.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.0.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.0.0.dex.jar;lifecycle-runtime-2.0.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.0.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar</EnabledSysJars>
|
||||||
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Base_Win32)'!=''">
|
<PropertyGroup Condition="'$(Base_Win32)'!=''">
|
||||||
<DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
|
<DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
|
||||||
<VerInfo_Locale>1033</VerInfo_Locale>
|
<VerInfo_Locale>1033</VerInfo_Locale>
|
||||||
@ -113,10 +133,6 @@
|
|||||||
</DCCReference>
|
</DCCReference>
|
||||||
<DCCReference Include="App1MainControllerU.pas"/>
|
<DCCReference Include="App1MainControllerU.pas"/>
|
||||||
<DCCReference Include="..\..\sources\MVCFramework.Middleware.ETag.pas"/>
|
<DCCReference Include="..\..\sources\MVCFramework.Middleware.ETag.pas"/>
|
||||||
<BuildConfiguration Include="Release">
|
|
||||||
<Key>Cfg_2</Key>
|
|
||||||
<CfgParent>Base</CfgParent>
|
|
||||||
</BuildConfiguration>
|
|
||||||
<BuildConfiguration Include="Base">
|
<BuildConfiguration Include="Base">
|
||||||
<Key>Base</Key>
|
<Key>Base</Key>
|
||||||
</BuildConfiguration>
|
</BuildConfiguration>
|
||||||
@ -124,6 +140,10 @@
|
|||||||
<Key>Cfg_1</Key>
|
<Key>Cfg_1</Key>
|
||||||
<CfgParent>Base</CfgParent>
|
<CfgParent>Base</CfgParent>
|
||||||
</BuildConfiguration>
|
</BuildConfiguration>
|
||||||
|
<BuildConfiguration Include="Release">
|
||||||
|
<Key>Cfg_2</Key>
|
||||||
|
<CfgParent>Base</CfgParent>
|
||||||
|
</BuildConfiguration>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ProjectExtensions>
|
<ProjectExtensions>
|
||||||
<Borland.Personality>Delphi.Personality.12</Borland.Personality>
|
<Borland.Personality>Delphi.Personality.12</Borland.Personality>
|
||||||
@ -174,22 +194,6 @@
|
|||||||
</Excluded_Packages>
|
</Excluded_Packages>
|
||||||
</Delphi.Personality>
|
</Delphi.Personality>
|
||||||
<Deployment Version="3">
|
<Deployment Version="3">
|
||||||
<DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib" Class="DependencyModule">
|
|
||||||
<Platform Name="OSX32">
|
|
||||||
<Overwrite>true</Overwrite>
|
|
||||||
</Platform>
|
|
||||||
</DeployFile>
|
|
||||||
<DeployFile LocalName="bin\middleware_etag.exe" Configuration="Debug" Class="ProjectOutput">
|
|
||||||
<Platform Name="Win32">
|
|
||||||
<RemoteName>middleware_etag.exe</RemoteName>
|
|
||||||
<Overwrite>true</Overwrite>
|
|
||||||
</Platform>
|
|
||||||
</DeployFile>
|
|
||||||
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libPCRE.dylib" Class="DependencyModule">
|
|
||||||
<Platform Name="iOSSimulator">
|
|
||||||
<Overwrite>true</Overwrite>
|
|
||||||
</Platform>
|
|
||||||
</DeployFile>
|
|
||||||
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libcgunwind.1.0.dylib" Class="DependencyModule">
|
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libcgunwind.1.0.dylib" Class="DependencyModule">
|
||||||
<Platform Name="iOSSimulator">
|
<Platform Name="iOSSimulator">
|
||||||
<Overwrite>true</Overwrite>
|
<Overwrite>true</Overwrite>
|
||||||
@ -200,11 +204,27 @@
|
|||||||
<Overwrite>true</Overwrite>
|
<Overwrite>true</Overwrite>
|
||||||
</Platform>
|
</Platform>
|
||||||
</DeployFile>
|
</DeployFile>
|
||||||
|
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libPCRE.dylib" Class="DependencyModule">
|
||||||
|
<Platform Name="iOSSimulator">
|
||||||
|
<Overwrite>true</Overwrite>
|
||||||
|
</Platform>
|
||||||
|
</DeployFile>
|
||||||
<DeployFile LocalName="$(BDS)\Redist\osx32\libcgsqlite3.dylib" Class="DependencyModule">
|
<DeployFile LocalName="$(BDS)\Redist\osx32\libcgsqlite3.dylib" Class="DependencyModule">
|
||||||
<Platform Name="OSX32">
|
<Platform Name="OSX32">
|
||||||
<Overwrite>true</Overwrite>
|
<Overwrite>true</Overwrite>
|
||||||
</Platform>
|
</Platform>
|
||||||
</DeployFile>
|
</DeployFile>
|
||||||
|
<DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib" Class="DependencyModule">
|
||||||
|
<Platform Name="OSX32">
|
||||||
|
<Overwrite>true</Overwrite>
|
||||||
|
</Platform>
|
||||||
|
</DeployFile>
|
||||||
|
<DeployFile LocalName="bin\middleware_etag.exe" Configuration="Debug" Class="ProjectOutput">
|
||||||
|
<Platform Name="Win32">
|
||||||
|
<RemoteName>middleware_etag.exe</RemoteName>
|
||||||
|
<Overwrite>true</Overwrite>
|
||||||
|
</Platform>
|
||||||
|
</DeployFile>
|
||||||
<DeployFile LocalName="Linux64\Debug\middleware_etag" Configuration="Debug" Class="ProjectOutput">
|
<DeployFile LocalName="Linux64\Debug\middleware_etag" Configuration="Debug" Class="ProjectOutput">
|
||||||
<Platform Name="Linux64">
|
<Platform Name="Linux64">
|
||||||
<RemoteName>middleware_etag</RemoteName>
|
<RemoteName>middleware_etag</RemoteName>
|
||||||
@ -219,6 +239,16 @@
|
|||||||
<Operation>0</Operation>
|
<Operation>0</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
</DeployClass>
|
</DeployClass>
|
||||||
|
<DeployClass Name="AndroidClasses">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>classes</RemoteDir>
|
||||||
|
<Operation>64</Operation>
|
||||||
|
</Platform>
|
||||||
|
<Platform Name="Android64">
|
||||||
|
<RemoteDir>classes</RemoteDir>
|
||||||
|
<Operation>64</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
<DeployClass Name="AndroidClassesDexFile">
|
<DeployClass Name="AndroidClassesDexFile">
|
||||||
<Platform Name="Android">
|
<Platform Name="Android">
|
||||||
<RemoteDir>classes</RemoteDir>
|
<RemoteDir>classes</RemoteDir>
|
||||||
@ -517,6 +547,10 @@
|
|||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
<Extensions>.framework</Extensions>
|
<Extensions>.framework</Extensions>
|
||||||
</Platform>
|
</Platform>
|
||||||
|
<Platform Name="OSXARM64">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
<Extensions>.framework</Extensions>
|
||||||
|
</Platform>
|
||||||
<Platform Name="Win32">
|
<Platform Name="Win32">
|
||||||
<Operation>0</Operation>
|
<Operation>0</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
@ -530,6 +564,10 @@
|
|||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
<Extensions>.dylib</Extensions>
|
<Extensions>.dylib</Extensions>
|
||||||
</Platform>
|
</Platform>
|
||||||
|
<Platform Name="OSXARM64">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
<Extensions>.dylib</Extensions>
|
||||||
|
</Platform>
|
||||||
<Platform Name="Win32">
|
<Platform Name="Win32">
|
||||||
<Operation>0</Operation>
|
<Operation>0</Operation>
|
||||||
<Extensions>.dll;.bpl</Extensions>
|
<Extensions>.dll;.bpl</Extensions>
|
||||||
@ -556,6 +594,10 @@
|
|||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
<Extensions>.dylib</Extensions>
|
<Extensions>.dylib</Extensions>
|
||||||
</Platform>
|
</Platform>
|
||||||
|
<Platform Name="OSXARM64">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
<Extensions>.dylib</Extensions>
|
||||||
|
</Platform>
|
||||||
<Platform Name="Win32">
|
<Platform Name="Win32">
|
||||||
<Operation>0</Operation>
|
<Operation>0</Operation>
|
||||||
<Extensions>.bpl</Extensions>
|
<Extensions>.bpl</Extensions>
|
||||||
@ -583,6 +625,9 @@
|
|||||||
<Platform Name="OSX64">
|
<Platform Name="OSX64">
|
||||||
<Operation>0</Operation>
|
<Operation>0</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
|
<Platform Name="OSXARM64">
|
||||||
|
<Operation>0</Operation>
|
||||||
|
</Platform>
|
||||||
<Platform Name="Win32">
|
<Platform Name="Win32">
|
||||||
<Operation>0</Operation>
|
<Operation>0</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
@ -1136,6 +1181,10 @@
|
|||||||
<RemoteDir>Contents\Resources</RemoteDir>
|
<RemoteDir>Contents\Resources</RemoteDir>
|
||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
|
<Platform Name="OSXARM64">
|
||||||
|
<RemoteDir>Contents\Resources</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
</DeployClass>
|
</DeployClass>
|
||||||
<DeployClass Required="true" Name="ProjectOutput">
|
<DeployClass Required="true" Name="ProjectOutput">
|
||||||
<Platform Name="Android">
|
<Platform Name="Android">
|
||||||
@ -1164,6 +1213,9 @@
|
|||||||
<Platform Name="OSX64">
|
<Platform Name="OSX64">
|
||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
|
<Platform Name="OSXARM64">
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
<Platform Name="Win32">
|
<Platform Name="Win32">
|
||||||
<Operation>0</Operation>
|
<Operation>0</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
@ -1202,18 +1254,21 @@
|
|||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
</DeployClass>
|
</DeployClass>
|
||||||
<ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>
|
<ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
|
||||||
<ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
|
<ProjectRoot Platform="Android64" Name="$(PROJECTNAME)"/>
|
||||||
<ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
|
<ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
|
||||||
<ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
|
<ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>
|
||||||
|
<ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
|
||||||
<ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/>
|
<ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/>
|
||||||
<ProjectRoot Platform="OSX32" Name="$(PROJECTNAME)"/>
|
<ProjectRoot Platform="OSX32" Name="$(PROJECTNAME)"/>
|
||||||
<ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
|
|
||||||
<ProjectRoot Platform="OSX64" Name="$(PROJECTNAME)"/>
|
<ProjectRoot Platform="OSX64" Name="$(PROJECTNAME)"/>
|
||||||
<ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
|
<ProjectRoot Platform="OSXARM64" Name="$(PROJECTNAME)"/>
|
||||||
<ProjectRoot Platform="Android64" Name="$(PROJECTNAME)"/>
|
<ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
|
||||||
|
<ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
|
||||||
</Deployment>
|
</Deployment>
|
||||||
<Platforms>
|
<Platforms>
|
||||||
|
<Platform value="Android">False</Platform>
|
||||||
|
<Platform value="Android64">False</Platform>
|
||||||
<Platform value="Linux64">True</Platform>
|
<Platform value="Linux64">True</Platform>
|
||||||
<Platform value="Win32">True</Platform>
|
<Platform value="Win32">True</Platform>
|
||||||
<Platform value="Win64">False</Platform>
|
<Platform value="Win64">False</Platform>
|
||||||
|
@ -56,10 +56,13 @@ type
|
|||||||
constructor Create;
|
constructor Create;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
function SetValue(const AName: string; const AValue: TValue): TMVCCacheItem;
|
function SetValue(const AName: string; const AValue: TValue): TMVCCacheItem;
|
||||||
|
procedure RemoveItem(const AName: string);
|
||||||
function Contains(const AName: string; out AValue: TValue): Boolean;
|
function Contains(const AName: string; out AValue: TValue): Boolean;
|
||||||
function ContainsItem(const AName: string; out AItem: TMVCCacheItem): Boolean;
|
function ContainsItem(const AName: string; out AItem: TMVCCacheItem): Boolean;
|
||||||
function GetValue(const AName: string): TValue;
|
function GetValue(const AName: string): TValue;
|
||||||
function ExecOnItemWithWriteLock(const AName: string; const AAction: TProc<TValue>): Boolean;
|
function ExecOnItemWithWriteLock(const AName: string; const AAction: TProc<TValue>): Boolean;
|
||||||
|
procedure BeginWrite;
|
||||||
|
procedure EndWrite;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TMVCCacheSingleton = class
|
TMVCCacheSingleton = class
|
||||||
@ -123,6 +126,11 @@ begin
|
|||||||
Result := lCacheItem;
|
Result := lCacheItem;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TMVCCache.EndWrite;
|
||||||
|
begin
|
||||||
|
FMREW.EndWrite;
|
||||||
|
end;
|
||||||
|
|
||||||
function TMVCCache.ExecOnItemWithWriteLock(const AName: string; const AAction: TProc<TValue>): Boolean;
|
function TMVCCache.ExecOnItemWithWriteLock(const AName: string; const AAction: TProc<TValue>): Boolean;
|
||||||
var
|
var
|
||||||
lItem: TMVCCacheItem;
|
lItem: TMVCCacheItem;
|
||||||
@ -140,6 +148,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TMVCCache.BeginWrite;
|
||||||
|
begin
|
||||||
|
FMREW.BeginWrite;
|
||||||
|
end;
|
||||||
|
|
||||||
function TMVCCache.Contains(const AName: string; out AValue: TValue): Boolean;
|
function TMVCCache.Contains(const AName: string; out AValue: TValue): Boolean;
|
||||||
var
|
var
|
||||||
lItem: TMVCCacheItem;
|
lItem: TMVCCacheItem;
|
||||||
@ -149,8 +162,7 @@ begin
|
|||||||
AValue := lItem.Value;
|
AValue := lItem.Value;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TMVCCache.ContainsItem(const AName: string;
|
function TMVCCache.ContainsItem(const AName: string; out AItem: TMVCCacheItem): Boolean;
|
||||||
out AItem: TMVCCacheItem): Boolean;
|
|
||||||
var
|
var
|
||||||
lItem: TMVCCacheItem;
|
lItem: TMVCCacheItem;
|
||||||
lRes: Boolean;
|
lRes: Boolean;
|
||||||
@ -196,6 +208,26 @@ begin
|
|||||||
Result := lResult;
|
Result := lResult;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TMVCCache.RemoveItem(const AName: string);
|
||||||
|
var
|
||||||
|
lCacheItem: TMVCCacheItem;
|
||||||
|
begin
|
||||||
|
FMREW.DoWithWriteLock(
|
||||||
|
procedure
|
||||||
|
var
|
||||||
|
lItem: TMVCCacheItem;
|
||||||
|
begin
|
||||||
|
if FStorage.TryGetValue(AName, lItem) then
|
||||||
|
begin
|
||||||
|
if lItem.Value.IsObjectInstance then
|
||||||
|
begin
|
||||||
|
lItem.Value.AsObject.Free;
|
||||||
|
end;
|
||||||
|
FStorage.Remove(AName);
|
||||||
|
end
|
||||||
|
end);
|
||||||
|
end;
|
||||||
|
|
||||||
{ TMVCFrameworkCacheItem }
|
{ TMVCFrameworkCacheItem }
|
||||||
|
|
||||||
constructor TMVCCacheItem.Create;
|
constructor TMVCCacheItem.Create;
|
||||||
@ -280,8 +312,7 @@ begin
|
|||||||
inherited;
|
inherited;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TMVCThreadedObjectCache<T>.TryGetValue(const Key: String;
|
function TMVCThreadedObjectCache<T>.TryGetValue(const Key: String; out Value: T): Boolean;
|
||||||
out Value: T): Boolean;
|
|
||||||
begin
|
begin
|
||||||
fCS.Enter;
|
fCS.Enter;
|
||||||
try
|
try
|
||||||
@ -291,6 +322,4 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
@ -43,8 +43,6 @@ type
|
|||||||
/// 7232</see>
|
/// 7232</see>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
TMVCETagMiddleware = class(TInterfacedObject, IMVCMiddleware)
|
TMVCETagMiddleware = class(TInterfacedObject, IMVCMiddleware)
|
||||||
private
|
|
||||||
function GetHashMD5FromStream(AStream: TStream): string;
|
|
||||||
public
|
public
|
||||||
procedure OnBeforeRouting(AContext: TWebContext; var AHandled: Boolean);
|
procedure OnBeforeRouting(AContext: TWebContext; var AHandled: Boolean);
|
||||||
procedure OnBeforeControllerAction(AContext: TWebContext; const AControllerQualifiedClassName: string;
|
procedure OnBeforeControllerAction(AContext: TWebContext; const AControllerQualifiedClassName: string;
|
||||||
@ -57,33 +55,11 @@ type
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
{$IF defined(TOKYOORBETTER)}
|
|
||||||
System.Hash,
|
|
||||||
{$ELSE}
|
|
||||||
IdHashMessageDigest,
|
|
||||||
{$ENDIF}
|
|
||||||
System.SysUtils,
|
System.SysUtils,
|
||||||
MVCFramework.Commons;
|
MVCFramework.Commons, MVCFramework.Utils;
|
||||||
|
|
||||||
{ TMVCETagMiddleware }
|
{ TMVCETagMiddleware }
|
||||||
|
|
||||||
function TMVCETagMiddleware.GetHashMD5FromStream(AStream: TStream): string;
|
|
||||||
{$IF not defined(TOKYOORBETTER)}
|
|
||||||
var
|
|
||||||
lMD5Hash: TIdHashMessageDigest5;
|
|
||||||
{$ENDIF}
|
|
||||||
begin
|
|
||||||
{$IF defined(TOKYOORBETTER)}
|
|
||||||
Result := THashMD5.GetHashString(AStream);
|
|
||||||
{$ELSE}
|
|
||||||
lMD5Hash := TIdHashMessageDigest5.Create;
|
|
||||||
try
|
|
||||||
Result := lMD5Hash.HashStreamAsHex(AStream);
|
|
||||||
finally
|
|
||||||
lMD5Hash.Free;
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TMVCETagMiddleware.OnAfterControllerAction(AContext: TWebContext;
|
procedure TMVCETagMiddleware.OnAfterControllerAction(AContext: TWebContext;
|
||||||
const AControllerQualifiedClassName: string;
|
const AControllerQualifiedClassName: string;
|
||||||
@ -101,10 +77,18 @@ var
|
|||||||
begin
|
begin
|
||||||
lContentStream := AContext.Response.RawWebResponse.ContentStream;
|
lContentStream := AContext.Response.RawWebResponse.ContentStream;
|
||||||
if not Assigned(lContentStream) then
|
if not Assigned(lContentStream) then
|
||||||
|
begin
|
||||||
Exit;
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not AContext.Response.RawWebResponse.GetCustomHeader('ETag').IsEmpty then
|
||||||
|
begin
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag#caching_of_unchanged_resources
|
||||||
lRequestETag := AContext.Request.Headers['If-None-Match'];
|
lRequestETag := AContext.Request.Headers['If-None-Match'];
|
||||||
lETag := GetHashMD5FromStream(lContentStream);
|
lETag := GetMD5HashFromStream(lContentStream);
|
||||||
lContentStream.Position := 0;
|
lContentStream.Position := 0;
|
||||||
|
|
||||||
AContext.Response.SetCustomHeader('ETag', lETag);
|
AContext.Response.SetCustomHeader('ETag', lETag);
|
||||||
|
@ -27,24 +27,67 @@ unit MVCFramework.Utils;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
MVCFramework.Serializer.Commons, JsonDataObjects, MVCFramework.DuckTyping;
|
MVCFramework.Serializer.Commons, JsonDataObjects, MVCFramework.DuckTyping,
|
||||||
|
System.Classes;
|
||||||
|
|
||||||
|
|
||||||
function NewJSONSerializer: IMVCJSONSerializer;
|
function NewJSONSerializer: IMVCJSONSerializer;
|
||||||
function StrToJSONObject(const aString: String; ARaiseExceptionOnError: Boolean = False): TJsonObject;
|
function StrToJSONObject(const aString: String; ARaiseExceptionOnError: Boolean = False): TJsonObject;
|
||||||
function StrToJSONArray(const aString: String; ARaiseExceptionOnError: Boolean = False): TJsonArray;
|
function StrToJSONArray(const aString: String; ARaiseExceptionOnError: Boolean = False): TJsonArray;
|
||||||
function WrapAsList(const AObject: TObject; AOwnsObject: Boolean = False): IMVCList;
|
function WrapAsList(const AObject: TObject; AOwnsObject: Boolean = False): IMVCList;
|
||||||
|
function GetMD5HashFromStream(AStream: TStream): string;
|
||||||
|
function GetMD5HashFromString(const AString: String): string;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
|
{$IF defined(TOKYOORBETTER)}
|
||||||
|
System.Hash,
|
||||||
|
{$ELSE}
|
||||||
|
IdHashMessageDigest,
|
||||||
|
{$ENDIF}
|
||||||
MVCFramework.Serializer.JsonDataObjects,
|
MVCFramework.Serializer.JsonDataObjects,
|
||||||
MVCFramework.Commons,
|
MVCFramework.Commons,
|
||||||
System.SysUtils,
|
System.SysUtils,
|
||||||
System.TypInfo;
|
System.TypInfo;
|
||||||
|
|
||||||
|
function GetMD5HashFromStream(AStream: TStream): string;
|
||||||
|
{$IF not defined(TOKYOORBETTER)}
|
||||||
|
var
|
||||||
|
lMD5Hash: TIdHashMessageDigest5;
|
||||||
|
{$ENDIF}
|
||||||
|
begin
|
||||||
|
{$IF defined(TOKYOORBETTER)}
|
||||||
|
Result := THashMD5.GetHashString(AStream);
|
||||||
|
{$ELSE}
|
||||||
|
lMD5Hash := TIdHashMessageDigest5.Create;
|
||||||
|
try
|
||||||
|
Result := lMD5Hash.HashStreamAsHex(AStream);
|
||||||
|
finally
|
||||||
|
lMD5Hash.Free;
|
||||||
|
end;
|
||||||
|
{$ENDIF}
|
||||||
|
end;
|
||||||
|
|
||||||
|
function GetMD5HashFromString(const AString: String): string;
|
||||||
|
{$IF not defined(TOKYOORBETTER)}
|
||||||
|
var
|
||||||
|
lMD5Hash: TIdHashMessageDigest5;
|
||||||
|
{$ENDIF}
|
||||||
|
begin
|
||||||
|
{$IF defined(TOKYOORBETTER)}
|
||||||
|
Result := THashMD5.GetHashString(AStream);
|
||||||
|
{$ELSE}
|
||||||
|
lMD5Hash := TIdHashMessageDigest5.Create;
|
||||||
|
try
|
||||||
|
Result := lMD5Hash.HashStringAsHex(AString);
|
||||||
|
finally
|
||||||
|
lMD5Hash.Free;
|
||||||
|
end;
|
||||||
|
{$ENDIF}
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
function NewJSONSerializer: IMVCJSONSerializer;
|
function NewJSONSerializer: IMVCJSONSerializer;
|
||||||
begin
|
begin
|
||||||
Result := TMVCJsonDataObjectsSerializer.Create;
|
Result := TMVCJsonDataObjectsSerializer.Create;
|
||||||
|
@ -380,7 +380,6 @@ type
|
|||||||
constructor Create(const AWebRequest: TWebRequest;
|
constructor Create(const AWebRequest: TWebRequest;
|
||||||
const ASerializers: TDictionary<string, IMVCSerializer>);
|
const ASerializers: TDictionary<string, IMVCSerializer>);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
|
||||||
function ClientIp: string;
|
function ClientIp: string;
|
||||||
function ClientPrefer(const AMediaType: string): Boolean;
|
function ClientPrefer(const AMediaType: string): Boolean;
|
||||||
function ClientPreferHTML: Boolean;
|
function ClientPreferHTML: Boolean;
|
||||||
@ -806,6 +805,11 @@ type
|
|||||||
function SessionAs<T: TWebSession>: T;
|
function SessionAs<T: TWebSession>: T;
|
||||||
procedure RaiseSessionExpired; virtual;
|
procedure RaiseSessionExpired; virtual;
|
||||||
|
|
||||||
|
// Avoiding mid-air collisions - support
|
||||||
|
procedure SetETag(const Data: String);
|
||||||
|
procedure CheckIfMatch(const Data: String);
|
||||||
|
// END - Avoiding mid-air collisions - support
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
property Context: TWebContext read GetContext write FContext;
|
property Context: TWebContext read GetContext write FContext;
|
||||||
property Session: TWebSession read GetSession;
|
property Session: TWebSession read GetSession;
|
||||||
@ -1108,13 +1112,15 @@ uses
|
|||||||
MVCFramework.JSONRPC,
|
MVCFramework.JSONRPC,
|
||||||
MVCFramework.Router,
|
MVCFramework.Router,
|
||||||
MVCFramework.Rtti.Utils,
|
MVCFramework.Rtti.Utils,
|
||||||
MVCFramework.Serializer.HTML, MVCFramework.Serializer.Abstract;
|
MVCFramework.Serializer.HTML, MVCFramework.Serializer.Abstract,
|
||||||
|
MVCFramework.Utils;
|
||||||
|
|
||||||
var
|
var
|
||||||
gIsShuttingDown: Int64 = 0;
|
gIsShuttingDown: Int64 = 0;
|
||||||
gMVCGlobalActionParamsCache: TMVCStringObjectDictionary<TMVCActionParamCacheItem> = nil;
|
gMVCGlobalActionParamsCache: TMVCStringObjectDictionary<TMVCActionParamCacheItem> = nil;
|
||||||
gHostingFramework: TMVCHostingFrameworkType = hftUnknown;
|
gHostingFramework: TMVCHostingFrameworkType = hftUnknown;
|
||||||
|
|
||||||
|
|
||||||
function IsShuttingDown: Boolean;
|
function IsShuttingDown: Boolean;
|
||||||
begin
|
begin
|
||||||
Result := TInterlocked.Read(gIsShuttingDown) = 1
|
Result := TInterlocked.Read(gIsShuttingDown) = 1
|
||||||
@ -3366,6 +3372,28 @@ end;
|
|||||||
|
|
||||||
{ TMVCController }
|
{ TMVCController }
|
||||||
|
|
||||||
|
procedure TMVCController.CheckIfMatch(const Data: String);
|
||||||
|
var
|
||||||
|
lReqETag: String;
|
||||||
|
begin
|
||||||
|
if Data.IsEmpty then
|
||||||
|
begin
|
||||||
|
raise EMVCException.Create(HTTP_STATUS.InternalServerError, 'Cannot calculate ETag using empty value');
|
||||||
|
end;
|
||||||
|
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag#avoiding_mid-air_collisions
|
||||||
|
lReqETag := Context.Request.GetHeader('If-Match');
|
||||||
|
if lReqETag.IsEmpty then
|
||||||
|
begin
|
||||||
|
raise EMVCException.Create(HTTP_STATUS.PreconditionFailed, 'If-Match header is empty');
|
||||||
|
end;
|
||||||
|
|
||||||
|
if lReqETag <> GetMD5HashFromString(Data) then
|
||||||
|
begin
|
||||||
|
raise EMVCException.Create(HTTP_STATUS.PreconditionFailed, 'mid-air collisions detected, cannot update or delete resource.');
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
constructor TMVCController.Create;
|
constructor TMVCController.Create;
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
@ -3693,6 +3721,11 @@ begin
|
|||||||
Result := MVCFramework.DuckTyping.WrapAsList(AObject, AOwnsObject);
|
Result := MVCFramework.DuckTyping.WrapAsList(AObject, AOwnsObject);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TMVCController.SetETag(const Data: String);
|
||||||
|
begin
|
||||||
|
Context.Response.SetCustomHeader('ETag', GetMD5HashFromString(Data));
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TMVCController.SetViewData(const aModelName: string; const Value: TObject);
|
procedure TMVCController.SetViewData(const aModelName: string; const Value: TObject);
|
||||||
begin
|
begin
|
||||||
GetViewModel.Add(aModelName, Value);
|
GetViewModel.Add(aModelName, Value);
|
||||||
|
Loading…
Reference in New Issue
Block a user