diff options
| author | yo momma <shutup@oops.wtf> | 2026-02-03 22:17:28 +0000 |
|---|---|---|
| committer | yo momma <shutup@oops.wtf> | 2026-02-03 22:17:28 +0000 |
| commit | 079fa651299418f8fed63f0d2bdb7e05abbec01a (patch) | |
| tree | d4cb76542d7fe90f6f205c4e1fca652be9d7e9b5 /static/resizetest/dump.fm.av.files/pichat.js | |
| parent | 5c0f41e1960d7b6f0ca5cc4795c5ab25eedca5c2 (diff) | |
Hump.fm: rename legacy resizetest/nickinterview fixtures
Diffstat (limited to 'static/resizetest/dump.fm.av.files/pichat.js')
| -rwxr-xr-x | static/resizetest/dump.fm.av.files/pichat.js | 1704 |
1 files changed, 0 insertions, 1704 deletions
diff --git a/static/resizetest/dump.fm.av.files/pichat.js b/static/resizetest/dump.fm.av.files/pichat.js deleted file mode 100755 index bdef69c..0000000 --- a/static/resizetest/dump.fm.av.files/pichat.js +++ /dev/null @@ -1,1704 +0,0 @@ -// http://plugins.jquery.com/files/jquery.cookie.js.txt -jQuery.cookie=function(name,value,options){if(typeof value!='undefined'){options=options||{};if(value===null){value='';options.expires=-1;} -var expires='';if(options.expires&&(typeof options.expires=='number'||options.expires.toUTCString)){var date;if(typeof options.expires=='number'){date=new Date();date.setTime(date.getTime()+(options.expires*24*60*60*1000));}else{date=options.expires;} -expires='; expires='+date.toUTCString();} -var path=options.path?'; path='+(options.path):'';var domain=options.domain?'; domain='+(options.domain):'';var secure=options.secure?'; secure':'';document.cookie=[name,'=',encodeURIComponent(value),expires,path,domain,secure].join('');}else{var cookieValue=null;if(document.cookie&&document.cookie!=''){var cookies=document.cookie.split(';');for(var i=0;i<cookies.length;i++){var cookie=jQuery.trim(cookies[i]);if(cookie.substring(0,name.length+1)==(name+'=')){cookieValue=decodeURIComponent(cookie.substring(name.length+1));break;}}} -return cookieValue;}}; - -var cache = {} -var PendingMessages = {} -var MessageContentCache = {} -var RawFavs = {} -var MaxImagePosts = 30 - -// todo: preload these. also, look into image sprites (no go on animating their sizes tho) -// css clipping perhaps? -Imgs = { - "chatThumb": "/static/img/thumbs/smallheartfaved.gif", - "chatThumbBig": "/static/img/thumbs/chatheartover.gif", - "chatThumbOff": "/static/img/thumbs/smallheart.gif", - "chatThumbDot": "/static/img/thumbs/smallheart.gif", - "logThumb": "/static/img/thumbs/heartfaved.gif", - "logThumbBig": "/static/img/thumbs/heartover.gif", - "logThumbOff": "/static/img/thumbs/heart.gif" -} - -Anim = { - "chatThumbBig": {"width": "54px", "height": "54px", "right": "0px", "bottom": "2px"}, - "chatThumbTiny": {"width": "16px", "height": "16px", "right": "8px", "bottom": "8px"}, - "chatThumb": {"width": "16px", "height": "16px", "right": "4px", "bottom": "4px"}, - "logThumb": {"width": "27px", "height": "27px", "marginRight": "0px", "marginTop": "0px"}, - "logThumbBig": {"width": "64px", "height": "64px", "marginRight": "-2px", "marginTop": "-2px"} -} - -// Utils - -isEmptyObject = function(obj) { - for (key in obj) { - if (obj.hasOwnProperty(key)) return false; - } - return true -} - -String.prototype.trim = function(){ return this.replace(/^\s+|\s+$/g,'') } - -function isCSSPropertySupported(prop){ return prop in document.body.style } - -function track(group, name) { - if (typeof pageTracker !== 'undefined') { - pageTracker._trackEvent(group, name, - typeof Nick !== 'undefined' ? Nick : 'anon'); - } -} - -var Preferences = { - "Domain": '.dump.fm', - - "getProperty": function(prop, defaultValue) { - var value = $.cookie(prop); - return (value !== null) ? value : defaultValue; - }, - - "setProperty": function(prop, val) { - $.cookie(prop, val, { domain: Preferences.Domain, path: '/' }); - }, - - "delProperty": function(prop) { - $.cookie(prop, null, { domain: Preferences.Domain, path: '/' }); - } -}; - -function escapeHtml(txt) { - if (!txt) { return ""; } -// txt = annoyingCaps(txt) - return $("<span>").text(txt).html() -} - -var Log = { - "Levels": ['info', 'warn', 'error'], - "AjaxSubmitLevels": ['warn', 'error'], - "AjaxSubmitPath": "/logerror", - - "SupplementalInfo": function() { - return { 'user': UserInfo && UserInfo.nick }; - }, - - "ajaxSubmit": function(level, component, msg) { - var info = Log.SupplementalInfo(); - var data = { 'level': level, 'component': component, 'msg': msg }; - $.extend(info, data); - - $.ajax({type: 'POST', - timeout: 5000, - url: Log.AjaxSubmitPath, - data: info - }); - }, - - "initialize": function() { - $.each(Log.Levels, function(i, level) { - Log[level] = function(component, msg) { - if (window.console && window.console[level]) - window.console[level](args); - if (Log.AjaxSubmitLevels.indexOf(level) != -1) - Log.ajaxSubmit(level, args); - }; - }); - } -}; - -Log.initialize(); - - -URLRegex = /((\b(http\:\/\/|https\:\/\/|ftp\:\/\/)|(www\.))+(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi; -PicRegex = /\.(jpg|jpeg|png|gif|bmp|svg|fid)$/i; - -function getImagesAsArray(text) { - var imgs = [] - var urls = text.match(URLRegex) - if (urls === null) return imgs - for (var i = 0; i<urls.length; i++){ - var url = urls[i] - var urlWithoutParams = url.replace(/\?.*$/i, ""); - if (PicRegex.test(urlWithoutParams)) - imgs.push(url) - } - return imgs -} - -function linkify(text) { - LastMsgContainsImage = false - text = text.replace(URLRegex, linkReplace); - return text -} - -function annoyingCaps(text){ - var chunks = text.split(" ") - for(var i=0; i<chunks.length; i++){ - var chunk = chunks[i] - if (!chunk.length || chunk.substr(0,4) == 'http') continue; - var letters=chunk.split("") - for(var j = 0; j<letters.length; j++){ - if (j % 2) letters[j] = letters[j].toUpperCase() - else letters[j] = letters[j].toLowerCase() - } - chunks[i] = letters.join("") - } - return chunks.join(" ") -} - - -function imgClickHandler() { - // Ugly hack. Don't open new links in chat, only in logs. - // Ugly hack mkII: ensure middle-click opens images in new tab - // c.f. http://code.google.com/p/chromium/issues/detail?id=255 - if ($.browser.webkit && event.button != 0) { - event.stopPropagation(); - } else { - return $('#chatrap').length == 0; - } -} - -// durty hack to use a global to check this... but otherwise i'd have to rewrite the String.replace function? :/ -var LastMsgContainsImage = false -function linkReplace(url) { - var lowerurl = url.toLowerCase(); - if (lowerurl.indexOf('http://') == 0 || lowerurl.indexOf('https://') == 0 || lowerurl.indexOf('ftp://') == 0) - linkUrl = url; - else - linkUrl = 'http://' + url; - - var uri = parseUri(url) - var type = getUriType(uri) - - if (type == 'image') { - LastMsgContainsImage = true; - return "<a target='_blank' href='" + linkUrl + "' class='img-wrapper' onclick='return imgClickHandler()'><img src='" + linkUrl + "'></a>"; - } else if (type == 'youtube') { - Youtube.startAnimation(); - return "<a target='_blank' class='youtube' href='" + linkUrl + "'>" + - "<img class='youtube-thumb' width='130' height='97' src='"+Youtube.nextThumbUrl(uri.queryKey.v)+"'>" + - "<img class='youtube-controls' src='/static/img/youtube.controls.png'></a>" - } else if (type == 'midi' || type == 'wav') { - return '<embed src="'+linkUrl+'" loop="false" autostart="false" volume="80" width="150" height="20" style="vertical-align:bottom"> <a href="'+linkUrl+'">'+uri.file+'</a>' - } else - return "<a target='_blank' href='" + linkUrl + "'>" + url + "</a>"; - -} - -Youtube = { - "timer": 0, - - "startAnimation": function(){ - if (!Youtube.timer) - Youtube.timer = setTimeout(Youtube.animate, 1000) - }, - - "animate": function(){ - var thumbs = $(".youtube-thumb") - thumbs.each(Youtube.nextThumb) - if (thumbs.length == 0){ - clearTimeout(Youtube.timer) - Youtube.timer = 0 - } else Youtube.timer = setTimeout(Youtube.animate, 1000); - }, - - "nextThumb": function(){ - var img = $(this); - // yt thumb url is http://i.ytimg.com/vi/0123456789A/1.jpg - var v = img.attr("src").substr(22,11) - var num = img.attr("src").charAt(34); - img.attr("src", (Youtube.nextThumbUrl(v, num))) - }, - - "nextThumbUrl": function(v, num){ - if (!num) num = 0; - num = (parseInt(num) % 3) + 1 // cycle over 1,2,3 - return "http://i.ytimg.com/vi/" + v + "/" + num + ".jpg" - }, - -} - - -function getUriType(uri){ - if (PicRegex.test(uri.file.toLowerCase())) - return "image"; - - if (parseDomain(uri.host) == "youtube.com" && ('v' in uri.queryKey || uri.anchor.indexOf('v') != -1)) - return "youtube"; - - if (uri.path.substr(-4) == ".mid" || uri.path.substr(-5) == ".midi") - return "midi" - - if (uri.path.substr(-4) == ".wav") - return "wav" - - - return "link"; -} - -function linkifyWithoutImage(text) { - LastMsgContainsImage = false - return text.replace(URLRegex, linkReplaceWithoutImage); -} - -function linkReplaceWithoutImage(url){ - var urlWithoutParams = url.replace(/\?.*$/i, ""); - linkUrl = url.indexOf('http://') == 0 ? url : 'http://' + url; - - return "<a target='_blank' href='" + linkUrl + "'>" + url + "</a>" -} - -// Message Handling - -var ImageMsgCount = 0 -function removeOldMessages(){ - // don't count posts that are all text - if (LastMsgContainsImage) ImageMsgCount += 1; - while (ImageMsgCount > MaxImagePosts) { - var imgMsg = $(".contains-image:first") - if (imgMsg.length) { - imgMsg.prevAll().remove() // remove all text messages before the image message - imgMsg.remove() - } else break; - ImageMsgCount -= 1; - } -} - -var TextEnabled = Preferences.getProperty("chat.textEnabled", "true") == "true"; - -function setTextEnable() { - if ($(this).attr('checked')) { - TextEnabled = true; - Preferences.setProperty("chat.textEnabled", "true"); - track('UI', 'TextEnabled'); - $('.dump').not('.contains-image').show(); - } else { - TextEnabled = false; - Preferences.setProperty("chat.textEnabled", "false"); - track('UI', 'TextDisabled'); - $('.dump').not('.contains-image').hide() - } -}; - -function buildMsgContent(content) { - if (content.substr(0,6) == "<safe>") - return content.substr(6,content.length - 13) - else return linkify(escapeHtml(content)); -} - -// todo: -// isLoading doesn't get passed the right thing by $.map in addMessages -function buildMessageDiv(msg, isLoading) { - var nick = escapeHtml(msg.nick); - removeOldMessages(); - - var builtContent = buildMsgContent(msg.content); - - var msgId = ('msg_id' in msg) ? 'id="message-' + msg.msg_id + '"' : ''; - var loadingClass = isLoading ? ' loading' : ''; - var containsImageClass = LastMsgContainsImage ? ' contains-image' : ''; - var displayStyle = (TextEnabled || LastMsgContainsImage) ? '' : ' style="display: none"'; - - return '<div class="msgDiv dump ' + loadingClass + containsImageClass + '" ' + msgId + displayStyle + '>' - + '<span class="nick"><b><a href="/' + nick + ' ">' + nick + '</a></b>' - + ' <img src="'+Imgs.chatThumbDot+'" class="chat-thumb" onclick="Tag.favorite(this)"> ' - + '</span>' - + '<span class="content">' + builtContent + '</span>' - + '</div>'; -} - -function buildUserDiv(user) { - if (user.avatar) { - return '<div class="username">' - + '<a href="/' + escapeHtml(user.nick) + '" target="_blank">' - + '<img src="' + user.avatar + '" width="50" height="50">' - + escapeHtml(user.nick) + '</a></div>'; - } else { - return '<div class="username">' - + '<a href="/' + escapeHtml(user.nick) + '" target="_blank">' - + '<img src="/static/img/noinfo.png" width="50" height="50">' - + escapeHtml(user.nick) + '</a></div>'; - } -} - -// Favs - -function buildFav(f) { - var h = '<div class="fav-note">' - + '<img src="/static/img/thumbs/chatheartover.gif">' - + '<a href="/' + f.from + '">' + f.from + '</a>' - + ' <span>just faved you!</span>' - + '</div>'; - return $(h); -} - -function removeFavAndHideBox() { - $(this).remove(); - if ($('#favbox').children().length == 0) - $('#favbox').hide(); -} - -function showFav(f) { - $('#favbox').show(); - buildFav(f).appendTo('#favbox').animate( - {"opacity": 0}, - {"duration": 9000, - "easing": "easeInExpo", - "complete": removeFavAndHideBox - }) - -} - - -function updateFavs(fs) { - if (fs.length == 0) - return; - $('#favbox').show(); - $(fs).each(function(i, f) { showFav(f) }); -} - - -// Growl - -function buildGrowlDataAndPopDatShit(msg) { - var nick = escapeHtml(msg.nick); - nick = '<a href="/' + nick + ' " style="color:pink">' + nick + '</a>:' - var msg = buildMsgContent(msg.content) - growl(nick, msg) -} - -function growl(user, msg) { - $.gritter.add({title: user, text: msg}); -} - -function handleMsgError(resp) { - var respText = resp.responseText ? resp.responseText.trim() : false; - if (respText == 'MUST_LOGIN') { - alert("Can't send message! Please login."); - } else if (respText) { - alert("Can't send message! " + respText); - } else { - alert("Can't send message!"); - } -} - -// Messages - -function invalidImageDomain(content) { - var words = content.toLowerCase().split(' '); - for (var i = 0; i < words.length; i++) { - var w = words[i]; - if (PicRegex.test(w)) { - for (var j = 0; j < InvalidDomains.length; j++) { - var d = InvalidDomains[j]; - if (w.indexOf(d) != -1) { - return d; - } - } - } - } -} - -function submitMessage() { - var content = $.trim($('#msgInput').val()); - - var invalidDomain = invalidImageDomain(content); - if (invalidDomain) { - $('#msgInput').blur(); // Remove focus to prevent FF alert loop - alert("Sorry, cannot accept images from " + invalidDomain + ". Maybe host the image elsewhere?"); - return; - } - - $('#msgInput').val(''); - if (content == '') { return; } - if (content.length > 2468) { - alert("POST TOO LONG DUDE!"); - return; - } // this shouldn't just be client side :V - PendingMessages[content] = true; - - var msg = { 'nick': Nick, 'content': content }; - var div = addNewMessage(msg, true); - - var onSuccess = function(json) { - if (typeof pageTracker !== 'undefined') { - pageTracker._trackEvent('Message', 'Submit', - typeof Room !== 'undefined' ? Room : 'UnknownRoom'); - } - div.attr('id', 'message-' + json) - .removeClass('loading').addClass('loaded'); - }; - var onError = function(resp, textStatus, errorThrown) { - div.remove(); - handleMsgError(resp); - }; - - $.ajax({ - type: 'POST', - timeout: 15000, - url: '/msg', - data: { 'room': Room, 'content': content }, - cache: false, - dataType: 'json', - success: onSuccess, - error: onError - }); -} - -function ifEnter(fn) { - return function(e) { - if (e.keyCode == 13) { fn(); } - }; -} - -function addNewMessages(msgs) { - var msgStr = $.map(msgs, buildMessageDiv).join(''); - $('#messageList').append(msgStr); -} - -function addNewMessage(msg, isLoading) { - var msgStr = buildMessageDiv(msg, isLoading); - var div = $(msgStr).appendTo('#messageList'); - return div; -} - -function setUserList(users) { - $("#userList").html($.map(users, buildUserDiv).join('')); -} - -function flattenUserJson(users) { - var s = ""; - $.map(users.sort(), function(user) { - s += user.nick + user.avatar; - }); - return s; -} - -function updateUI(msgs, users, favs) { - if (window['growlize'] && msgs && msgs.length > 0) { - $.map(msgs, buildGrowlDataAndPopDatShit) - } else if (msgs && msgs.length > 0) { - addNewMessages(msgs); - } - if (users !== null) { - var flattened = flattenUserJson(users); - if (!('userlist' in cache) || flattened != cache.userlist) { - $("#userList").html($.map(users.sort(sortUsersByAlpha), buildUserDiv).join('')); - } - cache.userlist = flattened - } - updateFavs(favs); -} - -function sortUsersByAlpha(a, b){ - var nickA = a.nick.toLowerCase() - var nickB = b.nick.toLowerCase() - if (nickA > nickB) return 1 - else if (nickA < nickB) return -1 - return 0 -} - -function isDuplicateMessage(m) { - if (m.nick == Nick && m.content in PendingMessages) { - delete PendingMessages[m.content]; - return true; - } else { - return false; - } -} - -function refresh() { - var onSuccess = function(json) { - try { - Timestamp = json.timestamp; - - $.map(json.messages, function(msg){ MessageContentCache[msg.msg_id.toString()] = msg.content }) - - var messages = $.grep( - json.messages, - function(m) { return !isDuplicateMessage(m) }); - updateUI(messages, json.users, json.favs); - if (!Away.HasFocus) - Away.UnseenMsgCounter += messages.length; - } catch(e) { - if (IsAdmin && window.console) { - console.error(e); - } - } - setTimeout(refresh, 1000); - }; - var onError = function(resp, textStatus, errorThrown) { - var msg = $.trim(resp.responseText); - if (msg == "UNKNOWN_ROOM") - location.href = "/"; - if (IsAdmin && window.console) { - console.error(resp, textStatus, errorThrown); - } - setTimeout(refresh, 4000); - }; - - $.ajax({ - type: 'GET', - timeout: 5000, - url: '/refresh', - data: { 'room': Room, 'since': Timestamp }, - cache: false, - dataType: 'json', - success: onSuccess, - error: onError - }); -} - -function sendClicked(){ - track('UI', 'SendButtonActuallyClicked'); - submitMessage(); -} - -function paletteClicked(){ - track('UI', 'FavPaletteActuallyClicked'); - paletteToggle(); -} - - -function initChat() { - Search.init() - - $('.oldmsg').each(function() { - var dump = $(this); - var content = dump.find(".content") - MessageContentCache[dump.attr("id").substr(8)] = content.text() - content.html(buildMsgContent(content.text())); - if (!TextEnabled && !dump.hasClass('contains-image')) - dump.hide(); - else - dump.show(); - }); - - $('#msgInput').keyup(ifEnter(submitMessage)); - $('#msgSubmit').click(sendClicked); - $('#palette-button').click(paletteClicked); - - messageList = $("#messageList")[0] - - initChatThumb(); - - scrollToEnd() - scrollWatcher() - - // see /static/webcam/webcam.js - if ('webcam' in window) webcam.init() -} - -function startChatUpdater() { - setTimeout(refresh, 1000); -} - -function makePlainText() { - var j = $(this); - j.text(j.text()); -} - -function activateProfileEditable() { - var onSubmit = function(attr, newVal, oldVal) { - newVal = $.trim(newVal); - if (newVal == oldVal) { return oldVal }; - - $.ajax({ - type: "POST", - timeout: 5000, - url: "/update-profile", - data: { 'attr': attr, 'val': newVal } - }); - if (attr == 'avatar') { - if (newVal != "") { - var s = '<img id="avatarPic" src="' + newVal + '" width="150" />'; - $('#avatarPic').replaceWith(s).show(); - } else { - $('#avatarPic').hide(); - } - } - return escapeHtml(newVal); - }; - - if ($('#avatar-editing').length > 0) - setupUploadAvatar('uploadp'); - - var textareaOpts = { 'default_text': 'Enter here!', - 'callback': onSubmit, - 'field_type': 'textarea', - 'callbackShowErrors': false }; - $('#contact.editable, #bio.editable') - .editInPlace(textareaOpts) - .each(makePlainText); -} - -function enableProfileEdit() { - $('img#contact').replaceWith('<div id="contact" class="linkify"></div>'); - $('img#bio').replaceWith('<div id="bio" class="linkify"></div>'); - $('#contact, #bio, #avatar').addClass('editable'); - $('#avatar-editing').show(); - var resetPage = function() { location.reload() }; - $('#edit-toggle a').text('done editing').click(resetPage); - activateProfileEditable(); -} - -function initProfile() { - Search.init() - $(".linkify").each(function() { - var text = jQuery(this).text(); - jQuery(this).html(linkifyWithoutImage(text)); - }); - - $('#edit-toggle').click(enableProfileEdit); - activateProfileEditable(); - - $('.dash-dump .content').each(function() { - var t = $(this); - t.html(buildMsgContent(t.text())); - }); -}; - -function initLog() { - Search.init() - $('.logged-dump .content').each(function() { - var t = $(this); - t.html(buildMsgContent(t.text())); - }); - initLogThumb(".logged-dump .thumb", '.dump'); -} - -function initLogThumb(selector, parentSelector) { - $(selector).bind('mouseover mouseout', - function(e) { - var favorited = $(this).parents(parentSelector).hasClass("favorite") ? true : false; - if (e.type == "mouseover") { - if (favorited) { - $(this).attr("src", Imgs.logThumbOff); - } else { - $(this).attr("src", Imgs.logThumbBig); - $(this).stop().animate(Anim.logThumbBig, 'fast'); - } - } else { // mouseout - if (favorited) { - $(this).attr("src", Imgs.logThumb); - $(this).stop().animate(Anim.logThumb, 'fast'); - } else { - $(this).attr("src", Imgs.logThumbOff); - $(this).stop().animate(Anim.logThumb, 'fast'); - } - } - }) - } - -function initChatThumb(){ - $(".chat-thumb").live('mouseover mouseout', - function(e) { - var favorited = $(this).parents(".dump").hasClass("favorite") ? true : false; - if (e.type == "mouseover") { - if (favorited) { - $(this).attr("src", Imgs.chatThumbOff); - } else { - $(this).attr("src", Imgs.chatThumbBig); - $(this).stop().animate(Anim.chatThumbBig, 'fast') - } - } else { // mouseout - if (favorited) { - $(this).attr("src", Imgs.chatThumb); - $(this).stop().animate(Anim.chatThumb, 'fast'); - } else { - $(this).delay(600).stop().animate(Anim.chatThumbTiny, 'fast', 'swing', - function(){ - $(this).attr("src", Imgs.chatThumbDot) - $(this).animate(Anim.chatThumb, 0) - }) - } - } - }) -} - - -function paletteToChat(img){ - var chatText = $("#msgInput").val() - if (chatText.length && chatText[chatText.length - 1] != " ") - chatText += " " - chatText += $(img).attr("src") + " " - $("#msgInput").val(chatText) - $("#msgInput").focus().val($("#msgInput").val()) //http://stackoverflow.com/questions/1056359/ - paletteHide() -} - -paletteImageCache = false -function paletteBuildImageThumbs(){ - if (paletteImageCache) { - var imgs = paletteImageCache - } else { - var imgs = [] - var dupeFilter = {} - for(fav in RawFavs){ - var parsedImgs = getImagesAsArray(RawFavs[fav]) - for (var i=0; i<parsedImgs.length; i++){ - var img = parsedImgs[i] - if (!dupeFilter[img]) { - imgs.push(img) - dupeFilter[img] = true - } - } - } - paletteImageCache = imgs - } - - for(var i=0; i<imgs.length; i++){ - $("#palette-thumbs").append("<img onclick='paletteToChat(this)' src='"+imgs[i]+"'>") - } -} - -function paletteShow(){ - $("#palette").css("display", "block") - if (isEmptyObject(RawFavs)) { - $('#palette-thumbs').html('<div style="width:300px;color:#000;">This is where all the stuff you FAV goes!<br><br>To FAV a post click the little heart <img src="/static/img/thumbs/smallheart.gif"> next to a users name.<br><br> Everything you fav gets saved to your profile.. Have fun!</div>'); - } else { - paletteBuildImageThumbs(); - } -} -function paletteHide(){ - $("#palette").css("display", "none") - $("#palette-thumbs").html("") -} - -function paletteToggle(){ - if ($("#palette").css("display") == "none") - paletteShow() - else - paletteHide() -} - - -function setupUpload(elementId, roomKey) { - var onSubmit = function(file, ext) { - if (!(ext && /^(jpg|png|jpeg|gif|bmp|svg)$/i.test(ext))) { - alert('SORRY, NOT AN IMAGE DUDE... '); - return false; - } - }; - var onComplete = function(file, response) { - var r = $.trim(response); - if (r.match(/FILE_TOO_BIG/)) { - var maxSize = r.split(" ")[1] / 1024; - alert("Sorry. Your file is just too darn big. " - + maxSize + "KB or less please."); - return; - } else if (r.match(/FILE_NOT_IMAGE/)) { - alert("What did you upload? Doesn't seem like an image. Sorry."); - return; - } else if (r.match(/INVALID_RESOLUTION/)) { - var maxWidth = r.split(" ")[1]; - var maxHeight = r.split(" ")[2]; - alert("Sorry, the maximum image resolution is " - + maxWidth + "x" + maxHeight); - return; - } else if (r != "OK") { - alert(r); - return; - } - - if (typeof pageTracker !== 'undefined') { - var r = typeof Room !== 'undefined' ? Room : 'UnknownRoom'; - pageTracker._trackEvent('Message', 'Upload', r); - } - } - new AjaxUpload(elementId, { - action: '/upload/message', - autoSubmit: true, - name: 'image', - data: { room: roomKey }, - onSubmit: onSubmit, - onComplete: onComplete - }); -} - -function setupUploadAvatar(elementId) { - // NOTE: AjaxUpload responses aren't converted from JSON. - var onSubmit = function(file, error) { - $('#spinner').show(); - }; - var onComplete = function(file, resp) { - $('#spinner').hide(); - var r = $.trim(resp); - - if (r == 'INVALID_REQUEST') { - location.reload(); - } else if (r == 'NOT_LOGGED_IN') { - location.reload(); - } else if (r == 'INVALID_IMAGE') { - alert("Sorry, dump.fm can't deal with your image. Pick another :("); - return; - } else if (r.match(/FILE_TOO_BIG/)) { - var maxSize = r.split(" ")[1] / 1024; - alert("Sorry. Your avatar is just too fucking big. " - + maxSize + "KB or less please."); - return; - } else if (r.match(/INVALID_RESOLUTION/)) { - var maxWidth = r.split(" ")[1]; - var maxHeight = r.split(" ")[2]; - alert("Sorry, the maximum avatar resolution is " - + maxWidth + "x" + maxHeight); - return; - } - - var s = '<img id="dashavatarPic" src="' + r + '" />'; - $('#dashavatar').html(s).show(); - }; - new AjaxUpload(elementId, { - action: '/upload/avatar', - autoSubmit: true, - name: 'image', - onSubmit: onSubmit, - onComplete: onComplete - }); -} - - -/* - search adds a script to the page... the script will call either Search.searchResult() or Search.searchError() - todo: clean this up. remove duplicated function names etc -*/ - -var Search = { - - 'term': "", - 'imagesPerPage': 25, - 'images': [], - 'tokens': [], - - 'init': function(){ - $("#search-query").val("search dump.fm") - $("#search-query").focus(function(){ - if ($("#search-query").val() == 'search dump.fm') - $("#search-query").val("") - }) - $("#search-query").blur(function(){ - if ($("#search-query").val().trim() == '') - $("#search-query").val("search dump.fm") - }) - $("#search-query").keydown(ifEnter(Search.doSearch)) - $("#search-results-images a").live("mouseup", Search.click) - }, - - 'addScript': function(term) { - $("#search-script").remove() - $("head").append("<scr"+"ipt src='/cmd/ghettosearch/"+term+"' id='search-script'></sc"+"ript>") - }, - 'setContent': function(x){ - $("#search-results-images").html(x) - }, - 'setMessage': function(x){ - $("#search-controls").css("display", "block") - $("#search-control-text").html(x) - }, - 'searchError': function(error){ - Search.setContent("") - $('#search-control-previous').css("visibility", "hidden") - $('#search-control-next').css("visibility", "hidden") - Search.setMessage(error) - }, - - 'doSearch': function(){ - term = $("#search-query").val().trim().toLowerCase() - var rawTokens = term.split(" ") - Search.tokens = [] - for(var t = 0; t < rawTokens.length; t++) { - if (rawTokens[t].length > 2) - Search.tokens.push(rawTokens[t]) - } - if (Search.tokens.length == 0) { - Search.setMessage("search query too small") - } else { - Search.setMessage("searching for '"+Search.tokens.join(" and ")+"'") - Search.addScript(Search.tokens.join("+")) - } - }, - - 'renderPage': function(num){ - $("#search-results-images").css("display", "block") - $("#search-controls").css("display", "block") - if (Search.images.length > 0) - Search.setMessage("results for '"+Search.tokens.join(" and ")+"' (page " + (num + 1) + ")"); - var contentString = '' - var start = num * Search.imagesPerPage - var imageCounter = 0 - for(var i = start; i < Search.images.length; i++){ - if(imageCounter > Search.imagesPerPage) break; - contentString += '<a href="'+Search.images[i]+'" target="_blank" onclick="return false"><img src="'+Search.images[i]+'"></a>' - imageCounter += 1 - } - contentString += '<br><br><div id="search-commands">' - if(num > 0) { - $('#search-control-previous').attr("href", 'javascript:Search.renderPage('+(num-1)+')') - $('#search-control-previous').css("visibility", "visible") - } else { - $('#search-control-previous').attr("href", 'javascript:void()') - $('#search-control-previous').css("visibility", "hidden") - } - - if (Search.images.length > start + imageCounter) { - $('#search-control-next').attr("href", 'javascript:Search.renderPage('+(num+1)+')') - $('#search-control-next').css("visibility", "visible") - } else { - $('#search-control-next').attr("href", 'javascript:void()') - $('#search-control-next').css("visibility", "hidden") - } - Search.setContent(contentString) - }, - - 'click': function(e){ - if (e.which == 1) // left click - if (Search.addToChatBoxIfPossible(this)) - window.open(this.href) - else if (e.which == 2) // middle click - window.open(this.href) - }, - - 'addToChatBoxIfPossible': function(img){ - var chatBoxExists = $("#msgInput").length - if (chatBoxExists) { - var chatText = $("#msgInput").val() - if (chatText.length && chatText[chatText.length - 1] != " ") - chatText += " " - chatText += $(img).attr("href") + " " - $("#msgInput").val(chatText) - $("#msgInput").focus().val($("#msgInput").val()) //http://stackoverflow.com/questions/1056359/ - return false - } else return true - }, - - 'searchResult': function(results){ - Search.images = [] - var alreadyGot = {} - if(results === null || results.length == 0) { - Search.setContent("") - Search.setMessage("no results found") - } else { - for(var r = 0; r<results.length; r++){ - var content = results[r]['content'] - if (content.substring(0,6) == "<safe>") continue; // skip html posts - var imageUrls = getImagesAsArray(content); - for (var i=0; i<imageUrls.length; i++){ - var imageUrl = imageUrls[i]; - if (imageUrl in alreadyGot) continue; - alreadyGot[imageUrl] = true - var validImage = true; - for(var t = 0; t<Search.tokens.length; t++){ - if (imageUrl.toLowerCase().indexOf(Search.tokens[t]) == -1) { - validImage = false; - break; - } - } - if (validImage) - Search.images.push(imageUrl); - } - } - if (Search.images.length == 0) { - Search.setMessage("no results found") - } - Search.renderPage(0) - } - }, - 'close': function(){ - Search.setContent("") - $('#search-control-previous').css("visibility", "hidden") - $('#search-control-next').css("visibility", "hidden") - $("#search-results-images").css("display", "none") - $("#search-controls").css("display", "none") - } - - -} - - -// scrolling stuff -// this code keeps the div scrolled to the bottom, but will also let the user scroll up, without jumping down - -function isScrolledToBottom(){ - var threshold = 15; - - var containerHeight = messageList.style.pixelHeight || messageList.offsetHeight - var currentHeight = (messageList.scrollHeight > 0) ? messageList.scrollHeight : 0 - - var result = (currentHeight - messageList.scrollTop - containerHeight < threshold); - - return result; -} - -function scrollIfPossible(){ - if (lastScriptedScrolledPosition <= messageList.scrollTop || isScrolledToBottom()) - scrollToEnd() -} - -var lastScriptedScrolledPosition = 0 -function scrollToEnd(){ - messageList.scrollTop = messageList.scrollHeight - lastScriptedScrolledPosition = messageList.scrollTop -} - -function scrollWatcher(){ - scrollIfPossible() - setTimeout(scrollWatcher, 500) -} - -// well fuck webkit for not supporting {text-decoration: blink} - -function blinkStart(){ - blinkTimer = setInterval(function(){ - $(".blink").removeClass("blink").addClass("blink-turning-off") - $(".blink-off").removeClass("blink-off").addClass("blink") - $(".blink-turning-off").removeClass("blink-turning-off").addClass("blink-off") - },500); -} - -function blinkStop(){ - clearInterval(blinkTimer); -} - -function initDirectory() { - $('.linkify').each(function() { - var t = $(this); - t.html(buildMsgContent(t.text())); - }); - Search.init() - initLogThumb('.dlogged-dump .thumb', '.dlogged-dump'); -} - -//big hand stuff -// TODO: replace this with simple pointer-events thing. -function initBigHand(id){ - var cursorId = "#cursor-big" - var cursor = $(cursorId)[0] - - // jquery's reported element sizes are not exactly the same as the browser's 'mouseover' target sizes - // so we'll allow a few pixels extra - var fudgeFactor = 2 - - $(id).addClass("no-cursor") - - // i have to do this weirdly bc putting the cursor image where the mouse cursor is causes problems with mouse events: - // * it stops mousemove events on the image below the mouse cursor - // * it fucks up mouseover/out and even mouseenter/leave events, as well as click - - // so i am doing this: - // on mousing over the image: - // make cursor visible - // find image co-ords - // bind a global mousemove func - // bind cursor click event - // unbind mouseover - // mousemove func: - // move image to mouse co-ords - // if mouse co-ords are outside the image co-ords: - // make cursor invisible - // unbind mousemove func - // unbind cursor click event - - var mousemove = function(e){ - var y = e.pageY, x = e.pageX, coords = initBigHand.coords - - cursor.style.top = y + "px" - cursor.style.left = x - 32 + "px" // 32: (4 pixels * 8 pixels per big pixel) to line up pointy finger with cursor - if (y < coords.top || - y > coords.bottom || - x < coords.left || - x > coords.right) { - $(cursorId).addClass('invisible') - $(cursorId).css({"top": 0, "left": 0 }) - $(cursorId).unbind('click', cursorClick) - $('logo7').unbind('mousemove', mousemove) - $(id).mouseover(imageMouseOver) - } - } - - var cursorClick = function(){ $(id).click() } - - var imageMouseOver = function(){ - //console.log("moused over...") - initBigHand.coords = { - "left": $(id).offset().left - fudgeFactor, - "top": $(id).offset().top - fudgeFactor, - "right": $(id).offset().left + $(id).width() + fudgeFactor, - "bottom": $(id).offset().top + $(id).height() + fudgeFactor - } - $('body').mousemove(mousemove) - $(cursorId).click(cursorClick) - $(cursorId).removeClass('invisible') - $(id).unbind('mouseover', imageMouseOver) - } - - $(id).mouseover(imageMouseOver) - -} - -// grab message id etc from some element e that's inside a dump -// (messages have something like id="message-0001" class="dump" ) -function getMessageInfo(e){ - var message = $(e).parents(".dump") - var id = message.attr("id").substr(8) // cut "message-001" to "001" - var nick = message.attr("nick") - var link = "/p/" + nick + "/" + id - var content = message.find(".linkify") - if (!content.length) content = message.find(".content") - var rawContent = content.html() - var img = content.find("img").attr("src") - var via = "via " + nick + " on dump.fm" - return {"nick": nick, "id": id, "link": encodeURIComponent(link), - "content": rawContent, "img": encodeURIComponent(img), - "via": encodeURIComponent(via)} -} - -Share = { - "openLink": function(url){ - window.open(url, "_blank") - }, - "facebook": function(button){ - var message = getMessageInfo(button) - var url = "https://www.facebook.com/share.php?u=" + message.img + "&t=" + message.via - Share.openLink(url) - }, - "tumblr": function(button){ - var message = getMessageInfo(button) - var url = "http://www.tumblr.com/share?v=3&u=" + message.img + "&t=" + message.via - Share.openLink(url) - }, - "twitter": function(button){ - var message = getMessageInfo(button) - var url = "http://twitter.com/home?status=" + message.img + encodeURIComponent(" ") + message.via - Share.openLink(url) - }, - "delicious": function(button){ - var message = getMessageInfo(button) - var url = "http://delicious.com/save?url=" + message.img + "&title=" + message.img + "¬es=" + message.via - Share.openLink(url) - } -} - -Tag = { - "favorite": function(button){ - var message = getMessageInfo(button) - var favorited = ($(button).parents(".dump").hasClass("favorite")) ? true : false - if (favorited) { - Tag.rm(message.id, "favorite") - $(button).parents(".dump").removeClass("favorite") - if (RawFavs[message.id]) { - delete RawFavs[message.id] - paletteImageCache = false - } - } else { - Tag.add(message.id, "favorite") - $(button).parents(".dump").addClass("favorite") - if (RawFavs && MessageContentCache[message.id]) { // chat ui stuff - if ($("#palette-button").css("display") == "none") - paletteButtonShowAnim() - RawFavs[message.id] = MessageContentCache[message.id] - paletteImageCache = false - } - } - }, - "add": function(message_id, tag){ - Tag.ajax("/cmd/tag/add", {"message_id": message_id, "tag": tag}) - }, - "rm": function(message_id, tag){ - Tag.ajax("/cmd/tag/rm", {"message_id": message_id, "tag": tag}) - }, - "ajax": function(url, data) { - $.ajax({ - "type": 'POST', - "timeout": 5000, - "url": url, - "data": data, - "cache": false - }); - } -} - - -// uhhh todo: move preload stuff into js: -// var nextImage = new Image(); -// nextImage.src = "your-url/newImage.gif"; - -// mAcRoMeDiA sHiT -function MM_swapImgRestore() { //v3.0 - var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc; -} - -function MM_preloadImages() { //v3.0 - var d=document;if(d.images){ if(!d.MM_p) d.MM_p=new Array();var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++) if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}} -} - -function MM_findObj(n, d) { //v4.01 - var p,i,x; if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) { - d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);} - if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n]; - for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document); - if(!x && d.getElementById) x=d.getElementById(n); return x; -} - -function MM_swapImage() { //v3.0 - var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3) - if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];} -} - -function timeFunc(f){ - var start = new Date().getTime(); - var res = f(); - console.log((new Date().getTime()) - start + " msecs"); - return res; -} - -// parseUri 1.2.2 from http://blog.stevenlevithan.com/archives/parseuri -// (c) Steven Levithan <stevenlevithan.com>, MIT License -function parseUri (str) { - var o = parseUri.options, - m = o.parser[o.strictMode ? "strict" : "loose"].exec(str), - uri = {}, - i = 14; - - while (i--) uri[o.key[i]] = m[i] || ""; - - uri[o.q.name] = {}; - uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { - if ($1) uri[o.q.name][$1] = $2; - }); - - return uri; -}; - -parseUri.options = { - strictMode: false, - key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], - q: { - name: "queryKey", - parser: /(?:^|&)([^&=]*)=?([^&]*)/g - }, - parser: { - strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, - loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ - } -}; -// end parseUri - -function parseDomain(host){ - return host.toLowerCase().replace(/^www\./, "") -} - -var Away = { - "UnseenMsgCounter": 0, - "OrigTitle": "", - "HasFocus": true, - "UpdateFrequency": 3000, - - "onFocus": function() { - Away.HasFocus = true; - Away.UnseenMsgCounter = 0; - // Courtesy http://stackoverflow.com/questions/2952384/changing-the-window-title-when-focussing-the-window-doesnt-work-in-chrome - window.setTimeout(function () { $('title').text(Away.OrigTitle); }, 100); - }, - "onBlur": function() { - Away.HasFocus = false; - }, - - "updateTitle": function () { - if (Away.UnseenMsgCounter > 0) { - var plural = Away.UnseenMsgCounter > 1 ? 's' : ''; - $('title').text(Away.UnseenMsgCounter + ' new dump' + plural + '! | ' + Away.OrigTitle); - } - setTimeout(Away.updateTitle, Away.UpdateFrequency); - - }, - "startTitleUpdater": function() { - Away.OrigTitle = $('title').text(); - $(window).blur(Away.onBlur); - $(window).focus(Away.onFocus); - setTimeout(Away.updateTitle, Away.UpdateFrequency); - } -}; - -var imgZoomThreshhold = [125, 125]; - -function initChatMsgs() { - $('.msgDiv .content').live('mouseenter', function(e) { - $(this).addClass('msg-hover'); - }); - - $('.msgDiv .content').live('mouseleave', function(e) { - $(this).removeClass('msg-hover'); - }); - - $('.msgDiv .content .img-wrapper').live('mouseenter', function(e) { - var img = $(this).find('img'); - - if (img.width() < imgZoomThreshhold[0] || img.height() < imgZoomThreshhold[1]) - return; - - var zoomlink = $('<a>') - .attr({'href': img.attr('src') }) - .addClass('msg-image-zoom') - .append($('<img>').attr('src', '/static/img/zoom.gif') - .addClass('zoom-icon')) - .click(function() { window.open(img.attr('src')); return false; }); - $(this).append(zoomlink); - }); - - $('.msgDiv .content .img-wrapper').live('mouseleave', function(e) { - $(this).find('.msg-image-zoom').remove(); - }); - - - $('.content').live('click', function(e) { - var tagName = e.target.tagName; - if (tagName == 'A' || tagName == 'EMBED' || $(e.target).hasClass('youtube-thumb')) { - return true; - } - var msg = $(this).parent('.msgDiv'); - var wasFavorited = msg.hasClass("favorite"); - var button = msg.find('.chat-thumb'); - if (wasFavorited) { - $(button).attr("src", Imgs.chatThumbOff); - } else { - $(button).attr("src", Imgs.chatThumbBig); - $(button).stop().animate(Anim.chatThumbBig, 'fast').animate(Anim.chatThumb, 'fast', 'swing'); - } - Tag.favorite(button); - return false; - }); -} - -// sha1.js - -/* - * 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)); -} |
