(module pastiche (pastiche) (import chicken scheme) (use awful colorize html-utils html-parser html-tags miscmacros simple-sha1 sql-de-lite spiffy tcp awful-sql-de-lite sql-de-lite files ports posix data-structures utils extras irregex (srfi 1 13) utf8) ;;; ;;; Captchas ;;; (define-record captcha string figlet) (define (create-captchas num #!key (min-captcha-len 4) (max-captcha-len 8)) ;; returns an alist mapping captcha hashes to captcha records (define chars '#(#\a #\b #\c #\d #\e #\f #\g #\h #\i #\j #\k #\l #\m #\n #\o #\p #\q #\r #\s #\t #\u #\v #\x #\y #\z)) (define random-captcha (let ((chars-len (vector-length chars))) (lambda () (list->string (let loop ((n (+ min-captcha-len (random (- max-captcha-len min-captcha-len))))) (if (zero? n) '() (cons (vector-ref chars (random chars-len)) (loop (- n 1))))))))) (define (figlet str) (call-with-input-pipe (string-append "figlet " str) read-all)) (let loop ((n (sub1 num))) (if (zero? n) '() (let ((captcha-string (random-captcha))) (cons (cons (string->sha1sum captcha-string) (make-captcha captcha-string (figlet captcha-string))) (loop (- n 1))))))) (define (get-captcha captchas) (list-ref captchas (random (length captchas)))) ;;; ;;; Pastiche ;;; (define (pastiche base-path db-file #!key (vandusen-port 22722) (vandusen-host "localhost") (base-url "http://paste.call-cc.org") (use-captcha? #t) (num-captchas 500) (browsing-steps 15) force-vandusen-notification? (awful-settings (lambda (_) (_)))) (define (delete-and-refill-captchas clist captcha) (if (= 1 (length clist)) (create-captchas num-captchas) (alist-delete captcha clist))) (parameterize ((app-root-path base-path)) (add-request-handler-hook! 'awful-paste (lambda (path handler) (when (string-prefix? base-path path) (switch-to-sql-de-lite-database) (parameterize ((app-root-path base-path) (db-credentials db-file) (page-css "http://wiki.call-cc.org/chicken.css")) (awful-settings handler))))) (define figlet-installed? (let ((install-status 'not-checked)) (lambda () (when (eq? install-status 'not-checked) (set! install-status (handle-exceptions exn #f (system* "figlet -v >/dev/null 2>&1")))) install-status))) (when (and use-captcha? (not (figlet-installed?))) (print "WARNING: `use-captcha?' indicates that captchas are enabled but figlet " "doesn't seem to be installed. Disabling captchas.") (set! use-captcha? #f)) (when (and force-vandusen-notification? (or (not vandusen-host) (not vandusen-port))) (error 'pastiche "`force-vandusen-notification?' requires both `vandusen-host' and `vandusen-port' to be set.")) (define captchas (and use-captcha? (create-captchas num-captchas))) ;; The database needs to be initialised once (unless (file-exists? db-file) (let ((db (open-database db-file))) (exec (sql db "create table pastes(hash text, author text, title text, time float, paste text)")) (close-database db))) (define (notify nick title url) (when vandusen-host (let ((cleaned-nick (with-input-from-string nick html-strip)) (cleaned-title (with-input-from-string title html-strip))) (ignore-errors (let ((stuff (sprintf "#chicken ~s pasted ~s ~a" cleaned-nick cleaned-title (make-pathname base-url url)))) (let-values (((i o) (tcp-connect vandusen-host vandusen-port))) (display stuff o) (newline o) (close-input-port i) (close-output-port o))))))) ; old "select * from pastes order by time desc limit ?,?" (define (fetch-last-pastes from to) (let ((r ($db "select * from pastes p where time = (select min(time) from pastes p2 where p2.hash=p.hash) order by time desc limit ?,?" values: (list from to)))) r)) (define (make-post-table n #!optional (from 0)) (define (format-row r) (list (second r) ; Nickname (link (make-pathname base-path (string-append "/paste?id=" (first r))) (third r)) ; title (prettify-time (fourth r)))) ;date (
class: "paste-table" (or (tabularize (map format-row (fetch-last-pastes from n)) header: '("Nickname" "Title" "Date")) (

"No pastes so far.")))) (define (navigation-links) (

id: "menu" (