Changeset 2660
- Timestamp:
- 03/05/08 13:04:56 (10 months ago)
- Files:
-
- trunk/bknr/web/src/images/image-handlers.lisp (modified) (1 diff)
- trunk/bknr/web/src/images/image.lisp (modified) (1 diff)
- trunk/bknr/web/src/packages.lisp (modified) (1 diff)
- trunk/bknr/web/src/web/handlers.lisp (modified) (1 diff)
- trunk/bknr/web/src/web/web-utils.lisp (modified) (4 diffs)
- trunk/projects/bknr-website/src/init.lisp (modified) (1 diff)
- trunk/projects/bknr-website/src/webserver.lisp (modified) (1 diff)
- trunk/projects/bos/web/allocation-area-handlers.lisp (modified) (2 diffs)
- trunk/projects/bos/web/poi-handlers.lisp (modified) (3 diffs)
- trunk/projects/lisp-ecoop/src/handlers.lisp (modified) (1 diff)
- trunk/projects/lisp-ecoop/src/tags.lisp (modified) (2 diffs)
- trunk/projects/quickhoney/src/handlers.lisp (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/bknr/web/src/images/image-handlers.lisp
r2650 r2660 80 80 (action (eql :upload))) 81 81 (with-bknr-page (:title "Image upload result") 82 (let (( file-pathname (cdr (find "file" (request-uploaded-files) :key #'car :test #'equal))))83 (unless file-pathname82 (let ((upload (request-uploaded-file "file"))) 83 (unless upload 84 84 (error "no file uploaded")) 85 85 (with-query-params (name keyword) 86 (let* ((image ( import-image file-pathname87 :user (bknr-session-user)88 :keywords (list keyword)89 :keywords-from-dir nil))86 (let* ((image (bknr.images:import-image upload 87 :user (bknr-session-user) 88 :keywords (when keyword (list keyword)) 89 :keywords-from-dir nil)) 90 90 (image-id (store-object-id image))) 91 91 (if image trunk/bknr/web/src/images/image.lisp
r2522 r2660 105 105 106 106 ;;; import 107 (defun import-image (pathname &key name user keywords directory (keywords-from-dir t) (class-name 'store-image) initargs) 108 "Create blob from given file" 109 (unless name 110 (setq name (pathname-name pathname))) 111 (unless (scan #?r"\D" name) 112 (error "invalid image name ~A, needs to contain at least one non-digit character" name)) 113 (when (store-image-with-name name) 114 (error "can't import image with name ~A, an image with this name already exists in the datastore" name)) 115 (with-image-from-file (image pathname) 116 ;; xxx not tx safe. hm. 117 (let ((store-image (apply #'make-object 118 (append (list class-name 119 :owners (list user) 120 :timestamp (get-universal-time) 121 :name name 122 :type (pathname-type-symbol pathname) 123 :width (image-width image) 124 :height (image-height image) 125 :directory directory 126 :keywords (if keywords-from-dir 127 (append (mapcar #'make-keyword-from-string directory) keywords) 128 keywords)) 129 initargs)))) 130 (blob-from-file store-image pathname) 131 store-image))) 107 (defgeneric import-image (pathname &key type name user keywords directory keywords-from-dir class-name initargs) 108 (:documentation "Create blob from given source") 109 (:method (pathname &key type name user keywords directory (keywords-from-dir t) (class-name 'store-image) initargs) 110 (unless name 111 (setq name (pathname-name pathname))) 112 (unless (scan #?r"\D" name) 113 (error "invalid image name ~A, needs to contain at least one non-digit character" name)) 114 (when (store-image-with-name name) 115 (error "can't import image with name ~A, an image with this name already exists in the datastore" name)) 116 (let ((type (or type (pathname-type pathname)))) 117 (unless (keywordp type) 118 (setf type (make-keyword-from-string type))) 119 (with-image-from-file (image pathname type) 120 ;; xxx not tx safe. 121 (let ((store-image (apply #'make-object 122 (append (list class-name 123 :owners (list user) 124 :timestamp (get-universal-time) 125 :name name 126 :type (make-keyword-from-string type) 127 :width (image-width image) 128 :height (image-height image) 129 :directory directory 130 :keywords (if keywords-from-dir 131 (append (mapcar #'make-keyword-from-string directory) keywords) 132 keywords)) 133 initargs)))) 134 (blob-from-file store-image pathname) 135 store-image))))) 132 136 133 137 (defun directory-recursive (pathname &key list-directories) trunk/bknr/web/src/packages.lisp
r2650 r2660 227 227 #:upload-name 228 228 #:upload-pathname 229 #:upload-original-filename 229 230 #:upload-size 230 231 #:upload-content-type 232 233 #:with-image-from-upload 234 #:with-image-from-upload* 231 235 232 236 #:bknr-url-path trunk/bknr/web/src/web/handlers.lisp
r2656 r2660 265 265 (do-error-log-request e))))))) 266 266 (handle handler)) 267 (handle handler)) 268 (handler-case 269 (mapcar #'delete-file (mapcar #'cdr (request-uploaded-files))) 270 (error (e) 271 (warn "error ~A ignored while deleting uploaded files" e)))))) 267 (handle handler))))) 272 268 273 269 (defmethod handle ((page-handler page-handler)) trunk/bknr/web/src/web/web-utils.lisp
r2639 r2660 3 3 (enable-interpol-syntax) 4 4 5 (defstruct upload name pathname content-type)5 (defstruct upload name pathname original-filename content-type) 6 6 7 7 (defgeneric object-url (obj)) … … 21 21 :query (uri-query uri))) 22 22 23 #+(or) 24 (defun get-multipart-form-data () 25 (unless (aux-request-value 'multipart-parsed) 26 (let (parameters 27 uploaded-files 28 file-size-limit-reached) 29 (loop 30 (multiple-value-bind (kind part-name file-name content-type) 31 (parse-multipart-header (get-multipart-header request)) 32 (case kind 33 (:eof (return)) 34 (:data (push (cons part-name (get-all-multipart-data request)) parameters)) 35 (:file (let ((contents (get-all-multipart-data request 36 :type :binary 37 :limit *upload-file-size-limit*)) 38 (file-basename (regex-replace #?r".*[\\/]" file-name ""))) 39 (cond 40 ((eq contents :limit) 41 (setf file-size-limit-reached t)) 42 ((equal file-name "") 43 (warn "Can't parse file name from uploaded file named ~a, file ignored" file-name)) 44 (t 45 (let ((uploaded-file-name (merge-pathnames file-basename (store-blob-root-tempdir)))) 46 (format t "; writing uploaded file ~a to ~a~%" file-name uploaded-file-name) 47 (ensure-directories-exist (store-blob-root-tempdir)) 48 (with-open-file (temporary-file uploaded-file-name 49 :direction :output 50 :if-exists :error 51 :element-type '(unsigned-byte 8)) 52 (write-sequence contents temporary-file)) 53 (push (make-upload :name part-name :pathname uploaded-file-name 54 :content-type content-type) uploaded-files)))))) 55 (t 56 (get-all-multipart-data request :limit *upload-file-size-limit*))))) 57 (when file-size-limit-reached 58 (error "upload file size limit exceeded")) 59 (setf (aux-request-value 'bknr-parsed-body-parameters) parameters) 60 (setf (aux-request-value 'uploaded-files) uploaded-files)))) 61 62 (defun get-urlencoded-form-data () 63 (format t "get-urlencoded-form-data not ported~%") 64 #+(or) 65 (loop for name-value in (form-urlencoded-to-query (get-request-body)) 66 do (push name-value (aux-request-value 'bknr-parsed-body-parameters)))) 67 68 (defun parse-request-body (&key uploads) 69 (let ((content-type (header-in :content-type))) 70 (cond 71 ((null content-type) 72 nil) 73 ((scan #?r"^(?i)application/x-www-form-urlencoded" content-type) 74 (format t "body parameters not parsed~%") 75 #+(or) 76 (get-urlencoded-form-data request)) 77 ((and uploads (scan #?r"^(?i)multipart/form-data" content-type)) 78 (format t "uploads not read~%") 79 #+(or) 80 (get-multipart-form-data))))) 81 82 (defun request-uploaded-files (&key all-info) 83 "Return a list of conses (NAME . PATHNAME) which contains files uploaded by the user. 84 If :all-info is non-nil, the full upload file information is returned as a list" 85 (format t "request-uploaded-files not yet ported~%") 86 (if all-info 87 (aux-request-value 'uploaded-files) 88 (mapcar (lambda (upload) (cons (upload-name upload) 89 (upload-pathname upload))) 90 (aux-request-value 'uploaded-files)))) 23 (defun request-uploaded-files () 24 "Return a list of UPLOAD structures describing the file uploads in the request." 25 (unless (aux-request-value 'uploaded-files) 26 (setf (aux-request-value 'uploaded-files) 27 (let ((uploads (remove-if-not #'listp (post-parameters) :key #'cdr)) retval) 28 (dolist (upload-info uploads) 29 (destructuring-bind (name pathname original-filename content-type) upload-info 30 (push (make-upload :name name :pathname pathname :original-filename original-filename :content-type content-type) retval))) 31 (nreverse retval)))) 32 (aux-request-value 'uploaded-files)) 91 33 92 34 (defun request-uploaded-file (parameter-name) 93 (cdr (find parameter-name (request-uploaded-files) :test #'equal :key #'car))) 35 (find parameter-name (request-uploaded-files) :test #'equal :key #'upload-name)) 36 37 (defmacro with-image-from-upload ((image upload &rest args) &body body) 38 `(with-image-from-file (,image (upload-pathname ,upload) (pathname-type (upload-original-filename ,upload)) ,@args) 39 ,@body)) 40 41 (defmacro with-image-from-upload* ((upload &rest args) &body body) 42 `(with-image-from-upload (cl-gd:*default-image* ,upload ,@args) 43 ,@body)) 44 45 (defmethod bknr.images:import-image ((upload upload) &rest args &key &allow-other-keys) 46 (apply #'bknr.images:import-image (upload-pathname upload) 47 :name (pathname-name (upload-original-filename upload)) 48 :type (make-keyword-from-string (pathname-type (upload-original-filename upload))) args)) 94 49 95 50 (defun all-request-params () … … 100 55 macro after the request body has been executed." 101 56 (unless (aux-request-value 'bknr-parsed-parameters) 102 (let ((request-charset (or (register-groups-bind (charset) (#?r".*charset=\"?([^\"; ]+).*" (header-in :content-type)) charset) 103 "utf-8"))) 104 ;; request-charset is not currently used because there seems to 105 ;; be no way to pass the character set for paramter decoding 106 ;; down to Hunchentoot. This will eventually be required (or 107 ;; will it?) 108 (setf (aux-request-value 'bknr-parsed-parameters) 109 (remove "" (query-params) 110 :key #'cdr :test #'string-equal)))) 57 (setf (aux-request-value 'bknr-parsed-parameters) 58 (remove-if (lambda (value) 59 "Remove empty strings (reported as NIL) and uploaded files" 60 (or (equal value "") 61 (listp value))) 62 (query-params) 63 :key #'cdr))) 111 64 (aux-request-value 'bknr-parsed-parameters)) 112 65 … … 119 72 (unless (equal value "") 120 73 value))) 121 122 74 123 75 (defun query-param-list (param-name &key (get t) (post t)) trunk/projects/bknr-website/src/init.lisp
r2652 r2660 14 14 (import-image (merge-pathnames #p"src/bknr-logo.png" bknr.website.config:*root-directory*) 15 15 :keywords '(:banner :bknr)) 16 (make-object 'b log16 (make-object 'bknr.text:blog 17 17 :name "bknr-devel" 18 18 :title "BKNR Website" trunk/projects/bknr-website/src/webserver.lisp
r2659 r2660 14 14 ("/admin" admin-handler) 15 15 ("/login" login-handler) 16 ("/import" import-handler) 16 17 images 17 18 user trunk/projects/bos/web/allocation-area-handlers.lisp
r2644 r2660 170 170 171 171 (defmethod handle-form ((handler create-allocation-area-handler) (action (eql :upload))) 172 (let ((uploaded-text-file ( cdr (find "text-file" (request-uploaded-files) :test #'equal :key #'car))))172 (let ((uploaded-text-file (request-uploaded-file "text-file"))) 173 173 (cond 174 174 ((not uploaded-text-file) … … 177 177 (:p "Please upload your text file containing the allocation polygon UTM coordinates"))) 178 178 (t 179 (with-bos-cms-page (:title #?"Importing allocation polygons from text file $(uploaded-text-file)")179 (with-bos-cms-page (:title #?"Importing allocation polygons from uploaded text file") 180 180 (handler-case 181 (let* ((vertices (polygon-from-text-file uploaded-text-file))181 (let* ((vertices (polygon-from-text-file (upload-pathname uploaded-text-file))) 182 182 (existing-area (find (coerce vertices 'list) 183 183 (class-instances 'allocation-area) trunk/projects/bos/web/poi-handlers.lisp
r2644 r2660 188 188 (action (eql :upload-airal)) 189 189 (poi poi)) 190 (let ((uploaded-file ( cdr (find "image-file" (request-uploaded-files) :test #'equal :key #'car))))190 (let ((uploaded-file (request-uploaded-file "image-file"))) 191 191 (unless uploaded-file 192 192 (error "no file uploaded in upload handler")) 193 ( cl-gd:with-image-from-file* (uploaded-file)193 (with-image-from-upload* (uploaded-file) 194 194 (unless (and (eql (cl-gd:image-width) *poi-image-width*) 195 195 (eql (cl-gd:image-height) *poi-image-height*)) … … 227 227 (action (eql :upload-panorama)) 228 228 (poi poi)) 229 (let ((uploaded-file ( cdr (find "image-file" (request-uploaded-files) :test #'equal :key #'car))))229 (let ((uploaded-file (request-uploaded-file "image-file"))) 230 230 (unless uploaded-file 231 231 (error "no file uploaded in upload handler")) 232 ( cl-gd:with-image-from-file* (uploaded-file)232 (with-image-from-upload* (uploaded-file) 233 233 ; just open the image to make sure that gd can process it 234 234 ) … … 275 275 (with-query-params (poi) 276 276 (setq poi (find-store-object (parse-integer poi) :class 'poi)) 277 (let ((uploaded-file ( cdr (find "image-file" (request-uploaded-files) :test #'equal :key #'car))))277 (let ((uploaded-file (request-uploaded-file "image-file"))) 278 278 (unless uploaded-file 279 279 (error "no file uploaded in upload handler")) 280 ( cl-gd:with-image-from-file* (uploaded-file)280 (bknr.web:with-image-from-upload* (uploaded-file) 281 281 (unless (and (eql (cl-gd:image-width) *poi-image-width*) 282 282 (eql (cl-gd:image-height) *poi-image-height*)) trunk/projects/lisp-ecoop/src/handlers.lisp
r2438 r2660 75 75 (with-query-params (info) 76 76 (format t "; new document - info ~S~%" info) 77 (let ((file-name ( request-uploaded-file "document")))77 (let ((file-name (upload-pathname (request-uploaded-file "document")))) 78 78 (with-open-file (pdf file-name) 79 79 (if (cl-ppcre:scan "^%PDF-" (read-line pdf)) trunk/projects/lisp-ecoop/src/tags.lisp
r2531 r2660 58 58 (with-query-params (type title abstract info) 59 59 (format t "; new submission - title ~S abstract ~S~%" title abstract) 60 (let ((file-name ( request-uploaded-file "document")))60 (let ((file-name (upload-pathname (request-uploaded-file "document")))) 61 61 (with-open-file (pdf file-name) 62 62 (if (cl-ppcre:scan "^%PDF-" (read-line pdf)) … … 121 121 (return-from submission-editor)))) 122 122 (when (request-uploaded-file "document") 123 (let ((file-name ( request-uploaded-file "document")))123 (let ((file-name (upload-pathname (request-uploaded-file "document")))) 124 124 (with-open-file (pdf file-name) 125 125 (cond trunk/projects/quickhoney/src/handlers.lisp
r2504 r2660 154 154 (defmethod handle ((handler upload-image-handler)) 155 155 (with-query-params (client) 156 (let ((uploaded-file ( cdr (find "image-file" (request-uploaded-files) :test #'equal :key #'car)))156 (let ((uploaded-file (request-uploaded-file "image-file")) 157 157 (keywords (mapcar #'make-keyword-from-string (decoded-handler-path handler)))) 158 158 (handler-case … … 160 160 (unless uploaded-file 161 161 (error "no file uploaded")) 162 ( cl-gd:with-image-from-file* (uploaded-file)162 (with-image-from-upload* (uploaded-file) 163 163 (let* ((color-table (make-hash-table :test #'eql)) 164 164 (width (cl-gd:image-width)) … … 170 170 (<= (hash-table-count color-table) 256)) 171 171 (cl-gd:true-color-to-palette)) 172 (let* ((image (make-store-image :name (pathname-name uploaded-file)172 (let* ((image (make-store-image :name (pathname-name (upload-original-filename uploaded-file)) 173 173 :class-name 'quickhoney-image 174 174 :keywords (cons :upload keywords) … … 203 203 (defmethod handle ((handler upload-animation-handler)) 204 204 (with-query-params (client) 205 (let* ((uploaded-files (request-uploaded-files :all-info t))205 (let* ((uploaded-files (request-uploaded-files)) 206 206 (uploaded-image (find "image-file" uploaded-files :test #'equal :key #'upload-name)) 207 207 (uploaded-animation (find "animation-file" uploaded-files :test #'equal :key #'upload-name))) … … 212 212 (unless (find (upload-content-type uploaded-animation) '("application/x-shockwave-flash" "video/quicktime" "application/x-director") :test #'equal) 213 213 (error "Invalid content type ~A - Please upload a Flash, Shockwave or Quicktime file" (upload-content-type uploaded-animation))) 214 ( cl-gd:with-image-from-file* ((upload-pathname uploaded-image))214 (with-image-from-upload* (uploaded-image) 215 215 (let* ((animation-blob (make-blob-from-file (upload-pathname uploaded-animation) 'blob 216 216 :type (upload-content-type uploaded-animation))) 217 (image (make-store-image :name (pathname-name (upload-pathname uploaded-image)) 217 (image (make-store-image :name (pathname-name (upload-original-filename uploaded-image)) 218 :type (make-keyword-from-string (pathname-type (upload-original-filename uploaded-image))) 218 219 :class-name 'quickhoney-animation-image 219 220 :keywords (list :upload :pixel :animation) … … 247 248 (defmethod handle ((handler upload-button-handler)) 248 249 (with-query-params (directory subdirectory) 249 (let ((uploaded-file ( cdr (find "image-file" (request-uploaded-files) :test #'equal :key #'car))))250 (let ((uploaded-file (request-uploaded-file "image-file"))) 250 251 (handler-case 251 252 (progn … … 258 259 (unless uploaded-file 259 260 (error "no file uploaded")) 260 ( cl-gd:with-image-from-file* (uploaded-file)261 (with-image-from-upload* (uploaded-file) 261 262 (unless (and (eql 208 (cl-gd:image-width)) 262 263 (eql 208 (cl-gd:image-height))) 263 (error "invalid image size, buttons must be 208 by 208 pixels")) 264 (let* ((image (make-store-image :name (pathname-name uploaded-file) 264 (error "invalid image size, button size must be 208 by 208 pixels")) 265 (let* ((image (make-store-image :name (pathname-name (upload-original-filename uploaded-file)) 266 :type (make-keyword-from-string (pathname-dimensions (upload-original-filename uploaded-file))) 265 267 :class-name 'store-image 266 268 :keywords (list :button
