====== CAPTCHA amb COBOL ====== Degut a la [[https://media.giphy.com/media/Ju7l5y9osyymQ/giphy.gif|gran expansió que actualment pren el llenguatge COBOL i la interfície de terminal de text]] he pensat que és molt necessària l'aplicació de la tecnologia CAPTCHA als logins de les aplicacions Cobol. {{:blog:cobcaptcha1.png?600|}} En aquest post s'ensenyarà com aplicar un Captcha a un programa Cobol. Es mostra un text en [[https://ca.wikipedia.org/wiki/Art_ASCII|ascii-art]] i l'usuari l'ha de transcriure amb el teclat. Si l'encerta, el programa continua però si el falla, el programa s'atura. Es recomana el compilador [[https://gnucobol.sourceforge.io/|gnucobol]] però pot funcionar amb qualsevol altre que admeti crides a sistema **CALL "SYSTEM" USING**... Per a començar, ens cal el següent: * Una shell de Unix (Bash, Korn...). * El compilador de Cobol gnucobol (pot ser qualsevol altre que admeti CALL). * L'entorn del compilador carregat (variable COB_LIBRARY_PATH). * El programa //figlet//. * Un editor de text (vi, emacs, ...) * Poca feina. Per anar al gra, el que cal afegir al nostre programa, per a que implementi el Captcha, és el següent: Dins la CONFIGURATION SECTION, afegirem aquest descriptor de fitxers: FILE-CONTROL. SELECT captchafile ASSIGN TO captchafilename ORGANIZATION IS LINE SEQUENTIAL. I dins la FILE SECTION afegirem la definició del descriptor: FD captchafile. 01 FILEGLOBAL. 02 FILELINE PIC X(80). 88 EOFcaptchafile VALUE HIGH-VALUES. En la WORKING-STORAGE SECTION afegirem les variables que utilitzem per al Captcha: 77 captchafilename PIC X(25) VALUE SPACES. 01 BANNERCMD PIC x(22) value "/usr/bin/figlet-figlet". 01 random-number PIC X(10). 01 CAPTCHA PIC X(10). 01 ARGV PIC X(100) VALUE SPACES. 88 RECV VALUE SPACES. Ja en la PROCEDURE DIVISION, en la SECTION en la que treballem, afegim: ACCEPT random-number FROM ENVIRONMENT "RANDOM2". ☝ Aquesta sentència pren un nombre al·leatori de la variable d'entorn (de la shell Unix) $RANDOM2. IF random-number = SPACE OR random-number = LOW-VALUE THEN DISPLAY "PROGRAM NOT CORRECTLY INITIATED. ABORTING EXECUTION." LINE 21 COLUMN 2 CALL "C$SLEEP" USING BY CONTENT 3 END-CALL STOP RUN END-IF ☝ Aquest bloc controla que s'hagi rebut un nombre des de la variable d'entorn $RANDOM2. CALL "SYSTEM" USING FUNCTION CONCATENATE(BANNERCMD " " random-number " > /tmp/.rnd-" random-number) END-CALL. MOVE FUNCTION CONCATENATE("/tmp/.rnd-" random-number) TO captchafilename OPEN INPUT captchafile READ captchafile AT END SET EOFcaptchafile TO TRUE END-READ. PERFORM UNTIL EOFcaptchafile DISPLAY FILELINE LINE CAPTCHA-Y COLUMN 2 ADD 1 TO CAPTCHA-Y READ captchafile AT END SET EOFcaptchafile TO TRUE END-READ END-PERFORM CLOSE captchafile CALL "CBL_DELETE_FILE" USING FUNCTION CONCATENATE("/tmp/.rnd-" random-number) I el bloc anterior el que fa és mitjançant un CALL executar el programa figlet i enviar la sortida a un fitxer de text temporal. Seguidament es llegeix (READ) el fitxer i s'imprimeix per pantalla línia a línia (PERFORM... DISPLAY). Finalment s'elimina el fitxer temporal. DISPLAY "ESCRIU EL NOMBRE D'AMUNT: " LINE 20 COLUMN 2. ACCEPT CAPTCHA AT 2026 WITH TIMEOUT AFTER 20 ON EXCEPTION STOP RUN. ☝ Aquí demanem a l'usuari que escrigui el nombre que apareix al Captcha i ho desem dins la variable CAPTCHA. IF CAPTCHA IS NOT EQUAL TO random-number THEN DISPLAY "NOT CORRECT. DISCONNECTING." LINE 21 COLUMN 2 CALL "C$SLEEP" USING BY CONTENT 3 END-CALL STOP RUN ELSE DISPLAY "CAPTCHA SOLVED CORRECTLY. CONNECTING..." LINE 21 COLUMN 2 CALL "C$SLEEP" USING BY CONTENT 3 END-CALL END-IF. ☝ I en el bloc de dalt controlem si l'usuari ha entrat correctament el codi o no. Segons el resultat, el programa agafa un camí (continuar l'execució) o l'altre (STOP RUN). Aquest procediment és molt millorable. Per exemple, hauriem de poder realitzar programàticament, en Cobol, el següent: - Obtenir el número al·leatori sense recórrer a la variable d'entorn. - Representar-lo amb ascii-art sense fer servir el programa //figlet//. Qui s'anima a fer-ho? Notes: Fem servir una variable d'entorn $RANDOM2 ja que el programa de Cobol no és capaç de llegir la variable $RANDOM, per tant, abans de la seva execució, assignem el valor de $RANDOM a $RANDOM2 i llavors el programa sí que és capaç de llegir aquesta nova variable.