diff options
Diffstat (limited to 'dynamic/capabilities/gallery.scm')
| -rw-r--r-- | dynamic/capabilities/gallery.scm | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/dynamic/capabilities/gallery.scm b/dynamic/capabilities/gallery.scm new file mode 100644 index 0000000..1d63061 --- /dev/null +++ b/dynamic/capabilities/gallery.scm @@ -0,0 +1,111 @@ +;;; Copyright © 2019 - 2022 Jakob L. Kreuze <zerodaysfordays@sdf.org> +;;; +;;; 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 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. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with this program. If not, see +;;; <http://www.gnu.org/licenses/>. + +(define-module (dynamic capabilities gallery) + #:use-module (dynamic util) + #:use-module (ice-9 binary-ports) + #:use-module (ice-9 ftw) + #:use-module (ice-9 match) + #:use-module (json) + #:use-module (squee) + #:use-module (srfi srfi-1) + #:use-module (web request) + #:use-module (web response) + #:use-module (web uri) + #:export (get-gallery get-image)) + +(define conn (connect-to-postgres-paramstring "dbname=jakob_gallery")) + +;; How many bytes of entropy to use when generating vanity ID's. +(define %vanity-length (make-parameter 9)) + +;; Path where gallery images are stored. +(define %gallery-image-directory (make-parameter "/home/jakob/gallery-images/")) + +(define (valid-gallery-code code) + "Check database to see if `code' names a nonempty gallery." + (and (= (string-length code) (base64-length (%vanity-length))) + (positive? + (length + (exec-query conn "SELECT * FROM images WHERE vanity = $1" + (list code)))))) + +(define (get-gallery-images code) + "Handler for enumerating the image in a gallery." + (define (format-image image) + (match image + ((title filename thumbnail datetime) + `((title . ,title) + (filename . ,filename) + (thumbnail . ,thumbnail) + (datetime . ,datetime))))) + (let* ((images (exec-query conn "SELECT title, filename, thumb_filename, datetime FROM images WHERE vanity = $1" (list code)))) + (list->vector (map format-image images)))) + +(define (get-gallery-info code) + "Handler for enumerating the image in a gallery." + (define (format-gallery info) + (match info + ((title description datetime) + `((title . ,title) + (description . ,description) + (datetime . ,datetime))))) + (let* ((info (exec-query conn "SELECT title, description, datetime FROM galleries WHERE vanity = $1" (list code)))) + (format-gallery (car info)))) + +(define (get-gallery request body) + (let* ((query-string (uri-query (request-uri request))) + (params (if query-string + (decode-form query-string) + '())) + (code (car (assoc-ref params "g")))) + (if (valid-gallery-code code) + (values '((content-type . (application/json))) + (scm->json-string `((info . ,(get-gallery-info code)) + (images . ,(get-gallery-images code))))) + (values (build-response #:code 400) + (scm->json-string + `((success . #f) + (error . "Invalid gallery code"))))))) + +(define (image-exists? file-name) + (define (string/= a b) (not (string= a b))) + (and (string/= file-name ".") + (string/= file-name "..") + (member file-name (scandir (%gallery-image-directory))))) + +(define (read-image file-name) + (let* ((ext (string-downcase (last (string-split file-name #\.)))) + (mime (cond ((string= ext "jpg") 'image/jpeg) + ((string= ext "png") 'image/png) + (else (error "Unknown MIME type."))))) + (values `((content-type . (,mime))) + (call-with-input-file (format #f "~a/~a" (%gallery-image-directory) file-name) + (lambda (port) + (get-bytevector-all port)))))) + +(define (get-image request body) + (let* ((query-string (uri-query (request-uri request))) + (params (if query-string + (decode-form query-string) + '())) + (file-name (car (assoc-ref params "name")))) + (if (image-exists? file-name) + (read-image file-name) + (values (build-response #:code 400) + (scm->json-string + `((success . #f) + (error . "Invalid filename"))))))) |