#151 mORMot 1 » Separate log for services » 2017-02-28 12:51:18

jaclas
Replies: 3

I use the event EchoCustom to log server behavior. However, I would like that every REST service had its own, separate log (separate event EchoCustom). How to do it correctly? Do I have to create an instance TSynLogFamily in each REST service?

#152 Re: mORMot 1 » Delphi XE2 - E2251 Ambiguous overloaded call to 'HexToBin' » 2017-02-15 12:02:00

btw it's interesting...

In Delphi XE2 message is:

E2251 Ambiguous overloaded call to 'HexToBin'"

in Delphi Berlin:

E2012 Type of expression must be BOOLEAN

Why Berlin message is inaccurate?

#153 Re: mORMot 1 » [dcc32 Error] SynLog.pas(2299): E2012 Type of expression must be BOOLE » 2017-02-15 08:05:23

Probably conflict in function name with unit System.Classes:

function HexToBin(Text: PWideChar; Buffer: PAnsiChar; BufSize: Integer): Integer; overload;

#154 mORMot 1 » [dcc32 Error] SynLog.pas(2299): E2012 Type of expression must be BOOLE » 2017-02-15 08:01:25

jaclas
Replies: 2

In SyslogMessage():

  if trimmsgfromlog and (len>27) then 
    if (P[0]='2') and (P[8]=' ') then begin
      inc(P,27); // trim e.g. '20160607 06442255  ! trace '
      dec(len,27);
    end else
    if HexToBin(P,nil,8) then begin   <------------------------------ line with error message
      inc(P,25); // trim e.g. '00000000089E5A13  " info '
      dec(len,25);
    end;

Delphi Berlin

#155 Re: mORMot 1 » Pass some object as interfaced service method parameter » 2017-01-28 18:59:02

Thanks for clarification. One more question:

why JSON is different (name quoted) between transfer as object or as record?

See on fields eg. VATID (and others):

send as record (with quotes):

{"VATID":"","PersonKind":76,"PKD":"","PlaceId":"","CommuneId":"","ProductId":268484512,"ProductVersion":0,"ProductReleaseDate":10000,"DemoVersionMode":76,"LastReceivedUUID":"","SystemId":42678,"SystemCodePage":-702306117,"ScreenResolution":-2,"DateOfCommencement":10000}

send as object (without quotes):

{VATID:"87654332",CommuneId:"0",DateOfCommencement:1485632481,LastReceivedUUID:"{3C71F148-5F70-4177-AF94-544E51FDC5D6}",PKD:"pkd",PlaceId:"09",ProductId:1234,ProductReleaseDate:100000,ProductVersion:87675675,ScreenResolution:700,SystemCodePage:987,SystemId:150}

#156 mORMot 1 » Pass some object as interfaced service method parameter » 2017-01-27 17:01:47

jaclas
Replies: 3

When I pass object via interfaced service method (with {$M+} and published) then before mORMot deserialize JSON with data of object I must create this object?

example:

service method:
function GetObject(const ObjectId : Integer; out Object : TMyObject);

use of this method:

var
 lObject  : TMyObject;
 //lObject := TMyObject.Create;  <-- without create object I get error on next line
 GetObject(x, lObject);  //<-- error if lObject = nil

mORMot can't autocreate this object?

#158 Re: mORMot 1 » Return RawJSON parameter in interfaced service and decode error » 2017-01-19 12:10:48

Thanks! But why do you paste three point list for me? ;-)

#159 Re: mORMot 1 » Return RawJSON parameter in interfaced service and decode error » 2017-01-18 21:14:33

Junior/RO wrote:

If you change the type RawJSON to RawUTF8?

It helped (escaping string in response), thx.
But I don't understand what is the type of RawJSON?

#160 Re: mORMot 1 » Return RawJSON parameter in interfaced service and decode error » 2017-01-18 12:50:26

Problem is no with record, but with field of type RawJSON that is coded with additional quotes and on client side decoding of server response raise error. Without this field call is sucessful.

{"UUID":"16551D01-CA15-4B32-BDFB-F5D0BDDA42E7",
"ReleaseTimestamp":1484210095,
"DeadTimestamp":1486767600,
"Topic":"Msg from: 2017-01-12 09:34:54",
"ContentsType":66,
"TagList":"{"Tag":["11","22","33","44"]}",  <---- see this, JSON parser not decoding this strange item
"DemoVersionMode":76,
"PersonKind":78}}

It seems to me that the type of RawJSON should be wrapped (be escaped).

#161 mORMot 1 » Return RawJSON parameter in interfaced service and decode error » 2017-01-18 08:52:05

jaclas
Replies: 10

I have server based on interfaced services.
In service I have method:

    function GetAnnouncementList(out aAnnouncementList: TAnnouncementDataList): Integer;

where:


  TAnnouncementDataList = TArray<RAnnouncementData>;

  RAnnouncementData = record
    UUID : TAnnouncementUUID;
    ReleaseTimestamp: TUnixTimestampUTC;
    DeadTimestamp : TUnixTimestampUTC;
    Topic: RawUTF8;
    ContentsType: SmallInt;
    TagList : RawJSON;   <------------------------------------------ this is problematic
    DemoVersionMode : AnsiChar;
    PersonKind : AnsiChar;
  end;

On client side I get this array like:

{"result":[[{"UUID":"16551D01-CA15-4B32-BDFB-F5D0BDDA42E7","ReleaseTimestamp":1484210095,"DeadTimestamp":1486767600,"Topic":"Msg from: 2017-01-12 09:34:54","ContentsType":66,
"TagList":"{"Tag":["11","22","33","44"]}","DemoVersionMode":76,"PersonKind":78},{"UUID":"FB5A930F-3D3C-4395-B4AC-81CA639E490C","ReleaseTimestamp":1484210097,"DeadTimestamp":1486767600,"Topic":"Msg from: 2017-01-12 09:34:57","ContentsType":66,
"TagList":"{"Tag":["11","22","33","44"]}","DemoVersionMode":76,"PersonKind":78}],2]}

Pay attention that TagList has quotes around: 

--->"{"Tag":["11","22","33","44"]}"<---

and client raise exception EInterfaceFactoryException on decoding this:

''Invalid returned JSON content: expects {result:...}, got {"result~~[[{"UUID":"16551D01-CA15-4B32-BDFB-F5D0BDDA42E7","ReleaseTimestamp":1484210095,"DeadTimestamp":1486767600,"Topic":"Wiadomość z chwili: 2017-01-12 09:34:54","ContentsType":66,"TagList":"{"Tag":["11","22","33","44"]}","DemoVersionMode":76,"PersonKind":78},{"UUID":"FB5A930F-3D3C-4395-B4AC-81CA639E490C","ReleaseTimestamp":1484210097,"DeadTimestamp":1486767600,"Topic":"Wiadomość z chwili: 2017-01-12 09:34:57","ContentsType":66,"TagList":"{"Tag":["11","22","33","44"]}","DemoVersionMode":76,"PersonKind":78}],2]}''

I generate the JSON in business code on the server side and I want to send it to the client.

What am I doing wrong? How can I do this right?

#162 Re: mORMot 1 » Last Modify bring a bug! » 2016-10-11 07:09:11

I confirm this bug.

[dcc32 Error] SynEcc.pas(3251): E2382 Cannot call constructors using instance variables

#163 Re: Other components » SynCommon except on initialize application » 2016-09-20 20:55:02

Maybe paranoid, but useful when tracing mem leaks :-)
Thx for info about SSE 42.

#164 Re: Other components » SynCommon except on initialize application » 2016-09-20 19:14:59

I search for except reason and.. I found. MadExcept cause this when option "Instantly crash on buffer overrun" is checked.

9VfKT9hE.png

#165 Re: Other components » SynCommon except on initialize application » 2016-09-19 18:11:08

Delphi version from MadExcept report: Delphi 10.1 Berlin
Framework up to date.

#166 Re: Other components » SynCommon except on initialize application » 2016-09-19 08:15:44

How can I help?

Screenshot before raised exception:
JpQe34ZF.png

#167 Other components » SynCommon except on initialize application » 2016-09-18 11:37:05

jaclas
Replies: 11

I use SynCrypto unit, it works ok. But when I enabled MadExcept to trace some memory leaks then Application raise AV on start, see callstack:

date/time          : 2016-09-18, 13:30:43, 480ms
operating system   : Windows 10 x64 build 14393
system language    : Polish
system up time     : 3 hours 15 minutes
program up time    : 575 milliseconds
processors         : 8x Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz
physical memory    : 8647/16323 MB (free/total)
free disk space    : (C:) 315,53 GB (D:) 222,00 GB
display mode       : 1920x1200, 32 bit
process id         : $2a48
allocated memory   : 240,97 MB
largest free block : 769,83 MB
executable         : JPKSender.exe
exec. date/time    : 2016-09-18 13:30
version            : 1.0.0.0
compiled with      : Delphi 10.1 Berlin
madExcept version  : 4.0.15
callstack crc      : $3a9974cc, $a6b50739, $a6b50739
exception number   : 1
exception class    : EAccessViolation
exception message  : Access violation at address 00864ABC in module 'JPKSender.exe'. Read of address 0A1C3000.

main thread ($33a8):
00864abc +008 JPKSender.exe SynCommons 23250  +5 StrCompSSE42
00868899 +031 JPKSender.exe SynCommons 32958  +5 FastFindPUTF8CharSorted
0086bdb0 +02c JPKSender.exe SynCommons 36327  +3 TJSONCustomParserRTTI.TypeNameToSimpleRTTIType
0086de39 +045 JPKSender.exe SynCommons 37008  +2 GetNextFieldType
0086dfe1 +145 JPKSender.exe SynCommons 37047 +29 TJSONRecordTextDefinition.Parse
0086dca0 +090 JPKSender.exe SynCommons 36991  +7 TJSONRecordTextDefinition.Create
0086dbec +070 JPKSender.exe SynCommons 36976  +8 TJSONRecordTextDefinition.FromCache
0086aff2 +06e JPKSender.exe SynCommons 35937  +6 TJSONCustomParsers.RegisterFromText
0087e37a +01a JPKSender.exe SynCommons 45053  +1 TTextWriter.RegisterCustomJSONSerializerFromText
00bdc438 +08c JPKSender.exe SynCommons 59135 +25 initialization
0040a186 +042 JPKSender.exe System     22279 +18 InitUnits
0040a1ef +03f JPKSender.exe System     22351 +14 @StartExe
004119a2 +042 JPKSender.exe SysInit     1419 +11 @InitExe
00bddf73 +00b JPKSender.exe JPKSender     58  +0 initialization
740862c2 +022 KERNEL32.DLL                       BaseThreadInitThunk

thread $2530:
740862c2 +22 KERNEL32.DLL  BaseThreadInitThunk

thread $18f0:
740862c2 +22 KERNEL32.DLL  BaseThreadInitThunk


cpu registers:
eax = f66a8cc0
ebx = 00000000
ecx = 0a1c2ff8
edx = 0a1c2ff8
esi = 00bdc3ac
edi = 000001f6
eip = 00864abc
esp = 0019fd54
ebp = 0019fd70

stack dump:
0019fd54  9f 88 86 00 59 57 86 00 - 00 00 00 00 0f 00 00 00  ....YW..........
0019fd64  f8 2f 1c 0a 1f 00 00 00 - 70 b9 be 00 8c fd 19 00  ./......p.......
0019fd74  b5 bd 86 00 e9 fd 00 00 - 06 70 88 00 06 00 00 00  .........p......
0019fd84  f8 2f 1c 0a 98 68 85 00 - b0 fd 19 00 3e de 86 00  ./...h......>...
0019fd94  0c fe 19 00 1e 29 86 00 - e9 fd 00 00 06 00 00 00  .....)..........
0019fda4  e8 c4 bd 00 0c fe 19 00 - 80 fe 19 00 34 fe 19 00  ............4...
0019fdb4  e6 df 86 00 34 fe 19 00 - 40 fe 19 00 24 9d 40 00  ....4...@...$.@.
0019fdc4  34 fe 19 00 bc b9 85 00 - 0c fe 19 00 cd 6f 40 00  4............o@.
0019fdd4  e8 fd 19 00 43 d1 40 00 - dc cf 1c 0a 04 00 00 00  ....C.@.........
0019fde4  e8 0f 1d 0a e8 8f 1c 0a - f0 8f 1c 0a 00 00 00 00  ................
0019fdf4  1c fe 19 00 00 00 00 00 - 28 a7 40 00 01 00 00 00  ........(.@.....
0019fe04  20 d3 4f 00 00 00 00 00 - 00 00 00 00 e6 d1 0c 00   .O.............
0019fe14  1c fe 19 00 e7 31 52 00 - be eb 58 00 00 00 00 00  .....1R...X.....
0019fe24  00 00 00 00 80 fe 19 00 - dc cf 1c 0a e8 2f 1d 0a  ............./..
0019fe34  90 fe 19 00 a5 dc 86 00 - 00 00 00 00 c0 fe 19 00  ................
0019fe44  03 9f 40 00 90 fe 19 00 - e8 2f 1d 0a 90 fe 19 00  ..@....../......
0019fe54  e6 d1 40 00 60 fe 19 00 - ed 6b 88 00 40 00 00 00  ..@.`....k..@...
0019fe64  40 00 00 00 00 8f 1d 0a - 40 00 00 00 00 00 00 00  @.......@.......
0019fe74  dc cf 1c 0a e8 0f 1d 0a - f6 01 00 01 f4 c4 bd 00  ................
0019fe84  f0 50 85 00 e8 c4 bd 01 - e8 2f 1d 0a b8 fe 19 00  .P......./......

#169 Re: Other components » SynCrypto - strange exception in decrypt AES » 2016-08-11 12:10:00

And again, I refactored and simplified example code, please look...

program Project2;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.Classes,
  SynCrypto;

const
 //string to encrypting
 CInputString : string = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque hendrerit augue quis lacus efficitur,' +
          ' sollicitudin tempor sapien dapibus. Vivamus quis neque congue, imperdiet nisi nec, hendrerit nulla.' +
          ' Ut quis dolor eget sapien sodales faucibus vel at turpis. Aenean sed varius arcu.';
 //password
 CPassword : TBytes = [0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1];

 //AES initialization vector
 CIV: TAESBlock = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);


//function to encrypt aInStream used aPassword and aAESClass, result is saved to aOutStream
procedure AESstreamCrypt(aAESClass: TAESAbstractClass; const aInStream, aOutStream: TStream; const aPassword: TBytes);
var
 aKeySize: Integer;
 lAES : TAESAbstract;
 lIn : RawByteString;
 lOut : RawByteString;
begin
 //get AES key size
 aKeySize := Length(aPassword) shl 3;

 //create an AES class object to encrypt stream
 lAES := aAESClass.Create(aPassword, aKeySize);
 try

 //copy aInStream to RawByteString local variable
 SetLength(lIn, aInStream.Size);
 aInStream.Position := 0;
 aInStream.ReadBuffer(lIn[1], aInStream.Size);

 //assign const vector
 lAES.IV := CIV;
 //encrypt TBytes
 lOut := lAES.EncryptPKCS7(lIn, False);

 //copy encrypted RawByteString to aOutStream
 aOutStream.Write(lOut[1], Length(lOut));
 finally
 lAES.Free;
 end;
end;

//function to decrypt aInStream used aPassword and aEASClass, result is saved to aOutStream
procedure AESstreamDecrypt(aAESClass: TAESAbstractClass; aInStream, aOutStream: TStream; const aPassword: TBytes);
var
 aKeySize: Integer;
 lAES : TAESAbstract;
 lIn : RawByteString;
 lOut: RawByteString;
begin
 //get AES key size
 aKeySize := Length(aPassword) shl 3;

 //create AES class object to decrypt stream
 lAES := aAESClass.Create(aPassword, aKeySize);
 try
 //copy aInStream to RawByteString local variable
 SetLength(lIn, aInStream.Size);

 aInStream.Position := 0;
 aInStream.ReadBuffer(lIn[1], aInStream.Size);

 //assign const vector
 lAES.IV := CIV;
 //decrypt TBytes
 lOut := lAES.DecryptPKCS7(lIn, False);

 //copy decrypted RawByteString to aOutStream
 aOutStream.Write(lOut[1], Length(lOut));
 finally
 lAES.Free;
 end;
end;

//simple wrapper on crypt method which only passes arguments to crypt method
procedure streamCryptWrapper(const aInStream, aOutStream: TStream; const aPassword: TBytes);
begin
  AESstreamCrypt(TAESCBC, aInStream, aOutStream, aPassword);
end;

//simple wrapper on decrypt method which only passes arguments to decrypt method
procedure streamDecryptWrapper(const aInStream, aOutStream: TStream; const aPassword: TBytes);
begin
  AESstreamDecrypt(TAESCBC, aInStream, aOutStream, aPassword);
end;

procedure SelfTest;
var
 decodedString: String;
 InStr, OutStr : TStringStream;
begin
  InStr := TStringStream.Create;
  OutStr := TStringStream.Create;
  try

  // TEST 1 ------------------------------------------------------------------
  InStr.Clear;
  OutStr.Clear;

  //put string into stream
  InStr.WriteString(CInputString);

  // crypt stream InStr -> OutStr
  AESstreamCrypt(TAESCBC, InStr, OutStr, CPassword);

  //decrypt stream OutStr -> InStr
  InStr.Clear;
  AESstreamDecrypt(TAESCBC, OutStr, InStr, CPassword);

  //check decoded string
  decodedString := InStr.DataString;
  Assert(decodedString = CInputString);
  // TEST 1 PASSED
  // end of TEST 1 -----------------------------------------------------------

  // -------------------------------------------------------------------------
  // TEST 2 with simple wrapper -  cause exception!
  InStr.Clear;
  OutStr.Clear;

  //put string into stream
  InStr.WriteString(CInputString);

  // crypt stream InStr -> OutStr
  streamCryptWrapper(InStr, OutStr, CPassword);

  // decrypt stream OutStr -> InStr
  InStr.Clear;
  streamDecryptWrapper(OutStr, InStr, CPassword); // <--- ESynCrypto exception: TAESCBC.DecryptPKCS7: Invalid content, why??

  //check decoded string
  decodedString := InStr.DataString;
  Assert(decodedString = CInputString);
  // end of TEST 2 -----------------------------------------------------------
  finally
  InStr.Free;
  OutStr.Free;
  end;
end;


begin
  try
   SelfTest;
  except
    on E: ESynCrypto do
      Writeln('ESynCrypto: ', E.Message); //TAESCBC.DecryptPKCS7: Invalid content !!!
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

...and thanks for time.


The main problem is a bug when I use wrappers, I don't know why :-(

#170 Re: Other components » SynCrypto - strange exception in decrypt AES » 2016-08-11 11:35:03

FixInsight show warnings on SynCrypto, maybe unimportant, but...

[FixInsight Warning] SynCrypto.pas(6734): W517 Variable 'iv' hides a class field, method or property
[FixInsight Warning] SynCrypto.pas(6770): W517 Variable 'iv' hides a class field, method or property
[FixInsight Warning] SynCrypto.pas(6784): W517 Variable 'iv' hides a class field, method or property
[FixInsight Warning] SynCrypto.pas(5062): W521 Return value of function 'TAESFull.EncodeDecode' might be undefined

#171 Re: Other components » SynCrypto - strange exception in decrypt AES » 2016-08-05 22:22:11

I add some comments:

program Project2;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.Classes,
  SynCrypto;

//helper function to convert ansi string to TBytes
function convertSB (const arg: AnsiString): TBytes;
var
   i: integer;
begin
  Setlength(Result, Length(arg));
   for i := 0 to length(arg) - 1 do
   begin
      result[i] := ord (arg [i + 1]);
   end;
end;

//function to encrypt aInStream used aPassword and aAESClass, result is saved to aOutStream
function AESstreamCrypt(aAESClass: TAESAbstractClass; const aInStream, aOutStream: TStream; const aPassword: TBytes): Integer;
var
 aKeySize: Integer;
 lAES : TAESAbstract;
 lBytesIn : TBytes;
 lBytesOut : TBytes;
begin
 //get AES key size
 aKeySize := Length(aPassword) shl 3;

 //create an AES class object to encrypt stream
 lAES := aAESClass.Create(aPassword, aKeySize);
 try

 //copy aInStream to TBytes local variable
 SetLength(lBytesIn, aInStream.Size);
 aInStream.Position := 0;
 aInStream.ReadBuffer(lBytesIn[0], aInStream.Size);

 //encrypt TBytes
 lBytesOut := lAES.EncryptPKCS7(lBytesIn, True);
 Result := Length(lBytesOut);

 //copy encrypted TBytes to aOutStream
 aOutStream.Write(lBytesOut[0], Length(lBytesOut));
 finally
 lAES.Free;
 end;
end;

//function to decrypt aInStream used aPassword and aEASClass, result is saved to aOutStream
function AESstreamDecrypt(aAESClass: TAESAbstractClass; aInStream, aOutStream: TStream; const aPassword: TBytes):
    Integer;
var
 aKeySize: Integer;
 lAES : TAESAbstract;
 lBytesIn : TBytes;
 lBytesOut : TBytes;
begin
 //get AES key size
 aKeySize := Length(aPassword) shl 3;

 //create AES class object to decrypt stream
 lAES := aAESClass.Create(aPassword, aKeySize);
 try
 //copy aInStream to TBytes local variable
 SetLength(lBytesIn, aInStream.Size);
 aInStream.Position := 0;
 aInStream.ReadBuffer(lBytesIn[0], aInStream.Size);

 //decrypt TBytes
 lBytesOut := lAES.DecryptPKCS7(lBytesIn, True);
 Result := Length(lBytesOut);

 //copy decrypted TBytes to aOutStream
 aOutStream.Write(lBytesOut[0], Length(lBytesOut));
 finally
 lAES.Free;
 end;
end;

//simple wrapper for AESstreamCrypt function
procedure streamCryptWrapper(const aInStream, aOutStream: TStream; const aPassword: TBytes);
begin
  AESstreamCrypt(TAESCBC, aInStream, aOutStream, aPassword);
end;

//simple wrapper for AESstreamDecrypt function
procedure streamDecryptWrapper(const aInStream, aOutStream: TStream; const aPassword: TBytes);
begin
  AESstreamDecrypt(TAESCBC, aInStream, aOutStream, aPassword);
end;

//test direct crypt and wrapped crypt
procedure SelfTest;
var
 decodedString: String;
 inputString: string;
 InStr, OutStr : TMemoryStream;
 InputStringStream : TStringStream;
 lInStrStream, lOutStrStream : TStringStream;
 lPasswordBytes: TBytes;
begin
  inputString := 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque hendrerit augue quis lacus efficitur,' +
          ' sollicitudin tempor sapien dapibus. Vivamus quis neque congue, imperdiet nisi nec, hendrerit nulla.' +
          ' Ut quis dolor eget sapien sodales faucibus vel at turpis. Aenean sed varius arcu.';
  lPasswordBytes := convertSB('01234567890123456789012345678901');
  InStr := TMemoryStream.Create;
  OutStr := TMemoryStream.Create;
  InputStringStream := TStringStream.Create(inputString, TEncoding.Unicode);
  try

  // -------------------------------------------------------------------------
  // TEST 1 - use direct AESstreamCrypt and AESstreamDecrypt functions
  InStr.Clear;
  OutStr.Clear;
  InStr.CopyFrom(InputStringStream, 0);
  InStr.Position := 0;
  // crypt
  AESstreamCrypt(TAESCBC, InStr, OutStr, lPasswordBytes);
  //decrypt
  InStr.Clear;
  AESstreamDecrypt(TAESCBC, OutStr, InStr, lPasswordBytes);
  decodedString := 'empty';
  decodedString := Copy(PChar(InStr.Memory), 1, Length(inputString));
  Assert(decodedString = inputString);
  // TEST 1 PASSED

  // -------------------------------------------------------------------------
  // TEST 2 with wrappers streamCryptWrapper and streamDecryptWrapper
  InStr.Clear;
  OutStr.Clear;
  InStr.CopyFrom(InputStringStream, 0);
  InStr.Position := 0;
  // crypt
  streamCryptWrapper(InStr, OutStr, lPasswordBytes);

  InStr.Clear;
  // decrypt
  streamDecryptWrapper(OutStr, InStr, lPasswordBytes);  //   <--- ESynCrypto exception: TAESCBC.DecryptPKCS7: Invalid content
  decodedString := 'pustka';
  InStr.Position := 0;
  decodedString := Copy(PChar(InStr.Memory), 1, Length(inputString));
  Assert(decodedString = inputString);
  finally
  InStr.Free;
  OutStr.Free;
  InputStringStream.Free;
  end;
end;


begin
  try
   SelfTest;
  except
    on E: ESynCrypto do
      Writeln('ESynCrypto: ', E.Message);
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

#172 Re: Other components » SynCrypto - strange exception in decrypt AES » 2016-07-29 15:26:43

And nothing? Nobody helps me out? Please check my code :-(

#173 Other components » SynCrypto - strange exception in decrypt AES » 2016-07-25 11:34:47

jaclas
Replies: 7

Please see example code (simple console project, please copy and save as Project2.dpr and run):

program Project2;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.Classes,
  SynCrypto;

function convertSB (const arg: AnsiString): TBytes;
var
   i: integer;
begin
  Setlength(Result, Length(arg));
   for i := 0 to length(arg) - 1 do
   begin
      result[i] := ord (arg [i + 1]);
   end;
end;

function EASstreamCrypt(aEASClass: TAESAbstractClass; const aInStream, aOutStream: TStream; const aPassword: TBytes): Integer;
var
 aKeySize: Integer;
 lAES : TAESAbstract;
 lBytesIn : TBytes;
 lBytesOut : TBytes;
begin
 aKeySize := Length(aPassword) shl 3;
 Assert((aKeySize = 128) or (aKeySize = 192) or (aKeySize = 256));
 lAES := aEASClass.Create(aPassword, aKeySize);
 try
 SetLength(lBytesIn, aInStream.Size);
 aInStream.Position := 0;
 aInStream.ReadBuffer(lBytesIn[0], aInStream.Size);
 lBytesOut := lAES.EncryptPKCS7(lBytesIn, True);
 Result := Length(lBytesOut);
 aOutStream.Write(lBytesOut[0], Length(lBytesOut));
 finally
 lAES.Free;
 end;
end;

function EASstreamDecrypt(aEASClass: TAESAbstractClass; aInStream, aOutStream: TStream; const aPassword: TBytes):
    Integer;
var
 aKeySize: Integer;
 lAES : TAESAbstract;
 lBytesIn : TBytes;
 lBytesOut : TBytes;
begin
 aKeySize := Length(aPassword) shl 3;
 Assert((aKeySize = 128) or (aKeySize = 192) or (aKeySize = 256));
 lAES := aEASClass.Create(aPassword, aKeySize);
 try
 SetLength(lBytesIn, aInStream.Size);
 aInStream.Position := 0;
 aInStream.ReadBuffer(lBytesIn[0], aInStream.Size);
 lBytesOut := lAES.DecryptPKCS7(lBytesIn, True);
 Result := Length(lBytesOut);
 aOutStream.Write(lBytesOut[0], Length(lBytesOut));
 finally
 lAES.Free;
 end;
end;

procedure streamCryptWrapper(const aInStream, aOutStream: TStream; const aPassword: TBytes);
begin
  EASstreamCrypt(TAESCBC, aInStream, aOutStream, aPassword);
end;

procedure streamDecryptWrapper(const aInStream, aOutStream: TStream; const aPassword: TBytes);
begin
   EASstreamDecrypt(TAESCBC, aInStream, aOutStream, aPassword);
end;

procedure SelfTest;
var
 decodedString: String;
 inputString: string;
 InStr, OutStr : TMemoryStream;
 InputStringStream : TStringStream;
 lInStrStream, lOutStrStream : TStringStream;
 lPasswordBytes: TBytes;
begin
  inputString := 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque hendrerit augue quis lacus efficitur,' +
          ' sollicitudin tempor sapien dapibus. Vivamus quis neque congue, imperdiet nisi nec, hendrerit nulla.' +
          ' Ut quis dolor eget sapien sodales faucibus vel at turpis. Aenean sed varius arcu.';
  lPasswordBytes := convertSB('01234567890123456789012345678901');
  InStr := TMemoryStream.Create;
  OutStr := TMemoryStream.Create;
  InputStringStream := TStringStream.Create(inputString, TEncoding.Unicode);
  try

  // -------------------------------------------------------------------------
  // TEST 1
  InStr.Clear;
  OutStr.Clear;
  InStr.CopyFrom(InputStringStream, 0);
  InStr.Position := 0;
  // crypt
  EASstreamCrypt(TAESCBC, InStr, OutStr, lPasswordBytes);
  //decrypt
  InStr.Clear;
  EASstreamDecrypt(TAESCBC, OutStr, InStr, lPasswordBytes);
  decodedString := 'empty';
  decodedString := Copy(PChar(InStr.Memory), 1, Length(inputString));
  Assert(decodedString = inputString);
  // TEST 1 PASSED

  // -------------------------------------------------------------------------
  // TEST 2 with simple wrapper
  InStr.Clear;
  OutStr.Clear;
  InStr.CopyFrom(InputStringStream, 0);
  InStr.Position := 0;
  // crypt
  streamCryptWrapper(InStr, OutStr, lPasswordBytes);

  InStr.Clear;
  // decrypt
  streamDecryptWrapper(OutStr, InStr, lPasswordBytes);  //   <--- ESynCrypto exception: TAESCBC.DecryptPKCS7: Invalid content
  decodedString := 'pustka';
  InStr.Position := 0;
  decodedString := Copy(PChar(InStr.Memory), 1, Length(inputString));
  Assert(decodedString = inputString);
  finally
  InStr.Free;
  OutStr.Free;
  InputStringStream.Free;
  end;
end;


begin
  try
   SelfTest;
  except
    on E: ESynCrypto do
      Writeln('ESynCrypto: ', E.Message);
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

This line raise exception:

  streamDecryptWrapper(OutStr, InStr, lPasswordBytes);  //   <--- ESynCrypto exception: TAESCBC.DecryptPKCS7: Invalid content

The code performs two tests, the first test is done by directly calling functions:

EASstreamCrypt / EASstreamDecrypt

a second test calls a very simple wrappers:

streamCryptWrapper / streamDecryptWrapper

procedure streamCryptWrapper(const aInStream, aOutStream: TStream; const aPassword: TBytes);
begin
  EASstreamCrypt(TAESCBC, aInStream, aOutStream, aPassword);
end;

...and I get exception, but I don't understand why sad

I was looking for a problem a few hours, please help me. Thanks.

#174 mORMot 1 » Port in use » 2016-06-10 07:04:59

jaclas
Replies: 4

How check that port is already in use when creating a server TSQLHttpServer (http.sys)?

#175 Re: mORMot 1 » How to intercept call the methods of interface based service? » 2016-01-31 14:42:44

Thanks again :-)
But... I well understand?
You're suggesting that I should use method AddInterceptor() RATHER than events OnBeforeURI and OnAfterURI? Because it looks that these solutions are interchangeable. That you mean?
I ask, because variety of solutions now surprised me :-)

best regards

#176 Re: mORMot 1 » How to intercept call the methods of interface based service? » 2016-01-29 09:11:40

Thx for information.

I don't want to use hardcoded magic value, because it is dangerous (length SERVICE_PSEUDO_METHOD can change).
Can you add public function or class method:

function ServicePseudoMethodCount : Integer;
begin
 result := Length(SERVICE_PSEUDO_METHOD);
end;

And I refresh my previous question:

How to get the value of any parameter?

I tried various tricks, but without effect hmm

#177 Re: mORMot 1 » How to intercept call the methods of interface based service? » 2016-01-28 20:06:10

Oh my god ... this is deeply buried :-)

It's OK? :

 sm := Ctxt.Service.InterfaceFactory.Methods[Ctxt.ServiceMethodIndex];

And how to get the value of any parameter?

#178 Re: mORMot 1 » How to intercept call the methods of interface based service? » 2016-01-28 19:23:28

I don't understand :-(
ServiceMethodIndex points to some array/list of methods? Where is this array/list?
Why ServiceParameters is nil in OnBeforeURI()?

jMF1PI99.png

Invoked method has 3 parameters.

#179 Re: mORMot 1 » How to intercept call the methods of interface based service? » 2016-01-28 14:10:16

Thanks for fast fix.

But, I still have one small problem. You wrote in the documentation:

    /// event trigerred when URI() starts to process a request
    // - the supplied Ctxt parameter would give access to the command about to
    // be executed, e.g. Ctxt.Command=execSOAByInterface would identify a SOA
    // service execution, with the corresponding Service and ServiceMethodIndex
    // parameters as set by TSQLRestServerURIContext.URIDecodeSOAByInterface   <--- this method not exist in class
    // - should return TRUE if the method can be executed
    // - should return FALSE if the method should not be executed, and set the
    // corresponding error to the supplied context e.g.
    // ! Ctxt.Error('Unauthorized method',HTML_NOTALLOWED);
    // - since this callback would be executed during all TSQLRestServer.URI,
    // it should better not make any slow process (like writing to a remote DB)
    OnBeforeURI: TNotifyBeforeURI;

but I can't find this method. But nevermind, my question:

How can I find out what method and what parameters is called by client?
How get it from Ctxt: TSQLRestServerURIContext?

#180 Re: mORMot 1 » How to intercept call the methods of interface based service? » 2016-01-28 11:59:09

Hello,

I'm starting to use these events and came across a minor oversight ;-)

  TNotifyBeforeURI = function(Ctxt: TSQLRestServerURIContext): boolean;
  TNotifyAfterURI = procedure(Ctxt: TSQLRestServerURIContext);
  TNotifyErrorURI = function(Ctxt: TSQLRestServerURIContext; E: Exception): boolean;

Can you add at the end "of object"? :-)

Thx and regards

#181 Re: mORMot 1 » Minor inconvenience :-) » 2016-01-26 15:19:41

I know, but these solutions are ... unsightly, dangerous, introduce depending on the source code order - this is not good.
I did alias on type PTypeInfo and I use that alias. Tough luck, let it be :-)

#182 Re: mORMot 1 » Minor inconvenience :-) » 2016-01-26 13:30:45

PTypeInfo is defined in System.TypInfo.pas - and we return to the starting point :-)

#183 Re: mORMot 1 » Minor inconvenience :-) » 2016-01-26 13:11:12

Ok, that was a bad example,  I think about something like this:

var p : PTypeInfo;
...
g := GetTypeData(p).Guid;

But using mORMot RTTI creates a new problems. In other place of my code I use a System.Rtti.pas. Using it forces me to use native type PTypeInfo.
I must unfortunately abandon the use of incompatible PTypeInfo from mORMot and do some workaround sad

#184 Re: mORMot 1 » Minor inconvenience :-) » 2016-01-25 22:17:53

For example, how to replace this code?

g := GetTypeData(TypeInfo(IMyInterface)).Guid;

#185 Re: mORMot 1 » Minor inconvenience :-) » 2016-01-25 19:02:36

This unfortunately does not solve the problem, because mORMot.pas does not have the PTypeData type (and additional functions like GetTypeData()), which forces me to use TypInfo - so the problem returns sad

#186 Re: mORMot 1 » Minor inconvenience :-) » 2016-01-25 18:40:06

SynCommons.PTypeInfo is in implementation section of unit, private.

#187 mORMot 1 » Minor inconvenience :-) » 2016-01-25 17:50:26

jaclas
Replies: 13

Hi,

Unit mORMot.pas has a defined type PTypeInfo. It is incompatible with the Delphi native type PTypeInfo. For this reason I have often errors when compiling my own code where I use both mORMot.pas and TypInfo.pas units.

Is it possible to change the name of this type in mORMot, for example to PMTypeInfo?

kind regards

#189 Re: mORMot 1 » How to intercept call the methods of interface based service? » 2016-01-19 19:51:59

Yes, I check OnMethodExecute, but it's not enough.
I need:
- perform the measurement of the execution time of my methods and monitor the load of threads
- at the end of execute each service method I need to call a procedure notifying about who called the method (this procedure creates a data packet and puts it into the processing queue - it is kind of billing)

The service method interceptor would be ideal solution. And I know that you could do it quite easily ;-)

#190 Re: mORMot 1 » How to intercept call the methods of interface based service? » 2016-01-19 14:28:56

I do not use mORMot tables, an entire layer of DB I'm doing in my own code.
I would just access to BeforeExecute and AfterExecute events for the called service method.

#191 mORMot 1 » How to intercept call the methods of interface based service? » 2016-01-19 12:40:48

jaclas
Replies: 20

Hi,

I wanted to use Spring4D to use "virtual methods interceptor" (Nick Hodges presents it here https://www.youtube.com/watch?v=bjVKtac6bAY).
However, it failed, mORMot rejected my interface as incompatible with class (TInterfaceProxy from Spring4D, he is right).

Question:

Is there a way to intercept each method invocation (in interface based service) before and after the execution (on server side)?

#192 Re: mORMot 1 » Memory manager - what? » 2015-10-29 21:18:58

But in my test environment with ScaleMM I get 3200 req/s and with FastMM only 2700 req/s. Difference is large.
RAM occupancy does not bother me, I care about performance.
Are there any other good memory managers?

#193 mORMot 1 » Memory manager - what? » 2015-10-29 18:58:39

jaclas
Replies: 3

Hi all,

What memory manager do you use in production servers that are to be heavily loaded on multiple threads?
FastMM is the bottleneck, ScaleMM is unstable (AV) SapMM is also unstable.
Are there other options worth considering?

#194 Re: mORMot 1 » Growing amount of the memory used on server » 2015-10-18 20:40:09

However, the problem was in my code. But it was not a memory leak, but the uncontrolled growth of data structures.
Now all is good.
Sorry for confusion.

best regards

#195 Re: mORMot 1 » Growing amount of the memory used on server » 2015-10-11 20:28:21

I access to Firebird by FireDAC. I use Delphi 10 Seattle.
I made simple app that have only REST layer (like in my app) and ...memory allocations not grow.
Now I search for reason in my code... but this is very uphill job.

#196 Re: mORMot 1 » Growing amount of the memory used on server » 2015-10-11 08:36:45

I do not use any SynDB unit. Operations on DB are performed outside mORMot (in my code).
But for testing purpose I gave Exit instruction in first line of REST service method. Now the server receive only "empty" requests and do nothing. But memory allocation still slow grows. What could be causing this?

#197 Re: mORMot 1 » Growing amount of the memory used on server » 2015-10-10 20:30:51

Hi,

I have the same problem, the server eats more and more memory. But I do not use ORM, only alone REST module. I connect several clients who perform ca 20 request per second ...and memory grows a few kilobytes on a few seconds. Without end.
It does not look good :-(

best regards

#198 Re: mORMot 1 » Logger and skip expected exceptions » 2015-09-20 16:28:00

I found in sources "IgnoreException" string only once in SynBidirSock.pas:

    /// low level WebSockets framing protocol
    function GetFrame(out Frame: TWebSocketFrame; TimeOut: cardinal; IgnoreExceptions: boolean): boolean;

#199 mORMot 1 » Logger and skip expected exceptions » 2015-09-20 16:09:14

jaclas
Replies: 3

Hi,

When I configure the logger with sllException level:

with TSQLLog.Family to
   begin
   Level: = [sllInfo, sllWarning, sllError, sllLastError, sllExceptionOS, sllException];
   end;

then mORMot will capture any exceptions that appear in applications (and in threads, this is very good!) and store them in the log. Even these that are caught in a try ... except. However, sometimes very useful it would be the ability to bypass the known and expected exception types.

Did you could add to logger opportunity to register exception classes, which will skipped in the log?

   with TSQLLog.Family to
   begin
   Level: = [sllInfo, sllWarning, sllError, sllLastError, sllExceptionOS, sllException];
   RegisterExpectedException(EMyException);
   RegisterExpectedException(EMyOtherException);
   end;

Thanks :-)

#200 mORMot 1 » Method params type restriction » 2015-06-11 09:51:44

jaclas
Replies: 4

When I register the service with a method that contains a parameter of type UInt16 (Word):

procedure RemoveValue(const aAPIKey: RawUTF8; aIdValue: UInt16);

I get the error:

"TInterfaceFactoryRTTI.Create:
IAdministrationService.RemoveValue "aIdValue" parameter has unexpected type Word - use integer / cardinal instead "

Why I can not use a type of 16-bit?

--
kind regards

Board footer

Powered by FluxBB