diff options
| author | Scott Ostler <sostler@deathmachine.local> | 2010-03-11 08:01:05 -0500 |
|---|---|---|
| committer | Scott Ostler <sostler@deathmachine.local> | 2010-03-11 08:01:05 -0500 |
| commit | 3d83db95469600000f4fbc1337bfc6aac9efd9a4 (patch) | |
| tree | 05ba06023a71bc27e04cbb05280f4c96b63bef9d | |
| parent | e8142b2742433ea26f6434e5933cddea8b4711c2 (diff) | |
Added upload limits
| -rwxr-xr-x | src/site.clj | 129 | ||||
| -rwxr-xr-x | src/utils.clj | 7 | ||||
| -rwxr-xr-x | static/js/pichat.js | 47 |
3 files changed, 137 insertions, 46 deletions
diff --git a/src/site.clj b/src/site.clj index be19830..d05686b 100755 --- a/src/site.clj +++ b/src/site.clj @@ -4,6 +4,7 @@ java.util.Date java.util.TimeZone java.io.File + javax.imageio.ImageIO org.apache.commons.codec.digest.DigestUtils javax.servlet.http.Cookie org.antlr.stringtemplate.StringTemplateGroup) @@ -59,6 +60,7 @@ "http://dump.fm" "http://localhost:8080")) +(def *root-directory* (System/getProperty "user.dir")) (def *image-directory* "images") (def *avatar-directory* "avatars") @@ -74,15 +76,23 @@ (defn swap [f] (fn [& more] (apply f (reverse more)))) +(def YYYYMMDD-format (new SimpleDateFormat "yyyyMMdd")) + +(defn today [] + (.format YYYYMMDD-format (new Date))) + (def formatter (new SimpleDateFormat "h:mm EEE M/d")) (defn non-empty-string? [s] (and s (> (count s) 0))) -(defn rel-join [& more] - (str-join (System/getProperty "file.separator") - (cons (System/getProperty "user.dir") - more))) +(defn open-file [dir-comps filename] + (let [d (str-join (System/getProperty "file.separator") + (cons *root-directory* dir-comps)) + f (str-join (System/getProperty "file.separator") + [d filename])] + (.mkdir (new File d)) + (new File f))) (defn sha1-hash [& more] (DigestUtils/shaHex (apply str more))) @@ -159,10 +169,13 @@ (vals @(room :users))))) (defn updates [room since] - {"users" (prepare-user-list room) - "messages" (map process-message-for-json - (new-messages room since)) - "topic" @(room :topic)}) + (let [m {"users" (prepare-user-list room) + "messages" (map process-message-for-json + (new-messages room since))} + topic @(room :topic)] + (if topic + (assoc m "topic" topic) + m))) (def *dumps-per-page* 20) @@ -392,8 +405,8 @@ (.setAttribute st "users" users) (cond (= offset 0) (.setAttribute st "prev" false) (= offset 1) (.setAttribute st "prev" "") - :else (.setAttribute st "prev" (str "/" (- offset 1)))) - (.setAttribute st "next" (str "/" (+ offset 1))) + :else (.setAttribute st "prev" (str "/" (dec offset)))) + (.setAttribute st "next" (str "/" (inc offset))) (.toString st))) ;; Topics @@ -420,21 +433,34 @@ [404 "UNKNOWN_ROOM"])) (defn set-topic! [room topic deadline maker] - (ref-set (room :topic) - {:topic topic - :deadline deadline - :maker maker})) + (dosync (ref-set (room :topic) + {:topic topic + :deadline deadline + :maker maker}))) + +(defn end-topic! [room] + (dosync (ref-set (room :topic) nil))) (defn validate-set-topic [session params] (let [room (@rooms (params :room)) topic (params :topic) - deadline (params :deadline)] + deadline (params :deadline) + maker (params :maker)] (cond (not (session :is_admin)) (resp-error "NOT_VIP") (not (valid-topic? topic)) (resp-error "INVALID_TOPIC") (not (valid-deadline? deadline)) (resp-error "INVALID_DEADLINE") (not room) (resp-error "INVALID_ROOM") + (not maker) (resp-error "NOT_MAKER") :else (do - (dosync (set-topic! room topic deadline (session :nick))) + (set-topic! room topic deadline maker) + (resp-success "OK"))))) + +(defn validate-end-topic [session params] + (let [room (@rooms (params :room))] + (cond (not (session :is_admin)) (resp-error "NOT_VIP") + (not room) (resp-error "INVALID_ROOM") + :else (do + (end-topic! room) (resp-success "OK"))))) ;; Chat @@ -590,31 +616,60 @@ ;; Upload +(def *max-image-height* 1000) +(def *max-image-width* 1000) +(def *vip-max-file-size* (mbytes 5)) ; don't be nuts guys +(def *max-file-size* (kbytes 250)) +(def *ignore-size-limit-for-vip* true) (def *avatar-dimensions* [50 50]) -(defn is-image-file? [path] - true) +(defn file-size-limit [vip] + (if (and *ignore-size-limit-for-vip* vip) + *vip-max-file-size* + *max-file-size*)) + +(defn is-file-too-big? [f vip] + (let [limit (file-size-limit vip)] + (if (> (.length f) limit) + (str "FILE_TOO_BIG " (limit vip))))) -(defn format-filename [s] +(defn is-image-invalid? [f] + (try + (let [i (ImageIO/read f) + height (.getHeight i) + width (.getWidth i)] + (if (or (> width *max-image-width*) + (> height *max-image-height*)) + (str "INVALID_RESOLUTION " *max-image-width* " " *max-image-height*))) + (catch Exception _ "FILE_NOT_IMAGE"))) + +(defn format-filename [s nick] (let [spaceless (.replace s \space \-) + nick-clean (re-gsub #"[^A-Za-z0-9]" "" nick) subbed (re-gsub #"[^\w.-]" "" spaceless)] - (str (System/currentTimeMillis) "-" subbed))) + (str-join "-" [(System/currentTimeMillis) nick-clean subbed]))) -(defn image-url-from-file [d f] - (str-join "/" [*server-url* d (.getName f)])) +(defn image-url-from-file [dir date file] + (str-join "/" [*server-url* dir date (.getName file)])) +(defn validate-upload [f vip] + (or (is-file-too-big? f vip) + (is-image-invalid? f))) (defn do-upload [session image room] - (let [filename (format-filename (:filename image)) - dest (File. (rel-join *image-directory* filename)) - url (image-url-from-file "images" dest) - msg-id (msg-db (session :user_id) (room :room_id) url) - msg (struct message-struct (session :nick) url (new Date) msg-id)] - (do - (dosync - (add-message msg room)) - (copy (:tempfile image) dest) - (resp-success url)))) + (if-let [err (validate-upload (image :tempfile) (session :is_admin))] + (resp-error err) + (let [filename (format-filename (:filename image) (session :nick)) + date (today) + dest (open-file [*image-directory* date] filename) + url (image-url-from-file "images" date dest) + msg-id (msg-db (session :user_id) (room :room_id) url) + msg (struct message-struct (session :nick) url (new Date) msg-id)] + (do + (dosync + (add-message msg room)) + (copy (:tempfile image) dest) + (resp-success url))))) (defn upload [session params] (let [room-key (params :room) @@ -622,7 +677,6 @@ image (params :image)] (cond (not nick) [200 "NOT_LOGGED_IN"] (not image) [200 "INVALID_REQUEST"] - (not (is-image-file? (image :filename))) [200 "INVALID_IMAGE"] (not (validate-room-access room-key session)) [200 "UNKNOWN_ROOM"] :else (do-upload session image (@rooms room-key))))) @@ -632,9 +686,10 @@ ;; N.B. -- Upload responses aren't JSON-evaluated (defn do-upload-avatar [session image] - (let [filename (format-filename (:filename image)) - dest (File. (rel-join *avatar-directory* filename)) - url (image-url-from-file "avatars" dest)] + (let [filename (format-filename (:filename image) (session :nick)) + date (today) + dest (open-file [*avatar-directory* date] filename) + url (image-url-from-file "avatars" date dest)] (do (copy-and-resize (:tempfile image) dest) (update-user-db (session :user_id) "avatar" url) @@ -645,7 +700,6 @@ (let [image (params :image)] (cond (not image) [200 "INVALID_REQUEST"] (not (session :nick)) [200 "NOT_LOGGED_IN"] - (not (is-image-file? (image :filename))) [200 "INVALID_IMAGE"] :else (do-upload-avatar session image)))) ;; 404 @@ -701,6 +755,7 @@ (POST "/update-profile" (update-profile session params)) (GET "/topic-list" (validate-topic-list session)) (POST "/set-topic" (validate-set-topic session params)) + (POST "/end-topic" (validate-end-topic session params)) (GET "/directory" (directory session 0)) (GET "/directory/:offset" (directory session (maybe-parse-int (-> request :route-params :offset) 0))) diff --git a/src/utils.clj b/src/utils.clj index 3180e89..7abed4f 100755 --- a/src/utils.clj +++ b/src/utils.clj @@ -13,6 +13,13 @@ :user "postgres" :password "root"})) + +(defn kbytes [b] + (* b 1024)) + +(defn mbytes [b] + (* b 1024 1024)) + ;; JSON responses (def yyyy-mm-dd-formatter (new SimpleDateFormat "yyyy-MM-dd")) diff --git a/static/js/pichat.js b/static/js/pichat.js index fd33729..7314ff8 100755 --- a/static/js/pichat.js +++ b/static/js/pichat.js @@ -215,12 +215,25 @@ function isSameTopic(curTopic, newTopic) { } } +function displayNewTopic(topic) { + $('#topic').empty() + .append(topic.topic) + .append(topic.deadline) + .append(topic.maker).show(); +} + +function hideTopic(topic) { + $('#topic').empty().hide(); +} + function updateTopic(newTopic) { + if ($('#topic').length == 0) { return; } if (isSameTopic(CurrentTopic, newTopic)) { return; } - alert('new topic'); - CurrentTopic = newTopic; - $('#topic').text(topic.topic); - + if (newTopic) { + displayNewTopic(newTopic); + } else { + hideTopic(); + } } function refresh() { @@ -366,13 +379,29 @@ function favoriteImage() {}; function setupUpload(elementId, roomKey) { var onSubmit = function(file, ext) { if (!(ext && /^(jpg|png|jpeg|gif|bmp)$/i.test(ext))) { - alert('SORRY, NOT AN IMAGE DUDE... '); - return false; + alert('SORRY, NOT AN IMAGE DUDE... '); + return false; } }; var onComplete = function(file, response) { - if (typeof pageTracker !== 'undefined') { - pageTracker._trackEvent('Message', 'Upload', typeof Room !== 'undefined' ? Room : 'UnknownRoom'); + if (response.match(/FILE_TOO_BIG/)) { + var maxSize = response.split(" ")[1] / 1024; + alert("Sorry. Your file is just too fucking big. " + + maxSize + "KB or less please."); + return; + } else if (response.match(/FILE_NOT_IMAGE/)) { + alert("What did you upload? Doesn't seem like an image. Sorry."); + return; + } else if (response.match(/INVALID_RESOLUTION/)) { + var maxWidth = response.split(" ")[1]; + var maxHeight = response.split(" ")[2]; + alert("Sorry, the maximum image resolution is " + + maxWidth + "x" + maxHeight); + return; + } + if (typeof pageTracker !== 'undefined') { + var room = typeof Room !== 'undefined' ? Room : 'UnknownRoom' + pageTracker._trackEvent('Message', 'Upload', room); } } new AjaxUpload(elementId, { @@ -380,7 +409,7 @@ function setupUpload(elementId, roomKey) { autoSubmit: true, name: 'image', data: { room: roomKey }, - onSubmit: onSubmit, + onSubmit: onSubmit, onComplete: onComplete }); } |
