Jump to content

ertank

Members
  • Content Count

    233
  • Joined

  • Last visited

Posts posted by ertank


  1. Since you try to display an XML in a Memo control, I presume you are using considerable sized XML files and do not need things like coloring/styling. You can use a code like below to "pretty print" your XML and display it in a Memo object.

    uses
      Xml.xmldom,
      Xml.XMLIntf, // Interface
      Xml.XMLDoc;  // TXMLDocument, FormatXMLData()
    
    procedure TForm1.Button1Click(Sender: TObject);
    var
      LXML: IXMLDocument;
    begin
      LXML := NewXMLDocument();
      LXML.LoadFromXML('<?xml version="1.0" encoding="UTF-8"?><some_node><another_node>node value</another_node></some_node>');
      LXML.XML.Text := FormatXMLData(LXML.XML.Text);
      Memo1.Text := LXML.XML.Text;
    end;

    Documentation says about TMemo "Under Win 9x, there is a limit of 64k of text for this control"


  2. 10 hours ago, PeterPanettone said:

    Thanks for all the answers. I was hoping that an existing addon like GExperts or MMX would provide that feature. As it is very easy to write such a tool (and I am not a night worker), I will do it tomorrow.

    Another alternative might be to use a text editor that can format your HTML and add quotes (possibly with the help of regex)

    Notepad++ https://notepad-plus-plus.org/downloads/

    CudaText https://cudatext.github.io

    TextEditorPro https://texteditor.pro

    SublimeText https://www.sublimetext.com


  3. 22 hours ago, Fuandi said:

    Hi, I need to do base64 decoding then decrypt the result with aes256

     

    I managed to do it in linux, this is the command

    printf "<encrypted string>" | base64 -d | gpg --no-options --batch --cipher-algo AES256 --passphrase "<client secret>" --decrypt

     

    How to do this with delphi ? Anyone can help me ?

    I am not good at such cryptographic coding. My limited knowledge, you will probably need to know "mode of operation"

    https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation

     

    I do not see any initialization vector (IV) information in your example so that might suggest you need ECB, but that is something you should clarify.

     

    I personally like CryptoLib4Pascal. Multi platform support (Lazarus, FMX, VCL, x64). Contains lots of features. Also includes Base64 routines. You will need to get codes from all three links below

    https://github.com/Xor-el/CryptoLib4Pascal

    https://github.com/Xor-el/HashLib4Pascal

    https://github.com/Xor-el/SimpleBaseLib4Pascal

     

    Sample AESCBC256 encrypt/decrypt code would look like as following. (AES128 or AES256 is auto determined by the length of Key parameter). You can take it as starting point and modify to your needs.

    uses
      ClpIBufferedCipher,
      ClpCipherUtilities,
      ClpIParametersWithIV,
      ClpParametersWithIV,
      ClpParameterUtilities,
      ClpEncoders,
      ClpSecureRandom,
      ClpISecureRandom;
    
    
    function EncryptAES(const Key, IV: TBytes; const PlainText: string; out CryptBase64Text: string): Boolean;
    var
      Cipher: IBufferedCipher;
      KeyParametersWithIV: IParametersWithIV;
      Buf: TBytes;
      CryptBytes: TBytes;
    begin
      try
        Cipher := TCipherUtilities.GetCipher('AES/CBC/PKCS7PADDING');
        KeyParametersWithIV := TParametersWithIV.Create(TParameterUtilities.CreateKeyParameter('AES', Key), IV);
        Cipher.Init(True, KeyParametersWithIV); // init encryption cipher
        Buf := TEncoding.ANSI.GetBytes(PlainText);
        CryptBytes := Cipher.DoFinal(Buf);
        CryptBase64Text := TBase64.Encode(CryptBytes);
      except
        Exit(False);
      end;
      Result := True;
    end;
    
    function DecryptAES(const Key, IV: TBytes; const CryptBase64Text: string; out PlainText: string): Boolean;
    var
      Cipher: IBufferedCipher;
      KeyParametersWithIV: IParametersWithIV;
      Buf: TBytes;
      PlainBytes: TBytes;
    begin
      try
        Cipher := TCipherUtilities.GetCipher('AES/CBC/PKCS7PADDING');
        KeyParametersWithIV := TParametersWithIV.Create(TParameterUtilities.CreateKeyParameter('AES', Key), IV);
        Cipher.Init(False, KeyParametersWithIV); // init decryption cipher
        Buf := TBase64.Decode(CryptBase64Text);
        PlainBytes := Cipher.DoFinal(Buf);
        PlainText := TEncoding.ANSI.GetString(PlainBytes);
      except
        Exit(False);
      end;
      Result := True;
    end;

     


  4. Hello,

     

    I normally use UniDAC with MARS. This time, I have to use FireDAC and I am not used to FireDAC at all.

     

    I checked MARS demo applications to prepare my INI file as below:

    [DefaultEngine]
    Port=8085
    ThreadPoolSize=100
    
    FireDAC.MAIN_DB.DriverID=FB
    FireDAC.MAIN_DB.Database="D:\rest_server\SAMPLE.FDB"
    FireDAC.MAIN_DB.User_Name=SYSDBA
    FireDAC.MAIN_DB.Password=mypassword
    FireDAC.MAIN_DB.Protocol=TCPIP
    FireDAC.MAIN_DB.Server=localhost
    FireDAC.MAIN_DB.Pooled=True
    FireDAC.MAIN_DB.POOL_MaximumItems=100
    FireDAC.MAIN_DB.TxOptions.Isolation=xiReadCommitted
    

    When server tries to establish a database connection, client receives below error:

    Internal server error: [EFDException] [FireDAC][Stan][Def]-254. Definition [MAIN_DB] is not found in []

    Server EXE is built as a windows service application. Fbclient.dll file with correct bitness and version is in the same directory as my EXE file.

     

    I have following in my code to make sure MARS uses certain definition in INI file.

      [Connection('MAIN_DB'), Path('token')]
      TTokenResource = class(TMARSTokenResource)

     

    Any help is appreciated.

     

    Thanks & Regards,

    Ertan 


  5. Hello,

     

    There is an application that consumes a SOAP web service. From time to time this web service is not stable and sending various html error messages instead of a valid response.

     

    Using Delphi 10.4.2 I would like to read incoming html data and display this to the user. Currently, all we can display is "Received content of invalid Content-Type setting: text/html - SOAP expect "text/xml" error message.

     

    I have searched the internet. Someone suggested to modify Soap.SOAPHTTPTrans.THTTPReqResp.CheckContentType and prevent it from raising an exception but this does not sound like a decent solution and might cause other troubles with other applications using SOAP. What I am after is a solution to be used just with this specific application of ours.

     

    I wonder if there is an alternative solution that can be used.

     

    Thanks & Regards,

    Ertan


  6. 2 hours ago, Martin Sedgewick said:

    I would first focus on why LInvoice.DataFields.FieldByName('ARP-CODE') seems to be NIL

    It is a shame that I did not see that at all. Changing into ARP_CODE and there is no access violation on that line. Thanks.

    However, when I try to post an invoice, now I get "Catastrophic failure" error. Below is the final state of my test code. It works down to LInvoice.Post()

    I compared code with C# working code. Price, Code, quantity etc assigned are identical. They are test values anyway.

      LInvoice := FComConnection.NewDataObject(doSalesInvoice);
      try
        LInvoice.New();
        LInvoice.DataFields.FieldByName('TYPE').Value := 8;
        LInvoice.DataFields.FieldByName('NUMBER').Value := '~';
        LInvoice.DataFields.FieldByName('DATE').Value := '29.01.2022';
        FComConnection.PackTime(12, 12, 12, LTime);
        LInvoice.DataFields.FieldByName('TIME').Value := LTime;
        LInvoice.DataFields.FieldByName('ARP_CODE').Value := '320.01.002';
        LInvoiceLines := LInvoice.DataFields.FieldByName('TRANSACTIONS').Lines;
        LInvoiceLines.AppendLine();
        LInvoiceLines[I].FieldByName('TYPE').Value := 0;
        LInvoiceLines[I].FieldByName('MASTER_CODE').Value := 'M.01.003';
        LInvoiceLines[I].FieldByName('QUANTITY').Value := 5.5 + I;
        LInvoiceLines[I].FieldByName('PRICE').Value := 3.5 + I;
        LInvoiceLines[I].FieldByName('VAT_RATE').Value := 8;
        LInvoiceLines[I].FieldByName('UNIT_CODE').Value := 'KG';
        if not LInvoice.Post() then  // <--- Here Catastrophic failure
        begin
          if LInvoice.ErrorCode <> 0 then
          begin
            FLog.LogError('Cannot post invoice: ' + IntToStr(LInvoice.ErrorCode) + ', ' + LInvoice.ErrorDesc);
            Exit();
          end;
        end;
        FLog.LogInfo('Internal reference: ' + LInvoice.DataFields.FieldByName('INTERNAL_REFERENCE').Value);

    Code is actually in try..except block, "Catastrophic error" is catched in except and logged. But I did not include it here

    2 hours ago, Martin Sedgewick said:

    is IQuery the interface from the COM library? how is the COM interface look in the TLB.pas file? is it a function with no parameters?

    IQuery is an interface from the COM library, yes. Below part is what I see in TLB file for IQuery. I can share whole TLB it in private message if you would like to look at different parts of it. It is almost 10k lines.

    // Initial definition
    IQuery = interface;
      
    // another line
    Query = IQuery;
    
    // function definition inside COM main interface
    function NewQuery: IQuery; safecall;
    
    
    // *********************************************************************//
    // Interface: IQuery
    // Flags:     (4416) Dual OleAutomation Dispatchable
    // GUID:      {3A1DB335-35DB-463B-AF5C-6BA2B143E65A}
    // *********************************************************************//
      IQuery = interface(IDispatch)
        ['{3A1DB335-35DB-463B-AF5C-6BA2B143E65A}']
        function Get_name: WideString; safecall;
        procedure Set_name(const Value: WideString); safecall;
        function Get_Statement: WideString; safecall;
        procedure Set_Statement(const Value: WideString); safecall;
        function Get_Error: Integer; safecall;
        function Get_QueryFields: IQueryFields; safecall;
        function FieldByName(const fieldName: WideString): IQueryField; safecall;
        function Execute: WordBool; safecall;
        function OpenDirect: WordBool; safecall;
        procedure Close; safecall;
        function First: WordBool; safecall;
        function Next: WordBool; safecall;
        function Previous: WordBool; safecall;
        function Last: WordBool; safecall;
        function Get_SQLClause: ISQLClause; safecall;
        function GetDateString(ADate: TDateTime): WideString; safecall;
        function Get_DBErrorDesc: WideString; safecall;
        property name: WideString read Get_name write Set_name;
        property Statement: WideString read Get_Statement write Set_Statement;
        property Error: Integer read Get_Error;
        property QueryFields: IQueryFields read Get_QueryFields;
        property SQLClause: ISQLClause read Get_SQLClause;
        property DBErrorDesc: WideString read Get_DBErrorDesc;
      end;

     

     

    2 hours ago, Martin Sedgewick said:

    I would review all the basics and see there is nothing simple being missed. Is there anything else missing from setting up the FMainConnection that might have it returning a NIL interface? 

    I doubt FMainConnection (now FComConnection) setting is wrong as I can do some other operations using it. Login, Disconnect, GetVersion, LastError, LastErrorString, GetTablename etc. But, it is a fact that I could not see that "hyphen" and "underscore" thing for a couple of days.

     

    Thanks & Regards,

    Ertan


  7. Hello,

     

    I am using Delphi 10.4.2.

     

    There is a type library that can be accessed using COM. I can import it and use some parts like login, disconnect, version. There are other parts to do database operations and it seems Delphi has problems using those parts of it.

     

    1- No interface retrieved

    var
      LQuery: IQuery;
     begin
      LQuery := FMainConnection.NewQuery(); 
      // Here LQuery still remains as nil
     end;

    2- Access Violation

    var
      LInvoice: IData;
      LInvoiceLines: ILines
      ATime: OleVariant;
    begin
      LInvoice := FMainConnection.NewDataObject(doSalesInvoice);
      try
        LInvoice.New();
        LInvoice.DataFields.FieldByName('TYPE').Value := 8;
        LInvoice.DataFields.FieldByName('NUMBER').Value := 'L0129002';
        LInvoice.DataFields.FieldByName('DOC_NUMBER').Value := 'L0129002';
        LInvoice.DataFields.FieldByName('AUXIL_CODE').Value := 'AUTO';
        LInvoice.DataFields.FieldByName('DATE').Value := '29.01.2022';
        FMainConnection.PackTime(12, 12, 12, ATime);
        LInvoice.DataFields.FieldByName('TIME').Value := ATime;
        LInvoice.DataFields.FieldByName('ARP-CODE').Value := '320.01.002'; // Here Access Violation raises
        LInvoiceLines := LInvoice.DataFields.FieldByName('TRANSACTIONS').Lines;

     

    However, If I try all of these using Visual Studio C#.NET, everything works. Since this is COM object, codes on both Visual Studio and Delphi are almost identical.

    Both Delphi and Visual Studio installed on my development computer. They are using same Type Library, same dll files and it is only Delphi fails to use its parts.

     

    I wonder if there is some catch to do with Delphi to fix such problems as I am not experienced much using type libraries. Any help is appreciated.

     

    Thanks & Regards,

    Ertan


  8. On 12/1/2021 at 8:05 PM, Andre Capelli said:

    Sorry, let me elaborate.

    Yes, It's in Delphi, the Backend will receive the JSONs and Insert into the Database. The response time was just in case anyone needed.

     

    But the problem is how I receive that much json and read and insert one per time, or all of them at the same time.

    I only checked Horse framework in the past and do not have deep knowledge about it. It was not to my taste. I like MARS-Curiosity more.

    I do not know how you coded Horse side of the things. I do know for sure that Horse is a multi-threaded framework. You should really check your codes on the Horse side.


  9. 7 hours ago, David Heffernan said:

    What problem are you trying to solve? Are you working with currency for instance? In which case binary floating point is not what you need. 

    These numbers are read from a scale generated barcode for calculating price of a product like cheese. Barcode has weight, unit price and amount of that weight printed in numbers on it. Application was calculating total amount 0.01 wrongly. I was trying to fix that old code to have exact amount displayed on that barcode.

     

    Turns out Currency type is the way to go. I tried it and works correctly on all samples I have. The code otherwise is same including rounding functions.


  10. Hello,

     

    Using Delphi 10.4.2 I get different rounded values using below code. Purpose is to round up and have 13.98 for both.

    uses
      System.Math;
    
    procedure TForm1.Button1Click(Sender: TObject);
    var
      ToBeRounded: Double;
      Rounded: Double;
    begin
      ToBeRounded := 55.9 * 0.25;
      Rounded := SimpleRoundTo(ToBeRounded, -2);
      ShowMessage(ToBeRounded.ToString() + ' ' + Rounded.ToString()); // ToBeRounded is 13.975 and Rounded is 13.97 at this point
      Rounded := SimpleRoundTo(13.975, -2);
      ShowMessage(Rounded.ToString); // Rounded is 13.98 at this point
    end;

    If one reads help file it has following table for expected results

    image.thumb.png.e6c5109c4070f20c33289baf8a28bee1.png

     

    I do not have deep floating point knowledge. I basically know they have a lot more digits than displayed.

     

    My question is, how can I always get 13.98 as result using multiplications and such.

     

    Thanks & Regards,

    Ertan


  11. 22 hours ago, Dave Nottage said:

    Perhaps AndroidManifest.template.xml was modified and the closing quote was removed by mistake?

    That was my mistake. Though, it is still not working even above quote error is fixed. I was thinking, can this be because of new template values of recent Android versions? For example, I think Android 5.0.2 does not have following

    android:usesCleartextTraffic="true"

    Since my test phone has recent versions of Android, I had to add it in order to be able to test the app.


  12. 7 hours ago, Dave Nottage said:

    Are you sure the error doesn't actually say: "..problem parsing the package"? It is important to ensure that error messages you quote are exact, otherwise it may be difficult for others to help.

    It was in Turkish and I did not have access to original message.

     

    7 hours ago, Dave Nottage said:

    In your case, it may be an issue with the manifest (AndroidManifest.xml in the project's output folder). Can you attach it here?

    You can find it attached.

     

    Thanks.

    AndroidManifest.xml


  13. Hello,

     

    I am using Delphi 10.4.2. There is a very simple app (needs internet and network status permissions, 3 pages total) that I need to run on Android 5.0.2.

    I compiled it with stock SDK 25.2.5 targeting Android32. When package tried to be loaded on Android 5.0.2 it says

    Compiler error
    There is a problem with the packet parsing.

    Docwiki says Delphi 10.4.2 supports Android 6 minimum. Even Delphi 10.3.3 supports Android 5.2 mimimum.

     

    I wonder if there is some "workaround" that I can use without installing an older version.

     

    Thanks & Regards,

    Ertan


  14. 3 hours ago, Halil Han Badem said:

    Compare an application with the requests in the test and production version

    Both projects are working on production. There is no test environment.

    3 hours ago, Halil Han Badem said:

    HTTPRio OnBeforeExecute

    I do not have problem "sending" the request. Error is raised when I receive the response. I shared both projects raw response beginnings (taken using Fiddler) to show there is no difference that would result in such an error. However, single SOAP web service project works OK. Double SOAP web service project (this and another web service supported in a single project) raises mentioned error.


  15. One additional information I should add is this main project where I am receiving error is using more than one soap web services.

    Thinking of that it maybe related with that RegisterInterface() or RegisterXSClass() functions used in WSDL generated web service units I tried to switch unit creation. That did not help, too.

    One of the web services returning its envelope as below

    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    	<SOAP-ENV:Header/>
    	<SOAP-ENV:Body>

    Problematic one returning its envelope as below

    <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
    	<env:Header/>
    	<env:Body>

    There is this "SOAP-ENV" and "env" difference. But, they both seem to be defined properly. Moreover, I have no problem using problematic web service in a single project.

     

    Any help is appreciated.

     

    Thanks & Regards,

    Ertan


  16. Hello,

     

    I am using Delphi 10.3.3, targeting Win32 executable.

     

    There is a SOAP web service that I have build a class for it. That class runs just fine on a test project. However, when I put it in my main project, I get below error

    DocumentElement http://schemas.xmlsoap.org/soap/envelope/:Envelope expected, :Envelope found

    I checked, there is only one single unit for this web service in my whole computer and both projects are using that unit.

     

    I have used different SOAP web services in the past. Some of them rarely raise "HTML found" kind of error messages, but never got ":Envelope found" until now. None of my web searches lead me to same error message that I receive.

     

    I have all requests and responses saved in text files. Comparing them I can see no difference. It is only number of records returned changes due to filter parameters. I also used Fiddler Telerik and captured whole response using both test project and main project. They are identical as far as I can tell.

     

    Test project response starts as:

    HTTP/1.1 200 OK
    Content-Type: text/xml;charset=UTF-8
    Connection: keep-alive
    Set-Cookie: JSESSIONIDSSO=529DA436282217EF9D8D9F21515121D3; Path=/; Secure
    Set-Cookie: JSESSIONID=82E5260FE1737AA7C77DCE37D71B7132; Path=/listingapi/ws; Secure
    Server-Timing: intid;desc=d2369e80a9274e5b
    Date: Sun, 06 Jun 2021 19:41:44 GMT
    Vary: Accept-Encoding
    Content-Length: 15213
    <env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
      <env:Header/>
      <env:Body>
        <ns1:getSalesByDateRangeResponse xmlns:ns1='http://sale.individual.ws.listingapi.gg.com'>
          <return>
            <ackCode>success</ackCode>
            <responseTime>06/06/2021 22:41:44</responseTime>
            <timeElapsed>1 ms</timeElapsed>
            <saleCount>11</saleCount>
            <sales>
              <sale>

     

    Main project response starts as:

    HTTP/1.1 200 OK
    Content-Type: text/xml;charset=UTF-8
    Connection: keep-alive
    Set-Cookie: JSESSIONIDSSO=7A2E4B6940B5E0E44F86FF95BBCD6C3D; Path=/; Secure
    Set-Cookie: JSESSIONID=0ED54949FAC10990F8F24B27B9174216; Path=/listingapi/ws; Secure
    Server-Timing: intid;desc=1a968daea7e9c9d9
    Date: Sun, 06 Jun 2021 19:41:17 GMT
    Vary: Accept-Encoding
    Content-Length: 9877
    <env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
      <env:Header/>
      <env:Body>
        <ns1:getSalesByDateRangeResponse xmlns:ns1='http://sale.individual.ws.listingapi.gg.com'>
          <return>
            <ackCode>success</ackCode>
            <responseTime>06/06/2021 22:41:17</responseTime>
            <timeElapsed>225 ms</timeElapsed>
            <saleCount>7</saleCount>
            <sales>
              <sale>

    Web service WSDL can be reached from: https://dev.gittigidiyor.com:8443/listingapi/ws/IndividualSaleService?wsdl

     

    I appreciate any help, please.

     

    Thanks & Regards,

    Ertan


  17. 1 minute ago, Vandrovnik said:

    I am not sure - in the directory C:\Program Files\Firebird\Firebird_2_5\WOW64, I do not have msvcp80.dll and msvcr80.dll (these were used in 2.5.9). I would try to put them there (32bits).

    This is 32Bit client directory for a 64bit installation for FirebirdSQL.

    1 minute ago, Vandrovnik said:

    Also, the application which tries to load fbclient.dll - is it 32bit? That is my "favourite" mistake, mismatch between 32 and 64 bits.

    It is indeed 32bit application. No mistake here.

     

    BTW, if you check the error message in my second post above, it is trying to load a DLL file in another directory (which is EXE directory) and saying file does not exists. Indeed there is no such file with EXE file and I am trying to figure an INI parameter to provide location of that file. If I copy just fbclient.dll file from C:\Program Files\Firebird\Firebird_2_5\WOW64 next to EXE and it works just fine.


  18. Just now, Vandrovnik said:

    fbclient.dll usually depends on other dlls (like msvcp100.dll, msvcr100.dll in FB 3.0), are they present?

    This is FirebirdSQL 2.5.9. File I am putting in INI file is FirebirdSQL installation directory. I suppose anything necessary would be present there. Moreover, there is no problem for other applications to use that identical client DLL file.

     

    I think this can be eliminated from possible reasons in my specific case.


  19. 10 hours ago, c0d3r said:

    Yes. you can as long as fbclient.dll is the right one.

    This is not helping in my case. I get below error which indicates a completely different dll filename

    First chance exception at $775DA8B2. Exception class EFOpenError with message 'Cannot open file "C:\dlp\MARS\Demos\EKON22\bin\fbclient.dll". The system cannot find the file specified'. Process EKON22ServerApplication.exe (13632)

    That directory mentioned in above error is the EXE directory itself. My INI file has lines in my initial post. INI file stays in the same directory as EXE and have same filename with EXE. The MARS Engine is started using below lines. My MARS code base is latest available from GitHub.

    procedure TMainForm.FormCreate(Sender: TObject);
    begin
      FEngine := TMARSEngine.Create();
      try
        FEngine.Parameters.LoadFromIniFile;
        FEngine.AddApplication('DefaultApp', '/default', ['Server.*']);
        PortNumberEdit.Text := IntToStr(FEngine.Port);
        TMARSFireDAC.LoadConnectionDefs(FEngine.Parameters, 'FireDAC');
        StartServerAction.Execute;
        RenderEngines(MainTreeView);
      except
        FreeAndNil(FEngine);
        raise;
      end;
    end;

    If I am missing something, let me know, please.

×