#1 Re: mORMot 1 » Smart Mobile Studio 3 - Compilation error » 2019-01-24 17:58:58

I download the mORMot_and_Open_Source_friends_234301_06b24ae728 today and patched some needed SynCrossPlatform units and mORMotWrappers (generate mORMot cross-platform clients code from the server). and some changes at the project 27 and 29 are required to work at both both 2.x and 3.x,

Now, it compiles and works in both SMS 2.2.2.04694 (lastest WinXP compatible) and SMS 3.1.0.80 (development version)! 

SMS 3x

download link: https://www.dropbox.com/s/d4y6wkdtrurcc … 3x.7z?dl=0

#2 Re: mORMot 1 » Smart Mobile Studio 3 - Compilation error » 2019-01-24 12:29:43

In fact, there is minor issue/bug on older SMS versions 1.2 | 2.0 | 2.0.1 | 2.2 and 2.2.2 - the TObject::Destroy method would just delete the property named "prop" rather than the actually all the properties of the object itself. For instance, obj.Free is doing nothing because the method Destroy was buggy.

var TObject={
    (...)
    Destroy: function (s) { for (var prop in s) if (s.hasOwnProperty(prop)) delete s.prop },
    Destroy$: function(s) { return s.ClassType.Destroy(s) },
    (...)
}

Look it should be: delete s[prop] --> It will remove all properties from JavaScript object itself. The delete operator is more about freeing memory than deleting an element. This issue was fixed on the DWScript trunk. On newer SMS version 3.x, they fixed the TObject::Destroy method.

Some changes are needed on the SynCrossPlatform units, Eric Grange has made some changes on the DWscript, nowadays, in my tests, it compiles and works in both SMS 2.2.2.04694 (lastest WinXP compatible) and SMS 3.1.0.80 (development version)!
I forgot to say, the examples 27 and 29 (specific SMS) should be updated on the current mORMot branch. There is an issue at the example 29. When you open the project, there's an ugly message: "Error while loading project file with the message: WebForm.pas doesn't exist". So, you can not open the project 29, because there's an bug in the SMS 2.x (Make Project/Item external) this issue, you can miss units on the project.

#3 Re: mORMot 1 » Destroy method issue on DWScript 1.x and 2.x branch » 2018-12-27 14:27:32

It compiles and works in both SMS 2.2.2.04694 (last WinXP compatible) and SMS 3.1.0.80 (development version)!

The updated examples 27 and 29 --> https://www.dropbox.com/s/uonih6izjpiw7 … x.rar?dl=0

The current mORMot branch, there is an issue at the example 29. When you open the project, there's an ugly message: "Error while loading project file with the message: WebForm.pas doesn't exist". You can not open the project 29, because there's an bug in the SMS 2.x (Make Project/Item external) this issue, you can miss units on the project.

Nowadays, the synchronous methods are deprecated is most modern browsers, it shows a info message:
"[Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/."

Yeah, that "false" makes the request synchronous (i.g. request.open('GET', '/bar/foo.txt', false)). Anyway, both synchronous and asynchronous methods work, depending on use case. For instance, you can invoke a method to calculate both in syn or async ways. When you call a method starting with underscore _*() methods means you are invoking as sync way, this should be avoid in these days.

#4 mORMot 1 » Destroy method issue on DWScript 1.x and 2.x branch » 2018-12-26 19:26:45

warleyalex
Replies: 2

I spent hours debugging an issue with mORMot classes with SMS 3.x I couldn't detect why it couldn't work like in the previous version 2.2x. I think the error comes from the /destroy method.

In previous versions, SMS 1.2 | 2.0 | 2.1 | 2.2 | 2.2.2, the method Destroy emitted by transpiler is

var TObject={
	$ClassName: "TObject",
	$Parent: null,
	ClassName: function (s) { return s.$ClassName },
	ClassType: function (s) { return s },
	ClassParent: function (s) { return s.$Parent },
	$Init: function () {},
	Create: function (s) { return s },
	Destroy: function (s) { for (var prop in s) if (s.hasOwnProperty(prop)) delete s.prop },
	Destroy$: function(s) { return s.ClassType.Destroy(s) },
	Free: function (s) { if (s!==null) s.ClassType.Destroy(s) }
}

Note this code would just delete the property named 'prop' rather than the actually properties of the object itself, which in turns meant references in a "freed" object could not be garbage collected until the freed object got out of the scope.

The Destroy method emitted by SMS 3.x is correct:

var TObject={
    (...)
    Destroy: function (s) { for (var prop in s) if (s.hasOwnProperty(prop)) delete s[prop] },
    Destroy$: function(s) { return s.ClassType.Destroy(s) },
    (...)
}

The following minimal snippet of code worked in previous SMS 2.0 | 2.1 | 2.2, but not longer works as expected in version 3x. See the client.Free automatically calls the destructor.

var
  model: TSQLModel;
  people: TSQLRecordPeople;
  client: TSQLRestClientHTTP;
begin
  model := GetModel;
  model.GetTableIndexExisting(TSQLRecordPeople);
  people := new TSQLRecordPeople;

     client := TSQLRestClientHTTP.Create('127.0.0.1',888,model,false);
     client.Connect(
      lambda

        if client.ServerTimeStamp=0 then
          ShowMessage('Impossible to retrieve server time stamp') else
          writeln('ServerTimeStamp='+IntToStr(client.ServerTimeStamp));
        if not client.SetUser(TSQLRestServerAuthenticationDefault,'User','synopse') then
          ShowMessage('Authentication Error');
        writeln('Safely connected with SessionID='+IntToStr(client.Authentication.SessionID));
        people := TSQLRecordPeople.Create(client,1); // blocking request
        assert(people.ID=1);
        writeln('Disconnect from server');
        client.Free;
      end,
      lambda
        ShowMessage('Impossible to connect to the server');
      end);

Note: mORMot examples 27 and 29 should not work with SMS 3.x out of box.

#5 Re: mORMot 1 » Smart Mobile Studio supported or not?? » 2018-05-02 11:13:26

AOG wrote:

@warleyalex
I might have enough time to help you with your efforts.
But important: could you give some more details about the opinion of the Pas2JS team on this. Are they opposed or have reserves ?

Alf,

We proposed to Pas2JS team (Michael Van Canneyt / Mattias Gaertner) an "open source" alternative with the Lazarus IDE as "base library". The Pas2JS team have reserves on this.

Mattias Gaertner wrote:

> About reverse engineering:
> If someone reverse engineered the same behavior, using different code,
> it is probably no problem.
> If someone reverse engineered the exact Pascal code from the TMS JS
> code, pas2js will create code that looks exactly like the TMS JS code.
> Then I guess it depends on the judge what to believe. It could be
> treated as disassembling instead of reverse engineering.
>> Of course, if it turns out you copied code from TMS, that code cannot be made public.
>> But at first sight, it does not seem to be so.


>The code looks as if someone has used a JS to pascal converter
>- AKA it was merely disassembled.

>I'm not a lawyer, but for my taste this is far too near a
>copyright violation. Using this as a base for a library would definitely
>give bad publicity.

>from Mattias

this file contains WebLib and some demos but using runtime components only.
https://www.dropbox.com/s/vvg0e086hsmh9 … n.rar?dl=0

Alf, maybe you also has ideas.

#6 Re: mORMot 1 » Smart Mobile Studio supported or not?? » 2018-05-01 23:40:06

The Pas2JS with Delphi/TMS it's a bit pricey!

1. TMS WEB Core:= 295 EUR introductory price
2. TMS WEB Studio := 595 EUR introductory price (TMS WEB Core + TMS FNC controls + TMS XData)
3. It can be installed in Delphi XE7 to Delphi Tokyo 10.2.x sad

We proposed to Pas2JS team another "open source" alternative using with the Lazarus IDE as base library.

...just analyzing the TMS Web Core emitted javascript output, and and quite a bit of effort, doing some reverve engineering I believe I've created a clone of the following components:

TLabel, TEdit, TButton, TComboBox, TMemo, TListBox, TSpinEdit, TCheckBox, TPaintBox, TImageControl, TPanel, TSplitter, TGridPanel, TSpeedButton, TToolBar, TDBEdit, TDBLabel, TDBSpinEdit, TDBMemo, TDBNavigator, TMessageDlg, TClientDataSource, TClientDataSet.

     ,  ,  , , , 
    <(__)> | | | 
    | \/ | \_|_/ 
     \^  ^/   | 
     /\--/\  /| 
    /  \/  \/ | 

- there are enough similarities that it's clear that they have the same source. I didn't illegaly copied the source code anyway, since TMS didn't release the product yet; some reverse reverse engineered the exact Pascal code from the TMS JS code, pas2js compiler will create code that looks exactly like the TMS JS code. The Pas2JS team think it could be treated as disassembling instead of reverser engineering. "It's far too near a copyright violation, AKA it was merely disassembled, using this as a base for a library would definitely
give bad publicity", said Pas2JS team.

Any idea about this - the code copyright "javascript piracy"?

#7 Re: mORMot 1 » Smart Mobile Studio supported or not?? » 2018-04-25 13:20:31

Smart Mobile Studio is cool and I love the DWScript based Object Pascal language. However, some ideas like Raspberry PI/iOT, Smart Desktop/Amibian.js, sounds like FUD to me. It seems that SMS is running too many races at once, we don't need stories about Smart potencial implementation wishes, but real working features. We do not need to know what SMS "can do", but what SMS "does".

I'm quite confident our mORMot suits better with the free open source Pas2JS FPC based project.
We have full code completion on the Lazarus IDE. About generating cross-platform client code for Pas2JS should not be so much difficult. A little issue is the missing Anonymous function missing feature. ...but some features like like generics, attributes and anonymous functions aim to get these items done throughout this year (2018). Certainly, Pas2JS is moving in faster steps. Whatsoever I've been thinking to follow SMS integration pattern, I think it is technically feasible and implement the client wrappers is certainly the way to allow safe and efficient access to a mORMot server.

There are a lot of possibilities, in the near feature, I hope we can use more than 80 components with the Pas2JS/Lazarus, for instance, we can use the TMS Web Core components, TMS FNC Components with Lazarus IDE.

In my experimental projecthttps://www.youtube.com/watch?v=1Y6JoWUFEXw I've already converted some TMS Web Core visual components to be used directly on the Lazarus IDE!

Pas2JS + mORMot + Lazarus = I love free stuff. No restrictions, no limits.

#8 Re: mORMot 1 » [Problem] Implementation conn pool in unigui ? » 2018-01-29 01:18:13

edwinsn wrote:

So it's a win for delphi deveopers?
One question -
- I think Ideara hasn't acquired FMSOFT?

I was probably drunk last night, Idera didn't buy FMSoft! (that's bad news for UNIGUI).

about Idera absorbing sencha company.
I remember since the Art Landro has joined the Sencha's company as its new CEO. The worst mistake was letting Sequoia near it. From that point it was all lies and sticky-tape. First decision: immediately, the super architect Aconran and others core employees were laid off and comes with the decision of the diabolic the requirement to purchase "5-dev license for only 5K", and wow, they simply deleted all the comments as "no longer relevant" about ExtJS. Sencha was treating their community like sh*t.
The latest version available to us has known bugs that are fixed already. I remember I fixed some bugs myself and submit countless fixes back to Sencha but don’t get to track their integration via a pull request or use the framework versions that incorporate them in my open source projects. These CEO left a large hole in the boat.

Let’s not pretend this acquisition is good news for anyone using Sencha products. It's indirect confirmed, IDERA has already dismissed all developers and will outsource the development process to places like India, and they have already told the Sencha services guys to look for new jobs. Presumably IDERA got Sencha for a fire sale price and now intends to milk the licensing revenues while they last without investing much. The acquisition comes along with the announcement on Single Developer Licences for Ext (US$960), this is indeed annual subscription license that includes 1 year of development and distribution rights. For perpetual license (minimum 5 licenses for $4,340).
--------
Look, this BIG predator, just care about how they can earn more and eliminate their competitors. I think they will propose a single developer perpetual license linked with Delphi to use ExtJS. That more expensive Delphi licenses await us (bad news). If so, only UniGUI will be the extra cost.

(mORMot with Ext) and (UniGUI with Ext) is like rocket and turtle if we spoke about speed.

#9 Re: mORMot 1 » [Problem] Implementation conn pool in unigui ? » 2018-01-28 02:24:29

To understand what is happening:
1. Idera, sees a flaw, a blatant lack and a shortfall in the EMB web products.
2. Idera sees in unigui, the ideal solution to overcome this lack. She wants UNIGUI.
3. Idera wants to offer Unigui as an add-on, at a reasonable price, she will have to get rid of the expensive Sencha licenses.
4. What she did by absorbing sencha company.
5. Idera is a good player: she counts on millions Delphi users in the world, Who are impressed by UNIGUI project.
6. Idera has no intention of re-inventing the wheel. It will be satisfied with the hard work of FMSOFT, of what has endured Farshad since 2009 !
7. Finally, as an apotheosis, as I know, most of the smaller companies bought by BIG predators, products dies at the end. These BIG predators can do any thing. As far I know they don't care about customers, they just care about how they can earn more and eliminate their competitors.

#10 Re: mORMot 1 » Understanding mORMot » 2017-04-02 22:37:39

Let's suppose you have an iPod, it's so beautiful and easy to play with it, but it is a tight coupling player, once the battery dies you might as well buy a new iPod because the battery is soldered fixed and won't come loose, thus making replacing very expensive. A loosely coupled player would allow effortlessly changing the battery.

Would you rather spend less money just for a battery and have a working iPod again or you would prefer to spend a lot of money for a whole iPod?

It's a trade-off when you try to pick between an tight coupled framework and a loosely coupled player set of tools that work together. The latter gives you more freedom but requires you to make more architectural decisions, it also means the learning curve is high an flexibility suffers. This loosely coupled framework was designed to be highly
optimized to speed. It uses a lot of established conventions/patterns and once you are familiar enough with them, it can make you very productive.

#11 Re: mORMot 1 » Simulate Web Form Post Response » 2017-03-22 13:11:09

I have to use the inherited method Post instead of the Request... and it worked as expected! Thanks a lot.

#12 Re: mORMot 1 » Simulate Web Form Post Response » 2017-03-21 22:16:40

I've got the following response: http://pastebin.com/raw/wpzPZdfx   (see the page is renderized)

The response using https://www.hurl.it/ is:
See the response picture See this image before page render

#13 Re: mORMot 1 » Simulate Web Form Post Response » 2017-03-21 19:22:29

No, the same response using stream.

I get the content (the source code) of the of the page.
view-source:http://www.clevercomponents.com/products/inetsuite/demos/serverformpost.asp

I would like to get this response:

Sent data:
Name = Mr.AB
Birthdate = May 5, 1985
Account = 12345

#14 mORMot 1 » Simulate Web Form Post Response » 2017-03-21 13:26:45

warleyalex
Replies: 5

I'm using 'SynCrtSock' unit and trying  to simulate the data submit action occured on "Submit" button click.
This code uses the HTTP POST method to send a data to web server specified, but unfortunately, I couldn't
get the response body. Any idea?

var
  fClient: TWinHTTP;
  URI: TURI;
  URL: RawUTf8;
  FHeader, FData: SockString;
  response: TMemoryStream;
begin
  URL := 'http://www.clevercomponents.com/products/inetsuite/demos/serverformpost.asp';
  URI.From(URL);

  response := TMemoryStream.Create();
  try
    fClient := TWinHTTP.Create(URI.Server, URI.Port, false);
    if fClient.Request('/products/inetsuite/demos/serverformpost.asp?insite=1', 'POST', 0, '',
      'Name=Mr.AB&Birthdate=May+5%2C+1985&Account=12345',
      'Content-Type: application/x-www-form-urlencoded', FHeader, FData) = 200 then begin
      response.Write(fHeader[1], length(fHeader));
      response.Position := 0;
      Memo1.Lines.LoadFromStream(response);
    end;
  finally
    response.Free;
    fClient.Free;
  end;

The expect result would be:
(*
Sent data:
Name = Mr.AB
Birthdate = May 5, 1985
Account = 12345
*)

How to get the response body?

#15 Re: mORMot 1 » My mORMot Videos » 2017-03-12 01:00:09

...a long time no mORMot video, the goal this weekend is to move... just enough so people don't think I'm dead. Take a look at the mORMot Lab.

#16 Re: mORMot 1 » Bugs with TSQLRestClientURI.OnAuthentificationFailed » 2017-03-09 21:34:44

...I had to just unpack, another clean mORMot and patched the units and... tandãã... it worked as expected!

/\(^_^)/\

Mr. AB could take a look at this code.

#17 Re: mORMot 1 » Bugs with TSQLRestClientURI.OnAuthentificationFailed » 2017-03-09 19:45:59

See athttp://i.makeagif.com/media/3-09-2017/T2uxmP.gif
a. server and client is Up
b. disconnect server and then
c. restart server
d. reconnect the client 1st time (you have 3 chances to guess the credentials) // it is working
e. disconnect server
f. restart server
f. try to reconnect the client (now you've got forbidden 403)

#19 Re: mORMot 1 » Bugs with TSQLRestClientURI.OnAuthentificationFailed » 2017-03-03 22:30:57

I've read today this comment:

"For me, spreading ignorance (or bad information due to ignorance) is an issue. If you are gonna talk about subject XYZ, make sure you know subject XYZ, well enough to talk about it. At least, make sure that you are not making gross errors about subject XYZ. Is it really too much to ask?"

I really like this comment, believe, I'm not truly qualified to answer this question, a long time that I really play with mORMot. Forget, hum, I'm fuck crazy guy, whatever, I will take some inspiration of the above comment, and I'll try to create another mORMot video tomorrow, stay tuned. We need to tame this little beast.

Hey, Can you confirm, it seems this crappy code is working, take a look:

function TForm2.ClientFallisceAutenticazioneEvento(Retry: integer; var
  aUserName, aPassword: string; out aPasswordHashed: boolean): Boolean;
begin
  for Retry := -1 to Database.MaximumAuthentificationRetry do
  begin
    Database.MaximumAuthentificationRetry := Retry - 1;

    case Retry of
      0, 1, 2:
        begin
          if TLoginForm.Login('Authentication', 'Please enter your credentials',
            aUserName, aPassword, TRUE, '') then
          begin
            result := Database.SetUser(aUserName, aPassWord);
            if result then
            begin
              break;
              exit;
            end
            else
              result := false;
          end;
        end;
    end;
  end;
  result := true;
end;

#20 Re: mORMot 1 » Bugs with TSQLRestClientURI.OnAuthentificationFailed » 2017-03-03 19:02:15

I can confirm the issue.
If you enter the correct credentials at 1st try; work as expected.
If you enter the wrong credentials at 1st try; the subsequent tries... it keeps failing - you are not re-authenticated;

#21 Re: mORMot 1 » Bugs with TSQLRestClientURI.OnAuthentificationFailed » 2017-03-03 14:08:59

Indeed, the authentication keeps failing, the Result is always true;

#22 Re: mORMot 1 » Streaming with THttpApiServer » 2017-02-16 19:30:12

AFAIK, currently it is not possible to communicate in raw binary mode (e.g. send raw video streaming), a new kind of record would be necessary to send binary data from the server to the client.
All communication is is done through base64-encoding (using interface based services), this will adds 30% to 50% overhead.

#23 Re: mORMot 1 » Serializing a Dynamic Array in Interfaced based services » 2017-02-13 12:19:08

In order to be able to use this kinda service, a factory is mandatory. Before, you have to explicity resolve the factory to get automatic injection, you need to register the magic factory via aServer.ServiceContainer.InjectResolver(..). Doing this, it would let the factory be owned by aServer.Services - the parent, so that way you would not need to manually release its instance - the parent will release for you.

#24 Re: mORMot 1 » event sourcing » 2017-02-06 18:07:54

No. This pattern (use interface parameters to interface-based service methods to send a callback to the server) can also be via client TSQLRestClient (which may be over HTTP).

{ login }
GET /root/TimeStamp HTTP/1.1
GET /root/Auth?UserName=Supervisor HTTP/1.1
GET /root/Auth?UserName=Supervisor&Password=e20f974a72b2e457d4d1b070ee7a8130e4e34d4fa2bd50422c684f3281917a84&ClientNonce=7218250DB57A2F308A8E4274E0859CB23F8572D76A6244C1B0FA8B28C451F421 HTTP/1.1
GET /root/TimeStamp?session_signature=012B5CCBF1452A52B3B4A862 HTTP/1.1

{ ServiceDefine on the client side }
POST /root/MyOtherService._contract_?session_signature=012B5CCBF1452A53A3E3DCBD HTTP/1.1
[]

POST /root/MyOtherCallback._contract_?session_signature=012B5CCBF1452A53674BAAE9 HTTP/1.1
[]

{ call the Withdrawal client method which will call the server callback MethodWithCallback(amount,self) }
POST /root/MyOtherCallback.Withdrawal?session_signature=012B5CCBF1452A53332FF6F1 HTTP/1.1
[2000]

{ client release }
GET /root/Auth?UserName=Supervisor&Session=19619019&session_signature=012B5CCBF1452A55EEFF2E27 HTTP/1.1

I can't find a way to invoke the Withdrawal method on the ajax client; for initialization of the registered interface, for instance, i believe the resolve method is required on the client side to work.

#25 Re: mORMot 1 » event sourcing » 2017-02-05 22:46:39

I would like to use a interface-based service "Test" method to send a callback to the server.
I'd like to receive the callback event.

Does anyone can shed some light on this?

type
  IMyCallback = interface(IInvokable)
    ['{5CD49AB1-D5A3-4059-B287-25E939DD2A0B}']
    procedure EventCalledFromServer(const withAValue: integer);
  end;
  IMyService = interface(IInvokable)
    ['{FB31BF33-38C7-45AE-9511-6AC727ADC4F4}']
    procedure MethodWithCallback(const anyParameter: variant; const TheCallBack: IMyCallback);
  end;
type
  TMyServiceClient = class(TInterfacedObject,IMyCallback)
  protected
    fRest: TSQLRestClient;
    // here the callback will point back to "self", so IMyCallback is implemented now
    // but you may set a callback from any another class implementing IMyCallback
    procedure EventCalledFromServer(const withAValue: integer);
  public
    procedure Test;
  end;

procedure TMyServiceClient.Test;
var MyService: IMyService;
begin
  if fRest.Services.Resolve(IMyService,MyService) then
    MyService.MethodWithCallback(1234,self);
end;

procedure TMyServiceClient.EventCalledFromServer(const withAValue: integer);
begin // will be called back by the server
end;

type
  TMyServiceServer = class(TInterfacedObject,IMyService)
  protected
    fCallback: IMyCallback; // for delayed call, in sicClientDriven mode
  public
    procedure MethodWithCallback(const anyParameter: variant; const TheCallBack: IMyCallback);
    procedure AnotherMethod;
  end;

procedure TMyServiceServer.MethodWithCallback(const anyParameter: variant; const TheCallBack: IMyCallback);
begin
  TheCallBack.EventCalledFromServer(1234);
  fCallback := TheCallBack; 
end;

procedure TMyServiceServer.AnotherMethod;
begin
  if assigned(fCallback) then
    fCallBack.EventCalledFromServer(5678);
end;

#26 mORMot 1 » event sourcing » 2017-02-03 19:55:57

warleyalex
Replies: 3

Hi guys, please forgive me if what I'm posting here is irrelevant.  I've created an educational project "ATM machine simulation" in SmartMobileStudio with withdrawal, deposit, transfer, bill payment, extract, balance options enabled.

See the Live Project at: ATM Machine
If you like to test, use the PIN=1234

I have heard about Event Sourcing before in the forum. I'm wondering based on this example if will give someone   some inspiration to create a demo about this.

I've been considering using Event sourcing in mORMot, but unfortunately, I didn't have a clue how to start, basically,
I know that an "Event" is something that happend in the past; you create an event for every state change of the object, something like:

BankAccountCreated  --> DepositPerformed  --> OwnerChanged  --> WithdrawalPerformed
id: 12                            accountID: 12           accountId: 12         accountId: 12
owner: John                   amount: 20               newOwner: Jane      amount: 10

Using event sourcing, since every change to state is traceable, we can:

- perform mining/analysing financial transactions to track terrorists;
- retroactive event, to make easy to do undo things; track "who did that", "when do that";
- you know which items customers removed from their shopping cart.


Any idea?

#28 Re: mORMot 1 » FPC + ARM don't compile testSQL3 » 2017-01-17 22:04:16

Using the latest newPascal, not exacty flawless but I've got good results in a very old computer with WinXP

Total assertions failed for all test suits:  7 / 24,316,034

See: http://pastebin.com/raw/SZB4vPED

#30 Re: mORMot 1 » new book about mORMot » 2016-12-15 19:34:46

Unfortunately I didn't read the book yet. The book itself seems to be of good quality. One thing I really didn't like was the front
cover art of the book. I would expect a demoniac cool marmot illustration on the cover of a mORMot book.

Do the source code files for programs shown in the book are available to download?

#31 Re: SyNode » Beta release of SyNode - ES6 JavaScript + NPM modules » 2016-10-24 22:27:20

Would it be possible to use SynNode to compile smart pascal to javascript?

Following ComingNine's example, generate similar code:

var TWorker = {
   $ClassName:"TWorker",$Parent:TObject
   ,$Init:function ($) {
      TObject.$Init($);
      $.fName = "";
   }

   ,Create$61:function(Self) {
      Self.fName = "A new TWorker instance";
      return Self
   }
   ,Destroy:TObject.Destroy
};

Self.fWorker = TWorker.Create$61($New(TWorker));
console.log(Self.fWorker.fName);  // "A new TWorker instance"

#32 Re: mORMot 1 » Calling mORMot webservice from Java » 2016-10-13 19:54:41

The TSQLRest class has a 
   property Services: TServiceContainer read fServices;
   which you can access to the interface-based services list, so can get a list such as:

[{
"contract" : "MyService",
"implementation" : "shared",
"methods" : [{
		"method" : "Add",
		"arguments" : [{
				"argument" : "Self",
				"direction" : "in",
				"type" : "self"
			}, {
				"argument" : "n1",
				"direction" : "in",
				"type" : "integer"
			}, {
				"argument" : "n2",
				"direction" : "in",
				"type" : "integer"
			}, {
				"argument" : "Result",
				"direction" : "out",
				"type" : "integer"
			}
		]
	}, {
		"method" : "GetSampleRecord",
		"arguments" : [{
				"argument" : "Self",
				"direction" : "in",
				"type" : "self"
			}, {
				"argument" : "id",
				"direction" : "in",
				"type" : "int64"
			}, {
				"argument" : "SampleRecord",
				"direction" : "out",
				"type" : "TSQLSampleRecord"
			}, {
				"argument" : "Result",
				"direction" : "out",
				"type" : "boolean"
			}
		]
	}
]
}]

#33 Re: mORMot 1 » Extra square bracket » 2016-10-13 15:46:58

huumm...
result := AFP.SaveToJSON(true);
it returns the correct output:
{"result":[[[0,1,2,3,"1000","2000"],[1,2,3,4,"1001","1999"],[2,3,4,5,"1002","1998"],[3,4,5,6,"1003","1997"]]]}

and...
result := RecordLoadJSON(F, pointer(test),TypeInfo(TFV));
it returns an extra square bracket.
{"result":[[1,2,3,4,"1001","1999"],[2,3,4,5,"1002","1998"],[3,4,5,6,"1003","1997"]]]}
The custom reader method return an extra ']' for last item of array, and you'll get a  Unexpected token ]

#35 mORMot 1 » Extra square bracket » 2016-10-12 22:39:28

warleyalex
Replies: 1

Following this post. Why does JSON have extra square bracket in the output?

{"result":[[1,2,3,4,"1001","1999"],[2,3,4,5,"1002","1998"],[3,4,5,6,"1003","1997"]]]}

  AFP.Init(TypeInfo(TFVs),AF);
  for i := 0 to 3 do begin
    F.Major := i;
    F.Minor := i+1;
    F.Release := i+2;
    F.Build := i+3;
    F.Main := IntToString(i+1000);
    F.Detailed := IntToString(2000-i);
    AFP.Add(F);
  end;

  test := AFP.SaveToJSON;
  result := RecordLoadJSON(F, pointer(test),TypeInfo(TFV));

#36 Re: mORMot 1 » Master/Slave replications - tips :) » 2016-10-10 21:31:12

I just had a closer look at this post

It seems there is some interesting concepts about sync that I think could be applied to.

#001. Each client (the mobile app) must decide when to sync with the server, e.g. when a user clicks "DO_SYNC Refresh". The app will sync by calling a method DO_SYNC(). This method will call syncFromServer() first and then syncToServer().  The app will always get new data FROM the server first and then send new data TO the server.

#002. The syncFROMServer() method on the client, will ask the server for all data changes since servercounter_lastsync. The server will answer this request by fetching all objects with object.counter_lastupdate > servercounter_lastsync and sending them to the client. The server will also send its current counter to the client.
The client will store this new value in servercounter_lastsync (because this is the server counter for which the
client has received all data changes).

Example Sync objects of type "booking" FROM server TO client (DOWNLOAD):
GET http://127.0.0.1/root/booking/list/12345

12345 = client.SERVERCOUNTER_LASTSYNC (counter value on server for start of sync)

JSON returned FROM server TO client:

{
	objects : [{
			guid : 65E5B3EB-72B3-4768-B86D-B0D07DF81C3E,
			pk : 2014-05-10,
			name : apples,
			value : 9,
			timestamp_created : 2014-03-20 13:15:00,
			timestamp_lastupdate : 2014-03-20 13:15:00
		}, {
			guid : 77310491-2B68-4EF2-AD8A-5DA75D0BB168,
			pk : 2014-0-12,
			name : oranges,
			value : 3,
			timestamp_created : 2014-03-20 12:18:08,
			timestamp_lastupdate : 2014-03-20 15:17:23
		}, {
			guid : 93F58F2C-8837-4CE3-A3DB-CA0AD01632B7,
			pk : 2014-07-18,
			name : cherries,
			value : 6,
			timestamp_created : 2014-03-20 13:16:32,
			timestamp_lastupdate : 2014-03-20 15:17:58
		}
	],
	result : {
		statuscode : OK,
		SERVERCOUNTER : 453
	}
}

#003. The syncTOServer() on the client, will send all its data changes TO the server since COUNTER_LASTSYNC.
The client will fetch its objects with object.counter_lastupdate > COUNTER_LASTSYNC and send them to the server.
When the server confirms have received the data (result = ok), the client will update its COUNTER_LASTSYNC with
the current value of its counter.

Example Sync objects of type "booking" FROM client TO server (UPLOAD):

POST http://127.0.0.1/root/booking/update

JSON in POST FROM client TO server: 

{
	objects : [{
			guid : 65E5B3EB-72B3-4768-B86D-B0D07DF81C3E,
			pk : 2014-05-11,
			name : apples,
			value : 9,
			timestamp_created : 2014-03-20 13:15:00,
			timestamp_lastupdate : 2014-03-20 13:15:00
		}, {
			guid : 77310491-2B68-4EF2-AD8A-5DA75D0BB168,
			pk : 2014-06-12,
			name : oranges,
			value : 7,
			timestamp_created : 2014-03-20 12:18:08,
			timestamp_lastupdate : 2014-03-20 15:23:25
		}, {
			guid : 93F58F2C-8837-4CE3-A3DB-CA0AD01632B7,
			pk : 2014-07-18,
			name : cherries,
			value : 9,
			timestamp_created : 2014-03-20 13:16:32,
			timestamp_lastupdate : 2014-03-20 15:19:43
		}
	]
}

JSON returned FROM server TO client : 
{
	result : {
		statuscode : OK,
		SERVERCOUNTER : 456
	}
}

The idea of EACH DEVICE (client) will keep track of its sync status using these 2 parameters:
• COUNTER_LASTSYNC: value of the local counter of the client on the last sync TO the server (upload)
• SERVERCOUNTER_LASTSYNC: value of the counter on the server, on the last sync FROM the server (download)

I wish I could implement the Sync using this approach.

#37 Re: mORMot 1 » Tables, permissions and more... » 2016-10-10 19:56:43

I think you can use a dedicated service, it will fulfill your needs. For more complete control, you may define some interface-based services, then set the per-interface or per-method security options, to allow/disallow each service for each user or group. For instance:

 Server.ServiceRegister(TServiceCalculator,[TypeInfo(ICalculator)],sicShared).
    DenyAll.AllowAllByName(['Supervisor']);

This will allow access to the ICalculator methods only for the Supervisor group of users.

More details about interface-based-services

#38 Re: mORMot 1 » Decode plus issue » 2016-09-28 14:51:55

I must've drunk two liters of caçacha. I've been posting a lot of non-sense posts.

#39 mORMot 1 » Decode plus issue » 2016-09-28 13:36:08

warleyalex
Replies: 3

"Javascript"
encodeURIComponent('TDsIInOXIfj+yvJ4XmSN7tfFa4eaYnY8D2DDwiA3cyD71eprc3OA7aBbGhWuLZml0ublwrxfDmmERKML2wfGRw==') ==>

"TDsIInOXIfj%2ByvJ4XmSN7tfFa4eaYnY8D2DDwiA3cyD71eprc3OA7aBbGhWuLZml0ublwrxfDmmERKML2wfGRw%3D%3D"

"Delphi"
http://localhost:8080/root/MyServiceFree.SignUp?userPass=TDsIInOXIfj%2ByvJ4XmSN7tfFa4eaYnY8D2DDwiA3cyD71eprc3OA7aBbGhWuLZml0ublwrxfDmmERKML2wfGRw%3D%3D


function TMyServiceFree.SignUp(userPass: RawUTF8): RawJSON;
var
  JSON: RawUTF8;
begin
 JSON := UrlDecode('TDsIInOXIfj%2ByvJ4XmSN7tfFa4eaYnY8D2DDwiA3cyD71eprc3OA7aBbGhWuLZml0ublwrxfDmmERKML2wfGRw%3D%3D');

WriteLn(JSON); --> 
TDsIInOXIfj+yvJ4XmSN7tfFa4eaYnY8D2DDwiA3cyD71eprc3OA7aBbGhWuLZml0ublwrxfDmmERKML2wfGRw==

WriteLn(UrlDecode(userPass)); -->
TDsIInOXIfj yvJ4XmSN7tfFa4eaYnY8D2DDwiA3cyD71eprc3OA7aBbGhWuLZml0ublwrxfDmmERKML2wfGRw==

+ is missing.

Any idea?

#40 Re: mORMot 1 » SignUp on HTTP » 2016-09-27 17:55:23

Apologies for my ignorance, this is simply a javascript callback smile. Thanks!

#41 mORMot 1 » SignUp on HTTP » 2016-09-27 13:55:05

warleyalex
Replies: 6

Hi everyone, sorry the ignorance,

I want to provide a server where anybody, via a web interface on HTTP, can register a new user.
Afterwards, the user will log in with his registered user name, and from here, all operations will be done logged in.
Since I am using a web interface for everything, I am going to use only the interface-based services as the interface
with the server. Internally, these services will comunicate with the database layer to perform whatever.

About the security, everything must be secured (using the framework security options), but the registration of a new user, which, since there is no user yet, it cannot be secured.

To allow the users to register a new user without security, I've created a "signup" method, this is actually
By Pass Authentication method in order to by-pass of the RESTful authentication scheme.

So, the app encodes a message with AES-256 and passes it to a server via AJAX. Then the server and decodes the message with SynCrypto.

I'll encrypt/decrypt the message with the "same key", the initialization vector (iv), would be dynamic, generated from the server, with a random 16-byte. Actually, the random IV is public.

for instance:
------------
At the client, onClick "Register" button, the public method genIV will be envoked:

I'll get the response of
POST http://localhost:8080/root/MyServiceFree.genIV --> response {"iv":"6e77e69599bf7401c63efebe449750f4"}

...and using CryptoJS AES-256 to encrypt the user info:

{"user":"warleyalex", "password":"abcd", "email":"abc@.com"}

On submit "form User registration":

POST http://localhost:8080/root/MyServiceFree.SignUp
{ "ciphertext":"48CFbqo+igV2FYcqD40aJ5C1P8DmZrlNIXp4W76zNftWSoRDOfU45aC8l5jtFORi
6FsW5IkkWJ4xvTUVirbJyA==" }

At the server, the problem is the server entity which will decrypt the message must know the generated IV "6e77e69599bf7401c63efebe449750f4".

Any hint?

#42 Re: mORMot 1 » AES Encrypt in CryptoJS and decrypt in SynCrypto » 2016-09-26 22:55:26

I've been thrown head first into a task which I'm feeling pretty disorientated about, trying to piece it all together...

and finally I got successfuly decrypt an encrypted AES-256 string from CryptoJS using SynCrypto smile

I'm using the tool mORMot/JS/AES to generate the key and IV, I just have to copy 'n paste the key/iv into SynCrypto and you can decrypt the cipherText.

#43 Re: mORMot 1 » AES Encrypt in CryptoJS and decrypt in SynCrypto » 2016-09-25 14:11:28

Note that CryptoJS generates similar strings start the same way, there's a salted prefix base64 encoded
The prefix 'Salted__' prefix is added to encrypted cipher.

U2FsdGVkX191ODhWOVL5TAGl0gvhK/VqGyyV90UimNg=   // test
U2FsdGVkX1+WwR/zthxXTCId8IE/CiSPmWjhXL/9YGU=    // test
U2FsdGVkX1/upKAyGuoFwDFdz5qrO6izE6TnYnunbYo=    // test
U2FsdGVkX19bNLYeAjWVjLxy0B8D89yW8gzSNEt95dU=   // test

I tried to insert the 'Salted__' prefix into SynCrypto to decrypt the cipherText from CryptoJS. No luck.
Anyway, I try the node-Crypto.

Any hint would be appreciated.

#44 Re: mORMot 1 » AES Encrypt in CryptoJS and decrypt in SynCrypto » 2016-09-24 22:25:48

Unfortunately, I could not decrypt the cipherText from SynCrypto sad

var
  key : TSHA256Digest;
  aes : TAESCBC;
  s    : RawByteString;
begin
  SynCommons.HexToBin(PAnsiChar(
    '33743b03c28fc783b01119d8b8c6b2564108318d465a2fb4ff319010c4aa6493'),@key,sizeof(key));

  aes := TAESCBC.Create(key, 256);
  try
    s := StringToUTF8(edtCrypted.Text);  ----> cipherText from CryptoJS

    edtDecrypted.Text := UTF8ToString(
      aes.DecryptPKCS7(Base64ToBin(s), true)
    );
  finally
    aes.Free;
  end;
end;

I suspect the iv, key and salt should match with the CryptoJS, SynCrypto generates very different output to similar config.

CryptoJS generates similar cipherText
U2FsdGVkX191ODhWOVL5TAGl0gvhK/VqGyyV90UimNg=   // test
U2FsdGVkX1+WwR/zthxXTCId8IE/CiSPmWjhXL/9YGU=    // test
U2FsdGVkX1/upKAyGuoFwDFdz5qrO6izE6TnYnunbYo=    // test
U2FsdGVkX19bNLYeAjWVjLxy0B8D89yW8gzSNEt95dU=   // test

whereas SynCrypto generates different cipherText, such as:

Xb6j9dHzEBqQk49Fnly3jvzRp3yLmeS3G5km5nJi2JM= 
xxVMU/6ytwYKZjuPVeEZP2EB6cEk403OK+WMiQAtvPA=
kpz1uR8oQTJzRIGgln+aplh+jEaJsiBKF/qaLgiQaKw=
AwJNKNx8OH37e7LQhTE2QM3WnpVMY8umnNhNwaLS4r0=
81MSSvWFN91HUeXdoVx8R2Dd0dZgOqFJomRwRIiH8+I=

#45 mORMot 1 » AES Encrypt in CryptoJS and decrypt in SynCrypto » 2016-09-24 12:32:58

warleyalex
Replies: 6

I'd like to use CryptoJS to perform the encryption and for the life of me I cannot work out why this won't decrypt with SynCrypto.

My knowledge of encryption isn't brilliant but the thing I am noticing is the CryptoJS encrypted ciphertext for the exact same string/key differs every time i perform the encryption in SynCrypto/Delphi. I suspect SynCrypto won't be able to decrypt the cipher if the initialization vector and salt match with SynCrypto, which I don't know how to set this is SynCrypto. Does someone shed some light on this.

CryptoJS:

var e  =  CryptoJS.AES.encrypt("test", 
  '33743b03c28fc783b01119d8b8c6b2564108318d465a2fb4ff319010c4aa6493', 
  '{"iv":"","mode":"CBC","padding":"Pkcs7","keySize":256,"cipher":"aes","salt":""}')
  .toString(); // "U2FsdGVkX180ir2xXrGQJ//1Z8YXhvRCsoZFTscG3A4="

CryptoJS.AES.decrypt(e, 
  '33743b03c28fc783b01119d8b8c6b2564108318d465a2fb4ff319010c4aa6493')
  .toString(CryptoJS.enc.Utf8);  // "test"

SynCrypto:

var
  key : TSHA256Digest;
  aes : TAESCBC;
  s:RawByteString;
begin
  //SynCommons.HexToBin(Pointer(SHA256(my_key)), @key, 32);
  //aes := TAESCBC.Create(key, 256);

  aes := TAESCBC.Create(('33743b03c28fc783b01119d8b8c6b2564108318d465a2fb4ff319010c4aa6493'), 256);
  try
    s := StringToUTF8(edtCrypted.Text); // "pbOMZBqrGzopqhE7vcfClTtRqsqh+C0axvMv6MN8uu4="
    edtDecrypted.Text := UTF8ToString(
      aes.DecryptPKCS7(Base64ToBin(s), true)  // "test"
    );
  finally
    aes.Free;
  end;
end;

#46 mORMot 1 » HTTP 500 Internal Server Error » 2016-09-15 12:28:28

warleyalex
Replies: 5

Sometimes the synopse forum are inaccessible due to an internal server error 500. I suspect that the server threw this  exception after I edit a big post message in the forum yesterday.

#47 Re: mORMot 1 » Some findings after spent an afternoon fiddling Linux/Lazarus/mORMot » 2016-09-14 14:47:53

Getting started with mORMot and FPC 3.1.1./Lazarus - target: i386-Linux

Step 1: Get the mORMot
a) If you don't know, there's a daily snapshot of the repository directly, just download this file:

b) Just unpack mORMotNightlyBuild.zip into C:\mORMot

Step 2: Unpack SQLite 3 static .obj files for i386-win32/win64
We'll also need the SQLite 3 static .obj files. This will allow our mORMot based application to embed the SQLite engine in our application.
a) If you plan to develop for 32-bit target environment just grab this file and extract it to your mORMot\sqlite3\ directory
b) If you plan to develop for 64-bit target environment just grab this file and place sqlite3-64.dll in your project’s build directory or in your Windows directory.

Step 3: Configure the mORMot environment

Add the following to your Delphi Library Path:
    C:\mORMot;
    C:\mORMot\SQLite3;
    C:\mORMot\SQLite3;
    C:\mORMot\CrossPlatform;
    C:\mORMot\SynDBDataset;
    C:\mORMot\SQLite3\DDD;
    C:\mORMot\SQLite3\DDD\dom;
    C:\mORMot\SQLite3\DDD\infra;

Step 4: Test the environment: target: i386-win32

Open C:\mORMot\SQLite3\TestSQL3.dpr with Delphi and run it. Make sure all the tests pass.

mORMot with FPC/Lazarus
The interface RTTI (available since Delphi 6), is not yet merged to the official FPC trunk, for its SOA feature, we need this to patch FPC RTL, but FPC core team are f* guys and does like to merge new features. To face such inconsistencies, some crazy-robo-enthusiastic guys (AB + longdirtyanimalf + MaciejIzak) just developed and merged some missing features and put all together in a project called NewPascal. This NewPascal contain a complete trunk FPC and Lazarus with dirty RTTI suitable for cross-compiling.

All right. Here you go.
Step 5: Install NewPascal
a) How to install NewPascal? Just go to this repository.


and grab this big package.

b) Unpack NPLazBaseWin32.rar in c:\NewPascal 
please note: it HAS to be installed in c:\NewPascal, otherwise things will not work !!

After unpack, you should have:

    c:\NewPascal\config_lazarus
    c:\NewPascal\fpc
    c:\NewPascal\fpcbootstrap
    c:\NewPascal\fpclazup
    c:\NewPascal\lazarus

Note: There's a link to start this Lazarus/NewPascal distro. (please note: you have to use this link to start, otherwise things will not work !!)

c) If you want to cross-compile, please unpack the desired archive in c:\NewPascal
for instance, if you want cross-compiling i386-linux from win32, just grab this cross-compiling-linux package.

then unpack into c:\NewPascal

Step 5: Sqlite3-FPC-only
As stated by the documentation, for FPC-only, we need static SQLite3 object .o files are needed for SQlite3 static linking for windows or Linux. Just grab this file.

and unpack two folders into C:\mORMot\

Step 6: Test the environment: target: i386-Linux

Open C:\mORMot\SQLite3\TestSQL3.dpr with Lazarus.
Note: put these conditionals at the start of the DPR/LPR

{$ifdef Linux}
  {$ifdef FPC_CROSSCOMPILING}
    {$ifdef CPUARM}
      //if GUI, then uncomment
      //{$linklib GLESv2}
    {$endif}
    {$linklib libc_nonshared.a}
  {$endif}
{$endif}


Dynamic Linking: target: i386-Linux
In my tests, we have to use the dynamic linking approach, so basically we have to comment a conditional in the synopse.inc

{$ifdef LINUX}
    {$ifdef CPUX86}
      {.$define FPCSQLITE3STATIC} // disable with dot !! <----------------------------
    {$endif}
  {$endif}

Project Options config
We're almost there. In the project options, set

(x) Build Modes (Linux)
-->Compiler Options
--> Paths --> Libraries (-Fi): C:\NewPascal\cross\lib\i386-linux\; C:\NewPascal\cross\bin\i386-linux\
--> config and Target --> Target OS: Linux
                                    Target CPU: i386
                                    Target Processor: default ;
--> Compilation and linking: ( 1 ) quick, debugger friendly -O1

Note:
--> Compilation and Linking
Optimization Levels:
( x ) 1 quick, debugger friendly -O1

/* It's wierd,  have to uncheck this feature to remove some errors in DDD test. */

Unit Style:
(   ) Smart Linkable -CX  ---> uncheck this feature
Linking:
(   ) Linking Smart -XX   ---> uncheck this feature

My system result with my very very old computer with Ubuntu 14.04.1 LTS was basically everything green.

FPC3.1.1+ CrossCompile+i386-linux32  smile smile smile smile smile

#48 Re: mORMot 1 » Some findings after spent an afternoon fiddling Linux/Lazarus/mORMot » 2016-09-13 21:17:32

Hum, dynamic linking. I just applied this trick, and sprint faster than Usain Bolt, mormot or squirrel... to see the tests on the very old computer with Ubuntu 14.04.1 LTS and almost everything is green. This is awesome!

FPC3.1.1+ CrossCompile+i386-linux32  smile smile smile smile smile


Nowadays, it's very difficult to find Kylix on the internet, but I it's especially powerful with mORMot.
Most developers would not notice or be concerned, after 16 years, the little mORMot still like this compiler. You can create small executables, the resulting executable just seemed to perform so much better if you compare with FPC.

#49 Re: mORMot 1 » Elevate Web Builder » 2016-09-13 20:33:56

Erick,
That's nice to see EWB with mORMot example.

Erick, one thing that I tend to disagree in both SmartMS and EWB is the RAD approach to build and manage the user interface. I sincerely do not like of this methodology, which I believe is difficult to work with a lot of views.
I'm just curious:
a) is easy to create a simple example like this in EWB This was created with SMS

b) Based on the example EWB-mORMot sample1a.wbs, IMHO, has generated a big overhead file size, f.i. sample1.html (192KB) and sample1.js (obfuscated/packed = 478KB). In this example, we can perform CRUD operations, it looks like Delphi RAD approach, using datasets, but I cannot see URI signature in the methods; is it possible to invoke services-methods transparently - just call the methods don't worry about the rest.

c) Unfortunately I can not afford EWB, could you provide us the EWB command line compiler, since non EWB customers can not post in the support forum. I would like to test this tool for educational purpose, and see the JS generated. Another thing is the new EWB 2.05 have the code insight feature? f.i. red when the file contains compilation errors, or code completion...

#50 Re: mORMot 1 » Some findings after spent an afternoon fiddling Linux/Lazarus/mORMot » 2016-09-13 19:56:46

AOG wrote:

FPC 3.1.1 from where?

This is from the NewPascal (a month ago) pack with Lazarus. It look likes there's a new pre-release which I didn't test;

AOG wrote:

Linux: also try dynamic linking (more or less the normal practice for Linux).

In order to use cross compile from Win32 to Linux I had to unpack the CrossLinuxi386.rar archive in c:\NewPascal

then in project Options
(x) Build Modes (default)
-->Compiler Options
--> Paths --> Libraries (-Fi): C:\NewPascal\cross\lib\i386-linux\; C:\NewPascal\cross\bin\i386-linux\
--> config and Target --> Target OS: Linux
                                    Target CPU: i386
                                    Target Processor: default ;
--> Compilation and linking: ( 1 ) quick, debugger friendly -O1

How do you perform cross compile from win32 to linux succeed using dynamic linking?

Board footer

Powered by FluxBB