Lazarus

Announcements => Third party => Topic started by: Gustavo 'Gus' Carreno on September 17, 2021, 10:07:02 pm

Title: Lazarus implementation of a CAPTCHA
Post by: Gustavo 'Gus' Carreno on September 17, 2021, 10:07:02 pm
Hi Y'all,

I was fumbling on GitHub, as you do, and found this gem: CAPTCHA Verification (https://github.com/JensBorrisholt/Captcha-Verification) for Delphi, made by Jens Borrisholt (https://github.com/JensBorrisholt).

And because I'm always procrastinating on my own projects and I had some free time, I decided to re-write it for Lazarus / Free Pascal.

The repository is here: lazCAPTCHA (https://github.com/gcarreno/lazCAPTCHA).

And attached are some screenshot of the example application, one under Ubuntu and another with Wine(Sorry have no access to a windows machine to make a screenshot).

Hope this helps someone in any way :)

Cheers,
Gus
Title: Re: Lazarus implementation of a CAPTCHA
Post by: Leledumbo on September 19, 2021, 06:20:39 am
At first I thought you were using some kind of online backend, but actually having this written in offline native Pascal expands the possibilities of practical usage to a different level. Great job!
I think it deserves a place in online package manager.
Title: Re: Lazarus implementation of a CAPTCHA
Post by: Gustavo 'Gus' Carreno on September 19, 2021, 07:45:45 am
Hey Leledumbo,

At first I thought you were using some kind of online backend, but actually having this written in offline native Pascal expands the possibilities of practical usage to a different level. Great job!

Thank you very much for the compliment, but alas, I can't accept all the credit. I just adapted/copied the work of the original author: Jens Borrisholt (https://github.com/JensBorrisholt).

I think it deserves a place in online package manager.

That's an awesome endorsement!! Thanks!!!

But, IMHO, it needs some modifications/additions before I can consider bugging GetMem for a consideration to be put on OPM:

With regards to 1, I'm a crappy component developer. I have no experience with it and I'm the last person to do it.
The original author had it descend from TComponent already, but I downgraded it to descending from TObject because I saw no functionality that would require it to descend from TComponent.
If I'm to continue to expand on the development of this, I'll require some help, or at least some time to look at some examples and then adventure in the realm of true component development.

With regards to 2 to 4, this isn't that hard to implement once I have a grasp of the whole component thing.

With regards to 5, again, not that hard to implement, but I think it's needed to at least have a consistent canvas size to contain a good amount of places to put characters.

With regards to 6: This for me is Voodoo realm and I think I need to report a bug but I'm not completely sure. I've started another thread (https://forum.lazarus.freepascal.org/index.php/topic,56336.0) where I'm discussing it.
My first problem was the background being black when I wanted it white. I finally found out how to do it but then I got an issue with the TBitmap's PixelFormat  property and the place I set it. If I set it after setting the Brush/Pen it pretty much resets those and the background was still black. So the solution is setting that before setting Brush/Pen, but I still don't understand how setting PixelFormat would reset the Brush/Pen setting :(
I'm now in the process of finding out why if the Optimization is not 1, then the rotation and size of the font is not obeyed.

Until I tackle those points, I guess I'll refrain from bugging GetMem for a place on OPM.
And I think I would have to make it a package, which ATM it isn't :)

Cheers,
Gus
Title: Re: Lazarus implementation of a CAPTCHA
Post by: cappe on September 19, 2021, 09:05:33 am
sounds interesting, i think i will use it too
Title: Re: Lazarus implementation of a CAPTCHA
Post by: Gustavo 'Gus' Carreno on September 19, 2021, 09:16:09 am
Hey cappe,

sounds interesting, i think i will use it too

Thanks man, I'll accept all the, ego boosting, love I can get :)

Cheers,
Gus
Title: Re: Lazarus implementation of a CAPTCHA
Post by: wp on September 19, 2021, 07:30:38 pm
An interesting topic which motivated me to do it myself - see attachment.

My TCaptcha descends from TGraphicControl and contains its own drawing routine --> just place it on the form and use it. There are several properties to define its behaviour:
Title: Re: Lazarus implementation of a CAPTCHA
Post by: howardpc on September 19, 2021, 08:31:33 pm
wp, yours is an elegant implementation, and a nice test app, thank you.
It is also a good illustration of intelligent use of indexed properties.
A very minor optimisation of the RotatePoint function would be to define a PiOver180 const the compiler would calculate once at compilation, and use the SinCos() routine from the Math unit which evaluates both needed values together.
Title: Re: Lazarus implementation of a CAPTCHA
Post by: Gustavo 'Gus' Carreno on September 19, 2021, 08:56:29 pm
Hey WP,

An interesting topic which motivated me to do it myself - see attachment.

Your implementation looks FRIGGIN AWESOME!!!!

I'll have a good look at it and try and learn a ton so I can change my implementation into the component that I wanted to do!!

Can't say this enough: Humongous awesome effort and I'm sure I'm gonna learn tons about making a graphical component!!!

Only one question: Did you stumble upon the optimization above 1 problem?

Cheers,
Gus
Title: Re: Lazarus implementation of a CAPTCHA
Post by: Gustavo 'Gus' Carreno on September 19, 2021, 09:51:40 pm
Hey WP,

Looks like Lazarus <= 2.0.12 doesn't have ColorToHSV.

Is there a way to make it compatible with Lazarus 2.0.12 and below?

Thanks!!

Cheers,
Gus
Title: Re: Lazarus implementation of a CAPTCHA
Post by: wp on September 19, 2021, 11:08:36 pm
Replaced it by ColorToHLS which has been there all the time (had not used it because I never know whether the H,L,S output covers the full byte range).

Put the component on my github now: https://github.com/wp-xyz/captcha_component. Maybe I ask for OPM integration later.
Title: Re: Lazarus implementation of a CAPTCHA
Post by: Gustavo 'Gus' Carreno on September 19, 2021, 11:20:13 pm
Hey WP,

Replaced it by ColorToHLS which has been there all the time (had not used it because I never know whether the H,L,S output covers the full byte range).

Awesome sauce!!! I'll switch to the cloned version of your repo instead of the zip file you provided erlyer, THANKS!!

Put the component on my github now: https://github.com/wp-xyz/captcha_component. Maybe I ask for OPM integration later.

Please do include it on OPM !!

And would it be too much to ask to create a thread on the Third Party forum to announce it? A bit of publicity wouldn't harm ;)

Can't say this enough: Many thanks for taking the challenge and making this awesome version!!

Cheers,
Gus
Title: Re: Lazarus implementation of a CAPTCHA
Post by: CM630 on September 20, 2021, 12:34:51 pm
I have modified the source code, but now it shows empty spaces instead of letters:


Code: Pascal  [Select][+][-]
  1.  
  2. function TCAPTCHA.GenerateCAPTCHAString: string;
  3. const
  4.   NoOfChars = 10;
  5. var
  6.   validChar: String;
  7.   i: Integer;
  8. begin
  9.   Result:= EmptyStr;
  10.   validChar:= EmptyStr;
  11.   if TCharCase.Number in FCharCase then
  12.     validChar:= validChar + '123456789';
  13.  
  14.  
  15.   if TCharCase.Lower in FCharCase then
  16.     validChar:= validChar + 'абвгдежзийклмнопрстуфхцчшщъьюя';
  17.     //validChar:= validChar + 'abcdefghijklmnopqrstuvwxyz';
  18.  
  19.  
  20.   if TCharCase.Upper in FCharCase then
  21.     validChar:= validChar + 'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЬЮЯ';
  22.     //validChar:= validChar + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  23.  
  24.  
  25.   SetLength(Result, NoOfChars);
  26.  
  27.  
  28.   for i:= 1 to NoOfChars do
  29.     Result[i]:= validChar[Random(Length(validChar)) + 1];
  30. end;      
Title: Re: Lazarus implementation of a CAPTCHA
Post by: Gustavo 'Gus' Carreno on September 20, 2021, 02:38:05 pm
Hey CM630,

I have modified the source code, but now it shows empty spaces instead of letters:

AAHHHH, Crap, the UTF8 ugly monster rears it's head!!

Looks like using TLogFont instead of TFont is more hassle than it should :(

Could I advise you that you use WP's implementation instead?: captcha_component (https://github.com/wp-xyz/captcha_component) and let us know if you can use Cyrillic with it?

I really need to pester WP into announcing his implementation on Third Part cuz mine is now proving itself to be more of a crappy solution than previously anticipated!!

Sorry for the inconvenience!!

Cheers,
Gus
Title: Re: Lazarus implementation of a CAPTCHA
Post by: CM630 on September 20, 2021, 03:57:59 pm

Could I advise you that you use WP's implementation instead?: captcha_component (https://github.com/wp-xyz/captcha_component) and let us know if you can use Cyrillic with it?
I tried to try it. I think that it will need some more significant modifications to provide multilanguage support.
I got to the last line in the code below.


Code: Pascal  [Select][+][-]
  1. procedure TCaptcha.InitText(ACount: Integer; KeepExisting: Boolean);
  2. var
  3.   i, j, n: Integer;
  4.   ok: Boolean;
  5.   AllChars: string = 'abcdefghijklmnopqrstuvw';
  6. begin
  7.   if (FOptions * [coUppercase, coLowerCase, coNumbers] <> []) and
  8.      (FOptions * [coFont1, coFont2] <> []) then
  9.   begin
  10.     if KeepExisting then
  11.       n := Length(FCaptchaChars)
  12.     else
  13.       n := 0;
  14.     // Get random captcha characters, but keep previously assigned chars.
  15.     SetLength(FCaptchaChars, ACount);
  16.     for i := n to High(FCaptchaChars) do
  17.     begin
  18.       // Pick random character
  19.       repeat
  20.         j := Random(3);
  21.         ok := true;
  22.         if (j = 0) and (coUppercase in FOptions) then
  23.         begin
  24.           //FCaptchaChars[i].Character := char(ord('A') + Random(26));
  25.           FCaptchaChars[i].Character := char(UTF8Copy(AllChars,random(UTF8Length(AllChars)),1));  
  26. ...
  27.  
                                                           

The problem seems to be here:

Quote
TCaptchaChar = record
    Character: Char;      // Character
    Angle: Integer;       // Rotation angle of character, in degrees
    Position: TPoint;     // Position of character within buffer bitmap (for TextOut)
    FontIndex: Integer;   // Index of font to be used
    Color: TColor;        // Random color of the character
  end; 

Or precisely in Character: Char;

I think that Char is not going well with UTF8, and it is widely used in WPs code.
Title: Re: Lazarus implementation of a CAPTCHA
Post by: Gustavo 'Gus' Carreno on September 20, 2021, 04:13:08 pm
Hey CM630,

Or precisely in Character: Char;
I think that Char is not going well with UTF8, and it is widely used in WPs code.

I think you're right, having a one byte for the characters will not work in a UTF8 solution!!

Well, I've asked WP on this issue (https://github.com/wp-xyz/captcha_component/issues/2) if he was willing to:
a) Add UTF8 support
b) Allow the user to set the valid characters

So let's wait for what he decides on the matter.

In the meantime, I'm sorry for the inconvenience. UTF8 is always hard and we Latin alphabet users often forget our non Latin alphabet co-programmers, which is a shame and I've been guilty of doing it myself :(
My deepest apologies for that!!

Cheers,
Gus
Title: Re: Lazarus implementation of a CAPTCHA
Post by: wp on September 20, 2021, 06:35:49 pm
The catcha component (https://github.com/wp-xyz/captcha_component) is UTF8-aware now, and the list of valid characters is exposed as properties UppercaseChars, LowercaseChars, NumericChars and CustomChars. Just replace them with kyrillic or whatever. Please report back if it's working (just tested the German umlauts, and they work).

Please note that I renamed some identifiers.
Title: Re: Lazarus implementation of a CAPTCHA
Post by: Gustavo 'Gus' Carreno on September 20, 2021, 06:45:59 pm
Hey CM630,

Looks like you've got your wish come true.

According to WP's post above, you're now able to use Cyrillic to your heart's content.

@WP: Thank mate, you da man!!

Cheers,
Gus
Title: Re: Lazarus implementation of a CAPTCHA
Post by: CM630 on September 21, 2021, 07:48:07 am
I have tried @WP's solution, it works with kirrilic, but should not function Verify(const AText: String): Boolean; rather be function Verify(const AText: String; IgnoreCase: boolean): Boolean; ?
For some letters for an end-user, it might be impossible to tell which character is lowercase and which one is uppercase.


Looks like you've got your wish come true.

Just testing  :D , actually I am not sure if I can use this somehow.
Title: Re: Lazarus implementation of a CAPTCHA
Post by: wp on September 21, 2021, 11:26:48 am
should not function Verify(const AText: String): Boolean; rather be function Verify(const AText: String; IgnoreCase: boolean): Boolean; ?
For some letters for an end-user, it might be impossible to tell which character is lowercase and which one is uppercase.
This sounds like requesting a complicated password with uppercase and lowercase characters and then checking its validity only with ignorecase...

If uppercase and lowercase characters are too similar in your language then I'd select only one of them in the Options of the component. Or, since Verify compares only strings, you could simply build it yourself:
Code: Pascal  [Select][+][-]
  1. uses
  2.   LazUTF8;
  3.  
  4. function TForm1.VerifyCaptcha(AText: String): boolean;
  5. begin
  6.   Result := UTF8Lowercase(Captcha1.Text) = UTF8Lowercase(AText);
  7. end;
TinyPortal © 2005-2018