#151 mORMot 1 » JsonSerialization question » 2016-07-11 17:43:27

ertank
Replies: 11

Hi,

I have below record definitions.

  TStTicket = packed record
    TransactionFlags: UInt32;
    OptionFlags: UInt32;
    ZNo: UInt16;
    FNo: UInt16;
    EJNo: UInt16;
    TotalReceiptAmount: UInt32;
    TotalReceiptTax: UInt32;
    TotalReceiptDiscount: UInt32;
    TotalReceiptIncrement: UInt32;
    CashBackAmount: UInt32;
    TotalReceiptItemCancel: UInt32;
    TotalReceiptPayment: UInt32;
    TotalReceiptReversedPayment: UInt32;
    KasaAvansAmount: UInt32;
    KasaPaymentAmount: UInt32;
    invoiceAmount: UInt32;
    invoiceAmountCurrency: UInt32;
    KatkiPayiAmount: UInt32;
    TaxFreeRefund: UInt32;
    TaxFreeCalculated: UInt32;
    bcdTicketDate: string;  
    bcdTicketTime: string; 
    ticketType: Byte;
    totalNumberOfItems: UInt16;
    numberOfItemsInThis: UInt16;
    totalNumberOfPayments: UInt16;
    numberOfPaymentsInThis: UInt16;
    TckNo: string;
    invoiceNo: string;
    invoiceDate: UInt32;
    invoiceType: Byte;
    totalNumberOfPrinterLines: Integer;
    numberOfPrinterLinesInThis: Integer;
    uniqueId: Array [0..23] of Byte;
    SaleInfo: Array [0..511] of TStSaleinfo;
    stPayment: TStPayment;
    stTaxDetails: Array [0..7] of TStVATDetail;
    stPrinterCopy: Array [0..1023] of TStPrinterDataForOneLine;
  end;

  TStSaleinfo = packed record
    ItemType: Byte;
    ItemPrice: UInt64;
    IncAmount: UInt64;
    DecAmount: UInt64;
    OrigialItemAmount: UInt32; 
    OriginalItemAmountCurrency: UInt16;
    ItemVatRate: UInt16;
    ItemCurrencyType: UInt16;
    ItemVatIndex: Byte;
    ItemCountPrecision: Byte;
    ItemCount: Integer;
    ItemUnitType: Byte;
    DeptIndex: Byte;
    Flag: UInt32;
    Name: string;
    Barcode: string;
  end;

  TStPayment = packed record
    flags: Byte;
    dateOfPayment: UInt32;
    typeOfPayment: UInt32;              // EPaymentTypes
    subtypeOfPayment: Byte;             // EPaymentSubtypes
    orgAmount: UInt32;                  // Exp; Currency Amount
    orgAmountCurrencyCode: UInt16;      // as defined in currecyTable from GIB
    payAmount: UInt32;                  
    payAmountCurrencyCode: UInt16;      
    cashBackAmountInTL: UInt32;         // currency with precision 2
    cashBackAmountInDoviz: UInt32;      // if currency sale, then curency amount
    stBankPayment: TStBankPaymentInfo;  // Keeps all payment info related with bank
  end;

  TStBankPaymentInfo = packed record
    batchNo: UInt32;
    stan: UInt32;
    balance: UInt32;
    bankBkmId: UInt16;
    numberOfdiscount: Byte;
    numberOfbonus: Byte;
    authorizeCode: string;
    transFlag: Array [0..1] of Byte;
    terminalId: string;
    rrn: string;
    merchantId: string;
    bankName: string;
    numberOfInstallments: Byte;
    numberOfsubPayment: Byte;
		numberOferrorMessage: Byte;
    stBankSubPaymentInfo: Array [0..11] of TStBankSubPaymentInfo;
    stCard: TStCardInfo;
    stPaymentErrMessage: TStPaymentErrMessage;
  end;

  TStBankSubPaymentInfo = packed record
    My_type: UInt16; 				// EPaymentSubType
	  amount: UInt32;
	  name: string;
  end;

  TStCardInfo = packed record
    inputType: Byte;
    pan: string;
    holderName: string;
    My_type: string;
    expireDate: string;
  end;

  TStPaymentErrMessage = packed record
    ErrorCode: string;    // bank error code
    ErrorMsg: string;
    AppErrorCode: string; // payment application specific error code
    AppErrorMsg: string;
  end;

  TStVATDetail = packed record
    u32VAT: Integer;                    //**< Total Tax in TL with precition 2 */
    u32Amount: Integer;                 //**< Total Amount in TL with precition 2 */
    u16VATPercentage: UInt16;           //**< Tax rate, it is 1800 for %18 */
  end;

  TStPrinterDataForOneLine = packed record
    Flag: UInt32;
    lineLen: Byte;
    line: string;
  end;

I am using below code to serialize this records into json:

var
  StTicket: TStTicket;
  JsonString: RawUTF8;
begin
  JsonString := RecordSaveJSON(StTicket, TypeInfo(TStTicket));
end;

I have quite a long json string. It's all fine but serialization of "StTaxDetails" defined in TStTicket. What I am having as a serialized json is something like below (beginning and end is cut for making it more readable):

.....":""}}},"stTaxDetails":"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","stPrinterCopy":[{".....

What I was expecting is something like:

.....":""}}},"stTaxDetails":[{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0}],"stPrinterCopy":[{".....

I am simply stuck at this point. Is it me doing some wrong record declaration(s) here?

Any help is appreciated.

Thanks.

#152 mORMot 1 » AES/CBC/PKCS5Padding » 2016-06-21 10:48:09

ertank
Replies: 0

Hi,

There will be two different applications (JAVA and fpc (free pascal compiler)) that will be communicating some information. I am still not very familiar with crypt things. However, I believe mORMot already has what I am searching for.

I need to implement a crypt/decrypt algorithm identical to subject standard.

Is it possible?
Which functions I need to be using?

Thanks.

#153 Re: mORMot 1 » SHA256 of a file » 2016-06-06 20:30:49

That did the job perfectly. Thank you.

#154 mORMot 1 » SHA256 of a file » 2016-06-06 08:38:13

ertank
Replies: 2

Hi,

I am mainly using SHA256 for the AES256 cryption. Recently, I needed to control if a file has changed. Size of the file is quite small (~20-30KB) and won't be increasing much. I thought I might save a SHA256 hash of the file somewhere and compare it to monitor "if file has changed"

When I tried to use SynCrypto.SHA256() I realize that it accepts RawByteString as a parameter. I believe, It may be used for file hashing, but I have no idea how to do that.

Is it possible to have an example of SynCrypto.SHA256() used for file hasing?

Thanks.

#155 Re: Low level and performance » LZO and SynLZ compression units » 2016-05-27 15:19:04

I tried SynZip already. Need something fast. Compression ratio is not my main concern. Though, even not as much as SynZip, FileSynLZ does compress.

Thanks.

#156 Re: Low level and performance » LZO and SynLZ compression units » 2016-05-27 13:53:51

Even I checked, I couldn't find it in documents. One last thing I would like to know about FileSynLZ/FileUnSynLZ is can I deflate a file using some other tool which is compressed using FileSynLZ?

I have already tried 7zip V15.14 and Winrar V5.30 and failed.

#157 Re: Low level and performance » Code to execute faster » 2016-05-27 09:20:17

I could only find ProDelphi myself.

What other profiler(s) are available free for Delphi 10 which I may try?

#158 Re: Low level and performance » LZO and SynLZ compression units » 2016-05-27 09:14:24

I see that function declaration as follows:

function FileSynLZ(const Source, Dest: TFileName; Magic: Cardinal): boolean;

I am not sure what value I should provide for parameter "Magic". Is it possible to have an example code, please?

Thanks.

#159 Re: Low level and performance » LZO and SynLZ compression units » 2016-05-26 21:47:49

Hi,

I want to fast backup some SQLite database files. Sizes mostly smaller than 2GB. Since it is indicated that lzopas_compressfile is faster than copying files, I wanted to give it a try. Unfortunately, I have found below comment in 1.18.2639 version of the framework in SynLZO unit.

{.$define LZOFILE}
{ attempt to use in-place file compression using memory mapping mechanism
  -> still not fully functional -> so do not define }

I wonder if the function is not to be used at all.

Thanks.

#160 Low level and performance » Code to execute faster » 2016-05-26 20:17:01

ertank
Replies: 3

Hi,

Trying to save as many CPU cycles as possible.

Using OnKeyPress event of a TEdit. Want to Check if Key is 'x' character (case insensitive). CharCase property of the component is ecNormal. Current code is:

if SynCommons.UpperCase(Key) = 'X' then
begin
end;

I have checked UpperCase function and it seems to do lots of things inside. I have changed my code as follows:

if Key = 'x' or Key = 'X' then
begin
end;

However, I do wonder if there is any code that can be proposed to execute faster.

Thanks.

#161 Re: mORMot 1 » Json serialization of a class » 2016-05-18 09:34:05

I could solve my problem as below:

  TStTaxRateString = packed record
    taxRate: string;
  end;
  TStTaxRatesString = Array of TStTaxRateString;

  TStTaxRateInteger = packed record
    taxRate: UInt32;
  end;
  TStTaxRatesInteger = Array of TStTaxRateInteger;


procedure TfrmMain.btnTaxClick(Sender: TObject);
var
  Json: AnsiString;
  sRaw:RawUTF8;
  RetValTax, RetValDept: TBytes;
  RetCode: UInt32;
  i, NumberOfTotalTaxRates, NumberOfTotalRecordsReceived: Integer;
  Taxes: TStTaxRatesString;
  StTaxRates: TStTaxRatesInteger;
begin
  SetLength(StTaxRates, 8);
  TTextWriter.RegisterCustomJSONSerializerFromText(TypeInfo(TStTaxRatesString), 'taxRate word');

  // Serialize
  Json := AnsiString(DynArraySaveJSON(Taxes, TypeInfo(TStTaxRatesString)));
  SetLength(RetValTax, STANDART_BUFFER);
  RetCode := Json_FiscalPrinter_GetTaxRates(NumberOfTotalTaxRates, NumberOfTotalRecordsReceived, Json, @RetValTax[0], Length(RetValTax), 8);
  if RetCode = 0 then
  begin
    // Convert TBytes to String which is actually a Json text
    s := TEncoding.Default.GetString(RetValTax);
    // Manually add " characters at beginning of numbers
    sRaw := StringReplaceAll(RawUTF8(s), '":', '":"');
    // Manually add " characters at the end of numbers
    sRaw := StringReplaceAll(sRaw, '}', '"}');
    // Set correct formatting for de-serialization
    TTextWriter.RegisterCustomJSONSerializerFromText(TypeInfo(TStTaxRatesString), 'taxRate string');
    // De-serialization itself
    DynArrayLoadJSON(Taxes, Pointer(sRaw), TypeInfo(TStTaxRatesString));

    // Copy String Record Type into Integer record type with necessary convertion
    for I := 0 to 7 do
      StTaxRates[i].taxRate := StrToUInt64(Taxes[i].taxRate);    
  end;
end;

#162 Re: mORMot 1 » Json serialization of a class » 2016-05-13 14:38:10

That did not work (function returned nil). Most likely because JSON formatting is a number formatting.

#163 Re: mORMot 1 » Json serialization of a class » 2016-05-13 13:12:56

Using version '1.18.2639' of framework, I am getting Access Violation when using DynArrayLoadJSON for a specific record definition.

Record definition which gets access violation:

  TStTaxRate = packed record
    taxRate: string;
  end;
  TStTaxRates = Array of TStTaxRate;

Below is called at FormCreate:

TTextWriter.RegisterCustomJSONSerializerFromText(TypeInfo(TStTaxRate), 'taxRate word');

Button click raises exception:

procedure TForm5.Button3Click(Sender: TObject);
var
  s: RawUTF8;
  stTaxRates: TStTaxRates;
begin
  SetLength(stTaxRates, 8);
  s := '[{"taxRate":100},{"taxRate":800},{"taxRate":0},{"taxRate":1800},{"taxRate":0},{"taxRate":100},{"taxRate":1800},{"taxRate":800}]';
  DynArrayLoadJSON(stTaxRates, Pointer(s), TypeInfo(TStTaxRates));
end;

I have another dynamic record which I do not have any problems with.

  TStDepartment = packed record
    szDeptName: string;
    u8TaxIndex: Byte;
    iCurrencyType: UInt16;
    iUnitType: UInt16;
    u64Limit: UInt64;
    u64Price: UInt64;
  end;
  TStDepartments = Array of TStDepartment;

  // No TTextWriter.RegisterCustomJSONSerializerFromText() call for this record since it works out of the box

procedure TForm5.Button4Click(Sender: TObject);
var
  s: RawUTF8;
  stDept: TStDepartments;
begin
  SetLength(stDept, 12);
  s := '[{"szDeptName":"KSM1","u8TaxIndex":0,"iCurrencyType":949,"iUnitType":1,"u64Limit":99999999,"u64Price":0},{"szDeptName":"KSM2","u8TaxIndex":1,"iCurrencyType":949,"iUnitType":1,"u64Limit":99999999,"u64Price":0},{"szDeptName":"KSM3","u8TaxIndex":2,"iCurrencyType":949,"iUnitType":1,"u64Limit":99999999,"u64Price":0},{"szDeptName":"KSM4","u8TaxIndex":3,"iCurrencyType":949,"iUnitType":1,"u64Limit":99999999,"u64Price":0},{"szDeptName":"KSM5","u8TaxIndex":4,"iCurrencyType":949,"iUnitType":1,"u64Limit":99999999,"u64Price":0},{"szDeptName":"KSM6","u8TaxIndex":5,"iCurrencyType":949,"iUnitType":1,"u64Limit":99999999,"u64Price":0},{"szDeptName":"KSM7","u8TaxIndex":6,"iCurrencyType":949,"iUnitType":1,"u64Limit":99999999,"u64Price":0},{"szDeptName":"KSM8","u8TaxIndex":7,"iCurrencyType":949,"iUnitType":1,"u64Limit":99999999,"u64Price":0},{"szDeptName":"KSM9","u8TaxIndex":0,"iCurrencyType":949,"iUnitType":1,"u64Limit":99999999,"u64Price":0},{"szDeptName":"KSM10","u8TaxIndex":1,"iCurrencyType":949,"iUnitType":1,"u64Limit":99999999,"u64Price":0},{"szDeptName":"KSM11","u8TaxIndex":2,"iCurrencyType":949,"iUnitType":1,"u64Limit":99999999,"u64Price":0},{"szDeptName":"KSM12","u8TaxIndex":3,"iCurrencyType":949,"iUnitType":1,"u64Limit":99999999,"u64Price":0}]';
  DynArrayLoadJSON(stDept, Pointer(s), TypeInfo(TStDepartments));
end;

#164 Re: mORMot 1 » Json serialization of a class » 2016-05-13 11:10:37

Sorry, couldn't find it in Documentation "10.1.3.2.4. Text-based definition" section. Is it written somewhere else?

#165 Re: mORMot 1 » Json serialization of a class » 2016-05-13 09:40:37

Hi Ab,

That code solved my problem. Thank you. I was starting to afraid that I won't be able to solve it in 1-2 lines of coding before I saw your post.

Should I use it always just before calling DynArraySaveJSON? Or, it is just fine to call once in the application (for example OnCreate event) and that is enough?

My working code is as follows:

  TStTaxRate = packed record
    taxRate: string;
  end;
  TStTaxRates = Array of TStTaxRate;

procedure TForm5.Button3Click(Sender: TObject);
var
  Json: AnsiString;
  stTaxRates: TStTaxRates;
begin
  TTextWriter.RegisterCustomJSONSerializerFromText(TypeInfo(TStTaxRates), 'taxRate word');
  SetLength(stTaxRates, 8);
//   Serialize
  Json := AnsiString(DynArraySaveJSON(stTaxRates, TypeInfo(TStTaxRates)));
  Memo1.Lines.Add('from mORMot: ' + String(Json));
  Exit;
end;

Memo1 display:

from mORMot: [{"taxRate":0},{"taxRate":0},{"taxRate":0},{"taxRate":0},{"taxRate":0},{"taxRate":0},{"taxRate":0},{"taxRate":0}]

That is exactly what I needed.

#166 Re: mORMot 1 » Json serialization of a class » 2016-05-12 21:09:21

Tried another code. This is not working for me, too.

  TStTaxRate = record
    taxRate: UInt16;
  end;
  TStTaxRates = Array of TStTaxRate;

procedure TForm5.Button3Click(Sender: TObject);
var
  Json: AnsiString;
  stTaxRates: TStTaxRates;
begin
  SetLength(stTaxRates, 8);
  // Serialize
  Json := AnsiString(DynArraySaveJSON(stTaxRates, TypeInfo(TStTaxRates)));
  Memo1.Lines.Add(String(Json));
  Exit;
end;

TSTTaxRates is an array type in above code. Result on screen is:

[0,0,0,0,0,0,0,0]

This is close to what I need, however still missing variable name in serialized string. How can I change my code to get below result:

[{"taxRate":0},{"taxRate":0},{"taxRate":0},{"taxRate":0},{"taxRate":0},{"taxRate":0},{"taxRate":0},{"taxRate":0}]

Thanks.

#167 Re: mORMot 1 » Json serialization of a class » 2016-05-12 18:57:38

I very much appreciate correction of my code, please.

#168 Re: mORMot 1 » Json serialization of a class » 2016-05-12 16:49:30

Latest version of the code:

  TST_TAX_RATE = record
    taxRate: UInt16;
  end;

procedure TForm5.Button3Click(Sender: TObject);
var
  Json: AnsiString; // DLL call needs me sending AnsiString as parameters
  stTaxRates: Array [1..8] of TST_TAX_RATE;
begin
  // Serialize
  Json := AnsiString(DynArraySaveJSON(stTaxRates, TypeInfo(TST_TAX_RATE), True));
  Memo1.Lines.Add(String(Json));
  Exit;
end;

my result still is

{"taxRate":0}

sad



EDIT: Just downloaded latest nightly build. Result is still same.

#169 Re: mORMot 1 » Json serialization of a class » 2016-05-11 16:40:24

Changed related part in my code to:

Json := AnsiString(DynArraySaveJSON(stDept, TypeInfo(TST_DEPARTMENT)));

What I received was:

{"taxRate":0}

Thanks for your help. Unfortunately, that didn't solve it.

#170 Re: mORMot 1 » Json serialization of a class » 2016-05-11 16:24:59

ab wrote:

Some points when serializing a class:

5. For nested list/arrays of classes, consider defining T*ObjArray types, register them and use ObjArray*() functions: TSynAutoCreateFields would also recognize such published fields and hold them.

Search for all those TSynPersistent / TSynAutoCreateFields keywords in the documentation.


I have searched documentation. Found part explaining TSynAutoCreateFields. Though, It is beyond my understanding. So, I thought it would be easier for me to provide an example and ask here. Staring with a simpler one since I might get it to my understanding and solve remaining myself.

I have following definitions:

  TST_TAX_RATE = record
    taxRate: UInt16;
  end;

And, I need to define that record as an array:

procedure TForm5.Button3Click(Sender: TObject);
var
  Json: AnsiString; // DLL call needs me sending AnsiString as parameters
  stTaxRates: Array [1..8] of TST_TAX_RATE;
begin
  // Serialize
  Json := AnsiString(RecordSaveJson(stTaxRates, TypeInfo(TST_TAX_RATE)));
  Memo1.Lines.Add(String(Json));
  Exit;
end;

When I run, above code displays following in Memo1:

{"taxRate":0}

What I expect to read in it is something like:

[{"taxRate":0},{"taxRate":0},{"taxRate":0},{"taxRate":0},{"taxRate":0},{"taxRate":0},{"taxRate":0},{"taxRate":0}]

I didn't understand where I am making a mistake here.

#171 mORMot 1 » Json serialization of a class » 2016-05-10 23:01:59

ertank
Replies: 19

Hello,

I tried to read more about how mORMot handles JSON in online documentation. I couldn't find an answer myself. If I have below definitions in my code can I serialize "TStDepartment" class using mORMot json function(s)? Or, Is it better I prepare a record definition of it somehow?

type
  TCurrencyType = (
    CURRENCY_NONE = 0,
    CURRENCY_TL = 949,
    CURRENCY_DOLAR = 840,
    CURRENCY_EU = 978,
    CURRENCY_GPR = 826
  );
  
  TItemUnitTypes = (
    ITEM_NONE,
    ITEM_NUMBER = 1,
    ITEM_KILOGRAM = 2,
    ITEM_GRAM = 3,
    ITEM_LITRE = 4,

    // Adetsel Birimler
    ITEM_DUZINE = 11,
    ITEM_DEMET, // 12
    ITEM_KASA, // 13
    ITEM_BAG, // 14

    // Agirlik Birimler
    ITEM_MILIGRAM = 31,
    ITEM_TON, // 32
    ITEM_ONS, // 33
    ITEM_DESIGRAM, // 34
    ITEM_SANTIGRAM, // 35
    ITEM_POUND, // 36
    ITEM_KENTAL, // 37

    // Uzunluk Birimler
    ITEM_METRE = 51,
    ITEM_SANTIMETRE, // 52
    ITEM_MILIMETRE, // 53
    ITEM_DEKAMETRE, // 54
    ITEM_HEKTAMETRE, // 55
    ITEM_KILOMETRE, // 56
    ITEM_DESIMETRE, // 57
    ITEM_MIKRON, // 58
    ITEM_INC, // 59
    ITEM_FOOT, // 60
    ITEM_YARD, // 61
    ITEM_MIL, // 62

    // Hacim Birimler
    ITEM_METREKUP = 71,
    ITEM_DESIMETREKUP, // 72
    ITEM_SANTIMETREKUP, // 73
    ITEM_MILIMETREKUP, // 74
    ITEM_DEKALITRE, // 75
    ITEM_HEKTOLITRE, // 76
    ITEM_KILOLITRE, // 77
    ITEM_DESILITRE, // 78
    ITEM_SANTILITRE, // 79
    ITEM_MILILITRE, // 80
    ITEM_INCKUP, // 81
    ITEM_GALLON, // 82
    ITEM_BUSHEL, // 83

    // Alan Birimler
    ITEM_METREKARE = 91,
    ITEM_DEKAMETREKARE, // 92
    ITEM_AR, // 93
    ITEM_KILOMETREKARE, // 94
    ITEM_DESIMETREKARE, // 95
    ITEM_SANTIMETREKARE, // 96
    ITEM_MILIMETREKARE, // 97
    ITEM_DONUM, // 98
    ITEM_HEKTAR, // 99
    ITEM_INCKARE // 100
  );

  TStDepartment = class
  private
    FDeptName: string;
    FU8TaxIndex: Byte;
    FCurrencyType: TCurrencyType;
    FUnitType: TItemUnitTypes;
    FU64Limit: UInt64;
    FU64Price: UInt64;
  public
    constructor Create();
  public
    property DeptName: string read FDeptName write FDeptName;
    property U8TaxIndex: Byte read FU8TaxIndex write FU8TaxIndex;
    property CurrencyType: TCurrencyType read FCurrencyType write FCurrencyType;
    property UnitType: TItemUnitTypes read FUnitType write FUnitType;
    property U64Limit: UInt64 read FU64Limit write FU64Limit;
    property U64Price: UInt64 read FU64Price write FU64Price;
  end;
  
{ TStDepartment }

constructor TStDepartment.Create;
begin
  FDeptName := '';
end;

#172 Re: mORMot 1 » JSON serialization and de-serialization - Delphi 10 » 2016-05-01 17:17:27

I might not understood your proposition. I tried to define my record variables as TBytes and resulting json was not what I have posed in #4 in this thread.

It is quite customized json format DLL requires. Otherwise, I am getting "json format error" as a result from function calls. Some of the variables are first converted to hex before converting them to Base64. Those are mainly numbers as far as I can see.

#173 Re: mORMot 1 » JSON serialization and de-serialization - Delphi 10 » 2016-04-29 14:58:05

I believe, I got it to work now. Code is as below. Tests seems to be working OK. Had to convert everything to AnsiString since that is what DLL requests.

There is this one thing I would like to get some suggestions though. Is there any faster function in mORMot to replace "TNetEncoding.Base64.EncodeBytesToString()" ?

Thanks.



  // DLL import definitions
  procedure GetErrorMessage(ErrorCode: UInt32; Buffer: TBytes); cdecl; external 'GMPSmartDLL.dll';
  function Json_FiscalPrinter_Echo(szEcho_Out: TBytes; EchoLen_Out, TimeoutInMiliseconds:integer): UInt32; cdecl; external 'GMPSmartDLL.dll';
  function Json_GMP_StartPairingInit(szPairing: AnsiString; var szPairingResp: TBytes; PairingRespLen: Integer): Uint32; cdecl; external 'GMPSmartDLL.dll';

type
  TST_GMP_PAIR = packed record
      In_ProcOrderNum : AnsiString;
      In_ProcDate : AnsiString;
      In_ProcTime : AnsiString;
      In_DeviceBrand : AnsiString;
      In_DeviceModel : AnsiString;
      In_DeviceSerialNum : AnsiString;
      In_DeviceEcrRegisterNo : AnsiString;
  end;

function TForm5.AscToBcd(const Value: string): TBytes;
begin
  if Length(Value) > 32 then
  begin
    // because static buffers are the best, we fail like the original code
  end else
  begin
    SetLength(Result, 16);
    HexToBin(PChar(Value), Result, Length(Result));
  end;
end;

procedure TForm5.btnPairClick(Sender: TObject);
var
  i:Integer;
  sent:TST_GMP_PAIR;
  //recv:TST_GMP_PAIR_RESP;
  s,json:AnsiString;
  pResp,b:TBytes;
begin
  // Fill record structure.
  sent.In_ProcOrderNum        := AnsiString(TNetEncoding.Base64.EncodeBytesToString(Copy(AscToBcd('000001'), 0, 16)));
  sent.In_ProcDate            := AnsiString(TNetEncoding.Base64.EncodeBytesToString(Copy(AscToBcd(FormatDateTime('ddmmyy', Now)), 0, 3)));
  sent.In_ProcTime            := AnsiString(TNetEncoding.Base64.EncodeBytesToString(Copy(AscToBcd(FormatDateTime('hhmmss', Now)), 0, 3)));
  sent.In_DeviceBrand         := AnsiString(TNetEncoding.Base64.EncodeBytesToString(TEncoding.ASCII.GetBytes('INGENICO')));
  sent.In_DeviceModel         := AnsiString(TNetEncoding.Base64.EncodeBytesToString(TEncoding.ASCII.GetBytes('IWE280')));
  sent.In_DeviceSerialNum     := AnsiString(TNetEncoding.Base64.EncodeBytesToString(TEncoding.ASCII.GetBytes('JHWE20000079')));
  sent.In_DeviceEcrRegisterNo := AnsiString(TNetEncoding.Base64.EncodeBytesToString(TEncoding.ASCII.GetBytes('12344567')));

  json := AnsiString(RecordSaveJSON(sent, TypeInfo(TST_GMP_PAIR)));
  Memo1.Lines.Add(EmptyStr);
  Memo1.Lines.Add('New Code Produced JSON:');
  Memo1.Lines.Add(string(json));

  SetLength(pResp, 200000);
  i := Json_GMP_StartPairingInit(json, pResp, Length(pResp));
  if i <> 0 then begin
    SetLength(b, 1000);
    GetErrorMessage(i, b);
    s := AnsiString(TEncoding.ASCII.GetString(b));
    Memo1.Lines.Add(EmptyStr);
    Memo1.Lines.Add('ERROR: ' + String(s));
  end else begin
    Memo1.Lines.Add(EmptyStr);
    Memo1.Lines.Add('Pairing: OK.');
  end;
end;

#174 Re: mORMot 1 » JSON serialization and de-serialization - Delphi 10 » 2016-04-29 09:31:54

Thanks for all suggestions. I have one more question. When I use RecordSaveJSON on byte variables. Does it automatically convert it into Base64 string?

#175 Re: mORMot 1 » JSON serialization and de-serialization - Delphi 10 » 2016-04-27 18:29:17

I was wrong. I could get a detail of "szJsonPairing" that is as follows:

C# Code for setting parameters for DLL call:

            ST_GMP_PAIR pairing = new ST_GMP_PAIR();
            pairing.In_DeviceBrand = Encoding.Default.GetBytes("INGENICO");
            pairing.In_DeviceModel = Encoding.Default.GetBytes("IWE280");
            pairing.In_DeviceEcrRegisterNo = Encoding.Default.GetBytes("12344567");
            pairing.In_DeviceSerialNum = Encoding.Default.GetBytes("JHWE20000079");
            pairing.In_ProcOrderNum = parsClass.GMP_AscToBcd("000001");
            Array.Copy(parsClass.GMP_AscToBcd(m_lblProcDate.Text.Substring(0, 2) + m_lblProcDate.Text.Substring(3, 2) + m_lblProcDate.Text.Substring(6, 2)), pairing.In_ProcDate, pairing.In_ProcDate.Length);
            Array.Copy(parsClass.GMP_AscToBcd(m_lblProcTime.Text.Substring(0, 2) + m_lblProcTime.Text.Substring(3, 2) + m_lblProcTime.Text.Substring(6, 2)), pairing.In_ProcTime, pairing.In_ProcTime.Length);

            ST_GMP_PAIR_RESP pairingResp = new ST_GMP_PAIR_RESP();

            resp = Json_GMPSmartDLL.GMP_StartPairingInit(ref pairing, ref pairingResp);

C# function making DLL call itself:

 public static UInt32 GMP_StartPairingInit(ref ST_GMP_PAIR pStPair, ref ST_GMP_PAIR_RESP pStPairResp, int TimeoutInMiliseconds = Defines.TIMEOUT_ECHO)
        {
            string szJsonPairing = JsonConvert.SerializeObject(pStPair);
            byte[] szJsonPairing_Out = new byte[Defines.GMP_TICKET_BUFFER];

            UInt32 retcode = Json_GMP_StartPairingInit(szJsonPairing, szJsonPairing_Out, szJsonPairing_Out.Length);
            if (retcode == 0)
            {
                string retJsonString = GMP_Tools.SetEncoding(szJsonPairing_Out);
                pStPairResp = JsonConvert.DeserializeObject<ST_GMP_PAIR_RESP>(retJsonString);
            }
            return retcode;
        }

Value of "szJsonPairing" after it is Serialized in DLL call function:

{"In_ProcOrderNum":"AAABAAAAAAAAAAAAAAAAAA==","In_ProcDate":"JwQW","In_ProcTime":"IEYg","In_DeviceBrand":"SU5HRU5JQ08=","In_DeviceModel":"SVdFMjgw","In_DeviceSerialNum":"SkhXRTIwMDAwMDc5","In_DeviceEcrRegisterNo":"MTIzNDQ1Njc="}

Since I have the hardware with me and Visual Studio installed some other city, I won't be able to get details of "szJsonPairing_Out" for about 2 weeks I assume.

#176 Re: mORMot 1 » JSON serialization and de-serialization - Delphi 10 » 2016-04-27 17:16:41

I've found out that C# application uses "Newtonsoft.Json.7.0.1" for converting Json to and from. Which seems to be a open source .NET framework.

http://www.newtonsoft.com/json

I think this is as far as I can get to the Json details of C# application.

#177 mORMot 1 » JSON serialization and de-serialization - Delphi 10 » 2016-04-27 16:40:45

ertank
Replies: 10

Hi,

I have very low to no knowledge of JSON. So, I maybe asking my question wrongly here. Hope it will be understandable.

There is this C# application with code available to me which uses a C# DLL. Application is communicating with a POS device using that DLL.

I am writing a Delphi application which uses that same C# DLL. I see that at some point C# application using JsonConvert.SerializeObject() and JsonConvert.DeserializeObject() functions, when I check the code. Sample lines from C# code is as follows:

        public static UInt32 GMP_StartPairingInit(ref ST_GMP_PAIR pStPair, ref ST_GMP_PAIR_RESP pStPairResp, int TimeoutInMiliseconds = Defines.TIMEOUT_ECHO)
        {
            string szJsonPairing = JsonConvert.SerializeObject(pStPair);
            byte[] szJsonPairing_Out = new byte[Defines.GMP_TICKET_BUFFER];

            UInt32 retcode = Json_GMP_StartPairingInit(szJsonPairing, szJsonPairing_Out, szJsonPairing_Out.Length);
            if (retcode == 0)
            {
                string retJsonString = GMP_Tools.SetEncoding(szJsonPairing_Out);
                pStPairResp = JsonConvert.DeserializeObject<ST_GMP_PAIR_RESP>(retJsonString);
            }
            return retcode;
        }

I do not know how to do that on Delphi. I have no sample data sent/received. I just know that mORMot project has JSON routines. So, I appreciate if someone can help me out.

Record structure to Serialize at Delphi:

    ST_GMP_PAIR : record
      In_ProcOrderNum : array [0..3] of Byte;
      In_ProcDate : array [0..3] of Byte;
      In_ProcTime : array [0..3] of Byte;
      In_DeviceBrand : array [0..16] of Byte;
      In_DeviceModel : array [0..16] of Byte;
      In_DeviceSerialNum : array [0..16] of Byte;
      In_DeviceEcrRegisterNo : array [0..17] of Byte;
    end;

Record structure to DeSerialize at Delphi:

    ST_GMP_PAIR_RESP: record
      Out_ProcOrderNum : array[0..6] of Byte;
      Out_ProcDate : array[0..6] of Byte;
      Out_ProcTime : array[0..6] of Byte;
      Out_DeviceBrand : array[0..16] of Byte;
      Out_DeviceModel : array[0..16] of Byte;
      Out_DeviceSerialNum : array[0..16] of Byte;
      Out_ErrorRespCode : array[0..2] of Byte;
      Out_StatusCode : array[0..2] of Byte;
      Out_VersionNumber : array[0..8] of Byte;
    end;

Thanks.

#178 Re: mORMot 1 » SynCommons - Lazarus v1.6 - FPC v3.0, compile fails » 2016-03-21 12:17:50

I do need AES256-SHA for WinCE. I will try what Marius suggested to see if that helps.

Marius, you say that you can compile SnyCrypto under Lazarus for wince-arm, is it possible you pass that file to me for testing? I do have platform to make tests. I also use "SynCommons.HexToBin", "SynCommons.StringToUTF8", and "SynCommons.BinToBase64" in my code. If these are not present in your modified SynCrypto, you may want to send me some code to do actual test together with the SynCrypto file.

#179 Re: mORMot 1 » SynCommons - Lazarus v1.6 - FPC v3.0, compile fails » 2016-03-19 20:02:16

Hi Marius,

I have tried your suggestion already. First I thought there will be slight changes and changes will be just at the beginning of file. I was wrong. Unfortunately, {$ifdef}, {$ifndef} and {$else} are all over it. Moreover, file has 55000 lines of code which I am completely not familiar with. I got lost, and converted everything back to default.

What I need is basically what SynCrypto file needs. However, I am lost trying to figure definitions, functions, etc. necessary to identify, too.

#180 mORMot 1 » Advise on hiding "Key" used for AES256 encryption » 2016-03-19 18:58:33

ertank
Replies: 1

Hi,

We all know that constants and strings written directly in source code are also directly written in compiled EXE files. So, someone trying to hack the key may go in assembly code, see some strings there & may search EXE file with a hex editor and also might extract my fixed string for reversing crypt text.

I wonder if there are some easy ways to "hide" my key used for AES256 encryption in compiled EXE file.

Thanks.

--Ertan

#181 mORMot 1 » SynCommons - Lazarus v1.6 - FPC v3.0, compile fails » 2016-03-19 11:06:30

ertank
Replies: 5

Hi,

My framework version is: 1.18.2458. When I include SynCommons.pas in my uses in Lazarus targeting WinCE platform with ARM cpu I get following error:

SynCommons.pas(765,3) Fatal: Cannot find BaseUnix used by SynCommons.

Is there any workaround I might do to get it compiled? All I need is SynCommons and SyncCrypt to compile with above configuration, not the complete framework.

Thanks.

--Ertan

#182 Re: mORMot 1 » Sample AES encryption » 2016-03-16 17:54:20

It turns out that I installed version 1.17 of the framework which is indicated as stable on the web site. When I switch to version 1.18 nightly build from 2016-03-15 I got IVAtBeginning as a parameter for EncryptPKCS7 and DecryptPKCS7 functions.

Now, I can encrypt, and decrypt.

My final code is as follows:

const
  my_key = 'testkey';

var
  Form10: TForm10;

implementation

{$R *.dfm}

uses SynCommons, SynCrypto;

procedure TForm10.btnMakeAESClick(Sender: TObject);
var
  key : TSHA256Digest;
  aes : TAESCFB;
  s:RawByteString;
begin
  SynCommons.HexToBin(Pointer(SHA256(my_key)), @key, 32);

  aes := TAESCFB.Create(key, 256);
  try
    s := StringToUTF8(edtTextToEncrypt.Text);
    s := BinToBase64(aes.EncryptPKCS7(s, True));
    edtCrypted.Text := UTF8ToString(s);
  finally
    aes.Free;
  end;
end;

procedure TForm10.btnDecryptAESClick(Sender: TObject);
var
  key : TSHA256Digest;
  aes : TAESCFB;
  s:RawByteString;
begin
  SynCommons.HexToBin(Pointer(SHA256(my_key)), @key, 32);

   aes := TAESCFB.Create(key, 256);
  try
    s := StringToUTF8(edtCrypted.Text);
    s := aes.DecryptPKCS7(Base64ToBin(s), True);
    edtDecrypted.Text := UTF8ToString(s);
  finally
    aes.Free;
  end;
end;

Now, I have different crypt strings for same text.
Text to crypt: 'Sample Text at all!'
Crypt text1: 'WcSmQUMs0yPMPEwaaseNCWThhFkNzSEifnn0631q3c6IfKnurWHxjxtNliCcTBBL'
Crypt text2 (clicked btnMakeAES again): 'ioFKOtLfMFxXATJ4oiQw5P5gXUExvGBssiWtlgeDoNMkIBpka2Y7eo8KuYo8n/MA'
Crypt text3 (clicked btnMakeAES 3rd time): 'Yb8aMYICC51nbynZ6DLG1CmtCPui8HD9vUQgtnDg5o/p0DywyrVDbaIOhnOSIS7n'

All above Crypt strings decrypt back to 'Sample Text at all!' which is good.

Now, I wonder if there is anything more I can do to make crypt strings stronger than they are now.

Thanks for all the support.

--Ertan

#183 Re: mORMot 1 » Sample AES encryption » 2016-03-16 15:43:04

ab wrote:

Or even better, do not create a manual fixed IV, but use the IVAtBeginning=true parameter to EncryptPKCS7/DecryptPKCS7 methods, which would create a random IV for each encryption.

I believe I could do all suggestions but above one. SynCommons.pas or SynCrypto.pas do not have "IVAtBeginning" text in it. I couldn't find this parameter declared anywhere at all. Would you explain a little bit more, please? Maybe with some code sample?

--Ertan

#184 Re: mORMot 1 » Sample AES encryption » 2016-03-16 13:26:56

After some more search on the forum I found this post: http://synopse.info/forum/viewtopic.php?id=1587
Thank you Swanty!

I have used it and below is the code that I came up with.

uses SynCommons, SynCrypto;

procedure TForm10.btnMakeAESClick(Sender: TObject);
const
  my_key = 'testkey';
  my_iv  = '1234567890ABCDEF';
var
  key : TSHA256Digest;
  aes : TAESCBC;
  iv  : TAESBlock;
begin
  HexToBin(Pointer(SHA256(my_key)), @key, 32);
  Move(TEncoding.ANSI.GetBytes(my_iv)[0], iv[0], 16);
  aes := TAESCBC.Create(key, 256, iv);
  try
    edtCrypted.Text := BinToBase64(aes.EncryptPKCS7(edtTextToEncrypt.Text));
  finally
    aes.Free;
  end;
end;

procedure TForm10.btnDecryptAESClick(Sender: TObject);
const
  my_key = 'testkey';
  my_iv  = '1234567890ABCDEF';
var
  key : TSHA256Digest;
  aes : TAESCBC;
  iv  : TAESBlock;
begin
  HexToBin(Pointer(SHA256(my_key)), @key, 32);
  Move(TEncoding.ANSI.GetBytes(my_iv)[0], iv[0], 16);
  aes := TAESCBC.Create(key, 256, iv);
  try
    edtDecrypted.Text := aes.DecryptPKCS7(Base64ToBin(edtCrypted.Text));
  finally
    aes.Free;
  end;
end;

edtTextToEncrypt.Text = 'Sample Text at all!'
edtCrypted.Text = 'Occ1u4nfrXSaJUZvbXCg1zpSytS4vFH4sldaZjU46gQ='
edtDecrypted.Text = 'Sample Text at all!'


So, could I do an AES crypt text with above code? Or, this is a crypt text but not an AES crypt because it uses "PKCS7"? Just give it to me being newbie, please.

#185 Re: mORMot 1 » Sample AES encryption » 2016-03-16 12:38:46

AOG wrote:

Length('Sample Text at all!') = 20 ?

I read below in SynCrypto.pas:
TAESBlock = packed array[0..AESBlockSize-1] of byte;
AESBlockSize = 16

I didn't understand how to fit for example 20 characters into 16 bytes. Or, 60 characters into 16 bytes.

Well, I tried to explain that I do not know cryptography and how to use it. I do need a sample to understand, please.

#186 mORMot 1 » Sample AES encryption » 2016-03-16 11:58:08

ertank
Replies: 9

Hi,

I am all new to this encryption stuff. I am suggested to use AES anyway. So here I am.

My code below is not working as I expected, and I couldn't find any other sample I can use of. So, I appreciate someone fix it for me, please.

uses SynCrypto;

procedure TForm10.Button1Click(Sender: TObject);
var
  myAES:TAES;
  myBlock:TAESBlock;
  I: Integer;
  s:string;
begin
  myAES.EncryptInit('12345678901234567890123456789012', 256);

  for I := 1 to 16 do begin
    myBlock[i-1] := Ord(edtTextToEncrypt.Text[i]);
  end;

  myAES.Encrypt(myBlock);

  // Fill with zeros
  s := '0000000000000000';  // 16 character string
  for I := 1 to 16 do begin
    s[i] := Chr(myBlock[i-1]);
  end;
  edtCrypted.Text := s;
end;

procedure TForm10.Button2Click(Sender: TObject);
var
  myAES:TAES;
  myBlock:TAESBlock;
  I: Integer;
  s:string;
begin
  myAES.DecryptInit('12345678901234567890123456789012', 256);

  for I := 1 to 16 do begin
    myBlock[i-1] := Ord(edtCrypted.Text[i]);
  end;

  myAES.Decrypt(myBlock);

  // Fill with zeros
  s := '0000000000000000';  // 16 character string
  for I := 1 to 16 do begin
    s[i] := Chr(myBlock[i-1]);
  end;
  edtDecrypted.Text := s;
end;

Text to encrypt is: Sample Text at all!
Decrypted text is: Sample Text at a

Thanks.

Board footer

Powered by FluxBB