Jump to content

david_navigator

Members
  • Content Count

    144
  • Joined

  • Last visited

Posts posted by david_navigator


  1. On 3/22/2024 at 8:13 PM, Kas Ob. said:

    Yes, this is the only way, also you can make it a DLL, only make sure to not use a shared memory memory manager with the exe.

     

    Use the OS heap API as local memory manager.

    @Kas Ob. could you explain in a little more detail about the memory manager please ? 
     


  2. 4 hours ago, Lajos Juhász said:

    How you are going to know if t is freed or not?

    I was hoping there was something that the OS could deal with. 
    If I made the scripting engine a stand alone EXE then whatever the user wrote, Windows would clean up when the exe closed. I was hoping that there might be some way to achieve that within my app.

    Doing some research I see that Job Objects details "The virtual memory of job objects isolates the memory behavior of a group of processes (tasks) from the rest of the system", but so far little about how this is achieved.


  3. One of my apps uses PascalScript to allow the user to customise various tasks. However as I've recently discovered it's really easy for the end user to write a script that leaks loads of memory. 

    As far as I can see PascalScript doesn't do any kind of memory tidy up when the script ends - it expects the script's author to do that.

    Is there some way to encapsulate the instantiated TPSScript object in such a way that I can free any memory when the script object is freed ?

     

    Something like (in psuedo code)

    Create memory container;
    PSScript:=TPSScript.Create(nil);
    PSScript.Script.Assign(fScript);
    PSScript.Compile;
    PSScript.Execute;
    PSScript.Free;
    Destroy memory container;

     

     


  4. >Are you sure you are supposed to be using implicit TLS on port 143, and not explicit TLS instead?

    If I change the test code above to use 
    explicit then

    TheImap.Connect;

    never returns. Have I missed setting something else or if this just a strange server ?

     

     


  5. [Some time later]

     

    I've now discovered that the IdSSLIOHandlerSocketOpenSSL1 code changes the TIMAP4.port property to 993, even though my server wants 143, so setting

    TheImap.Port := 143;

    after setting the IdSSLIOHandlerSocketOpenSSL1 properties, addresses the issue. 

    Not sure if this is an Indy bug or a misunderstanding of how it should work by me.

     

    Replying to my own question simply because this will no doubt bite me on the bum in 5 years time when I refactor the code !!!

    • Like 1

  6. I have the following fairly simple code to connect to my IMAP server, however I'm doing something wrong, but I can't work out what.

    The first time I click the button, I always get 

    ExceptionMessage="Socket Error # 10061
    Connection refused."
    ExceptionName="EIdSocketError"

    However if I then click on the button again, the IMAP control connects to my server just fine and I can retrieve anything I like without a problem.

     

    I've tried setting various properties in various different orders, but that makes no difference, so why does it not work the first time ?

     

    If I make TheImap &  IdSSLIOHandlerSocketOpenSSL1 local to the button1click procedure, rather than class level, then TheIMAP never connects, so that seems to rule out something external blocking the connection first time round and points to something not being initialized correctly, but what am I missing ?

     

    type
      TForm3 = class(TForm)
        Button1: TButton;
        procedure FormCreate(Sender: TObject);
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
        TheImap: TIdIMAP4;
        IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL;
      public
        { Public declarations }
      end;
    
    var
      Form3: TForm3;
    
    implementation
    
    {$R *.dfm}
    
    procedure TForm3.FormCreate(Sender: TObject);
    begin
      TheImap := TIdIMAP4.Create(nil);
      IdSSLIOHandlerSocketOpenSSL1 := TIdSSLIOHandlerSocketOpenSSL.Create(TheImap);
    end;
    
    procedure TForm3.Button1Click(Sender: TObject);
    
    begin
      if TheImap.connected then TheImap.Disconnect;
    
      TheImap.Host := 'xxxxxxxxx';
      TheImap.Username := 'xxxxxxx';
      TheImap.Password := 'xxxxxxx';
      TheImap.Port := 143;
    
      with IdSSLIOHandlerSocketOpenSSL1 do
      begin
        Destination := format('%s:%d', [TheImap.Host, TheImap.Port]); // e.g 'imap.gmail.com:993';
        Host := TheImap.Host;
        MaxLineAction := maException;
        Port := TheImap.Port;
        DefaultPort := 0;
        SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
        SSLOptions.Mode := sslmUnassigned;
        SSLOptions.VerifyMode := [];
        SSLOptions.VerifyDepth := 0;
      end;
      TheImap.IOHandler := IdSSLIOHandlerSocketOpenSSL1;
    
      TheImap.UseTLS := utUseImplicitTLS;
    
      try
        TheImap.Connect;
      except
        on E: exception do
          showmessage(E.Message);
      end;
      if TheImap.Connected then
        showmessage('Connected ok');
    end;

     


  7. Surprisingly I can't find an answer to my question here or via google (I'm probably asking the wrong question), but what's the best way to obfuscate API secrets in Delphi ?

     

    e.g. My app needs to send email using Office 365, which requires an oAuth2 login. To start the login process I have a client_ID & a client_secret given to me by Microsoft to identify my app. 
    Obviously these need to be stored within the exe but how to hide them such that some (casual) hacker, can't pull them out and pretend to be me ?

     

    Cheers

     

    David


  8. I have some inherited code that does some complex maths using a recursive function (i.e the function calls itself). Last night a customer had a situation where running the routine killed the app. My belief is that the app ran out of stack space due to this routine calling itself multiple times and thus died.

    Is there anyway to detect this is likely to happen so that the code can be aborted with a message instead?

     

    David 


  9. Using Delphi to upload or download from a cloud S3 server, my customers are getting this intermittent error.

     

    exception class    : ENetHTTPClientException
    exception message  : Error sending data: (12030) The connection with the server was terminated abnormally.
    
    thread $2f68:
    01d4096a +126 HireTrackNX.exe System.Net.HttpClient.Win                           TWinHTTPClient.HandleExecuteError
    01d40c76 +2d2 HireTrackNX.exe System.Net.HttpClient.Win                           TWinHTTPClient.DoExecuteRequest
    01d4bda2 +1ea HireTrackNX.exe System.Net.HttpClient                               THTTPClient.ExecuteHTTPInternal
    01d4c080 +008 HireTrackNX.exe System.Net.HttpClient                               THTTPClient.ExecuteHTTP
    01d4b0f2 +0ee HireTrackNX.exe System.Net.HttpClient                               THTTPClient.Execute
    01d4bb05 +04d HireTrackNX.exe System.Net.HttpClient                               THTTPClient.DoExecute
    01d4fe18 +050 HireTrackNX.exe System.Net.HttpClient                               THTTPClient.Put
    022b7f32 +03a HireTrackNX.exe Data.Cloud.CloudAPI                                 TCloudHTTP.Put
    022b77e7 +077 HireTrackNX.exe Data.Cloud.CloudAPI                                 TCloudService.IssuePutRequest

     

    Google seems to suggest it could be a Winsock timeout or a TLS mismatch between the target machine and console machine., but I have no understanding of what that actually means in practical terms - it certainly doesn't seem to be related to the size of the file being transferred.
    Would that be something as simple as a network connection issue between the client & server ? The server's hosting company tell me there's no issue at their end and the user is connecting to the client over RDP, so there can't be an internet issue at their end either.

     

    I'm really looking for any ideas or suggestions on how to either deal with the error better from a user's POV or how to diagnose what the actual cause is and address that.

     

    Usually if the user retries the upload or download process a couple of times, it does eventually work.

     

    Many thanks

     

    David

     


  10. I have some code that I inherited from someone else which is used to convert a dataset to JSON.

     

    Mostly it works OK, but rather than a £ being converted to \u00A3 it gets converted to \\u00A3 i.e the slash gets escaped again.

     

    So from

    "Additional Fuel Used 170 Litres @ £2.00 per Litre"

    rather than 
     "Additional Fuel Used 170 Litres @ \u00A32.00 per Litre"

    I get 

    "Additional Fuel Used 170 Litres @ \\u00A32.00 per Litre"

     

    I've found very similar code in StackOverflow, but that has the same issue. This is the SO code as it's potentially easier to read. 

    Can anyone point out where I/they are going wrong please ?

    As far as I can tell the EscapeValue code is correctly converting the £ to \u00A3, but then the TJSONPair.create seems to be then re-escaping the one '\' in to '\\'

     

    image.png.52b58df173083a62b9c5e022f379e798.png

     

    unit Unit71;
    
    interface
    
    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, dbxjson, json;
    
    type
      TForm71 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    
      type
      TSvJsonString = class(TJSONString)
      private
        function EscapeValue(const AValue: string): string;
      public
        constructor Create(const AValue: string); overload;
      end;
    
    var
      Form71: TForm71;
    
    implementation
    
    {$R *.dfm}
    
    constructor TSvJsonString.Create(const AValue: string);
    begin
      inherited Create(EscapeValue(AValue));
    end;
    
    function TSvJsonString.EscapeValue(const AValue: string): string;
    
      procedure AddChars(const AChars: string; var Dest: string; var AIndex: Integer); inline;
      begin
        System.Insert(AChars, Dest, AIndex);
        System.Delete(Dest, AIndex + 2, 1);
        Inc(AIndex, 2);
      end;
    
      procedure AddUnicodeChars(const AChars: string; var Dest: string; var AIndex: Integer); inline;
      begin
        System.Insert(AChars, Dest, AIndex);
        System.Delete(Dest, AIndex + 6, 1);
        Inc(AIndex, 6);
      end;
    
    var
      i, ix: Integer;
      AChar: Char;
    begin
      Result := AValue;
      ix := 1;
      for i := 1 to System.Length(AValue) do
      begin
        AChar :=  AValue[i];
        case AChar of
          '/', '\', '"':
          begin
            System.Insert('\', Result, ix);
            Inc(ix, 2);
          end;
          #8:  //backspace \b
          begin
            AddChars('\b', Result, ix);
          end;
          #9:
          begin
            AddChars('\t', Result, ix);
          end;
          #10:
          begin
            AddChars('\n', Result, ix);
          end;
          #12:
          begin
            AddChars('\f', Result, ix);
          end;
          #13:
          begin
            AddChars('\r', Result, ix);
          end;
          #0 .. #7, #11, #14 .. #31:
          begin
            AddUnicodeChars('\u' + IntToHex(Word(AChar), 4), Result, ix);
          end
          else
          begin
            if Word(AChar) > 127 then
            begin
              AddUnicodeChars('\u' + IntToHex(Word(AChar), 4), Result, ix);
            end
            else
            begin
              Inc(ix);
            end;
          end;
        end;
      end;
    end;
    
    
    procedure TForm71.Button1Click(Sender: TObject);
    var
      LText, LEscapedText: string;
      LJsonString: TSvJsonString;
      LJsonPair: TJsonPair;
      LJsonObject: TJsonObject;
    begin
      LText := 'The price is £20.00';
      LJsonString := TSvJsonString.Create(LText);
      LJsonPair := TJsonPair.Create('MyString', LJsonString);
      LJsonObject := TJsonObject.Create(LJsonPair);
      try
        LEscapedText := LJsonObject.ToString;
        showmessage(LEscapedText);
        LEscapedText := LJsonObject.ToJSON;
        showmessage(LEscapedText);
      finally
        LJsonObject.Free;
      end;
    end;
    
    end.

     


  11. 1 hour ago, David Schwartz said:

    I've been playig around wiht ChatGPT and am really surprised at how quickly it can generate useful code for specific needs.

    Me too and there's definitely a learning curve in working out what ChatGPT is good at and what it's not.


    Tonight I got it to do, like you, the boring part of writing some class code (I was going to say creating, but I think I'm creating, it's just writing), but I also asked it to write a simple function to remove tags from some HTML to just leave plain text. Even after 8 iterations the code wouldn't still wouldn't compile and even after I'd fixed those issues, the code didn't do what was requested. I'm guessing too many StackOverflow wrong answers have been analysed as code sampled !

     


  12. Something I found it really useful is explaining code that I don't understand.

    For example last week someone sent me a function in Python (a new language for me) which even with the comments I couldn't work out what it was doing.

    I asked ChatGPT to explain the code, and it did, in a way that then meant I could code something in delphi very quickly.

    For example, with your code.

     

    Quote

    This code defines a Delphi unit called "Person", which contains the definition of a class called "TPerson". This class represents a person and has three properties: FirstName, LastName, and Age. The properties are implemented with getter and setter methods that read and write private fields.

    The class also has two methods that are used to convert the person object to and from JSON format. The ToJSON method takes the person object and returns a JSON string that represents the object's properties. The FromJSON method takes a JSON string and creates a new person object with properties that match the values in the JSON string.

    The implementation of the ToJSON method creates a new TJSONObject and adds the person's properties to it as name-value pairs. The method then returns the JSON string representation of the TJSONObject.

    The implementation of the FromJSON method first parses the JSON string into a TJSONObject, and then creates a new TPerson object. The method then sets the properties of the new TPerson object to the values of the corresponding name-value pairs in the TJSONObject.

    The "uses" clause at the top of the unit indicates that the System.SysUtils and System.JSON units are required for this code to compile.



     

     

     


  13. why didn't I think of asking #AI ??

     

    can you explain what this python code does ?
    
    def marsaglia_xorshift_128(x = 123456789, y = 362436069, z = 521288629, w = 88675123):
        while True:
            t = (x ^ (x << 11)) & 0xffffffff
            x, y, z = y, z, w
            w = (w ^ (w >> 19) ^ (t ^ (t >> 8)))
            yield w
    
    This is a Python function that implements the Marsaglia Xorshift 128 random number generator algorithm. The function takes four parameters x, y, z, and w which serve as the seed values for the generator.
    
    The function contains an infinite loop that generates random numbers using the Xorshift 128 algorithm. The loop uses bitwise operations to perform the necessary calculations to generate a new random number on each iteration.
    
    The t variable is calculated by performing a bitwise XOR operation on x shifted left by 11 bits and x, and then taking the result and performing a bitwise AND with the hexadecimal value 0xffffffff. The purpose of this calculation is to produce a new value for t that is used in the calculation of the next random number.
    
    Next, x, y, and z are updated by taking the previous values of y, z, and w. w is then calculated by performing a series of bitwise XOR and right-shift operations.
    
    The yield statement returns the new value of w on each iteration of the loop. This allows the function to be used as a generator that can be used to produce an infinite sequence of random numbers.
    
    Each time the function is called with the same seed values, it will produce the same sequence of random numbers. To get a different sequence, the seed values must be changed.
    
    
    
    

     

    • Like 1

  14. I need to convert some python code to delphi, though my knowledge of python is somewhat thin. I've done most of what's needed but there's a part that I don't really understand.

    starting with _extract, it seems to call marsaglia_xorshift_128 but why does that have a while True & yield - is that so everything is treated as a persistent variable  ?
    Does marsaglia_xorshift_128 effectively get called again for each byte in contents[12:16], from the deobfuscate_string so that w is the value from the "next" iteration ?

    How would I do something similar in delphi ?

     

    def marsaglia_xorshift_128(x = 123456789, y = 362436069, z = 521288629, w = 88675123):
        while True:
            t = (x ^ (x << 11)) & 0xffffffff
            x, y, z = y, z, w
            w = (w ^ (w >> 19) ^ (t ^ (t >> 8)))
            yield w
    
    # The lower 8-bits from the Xorshift PNR are subtracted from byte
    # values during extraction, and added to byte values on insertion.
    # When calling deobfuscate_string() the whole string is processed.
    def deobfuscate_string(pnr, obfuscated, operation=int.__sub__):
        return ''.join([chr((operation(ord(c), pnr.next())) & 0xff) for c in obfuscated])
    
    def _extract(container_filename):
    ...
    ...
    ... 
            contents = container.read(compressed_length)
            header_length, mangling_method, truncated_timestamp, original_length = struct.unpack('>HHLL', contents[:12])
            assert header_length == 12 and mangling_method == 1
    
            # The file contents are obfuscated with a Marsaglia xorshift PNR
            pnr = marsaglia_xorshift_128(x = truncated_timestamp, y = original_length)
    
    
            qcompress_prefix = deobfuscate_string(pnr, contents[12:16])

     


  15. 2 hours ago, Stano said:

    I know/I read of two cases where programmers used it. AI reduced their time to create the right code from a week to a day. No, they didn't get the right result. But AI led them to it.

    He who knows what he wants and what he is doing will help himself.

    That's the experience I've had. Each sample of code has not compiled out of the box, but fixing it has given me an understanding of the code or pointed me in the direction of something I didn't know about.

    • Like 1
×