Jump to content

rvk

Members
  • Content Count

    169
  • Joined

  • Last visited

  • Days Won

    3

Posts posted by rvk


  1. 5 minutes ago, Squall_FF8 said:

    Even IBX adopted Sequence, which if used makes Generators a little obsolete.

    Even with SEQUENCE you need a trigger in Firebird. It was mainly a name change in Firebird 3. As of Firebird 4 there is also an auto increment option (IDENTITY).

     

    (Because I still support some 2.5 DB's I do still sometimes use GENERATORs.)

     


  2. 6 minutes ago, Squall_FF8 said:

    I assume that is the BDE way, but I missed that class (academic, not Delphi)  🙂

    It's the TDataset way. (BDE is way older) I use IBX in Delphi (but I'm sure FireDac works similarly).

    6 minutes ago, Squall_FF8 said:

    BTW what happens with the ID after Insert? Is it automatically received or you need to make sure that Insert statement have the right things (like 'OUTPUT INSERTED ID' in MS SQL)

    I use Firebird, not MSSQL. In Firebird, in the past, you needed to first get the GENERATOR value and use it with your insert (if you didn't want ID to automatically generated via trigger because you needed the inserted value directly afterwards) . But in later versions you can use RETURNING ID if the ID is generated by a TRIGGER.

     

    So if you have a trigger in MSSQL which advances the ID automatically, you should be able to use "INSERT INTO table (name) OUTPUT Inserted.ID VALUES(:x,:y,:z)" or you can use SCOPE_IDENTITY() directly after the INSERT statement.

     


  3. 2 minutes ago, Uwe Raabe said:

    In terms of SKU, the Community Edition is in fact a Professional Edition. It is just the License restrictions that make it a CE.

    Wat does "Personal" mean in the details then for the Community edition?

     

    11 minutes ago, dmitrybv said:

    I tested RAD Studio 12.1 Community Edition.
    For this edition, the "Detail" properties of the bds.exe contain the value “Personal”.
    I don’t know what the value Personal means and whether it is related to the concept of Edition at all.

     


  4. Note that bds.exe /ProductInfo:SKU doesn't work in all version !! For me it prompts a popup dialog where I need to enter a license key (while I already have a licensed version installed).

    So I wouldn't trust prameters to bds.exe unless you determined those parameters are correct for all versions.

     

    You might have better luck just looking at the "Detail" properties of the bds.exe itself. Mine says "Product name: Professional" so I guess the community version would display "Community edition" or something.

     

    (I wonder how the Jedi project does this. I think they use one or the other depending on the version.)


  5. 13 minutes ago, Squall_FF8 said:

    It will be interesting to peek in a snippet of it ^_^

    function EditStreamInCallback(dwCookie: Longint; pbBuff: PByte;
      cb: Longint; var pcb: Longint): dword; stdcall;
    const
      E_FAIL = dword($80004005);
    var
      theStream: TStream;
      dataAvail: Longint;
    begin
      theStream := TStream(dwCookie);
      with theStream do
      begin
        dataAvail := Size - Position;
        Result := 0; { assume everything is ok }
        if dataAvail <= cb then
        begin
          pcb := read(pbBuff^, dataAvail);
          if pcb <> dataAvail then { couldnt read req. amount of bytes }
              Result := E_FAIL;
        end
        else
        begin
          pcb := read(pbBuff^, cb);
          if pcb <> cb then
              Result := E_FAIL;
        end;
      end;
    end;
    
    function EditStreamOutCallback(dwCookie: Longint; pbBuff: PByte;
      cb: Longint; var pcb: Longint): dword; stdcall;
    var
      theStream: TStream;
    begin
      theStream := TStream(dwCookie);
    
      with theStream do
      begin
        if cb > 0 then
            pcb := write(pbBuff^, cb);
        Result := 0;
      end;
    end;
    
    procedure GetRTFSelection(aRichEdit: TJvRichEdit; intoStream: TStream);
    var
      editstream: TEditStream;
    begin
      with editstream do
      begin
        dwCookie := Longint(intoStream);
        dwError := 0;
        pfnCallback := @EditStreamOutCallback;
      end;
      aRichEdit.Perform(EM_STREAMOUT, SF_RTF or SFF_SELECTION, LParam(@editstream));
    end;
    
    procedure PutRTFSelection(aRichEdit: TJvRichEdit; sourceStream: TStream);
    var
      editstream: TEditStream;
    begin
      with editstream do
      begin
        dwCookie := Longint(sourceStream);
        dwError := 0;
        pfnCallback := @EditStreamInCallback;
      end;
      aRichEdit.Perform(EM_STREAMIN, SF_RTF or SFF_SELECTION, LParam(@editstream));
    end;
    
    function GetRTF(RE: TJvRichEdit; Selection: Boolean = false): string;
    var
      strStream: TStringStream;
    begin
      strStream := TStringStream.Create('');
      try
        if Selection then
        begin
          GetRTFSelection(RE, strStream);
          Result := strStream.DataString;
        end
        else
        begin
          RE.PlainText := false;
          RE.Lines.SaveToStream(strStream);
          Result := strStream.DataString;
        end;
      finally
          strStream.Free
      end;
    end;
    
    procedure SetRTF(var RE: TJvRichEdit; S: string);
    var
      strStream: TStringStream;
    begin
      strStream := TStringStream.Create('');
      try
        strStream.WriteString(S);
        strStream.Position := 0;
        RE.PlainText := false;
        RE.Lines.LoadFromStream(strStream);
      finally
          strStream.Free
      end;
    end;

    GetRTF/SetRTF for the complete content of TRichEdit (I use TJvRichEdit but you can change that to TRichEdit).

    GetRTFSelection/SetRTFSelection for only the selected content.

     

    13 minutes ago, Squall_FF8 said:

    How that works in conjunction with TQuery?
    I mean, when I call ExecSQL with Insert/Update, TDBRichEdit automatically provides the context for my BLOB field (no extra code)? Or I need to provide some code before/after ExecSQL?

    With ExecSQL you don't work with dataaware components. The you can just use TField.AsString for the parameterized select/update/insert. TRichEdit is not dataaware.

    When you want to work with data-aware components like TDBRichEdit, you don't need to use ExecSQL. You can just do SELECT and fill in the UpdateSQL Object with INSERT/UPDATE/DELETE statements.

    Then in code you only have to do TQuery.Open (for the SELECT). Your TDBRichEdit will be automatically filled.

    When you do TQuery.Edit you enter edit mode (or you can do TQuery.Insert to insert a new record).

    After you are ready, you do TQuery.Post and the records (including the content of TDBRichEdit) is saved. (don't forget to Commit the transaction)

     

    • Thanks 1

  6. 13 hours ago, Vandrovnik said:

    What about clients connected directly to central database server through a VPN?

    Surely after using VPN... you could use RDP over that VPN.

     

    On 6/23/2025 at 8:06 PM, chkaufmann said:

    For one client it is not possible anymore to open an application over RDP. I need to find a solution using https only.

    What is the reason one client can't open the application over RDP anymore?

    I hope you have RDP behind a VPN? (just recently got a customer with open RDP port, which had his server ransomware'd).

    If it's just port-restriction at client side, you could try VPN over 443/https port and then use the RDP app.

     


  7. 11 hours ago, Squall_FF8 said:

    BTW this might be interesting for you - Delphi and WordPad put exact same control codes. In my observation - 13, 10 after \par and 0 at the end.  

    Correct. That's why I use BLOB. (in Firebird BLOB SUB_TYPE 0 SEGMENT SIZE 80)

    (In Firebird you could also use SUB_TYPE 1 to let the DB treat it as text blob, but then you would need to make sure the char set is correct.)

     

    Then... I don't use the TBlobField(TField).LoadFromStream etc. for just RTF text (where I do for dropping random attachment and files in the DB).

    I use my own GetRTF(RichEdit1) and GetRTFSelection which retrieve the raw RTF and then use the normal TField.asString via parameterized update/insert queries.

     

    But... there is also a TDBRichEdit which should handle this automatically (I create my own TMyDBRichEdit for also handling some extras).

    So... when you have a visual richedit on screen, use the TDBRichEdit. When you need to store and read without visual richedit, use a GetRTF/SetRTF function.

     

    Don't show RTF in a grid as column (when you would use varchar). Because of the encoding it's not for reading directly anyways.

     


  8. 44 minutes ago, emileverh said:

    So not for the full scope but for the send-only scope. If you have any good tips for Indy, that is of course also welcome! ( https://www.googleapis.com/auth/gmail.send  )

    I'm beginning to think that using the limited scope gmail.send isn't allowed for SMTP sending.

     

     

    Quote

     

    The scope for IMAP, POP, and SMTP access is https://mail.google.com/. If you request access to the full mail scope for your IMAP, POP or SMTP app, it must be in compliance with our Google API Services: User Data Policy.

     

    https://developers.google.com/gmail/imap/xoauth2-protocol

     

    There you see the remark (second point) "migrate to the Gmail API and use more granular restricted scopes".

    So for the limited scopes you would need to use the GMail API and not the SMTP service (?)

     

    For SMTP access I still use App passwords (which still work fine). For OAuth2 access with limited gmail.send and gmail.compose I use the GMail API at https://gmail.googleapis.com/upload/gmail/v1/users/{userId}/drafts/send (with attachments).

    You can either use drafts/send or messages/send method via the GMail API. https://developers.google.com/gmail/api/guides/sending

     

    Maybe someone else can confirm the above (that gmail.send scope can't be used with the smtp service).

    I already see here that it is confirmed on stackoverflow. https://stackoverflow.com/questions/39161914/using-gmail-send-scope-with-smtp-msa

    Quote

    The send scope is only documented to work on the Gmail API (HTTP REST interface). If you want to use SMTP yes, it only accepts the full mail scope.

     


  9. If you didn't go through the CASA Tier 2 then you are still in "Testing" phase. But that's ok and indeed perhaps off topic.

     

    Did you add scope https://www.googleapis.com/auth/gmail.send when asking for authentication? I know you said you added it to your consent screen but you also need to provide that scope (in your code) when going through the OAuth2 process.

     

    And second... when entering the consent screen, you need to CHECK the "Allow send" checkbox. It's not checked by default (and if you forget it, you won't have direct send access). I just did this myself again in my program and both my compose draft and send mail checkboxes where not checked by default.

     

    (I don't use the Indy components but Synapse but that shouldn't matter for above issues.)

     


  10. On 2/9/2025 at 12:29 PM, emileverh said:

    So I went to the verification approval process of Google and I passed 😉 

    Did you also pass the "CASA Tier 2 security assessment" for your application? Can you provide the steps?

     

    I tried this a few years ago but they didn't provide any documentation as how to pass this.

    Tier 2 was only documented for online environments and Android Apps (where I would need to provide my app so they could test it).

    But I have an offline Windows application (which they don't seem to take into account).

    I finally gave up on the verification process. (I still get the "not verified" before entering the authentication screen)

     

    Or are you just in the test-phase where you can have a limited number of users (also normally used for internal testing)? (And also have the "not verified" screen)

     

    Regarding the error... I've only used the "AUTHENTICATE XOAUTH2" command with IMAP access to gMail. I see this library tries to do a user Bearer token.

    Did you try creating a new refresh-token (so going through the consent screen again)?

     

     


  11. Just now, GabrielMoraru said:

    If an unsigned executable has been downloaded and executed by many users over a long period without triggering significant antivirus or security alerts, systems like Microsoft's SmartScreen may assign it a positive reputation.

    What color banner does it show then if you start up those programs? I'm sure it's not this (below) blue banner because there is no verified producer name. So it will still show you the other yellow banner. It won't prompt smartscreen because that's something different. But it will probably you that install screen with yellow banner and no certificate warning.

     

    OVL-blue.thumb.png.46d2fcb6b725f0c2b0e86a0e1655fc53.png

     

    But yes, you need to adjust your workflow now to incorporate the new certificate :classic_biggrin:


  12. Just now, GabrielMoraru said:

    Over time the file acquires "trust" on Microsoft's servers. Once it goes in "blue" it will remain like that and it can be installed in new computers.

    Maybe that's true for the full blue screen (where you need to tap more info). I don't think it's true for the install screens you showed in that article (blue banner for valid and yellow for invalid or not present). At least it shouldn't because that screen shouldn't get the info from smartscreen but directly from the certificate in the executable.


  13. 1 minute ago, GabrielMoraru said:

    Yes. But once the application passes the "smart screen" it will remain "blue" even if the certificate expires.

    Not if used on a new computer. 

    I don't know what happens on existing computers. But it's never wise to not sign with a timeserver.

     

    And maybe it passes smartscreen during download but it will not give you the blue screen when installing but a yellow screen promoting the expired certificate.

     


  14. Just now, GabrielMoraru said:

    Issued by sectigo public code CA R36

    Valid from: 2022-04-01 to 2025-04-01

    Yep. Then you can take that article down because it's based on old information. You can't do it like that anymore with new issued certificates. And you signed with the old certificate in that article.

     

    Also... all you previously signed exes will complain after that date. That's why you need to sign with a timeserver so those exes will keep working, even after the date of expiration of the certificate with which you signed.

     


  15. Just now, GabrielMoraru said:

    Yes. I right-click the exe file and I see the "digital signature" tab. It says that it is signed under my name (digest algorithm sha 256) but the timestamp is "Not available".

    O wow, then you didn't even signed with a timeserver with timestamp (which means the signed exe will complain when the certificate expires). Normally you sign with the timeserver so the exe will be usable also after your certificate expires. You just can't sign new exe anymore with an expired certificate.

     

    Because you didn't, and don't seem to be able to go to the real certificate, it leads me te believe you didn't even check things.

     

    Now do the same as before (right click exe, properties, certificate tab) but now click a SHA256 and click Details.

    Then click View certificate.

    There you have "Issued to", "Issued by" but also "Valid from/to".

    What are the dates there?

     


  16. Just now, GabrielMoraru said:

    used SignTool\signtool.exe verify /pa Test.exe and I get

    No, you need to right click the file and go to properties. Choose the certificate tab and see if it had the new certificate.

     

    That command just shows you still have a valid verificatie but that could still be the certificate which you can't use anymore after the spring to sign new files after that.

     


  17. 15 minutes ago, GabrielMoraru said:

    I think the PFX came attached to that email.


    My current certificate is still valid but it will expire this spring 😞

    Can you check the actually signed exe file? Did it really contain the new certificate. I still have a feeling you are working with old files because the new method shouldn't allow token-less certificates anymore. So the old pfx isn't allowed anymore after it expires.

     

    https://knowledge.digicert.com/general-information/new-private-key-storage-requirement-for-standard-code-signing-certificates-november-2022

     

    That mail is from the old way of doing things before 2023. So if you used the pfx from there... Then that's not going to work anymore after the certification expires in a few months.

     


  18. 39 minutes ago, GabrielMoraru said:

    Because they charge your $130 for that USB stick (so called "packing and handling fees"). They make more money from that USB than they make from the token itself.

    Luckily I should get a usb stick when my 3 years run out (including a certificate for another year) as part of the promo when they switched to the new form. 

     

    But you said you have a pfx without a usb stick and don't need a password. How does that work? How did you get that from sectigo? If you only have a pfx this is portable to another computer/developer without the usb stick present. That shouldn't be possible anymore. How did you get the pfx? Mail of usb stick? And if you did get the usb key how did you extract the pfx from that?

     

    Edit: I wonder if you are not just signing with an old certificate :classic_wink:


  19. 1 hour ago, GabrielMoraru said:

    Stay away from USB tokens. Use a seller that does not force you to use such device. For my token I only needed the "singtool.exe" from Microsoft, which also DOES NOT requires you to enter the password every time you want to sign an exe file.💪

    So Sectigo is still selling certificates which can be used as .pfx directly with signtool.exe without providing a prompt ?

    So why are they providing a USB stick then? This could just be done electronically via mail.

     


  20. I've just tested with a server which can't do HTTP/2 (but only does HTTP 1.1) and it always returns OK inside the service.

    So I think the problem is that, when running as local system account. the HTTP/2 is requested.

    If it's not available, you'll get the OK. If HTTP/2 is available, there is no OK.

     

    Maybe you can test it with a server where you always get a HTTP1.1 result (and never a HTTP/2 result).

     

    You can also test this yourself by logging res.Version. I didn't test it but I'll bet you'll get version 2 back for no OK, and 1.1 for OK.

      THTTPProtocolVersion = (UNKNOWN_HTTP, HTTP_1_0, HTTP_1_1, HTTP_2_0);

     

    Grrr. Nope. Also not it:

    Quote

    result 200 /  / HTTP_1_1

    I give up 🙂

     

    • Like 1

  21. Your welcome. BTW. I just tested curl on a Linux machine (just for fun):

     

    Quote

    pi@space01:~ $ sudo curl -I http://www.google.com
    HTTP/1.1 200 OK
    Content-Type: text/html; charset=ISO-8859-1
    Content-Security-Policy-Report-Only: object-src 'none';base-uri 'self';script-src 'nonce-X-ktTYexJNugET9N6Fa8vQ' 'strict-dynamic' 'report-sample' 'unsafe-eval' 'unsafe-inline' https: http:;report-uri https://csp.withgoogle.com/csp/gws/other-hp
    Date: Thu, 05 Dec 2024 15:15:54 GMT
    Server: gws
    X-XSS-Protection: 0
    X-Frame-Options: SAMEORIGIN
    Transfer-Encoding: chunked
    Expires: Thu, 05 Dec 2024 15:15:54 GMT
    Cache-Control: private
    Set-Cookie: AEC=AZ6Zc-Xn8oa4IZiywmOCd4dkoEHyXgH7rRc_XoRQjDkCGcQkwZ6GlBvsgg; expires=Tue, 03-Jun-2025 15:15:54 GMT; path=/; domain=.google.com; Secure; HttpOnly; SameSite=lax

     

    Quote

     

    pi@space01:~ $ sudo curl -I https://www.google.com
    HTTP/2 200
    content-type: text/html; charset=ISO-8859-1
    content-security-policy-report-only: object-src 'none';base-uri 'self';script-src 'nonce-UW3w19xpBP4YYGNbmXdokw' 'strict-dynamic' 'report-sample' 'unsafe-eval' 'unsafe-inline' https: http:;report-uri https://csp.withgoogle.com/csp/gws/other-hp
    accept-ch: Sec-CH-Prefers-Color-Scheme
    p3p: CP="This is not a P3P policy! See g.co/p3phelp for more info."
    date: Thu, 05 Dec 2024 15:15:59 GMT
    server: gws
    x-xss-protection: 0
    x-frame-options: SAMEORIGIN
    expires: Thu, 05 Dec 2024 15:15:59 GMT
    cache-control: private
    set-cookie: AEC=AZ6Zc-XkeaKNk-uXqoapVf2puXQG9x0eGErkTj0C7NeZElHIH5Ku75bGoA; expires=Tue, 03-Jun-2025 15:15:59 GMT; path=/; domain=.google.com; Secure; HttpOnly; SameSite=lax
    set-cookie: __Secure-ENID=24.SE=heUvBvT50RTq1RwovcPhzD6tBNqpGWCpwMoUorKeIKsiwMPnA-97OEpIzRkS96B2OQ5I7eldjw80PzRouMRH55s7Dl08bNfA_hmCBhHyO9tlqLtlpCx9_N1yQVaRs4CRJLk_gYhm03iSBZJl-hgxixiI64A7j2OFon6vX6MKtb4rTyh9C_DM7Vqqb_5Ei_ACoQDqDQ2Lrl2NTdeLo4T2BcG8X-iBiVGZwWyqCe8; expires=Mon, 05-Jan-2026 07:34:17 GMT; path=/; domain=.google.com; Secure; HttpOnly; SameSite=lax
    alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000


     

     

    Notice the absence of OK on the HTTPS result. HTTP did give OK 😉

    HTTPS is HTTP/2 (not 1.1) so maybe we are getting HTTP/2 back.

    Forcing curl to do http 1.1 will give OK. sudo curl --http1.1 -I https://www.google.com

     

    But yes... you don't need to worry about the reason-phrase. It should be ignored anyway.

     

    • Like 1
×