-
Content Count
168 -
Joined
-
Last visited
-
Days Won
3
Everything posted by rvk
-
It's the TDataset way. (BDE is way older) I use IBX in Delphi (but I'm sure FireDac works similarly). 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.
-
programmatically determine the edition of RAD Studio 12.3
rvk replied to dmitrybv's topic in Delphi IDE and APIs
For Delphi 10.2 this also pops up a registration form. -
programmatically determine the edition of RAD Studio 12.3
rvk replied to dmitrybv's topic in Delphi IDE and APIs
Delphi 10.2 Professional shows "Product name: Professional" and "Product version: 25.0". in the properties of bds.exe. -
programmatically determine the edition of RAD Studio 12.3
rvk replied to dmitrybv's topic in Delphi IDE and APIs
Wat does "Personal" mean in the details then for the Community edition? -
programmatically determine the edition of RAD Studio 12.3
rvk replied to dmitrybv's topic in Delphi IDE and APIs
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.) -
RTF Roulette: The Hidden Dangers of Storing Rich Text in VARCHAR Fields
-
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. 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)
-
Surely after using VPN... you could use RDP over that VPN. 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.
-
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.
-
Google OAuth2, "username and password not accepted" when sending
rvk replied to emileverh's topic in Network, Cloud and Web
I'm beginning to think that using the limited scope gmail.send isn't allowed for SMTP sending. 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 -
Google OAuth2, "username and password not accepted" when sending
rvk replied to emileverh's topic in Network, Cloud and Web
BTW. For the mentioned library... the same issue is described here: https://github.com/geoffsmith82/GmailAuthSMTP/issues/19 -
Google OAuth2, "username and password not accepted" when sending
rvk replied to emileverh's topic in Network, Cloud and Web
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.) -
Google OAuth2, "username and password not accepted" when sending
rvk replied to emileverh's topic in Network, Cloud and Web
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)? -
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. But yes, you need to adjust your workflow now to incorporate the new certificate
-
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.
-
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.
-
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.
-
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?
-
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.
-
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.
-
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
-
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.
-
TNetHTTPClient and StatusText not being "OK"
rvk replied to alank2's topic in RTL and Delphi Object Pascal
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: I give up 🙂 -
TNetHTTPClient and StatusText not being "OK"
rvk replied to alank2's topic in RTL and Delphi Object Pascal
Your welcome. BTW. I just tested curl on a Linux machine (just for fun): 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. -
TNetHTTPClient and StatusText not being "OK"
rvk replied to alank2's topic in RTL and Delphi Object Pascal
Only start the timer during the start service sequence. But that's besides the point for this problem. BTW. The reason-phrase is optional in the http-protocol. See https://datatracker.ietf.org/doc/html/rfc9112#name-status-line Also it says that you should ignore it.