diff options
| -rwxr-xr-x | bin/repl.bat | 2 | ||||
| -rwxr-xr-x | bin/repl.sh | 2 | ||||
| -rwxr-xr-x | db/0-create.psql | 3 | ||||
| -rwxr-xr-x | lib/clojure-contrib.jar | bin | 2945084 -> 3292187 bytes | |||
| -rwxr-xr-x | lib/clojure.jar | bin | 1534952 -> 1846856 bytes | |||
| -rw-r--r-- | lib/mail-1.4.4.jar | bin | 0 -> 482977 bytes | |||
| -rw-r--r-- | src/email.clj | 68 | ||||
| -rwxr-xr-x | src/site.clj | 38 | ||||
| -rwxr-xr-x | static/index.html | 392 | ||||
| -rwxr-xr-x | static/js/home.js | 28 | ||||
| -rwxr-xr-x | static/js/pichat.js | 361 | ||||
| -rw-r--r-- | template/directory.st | 7 |
12 files changed, 504 insertions, 397 deletions
diff --git a/bin/repl.bat b/bin/repl.bat index 79a0aaf..5ab0646 100755 --- a/bin/repl.bat +++ b/bin/repl.bat @@ -1,3 +1,3 @@ REM Windows REPL script SHIFT -java -Xmx256m -server -cp lib/commons-io-1.4.jar;lib/commons-fileupload-1.2.1.jar;lib/commons-codec-1.3.jar;lib/clojure.jar;lib/clojure-contrib.jar;lib/compojure-3.2v1.jar;lib/jetty-6.1.14.jar;lib/jetty-util-6.1.14.jar;lib/servlet-api-2.5-6.1.14.jar;lib/jline-0.9.94.jar;lib/postgresql-8.4-701.jdbc4.jar;lib/stringtemplate-3.2.1.jar;lib/antlr-2.7.7.jar;src/ jline.ConsoleRunner clojure.main -i %0 -r %* +java -Xmx256m -server -cp lib/commons-io-1.4.jar;lib/commons-fileupload-1.2.1.jar;lib/commons-codec-1.3.jar;lib/clojure.jar;lib/clojure-contrib.jar;lib/compojure-3.2v1.jar;lib/jetty-6.1.14.jar;lib/jetty-util-6.1.14.jar;lib/servlet-api-2.5-6.1.14.jar;lib/jline-0.9.94.jar;lib/postgresql-8.4-701.jdbc4.jar;lib/stringtemplate-3.2.1.jar;lib/antlr-2.7.7.jar;lib/mail-1.4.4.jar;src/ jline.ConsoleRunner clojure.main -i %0 -r %* diff --git a/bin/repl.sh b/bin/repl.sh index d4beeda..5fc36b8 100755 --- a/bin/repl.sh +++ b/bin/repl.sh @@ -1,3 +1,3 @@ #!/bin/sh -java -Xmx256m -server -cp .:lib/commons-io-1.4.jar:lib/commons-fileupload-1.2.1.jar:lib/commons-codec-1.3.jar:lib/jline-0.9.94.jar:lib/clojure.jar:lib/clojure-contrib.jar:lib/compojure-3.2v1.jar:lib/jetty-6.1.14.jar:lib/jetty-util-6.1.14.jar:lib/servlet-api-2.5-6.1.14.jar:lib/postgresql-8.4-701.jdbc4.jar:lib/stringtemplate-3.2.1.jar:lib/antlr-2.7.7.jar:src/ jline.ConsoleRunner clojure.main -i $1 -r $@ +java -Xmx256m -server -cp .:lib/commons-io-1.4.jar:lib/commons-fileupload-1.2.1.jar:lib/commons-codec-1.3.jar:lib/jline-0.9.94.jar:lib/clojure.jar:lib/clojure-contrib.jar:lib/compojure-3.2v1.jar:lib/jetty-6.1.14.jar:lib/jetty-util-6.1.14.jar:lib/servlet-api-2.5-6.1.14.jar:lib/postgresql-8.4-701.jdbc4.jar:lib/stringtemplate-3.2.1.jar:lib/antlr-2.7.7.jar:lib/mail-1.4.4.jar:src/ jline.ConsoleRunner clojure.main -i $1 -r $@ diff --git a/db/0-create.psql b/db/0-create.psql index 00ea012..1316a36 100755 --- a/db/0-create.psql +++ b/db/0-create.psql @@ -9,7 +9,8 @@ CREATE TABLE users ( is_admin boolean NOT NULL DEFAULT false, avatar text NOT NULL DEFAULT '', contact text NOT NULL DEFAULT '', - bio text NOT NULL DEFAULT '' + bio text NOT NULL DEFAULT '', + profile_bg text ); CREATE TABLE rooms ( diff --git a/lib/clojure-contrib.jar b/lib/clojure-contrib.jar Binary files differindex aca1fec..883638d 100755 --- a/lib/clojure-contrib.jar +++ b/lib/clojure-contrib.jar diff --git a/lib/clojure.jar b/lib/clojure.jar Binary files differindex fce575b..eefb8fc 100755 --- a/lib/clojure.jar +++ b/lib/clojure.jar diff --git a/lib/mail-1.4.4.jar b/lib/mail-1.4.4.jar Binary files differnew file mode 100644 index 0000000..c4fc4c8 --- /dev/null +++ b/lib/mail-1.4.4.jar diff --git a/src/email.clj b/src/email.clj new file mode 100644 index 0000000..2a68e7b --- /dev/null +++ b/src/email.clj @@ -0,0 +1,68 @@ +(ns email + (:import org.antlr.stringtemplate.StringTemplateGroup) + (:require [clojure.contrib.str-utils2 :as str-utils2])) + +(defn base-mail [& m] + (let [mail (apply hash-map m) + props (java.util.Properties.)] + + (doto props + (.put "mail.smtp.host" (:host mail)) + (.put "mail.smtp.port" (:port mail)) + (.put "mail.smtp.user" (:user mail)) + (.put "mail.smtp.socketFactory.port" (:port mail)) + (.put "mail.smtp.auth" "true")) + + (if (= (:ssl mail) true) + (doto props + (.put "mail.smtp.starttls.enable" "true") + (.put "mail.smtp.socketFactory.class" + "javax.net.ssl.SSLSocketFactory") + (.put "mail.smtp.socketFactory.fallback" "false"))) + + (let [authenticator (proxy [javax.mail.Authenticator] [] + (getPasswordAuthentication + [] + (javax.mail.PasswordAuthentication. + (:user mail) (:password mail)))) + session (javax.mail.Session/getDefaultInstance props authenticator) + msg (javax.mail.internet.MimeMessage. session)] + + (.setFrom msg (javax.mail.internet.InternetAddress. (:user mail))) + (doseq [to (:to mail)] + (.setRecipients msg + (javax.mail.Message$RecipientType/TO) + (javax.mail.internet.InternetAddress/parse to))) + (.setSubject msg (:subject mail)) + (.setText msg (:text mail)) + (javax.mail.Transport/send msg)))) + +(def mail-templates (new StringTemplateGroup "dumpfm-mail" "template/mail")) +(.setRefreshInterval mail-templates 3) + +(defn parse-mail-template [temp props] + (let [st (.getInstanceOf mail-templates temp)] + (doseq [[k v] props] + (.setAttribute st k v)) + (let [[s b] (.split (.toString st) "\\n" 2)] + [(.trim (.replaceFirst s "SUBJECT: " "")) + (.trim b)]))) + +(defn dump-mail [to subject text] + (base-mail :user "info@dump.fm" + :password "dumprulez7" + :host "smtpout.secureserver.net" + :port 25 + :ssl false + :to to + :subject subject + :text text)) + +(defn send-registration-email [nick email] + (let [[s b] (parse-mail-template "welcome" {"nick" nick})] + (dump-mail [email] s b))) + +(defn send-reset-email [nick email key] + (let [[s b] (parse-mail-template "reset" {"nick" nick "key" key})] + (dump-mail [email] s b))) + diff --git a/src/site.clj b/src/site.clj index 63d2eec..75b0f52 100755 --- a/src/site.clj +++ b/src/site.clj @@ -15,6 +15,7 @@ clojure.contrib.sql clojure.contrib.str-utils compojure + email utils cookie-login session-sweeper @@ -321,6 +322,7 @@ [:nick :hash :email] [nick hash email]) (let [db-user (fetch-nick nick)] + (send-registration-email nick email) [(session-assoc-from-db db-user) (resp-success "OK")]))))) @@ -385,7 +387,8 @@ (defn directory-search [offset] (let [directory @*directory-listing* users (subvec directory - (* offset *per-directory-page*) + (min (count directory) + (* offset *per-directory-page*)) (min (count directory) (* (inc offset) *per-directory-page*))) user-ids (apply str (interpose ", " (map #(%1 :user_id) users))) @@ -400,17 +403,19 @@ ORDER BY created_on DESC LIMIT 1)")] (when (> (count user-ids) 0) (let [res (do-select [qry]) - keys (map :user_id res) - dict (zipmap keys res)] + keys (map :user_id res) + res-dict (zipmap keys res)] (map (fn [u] (let [u-id (u :user_id)] - (process-directory-listing (merge u (dict u-id))))) + (process-directory-listing (merge u (res-dict u-id))))) users))))) (defn update-directory! [] (let [qry "SELECT u.user_id, COUNT(m) as cnt FROM users u, messages m WHERE u.user_id = m.user_id + AND m.room_id = 1 + AND m.is_image = true GROUP BY u.user_id ORDER BY COUNT(m) DESC" res (vec (do-select [qry]))] @@ -434,6 +439,8 @@ (cond (= offset 0) (.setAttribute st "prev" false) (= offset 1) (.setAttribute st "prev" "") :else (.setAttribute st "prev" (str "/" (dec offset)))) + (if (> offset 0) + (.setAttribute st "cur" offset)) (.setAttribute st "next" (str "/" (inc offset))) (if (zero? (count @*directory-listing*)) (.setAttribute st "notloaded" true)) @@ -656,10 +663,23 @@ (log session (@rooms room-key) offset params) (resp-error "UNKNOWN_ROOM"))) +;; Account resets + +(defn reset-page [session] + ) + +(defn reset-account-request! [session params] + ) + +(defn reset-account! [session key] + ) + ;; Upload (def *max-image-height* 2000) (def *max-image-width* 2000) +(def *max-avatar-height* 2000) +(def *max-avatar-width* 2000) (def *vip-max-file-size* (mbytes 5)) ; don't be nuts guys (def *max-file-size* (kbytes 750)) (def *ignore-size-limit-for-vip* true) @@ -722,10 +742,6 @@ (not (validate-room-access room-key session)) [200 "UNKNOWN_ROOM"] :else (do-upload session image (@rooms room-key))))) -(defn copy-and-resize [image dest] - ; TODO: resize - (copy image dest)) - ;; N.B. -- Upload responses aren't JSON-evaluated (defn do-upload-avatar [session image] (let [filename (format-filename (:filename image) (session :nick)) @@ -733,7 +749,7 @@ dest (open-file [*avatar-directory* date] filename) url (image-url-from-file "avatars" date dest)] (do - (copy-and-resize (:tempfile image) dest) + (copy (:tempfile image) dest) (update-user-db (session :user_id) "avatar" url) [(session-assoc :avatar url) [200 url]]))) @@ -793,6 +809,7 @@ (-> request :route-params :room) (-> request :route-params :offset) params)) + ;; TODO: add form tokens for all destructive actions (POST "/msg" (validated-msg session params)) (POST "/submit-registration" (register session params)) (POST "/update-profile" (update-profile session params)) @@ -802,6 +819,9 @@ (GET "/directory" (directory session 0)) (GET "/directory/:offset" (directory session (maybe-parse-int (-> request :route-params :offset) 0))) + (GET "/reset" (reset-page session)) + (POST "/reset-request" (reset-account-request! session params)) + (POST "/reset/:key" (reset-account! session (-> request :route-params :key))) (GET "/about_us" (serve-template "about_us" session)) (GET "/goodies" (serve-template "goodies" session)) (GET "/help" (serve-template "help" session)) diff --git a/static/index.html b/static/index.html index badf35a..d8e0de1 100755 --- a/static/index.html +++ b/static/index.html @@ -1,230 +1,198 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" -"http://www.w3.org/TR/html4/strict.dtd"> - -<html><head> -<title>dump.fm</title> +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<html> + <head> + <title>dump.fm</title> + <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <META NAME="keywords" CONTENT="dump.fm, image chat, realtime, internet 3.0, dump, dump fm, image dump, pictures, image links, image board"> -<META NAME="description" CONTENT="Talk with pictures!"> -<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script> -<script type="text/javascript" src="/static/js/sha1.js"></script> -<script type="text/javascript" src="/static/js/home.js"></script> -<script> -$(document).ready(initLoginForm); -function MM_swapImgRestore() { //v3.0 - var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc; -} -function MM_preloadImages() { //v3.0 - var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array(); - var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++) - if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}} -} - -function MM_findObj(n, d) { //v4.01 - var p,i,x; if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) { - d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);} - if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n]; - for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document); - if(!x && d.getElementById) x=d.getElementById(n); return x; -} - -function MM_swapImage() { //v3.0 - var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3) - if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];} -} -</script> -<link rel="stylesheet" type="text/css" href="static/reset.css"> - <link rel="shortcut icon" href="static/favicon.ico"> - <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>dump.fm</title></head> -<style type="text/css"> - - - -body { - background:#EEF2FF url(/static/fade-blue.png) top center repeat-x; - background-repeat:repeat-x; - background-position:top; - margin:6%; -} -#preload { - position: absolute; - left: 0px; - top: 0px; -} -#main { - width:460px; - margin: 0 auto 0 auto; - padding: 19px 0; - border-radius: 15px; - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border:solid 1px #fff; - position: relative; - box-shadow: 0 0 10px #d8dbde, 0px 0px 10px #d8dbde; - -webkit-box-shadow: 0 0 10px #d8dbde, 0px 0px 10px #d8dbde; - -moz-box-shadow: 0 0 10px #d8dbde, 0px 0px 10px #d8dbde; -} -#logo-and-text { - position: relative; - z-index: 20; - padding-bottom: 20px; -} - -#horse { - position: absolute; - z-index: 10; - top: 12px; - left: 140px; -} -#remember{ + <META NAME="description" CONTENT="Talk with pictures!"> + <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script> + <script type="text/javascript" src="/static/js/sha1.js"></script> + <script type="text/javascript" src="/static/js/home.js"></script> + <script> + $(document).ready(initLoginForm); + </script> + <link rel="stylesheet" type="text/css" href="static/reset.css"> + <link rel="shortcut icon" href="static/favicon.ico"> + <style type="text/css"> + body { + background:#EEF2FF url(/static/fade-blue.png) top center repeat-x; + background-repeat:repeat-x; + background-position:top; + margin:6%; + } + #preload { + position: absolute; + left: 0px; + top: 0px; + } + #main { + width:460px; + margin: 0 auto 0 auto; + padding: 19px 0; + border-radius: 15px; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border:solid 1px #fff; + position: relative; + box-shadow: 0 0 10px #d8dbde, 0px 0px 10px #d8dbde; + -webkit-box-shadow: 0 0 10px #d8dbde, 0px 0px 10px #d8dbde; + -moz-box-shadow: 0 0 10px #d8dbde, 0px 0px 10px #d8dbde; + } + #logo-and-text { + position: relative; + z-index: 20; + padding-bottom: 20px; + } -} -#customer { - position: absolute; - left: -90px; - top: -75px; - z-index: 10; + #horse { + position: absolute; + z-index: 10; + top: 12px; + left: 140px; + } + #remember{ -} -#info { - width:420px; - margin: 11px auto -1px auto; -opacity:0.9; -height:30; - vertical-align: bottom; -} + } + #customer { + position: absolute; + left: -90px; + top: -75px; + z-index: 10; + } + #info { + width:420px; + margin: 11px auto -1px auto; + opacity:0.9; + height:30; + vertical-align: bottom; + } -p { - font-family: Arial, Helvetica, sans-serif; - font-size: 24px; -} -.btnav { border: 0px #000 solid;} + p { + font-family: Arial, Helvetica, sans-serif; + font-size: 24px; + } -.submit { - - text-shadow: -1px 1px 1px #ccc; - font-size:15px; -} + .btnav { border: 0px #000 solid;} -input { - height:40px; - width:300px; - border:3px #000; - background:#e3e3e3; - margin:10px; - color:#000; - font-size:30px; - -} -.txt { - font-family:Arial, Helvetica, sans-serif; - font-size:14px; -line-height:1.2; - text-shadow:1px 1px 0.5px #ccc; - word-spacing: 3px; -} - .line { - font-family:Arial, Helvetica, sans-serif; - letter-spacing:0px; -line-height:-1; - color:#000; - font-size:17px; -} + .submit { + + text-shadow: -1px 1px 1px #ccc; + font-size:15px; + } -.no-cursor { cursor: none; } -.invisible { display: none !important; } -#cursor-big { position: absolute; z-index: 1000; } + input { + height:40px; + width:300px; + border:3px #000; + background:#e3e3e3; + margin:10px; + color:#000; + font-size:30px; + + } + .txt { + font-family:Arial, Helvetica, sans-serif; + font-size:14px; + line-height:1.2; + text-shadow:1px 1px 0.5px #ccc; + word-spacing: 3px; + } + .line { + font-family:Arial, Helvetica, sans-serif; + letter-spacing:0px; + line-height:-1; + color:#000; + font-size:17px; + } -#signin-submit { - display:inline-block; - width:300px; - height:33px; - font-size:20px; - background-image:url(/static/btngrad1.png); - font-weight:bold; - word-spacing:7; - margin-top:12px; - text-align:center; - z-index:100; - font-size:16px; - color:#fff; - text-shadow:1px 1px 3px #000; - border-radius: 5px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px;*/ - border:solid 1px #eee; -} + .no-cursor { cursor: none; } + .invisible { display: none !important; } + #cursor-big { position: absolute; z-index: 1000; } -#remembermeInput { - width: 15px; - height: 15px; - margin: 1px; -} + #signin-submit { + display:inline-block; + width:300px; + height:33px; + font-size:20px; + background-image:url(/static/btngrad1.png); + font-weight:bold; + word-spacing:7; + margin-top:12px; + text-align:center; + z-index:100; + font-size:16px; + color:#fff; + text-shadow:1px 1px 3px #000; + border-radius: 5px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px;*/ + border:solid 1px #eee; + } -label { - display: block; - width: 300px; - text-align: right; - font-size: 16px; - color: #222; -} + #remembermeInput { + width: 15px; + height: 15px; + margin: 1px; + } - -</style> -</head> -<body> - -<div id="main" align="center"> - - <img src="/static/flyhorse.gif" id="horse" /> - <img src="/static/guaranteed_customer_satisfaction.gif" id="customer" /> - - <div id="registerbox"> - <div id="logo-and-text"> - <a href="/"><img src="/static/dumpmod1.png"></a> - <p align="center" class="line">Talk with pictures!</p> - <div align="right" class="txt"> - <br> - <div align="center">dump.fm lets you talk with pictures<br> - <a href="/register" style="text-decoration:none;">Click here to Register!</a> <br> + label { + display: block; + width: 300px; + text-align: right; + font-size: 16px; + color: #222; + } + </style> + </head> + <body> + <div id="main" align="center"> + + <img src="/static/flyhorse.gif" id="horse" /> + <img src="/static/guaranteed_customer_satisfaction.gif" id="customer" /> + + <div id="registerbox"> + <div id="logo-and-text"> + <a href="/"><img src="/static/dumpmod1.png"></a> + <p align="center" class="line">Talk with pictures!</p> + <div align="right" class="txt"> + <br> + <div align="center">dump.fm lets you talk with pictures<br> + <a href="/register" style="text-decoration:none;">Click here to Register!</a> <br> + </div> + </div> + <input type="text" id="nickInput" size="17" /> + <input id="passwordInputLabel" name="passwordInputLabel" size="17" type="text" class="invisible"> + <input type="password" id="passwordInput" size="17" /><br /> + <input id="signin-submit" value="Sign In" /> + <div id="remember"><label> + <input checked="checked" type="checkbox" name="rememberme" id="remembermeInput" /> + Remember Me + </label></div> </div> </div> - </div> - <input type="text" id="nickInput" size="17" /> - <input id="passwordInputLabel" name="passwordInputLabel" size="17" type="text" class="invisible"> - <input type="password" id="passwordInput" size="17" /><br /> - - - <!-- <br /><a id="signin-submit">Sign In</a> --> - <input id="signin-submit" value="Sign In" /> - <div id="remember"><label> - <input checked="checked" type="checkbox" name="rememberme" id="remembermeInput" /> - Remember Me - </label></div> - </div> -</div> -<div id="info" align="right"> - <img src="/static/vxhtml.gif"> - <img src="/static/aol_suck.gif"> - <img src="/static/html_3_2.gif"> - <img src="/static/geocities.gif"> - <img src="/static/valid_html.gif"> -</div> - -<div id="preload"> - <img src="/static/img/cursors/osx.hand.gif" class="no-cursor invisible" id="cursor-big"> -</div> + <div id="info" align="right"> + <img src="/static/vxhtml.gif"> + <img src="/static/aol_suck.gif"> + <img src="/static/html_3_2.gif"> + <img src="/static/geocities.gif"> + <img src="/static/valid_html.gif"> + </div> -<script type="text/javascript"> -var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); -document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E")); -</script> -<script type="text/javascript"> -try { -var pageTracker = _gat._getTracker("UA-12364576-1"); -pageTracker._trackPageview(); -} catch(err) {}</script> + <div id="preload"> + <img src="/static/img/cursors/osx.hand.gif" class="no-cursor invisible" id="cursor-big"> + </div> -</body> + <script type="text/javascript"> + var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); + document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E")); + </script> + <script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-12364576-1"); + pageTracker._trackPageview(); + } catch(err) {} + </script> + </body> </html> diff --git a/static/js/home.js b/static/js/home.js index e9be833..072617a 100755 --- a/static/js/home.js +++ b/static/js/home.js @@ -171,3 +171,31 @@ function login() { error: onError }); }; + + +function MM_swapImgRestore() { //v3.0 + var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc; +} +function MM_preloadImages() { //v3.0 + var d=document; if(d.images){ + if(!d.MM_p) d.MM_p=new Array(); + var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++) + if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}} +} + +function MM_findObj(n, d) { //v4.01 + var p,i,x; if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) { + d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);} + if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n]; + for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document); + if(!x && d.getElementById) x=d.getElementById(n); return x; +} + +function MM_swapImage() { //v3.0 + var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3) + if ((x=MM_findObj(a[i]))!=null){ + document.MM_sr[j++]=x; + if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2]; + } +} + diff --git a/static/js/pichat.js b/static/js/pichat.js index aa02aae..a13b572 100755 --- a/static/js/pichat.js +++ b/static/js/pichat.js @@ -7,67 +7,67 @@ var MaxImagePosts = 40 // use e.g. "backgroundColor" not "background-color" function isCSSPropertySupported(prop){ - return prop in document.body.style; + return prop in document.body.style; } function escapeHtml(txt) { - if (!txt) { return ""; } - else { return $("<span>").text(txt).html(); } + if (!txt) { return ""; } + else { return $("<span>").text(txt).html(); } } function linkify(text) { - LastMsgContainsImage = false - var URLRegex = /((\b(http\:\/\/|https\:\/\/|ftp\:\/\/)|(www\.))+(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi; - return text.replace(URLRegex, linkReplace); + LastMsgContainsImage = false + var URLRegex = /((\b(http\:\/\/|https\:\/\/|ftp\:\/\/)|(www\.))+(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi; + return text.replace(URLRegex, linkReplace); } // durty hack to use a global to check this... but otherwise i'd have to rewrite the String.replace function? :/ var LastMsgContainsImage = false -function linkReplace(url){ - var PicRegex = /\.(jpg|jpeg|png|gif|bmp)$/i; - var urlWithoutParams = url.replace(/\?.*$/i, ""); - - if (url.indexOf('http://') == 0 || url.indexOf('https://') == 0 || url.indexOf('ftp://') == 0) - linkUrl = url; - else - linkUrl = 'http://' + url; - - if (PicRegex.test(urlWithoutParams)){ - LastMsgContainsImage = true - return "<a target='_blank' href='" + linkUrl + "'><img src='" + linkUrl + "'></a>" - } else { - return "<a target='_blank' href='" + linkUrl + "'>" + url + "</a>" - } +function linkReplace(url) { + var PicRegex = /\.(jpg|jpeg|png|gif|bmp)$/i; + var urlWithoutParams = url.replace(/\?.*$/i, ""); + + if (url.indexOf('http://') == 0 || url.indexOf('https://') == 0 || url.indexOf('ftp://') == 0) + linkUrl = url; + else + linkUrl = 'http://' + url; + + if (PicRegex.test(urlWithoutParams)){ + LastMsgContainsImage = true + return "<a target='_blank' href='" + linkUrl + "'><img src='" + linkUrl + "'></a>" + } else { + return "<a target='_blank' href='" + linkUrl + "'>" + url + "</a>" + } } function linkifyWithoutImage(text) { - LastMsgContainsImage = false - var URLRegex = /((\b(http\:\/\/|https\:\/\/|ftp\:\/\/)|(www\.))+(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi; - return text.replace(URLRegex, linkReplaceWithoutImage); + LastMsgContainsImage = false + var URLRegex = /((\b(http\:\/\/|https\:\/\/|ftp\:\/\/)|(www\.))+(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi; + return text.replace(URLRegex, linkReplaceWithoutImage); } function linkReplaceWithoutImage(url){ - var PicRegex = /\.(jpg|jpeg|png|gif|bmp)$/i; - var urlWithoutParams = url.replace(/\?.*$/i, ""); - linkUrl = url.indexOf('http://') == 0 ? url : 'http://' + url; + var PicRegex = /\.(jpg|jpeg|png|gif|bmp)$/i; + var urlWithoutParams = url.replace(/\?.*$/i, ""); + linkUrl = url.indexOf('http://') == 0 ? url : 'http://' + url; - return "<a target='_blank' href='" + linkUrl + "'>" + url + "</a>" + return "<a target='_blank' href='" + linkUrl + "'>" + url + "</a>" } // Message Handling var ImageMsgCount = 0 function removeOldMessages(){ - // don't count posts that are all text - if (LastMsgContainsImage) ImageMsgCount += 1; - while (ImageMsgCount > MaxImagePosts) { - var imgMsg = $(".contains-image:first") - if (imgMsg.length) { - imgMsg.prevAll().remove() // remove all text messages before the image message - imgMsg.remove() - } else break; - ImageMsgCount -= 1; - } + // don't count posts that are all text + if (LastMsgContainsImage) ImageMsgCount += 1; + while (ImageMsgCount > MaxImagePosts) { + var imgMsg = $(".contains-image:first") + if (imgMsg.length) { + imgMsg.prevAll().remove() // remove all text messages before the image message + imgMsg.remove() + } else break; + ImageMsgCount -= 1; + } } function buildMsgContent(content) { @@ -75,15 +75,15 @@ function buildMsgContent(content) { } function buildMessageDiv(msg, isLoading) { - removeOldMessages() - var nick = escapeHtml(msg.nick); - var msgId = !isLoading ? 'id="message-' + msg.msg_id + '"' : ''; - var loadingClass = isLoading ? ' loading' : ''; - var containsImageClass = LastMsgContainsImage ? ' contains-image' : ''; - return '<div class="msgDiv ' + loadingClass + containsImageClass + '" ' + msgId + '>' - + '<b><a href="/u/' + nick + ' ">' + nick + '</a>: </b>' - + buildMsgContent(msg.content) - + '</div>'; + removeOldMessages() + var nick = escapeHtml(msg.nick); + var msgId = !isLoading ? 'id="message-' + msg.msg_id + '"' : ''; + var loadingClass = isLoading ? ' loading' : ''; + var containsImageClass = LastMsgContainsImage ? ' contains-image' : ''; + return '<div class="msgDiv ' + loadingClass + containsImageClass + '" ' + msgId + '>' + + '<b><a href="/u/' + nick + ' ">' + nick + '</a>: </b>' + + buildMsgContent(msg.content) + + '</div>'; } function buildUserDiv(user) { @@ -95,6 +95,7 @@ function buildUserDiv(user) { } else { return '<div class="username">' + '<a href="/u/' + escapeHtml(user.nick) + '" target="_blank">' + + '<img src="/static/noinfo.png" width="50" height="50">' + escapeHtml(user.nick) + '</a></div>'; } } @@ -139,8 +140,8 @@ function submitMessage() { var div = addNewMessage(msg, true); var onSuccess = function(json) { - if (typeof pageTracker !== 'undefined') { - pageTracker._trackEvent('Message', 'Submit', typeof Room !== 'undefined' ? Room : 'UnknownRoom'); + if (typeof pageTracker !== 'undefined') { + pageTracker._trackEvent('Message', 'Submit', typeof Room !== 'undefined' ? Room : 'UnknownRoom'); } div.attr('id', 'message-' + json) .removeClass('loading').addClass('loaded'); @@ -207,11 +208,11 @@ function updateUI(msgs, users) { } function sortUsersByAlpha(a, b){ - var nickA = a.nick.toLowerCase() - var nickB = b.nick.toLowerCase() - if (nickA > nickB) return 1 - else if (nickA < nickB) return -1 - return 0 + var nickA = a.nick.toLowerCase() + var nickB = b.nick.toLowerCase() + if (nickA > nickB) return 1 + else if (nickA < nickB) return -1 + return 0 } function isDuplicateMessage(m) { @@ -312,7 +313,7 @@ function activateProfileEditable() { var onSubmit = function(attr, newVal, oldVal) { newVal = $.trim(newVal); if (newVal == oldVal) { return oldVal }; - + $.ajax({ type: "POST", timeout: 5000, @@ -386,13 +387,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 r = typeof Room !== 'undefined' ? Room : 'UnknownRoom'; + pageTracker._trackEvent('Message', 'Upload', r); } } new AjaxUpload(elementId, { @@ -400,7 +417,7 @@ function setupUpload(elementId, roomKey) { autoSubmit: true, name: 'image', data: { room: roomKey }, - onSubmit: onSubmit, + onSubmit: onSubmit, onComplete: onComplete }); } @@ -432,50 +449,50 @@ function setupUploadAvatar(elementId) { onComplete: onComplete }); } - + // scrolling stuff // this code keeps the div scrolled to the bottom, but will also let the user scroll up, without jumping down function isScrolledToBottom(){ - var threshold = 15; - - var containerHeight = messageList.style.pixelHeight || messageList.offsetHeight - var currentHeight = (messageList.scrollHeight > 0) ? messageList.scrollHeight : 0 + var threshold = 15; + + var containerHeight = messageList.style.pixelHeight || messageList.offsetHeight + var currentHeight = (messageList.scrollHeight > 0) ? messageList.scrollHeight : 0 - var result = (currentHeight - messageList.scrollTop - containerHeight < threshold); + var result = (currentHeight - messageList.scrollTop - containerHeight < threshold); - return result; + return result; } function scrollIfPossible(){ - if (lastScriptedScrolledPosition <= messageList.scrollTop || isScrolledToBottom()) - scrollToEnd() + if (lastScriptedScrolledPosition <= messageList.scrollTop || isScrolledToBottom()) + scrollToEnd() } var lastScriptedScrolledPosition = 0 function scrollToEnd(){ - messageList.scrollTop = messageList.scrollHeight - lastScriptedScrolledPosition = messageList.scrollTop + messageList.scrollTop = messageList.scrollHeight + lastScriptedScrolledPosition = messageList.scrollTop } function scrollWatcher(){ - scrollIfPossible() - setTimeout(scrollWatcher, 500) + scrollIfPossible() + setTimeout(scrollWatcher, 500) } // well fuck webkit for not supporting {text-decoration: blink} function blinkStart(){ - blinkTimer = setInterval(function(){ - $(".blink").removeClass("blink").addClass("blink-turning-off") - $(".blink-off").removeClass("blink-off").addClass("blink") - $(".blink-turning-off").removeClass("blink-turning-off").addClass("blink-off") - },500); + blinkTimer = setInterval(function(){ + $(".blink").removeClass("blink").addClass("blink-turning-off") + $(".blink-off").removeClass("blink-off").addClass("blink") + $(".blink-turning-off").removeClass("blink-turning-off").addClass("blink-off") + },500); } function blinkStop(){ - clearInterval(blinkTimer); + clearInterval(blinkTimer); } function initDirectory() { @@ -489,104 +506,106 @@ function initDirectory() { // TODO: replace this with simple pointer-events thing. function initBigHand(id){ - var cursorId = "#cursor-big" - var cursor = $(cursorId)[0] - - // jquery's reported element sizes are not exactly the same as the browser's 'mouseover' target sizes - // so we'll allow a few pixels extra - var fudgeFactor = 2 + var cursorId = "#cursor-big" + var cursor = $(cursorId)[0] + + // jquery's reported element sizes are not exactly the same as the browser's 'mouseover' target sizes + // so we'll allow a few pixels extra + var fudgeFactor = 2 - $(id).addClass("no-cursor") + $(id).addClass("no-cursor") - // i have to do this weirdly bc putting the cursor image where the mouse cursor is causes problems with mouse events: - // * it stops mousemove events on the image below the mouse cursor - // * it fucks up mouseover/out and even mouseenter/leave events, as well as click - - // so i am doing this: - // on mousing over the image: - // make cursor visible - // find image co-ords - // bind a global mousemove func - // bind cursor click event - // unbind mouseover - // mousemove func: - // move image to mouse co-ords - // if mouse co-ords are outside the image co-ords: - // make cursor invisible - // unbind mousemove func - // unbind cursor click event + // i have to do this weirdly bc putting the cursor image where the mouse cursor is causes problems with mouse events: + // * it stops mousemove events on the image below the mouse cursor + // * it fucks up mouseover/out and even mouseenter/leave events, as well as click + + // so i am doing this: + // on mousing over the image: + // make cursor visible + // find image co-ords + // bind a global mousemove func + // bind cursor click event + // unbind mouseover + // mousemove func: + // move image to mouse co-ords + // if mouse co-ords are outside the image co-ords: + // make cursor invisible + // unbind mousemove func + // unbind cursor click event - var mousemove = function(e){ - var y = e.pageY, x = e.pageX, coords = initBigHand.coords + var mousemove = function(e){ + var y = e.pageY, x = e.pageX, coords = initBigHand.coords + + cursor.style.top = y + "px" + cursor.style.left = x - 32 + "px" // 32: (4 pixels * 8 pixels per big pixel) to line up pointy finger with cursor + if (y < coords.top || + y > coords.bottom || + x < coords.left || + x > coords.right) { + $(cursorId).addClass('invisible') + $(cursorId).css({"top": 0, "left": 0 }) + $(cursorId).unbind('click', cursorClick) + $('logo7').unbind('mousemove', mousemove) + $(id).mouseover(imageMouseOver) + } + } - cursor.style.top = y + "px" - cursor.style.left = x - 32 + "px" // 32: (4 pixels * 8 pixels per big pixel) to line up pointy finger with cursor - if (y < coords.top || - y > coords.bottom || - x < coords.left || - x > coords.right) { - $(cursorId).addClass('invisible') - $(cursorId).css({"top": 0, "left": 0 }) - $(cursorId).unbind('click', cursorClick) - $('logo7').unbind('mousemove', mousemove) - $(id).mouseover(imageMouseOver) - } - } - - var cursorClick = function(){ $(id).click() } - - var imageMouseOver = function(){ - //console.log("moused over...") - initBigHand.coords = { - "left": $(id).offset().left - fudgeFactor, - "top": $(id).offset().top - fudgeFactor, - "right": $(id).offset().left + $(id).width() + fudgeFactor, - "bottom": $(id).offset().top + $(id).height() + fudgeFactor + var cursorClick = function(){ $(id).click() } + + var imageMouseOver = function(){ + //console.log("moused over...") + initBigHand.coords = { + "left": $(id).offset().left - fudgeFactor, + "top": $(id).offset().top - fudgeFactor, + "right": $(id).offset().left + $(id).width() + fudgeFactor, + "bottom": $(id).offset().top + $(id).height() + fudgeFactor + } + $('body').mousemove(mousemove) + $(cursorId).click(cursorClick) + $(cursorId).removeClass('invisible') + $(id).unbind('mouseover', imageMouseOver) } - $('body').mousemove(mousemove) - $(cursorId).click(cursorClick) - $(cursorId).removeClass('invisible') - $(id).unbind('mouseover', imageMouseOver) - } - - $(id).mouseover(imageMouseOver) - + + $(id).mouseover(imageMouseOver) + } Share = { - "getMessage": function(button){ - var message = $(button).parents(".logged-dump") - var id = message.attr("id").substr(8) // cut "message-001" to "001" - var nick = message.attr("nick") // cut "/u/timb" to "timb" - var link = "http://dump.fm/p/" + nick + "/" + id - var content = message.find(".linkify") - if (!content.length) content = message.find(".content") - var rawContent = content.html() - var img = content.find("img").attr("src") - var via = "via " + nick + " on dump.fm" - return {"nick": nick, "id": id, "link": encodeURIComponent(link), "content": content, "img": encodeURIComponent(img), "via": encodeURIComponent(via)} - }, - "openLink": function(url){ - window.open(url, "_blank") - }, - "facebook": function(button){ - var message = Share.getMessage(button) - var url = "http://www.facebook.com/share.php?u=" + message.img + "&t=" + message.via - Share.openLink(url) - }, - "tumblr": function(button){ - var message = Share.getMessage(button) - var url = "http://www.tumblr.com/share?v=3&u=" + message.img + "&t=" + message.via - Share.openLink(url) - }, - "twitter": function(button){ - var message = Share.getMessage(button) - var url = "http://twitter.com/home?status=" + message.img + encodeURIComponent(" ") + message.via - Share.openLink(url) - }, - "delicious": function(button){ - var message = Share.getMessage(button) - var url = "http://delicious.com/save?url=" + message.img + "&title=" + message.img + "¬es=" + message.via - Share.openLink(url) - } + "getMessage": function(button){ + var message = $(button).parents(".logged-dump") + var id = message.attr("id").substr(8) // cut "message-001" to "001" + var nick = message.attr("nick") // cut "/u/timb" to "timb" + var link = "http://dump.fm/p/" + nick + "/" + id + var content = message.find(".linkify") + if (!content.length) content = message.find(".content") + var rawContent = content.html() + var img = content.find("img").attr("src") + var via = "via " + nick + " on dump.fm" + return {"nick": nick, "id": id, "link": encodeURIComponent(link), + "content": content, "img": encodeURIComponent(img), + "via": encodeURIComponent(via)} + }, + "openLink": function(url){ + window.open(url, "_blank") + }, + "facebook": function(button){ + var message = Share.getMessage(button) + var url = "http://www.facebook.com/share.php?u=" + message.img + "&t=" + message.via + Share.openLink(url) + }, + "tumblr": function(button){ + var message = Share.getMessage(button) + var url = "http://www.tumblr.com/share?v=3&u=" + message.img + "&t=" + message.via + Share.openLink(url) + }, + "twitter": function(button){ + var message = Share.getMessage(button) + var url = "http://twitter.com/home?status=" + message.img + encodeURIComponent(" ") + message.via + Share.openLink(url) + }, + "delicious": function(button){ + var message = Share.getMessage(button) + var url = "http://delicious.com/save?url=" + message.img + "&title=" + message.img + "¬es=" + message.via + Share.openLink(url) + } }
\ No newline at end of file diff --git a/template/directory.st b/template/directory.st index 8c734d9..aec8363 100644 --- a/template/directory.st +++ b/template/directory.st @@ -1,7 +1,10 @@ <html> <head> - - <title>dump.fm</title> + $if(cur)$ + <title>dump.fm directory [$cur$]</title> + $else$ + <title>dump.fm directory</title> + $endif$ $head()$ <link rel="stylesheet" type="text/css" href="/static/directory.css"> <script> |
