#101 mORMot 1 » TAESCFB.EncryptPKCS7() raise SIGABRT when used in a thread » 2018-08-03 17:03:02

ertank
Replies: 1

Hello,

I am using Lazarus 1.8.4 with fpc 3.0.4. Installed from official DEB files in lazarus web site. Target is Linux amd64.

When I use below code out of a thread, in a GUI application, it just runs fine. However, if I put it in thread run IdTCPServer1Execute() procedure I have subject exception in line marked below:

procedure TForm1.Button1Click(Sender: TObject);
const
  AKey : Array[0..47] of Byte =  (121, 81,  10,  23,  25,  35,  45,  199, 112, 129, 27,  113, 114, 164, 187, 119, 141, 157, 162, 171, 180, 197, 102, 110, 195, 185, 172, 45,  35,  00,  56,  01, 148, 147, 247, 213, 124, 137, 141, 155, 132, 133, 132, 139, 130, 137, 138, 135);

var
  NewUsername: string;
  Key: TSHA256Digest;
  Aes: TAESCFB;
  AUtf8String: RawByteString;
  CryptUsername: string;
  CryptText: RawByteString;
begin
  NewUsername := 'pars.6C3C66740B954028A56EA610314BFAC6';
  Key := SHA256Digest(Pointer(@AKey), SizeOf(AKey));
  Aes := TAESCFB.Create(Key, 256);
  try
    AUtf8String := StringToUTF8(NewUsername);
    try
      CryptText := Aes.EncryptPKCS7(AUtf8String, True);  // <===== Exception here
      AUtf8String := BinToBase64(CryptText);
    except
      on E: Exception do
      begin
        ShowMessage(E.Message);  // Thread code do not have any interaction with GUI at all.
      end;
    end;
    CryptUsername := UTF8ToString(AUtf8String);
  finally
    Aes.Free();
  end;
end;

I have been using same lines for a while. They are just working. I cannot figure if there is anything I am doing wrong.

Any help is appreciated.

Thanks & regards,
Ertan

#102 GDI+ » Script fonts » 2018-07-01 22:42:04

ertank
Replies: 0

Hello,

Some script fonts are not printed completely both using SynDGIPlus or regular TBitmap.Canvas.TextOut(). I could not find a solution as to how I should be able to print them and they look fine on the final bitmap file.

Sample image: https://imgur.com/AR7I15t

Code sample:

procedure TForm1.Button1Click(Sender: TObject);
var Bmp: TBitmap;
    MF: TMetaFile;
    MetafileCanvas: TMetafileCanvas;
    DC: HDC;
    ScreenLogPixels: Integer;
begin
  MF := TMetaFile.Create;
  DC := GetDC(0);
  ScreenLogPixels := GetDeviceCaps(DC, LOGPIXELSY);
  MF.Inch := ScreenLogPixels;
  MF.Width := 3400;
  MF.Height := 4200;

  MetafileCanvas := TMetafileCanvas.Create(MF, DC);

  MetafileCanvas.font.Color := clblue;
  MetafileCanvas.font.Name := 'Gentle air2';
  MetafileCanvas.font.Size := 1000;

  MetafileCanvas.TextOut(0, 0, 'Car handle'); // Letters "C" and "h" are not completely printed

  ReleaseDC(0, DC);


  MetafileCanvas.Free;
  MF.Enhanced := FALSE;

  Bmp := TBitmap.Create;
  BMp.Width := 3400;
  Bmp.Height := 4200;

  ExpectGDIPlusFull;

  Bmp := Gdip.DrawAntiAliased(MF,100,100, smAntiAlias);
  Bmp.SaveToFile('deneme2.bmp');

  bmp.Free;
  MF.Destroy;
end;

I have no deep font handling knowledge.

I appreciate any help.

Thanks & regards.

#103 Re: mORMot 1 » Help needed with TAESECB » 2018-07-01 22:21:32

Hello,

jaclas wrote:

but you must known and pass IV

I do not know much about encryption. Sample link I provided above says ECB mode does not require any IV. I do not know how to use ECB mode in mORMot.

jaclas wrote:

2. You use encoding to Base64, but you expected result in hex?

You are right. It seems result should be converted to hex from bytes. However, my initial problem above still remains.

Thanks.

#104 mORMot 1 » Help needed with TAESECB » 2018-06-16 17:54:57

ertank
Replies: 3

Hello,

There is a Aes-ECB crypt information with sample input values and result. I want to have same result using mORMot, but I could not achieve that. Code I tried is below:

const
  AKey: string  = '783490FD6A6C90F07236A8ED402794F8732C96FB711FA0F46C349AC4792493E8';
var
  Key: TSHA256Digest;
  Aes: TAESECB;
  Utf8String: RawByteString;
begin
  Key := SHA256Digest(Pointer(@AKey), Length(AKey));

  Aes := TAESECB.Create(Key, 256);
  try
    Utf8String := StringToUTF8('000102030405060708090A0B0C0D0E0F');
    try
      Utf8String := BinToBase64(Aes.EncryptPKCS7(Utf8String, False));
    except
      Exit();
    end;
    ShowMessage(string(Utf8String));
  finally
    Aes.Free();
  end;
end;

Result I get is: 'oZSifB86ZMrA0l5sYpUyCj85t2klIRSDqcwEnyx+wHVugxvzP3U9+BtDD+eqx+pu'
Result I expected is: 'E6861877DB7B021E8B755F927243ED7B'

Online crypt link for same data: http://extranet.cryptomathic.com/aescal … 927243ED7B

I so far only used TAESCFB with mORMot with the help of this forum. I do not have experience about cryptography. I could not fix my code.

I appreciate any help.

#105 Re: GDI+ » PNG Transparency » 2018-06-11 15:47:23

Hello,

I also need to add a transparency and set its color for PNG image. I chacked TPngImage class in the framework, but I only see Transparent property available.
It is possible I overlooked at something and would like to ask in here.
Is there any change in framework to include such a feature?

Thanks.

#106 Re: mORMot 1 » RecordSaveJSON() returning simple "{}" as result » 2018-05-15 09:53:38

Turning on Range check showed me the problem. Nasty out of range writing in a dynamic record variable. That probably leads to memory corruption and my luck it hit SynCommons functions memory area.

Sorry for the noise.

#107 mORMot 1 » RecordSaveJSON() returning simple "{}" as result » 2018-05-15 08:26:55

ertank
Replies: 2

Hello,

In the project I am working on, if I try to serialize below record it simply returns "{}" for my *second* call of it.

  TPromotion = packed record
    &type: Byte;
    amount: Integer;
    ticketMsg: string;
  end;

  TStItem = packed record
    &type: Byte;
    subType: Byte;
    deptIndex: Byte;
    unitType: Byte;
    amount: UInt32;
    currency: UInt16;
    count: UInt32;
    flag: UInt32;
    countPrecition: Byte;
    pluPriceIndex: Byte;
    name: string;
    barcode: string;
    firm: string;
    invoiceNo: string;
    subscriberId: string;
    tckno: string;
    Reserved: UInt32;
    Date: string;
    promotion: TPromotion;
    OnlineInvoiceItemExceptionCode: UInt16;
  end;

There is no TTextWriter custom format defined or any specific options for serialization/de-serialization. They are all defaults.
There is a procedure variable (not a form wide or project wide) used to hold record information. I change some values in it and serialize.
When I debug run, I see that record is fine. Contains information.
If I am to test it in a new project to see if I can reproduce the problem, I see that it works every and each time I call the function. So, I have something in my formal project that cause second call to return empty json.

My question is: Are there any possible case(s) that results to receive "{}" to a call to RecordSaveJSON() function?

Thanks & regards,
Ertan


P.S. I just realize that this is not just that record I am having problem. After first pass, any record serialization attempt either returns a simple "{}" as a result or I get an access violation at address 00000004.

#108 Re: mORMot 1 » How to generate same json as C# does » 2018-05-15 08:10:42

I did not know about that option.
These json's are sent and received. It is not just one way.

My case, there is a kind of bug on the fiscal device. Normally it should not include any fields. Those added fields belong to old version of the fiscal device. Company just overlooked it because they do not have any problem with their json library communicating with the device.

Thanks for the info.

#109 Re: mORMot 1 » How to generate same json as C# does » 2018-05-15 04:28:07

I did progress on my work. Now I have just discovered following situation.

C# project has a structure (example below is simplified):

    public class ST_TICKET
    {
        public UInt32 TransactionFlags;
        public UInt32 OptionFlags;
        public UInt16 ZNo;
        public UInt16 FNo;
        public UInt16 EJNo;
        public string szTicketDate;
        public string szTicketTime;

        public ST_TICKET()
        {
            szTicketDate = "";
            szTicketTime = "";
        }
    };

This is serialized and sent to a fiscal device. Then device process and send back information in following json format:

{  
   "TransactionFlags":131074,
   "OptionFlags":7,
   "ZNo":66,
   "FNo":16,
   "EJNo":1,
   "bcdTicketDate":"EAAA",
   "bcdTicketTime":"AFAA",
   "szTicketDate":"180515",
   "szTicketTime":"065643"
}

It is clear that fiscal device included some *additional* fields in returned json. Apparently, json library that is used in C# (Newtonsoft.Json.dll) does not have any problem processing that json with additional fields and it is simply omitting missing fields. As to my checks, there are at least two different places that such a situation happens. Some of them are several structures deep (some structures include several levels of other structures in it).

My question is: Is it possible to tell mORMot omit some missing fields and only process the ones that are present?

I really would like to avoid to prepare copies of record definitions one for sending and another one for receiving.

Thanks & regards,
Ertan

#110 Re: mORMot 1 » How to generate same json as C# does » 2018-05-09 09:20:03

igors233 wrote:

It seems that C# treats everything as Variant, so empty string is null and empty array is null.
Do you need to load that json generated to your records or just create one?
Few ideas:
a) Reformat your Delphi generated json (use StringReplace) so that [] becomes null.
b) Change declaration of your record to use Variant insted of array of Byte and work with it as Variant.
c) Use TDocVariantData instead of records, but then you would also have to treat everything as Variant.

igors233, it seems Variant is the way to go in my case. I need to de-serialize replies from device. Need more testing though.

Thanks.

#111 Re: mORMot 1 » How to generate same json as C# does » 2018-05-09 09:18:59

ab wrote:

BTW I wonder the reasons why you switch to Delphi, and have some feedback about what should be implemented.

Actually, C# is a simulator application showing how to manipulate DLL file company provides. Everybody develop its own application and I know Object Pascal way better than C# myself.

#112 mORMot 1 » How to generate same json as C# does » 2018-05-08 22:33:04

ertank
Replies: 9

Hello,

I tried to find as small examples as possible to keep my post short.

I am working on converting a C#.NET project into Delphi. C# project by default uses structures and Newtonsoft.Json DLLs for json serialization/deserialization.
Example C# structure:

    public class _ST_PAYMENT_REQUEST_ORGINAL_DATA
    {
        public UInt32 TransactionAmount;
        public UInt32 LoyaltyAmount;
        public UInt16 NumberOfinstallments;
        public byte[] AuthorizationCode;
        public byte[] rrn;
        public byte[] TransactionDate;
        public byte[] MerchantId;
        public byte TransactionType;
        public byte[] referenceCodeOfTransaction;
    };

C# json generated for this structure:

{  
      "TransactionAmount":0,
      "LoyaltyAmount":0,
      "NumberOfinstallments":0,
      "AuthorizationCode":null,
      "rrn":null,
      "TransactionDate":null,
      "MerchantId":null,
      "TransactionType":0,
      "referenceCodeOfTransaction":null
   }

Delphi record definition for same structure:

  TStPaymentRequestOrginalData = packed record
    TransactionAmount: UInt32;
    LoyaltyAmount: UInt32;
    NumberOfinstallments: UInt16;
    AuthorizationCode: Array of Byte;
    rrn: Array of Byte;
    TransactionDate: Array of Byte;
    MerchantId: Array of Byte;
    TransactionType: Byte;
    referenceCodeOfTransaction: Array of Byte;
  end;

mORMot json for Delphi record:

{  
      "TransactionAmount":0,
      "LoyaltyAmount":0,
      "NumberOfinstallments":0,
      "AuthorizationCode":[],
      "rrn":[],
      "TransactionDate":[],
      "MerchantId":[],
      "TransactionType":0,
      "referenceCodeOfTransaction":[]
   }

These json texts are for communicating with a device and I have to produce same json as C# project. I am having different representation for byte array variables in my mORMot generated json. Moreover, I also have examples that C# project serialize some string variables as "null" (without quotes as in above C# json example) because they are empty (which I suppose is not correct).

My question is: Is there any way other than manually trying to parse and replace mORMot generated json to be identical with C# generated one? I know about "TTextWriter.RegisterCustomJSONSerializerFromText()" but I do not know what to pass as parameter for having null serialization or even if that is possible.

Since there are lots of different structures, I really do not want to do something manual.

I appreciate any help.

Thanks & regards,
Ertan

#113 Re: mORMot 1 » How to write record for that json? » 2018-01-10 20:07:37

So, I should write a record including everything in this json returning in below link is what I understand.

https://poloniex.com/public?command=returnTicker

#114 mORMot 1 » How to write record for that json? » 2018-01-10 18:40:09

ertank
Replies: 3

Hello,

I have following json (cut to make it shorter):

{
	"BTC_BCN": {
		"id": 7,
		"last": "0.00000074",
		"lowestAsk": "0.00000075",
		"highestBid": "0.00000074",
		"percentChange": "-0.19565217",
		"baseVolume": "501.50839619",
		"quoteVolume": "628594122.91910744",
		"isFrozen": "0",
		"high24hr": "0.00000092",
		"low24hr": "0.00000070"
	},
	"BTC_BELA": {
		"id": 8,
		"last": "0.00003080",
		"lowestAsk": "0.00003123",
		"highestBid": "0.00003061",
		"percentChange": "-0.00996464",
		"baseVolume": "30.82899899",
		"quoteVolume": "986053.00991061",
		"isFrozen": "0",
		"high24hr": "0.00003287",
		"low24hr": "0.00002887"
	},
	"BTC_BLK": {
		"id": 10,
		"last": "0.00005982",
		"lowestAsk": "0.00005982",
		"highestBid": "0.00005951",
		"percentChange": "-0.04654128",
		"baseVolume": "37.08548659",
		"quoteVolume": "629307.51359707",
		"isFrozen": "0",
		"high24hr": "0.00006476",
		"low24hr": "0.00005539"
	}
}

I simply could not figure how I should be writing it's record(s). So far, I only put detail record and for master I simply stuck.

  Detail = packed record
    id: Integer;
    last: string;
    lowestAsk: string;
    highestBid: string;
    percentChange: string;
    baseVolume: string;
    quoteVolume: string;
    isFrozen: string;
    high24hr: string;
    low24hr: string;
  end;

  Main = packed record

  end;

Any help is appreciated.

Thanks
-Ertan

#115 Re: mORMot 1 » Proper code to run service application » 2017-12-26 10:15:32

When I try suggested code, result is same. Application exit immediately. Probably this is some kind of a bug in TCustomApplication class. I will see if Lazarus forum will be of any help.

Thanks.

#116 Re: mORMot 1 » Proper code to run service application » 2017-12-25 20:59:59

It is a TCustomApplication class. I believe I copy paste it long time ago from some demo application.

  TMyInterfaceServer = class(TCustomApplication)
  protected
    procedure DoRun; override;
  private
    LogDir: string;
    procedure RunServer();
  public
    constructor Create(TheOwner: TComponent); override;
    destructor Destroy; override;
    procedure WriteHelp; virtual;
  end;

Sorry about long code paste. I shall find a working pastebin alternative. It cannot be reached as I have governmental internet ban for some web sites.

#117 mORMot 1 » Proper code to run service application » 2017-12-24 18:21:08

ertank
Replies: 5

Hello,

I am using Lazarus 1.8.1 (1.8 fixes branch), fpc 3.1.1 (trunk) on a Raspberry Pi 3 device running Raspbian Stretch. mORMot commit version is 1.18.3688

I am basically a Windows programmer and I know no technical details as to linux daemons. I recently completed my interface based service on Raspberry Pi 3 device. I have following code in my LPR file:

var
  Application: TMyInterfaceServer;
begin
  Application := TMyInterfaceServer.Create(nil);
  Application.Run();
  Application.RunServer();
  while not Application.Terminated do Sleep(1000);
  Application.Free();
end.

Above code results in instant shutdown of the application as if it is terminated. Relevant log lines are:

/home/pi/interfaceserver 0.0.0.0 (2017-12-24 20:48:11)
Host=raspberrypi User=root CPU=0 OS=Linux-4.9.59-v7+#1047-SMP-Sun-Oct-29-12:19:23-GMT-2017 Wow64=0 Freq=1000000000
TSynLog 1.18.3688 FTS3 2017-12-24T17:50:06

20171224 17500617  +    mORMotHttpServer.TSQLHttpServer(76A45380).Create useBidirSocket (secNone) on port 8888
20171224 17500617  -    00.000.172
20171224 17500618 http  mORMotHttpServer.TSQLHttpServer(76A45380) {"TWebSocketServerRest(76A645C0)":{"ServerConnectionCount":0,"ServerKeepAliveTimeOut":3000,"TCPPrefix":"","ThreadPool":{"TSynThreadPoolTHttpServer(76CACB60)":{"HeaderErrors":0,"HeaderProcessed":0,"BodyProcessed":0,"BodyOwnThreads":0,"RunningThreads":2}},"ThreadPoolContentionCount":0,"ThreadPoolContentionAbortCount":0,"APIVersion":"Synopse CrossPlatform Socket Layer.514","ServerName":"mORMot (Linux)","ProcessName":"root "}} initialized for root
20171224 17500618 info  SetThreadName 75F53470=TSQLHttpServer 8888/root TWebSocketServerRest
20171224 17500618 trace mORMot.TSQLRestServerFullMemory(76A34D40) BeginCurrentThread(TWebSocketServerRest) root=root ThreadID=75F53470 ThreadCount=1
20171224 17500618  +    mORMotHttpServer.TSQLHttpServer(76A45380).
20171224 17500618  -    00.000.124
20171224 17500618 http  mORMotHttpServer.TSQLHttpServer(76A45380) {"TWebSocketServerRest(76A645C0)":{"ServerConnectionCount":0,"ServerKeepAliveTimeOut":3000,"TCPPrefix":"","ThreadPool":{"TSynThreadPoolTHttpServer(76CACB60)":{"HeaderErrors":0,"HeaderProcessed":0,"BodyProcessed":0,"BodyOwnThreads":0,"RunningThreads":2}},"ThreadPoolContentionCount":0,"ThreadPoolContentionAbortCount":0,"APIVersion":"Synopse CrossPlatform Socket Layer.514","ServerName":"mORMot (Linux)","ProcessName":"root "}} finalized for 1 server
20171224 17500618  +    mORMotHttpServer.TSQLHttpServer(76A45380).Shutdown(true)
20171224 17500618  -    00.000.078
20171224 17500650 trace mORMot.TSQLRestServerFullMemory(76A34D40) EndCurrentThread(TWebSocketServerRest) ThreadID=75F53470 ThreadCount=0
20171224 17500650  +    mORMot.TSQLRestServerFullMemory(76A34D40).Shutdown CurrentRequestCount=0 File=
20171224 17500650  -    00.005.133
20171224 17500650 info  mORMot.TSQLRestStorageInMemory(76904020) TSQLRestStorageInMemory.Destroy
20171224 17500650 info  mORMot.TSQLRestStorageInMemory(769040F0) TSQLRestStorageInMemory.Destroy
20171224 17500650 info  mORMot.TSQLRestServerFullMemory(76A34D40) TSQLRestServerFullMemory.Destroy

However, below code keeps the application running:

var
  Application: TMyInterfaceServer;
begin
  Application := TMyInterfaceServer.Create(nil);
  Application.Run();
  Application.RunServer();
  while True do Sleep(1000);  // modified line
  Application.Free;
end.

I am not sure if this should be the way I should keep the application running. I think second code results in a memory leak or something. I cannot be sure because of my lack of linux knowledge.

All suggestions are welcome.

Thanks & regards,
Ertan

#118 Re: mORMot 1 » Decrypt results differ for Win32 and Win64 (Delphi 10.2) » 2017-12-18 05:53:09

I actually checked it and it returns 48 and not the size of the pointer. That is same for 32bit and 64bit.

My usage is very similar to below code:

const
  Test: Array of Byte = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

procedure TestMe(const Key: array of Byte);
begin
  ShowMessage('TestMe: ' + IntToStr(SizeOf(Key)));  // Here you get 10
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ShowMessage(IntToStr(SizeOf(Test)));  // Here you get 4
  TestMe(Test);
end;

#119 Re: mORMot 1 » Decrypt results differ for Win32 and Win64 (Delphi 10.2) » 2017-12-17 19:17:08

Yes, it is my mistake. Sorry for all the fuss.

Below is the current code which is working in both 32bit and 64bit platforms. Encrypt text in one platform can be decrypt in another platform just fine.

unit Unit1;

interface

uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Variants,
  System.Classes,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs,
  Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    Edit1: TEdit;
    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

const
    KeyPC :   Array of Byte =  [00,  101, 02,  03,  40,  05,  106, 07,
                                08,  09,  07,  100, 110, 201, 117, 45,
                                10,  11,  12,  13,  140, 150, 160, 170,
                                13,  1,   17,  130, 40,  16,  106, 70,
                                180, 190, 174, 200, 0,   1,   11,  15,
                                80,  91,  72,  130, 101, 111, 107, 45];
var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  SynCommons,
  SynCrypto;


function DecryptItAES(const s: string; AKey: Array of Byte; out Value: string): Boolean;
var
  Key: TSHA256Digest;
  Aes: TAESCFB;
  Utf8Str: RawByteString;
begin
  if s = EmptyStr then Exit(False);

  Key := SHA256Digest(Pointer(@AKey), SizeOf(AKey));

  Aes := TAESCFB.Create(Key, 256);
  try
    Utf8Str := StringToUTF8(s);

    try
      Utf8Str := Aes.DecryptPKCS7(Base64ToBin(Utf8Str), True);
    except
      Value  := EmptyStr;
      Exit(False);
    end;

    Value := UTF8ToString(Utf8Str);
  finally
    Aes.Free();
  end;

  Result := True;
end;

function EncryptItAES(const s: string; aKey: Array of Byte; out Value: string): Boolean;
var
  Key: TSHA256Digest;
  Aes: TAESCFB;
  Utf8Str: RawByteString;
begin
  if s = EmptyStr then Exit(False);

  Key := SHA256Digest(Pointer(@AKey), SizeOf(AKey));

  Aes := TAESCFB.Create(Key, 256);
  try
    Utf8Str := StringToUTF8(s);
    try
      Utf8Str := BinToBase64(Aes.EncryptPKCS7(Utf8Str, True));
    except
      Exit(False);
    end;
    Value := UTF8ToString(Utf8Str);
  finally
    Aes.Free();
  end;

  Result := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  TempString: string;
begin
  EncryptItAES(Edit1.Text, KeyPC, TempString);
  Memo1.Lines.Add(EmptyStr);
  Memo1.Lines.Add(TempString);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  TempString: string;
begin
  TempString := EmptyStr;
  DecryptItAES(Edit1.Text, KeyPC, TempString);
  Memo1.Lines.Add('Plain: ' + QuotedStr(TempString));
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Memo1.Lines.Clear();
end;

end.

@zed appreciate you pointing me my bug.
@ab appreciate you correct my basic definition type for KeyPC

That is a good lesson learned for me as I now need to update quite some applications running in different locations.

Regards,
Ertan

#120 Re: mORMot 1 » Decrypt results differ for Win32 and Win64 (Delphi 10.2) » 2017-12-17 11:28:19

I just tested same code on Delphi 10.2.2
I got exception on 64bit executable where I have correct result on 32bit executable.
I also got exception encrypt text on 64bit system and trying to decrypt it in 32bit system.

If I encrypt using 64bit executable, it can decrypt that information on 64bit system.
If I encrypt using 32bit executable, it can decrypt that information on 32bit system.

It seems encrypt information is not 32bit <-> 64bit exchangeable. At least on Windows platforms.

Encryption code I used is:

function EncryptItAES(const s, aKey: string; out Value: string): Boolean;
var
  Key: TSHA256Digest;
  Aes: TAESCFB;
  Utf8String: RawByteString;
begin
  if s = EmptyStr then Exit(False);

  //SynCommons.HexToBin(Pointer(SHA256(StringToUTF8(aKey))), @key, 32);
  Key := SHA256Digest(StringToUTF8(AKey));

  Aes := TAESCFB.Create(key, 256);
  try
    Utf8String := StringToUTF8(s);
    try
      Utf8String := BinToBase64(Aes.EncryptPKCS7(Utf8String, True));
    except
      Exit(False);
    end;
    Value := UTF8ToString(Utf8String);
  finally
    Aes.Free();
  end;

  Result := True;
end;

#121 Re: mORMot 1 » Decrypt results differ for Win32 and Win64 (Delphi 10.2) » 2017-12-16 20:11:04

I am using plain Delphi 10.2 with April hotfix applied.

Thanks for additional regression tests.

I am not sure it is the test code having something wrong. I am not changing any code but target platform. Win32 it works and Win64 it does not.
I will wait for a while with the hope that someone in the forum who has Delphi 10.2 (plain or update 1, 2) to test above code example just to be sure.
Both update 1 and update 2 has their own issues and I simply do not want to install neither at the moment.

I might prepare a virtual machine to test with update 1 or update 2 if I can find the time to test the code.

#122 Re: mORMot 1 » Decrypt results differ for Win32 and Win64 (Delphi 10.2) » 2017-12-16 09:37:26

I tested with Revision 1.18.4080. Same problem continues. Working fine with 32Bit executable. Different decrypt result for 64bit executable using same code and inputs. Please check if you can reproduce using below information.

Delphi version: Embarcadero® RAD Studio 10.2 Version 25.0.26309.314
Decrypt text should be small letter "a"

const
    KeyPC :   Array of Char =  [#00,  #101, #02,  #03,  #40,  #05,  #106, #07,
                                #08,  #09,  #07,  #100, #110, #201, #117, #45,
                                #10,  #11,  #12,  #13,  #140, #150, #160, #170,
                                #13,  #1,   #17,  #130, #40,  #16,  #106, #70,
                                #180, #190, #174, #200, #0,   #1,   #11,  #15,
                                #80,  #91,  #72,  #130, #101, #111, #107, #45];

implementation

uses
  SynCommons,
  SynCrypto;

function DecryptItAES(const s, AKey: string; out Value: string): Boolean;
var
  Key: TSHA256Digest;
  Aes: TAESCFB;
  Utf8String: RawByteString;
begin
  if s = EmptyStr then Exit(False);

  //SynCommons.HexToBin(Pointer(SHA256(StringToUTF8(aKey))), @key, 32);
  Key := SHA256Digest(StringToUTF8(AKey));

  Aes := TAESCFB.Create(Key, 256);
  try
    Utf8String := StringToUTF8(s);

    try
      Utf8String := Aes.DecryptPKCS7(Base64ToBin(Utf8String), True);
    except
      on E: Exception do
      begin
        ShowMessage(E.Message);
        Value  := EmptyStr;
        Exit(False);
      end;
    end;

    Value := UTF8ToString(Utf8String);
  finally
    Aes.Free();
  end;

  Result := True;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  DecryptItAES('oWN2TRhEkb4sJ8IrfqQSm+9qhW5u+xty7qbigw9yk4A=', string(KeyPC), PlainText);
  Memo1.Lines.Add('Plain: ' + QuotedStr(PlainText));
end;

BTW, I cannot debug 64bit applications. Couldn't find what problem is with debugging 64bit executable. Execution do not stop at break points even I have compiler and linker debugging information set on.

However, when I try to display exception on the screen I see that there is indeed an exception raised and it is saying:

TAESCFB.DecryptPKCS7: Invalid Input

No such exception in 32bit executable and result is displayed just fine.

#123 Re: mORMot 1 » Decrypt results differ for Win32 and Win64 (Delphi 10.2) » 2017-12-12 18:57:31

Just tried with 1.18.4071 revision.

That revision raise an exception saying "TAESCFB.DecryptPKCS7: Invalid Input" when Win64 executable.
Using same revision and Win32 executable everything works fine.

#124 mORMot 1 » Decrypt results differ for Win32 and Win64 (Delphi 10.2) » 2017-12-12 16:52:50

ertank
Replies: 13

Hello,

I am using Delphi 10.2, mORMot commit version 1.18.3599

I do not know if this is something known.

I have switched my target platform to 64bit Windows for one of my applications. There is no code change at all. That 64bit application could not decrypt information crypt with Win32 executable using same mORMot version. Everything is normal if I switch back to Win32 platform.

My code for decrypt is as follows:

function DecryptItAES(const s: string; const AKey: string): string;
var
  Key: TSHA256Digest;
  Aes: TAESCFB;
  _s: RawByteString;
begin
  Result := EmptyStr;
  SynCommons.HexToBin(Pointer(SHA256(StringToUTF8(AKey))), @Key, 32);

  Aes := TAESCFB.Create(Key, 256);
  try
    _s     := StringToUTF8(s);
    _s     := Aes.DecryptPKCS7(Base64ToBin(_s), True);
    Result := UTF8ToString(_s);
  finally
    Aes.Free();
  end;
end;

There is no exception raising at all. It is simply decrypt content is not that it should be.

I appreciate any help.

Thanks & regards,
Ertan

#125 Re: Low level and performance » LZO and SynLZ compression units » 2017-11-04 21:16:41

Hello,

I highly doubt, but it is better to ask. Is it somehow possible to use FileSynLz() compress multiple files like TZipWrite does?

If not, is it possible to use TZipWrite only as a container? In other words, can I have TZipWrite to create a zip file having several FileSynLz() created files without trying to compress them again.

Thanks.

#126 Re: mORMot 1 » Proper way to use Delphi 10.2 DLL in a Delphi 7 application (json) » 2017-09-14 21:13:08

Hello ab,

Thank you for the tip.

I could not get much help from documentation. I found some information in section "10.1.3.2 Serialization for older Delphi versions". However, your blog post in below link was in detail and helped me a lot.
http://blog.synopse.info/post/2013/12/1 … ialization

My current code is as follows. All is working just fine at the moment. As I had national language issues, I converted all string variables to RawUTF8.

unit uDefines;

interface

uses
  SynCommons;

const
  RESPONSE_OK = 0;
  SOAP_ERROR = 1;
  SOAP_ERROR_CREATE = 2;
  SOAP_ERROR_ADD_RECORD = 3;
  JSON_EMPTY = 4;
  JSON_BAD_FORMAT1 = 5;
  JSON_BAD_FORMAT2 = 6;
  JSON_ERROR = 7;

var
  __OlcumBilgileriInput: string;
  __OlcumBilgileriSonuc: string;

type
  TOlcumBilgileriInput = packed record
    kantarNo: RawUTF8;
    turu: RawUTF8;
    tartimTarihi: TDateTime;
    tartimSaati: RawUTF8;
    dbaBelgeNo: RawUTF8;
    operatorNo: RawUTF8;
    konteynerNo: RawUTF8;
    konteynerPayLoad: Double;
    operatorTcNo: RawUTF8;
    operatorAdSoyad: RawUTF8;
    olcumSonucu: Double;
    arac1Plaka: RawUTF8;
    arac1BosAgirlik: Double;
    arac2Plaka: RawUTF8;
    arac2BosAgirlik: Double;
    konteynerDara: Double;
    yukletenVergiNo: RawUTF8;
    yukletenUnvan: RawUTF8;
    gidecegiLimanId: Double;
  end;

  TOlcumBilgileriSonuc = packed record
    sonucKodu: Integer;
    sonucMesaji: RawUTF8;
    udhbOlcumSonucId: Int64;
  end;

implementation


initialization
  __OlcumBilgileriInput := 'kantarNo RawUTF8 turu RawUTF8 tartimTarihi TDateTime tartimSaati RawUTF8 dbaBelgeNo RawUTF8 operatorNo RawUTF8 konteynerNo RawUTF8 konteynerPayLoad Double operatorTcNo RawUTF8 operatorAdSoyad RawUTF8 ' +
                           'olcumSonucu Double arac1Plaka RawUTF8 arac1BosAgirlik Double arac2Plaka RawUTF8 arac2BosAgirlik Double konteynerDara Double yukletenVergiNo RawUTF8 yukletenUnvan RawUTF8 gidecegiLimanId Double';
  __OlcumBilgileriSonuc := 'sonucKodu Integer sonucMesaji RawUTF8 udhbOlcumSonucId Int64';

  TTextWriter.RegisterCustomJSONSerializerFromText(TypeInfo(TOlcumBilgileriInput), __OlcumBilgileriInput);
  TTextWriter.RegisterCustomJSONSerializerFromText(TypeInfo(TOlcumBilgileriSonuc), __OlcumBilgileriSonuc);
end.

#127 Re: mORMot 1 » Proper way to use Delphi 10.2 DLL in a Delphi 7 application (json) » 2017-09-14 19:44:18

***Correction***

I just learned that problem exists in Delphi 7 before calling DLL function. Delphi 7 is to prepare Json string and send it as a constant WideString to DLL function. What is prepared using RecordSaveJSON() seems to be non-readable text. Details as below:

Record definitions:

  TOlcumBilgileriInput = packed record
    kantarNo: string;
    turu: string;
    tartimTarihi: TDateTime;
    tartimSaati: string;
    dbaBelgeNo: string;
    operatorNo: string;
    konteynerNo: string;
    konteynerPayLoad: Double;
    operatorTcNo: string;
    operatorAdSoyad: string;
    olcumSonucu: Double;
    arac1Plaka: string;
    arac1BosAgirlik: Double;
    arac2Plaka: string;
    arac2BosAgirlik: Double;
    konteynerDara: Double;
    yukletenVergiNo: string;
    yukletenUnvan: string;
    gidecegiLimanId: Double;
  end;

Code calling RecordSaveJSON():

var
  OBI: TOlcumBilgileriInput;
  Json: RawUTF8;
begin
  OBI.kantarNo          := '1031';
  OBI.turu              := 'YON1';
  OBI.tartimTarihi      := EncodeDate(2017, 1, 1);
  OBI.tartimSaati       := FormatDateTime('hh:nn', EncodeTime(11, 24, 0, 0));
  OBI.dbaBelgeNo        := 'BKN.656178.Y-1.41.9';
  OBI.operatorNo        := EmptyStr;
  OBI.konteynerNo       := '123456';
  OBI.konteynerPayLoad  := 123456;
  OBI.operatorTcNo      := '23851792108';
  OBI.operatorAdSoyad   := 'TEST PERSON';
  OBI.olcumSonucu       := 321;
  OBI.arac1Plaka        := '41VV524';
  OBI.arac1BosAgirlik   := 121;
  OBI.arac2Plaka        := EmptyStr;
  OBI.arac2BosAgirlik   := 0;
  OBI.konteynerDara     := 12;
  OBI.yukletenVergiNo   := '1030050950';
  OBI.yukletenUnvan     := 'SOME COMPANY NAME HERE';
  OBI.gidecegiLimanId   := 715525;

  Json := RecordSaveJSON(OBI, TypeInfo(TOlcumBilgileriInput));

At this point variable Json having below value:

"ï¿°BDEwMzEEWU9OMQAAAAAA3uRABTExOjI0E0JLTi42NTYxNzguWS0xLjQxLjkABjEyMzQ1NgAAAAAAJP5ACzIzODUxNzkyMTA4DkVSRE/QQU4g1lpLQVlBAAAAAAAQdEAHNDFWVjUyNAAAAAAAQF5AAAAAAAAAAAAAAAAAAAAAKEAKMTAzMDA1MDk1MDtFVllBUCBERU7dWiDd3kxFVE1FQ91M3dDdIExPSt1TVN1LIFZFIN1O3kFBVCBBTk9O3U0g3t1SS0VU3QAAAAAK1iVB"

Seems like Base64 converted text.

#128 mORMot 1 » Proper way to use Delphi 10.2 DLL in a Delphi 7 application (json) » 2017-09-14 18:39:27

ertank
Replies: 3

Hello,

I always used mORMot with recent Delphi versions and had no problems until today. Now, I am in a project where I need to use (my side) Delphi 10.2 to build a DLL for SOAP Web Service consuming. That DLL functions are allocating WideString to put json inside and returning these WideStrings to (other party) Delphi 7 application to use.

We are proceeding method by method. Our first methods we did not use any json on Delphi 7 side. They were only WideString information going back and forth. We now reached our first method to utilize json usage and I realize that mORMot needs a slightly modified FastMM for Delphi 7. Other party put all necessary files in place. First line of the project dpr file is modified to use "FastMM4". Project compiles fine.

When they we call json string returning DLL function, it is all garbage text received as a reply.

I have no experience using mORMot with Delphi 7 and asking for help in here.

Is there anything we should be doing in order to make above explained scenario to work?

Thanks & regards,

Ertan

#129 Re: mORMot 1 » RecordLoadJSON() returns false » 2017-08-23 08:26:41

Hello igors233, Thank you. That must be it that I could not see at late night hours. Appreciated.

#130 mORMot 1 » RecordLoadJSON() returns false » 2017-08-22 22:45:57

ertank
Replies: 2

Hello,

Using Delphi 10.2. Target is Win32 executable.
mORMot commit version is 1.18.3599

I have following definitions:

type
  TItem = packed record
    FNo: string;
    FDescription: string;
    FUoM: string;
    FPrice: Double;
    FStock: Double;
  end;
  TItems = TArray<TItem>;

I am receiving below json string from a webservice:

[{"FNo":"LSU-8","FDescription":"8\"100W mellemtone i højttaler","FUoM":"STK","FPrice":21,"FStock":15}]

My code for RecordLoadJSON is as follows:

var
  AItems: TItems;
  Json: WideString;
  AJson: string;
begin
  Response := GetItem(Json, Error);
  if Response <> RESPONSE_OK then
  begin
    ShowMessage('Soap error: ' + Error);
    Exit();
  end;

  AJson := Json;  // Convert WideString to string as I am not able to find where the error is

  if not RecordLoadJSON(AItems, RawUTF8(AJson), TypeInfo(TItems)) then
  begin
    ShowMessage('Json error: Cannot decode json into record. Json string will be printed in Memo');
    Memo1.Lines.Text := AJson;
    Exit();
  end;
end;

Above code always gives me "Cannot decode json..." error displayed for provided json string.

It is very late and I maybe missing something obvious. Just wanted some different eyes to check it out.

I appreciate any help.

Thanks.

-Ertan

#131 Re: mORMot 1 » EServiceException: TInterfaceFactory.GUID2TypeInfo » 2017-07-26 18:41:17

I found below link in documents however, I cannot fully and clearly understand what I need to do with Delphi, how I supposed to use it with fpc.
https://synopse.info/files/html/Synopse … #TITLE_669

I also appreciate a link for NewPascal fork.

#132 mORMot 1 » EServiceException: TInterfaceFactory.GUID2TypeInfo » 2017-07-26 09:00:46

ertank
Replies: 2

Hello,

Tried to make a test of stock sample no "14 - Interface based services" on a Linux debian 3.16.0-4-amd64 #1 SMP Debian 3.16.43-2+deb8u2 (2017-06-26) x86_64 GNU/Linux

Using mORMot commit version 1.18.3688, fpc/trunk and Lazarus 1.8.0RC3.

Project compiled OK. When I run I get below output. Using root account also produces same output.

20170726 08562000  +    mORMot.TSQLRestServerFullMemory(00007F305C4CCB70).Shutdown CurrentRequestCount=0 File=
20170726 08562000  -    00.005.256
20170726 08562000 info  mORMot.TSQLRestStorageInMemory(00007F305B8724C0) TSQLRestStorageInMemory.Destroy
20170726 08562000 info  mORMot.TSQLRestStorageInMemory(00007F305B872640) TSQLRestStorageInMemory.Destroy
20170726 08562000 info  mORMot.TSQLRestServerFullMemory(00007F305C4CCB70) TSQLRestServerFullMemory.Destroy
An unhandled exception occurred at $00000000005AAAB8:
EServiceException: TInterfaceFactory.GUID2TypeInfo({9A60C8ED-CEB2-4E09-87D4-4A16F496E5FE}): Interface not registered - use TInterfaceFactory.RegisterInterfaces()
  $00000000005AAAB8 line 53490 of ../../mORMot.pas
  $00000000005AAA62 line 53483 of ../../mORMot.pas
  $000000000056FE89 line 40995 of ../../mORMot.pas
  $000000000040168B line 49 of Project14ServerHttp.dpr

I did not change source code and when I check source I definitely see type is being registered.

Any help is appreciated.

#134 Re: mORMot 1 » Raspberry Pi - Lazarus 1.8.0RC2 - mORMot » 2017-06-29 12:42:06

As per suggestion I changed to using WebSockets. Used the guide and 3rd party examples (https://synopse.info/files/html/Synopse … l#TITL_150)

Server relevant code:

aHTTPServer := TSQLHttpServer.Create(PORT_NAME, [aServer], '+', useBidirSocket);
aHTTPServer.WebSocketsEnable(aServer, '2141D32ADAD54D9A9DB56000CC9A4A70');

Client relevant code:

Client := TSQLHttpClientWebsockets.Create('192.168.1.101', PORT_NAME, Model);
TSQLHttpClientWebsockets(Client).WebSocketsUpgrade('2141D32ADAD54D9A9DB56000CC9A4A70');

Client (Delphi application on windows) can get results fine. But, I read below line on server (FPC-Lazarus application on Raspberry Pi):

20170629 12380908  +    mORMotHttpServer.TSQLHttpServer(76B21B60).Create useBidirSocket (secNone) on port 8888

My understanding; above line tells me that there is no encryption set. I am a newbie to mORMot so most likely I am doing something wrong here.

Any help is appreciated.

Thanks & regards,
Ertan

#135 Re: mORMot 1 » Raspberry Pi - Lazarus 1.8.0RC2 - mORMot » 2017-06-29 11:41:17

Just to clarify,

Windows is a Delphi 10.2 Tokyo application,
Raspberry Pi is a FPC-Lazarus application

My mistake not indicating this the first time.

#136 Re: mORMot 1 » Raspberry Pi - Lazarus 1.8.0RC2 - mORMot » 2017-06-28 21:35:53

After updating to fpc/trunk I am able to compile and run OK the test server (sample 14).
On the other hand, I have a problem using mORMot with its own communication encryption.

Related server code:

// launch the HTTP server
aHTTPServer := TSQLHttpServer.Create(PORT_NAME, [aServer], '+', useHttpSocket, 32, secSynShaAes);

Related client code:

Client := TSQLHttpClient.Create('192.168.1.101', PORT_NAME, Model);
TSQLHttpClientWinHTTP(Client).Compression := [hcSynShaAes];  // removing this line and everything works

Above code raises following exception for both 32bit & 64bit client EXE:

errorCode: 406
errorText: sicShared execution failed (probably due to bad input parameters) for TestMe.TestString

Raspberry mORMot version: 1.18.3688
Windows mORMot version: 1.18.3599

Sample Windows Delphi 10.2 Tokyo project: mormot-windows-string-test.zip
Sample Raspberry Pi Lazarus project: mormot-pi-string-test.bz2

I am not aware that if there is no support for encryption between different systems. If so, I believe I need to use https with a certificate.

Thanks & regards,
Ertan

#137 Re: mORMot 1 » Raspberry Pi - Lazarus 1.8.0RC2 - mORMot » 2017-06-19 18:50:42

I have another project built on this same Raspberry Pi. I better do not change fpc version at the moment.

This was fpc 3.0.2 built from sources (Mon, 06 Feb 2017). Svn tag: release_3_0_2, svn revision 35401 Definetely not "trunk" though.

Thanks for the feedback. I will try again later, once I can upgrade to fpc trunk.

#138 mORMot 1 » Raspberry Pi - Lazarus 1.8.0RC2 - mORMot » 2017-06-19 17:56:47

ertank
Replies: 8

Hi,

I tested for educational purposes, if Raspberry Pi 3 is capable of building server code. Actually compilation was successful. It was run-time I get following error:

pi@raspberrypi:~/mORMot/SQLite3/Samples/14 - Interface based services $ sudo ./Project14ServerHttp 
20170619 17092057  +    mORMot.TSQLRestServerFullMemory(76B43020).Shutdown CurrentRequestCount=0 File=
20170619 17092058  -    00.005.173
20170619 17092058 info  mORMot.TSQLRestStorageInMemory(76B2B110) TSQLRestStorageInMemory.Destroy
20170619 17092058 info  mORMot.TSQLRestStorageInMemory(76B2B200) TSQLRestStorageInMemory.Destroy
20170619 17092058 info  mORMot.TSQLRestServerFullMemory(76B43020) TSQLRestServerFullMemory.Destroy
An unhandled exception occurred at $001CEBE4:
EServiceException: TInterfaceFactory.GUID2TypeInfo({9A60C8ED-CEB2-4E09-87D4-4A16F496E5FE}): Interface not registered - use TInterfaceFactory.RegisterInterfaces()
  $001CEBE4  TINTERFACEFACTORY__GUID2TYPEINFO,  line 53490 of /home/pi/mORMot/SQLite3/mORMot.pas
  $001CEB94  TINTERFACEFACTORY__GUID2TYPEINFO,  line 53484 of /home/pi/mORMot/SQLite3/mORMot.pas
  $00193908  TSQLRESTSERVER__SERVICEDEFINE,  line 40995 of /home/pi/mORMot/SQLite3/mORMot.pas
  $00010FCC  main,  line 52 of Project14ServerHttp.dpr

Probably it won't be a good server Raspberry Pi anyway. It was nice to test it though.

Raspberry Pi client connecting to Windows Delphi 10.2 build server, I get error:

TInterfaceFactory.GUID2TypeInfo({some guid number}): Interface not registered - use TInterfaceFactory.RegisterInterfaces().

I am not aware if platform is supported or not. It seems to have problems at the moment. mORMot was a nightly build downloaded today.

Regards,
Ertan

#139 mORMot 1 » Understanding client connections » 2017-06-19 16:26:42

ertank
Replies: 1

Hello,

I am a happy user of AES encryption only functions of mORMot for over a year. I have a need to develop a license server using a kind of web service. As mORMot is a web service I started to read about it. It was not easy for me to understand the logic because I am totally and I mean purely a newbie on ORM.

Example "14 - Interface based services" was helpful to my needs. I also checked other examples to have better knowledge. Which helped me to setup encryption on my connection and data transmission. I think I have set it up on my server side OK as I can see below lines when server starts:

20170619 15453031  +    mORMotHttpServer.TSQLHttpServer(0364F200).Create useHttpApiRegisteringURI (secSynShaAes) on port 8888

However, I am not sure if my client setup is OK. I cannot understand from client connection logs if they are encrypt or not. I do not wish to install Wireshark as I am not comfortable using it (I have tried it earlier this year and could not use right).

Is it possible to know somehow if connection is encrypt or not?

My test server related code:

aHTTPServer := TSQLHttpServer.Create(PORT_NAME, [aServer], '+', useHttpApiRegisteringURI, 32, secSynShaAes);

My test client related code:

Client := TSQLHttpClient.Create('localhost', PORT_NAME, Model);
TSQLHttpClientWinHTTP(Client).Compression := [hcSynShaAes];

Thanks & regards,

Ertan

#140 mORMot 1 » Is it possible to parse PostgreSQL arrays? » 2017-04-19 15:21:44

ertank
Replies: 1

Hi,

PostgreSQL has ability to use arrays in a field. They are something like below

{A,B,C,E}	
{F,G,H,I}	
{Ş,Ğ,İ,Ö}	
{some,text}
{more,text}
{"a test text"}

I am searching for a parser for such array values I get from database. I wonder if there is a way to parse them using mORMot framework. I might be OK to use some record definitions if I need to.

Thanks & regards,
-Ertan

#141 Re: mORMot 1 » Json de-serialize help needed » 2017-03-07 21:34:12

I found problem and its solution.

THasta record was presented me in an earlier sample json with 2 variables in it. Current real-life json includes 3 variables in it. Once I added 3rd variable in THasta record definition everything started to work again.

Thanks.

#142 mORMot 1 » Json de-serialize help needed » 2017-03-07 15:36:31

ertank
Replies: 2

Hello,

I am provided following json which seems to be a valid json according to an online json validator.
http://pasted.co/5449b77b

I have setup my records as follows and I am not able to de-serialize it as function returns false to me. Could not find and solve what problem is here. I appreciate any help.

 THasta = packed record
   hastaTC: string;
   adSoyad: string;
 end;

 TGebelikBildirim = packed record
   sysTakipNo: string;
   hekimAdSoyad: string;
   kurumAdi: string;
   kangrubu: Smallint;
   islemzamani: string;
   sonadettarihi: string;
   gonderimZamani: string;
 end;
 TGebelikBildirimleri = TArray<TGebelikBildirim>;

 TSonuc = packed record
   hasta: THasta;
   gebelikBildirim: TGebelikBildirimleri;
 end;
 TSonuclar = TArray<TSonuc>;

 TResult = packed record
   durum: Smallint;
   sonuc: TSonuclar;
   mesaj: string;
 end;

Below is the code piece I am using to de-serialize:

procedure TForm1.Button1Click(Sender: TObject);
var
  JsonRecord: TResult;
  JsonString: string;
  i, i2: Integer;
begin
  ClientDataSet1.EmptyDataSet();

  JsonString := memJson.Text;
  if not RecordLoadJSON(JsonRecord, StringToUTF8(JsonString), TypeInfo(TResult)) then
  begin
    ShowMessage('Json de-serialize failed!');
  end
  else
  begin
    // Some database saving code here
  end;
end;

Thanks & regards,
Ertan

#144 Re: mORMot 1 » Help on deserialization of a json » 2016-12-31 19:22:01

igors233 wrote:

It's hard to say like this, can you send example of your json content so I could try it?

Sample Json is in a link in my initial post.

#145 Re: mORMot 1 » Help on deserialization of a json » 2016-12-30 20:18:51

Thanks igors233.

I tried to test this method with my json which has some nested levels. Unfortunately, I could not manage this. Would you give me a sample to display "xlZReportData[0].xZReportCashierDataList[0].iCashierName" as a message?

Thanks.

#146 Re: mORMot 1 » Help on deserialization of a json » 2016-12-30 13:27:35

After spending some hours, I found that documentation is not showing reality. There are just a bit different field names are used in the incoming Json. After adapting name changes in my code everything is fine now.

Thanks.

#147 mORMot 1 » Help on deserialization of a json » 2016-12-30 10:04:25

ertank
Replies: 8

Hello,

I am using 1.18.3101 version of Synopse with Delphi 10.1 Update 2. Target is 32bit EXE.

I am provided a rest web service with following json returning as a reply
http://pasted.co/de92e9db

My types defined for it in Delphi as to service documentation is as follows:
http://pasted.co/051c3880

I try to deserialize using following code. Please note that I am still trying to understand json basics. So, below code might completely be wrong.

procedure TForm1.Button1Click(Sender: TObject);
var
  RequestDetails: TRequest;
  Response: TResponse;
  lRequest: TStringStream;
  JsonString: RawUTF8;
  ResponseJson: string;
begin
  // Request information is filled correctly. Request json is prepared below
  JsonString := RecordSaveJSON(RequestDetails, TypeInfo(TRequest));
  lRequest := TStringStream.Create(UTF8ToString(JsonString), TEncoding.UTF8);
  try
    Screen.Cursor := crHourGlass;
    Memo1.Lines.Add('service link: ' + ServiceURL);
    Memo1.Lines.Add('request time: ' + DateTimeToStr(Now()));
    Memo1.Lines.Add(UTF8ToString(JsonString));
    IdHTTP1.Request.ContentType := 'application/json';
    IdHTTP1.Request.CharSet     := 'utf-8';
    try
      // Get response
      ResponseJson := IdHTTP1.Post(ServiceURL, lRequest);
      Memo1.Lines.Add('incoming: ' + DateTimeToStr(Now()));
      Memo1.Lines.Add(ResponseJson);
      RecordLoadJSON(Response, RawUTF8(ResponseJson), TypeInfo(TResponse));
      Memo1.Lines.Add('Response: ' + BoolToStr(Response.bReturnValue, True));
      Memo1.Lines.Add('Total Receipt(s) in Data: ' + Length(Response.xExtReceipts).ToString()); // Always zero here.
    except
      on E: Exception do
      begin
        ShowMessage('Error on request: ' + sLineBreak + E.Message);
      end;
    end;
  finally
    lRequest.Free();
    Screen.Cursor := crDefault;
  end;
end;

My problem is RecordLoadJson() always returns false and I cannot understand what problem is in my case.

Any help is appreciated.

Thanks & regards,
Ertan

#148 Re: mORMot 1 » JSON parsing problem » 2016-12-01 21:00:11

Very much like to main question, How can I read first set of "rings" in below Json?

{
"name": "OBJECTID",
"FieldName": "",
"Type": "Polygon",
"fields": [
{
"name": "GID",
"alias": "GID",
"type": "FieldTypeInteger"
}
],
"features": [
{
"attributes": {
"GID": 32289
},
"geometry": {
"rings": [
[
[
47.213439779999987,
41.039492069999994
],
[
47.213007080000011,
41.039838900000007
]
]
] 


}
}
}

What I wrote and didn't work is something like:

procedure TForm1.Button1Click(Sender: TObject);
var
  Json: string;
  Value: Variant;
begin
  Json := Memo1.Text;
  Value := _JsonFast(RawUtf8(Json));
  Label1.Caption := Value.rings._(0);
end;

Error I receive is invalid variant operation.

Thanks.

#149 Re: mORMot 1 » JsonSerialization question » 2016-07-12 16:25:11

@sevo, how did you add a dummy string field and *not* have it serialized in the final json string?

#150 Re: mORMot 1 » JsonSerialization question » 2016-07-12 13:58:15

Sorry, I couldn't be on the Internet before.

I am using Delphi 10.

Is there an option to "extend" rtti for Delphi 10? I do not have deep knowledge about rtti, and do not know if there is such an option/parameter etc.

This json, for me, needs to be generated as Integer type like

"u32VAT":0

and if I am to define these record as string variables, I believe json generated will be like

"u32VAT":"0"

As I am exchanging information with another software, this will be a problem for me. I already used "TTextWriter.RegisterCustomJSONSerializerFromText()" function in my application. However, it was a direct use. I mean, record variable was defined in my record itself. My TStTicket record has sub records in it. What I need to "tweak" is one of these sub types. I am not sure if I can still use that function (before and after exchanging json string) and make it work for my specific case.

Lastly, for me to have a better understanding, I have other UInt16 record variables used at the beginning ot TStTicket record

TStTicket = packed record
    TransactionFlags: UInt32;
    OptionFlags: UInt32;
    ZNo: UInt16;
    FNo: UInt16;
    EJNo: UInt16;

These seems to be fine when json serialized. Is it Integer type that is causing a problem for me?

Thanks.

Board footer

Powered by FluxBB