From 86652e790c7de5dd3a42266b3c351116b7b1d224 Mon Sep 17 00:00:00 2001 From: mappu Date: Sat, 8 Oct 2016 14:58:37 +1300 Subject: [PATCH] initial commit --- .hgignore | 6 + Config.go | 23 ++ build.sh | 167 ++++++++ client/apple-touch-icon.png | Bin 0 -> 19872 bytes client/dcwebui.css | 396 +++++++++++++++++++ client/dcwebui.js | 747 ++++++++++++++++++++++++++++++++++++ client/favicon.ico | Bin 0 -> 6830 bytes client/index.htm | 59 +++ client/socket.io-1.4.5.js | 4 + main.go | 244 ++++++++++++ nmdc-webfrontend.conf | 23 ++ 11 files changed, 1669 insertions(+) create mode 100644 .hgignore create mode 100644 Config.go create mode 100644 build.sh create mode 100644 client/apple-touch-icon.png create mode 100644 client/dcwebui.css create mode 100644 client/dcwebui.js create mode 100644 client/favicon.ico create mode 100644 client/index.htm create mode 100644 client/socket.io-1.4.5.js create mode 100644 main.go create mode 100644 nmdc-webfrontend.conf diff --git a/.hgignore b/.hgignore new file mode 100644 index 0000000..d58532a --- /dev/null +++ b/.hgignore @@ -0,0 +1,6 @@ +mode:regex + +\.exe$ + +^_dist/ +^bindata\.go$ \ No newline at end of file diff --git a/Config.go b/Config.go new file mode 100644 index 0000000..d6c8d07 --- /dev/null +++ b/Config.go @@ -0,0 +1,23 @@ +package main + +type Config struct { + App struct { + Name string + Version string + MotdHTML string + Debug bool + } + + Web struct { + Port int + BindTo string + Extern string + Title string + } + + Hub struct { + Address string + Port int + Tag string + } +} diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..6cffd23 --- /dev/null +++ b/build.sh @@ -0,0 +1,167 @@ +#!/bin/bash +# godist.sh is a template build script for golang applications. +# +# Copyright (c) 2016, The godist.sh Author(s) +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. +# + +set -eu + +DIST_DIR=./_dist + +get_package_name() { + # Binaries are named after the containing folder. + pwd | tr / $'\n' | tail -n1 +} + +check_dependencies() { + # `set -e` will take care of killing the application if the dependency + # goes unresolved. + which 7z > /dev/null + which php > /dev/null +} + +get_platform_description() { + if [[ $GOOS == windows ]] ; then + echo -n "win" + else + echo -n "${GOOS}" + fi + + if [[ $GOARCH == 386 ]] ; then + echo -n 32 + elif [[ $GOARCH == amd64 ]] ; then + echo -n 64 + else + echo -n "-${GOARCH}" + if [[ -v $GOARM ]] ; then + echo -n "v${GOARM}" + fi + fi +} + +pathfix() { + if [[ $(uname -o) == Cygwin ]] ; then + cygpath -w "$1" + else + echo "$1" + fi +} + +single_build() { + local version="$1" + + # Determine build output name + local bin_name='' + if [[ $GOOS == windows ]] ; then + local_bin_name="$(get_package_name).exe" + else + local_bin_name="$(get_package_name)" + fi + + if [[ -f ./$local_bin_name ]] ; then + rm -f "./$local_bin_name" + fi + + local tmpdir=$(mktemp -d) + + # Platform identifier + local platform="$(get_platform_description)" + echo "[INFO] Building ${version} for ${platform}..." + + # Build. + # GOARCH/GOOS supplied in function env + go build \ + -a \ + -ldflags '-s -w' \ + -gcflags "-trimpath=${GOPATH}" \ + -asmflags "-trimpath=${GOPATH}" \ + -o "$(pathfix "${tmpdir}/${local_bin_name}")" + + # Archive. + if [[ ! -d $DIST_DIR ]] ; then + mkdir "$DIST_DIR" + fi + local archive_name="${DIST_DIR}/$(get_package_name)-${version}-${platform}" + if [[ $GOOS == windows ]] ; then + archive_name="${archive_name}.7z" + 7z a -mx9 "$archive_name" "${tmpdir}/${local_bin_name}" >/dev/null + else + archive_name="${archive_name}.tar.xz" + XZ_OPT='-9' tar caf "$archive_name" -C "${tmpdir}" "${local_bin_name}" --owner=0 --group=0 >/dev/null + fi + + # Cleanup + rm -f "${tmpdir}/${local_bin_name}" + rmdir "$tmpdir" + +} + +datestamp() { + ( TZ=UTC date +%Y%m%d%H%M%SZ ) +} + +usage() { + cat <&2 + exit 1 + fi + if [[ ! -d $GOPATH ]] ; then + echo "Invalid GOPATH set." >&2 + exit 1 + fi + + local version="" + while getopts ':v:' flag ; do + case "$flag" in + v) + version="$OPTARG" + ;; + *) + usage + ;; + esac + done + + if [[ $version == "" ]] ; then + read -p "Enter version string (blank for timestamp)> " version + if [[ $version == "" ]] ; then + version=$(datestamp) + fi + fi + + if [[ -f ./bindata.go ]] ; then + rm ./bindata.go + fi + go-bindata -nomemcopy -prefix client client + + GOARCH=amd64 GOOS=windows single_build "$version" + GOARCH=386 GOOS=windows single_build "$version" + GOARCH=amd64 GOOS=linux single_build "$version" + GOARCH=386 GOOS=linux single_build "$version" + + echo "[INFO] Build complete." +} + +main "$@" diff --git a/client/apple-touch-icon.png b/client/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..7746f2ea063a476d2abb188e37fc05b3700b661a GIT binary patch literal 19872 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 literal 0 HcmV?d00001 diff --git a/client/dcwebui.css b/client/dcwebui.css new file mode 100644 index 0000000..45e7291 --- /dev/null +++ b/client/dcwebui.css @@ -0,0 +1,396 @@ +/* dcwebui.css */ + +* { + -webkit-text-size-adjust:100% + -moz-text-size-adjust:100% + -ms-text-size-adjust:100% +} + +html,body { + height:100%; + width:100%; + margin:0; + padding:0; + border:0; + font-family:Geneva,Helvetica,Arial,sans-serif; + font-size: 12px; +} +.placement-top { + height:24px; + + position:absolute; + top:0; + left:0; + right:0; +} +.placement-mid { + position:absolute; + top:24px; + right:0; + bottom:40px; + left:0; +} +.placement-bottom { + height:40px; + + position:absolute; + bottom:0; + left:0; + right:0; +} +.placement-panel { + width:150px; + + position:absolute; + right:0; + top:24px; + bottom:40px; +} +.placement-vary { + /* Nothing, at this media query level */ +} + +/* WiiU placements */ +.navigator-wiiu .placement-mid { + bottom:120px; +} +.navigator-wiiu .placement-bottom { + height:120px; +} +.navigator-wiiu .placement-panel { + bottom:120px; +} + +/* Menu button */ +.menubutton { + position:absolute; + right:2px; + top:2px; + + cursor:pointer; + color:black; + font-weight:bold; + + line-height:18px; + width:18px; + text-align:center; +} +.menubutton:hover { + background:white; +} +/* Menu list */ +.menu { + background:#DDD; + + box-shadow: 0 4px 24px #CCC; + + display:none; /* default state */ + + position:absolute; /* but not positioned anywhere specifically */ + + width:200px; + z-index:10; /* above placement-panel */ + + overflow-y:auto; +} +.menu ul { + margin:0; + padding:0; +} +.menu li { + list-style-type:none; + padding:6px; + cursor:pointer; +} +.menu li:hover { + background:#333; + color:white; +} +/* Tabs */ +.tabbar { + position:relative; + overflow:hidden; + + background:darkgrey; + background-image: linear-gradient(bottom,#BBBBBB,#EEEEEE); + background-image: -ms-linear-gradient(bottom,#BBBBBB,#EEEEEE); + background-image: -moz-linear-gradient(bottom,#BBBBBB,#EEEEEE); + background-image: -webkit-linear-gradient(bottom,#BBBBBB,#EEEEEE); + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#BBBBBB, endColorstr=#EEEEEE); /* IE 6-8 */ +} +.tabitem { + display:inline-block; + background:white; + + height:20px; + border-top:2px solid white; + border-right:1px solid lightgrey; + margin-top:2px; + padding:0 8px; +} +.tabitem:hover { + border-top:2px solid #EEE; +} +.tabitem.selected { + border-top:2px solid darkgreen; +} +.tabitem.unread { + background:lightyellow; +} +.tab-label { + cursor:pointer; +} +.tab-closer { + background:#F8F8F8; + color:grey; + font-weight:bold; + cursor:pointer; + + display:inline-block; + *display:block; /* IE7 */ + *zoom:1; /* IE7 */ + + text-align:center; + + /* Cosmetic */ + + padding:0 3px; + border-radius:12px; + border:1px solid white; + line-height:12px; + + position:relative; + top:1px; + + -webkit-transition:0.1s linear all; + -moz-transition:0.1s linear all; + transition:0.1s linear all; +} +.tab-closer:hover { + background:#FFDDDD; + border:1px solid red; + color:black; +} +/* */ +.content { + display:block; +} +.content-inner { + overflow:hidden; + overflow-y:auto; + -webkit-transition: all 0.25s ease-in-out; + + padding:0; /*4px;*/ + margin:0; + box-sizing:border-box; + + position:absolute; + top:4px; + bottom:0; + left:4px; + right:0; +} +/* */ +#basebar { + border-top: 1px solid #999; + + text-align:center; + font-weight:bold; + color:white; + vertical-align:middle; + + background: #ACB9CA; + background-image: linear-gradient(bottom,#6E85A2,#ACB9CA); + background-image: -ms-linear-gradient(bottom,#6E85A2,#ACB9CA); + background-image: -moz-linear-gradient(bottom,#6E85A2,#ACB9CA); + background-image: -webkit-linear-gradient(bottom,#6E85A2,#ACB9CA); + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#6E85A2, endColorstr=#ACB9CA); /* IE 6-8 */ +} +#form-none { + height:32px; + position:absolute; + right:4px; + left:4px; + top:4px; +} +#chatbox-container { + padding:1px; + + padding-right: 15px; /* (6 + 1)*2 plus 1 expected */ + + position:absolute; + left:0;top:0;bottom:0;right:32px; +} +#chatbox { + font-size:1.2em; + font-family:Geneva,Helvetica,Arial,sans-serif; + + border:1px; + border-radius:3px; + padding:0 6px; + margin:0; + + display:block; + width:100%; + height:100%; +} +#submit-container { + position:absolute; + top:0;bottom:0;right:0;width:32px; +} +#btsubmit { + width:100%; + height:100%; + + font-size:1.2em; + font-family:Geneva,Helvetica,Arial,sans-serif; +} + +/* iOS-style list view */ + +.ul-large { + background-color: #e9e9e9; + border: 1px solid #ccc; + width: 95%; + display: block; + position: relative; + padding: 0; + margin-left: auto; + margin-right: auto; + -webkit-border-radius: 12px; + -moz-border-radius: 12px; + border-radius: 12px; +} +.ul-large li { + color: #333; + font: bold 15px Geneva, Arial, Helvetica, sans-serif; + vertical-align: middle; + border-bottom: 1px solid #ccc; + list-style-type: none; + text-align: left; + white-space: nowrap; + overflow: hidden; + height: 30px; + list-style-type: none; + display: block; + padding: 15px 5px 5px 10px; +} +.ul-large li:first-child { + border-top: 0; + -webkit-border-top-left-radius: 12px; + -webkit-border-top-right-radius: 12px; + -moz-border-top-left-radius: 12px; + -moz-border-top-right-radius: 12px; + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} +.ul-large li:last-child { + border-bottom: 0; + -webkit-border-bottom-left-radius: 12px; + -webkit-border-bottom-right-radius: 12px; + -moz-border-bottom-left-radius: 12px; + -moz-border-bottom-right-radius: 12px; + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +.ul-large li { + cursor:pointer; +} + +/* Text */ + +.tx-time { + color:grey; +} +.tx-sys { + font-weight: bold; + color: darkgreen; +} +.tx-user { + font-weight: bold; + color: black; +} +.tx-chat { + color: black; +} +.tx-private { + color: red; + font-style: italic; +} + +/* webkit scrollbars */ + +::-webkit-scrollbar-track-piece{ + /*background-color:#fff;*/ + -webkit-border-radius:0; +} +::-webkit-scrollbar{ + width:8px; + height:8px; +} +::-webkit-scrollbar-thumb{ + height:50px; + background-color:#CCC; + -webkit-border-radius:4px; + outline:2px solid #fff; + outline-offset:-2px; + border: 2px solid #fff; + + -webkit-transition:background-color 0.1s; + transition:background-color 0.1s; +} +::-webkit-scrollbar-thumb:hover{ + height:50px; + background-color:#999; + -webkit-border-radius:4px; +} + +/* Userlist */ + +#panel-userlist { + border-left:1px solid #EEE; + background:#F8F8F8; + overflow-y: auto; +} + +/* User sprite */ + +.ul-mini { + padding-left: 4px; + margin-top:4px; +} +.ul-mini li { + list-style-type:none; + min-height:13px; + line-height:13px; + padding-left:14px; + margin-bottom:5px; + cursor:pointer; + + background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAANCAYAAACQN/8FAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABh0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzT7MfTgAAAZJJREFUKJFtz71rE2EAgPHnrknbXBKkLWhx0DhoWsEOxk0taMGlQ7cimElK5uroH5DFSUQ3KQpV2qlQEDJ4mKFQ0MVS6kfN1dQP2ss1ydW79y6Xu3udBG36zL/lUaSUVKtVqes6hmGgaRqlUulUoVAw+ScV4P2bFfrEPhnF4+v2NuVy+QFHSjiNXWV2cgzh+dRqX1hsNflcr5/tgcJ14larSdDxCYIOuWEV0c3+7oEAxk4NANu2GUnFFIt3FnvgydxFZb9hSRmFCCGwmjb3i3OVo1AFyF2bZm/PxDRN4rDDo4WHt4+F77RfmKNZ1MQA9ukTPPeXXt14OvXita5f+guVJ+uPZ1brlZUJI08qG/F26AP9chDXO8RpeyzNvMyMnc+7fembmU9WYJFXL7M1YtBNhqRIEYURh1Gb/u+DH69fubqRaLQOcAccHDy++TW0pEaATzcOkFHMxs/NCQD13oV50laaH/EuQdhBhAIRClzF/W9GkVIC8Gx54dZafa3SDmxc1SEdZxgfHmdu+m7y3Jlc+AextbuG6q1RSQAAAABJRU5ErkJggg==') no-repeat 0 0; +} +.ul-mini li:hover { + background-color:#EEE; +} + +/* Display userlist alongside main chat for wide screens */ + +#panel-userlist { + display:none; +} +@media screen and (min-width: 590px) { + + .placement-vary { + right:150px; + } + #panel-userlist { + display:block; + } + #tabitem-tab-users { + display:none; + } + .position-panel { + display:block; + } +} \ No newline at end of file diff --git a/client/dcwebui.js b/client/dcwebui.js new file mode 100644 index 0000000..2aea532 --- /dev/null +++ b/client/dcwebui.js @@ -0,0 +1,747 @@ +/* dcwebui.js */ +//;(function() { + +"use strict"; + +var $ = (document.querySelectorAll ? + function(s) { + var r = document.querySelectorAll(s); + return (s[0] === '#' && r.length === 1) ? r[0] : r; + } : + function(s) { + // i'm not writing a selector engine... + if (! s.length) return []; + if (s[0] === '#') { + return document.getElementById(s.slice(1)); + } else if (s[0] === '.') { + return document.getElementsByClassName(s.slice(1)); + } else { + return document.getElementsByTagName(s); + } + } +); + +var nmdc_escape = function(str) { + return (''+str).length ? (''+str). + replace(/&/g,'&').replace(/\|/g,'|').replace(/\$/g,'$') : + ' '; +}; + +var hesc = function(s) { + var filter = { + '&': '&', '<': '<', '>': '>', '"': '"', '\'': ''' + }; + return s.toString().replace(/[&<>'"]/g, function(s) { return filter[s]; }); +}; + +var nl2br = function(str) { // thanks php.js! + return (str+'').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1
$2'); +}; + +var linkify = function(str) { + return str.replace( + /(https?:\/\/[^\s<]+)/g, "$1" + ); +}; + +var sanitise = function(s) { + return linkify(nl2br(hesc(s))); +}; + +var toggle = function($el) { + $el.style.display = ($el.style.display === "block") ? "none" : "block"; +}; + +var textContent = function($el) { + if ($el.textContent) return $el.textContent; + if ($el.innerText) return $el.innerText; + return ""; +}; + +// https://gist.github.com/eligrey/1276030 +var appendInnerHTML = function($el, html) { + var child = document.createElement("span"); + child.innerHTML = html; + + var node; + while ((node = child.firstChild)) { + $el.appendChild(node); + } +}; + +// http://stackoverflow.com/a/5598797 +function getOffsetLeft( elem ) { + var offsetLeft = 0; + do { + if (!isNaN(elem.offsetLeft)) { + offsetLeft += elem.offsetLeft; + } + } while (elem = elem.offsetParent); + return offsetLeft; +} + +function getOffsetTop( elem ) { + var offsetTop = 0; + do { + if (!isNaN(elem.offsetTop)) { + offsetTop += elem.offsetTop; + } + } while (elem = elem.offsetParent); + return offsetTop; +} + +/* Tab writers */ + +var write = function(tab) { + var $tab = $('#inner-'+tab); + return { + 'cls': function() { + $tab.innerHTML = ''; + return this; + }, + 'scroll': function() { + $tab.scrollTop = $tab.scrollHeight; + return this; + }, + 'raw': function(s) { + appendInnerHTML($tab, s); + return this.scroll(); + }, + 'c': function(c, s) { + return this.raw(''+s+''); + }, + 'time': function() { + var d = new Date(); + var pad = function(s) { + return (s < 10) ? '0'+s : ''+s ; + }; + return this.raw( + '['+ + pad(d.getHours()) + ":" + pad(d.getMinutes())+ + "] " + ); + }, + 'system': function(s) { + return this.time().c('tx-sys', sanitise(s)).raw('
'); + }, + 'pubnick': function(u) { + return this.raw('<'+hesc(u)+'>'); + }, + 'pub': function(u, s) { + return this.time(). + pubnick(u).raw(' '). + c('tx-chat', sanitise(s)).raw('
'); + }, + 'priv': function(f, t, s) { + return this.time(). + c('tx-user', '<'+hesc(f)+' -> '+hesc(t)+'>'). + raw(' '). + c('tx-private', sanitise(s)). + raw('
'); + } + }; +}; + +/* Userlist */ + +var switchToPM = function(u) { + writerFor(u); // create + tab_set(pm_tabs[u]); // switch + writerFor(u).scroll(); // scroll +}; + +var userMenu = function(u, ev) { + + usermenu.hide(); + usermenu = new MenuList(ev.target); + usermenu.add("Send private message...", function() { + switchToPM(u); + }); + // Usercommands + for (var i = 0; i < user_usercommands.length; i++) (function(i) { + var raw = user_usercommands[i].raw; + usermenu.add(user_usercommands[i].title, function() { + + var message = usercommand_process( raw .replace(/%\[nick\]/g, u) ); + sock.emit('raw', {message: message}); + }); + })(i); + + // Show + usermenu.show(); + + // + ev.preventDefault(); + return false; +}; + +var userlist = { + 'add': function(u) { + if (this.has(u)) return; + + var userlists = $(".userlist"); + for (var l = 0, e = userlists.length; l !== e; ++l) { + var userlist = userlists[l]; + + var to_add = document.createElement('li'); + to_add.innerHTML = hesc(u); + + to_add.onclick = function() { switchToPM(u); }; + to_add.oncontextmenu = function(ev) { return userMenu(u, ev); }; + + var users = userlist.children; + var cmp = hesc(u).toUpperCase(); + + var found = false; + for (var i = 0; i < users.length; i++) { + if ((''+users[i].innerHTML).toUpperCase() > cmp) { + userlist.insertBefore(to_add, users[i]); + found = true; + break; + } + } + if (! found) { + userlist.appendChild(to_add); + } + } + return this; + }, + 'del': function(u) { + var userlists = $(".userlist"); + for (var l = 0, e = userlists.length; l !== e; ++l) { + if (! userlists[l].children) continue; + var userlist = userlists[l]; + + var users = userlist.children; + var cmp = hesc(u).toUpperCase(); + for (var i = 0; i < users.length; i++) { + if ((''+users[i].innerHTML).toUpperCase() === cmp) { + userlist.removeChild(users[i]); + break; + } + } + } + return this; + }, + 'clear': function() { + var userlists = $(".userlist"); + for (var i in userlists) { + if (! userlists[i].children) continue; + var userlist = userlists[i]; + + var users = userlist.children; + for (var j = 0; j < users.length; j++) { + userlist.removeChild(users[j]); + } + } + return this; + }, + 'names': function() { + var userlist = $(".userlist")[0].children; + var ret = []; + for (var i = 0, e = userlist.length; i < e; ++i) { + ret.push( textContent(userlist[i]) ); + } + return ret; + }, + 'has': function(u) { + var userlist = $(".userlist")[0].children; + for (var i = 0, e = userlist.length; i < e; ++i) { + if (textContent(userlist[i]) === u) { + return true; + } + } + return false; + }, + 'count': function() { + return $(".userlist")[0].children.length; + } +}; + +var submit = function() { + var str = $("#chatbox").value; + if (! str.length) return; + + if (hub_state === 0) { + hub_state = 1; + + var name_parts = str.split(":", 2); + hub_last_nick = name_parts[0]; + + sock.emit('hello', {'nick' : hub_last_nick, 'pass' : name_parts.length >= 2 ? name_parts[1] : ''}); + $("#chatbox").disabled = true; + write("tab-main").system("Connecting..."); + + } else if (hub_state === 2) { + if (pm_target !== false) { + sock.emit('priv', {'user': pm_target, 'message': str}); + writerFor(pm_target).pub(hub_last_nick, str ); + } else { + sock.emit('pub', {'message' : str}); + } + + } else { + write("tab-main").system("Invalid internal state."); + } + + $("#chatbox").value = ''; +}; + +/* tabs */ + +/** + * Switch active tab + * + * @param {String} tab Full tab ID (e.g. tab-main, tab-users, tab-ext-???) + */ +var tab_set = function(tab) { + + var tabs = $(".tabpane"); + for (var i in tabs) { + try { + tabs[i].style.display = (tabs[i].id === tab ? 'block' : 'none'); + } catch (e) {}; + } + var tabitems = $(".tabitem"); + for (var i in tabitems) { + try { + tabitems[i].className = "tabitem" + (tabitems[i].getAttribute('data-tab') === tab ? ' selected' : ''); + } catch (e) {}; + } + + pm_target = false; + for (var i in pm_tabs) { + if (pm_tabs[i] === tab) { + pm_target = i; + break; + } + } + + updateTitle(); + + write(tab).scroll(); + $("#chatbox").focus(); + last_tab = tab; +}; + +var tab_new = function(id, name) { + appendInnerHTML($("#bar"), + '
'+ + ''+ + hesc(name)+ + ' '+ + '×'+ + '
' + ); + appendInnerHTML($("#extratabs"), + ' ' + ); + tab_addHandlers(); + return "tab-ext-"+id; +}; + +var tab_free = function(id) { + if (id === "tab-main") return; + + // remove tab item and body + var el = $("#tabitem-"+id); + el.parentNode.removeChild(el); + + var el = $("#"+id); + el.parentNode.removeChild(el); + + // clear from PM tabs + for (var i in pm_tabs) { + if (pm_tabs[i] === id) { + pm_tabs[i] = false; + } + } + + // maybe clear the 'new pm' warning + updateTitle(); + + // don't leave us with no tab displayed + if (last_tab === id) { + tab_set("tab-main"); + } +}; + +var tab_addHandlers = function() { + var tabitems = $(".tabitem"); + for (var i = 0; i < tabitems.length; i++) { + if (! tabitems[i]) continue; + + tabitems[i].onclick = function(ev) { + tab_set( this.getAttribute('data-tab') ); + + // 360nobubble + if (ev.stopPropagation) { + ev.stopPropagation(); + } else { + ev.cancelBubble = true; // oldIE + } + return false; + }; + } + + var tabclosers = $(".tab-closer"); + for (var i = 0; i < tabclosers.length; i++) { + if (! tabclosers[i]) continue; + + tabclosers[i].onclick = function(ev) { + tab_free( this.getAttribute('data-tab') ); + + // 360nobubble + if (ev.stopPropagation) { + ev.stopPropagation(); + } else { + ev.cancelBubble = true; // oldIE + } + return false; + }; + } +}; + +/* */ + +var writerFor = function(username) { + var tabid = ""; + if (! username in pm_tabs || ! pm_tabs[username]) { + tabid = tab_new(next_tabid++, username); + pm_tabs[username] = tabid; + } else { + tabid = pm_tabs[username]; + } + + return write(tabid); +}; + +/* */ + +var tabcomplete_state = ''; + +var tabcompletion_start = function() { + + var cursor = $("#chatbox").value.replace(/^.*\s([^\s]+)$/, '$1'); + + if (tabcomplete_state === '') { + // new tab completion + tabcomplete_state = cursor; + } + + // Find all users who start with tabcomplete_state and retrieve the first + // one after cursor + + var users = userlist.names(); + var match = []; + + for (var i = 0, e = users.length; i !== e; ++i) { + if (users[i].toUpperCase().indexOf(tabcomplete_state.toUpperCase()) === 0) { + match.push(users[i]); + } + } + + if (match.length === 0) { + // no matches + return; + } + + // Is cursor in the list? + var cpos = -1; + for (var i = 0, e = match.length; i !== e; ++i) { + if (match[i] === cursor) { + cpos = i; break; + } + } + + var targetName = match[(i + 1) % match.length]; + + // Replace in textbox + + var chatprefix = $("#chatbox").value.substr(0, $("#chatbox").value.length - cursor.length); + + $("#chatbox").value = chatprefix + targetName; + $("#chatbox").focus(); +}; + +var tabcompletion_inactive = function() { + tabcomplete_state = ''; +}; + +/* */ + +var MenuList = function(el) { + this.el = el; + + this.div = document.createElement("div"); + this.div.classList.add("menu"); + this.div.style.position = "absolute"; + + this.ul = document.createElement("ul"); + this.div.appendChild(this.ul); + + document.body.appendChild(this.div); + +}; +MenuList.prototype.clear = function() { + while (this.ul.children.length) { + this.ul.children[0].parentNode.removeChild( this.ul.children[0] ); + } +}; +MenuList.prototype.add = function(txt, cb) { + var li = document.createElement("li"); + li.innerHTML = txt; + li.onclick = cb; + this.ul.appendChild(li); +}; +MenuList.prototype.show = function() { + this.div.style.display = "block"; + + this.div.style.top = (getOffsetTop(this.el) + this.el.clientHeight)+"px"; + this.div.style.left = (getOffsetLeft(this.el) - 200 + this.el.clientWidth)+"px"; +}; +MenuList.prototype.hide = function() { + this.div.style.display = "none"; +}; +MenuList.prototype.toggle = function() { + // ES5 strict mode sets `this` to undefined + (this.div.style.display === "block" ? this.hide : this.show).call(this); +}; + +/* */ + +var menu = new MenuList($("#menubutton")); + +menu.reset = function() { + this.clear(); + this.add(joinparts_getstr(), toggle_joinparts); +}; + +var usermenu = new MenuList(document.body); + +/** + * Process all substitutions in a usercommand. May prompt the user for input. + * + * @param {String} str + * @returns {String} + */ +var usercommand_process = function(str) { + var message = str + .replace(/%\[mynick\]/g, hub_last_nick) + ; + var match = null; + for(;;) { + match = message.match(/%\[line:([^\]]*)\]/); + if (match === null) break; + + var res = prompt(match[1]); + if (res === null) return; //cancelled + + message = + message.substr(0, match.index) + + nmdc_escape(res) + + message.substr(match.index + match[0].length) + ; + } + + return message; +}; + +var user_usercommands = []; + +/** + * Called when a $UserCommand is recieved from the server. Register it in all + * relevant context menus. + * + * @param {Object} data Has properties type, context, title, raw + * @returns {undefined} + */ +var process_usercommand = function(data) { + switch(data.type) { + case 0: { /* USERCOMMAND_TYPE_SEPARATOR */ + // ignore + } break; + + case 1: /* USERCOMMAND_TYPE_RAW */ + case 2:/* USERCOMMAND_TYPE_NICKLIMITED */ + { + if (data.context & 1) { /* USERCOMMAND_CONTEXT_HUB */ + menu.add(data.title, function() { + sock.emit('raw', {message: usercommand_process(data.raw)}); + }); + } + + if (data.context & 2) { /* USERCOMMAND_CONTEXT_USER */ + user_usercommands.push(data); + } + } break; + + case 255: { /* USERCOMMAND_TYPE_CLEARALL */ + if (data.context & 1) { + menu.reset(); + } + + if (data.context & 2) { + user_usercommands = []; // clear + } + } break; + } +}; + +var joinparts_getstr = function() { + return (show_joins ? "☑" : "☐") + " Show Joins/Parts"; +}; + +var toggle_joinparts = function(ev) { + var $el = ev.target || ev.srcElement; + show_joins = ! show_joins; + $el.innerHTML = joinparts_getstr(); +}; + +/* */ + +var updateTitle = function() { + document.title = + ($(".unread").length ? "[NEW PM] " : "") + + "("+userlist.count()+") "+ + hub_hubname; +}; + +var sock = {}; +var hub_state = 0; // [disconnected, sent-nick, connected] +var hub_last_nick = ''; +var hub_hubname = 'DCWebUI'; + +var pm_tabs = {}; // nick => tabid +var next_tabid = 1; +var pm_target = false; + +var last_tab = "tab-main"; + +var show_joins = false; + +window.onload = function() { + write("tab-main").system("Communicating with server..."); + + document.title = DCWEBUI_CONF.title; + + // HTML event handlers + + $("#form-none").onsubmit = function(ev) { + submit(); + + // don't submit form + ev.preventDefault(); + return false; + }; + + $("#chatbox").onkeydown = function(ev) { + if (ev.keyCode === 9) { + // tab + tabcompletion_start(); + ev.preventDefault(); + return false; + + } else { + tabcompletion_inactive(); + } + }; + + window.onresize = function() { + if (last_tab === "tab-users" && document.documentElement.clientWidth >= 590) { + tab_set("tab-main"); + } + + menu.hide(); + usermenu.hide(); + }; + + $("#menubutton").onclick = function(ev) { + menu.toggle(); + ev.preventDefault(); + ev.stopPropagation(); + return false; + }; + + window.onclick = function() { + menu.hide(); + usermenu.hide(); + }; + + menu.reset(); + + tab_addHandlers(); + + // Hacks for WiiU user-agent + + if (navigator && navigator.userAgent && !!navigator.userAgent.match("Nintendo WiiU")) { + document.body.className += " navigator-wiiu"; + } + + // Socket event handlers + + sock = io.connect(DCWEBUI_CONF.extern); + sock.on('cls', function() { + write("tab-main").cls(); + userlist.clear(); + hub_state = 0; + }); + sock.on('hubname', function(s) { + write("tab-main").system("Now talking on "+s); + hub_hubname = s; + updateTitle(); + }); + sock.on('sys', function(data) { + write("tab-main").system(data); + }); + sock.on('raw', function(data) { + write("tab-main").raw(data); + }); + sock.on('pub', function(data) { + write("tab-main").pub( data.user, data.message); + }); + sock.on('priv', function(data) { + writerFor(data.user).pub( data.user, data.message); + if (last_tab !== pm_tabs[data.user] && + ($("#tabitem-"+pm_tabs[data.user]).className.indexOf('unread') === -1) + ) { + $("#tabitem-"+pm_tabs[data.user]).className += " unread"; + updateTitle(); + } + }); + sock.on('hello', function() { + hub_state = 2; + $("#chatbox").disabled = false; + }); + sock.on('part', function(u) { + userlist.del(u.user); + if (show_joins) { + write("tab-main").system("*** Parts: "+u.user); // sanitised + } + updateTitle(); + }); + sock.on('join', function(u) { + userlist.add(u.user); + if (show_joins) { + write("tab-main").system("*** Joins: "+u.user); + } + updateTitle(); + }); + sock.on('close', function() { + hub_state = 0; + userlist.clear(); + write("tab-main").system("Connection closed by remote host."); + }); + sock.on('disconnect', function() { + hub_state = 0; + userlist.clear(); + write("tab-main").system("Lost connection to the server."); + }); + sock.on('usercommand', function(data) { + process_usercommand(data); + }); +}; + +//})(); diff --git a/client/favicon.ico b/client/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..0290130891d62e6efc5b4f0e862196b3f0fed972 GIT binary patch literal 6830 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 A>;M1& literal 0 HcmV?d00001 diff --git a/client/index.htm b/client/index.htm new file mode 100644 index 0000000..49699d2 --- /dev/null +++ b/client/index.htm @@ -0,0 +1,59 @@ + + + + + + + + + + Loading... + + +
+ +
+ + Main + +
+
+ + Users + +
+
+ +
+
+
+
+
+
    +
    +
    + + + +
    + +
    +
    +
    + +
    +
    + +
    +
    +
    + + + + + + \ No newline at end of file diff --git a/client/socket.io-1.4.5.js b/client/socket.io-1.4.5.js new file mode 100644 index 0000000..6f478d8 --- /dev/null +++ b/client/socket.io-1.4.5.js @@ -0,0 +1,4 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.io=f()}})(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o0){this.extraHeaders=opts.extraHeaders}}this.open()}Socket.priorWebsocketSuccess=false;Emitter(Socket.prototype);Socket.protocol=parser.protocol;Socket.Socket=Socket;Socket.Transport=_dereq_("./transport");Socket.transports=_dereq_("./transports");Socket.parser=_dereq_("engine.io-parser");Socket.prototype.createTransport=function(name){debug('creating transport "%s"',name);var query=clone(this.query);query.EIO=parser.protocol;query.transport=name;if(this.id)query.sid=this.id;var transport=new transports[name]({agent:this.agent,hostname:this.hostname,port:this.port,secure:this.secure,path:this.path,query:query,forceJSONP:this.forceJSONP,jsonp:this.jsonp,forceBase64:this.forceBase64,enablesXDR:this.enablesXDR,timestampRequests:this.timestampRequests,timestampParam:this.timestampParam,policyPort:this.policyPort,socket:this,pfx:this.pfx,key:this.key,passphrase:this.passphrase,cert:this.cert,ca:this.ca,ciphers:this.ciphers,rejectUnauthorized:this.rejectUnauthorized,perMessageDeflate:this.perMessageDeflate,extraHeaders:this.extraHeaders});return transport};function clone(obj){var o={};for(var i in obj){if(obj.hasOwnProperty(i)){o[i]=obj[i]}}return o}Socket.prototype.open=function(){var transport;if(this.rememberUpgrade&&Socket.priorWebsocketSuccess&&this.transports.indexOf("websocket")!=-1){transport="websocket"}else if(0===this.transports.length){var self=this;setTimeout(function(){self.emit("error","No transports available")},0);return}else{transport=this.transports[0]}this.readyState="opening";try{transport=this.createTransport(transport)}catch(e){this.transports.shift();this.open();return}transport.open();this.setTransport(transport)};Socket.prototype.setTransport=function(transport){debug("setting transport %s",transport.name);var self=this;if(this.transport){debug("clearing existing transport %s",this.transport.name);this.transport.removeAllListeners()}this.transport=transport;transport.on("drain",function(){self.onDrain()}).on("packet",function(packet){self.onPacket(packet)}).on("error",function(e){self.onError(e)}).on("close",function(){self.onClose("transport close")})};Socket.prototype.probe=function(name){debug('probing transport "%s"',name);var transport=this.createTransport(name,{probe:1}),failed=false,self=this;Socket.priorWebsocketSuccess=false;function onTransportOpen(){if(self.onlyBinaryUpgrades){var upgradeLosesBinary=!this.supportsBinary&&self.transport.supportsBinary;failed=failed||upgradeLosesBinary}if(failed)return;debug('probe transport "%s" opened',name);transport.send([{type:"ping",data:"probe"}]);transport.once("packet",function(msg){if(failed)return;if("pong"==msg.type&&"probe"==msg.data){debug('probe transport "%s" pong',name);self.upgrading=true;self.emit("upgrading",transport);if(!transport)return;Socket.priorWebsocketSuccess="websocket"==transport.name;debug('pausing current transport "%s"',self.transport.name);self.transport.pause(function(){if(failed)return;if("closed"==self.readyState)return;debug("changing transport and sending upgrade packet");cleanup();self.setTransport(transport);transport.send([{type:"upgrade"}]);self.emit("upgrade",transport);transport=null;self.upgrading=false;self.flush()})}else{debug('probe transport "%s" failed',name);var err=new Error("probe error");err.transport=transport.name;self.emit("upgradeError",err)}})}function freezeTransport(){if(failed)return;failed=true;cleanup();transport.close();transport=null}function onerror(err){var error=new Error("probe error: "+err);error.transport=transport.name;freezeTransport();debug('probe transport "%s" failed because of error: %s',name,err);self.emit("upgradeError",error)}function onTransportClose(){onerror("transport closed")}function onclose(){onerror("socket closed")}function onupgrade(to){if(transport&&to.name!=transport.name){debug('"%s" works - aborting "%s"',to.name,transport.name);freezeTransport()}}function cleanup(){transport.removeListener("open",onTransportOpen);transport.removeListener("error",onerror);transport.removeListener("close",onTransportClose);self.removeListener("close",onclose);self.removeListener("upgrading",onupgrade)}transport.once("open",onTransportOpen);transport.once("error",onerror);transport.once("close",onTransportClose);this.once("close",onclose);this.once("upgrading",onupgrade);transport.open()};Socket.prototype.onOpen=function(){debug("socket open");this.readyState="open";Socket.priorWebsocketSuccess="websocket"==this.transport.name;this.emit("open");this.flush();if("open"==this.readyState&&this.upgrade&&this.transport.pause){debug("starting upgrade probes");for(var i=0,l=this.upgrades.length;i';iframe=document.createElement(html)}catch(e){iframe=document.createElement("iframe");iframe.name=self.iframeId;iframe.src="javascript:0"}iframe.id=self.iframeId;self.form.appendChild(iframe);self.iframe=iframe}initIframe();data=data.replace(rEscapedNewline,"\\\n");this.area.value=data.replace(rNewline,"\\n");try{this.form.submit()}catch(e){}if(this.iframe.attachEvent){this.iframe.onreadystatechange=function(){if(self.iframe.readyState=="complete"){complete()}}}else{this.iframe.onload=complete}}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:typeof global!=="undefined"?global:{})},{"./polling":8,"component-inherit":16}],7:[function(_dereq_,module,exports){(function(global){var XMLHttpRequest=_dereq_("xmlhttprequest-ssl");var Polling=_dereq_("./polling");var Emitter=_dereq_("component-emitter");var inherit=_dereq_("component-inherit");var debug=_dereq_("debug")("engine.io-client:polling-xhr");module.exports=XHR;module.exports.Request=Request;function empty(){}function XHR(opts){Polling.call(this,opts);if(global.location){var isSSL="https:"==location.protocol;var port=location.port;if(!port){port=isSSL?443:80}this.xd=opts.hostname!=global.location.hostname||port!=opts.port;this.xs=opts.secure!=isSSL}else{this.extraHeaders=opts.extraHeaders}}inherit(XHR,Polling);XHR.prototype.supportsBinary=true;XHR.prototype.request=function(opts){opts=opts||{};opts.uri=this.uri();opts.xd=this.xd;opts.xs=this.xs;opts.agent=this.agent||false;opts.supportsBinary=this.supportsBinary;opts.enablesXDR=this.enablesXDR;opts.pfx=this.pfx;opts.key=this.key;opts.passphrase=this.passphrase;opts.cert=this.cert;opts.ca=this.ca;opts.ciphers=this.ciphers;opts.rejectUnauthorized=this.rejectUnauthorized;opts.extraHeaders=this.extraHeaders;return new Request(opts)};XHR.prototype.doWrite=function(data,fn){var isBinary=typeof data!=="string"&&data!==undefined;var req=this.request({method:"POST",data:data,isBinary:isBinary});var self=this;req.on("success",fn);req.on("error",function(err){self.onError("xhr post error",err)});this.sendXhr=req};XHR.prototype.doPoll=function(){debug("xhr poll");var req=this.request();var self=this;req.on("data",function(data){self.onData(data)});req.on("error",function(err){self.onError("xhr poll error",err)});this.pollXhr=req};function Request(opts){this.method=opts.method||"GET";this.uri=opts.uri;this.xd=!!opts.xd;this.xs=!!opts.xs;this.async=false!==opts.async;this.data=undefined!=opts.data?opts.data:null;this.agent=opts.agent;this.isBinary=opts.isBinary;this.supportsBinary=opts.supportsBinary;this.enablesXDR=opts.enablesXDR;this.pfx=opts.pfx;this.key=opts.key;this.passphrase=opts.passphrase;this.cert=opts.cert;this.ca=opts.ca;this.ciphers=opts.ciphers;this.rejectUnauthorized=opts.rejectUnauthorized;this.extraHeaders=opts.extraHeaders;this.create()}Emitter(Request.prototype);Request.prototype.create=function(){var opts={agent:this.agent,xdomain:this.xd,xscheme:this.xs,enablesXDR:this.enablesXDR};opts.pfx=this.pfx;opts.key=this.key;opts.passphrase=this.passphrase;opts.cert=this.cert;opts.ca=this.ca;opts.ciphers=this.ciphers;opts.rejectUnauthorized=this.rejectUnauthorized;var xhr=this.xhr=new XMLHttpRequest(opts);var self=this;try{debug("xhr open %s: %s",this.method,this.uri);xhr.open(this.method,this.uri,this.async);try{if(this.extraHeaders){xhr.setDisableHeaderCheck(true);for(var i in this.extraHeaders){if(this.extraHeaders.hasOwnProperty(i)){xhr.setRequestHeader(i,this.extraHeaders[i])}}}}catch(e){}if(this.supportsBinary){xhr.responseType="arraybuffer"}if("POST"==this.method){try{if(this.isBinary){xhr.setRequestHeader("Content-type","application/octet-stream")}else{xhr.setRequestHeader("Content-type","text/plain;charset=UTF-8")}}catch(e){}}if("withCredentials"in xhr){xhr.withCredentials=true}if(this.hasXDR()){xhr.onload=function(){self.onLoad()};xhr.onerror=function(){self.onError(xhr.responseText)}}else{xhr.onreadystatechange=function(){if(4!=xhr.readyState)return;if(200==xhr.status||1223==xhr.status){self.onLoad()}else{setTimeout(function(){self.onError(xhr.status)},0)}}}debug("xhr data %s",this.data);xhr.send(this.data)}catch(e){setTimeout(function(){self.onError(e)},0);return}if(global.document){this.index=Request.requestsCount++;Request.requests[this.index]=this}};Request.prototype.onSuccess=function(){this.emit("success");this.cleanup()};Request.prototype.onData=function(data){this.emit("data",data);this.onSuccess()};Request.prototype.onError=function(err){this.emit("error",err);this.cleanup(true)};Request.prototype.cleanup=function(fromError){if("undefined"==typeof this.xhr||null===this.xhr){return}if(this.hasXDR()){this.xhr.onload=this.xhr.onerror=empty}else{this.xhr.onreadystatechange=empty}if(fromError){try{this.xhr.abort()}catch(e){}}if(global.document){delete Request.requests[this.index]}this.xhr=null};Request.prototype.onLoad=function(){var data;try{var contentType;try{contentType=this.xhr.getResponseHeader("Content-Type").split(";")[0]}catch(e){}if(contentType==="application/octet-stream"){data=this.xhr.response}else{if(!this.supportsBinary){data=this.xhr.responseText}else{try{data=String.fromCharCode.apply(null,new Uint8Array(this.xhr.response))}catch(e){var ui8Arr=new Uint8Array(this.xhr.response);var dataArray=[];for(var idx=0,length=ui8Arr.length;idxbytes){end=bytes}if(start>=bytes||start>=end||bytes===0){return new ArrayBuffer(0)}var abv=new Uint8Array(arraybuffer);var result=new Uint8Array(end-start);for(var i=start,ii=0;i>2]; +base64+=chars[(bytes[i]&3)<<4|bytes[i+1]>>4];base64+=chars[(bytes[i+1]&15)<<2|bytes[i+2]>>6];base64+=chars[bytes[i+2]&63]}if(len%3===2){base64=base64.substring(0,base64.length-1)+"="}else if(len%3===1){base64=base64.substring(0,base64.length-2)+"=="}return base64};exports.decode=function(base64){var bufferLength=base64.length*.75,len=base64.length,i,p=0,encoded1,encoded2,encoded3,encoded4;if(base64[base64.length-1]==="="){bufferLength--;if(base64[base64.length-2]==="="){bufferLength--}}var arraybuffer=new ArrayBuffer(bufferLength),bytes=new Uint8Array(arraybuffer);for(i=0;i>4;bytes[p++]=(encoded2&15)<<4|encoded3>>2;bytes[p++]=(encoded3&3)<<6|encoded4&63}return arraybuffer}})("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")},{}],14:[function(_dereq_,module,exports){(function(global){var BlobBuilder=global.BlobBuilder||global.WebKitBlobBuilder||global.MSBlobBuilder||global.MozBlobBuilder;var blobSupported=function(){try{var a=new Blob(["hi"]);return a.size===2}catch(e){return false}}();var blobSupportsArrayBufferView=blobSupported&&function(){try{var b=new Blob([new Uint8Array([1,2])]);return b.size===2}catch(e){return false}}();var blobBuilderSupported=BlobBuilder&&BlobBuilder.prototype.append&&BlobBuilder.prototype.getBlob;function mapArrayBufferViews(ary){for(var i=0;i=31}exports.formatters.j=function(v){return JSON.stringify(v)};function formatArgs(){var args=arguments;var useColors=this.useColors;args[0]=(useColors?"%c":"")+this.namespace+(useColors?" %c":" ")+args[0]+(useColors?"%c ":" ")+"+"+exports.humanize(this.diff);if(!useColors)return args;var c="color: "+this.color;args=[args[0],c,"color: inherit"].concat(Array.prototype.slice.call(args,1));var index=0;var lastC=0;args[0].replace(/%[a-z%]/g,function(match){if("%%"===match)return;index++;if("%c"===match){lastC=index}});args.splice(lastC,0,c);return args}function log(){return"object"===typeof console&&console.log&&Function.prototype.apply.call(console.log,console,arguments)}function save(namespaces){try{if(null==namespaces){exports.storage.removeItem("debug")}else{exports.storage.debug=namespaces}}catch(e){}}function load(){var r;try{r=exports.storage.debug}catch(e){}return r}exports.enable(load());function localstorage(){try{return window.localStorage}catch(e){}}},{"./debug":18}],18:[function(_dereq_,module,exports){exports=module.exports=debug;exports.coerce=coerce;exports.disable=disable;exports.enable=enable;exports.enabled=enabled;exports.humanize=_dereq_("ms");exports.names=[];exports.skips=[];exports.formatters={};var prevColor=0;var prevTime;function selectColor(){return exports.colors[prevColor++%exports.colors.length]}function debug(namespace){function disabled(){}disabled.enabled=false;function enabled(){var self=enabled;var curr=+new Date;var ms=curr-(prevTime||curr);self.diff=ms;self.prev=prevTime;self.curr=curr;prevTime=curr;if(null==self.useColors)self.useColors=exports.useColors();if(null==self.color&&self.useColors)self.color=selectColor();var args=Array.prototype.slice.call(arguments);args[0]=exports.coerce(args[0]);if("string"!==typeof args[0]){args=["%o"].concat(args)}var index=0;args[0]=args[0].replace(/%([a-z%])/g,function(match,format){if(match==="%%")return match;index++;var formatter=exports.formatters[format];if("function"===typeof formatter){var val=args[index];match=formatter.call(self,val);args.splice(index,1);index--}return match});if("function"===typeof exports.formatArgs){args=exports.formatArgs.apply(self,args)}var logFn=enabled.log||exports.log||console.log.bind(console);logFn.apply(self,args)}enabled.enabled=true;var fn=exports.enabled(namespace)?enabled:disabled;fn.namespace=namespace;return fn}function enable(namespaces){exports.save(namespaces);var split=(namespaces||"").split(/[\s,]+/);var len=split.length;for(var i=0;i1){return{type:packetslist[type],data:data.substring(1)}}else{return{type:packetslist[type]}}}var asArray=new Uint8Array(data);var type=asArray[0];var rest=sliceBuffer(data,1);if(Blob&&binaryType==="blob"){rest=new Blob([rest])}return{type:packetslist[type],data:rest}};exports.decodeBase64Packet=function(msg,binaryType){var type=packetslist[msg.charAt(0)];if(!global.ArrayBuffer){return{type:type,data:{base64:true,data:msg.substr(1)}}}var data=base64encoder.decode(msg.substr(1));if(binaryType==="blob"&&Blob){data=new Blob([data])}return{type:type,data:data}};exports.encodePayload=function(packets,supportsBinary,callback){if(typeof supportsBinary=="function"){callback=supportsBinary;supportsBinary=null}var isBinary=hasBinary(packets);if(supportsBinary&&isBinary){if(Blob&&!dontSendBlobs){return exports.encodePayloadAsBlob(packets,callback)}return exports.encodePayloadAsArrayBuffer(packets,callback)}if(!packets.length){return callback("0:")}function setLengthHeader(message){return message.length+":"+message}function encodeOne(packet,doneCallback){exports.encodePacket(packet,!isBinary?false:supportsBinary,true,function(message){doneCallback(null,setLengthHeader(message))})}map(packets,encodeOne,function(err,results){return callback(results.join(""))})};function map(ary,each,done){var result=new Array(ary.length);var next=after(ary.length,done);var eachWithIndex=function(i,el,cb){each(el,function(error,msg){result[i]=msg;cb(error,result)})};for(var i=0;i0){var tailArray=new Uint8Array(bufferTail);var isString=tailArray[0]===0;var msgLength="";for(var i=1;;i++){if(tailArray[i]==255)break;if(msgLength.length>310){numberTooLong=true;break}msgLength+=tailArray[i]}if(numberTooLong)return callback(err,0,1);bufferTail=sliceBuffer(bufferTail,2+msgLength.length);msgLength=parseInt(msgLength);var msg=sliceBuffer(bufferTail,0,msgLength);if(isString){try{msg=String.fromCharCode.apply(null,new Uint8Array(msg))}catch(e){var typed=new Uint8Array(msg);msg="";for(var i=0;i1e4)return;var match=/^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str);if(!match)return;var n=parseFloat(match[1]);var type=(match[2]||"ms").toLowerCase();switch(type){case"years":case"year":case"yrs":case"yr":case"y":return n*y;case"days":case"day":case"d":return n*d;case"hours":case"hour":case"hrs":case"hr":case"h":return n*h;case"minutes":case"minute":case"mins":case"min":case"m":return n*m;case"seconds":case"second":case"secs":case"sec":case"s":return n*s;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return n}}function short(ms){if(ms>=d)return Math.round(ms/d)+"d";if(ms>=h)return Math.round(ms/h)+"h";if(ms>=m)return Math.round(ms/m)+"m";if(ms>=s)return Math.round(ms/s)+"s";return ms+"ms"}function long(ms){return plural(ms,d,"day")||plural(ms,h,"hour")||plural(ms,m,"minute")||plural(ms,s,"second")||ms+" ms"}function plural(ms,n,name){if(ms=55296&&value<=56319&&counter65535){value-=65536;output+=stringFromCharCode(value>>>10&1023|55296);value=56320|value&1023}output+=stringFromCharCode(value)}return output}function checkScalarValue(codePoint){if(codePoint>=55296&&codePoint<=57343){throw Error("Lone surrogate U+"+codePoint.toString(16).toUpperCase()+" is not a scalar value")}}function createByte(codePoint,shift){return stringFromCharCode(codePoint>>shift&63|128)}function encodeCodePoint(codePoint){if((codePoint&4294967168)==0){return stringFromCharCode(codePoint)}var symbol="";if((codePoint&4294965248)==0){symbol=stringFromCharCode(codePoint>>6&31|192)}else if((codePoint&4294901760)==0){checkScalarValue(codePoint);symbol=stringFromCharCode(codePoint>>12&15|224);symbol+=createByte(codePoint,6)}else if((codePoint&4292870144)==0){symbol=stringFromCharCode(codePoint>>18&7|240);symbol+=createByte(codePoint,12);symbol+=createByte(codePoint,6)}symbol+=stringFromCharCode(codePoint&63|128);return symbol}function utf8encode(string){var codePoints=ucs2decode(string);var length=codePoints.length;var index=-1;var codePoint;var byteString="";while(++index=byteCount){throw Error("Invalid byte index")}var continuationByte=byteArray[byteIndex]&255;byteIndex++;if((continuationByte&192)==128){return continuationByte&63}throw Error("Invalid continuation byte")}function decodeSymbol(){var byte1;var byte2;var byte3;var byte4;var codePoint;if(byteIndex>byteCount){throw Error("Invalid byte index")}if(byteIndex==byteCount){return false}byte1=byteArray[byteIndex]&255;byteIndex++;if((byte1&128)==0){return byte1}if((byte1&224)==192){var byte2=readContinuationByte();codePoint=(byte1&31)<<6|byte2;if(codePoint>=128){return codePoint}else{throw Error("Invalid continuation byte")}}if((byte1&240)==224){byte2=readContinuationByte();byte3=readContinuationByte();codePoint=(byte1&15)<<12|byte2<<6|byte3;if(codePoint>=2048){checkScalarValue(codePoint);return codePoint}else{throw Error("Invalid continuation byte")}}if((byte1&248)==240){byte2=readContinuationByte();byte3=readContinuationByte();byte4=readContinuationByte();codePoint=(byte1&15)<<18|byte2<<12|byte3<<6|byte4;if(codePoint>=65536&&codePoint<=1114111){return codePoint}}throw Error("Invalid UTF-8 detected")}var byteArray;var byteCount;var byteIndex;function utf8decode(byteString){byteArray=ucs2decode(byteString);byteCount=byteArray.length;byteIndex=0;var codePoints=[];var tmp;while((tmp=decodeSymbol())!==false){codePoints.push(tmp)}return ucs2encode(codePoints)}var utf8={version:"2.0.0",encode:utf8encode,decode:utf8decode};if(typeof define=="function"&&typeof define.amd=="object"&&define.amd){define(function(){return utf8})}else if(freeExports&&!freeExports.nodeType){if(freeModule){freeModule.exports=utf8}else{var object={};var hasOwnProperty=object.hasOwnProperty;for(var key in utf8){hasOwnProperty.call(utf8,key)&&(freeExports[key]=utf8[key])}}}else{root.utf8=utf8}})(this)}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:typeof global!=="undefined"?global:{})},{}],30:[function(_dereq_,module,exports){"use strict";var alphabet="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_".split(""),length=64,map={},seed=0,i=0,prev;function encode(num){var encoded="";do{encoded=alphabet[num%length]+encoded;num=Math.floor(num/length)}while(num>0);return encoded}function decode(str){var decoded=0;for(i=0;i0&&!this.encoding){var pack=this.packetBuffer.shift();this.packet(pack)}};Manager.prototype.cleanup=function(){debug("cleanup");var sub;while(sub=this.subs.shift())sub.destroy();this.packetBuffer=[];this.encoding=false;this.lastPing=null;this.decoder.destroy()};Manager.prototype.close=Manager.prototype.disconnect=function(){debug("disconnect");this.skipReconnect=true;this.reconnecting=false;if("opening"==this.readyState){this.cleanup()}this.backoff.reset();this.readyState="closed";if(this.engine)this.engine.close()};Manager.prototype.onclose=function(reason){debug("onclose");this.cleanup();this.backoff.reset();this.readyState="closed";this.emit("close",reason);if(this._reconnection&&!this.skipReconnect){this.reconnect()}};Manager.prototype.reconnect=function(){if(this.reconnecting||this.skipReconnect)return this;var self=this;if(this.backoff.attempts>=this._reconnectionAttempts){debug("reconnect failed");this.backoff.reset();this.emitAll("reconnect_failed");this.reconnecting=false}else{var delay=this.backoff.duration();debug("will wait %dms before reconnect attempt",delay);this.reconnecting=true;var timer=setTimeout(function(){if(self.skipReconnect)return;debug("attempting reconnect");self.emitAll("reconnect_attempt",self.backoff.attempts);self.emitAll("reconnecting",self.backoff.attempts);if(self.skipReconnect)return;self.open(function(err){if(err){debug("reconnect attempt error");self.reconnecting=false;self.reconnect();self.emitAll("reconnect_error",err.data)}else{debug("reconnect success");self.onreconnect()}})},delay);this.subs.push({destroy:function(){clearTimeout(timer)}})}};Manager.prototype.onreconnect=function(){var attempt=this.backoff.attempts;this.reconnecting=false;this.backoff.reset();this.updateSocketIds();this.emitAll("reconnect",attempt)}},{"./on":33,"./socket":34,backo2:36,"component-bind":37,"component-emitter":38,debug:39,"engine.io-client":1,indexof:42,"socket.io-parser":47}],33:[function(_dereq_,module,exports){module.exports=on;function on(obj,ev,fn){obj.on(ev,fn);return{destroy:function(){obj.removeListener(ev,fn)}}}},{}],34:[function(_dereq_,module,exports){var parser=_dereq_("socket.io-parser");var Emitter=_dereq_("component-emitter");var toArray=_dereq_("to-array");var on=_dereq_("./on");var bind=_dereq_("component-bind");var debug=_dereq_("debug")("socket.io-client:socket");var hasBin=_dereq_("has-binary");module.exports=exports=Socket;var events={connect:1,connect_error:1,connect_timeout:1,connecting:1,disconnect:1,error:1,reconnect:1,reconnect_attempt:1,reconnect_failed:1,reconnect_error:1,reconnecting:1,ping:1,pong:1};var emit=Emitter.prototype.emit;function Socket(io,nsp){this.io=io;this.nsp=nsp;this.json=this;this.ids=0;this.acks={};this.receiveBuffer=[];this.sendBuffer=[];this.connected=false;this.disconnected=true;if(this.io.autoConnect)this.open()}Emitter(Socket.prototype);Socket.prototype.subEvents=function(){if(this.subs)return;var io=this.io;this.subs=[on(io,"open",bind(this,"onopen")),on(io,"packet",bind(this,"onpacket")),on(io,"close",bind(this,"onclose"))]};Socket.prototype.open=Socket.prototype.connect=function(){if(this.connected)return this;this.subEvents();this.io.open();if("open"==this.io.readyState)this.onopen();this.emit("connecting");return this};Socket.prototype.send=function(){var args=toArray(arguments);args.unshift("message");this.emit.apply(this,args);return this};Socket.prototype.emit=function(ev){if(events.hasOwnProperty(ev)){emit.apply(this,arguments);return this}var args=toArray(arguments);var parserType=parser.EVENT;if(hasBin(args)){parserType=parser.BINARY_EVENT}var packet={type:parserType,data:args};packet.options={};packet.options.compress=!this.flags||false!==this.flags.compress;if("function"==typeof args[args.length-1]){debug("emitting packet with ack id %d",this.ids);this.acks[this.ids]=args.pop();packet.id=this.ids++}if(this.connected){this.packet(packet)}else{this.sendBuffer.push(packet)}delete this.flags;return this};Socket.prototype.packet=function(packet){packet.nsp=this.nsp;this.io.packet(packet)};Socket.prototype.onopen=function(){debug("transport is open - connecting");if("/"!=this.nsp){this.packet({type:parser.CONNECT})}};Socket.prototype.onclose=function(reason){debug("close (%s)",reason);this.connected=false;this.disconnected=true;delete this.id;this.emit("disconnect",reason)};Socket.prototype.onpacket=function(packet){if(packet.nsp!=this.nsp)return;switch(packet.type){case parser.CONNECT:this.onconnect();break;case parser.EVENT:this.onevent(packet);break;case parser.BINARY_EVENT:this.onevent(packet);break;case parser.ACK:this.onack(packet);break;case parser.BINARY_ACK:this.onack(packet);break;case parser.DISCONNECT:this.ondisconnect();break;case parser.ERROR:this.emit("error",packet.data);break}};Socket.prototype.onevent=function(packet){var args=packet.data||[];debug("emitting event %j",args);if(null!=packet.id){debug("attaching ack callback to event");args.push(this.ack(packet.id))}if(this.connected){emit.apply(this,args)}else{this.receiveBuffer.push(args)}};Socket.prototype.ack=function(id){var self=this;var sent=false;return function(){if(sent)return;sent=true;var args=toArray(arguments);debug("sending ack %j",args);var type=hasBin(args)?parser.BINARY_ACK:parser.ACK;self.packet({type:type,id:id,data:args})}};Socket.prototype.onack=function(packet){var ack=this.acks[packet.id];if("function"==typeof ack){debug("calling ack %s with %j",packet.id,packet.data);ack.apply(this,packet.data);delete this.acks[packet.id]}else{debug("bad ack %s",packet.id)}};Socket.prototype.onconnect=function(){this.connected=true;this.disconnected=false;this.emit("connect");this.emitBuffered()};Socket.prototype.emitBuffered=function(){var i;for(i=0;i0&&opts.jitter<=1?opts.jitter:0;this.attempts=0}Backoff.prototype.duration=function(){var ms=this.ms*Math.pow(this.factor,this.attempts++);if(this.jitter){var rand=Math.random();var deviation=Math.floor(rand*this.jitter*ms);ms=(Math.floor(rand*10)&1)==0?ms-deviation:ms+deviation}return Math.min(ms,this.max)|0};Backoff.prototype.reset=function(){this.attempts=0};Backoff.prototype.setMin=function(min){this.ms=min};Backoff.prototype.setMax=function(max){this.max=max};Backoff.prototype.setJitter=function(jitter){this.jitter=jitter}},{}],37:[function(_dereq_,module,exports){var slice=[].slice;module.exports=function(obj,fn){if("string"==typeof fn)fn=obj[fn];if("function"!=typeof fn)throw new Error("bind() requires a function");var args=slice.call(arguments,2);return function(){return fn.apply(obj,args.concat(slice.call(arguments)))}}},{}],38:[function(_dereq_,module,exports){module.exports=Emitter;function Emitter(obj){if(obj)return mixin(obj)}function mixin(obj){for(var key in Emitter.prototype){obj[key]=Emitter.prototype[key]}return obj}Emitter.prototype.on=Emitter.prototype.addEventListener=function(event,fn){this._callbacks=this._callbacks||{};(this._callbacks["$"+event]=this._callbacks["$"+event]||[]).push(fn);return this};Emitter.prototype.once=function(event,fn){function on(){this.off(event,on);fn.apply(this,arguments)}on.fn=fn;this.on(event,on);return this};Emitter.prototype.off=Emitter.prototype.removeListener=Emitter.prototype.removeAllListeners=Emitter.prototype.removeEventListener=function(event,fn){this._callbacks=this._callbacks||{};if(0==arguments.length){this._callbacks={};return this}var callbacks=this._callbacks["$"+event];if(!callbacks)return this;if(1==arguments.length){delete this._callbacks["$"+event];return this}var cb;for(var i=0;i1)))/4)-floor((year-1901+month)/100)+floor((year-1601+month)/400)}}if(!(isProperty=objectProto.hasOwnProperty)){isProperty=function(property){var members={},constructor;if((members.__proto__=null,members.__proto__={toString:1},members).toString!=getClass){isProperty=function(property){var original=this.__proto__,result=property in(this.__proto__=null,this);this.__proto__=original;return result}}else{constructor=members.constructor;isProperty=function(property){var parent=(this.constructor||constructor).prototype;return property in this&&!(property in parent&&this[property]===parent[property])}}members=null;return isProperty.call(this,property)}}forEach=function(object,callback){var size=0,Properties,members,property;(Properties=function(){this.valueOf=0}).prototype.valueOf=0;members=new Properties;for(property in members){if(isProperty.call(members,property)){size++}}Properties=members=null;if(!size){members=["valueOf","toString","toLocaleString","propertyIsEnumerable","isPrototypeOf","hasOwnProperty","constructor"];forEach=function(object,callback){var isFunction=getClass.call(object)==functionClass,property,length;var hasProperty=!isFunction&&typeof object.constructor!="function"&&objectTypes[typeof object.hasOwnProperty]&&object.hasOwnProperty||isProperty;for(property in object){if(!(isFunction&&property=="prototype")&&hasProperty.call(object,property)){callback(property)}}for(length=members.length;property=members[--length];hasProperty.call(object,property)&&callback(property));}}else if(size==2){forEach=function(object,callback){var members={},isFunction=getClass.call(object)==functionClass,property;for(property in object){if(!(isFunction&&property=="prototype")&&!isProperty.call(members,property)&&(members[property]=1)&&isProperty.call(object,property)){callback(property)}}}}else{forEach=function(object,callback){var isFunction=getClass.call(object)==functionClass,property,isConstructor;for(property in object){if(!(isFunction&&property=="prototype")&&isProperty.call(object,property)&&!(isConstructor=property==="constructor")){callback(property)}}if(isConstructor||isProperty.call(object,property="constructor")){callback(property)}}}return forEach(object,callback)};if(!has("json-stringify")){var Escapes={92:"\\\\",34:'\\"',8:"\\b",12:"\\f",10:"\\n",13:"\\r",9:"\\t"};var leadingZeroes="000000";var toPaddedString=function(width,value){return(leadingZeroes+(value||0)).slice(-width)};var unicodePrefix="\\u00";var quote=function(value){var result='"',index=0,length=value.length,useCharIndex=!charIndexBuggy||length>10;var symbols=useCharIndex&&(charIndexBuggy?value.split(""):value);for(;index-1/0&&value<1/0){if(getDay){date=floor(value/864e5);for(year=floor(date/365.2425)+1970-1;getDay(year+1,0)<=date;year++);for(month=floor((date-getDay(year,0))/30.42);getDay(year,month+1)<=date;month++);date=1+date-getDay(year,month);time=(value%864e5+864e5)%864e5;hours=floor(time/36e5)%24;minutes=floor(time/6e4)%60;seconds=floor(time/1e3)%60;milliseconds=time%1e3}else{year=value.getUTCFullYear();month=value.getUTCMonth();date=value.getUTCDate();hours=value.getUTCHours();minutes=value.getUTCMinutes();seconds=value.getUTCSeconds();milliseconds=value.getUTCMilliseconds()}value=(year<=0||year>=1e4?(year<0?"-":"+")+toPaddedString(6,year<0?-year:year):toPaddedString(4,year))+"-"+toPaddedString(2,month+1)+"-"+toPaddedString(2,date)+"T"+toPaddedString(2,hours)+":"+toPaddedString(2,minutes)+":"+toPaddedString(2,seconds)+"."+toPaddedString(3,milliseconds)+"Z"}else{value=null}}else if(typeof value.toJSON=="function"&&(className!=numberClass&&className!=stringClass&&className!=arrayClass||isProperty.call(value,"toJSON"))){value=value.toJSON(property)}}if(callback){value=callback.call(object,property,value)}if(value===null){return"null"}className=getClass.call(value);if(className==booleanClass){return""+value}else if(className==numberClass){return value>-1/0&&value<1/0?""+value:"null"}else if(className==stringClass){return quote(""+value)}if(typeof value=="object"){for(length=stack.length;length--;){if(stack[length]===value){throw TypeError()}}stack.push(value);results=[];prefix=indentation;indentation+=whitespace;if(className==arrayClass){for(index=0,length=value.length;index0){for(whitespace="",width>10&&(width=10);whitespace.length=48&&charCode<=57||charCode>=97&&charCode<=102||charCode>=65&&charCode<=70)){abort()}}value+=fromCharCode("0x"+source.slice(begin,Index));break;default:abort()}}else{if(charCode==34){break}charCode=source.charCodeAt(Index);begin=Index;while(charCode>=32&&charCode!=92&&charCode!=34){charCode=source.charCodeAt(++Index)}value+=source.slice(begin,Index)}}if(source.charCodeAt(Index)==34){Index++;return value}abort();default:begin=Index;if(charCode==45){isSigned=true;charCode=source.charCodeAt(++Index)}if(charCode>=48&&charCode<=57){if(charCode==48&&(charCode=source.charCodeAt(Index+1),charCode>=48&&charCode<=57)){abort()}isSigned=false;for(;Index=48&&charCode<=57);Index++);if(source.charCodeAt(Index)==46){position=++Index;for(;position=48&&charCode<=57);position++);if(position==Index){abort()}Index=position}charCode=source.charCodeAt(Index);if(charCode==101||charCode==69){charCode=source.charCodeAt(++Index);if(charCode==43||charCode==45){Index++}for(position=Index;position=48&&charCode<=57);position++);if(position==Index){abort()}Index=position}return+source.slice(begin,Index)}if(isSigned){abort()}if(source.slice(Index,Index+4)=="true"){Index+=4;return true}else if(source.slice(Index,Index+5)=="false"){Index+=5;return false}else if(source.slice(Index,Index+4)=="null"){Index+=4;return null}abort()}}return"$"};var get=function(value){var results,hasMembers;if(value=="$"){abort()}if(typeof value=="string"){if((charIndexBuggy?value.charAt(0):value[0])=="@"){return value.slice(1)}if(value=="["){results=[];for(;;hasMembers||(hasMembers=true)){value=lex();if(value=="]"){break}if(hasMembers){if(value==","){value=lex();if(value=="]"){abort()}}else{abort()}}if(value==","){abort()}results.push(get(value))}return results}else if(value=="{"){results={};for(;;hasMembers||(hasMembers=true)){value=lex();if(value=="}"){break}if(hasMembers){if(value==","){value=lex();if(value=="}"){abort()}}else{abort()}}if(value==","||typeof value!="string"||(charIndexBuggy?value.charAt(0):value[0])!="@"||lex()!=":"){abort()}results[value.slice(1)]=get(lex()) +}return results}abort()}return value};var update=function(source,property,callback){var element=walk(source,property,callback);if(element===undef){delete source[property]}else{source[property]=element}};var walk=function(source,property,callback){var value=source[property],length;if(typeof value=="object"&&value){if(getClass.call(value)==arrayClass){for(length=value.length;length--;){update(value,length,callback)}}else{forEach(value,function(property){update(value,property,callback)})}}return callback.call(source,property,value)};exports.parse=function(source,callback){var result,value;Index=0;Source=""+source;result=get(lex());if(lex()!="$"){abort()}Index=Source=null;return callback&&getClass.call(callback)==functionClass?walk((value={},value[""]=result,value),"",callback):result}}}exports["runInContext"]=runInContext;return exports}if(freeExports&&!isLoader){runInContext(root,freeExports)}else{var nativeJSON=root.JSON,previousJSON=root["JSON3"],isRestored=false;var JSON3=runInContext(root,root["JSON3"]={noConflict:function(){if(!isRestored){isRestored=true;root.JSON=nativeJSON;root["JSON3"]=previousJSON;nativeJSON=previousJSON=null}return JSON3}});root.JSON={parse:JSON3.parse,stringify:JSON3.stringify}}if(isLoader){define(function(){return JSON3})}}).call(this)}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:typeof global!=="undefined"?global:{})},{}],51:[function(_dereq_,module,exports){module.exports=toArray;function toArray(list,index){var array=[];index=index||0;for(var i=index||0;i") + so.Emit("sys", "Enter a name to connect as (or name:pass for a registered nick)") + + doneChan := make(chan struct{}, 0) + + so.On("hello", func(data map[string]string) { + log.Printf("[%s] Connection request", so.Id()) + go this.HubWorker(data["nick"], data["pass"], so, doneChan) + }) + + so.On("disconnection", func() { // n.b. not 'disconnect' (??) + log.Printf("[%s] Client dropped", so.Id()) + close(doneChan) + }) + +} + +func (this *App) ConfigRequestHandler(w http.ResponseWriter, r *http.Request) { + + confStruct := struct { + Extern string `json:"extern"` + Title string `json:"title"` + }{ + Extern: this.cfg.Web.Extern, + Title: this.cfg.Web.Title, + } + confBytes, _ := json.Marshal(confStruct) + + // + + w.Header().Set("Content-Type", "text/javascript") + w.WriteHeader(200) + fmt.Fprintf(w, "var DCWEBUI_CONF = %s;\n", string(confBytes)) +} + +func (this *App) StaticRequestHandler(w http.ResponseWriter, r *http.Request) { + fileName := r.URL.Path[1:] + + data, err := Asset(fileName) + if err != nil { + w.WriteHeader(404) + return + } + + knownContentTypes := map[string]string{ + ".htm": "text/html", + ".css": "text/css", + ".js": "application/javascript", + ".png": "image/png", + } + + foundMime := false + for ext, mimeType := range knownContentTypes { + if strings.HasSuffix(fileName, ext) { + w.Header().Set("Content-Type", mimeType) + foundMime = true + break + } + } + if !foundMime { + w.Header().Set("Content-Type", "application/x-octet-stream") + } + dataInfo, _ := AssetInfo(fileName) + w.Header().Set("Content-Length", fmt.Sprintf("%d", dataInfo.Size())) + + w.Write(data) +} + +func (this *App) RunServer() { + + // Socket.io handler + server, err := socketio.NewServer(nil) + if err != nil { + log.Fatal(err) + } + server.On("connection", this.SocketIOServer) + server.On("error", func(so socketio.Socket, err error) { + log.Println("error:", err) + }) + http.Handle("/socket.io/", server) + + // Configuration handler + http.HandleFunc("/conf", this.ConfigRequestHandler) + + // Other files: asset handler + http.HandleFunc("/", this.StaticRequestHandler) + + // Listen and serve + bindAddr := fmt.Sprintf("%s:%d", this.cfg.Web.BindTo, this.cfg.Web.Port) + log.Printf("Serving at %s...", bindAddr) + log.Fatal(http.ListenAndServe(bindAddr, nil)) +} + +func main() { + + a, err := NewApp("nmdc-webfrontend.conf") + if err != nil { + log.Fatal(err.Error()) + return + } + + a.RunServer() +} diff --git a/nmdc-webfrontend.conf b/nmdc-webfrontend.conf new file mode 100644 index 0000000..61cee40 --- /dev/null +++ b/nmdc-webfrontend.conf @@ -0,0 +1,23 @@ +{ + + "app": { + "name" : "DCWebUI2", + "version": "1.3.0", + "motd" : "Welcome!
    ", + "debug" : true + }, + + "web": { + "port" : 8082, + "bind_to": "127.0.0.1", + "extern" : "http://127.0.0.1:8082", + "title" : "DCWebUI" + }, + + "hub": { + "address": "127.0.0.1", + "port" : 411, + "tag" : "DCWebUI2.js" + } + +} \ No newline at end of file