diff --git a/kaptchapelo.lisp b/kaptchapelo.lisp index 2a589a9..b813466 100644 --- a/kaptchapelo.lisp +++ b/kaptchapelo.lisp @@ -1,16 +1,16 @@ ;;; Copyright 2023, Jaidyn Ann ;;; ;;; This program is free software: you can redistribute it and/or -;;; modify it under the terms of the GNU General Public License as -;;; published by the Free Software Foundation, either version 3 of +;;; modify it under the terms of the GNU Affero General Public License +;;; as published by the Free Software Foundation, either version 3 of ;;; the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;;; GNU General Public License for more details. +;;; GNU Affero General Public License for more details. ;;; -;;; You should have received a copy of the GNU General Public License +;;; You should have received a copy of the GNU Affero General Public License ;;; along with this program. If not, see . (defpackage #:kaptchapelo @@ -29,6 +29,7 @@ (defun random-file (directory &key (file-ext "")) + "Select a random file from the given DIRECTORY of a specific FILE-EXTension." (alexandria:random-elt (directory (str:concat (format nil "~A" directory) "/*" @@ -38,16 +39,17 @@ (defun new-captcha-json (captcha-image-uri captcha-text-file) - "Return the kocaptcha-formed JSON to be returned for a new captcha request." + "Create a Kocaptcha-compatibile captcha challenge in JSON-format." (yason:with-output-to-string* () (yason:encode-plist (list "md5" (byte-array-to-hex-string captcha-text-file) "url" captcha-image-uri + ;; I don’t know what Kocaptcha’s token does! :P "token" "This_isnt_actually_used_lol")))) (defun new-captcha-response (captcha-dir) - "Create an HTTP response for use with Clack with a new captcha." + "Create a Clack HTTP response with a new captcha." (let* ((captcha-txt-file (random-file captcha-dir :file-ext "txt")) (captcha-img-file (str:concat (pathname-name captcha-txt-file) ".png")) (captcha-md5-str (byte-array-to-hex-string @@ -58,35 +60,52 @@ (defun image-response (request-uri captcha-dir) + "Given a /captcha/… REQUEST-URI and the CAPTCHA-DIR where images can be found, +make a Clack HTTP response that serves the appropriate image." (let ((image-path (str:replace-first "/captcha/" (format nil "~A" captcha-dir) request-uri))) - (list 201 '(:content-type "image/png") (pathname image-path)))) + (list 201 '(:content-type "image/png") + (pathname image-path)))) (defun index-response () - '(201 (:content-type "text/plain") ("You’ve installed Kaptĉapelo! Good work, guy!"))) + "Return a friendly “salutations” Clack-response for those visting the root-page." + '(201 (:content-type "text/plain") + ("You’ve installed Kaptĉapelo; good work! If you’d like a captcha challenge, visit /new !"))) + (defun 404-response () + "Create a 404-comlpaining HTTP Clack-response." '(404 (:content-type "text/plain") ("No such page."))) (defun server (env captcha-dir) + "The heart of the server; returns requests for Clack." (let* ((uri (quri:uri (getf env :request-uri))) - (uri-path (quri:uri-path uri)) - (params (quri:uri-query-params uri))) + (uri-path (quri:uri-path uri))) (format *error-output* "~A" uri-path) - (cond ((string= uri-path "/new") - (new-captcha-response captcha-dir)) - ((or (string= uri-path "/") - (string= uri-path "/index.html")) - (index-response)) - ((str:starts-with? "/captcha/" uri-path) -;; (str:ends-with? ".png" uri-path)) - (image-response uri-path captcha-dir)) - ('t - (404-response))))) + (cond + ;; Create a new captcha at /new + ((string= uri-path "/new") + (new-captcha-response captcha-dir)) + ;; For lost souls visiting /[index.html], say “hi.” + ((or (string= uri-path "/") + (string= uri-path "/index.html")) + (index-response)) + ;; At /captcha/*.png, server the given image. + ((and (str:starts-with? "/captcha/" uri-path) + (str:ends-with? ".png" uri-path)) + (image-response uri-path captcha-dir)) + ;; Otherwise… IDK, 404! ¯\_(ツ)_/¯ + ('t + (404-response))))) (defun start-server (&key (address "0.0.0.0") (port 5001) (captcha-directory #p"captcha/")) + "Start the Kaptchapelo server, which takes captcha challenges from the given +CAPTCHA-DIRECTORY. Challenges are made up of two files: + * A challenge PNG file (ex. bird.png) + * An answer TXT file (ex. bird.txt) +Note that the The answer text-file should not contain a trailing newline." (clack:clackup (lambda (env) (funcall #'server env captcha-directory))