summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbin/repl.bat2
-rwxr-xr-xdb/0-create.psql28
-rwxr-xr-xlib/postgresql-8.4-701.jdbc4.jarbin0 -> 510170 bytes
-rw-r--r--src/site.clj67
-rwxr-xr-xstatic/index.html77
-rwxr-xr-xstatic/pichat.css35
-rwxr-xr-xstatic/pichat.js51
-rwxr-xr-xstatic/register.html26
-rwxr-xr-xstatic/register.js30
-rwxr-xr-xstatic/sha1.js330
-rwxr-xr-xstatic/style.css21
11 files changed, 591 insertions, 76 deletions
diff --git a/bin/repl.bat b/bin/repl.bat
index 68b1814..faa6ee2 100755
--- a/bin/repl.bat
+++ b/bin/repl.bat
@@ -1,3 +1,3 @@
REM Windows REPL script
-java -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.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 jline.ConsoleRunner clojure.lang.Repl %1 \ No newline at end of file
+java -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.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 jline.ConsoleRunner clojure.lang.Repl %1 \ No newline at end of file
diff --git a/db/0-create.psql b/db/0-create.psql
new file mode 100755
index 0000000..39b4efd
--- /dev/null
+++ b/db/0-create.psql
@@ -0,0 +1,28 @@
+CREATE TABLE users (
+ user_id SERIAL PRIMARY KEY,
+ nick text UNIQUE NOT NULL,
+ hash text NOT NULL,
+ email text NOT NULL,
+ created_on timestamp NOT NULL DEFAULT now()
+);
+
+CREATE TABLE rooms (
+ room_id SERIAL PRIMARY KEY,
+ name text UNIQUE NOT NULL,
+ created_on timestamp NOT NULL
+);
+
+CREATE TABLE messages (
+ message_id SERIAL PRIMARY KEY,
+ user_id integer NOT NULL REFERENCES users,
+ room_id integer NOT NULL REFERENCES rooms,
+ content text NOT NULL,
+ created_on timestamp NOT NULL
+);
+
+CREATE TABLE user_session (
+ session_id bigint PRIMARY KEY,
+ user_id integer NOT NULL REFERENCES users,
+ id_address text NOT NULL,
+ ttl timestamp NOT NULL
+); \ No newline at end of file
diff --git a/lib/postgresql-8.4-701.jdbc4.jar b/lib/postgresql-8.4-701.jdbc4.jar
new file mode 100755
index 0000000..e21beec
--- /dev/null
+++ b/lib/postgresql-8.4-701.jdbc4.jar
Binary files differ
diff --git a/src/site.clj b/src/site.clj
index 8ca16d6..417130e 100644
--- a/src/site.clj
+++ b/src/site.clj
@@ -1,9 +1,20 @@
; site.clj
(ns pichat
- (:import java.lang.System)
+ (:import java.lang.System
+ org.apache.commons.codec.digest.DigestUtils)
(:use compojure
- clojure.contrib.json.write))
+ clojure.contrib.json.write
+ clojure.contrib.sql))
+
+(let [db-host "localhost"
+ db-port 5432
+ db-name "dumpfm"]
+ (def db {:classname "org.postgresql.Driver"
+ :subprotocol "postgresql"
+ :subname (str "//" db-host ":" db-port "/" db-name)
+ :user "postgres"
+ :password "root"}))
(defstruct user-struct :nick :last-seen)
(defstruct message-struct :nick :content :timestamp)
@@ -54,13 +65,59 @@
([] {"users" (sort (keys @users)) "messages" (new-messages)})
([since] {"users" (sort (keys @users)) "messages" (new-messages since)}))
+(defn do-select [query]
+ (with-connection db
+ (with-query-results rs [query]
+ (doall rs))))
+
+(defn retrieve-nick [nick]
+ (let [query (str "SELECT * FROM users WHERE nick = '" nick "'")]
+ (first (do-select query))))
+
+(defn authorize-nick-hash [nick hash]
+ (let [db-user (retrieve-nick nick)]
+ (and db-user (= (db-user :hash) hash))))
+
+(defn register [session params]
+ (let [nick (params :nick)
+ email (params :email)
+ hash (params :hash)]
+ (if (retrieve-nick nick)
+ (resp-error "NICK_TAKEN")
+ (with-connection db
+ (insert-values :users
+ [:nick :hash :email]
+ [nick hash email])
+ (resp-success "OK")))))
+
+(defn renamed-user-struct [old-nick nick]
+ (let [old-struct (@users old-nick)]
+ (if old-struct
+ (assoc old-struct :nick nick)
+ (struct user-struct nick (System/currentTimeMillis)))))
+
+(defn login [session params]
+ (let [old-nick (session :nick)
+ nick (params :nick)
+ hash (params :hash)
+ ts (params :ts)]
+ (if (authorize-nick-hash nick hash)
+ (dosync
+ (set-session {:nick nick :logged-in true})
+ (let [user-struct (renamed-user-struct old-nick nick)]
+ (alter users dissoc old-nick)
+ (alter users assoc nick user-struct)
+ [(session-assoc :nick nick :logged-in true)
+ (resp-success "OK")]))
+ (resp-error "BAD_LOGIN"))))
+
(defn init [session]
(let [new-nick (make-random-nick)]
(dosync
(alter users assoc new-nick
(struct user-struct new-nick (System/currentTimeMillis)))
[(session-assoc :nick new-nick)
- (resp-success (assoc (updates) :nick new-nick))])))
+ (resp-success (assoc (updates) :nick new-nick :loggedin false))])))
(defn refresh [nick]
(dosync
@@ -70,7 +127,6 @@
(resp-success (updates last-seen)))
(resp-error "UNKNOWN_USER"))))
-
(defn msg [session params]
(dosync
(let [nick (session :nick)
@@ -86,7 +142,10 @@
(GET "/static/*" (or (serve-file "static" (params :*))
:next))
(GET "/favicon.ico" (serve-file "static" "favicon.ico"))
+ (GET "/register" (serve-file "static" "register.html"))
+ (GET "/submit-registration" (register session params))
(GET "/init" (init (session :nick)))
+ (GET "/login" (login session params))
(GET "/refresh" (refresh (session :nick)))
(GET "/msg" (msg session params))
(ANY "*" [404 "Page not found"]))
diff --git a/static/index.html b/static/index.html
index b309f74..ae4a48f 100755
--- a/static/index.html
+++ b/static/index.html
@@ -8,64 +8,75 @@
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
+ <script type="text/javascript" src="static/sha1.js"></script>
<script type="text/javascript" src="static/pichat.js"></script>
<script>
$(document).ready(function() {
- init();
+ init();
});
</script>
<script type="text/javascript">
-function showPopup(url) {
-newwindow=window.open(url,'name','height=600,width=820,top=30,left=10,resizable');
-if (window.focus) {newwindow.focus()}
-}
-</script>
+ function showPopup(url) {
+ newwindow=window.open(url,'name','height=600,width=820,top=30,left=10,resizable');
+ if (window.focus) {newwindow.focus()}
+ }
+ </script>
</head>
<body>
+ <div id="loginbar" style="display: none">
+ <span>Username:</span><input id="nickInput" type="input" />
+ <br />
+ <span>Password:</span><input id="passwordInput" type="password" />
+ <br />
+ <input type="button" id="loginSubmit" value="login" />
+ </div>
+
<div id="content">
<div id="logo"><img src="static/bubley.png" width="332" height="113"></div>
<div id="chatbox">
+
<div id="welcomebar" style="display: none">
<span>Welcome, </span>
- <span id="nickspan"></span>
+ <span id="nickspan"></span>
+ </div>
+ <div id="messagetabs">
+ <div align="right"><a href="log.h"><img src="static/log4.png" width="97" height="39"></a></div>
</div>
- <div id="messagetabs">
- <div align="right"><a href="log.h"><img src="static/log4.png" width="97" height="39"></a></div>
- </div>
<div id="rapper">
- <div id="userListicon">
+ <div id="userListicon">
- <div align="left">
- <p>UsrLst</p>
-</div>
- </div>
- <div id="popout">
- <div align="right"><a href="http://dump.fm"onClick='showPopup(this.href);return(false);'>popout room</a></div>
- </div>
- <div id="userList"></div>
-
- <div id="messagePane">
+ <div align="left">
+ <p>UsrLst</p>
+ </div>
+ </div>
+ <div id="popout">
+ <div align="right"><a href="http://dump.fm"onClick='showPopup(this.href);return(false);'>popout room</a></div>
+ </div>
+ <div id="userList"></div>
+
+ <div id="messagePane">
- <div id="messageList"></div>
- <div id="msgInputDiv">
- <input id="msgInput" type="input" disabled="disabled" />
- <input id="msgSubmit" type="submit" value="Send Image URL"
- disabled="disabled" />
+ <div id="messageList"></div>
+ <div id="msgInputDiv">
+ <input id="msgInput" type="input" disabled="disabled" />
+ <input id="msgSubmit" type="submit" value="Send Image URL"
+ disabled="disabled" />
+ </div>
</div>
</div>
</div>
</div>
- </div>
- <div id="lillogo" align="center">
- <div align="center">
- <div id="binfo">
- <p>dump.fm lets you talk with pictures. beta 0.0127! <img src="static/lillogo.png" width="16" height="16"></p>
+
+ <div id="lillogo" align="center">
+ <div align="center">
+ <div id="binfo">
+ <p>dump.fm lets you talk with pictures. beta 0.0127! <img src="static/lillogo.png" width="16" height="16"></p>
+ </div>
</div>
+ <div id="plane"></div>
</div>
- <div id="plane"></div>
- </div>
</body>
</html>
diff --git a/static/pichat.css b/static/pichat.css
index f33f7e0..28e7431 100755
--- a/static/pichat.css
+++ b/static/pichat.css
@@ -28,8 +28,8 @@ h1,h2{
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
left:2px;
-top:5px;
- position: fixed;
+ top:5px;
+ position: fixed;
}
#messagePane {
border: 2px solid #15fff3;
@@ -37,18 +37,17 @@ top:5px;
padding: 5px;
position: fixed;
width: 80%;
-max-width:1500px;
-background-color:#FFF;
-left:35px;
-top:80px;
+ max-width:1500px;
+ background-color:#FFF;
+ left:35px;
+ top:80px;
float: left;
z-index:5;
}
#logo {
position:fixed;
left:18px;
- top:3px;
-
+ top:3px;
z-index:7;
}
#welcomebar {
@@ -57,9 +56,9 @@ top:80px;
top:20px;
font-family: Arial, Helvetica, sans-serif;
font-size: 9px;
-left:350px;
-top:67px;
- position: fixed;
+ left:350px;
+ top:67px;
+ position: fixed;
}
#messageList {
height: 100%;
@@ -173,3 +172,17 @@ height: expression(this.width > 400 ? 400: true);max-width:400px;}
font-size:10px;
text-align:right;
}
+
+#loginbar {
+ padding: 5px;
+ position: absolute;
+ bottom: 40px;
+ left: 40px;
+ line-height: 8px;
+ z-index: 2;
+ border: 1px solid #15fff3;
+}
+
+#loginsubmit {
+ float: right;
+} \ No newline at end of file
diff --git a/static/pichat.js b/static/pichat.js
index 8e8647e..d665e2b 100755
--- a/static/pichat.js
+++ b/static/pichat.js
@@ -1,6 +1,7 @@
// pichat.js
var Nick = null;
+var LoggedIn = false;
function handleMsgError(resp) {
var respText = resp.responseText ? resp.responseText.trim() : false;
@@ -49,6 +50,12 @@ function buildMessageDiv(msg) {
+ buildContent(msg.content) + '</div>';
}
+function setNick(nick) {
+ Nick = nick;
+ $('#nickspan').text(nick);
+ $('#welcomebar').show();
+}
+
function submitMessage() {
var content = $('#msgInput').val();
var msg = { 'nick': Nick, 'content': content, 'timestamp': new Date() };
@@ -64,8 +71,7 @@ function submitMessage() {
}
var onSuccess = function() {};
- var onError = function(resp, textStatus, errorThrown) {
-
+ var onError = function(resp, textStatus, errorThrown) {
handleMsgError(resp);
};
@@ -87,6 +93,33 @@ function ifEnter(fn) {
};
}
+function login() {
+ var nick = $('#nickInput').val();
+ var password = $('#passwordInput').val();
+ var hash = hex_sha1(nick + '$' + password + '$dumpfm');
+
+ var onSuccess = function(json) {
+ $('#loginbar').hide();
+ LoggedIn = true;
+ setNick(nick);
+ };
+
+ var onError = function(resp, textStatus, errorThrown) {
+ alert("Error logging in!");
+ };
+
+ $.ajax({
+ type: 'GET',
+ timeout: 5000,
+ url: 'login',
+ data: {'nick': nick, 'hash': hash },
+ cache: false,
+ dataType: 'json',
+ success: onSuccess,
+ error: onError
+ });
+};
+
function isScrolledToBottom(div) {
return Math.abs(div.scrollTop - (div.scrollHeight - div.offsetHeight)) <= 3;
}
@@ -126,15 +159,19 @@ function refresh() {
});
}
-
-
function init() {
var onSuccess = function(json) {
$('#loadingbox').hide();
Nick = json.nick;
- $('#nickspan').text(Nick);
- $('#welcomebar').show();
+ setNick(Nick);
+ if (json.loggedin) {
+ LoggedIn = true;
+ } else {
+ $('#loginbar').show();
+ $('#loginSubmit').click(login);
+ $('#passwordInput').keyup(ifEnter(login));
+ }
var msgStr = $.map(json.messages, buildMessageDiv).join('');
$('#messageList').append(msgStr);
@@ -148,7 +185,7 @@ function init() {
var onError = function(resp, textStatus, errorThrown) {
alert("Error connecting to chat server!");
- };
+ };
$.ajax({
type: 'GET',
diff --git a/static/register.html b/static/register.html
new file mode 100755
index 0000000..e5ae761
--- /dev/null
+++ b/static/register.html
@@ -0,0 +1,26 @@
+<html>
+ <head>
+ <title>dump.fm Registration</title>
+ <link rel="stylesheet" type="text/css" href="static/reset.css">
+ <link rel="shortcut icon" href="static/favicon.ico">
+ <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
+ <script type="text/javascript" src="static/sha1.js"></script>
+ <script type="text/javascript" src="static/register.js"></script>
+ <script>
+ $(document).ready(initRegister);
+ </script>
+ </head>
+ <body>
+ <h1>Register</h1>
+ <span>Nickname:</span>
+ <input type="text" id="nickInput" />
+ <br />
+ <span>Email:</span>
+ <input type="text" id="emailInput" />
+ <br />
+ <span>Password:</span>
+ <input type="password" id="passwordInput" />
+ <br />
+ <input type="submit" id="submit" value="register" />
+ </body>
+</html>
diff --git a/static/register.js b/static/register.js
new file mode 100755
index 0000000..d60f223
--- /dev/null
+++ b/static/register.js
@@ -0,0 +1,30 @@
+function submitRegistration() {
+ var nick = $('#nickInput').val();
+ var email = $('#emailInput').val();
+ var password = $('#passwordInput').val();
+ var hash = hex_sha1(nick + '$' + password + '$dumpfm');
+
+ var onSuccess = function() {
+ location.href = "/";
+ };
+
+ var onError = function() {
+ alert("Unable to register!");
+ };
+
+ $.ajax({
+ type: 'GET',
+ timeout: 5000,
+ url: 'submit-registration',
+ data: {'nick': nick, 'email': email, 'hash': hash },
+ cache: false,
+ dataType: 'json',
+ success: onSuccess,
+ error: onError
+
+ });
+}
+
+function initRegister() {
+ $('#submit').click(submitRegistration);
+} \ No newline at end of file
diff --git a/static/sha1.js b/static/sha1.js
new file mode 100755
index 0000000..56418eb
--- /dev/null
+++ b/static/sha1.js
@@ -0,0 +1,330 @@
+/*
+ * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
+ * in FIPS 180-1
+ * Version 2.2 Copyright Paul Johnston 2000 - 2009.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for details.
+ */
+
+/*
+ * Configurable variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ */
+var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
+var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
+
+/*
+ * These are the functions you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+function hex_sha1(s) { return rstr2hex(rstr_sha1(str2rstr_utf8(s))); }
+function b64_sha1(s) { return rstr2b64(rstr_sha1(str2rstr_utf8(s))); }
+function any_sha1(s, e) { return rstr2any(rstr_sha1(str2rstr_utf8(s)), e); }
+function hex_hmac_sha1(k, d)
+ { return rstr2hex(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d))); }
+function b64_hmac_sha1(k, d)
+ { return rstr2b64(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d))); }
+function any_hmac_sha1(k, d, e)
+ { return rstr2any(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
+
+/*
+ * Perform a simple self-test to see if the VM is working
+ */
+function sha1_vm_test()
+{
+ return hex_sha1("abc").toLowerCase() == "a9993e364706816aba3e25717850c26c9cd0d89d";
+}
+
+/*
+ * Calculate the SHA1 of a raw string
+ */
+function rstr_sha1(s)
+{
+ return binb2rstr(binb_sha1(rstr2binb(s), s.length * 8));
+}
+
+/*
+ * Calculate the HMAC-SHA1 of a key and some data (raw strings)
+ */
+function rstr_hmac_sha1(key, data)
+{
+ var bkey = rstr2binb(key);
+ if(bkey.length > 16) bkey = binb_sha1(bkey, key.length * 8);
+
+ var ipad = Array(16), opad = Array(16);
+ for(var i = 0; i < 16; i++)
+ {
+ ipad[i] = bkey[i] ^ 0x36363636;
+ opad[i] = bkey[i] ^ 0x5C5C5C5C;
+ }
+
+ var hash = binb_sha1(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
+ return binb2rstr(binb_sha1(opad.concat(hash), 512 + 160));
+}
+
+/*
+ * Convert a raw string to a hex string
+ */
+function rstr2hex(input)
+{
+ try { hexcase } catch(e) { hexcase=0; }
+ var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+ var output = "";
+ var x;
+ for(var i = 0; i < input.length; i++)
+ {
+ x = input.charCodeAt(i);
+ output += hex_tab.charAt((x >>> 4) & 0x0F)
+ + hex_tab.charAt( x & 0x0F);
+ }
+ return output;
+}
+
+/*
+ * Convert a raw string to a base-64 string
+ */
+function rstr2b64(input)
+{
+ try { b64pad } catch(e) { b64pad=''; }
+ var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ var output = "";
+ var len = input.length;
+ for(var i = 0; i < len; i += 3)
+ {
+ var triplet = (input.charCodeAt(i) << 16)
+ | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
+ | (i + 2 < len ? input.charCodeAt(i+2) : 0);
+ for(var j = 0; j < 4; j++)
+ {
+ if(i * 8 + j * 6 > input.length * 8) output += b64pad;
+ else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
+ }
+ }
+ return output;
+}
+
+/*
+ * Convert a raw string to an arbitrary string encoding
+ */
+function rstr2any(input, encoding)
+{
+ var divisor = encoding.length;
+ var remainders = Array();
+ var i, q, x, quotient;
+
+ /* Convert to an array of 16-bit big-endian values, forming the dividend */
+ var dividend = Array(Math.ceil(input.length / 2));
+ for(i = 0; i < dividend.length; i++)
+ {
+ dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
+ }
+
+ /*
+ * Repeatedly perform a long division. The binary array forms the dividend,
+ * the length of the encoding is the divisor. Once computed, the quotient
+ * forms the dividend for the next step. We stop when the dividend is zero.
+ * All remainders are stored for later use.
+ */
+ while(dividend.length > 0)
+ {
+ quotient = Array();
+ x = 0;
+ for(i = 0; i < dividend.length; i++)
+ {
+ x = (x << 16) + dividend[i];
+ q = Math.floor(x / divisor);
+ x -= q * divisor;
+ if(quotient.length > 0 || q > 0)
+ quotient[quotient.length] = q;
+ }
+ remainders[remainders.length] = x;
+ dividend = quotient;
+ }
+
+ /* Convert the remainders to the output string */
+ var output = "";
+ for(i = remainders.length - 1; i >= 0; i--)
+ output += encoding.charAt(remainders[i]);
+
+ /* Append leading zero equivalents */
+ var full_length = Math.ceil(input.length * 8 /
+ (Math.log(encoding.length) / Math.log(2)))
+ for(i = output.length; i < full_length; i++)
+ output = encoding[0] + output;
+
+ return output;
+}
+
+/*
+ * Encode a string as utf-8.
+ * For efficiency, this assumes the input is valid utf-16.
+ */
+function str2rstr_utf8(input)
+{
+ var output = "";
+ var i = -1;
+ var x, y;
+
+ while(++i < input.length)
+ {
+ /* Decode utf-16 surrogate pairs */
+ x = input.charCodeAt(i);
+ y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
+ if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
+ {
+ x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
+ i++;
+ }
+
+ /* Encode output as utf-8 */
+ if(x <= 0x7F)
+ output += String.fromCharCode(x);
+ else if(x <= 0x7FF)
+ output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
+ 0x80 | ( x & 0x3F));
+ else if(x <= 0xFFFF)
+ output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
+ 0x80 | ((x >>> 6 ) & 0x3F),
+ 0x80 | ( x & 0x3F));
+ else if(x <= 0x1FFFFF)
+ output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
+ 0x80 | ((x >>> 12) & 0x3F),
+ 0x80 | ((x >>> 6 ) & 0x3F),
+ 0x80 | ( x & 0x3F));
+ }
+ return output;
+}
+
+/*
+ * Encode a string as utf-16
+ */
+function str2rstr_utf16le(input)
+{
+ var output = "";
+ for(var i = 0; i < input.length; i++)
+ output += String.fromCharCode( input.charCodeAt(i) & 0xFF,
+ (input.charCodeAt(i) >>> 8) & 0xFF);
+ return output;
+}
+
+function str2rstr_utf16be(input)
+{
+ var output = "";
+ for(var i = 0; i < input.length; i++)
+ output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
+ input.charCodeAt(i) & 0xFF);
+ return output;
+}
+
+/*
+ * Convert a raw string to an array of big-endian words
+ * Characters >255 have their high-byte silently ignored.
+ */
+function rstr2binb(input)
+{
+ var output = Array(input.length >> 2);
+ for(var i = 0; i < output.length; i++)
+ output[i] = 0;
+ for(var i = 0; i < input.length * 8; i += 8)
+ output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
+ return output;
+}
+
+/*
+ * Convert an array of big-endian words to a string
+ */
+function binb2rstr(input)
+{
+ var output = "";
+ for(var i = 0; i < input.length * 32; i += 8)
+ output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF);
+ return output;
+}
+
+/*
+ * Calculate the SHA-1 of an array of big-endian words, and a bit length
+ */
+function binb_sha1(x, len)
+{
+ /* append padding */
+ x[len >> 5] |= 0x80 << (24 - len % 32);
+ x[((len + 64 >> 9) << 4) + 15] = len;
+
+ var w = Array(80);
+ var a = 1732584193;
+ var b = -271733879;
+ var c = -1732584194;
+ var d = 271733878;
+ var e = -1009589776;
+
+ for(var i = 0; i < x.length; i += 16)
+ {
+ var olda = a;
+ var oldb = b;
+ var oldc = c;
+ var oldd = d;
+ var olde = e;
+
+ for(var j = 0; j < 80; j++)
+ {
+ if(j < 16) w[j] = x[i + j];
+ else w[j] = bit_rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
+ var t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)),
+ safe_add(safe_add(e, w[j]), sha1_kt(j)));
+ e = d;
+ d = c;
+ c = bit_rol(b, 30);
+ b = a;
+ a = t;
+ }
+
+ a = safe_add(a, olda);
+ b = safe_add(b, oldb);
+ c = safe_add(c, oldc);
+ d = safe_add(d, oldd);
+ e = safe_add(e, olde);
+ }
+ return Array(a, b, c, d, e);
+
+}
+
+/*
+ * Perform the appropriate triplet combination function for the current
+ * iteration
+ */
+function sha1_ft(t, b, c, d)
+{
+ if(t < 20) return (b & c) | ((~b) & d);
+ if(t < 40) return b ^ c ^ d;
+ if(t < 60) return (b & c) | (b & d) | (c & d);
+ return b ^ c ^ d;
+}
+
+/*
+ * Determine the appropriate additive constant for the current iteration
+ */
+function sha1_kt(t)
+{
+ return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
+ (t < 60) ? -1894007588 : -899497514;
+}
+
+/*
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+function safe_add(x, y)
+{
+ var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+ var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+ return (msw << 16) | (lsw & 0xFFFF);
+}
+
+/*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+function bit_rol(num, cnt)
+{
+ return (num << cnt) | (num >>> (32 - cnt));
+} \ No newline at end of file
diff --git a/static/style.css b/static/style.css
index 8aae921..56606ae 100755
--- a/static/style.css
+++ b/static/style.css
@@ -176,31 +176,12 @@ body {
width:100%;
height:100%;
z-index:1;
- background-image: url(static/cloudbg1.png);
+ background-image: url("./cloudbg1.png");
background-repeat: no-repeat;
background-position:center;
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
.extruder{
position:fixed;
cursor:default;