Skip to content

Instantly share code, notes, and snippets.

@daviddahl
Created July 25, 2011 21:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save daviddahl/1105340 to your computer and use it in GitHub Desktop.
Save daviddahl/1105340 to your computer and use it in GitHub Desktop.
chatter.js
// Encrypt chat bookmarklet
// Author: David Dahl <ddahl@mozilla.com>
// (function (){ var e = document.createElement("script"); e.src = "https://raw.github.com/gist/1105340/88e82d098691fbc1d1ba37ca6ed7c9d5aef97c1c/chatter.js?t=" + Date.now(); document.body.appendChild(e);}());
function Chatter()
{
var DEBUG = false;
var self = this;
document.addEventListener("DOMNodeInserted", function nodeInserted(aEvent) {
console.log("...DOMNodeInserted...");
console.log(aEvent.target);
self.discoverMessage(aEvent);
});
if (DEBUG) {
document.getElementById("send").addEventListener("click",
// XXX: this event is for the demo only
function clickButton(aEvent) {
self.transformMessage();
var node = document.createElement("div");
node.setAttribute("class", "msg-node");
node.innerHTML = new String(self.inputNode.value);
var parent = document.getElementById("messages");
document.getElementById("messages").insertBefore(node, parent.childNodes[0]);
self.inputNode.value = "";
}, false);
}
this.testMode = true;
this.launchUI();
}
Chatter.prototype = {
chooseInputNodeEvent: function c_chooseInputNodeEvent()
{
var self = this;
var attempts = 0;
window.addEventListener("click", function chooseNode(aEvent) {
attempts++;
if (self.chooseInputNode(aEvent)) {
window.removeEventListener("click", chooseNode, false);
}
else {
if (attempts > 3) {
alert("Apparently you do not understand what to do. Please read the docs at http://domcrypt.org");
attempts = 0;
}
else {
alert("Please choose a chat input widget");
}
}
}, false);
},
uiMinimized: false,
uiVisible: false,
onscroll: function c_onscroll()
{
var _scroll;
if (window.onscroll) {
window.onscroll = _scroll;
}
window.onscroll = function _chatterOnScroll(aEvent) {
// move the UI down or up on scroll...
var node = document.querySelector("#_chatter-writing-node");
node.style.top = window.scrollY + "px";
node = document.querySelector("#_chatter-minimized");
node.style.top = window.scrollY + "px";
console.log("adjusted position");
if (_scroll) {
_scroll(aEvent);
}
};
},
showEncodingEditor: function c_showEncodingEditor()
{
document.querySelector("#_chatter-message-encoder").style.display = "block";
},
hide: function c_hide()
{
document.getElementById("_chatter-minimized").style.display = "block";
document.getElementById("_chatter-writing-node").style.display = "none";
},
show: function c_show()
{
document.getElementById("_chatter-writing-node").style.display = "block";
document.getElementById("_chatter-minimized").style.display = "none";
},
launchUI: function c_launchUI()
{
this.onscroll();
this.uiVisible = true;
var nodeStr = '<div id="_chatter-minimized" onclick="_chatter.show();" '
+ 'style="position:absolute; top: 0px; left: 0px; display:none; '
+ 'cursor: pointer; width: 5%; '
+ 'background-color: #ccc; border: 1px solid #999;">'
+ '<span>chatter</span></div>'
+ '<div class="max" id="_chatter-writing-node" '
+ 'style="background-color: #eee; border: 1px solid #aaa; position:absolute; top: 0px; left: 0px;">'
+ '<div class="min" id="handle" '
+ 'style="background-color: #eee; width:100%; '
+ 'border: 1px solid #bbb;">'
+ ' <span style="font-size: 90%; font-weight: bold; text-transform: uppercase">Chatter</span> '
+ '<button onclick="_chatter.chooseInputNodeEvent();" id="_chatter-choose-input">Select Chat Input</button>'
+ '<button id="_chatter-encode-message-ui-btn" onclick="_chatter.showEncodingEditor();">Message Pad</button>'
+ '<button id="_chatter-hide-btn" onclick="_chatter.hide();">Hide</button>'
+ ' </div>'
+ '<div id="_chatter-message-encoder" style="display: none;">'
+ '<textarea class="min" style="width: 70%; height:8em; margin:1em;"'
+ 'id="_chatter-writing-node-textarea">'
+ '</textarea> '
+ '<button onclick="_chatter.encodeMessage();" class="min" style="margin: 1em;" id="_chatter-button">Make Message Private</button>'
+ '<button onclick="_chatter.hideEncodingEditor();" class="min" style="margin: 1em;" id="_chatter-cancel-btn">Cancel</button>'
+ '</div>'
+ '<div id="_chatter-console" style="font-family: monospace; font-size: 90%;"></div>'
+ '</div>';
var wrapperNode = document.createElement("div");
wrapperNode.innerHTML = nodeStr;
var body = document.querySelector("body");
var node;
for (var i = 0; i < body.childNodes.length; i++) {
node = body.childNodes.item(i);
if (node.nodeType == 1) {
body.insertBefore(wrapperNode, node);
break;
}
}
},
hideEncodingEditor: function c_hideEncodingEditor()
{
document.querySelector("#_chatter-message-encoder").style.display = "none";
},
inputNode: null,
recipientPubKey: null,
init: function c_init()
{
this.launchUI();
},
get writingNode() {
return document.getElementById("_chatter-writing-node-textarea");
},
verbose: false,
encodeMessage: function c_encodeMessage()
{
var self = this;
var str = this.writingNode.value;
if (!str) {
alert("Please enter a message to encode");
}
else {
if (!window.recipientPubKey) {
alert("Your chatting partner has not initiated private message sending");
return;
}
window.mozCipher.pk.encrypt(str, window.recipientPubKey,
function callback(aCipherMsg) {
var cipherTxt = JSON.stringify(aCipherMsg);
self.inputNode.value = "chatter||||" + "Private Message" + "||||" + cipherTxt;
self.writingNode.value = "";
self.hideMessagePad();
if (self.verbose)
alert("Now you can send the private message");
});
}
},
hideMessagePad: function c_hideMessagePad()
{
document.getElementById("_chatter-message-encoder").style.display = "none";
},
transformMessage: function c_transformMessage(aEvent)
{
var self = this;
var str = this.inputNode.value;
var data = str.split("||||");
console.log(data);
if (data.length != 3 || !data[0]) {
// plain text message needs to be encrypted
window.mozCipher.pk.encrypt(str, window.recipientPubKey,
function callback(aCipherMsg) {
var cipherTxt = JSON.stringify(aCipherMsg);
self.inputNode.value = "chatter||||" + "Private Message" + "||||" + cipherTxt;
});
}
},
testMode: function c_testMode()
{
window.mozCipher.pk.getPublicKey(function (aKey) {
window.recipientPubKey = aKey;
console.log("_chatter: test mode started");
});
},
discoverMessage: function c_discoverMessage(aEvent)
{
var self = this;
console.log(aEvent.target);
if (aEvent.target) {
var str = aEvent.target.innerHTML;
var data = str.split("||||");
if (data[0] == "chatter") {
// switch through the commands, set pubkey or parse, decrypt message and display message
console.log(data[0]);
console.log(data[1]);
console.log(data[2]);
switch (data[1]) {
case "Private Message":
if (window.recipientPubKey) {
console.info("decrypting...");
console.info("target: " + aEvent.target);
console.info("data[2]: " + data[2]);
try {
self.decryptMessage(data[2], window.recipientPubKey, aEvent.target);
}
catch (ex) {
console.log(ex);
console.log(ex.stack);
}
}
else {
console.error("Error: Configuration problem");
}
break;
case "Initiate Private Message":
console.log("Initiate Private Message!!!!");
console.log(data[2]);
window.recipientPubKey = data[2];
default:
break;
}
}
else {
// not a recognized incoming message
}
}
},
decryptMessage: function c_decryptMessage(aMsg, aPubKey, aNode)
{
console.log("aMsg: ");
console.log(aMsg);
var msg = JSON.parse(aMsg);
console.log("message object: " + msg);
var self = this;
try {
window.mozCipher.pk.decrypt(msg, function decrypt(aPlainTxt) {
console.log(msg);
aNode.innerHTML = "<pre>"
+ aPlainTxt
+ "</pre>";
});
}
catch(ex) {
console.log(ex);
console.log(ex.stack);
}
},
offerKey: function c_offerKey(aKey)
{
this.inputNode.value = "chatter||||Initiate Private Message||||" + aKey;
},
checkKey: function c_checkKey()
{
// var self = this;
// var pubKey = localStorage.getItem("_chatter_pubkey");
// if (pubKey != "" && pubKey != null && pubKey != undefined) {
// self.offerKey(pubKey);
// return;
// }
var self = this;
// check if we have a pubKey
window.mozCipher.pk.getPublicKey(function callback(aKey) {
if (aKey) {
console.log("getPubKey");
// localStorage.setItem("_chatter_pubkey", aKey);
self.offerKey(aKey);
}
else {
// generate a keyPair
console.log("generatePubKey");
window.mozCipher.pk.generateKeypair(function callback (aNewKey) {
// localStorage.setItem("_chatter_pubkey", aNewKey);
self.offerKey(aNewKey);
});
}
});
},
chooseInputNode: function c_chooseInputNode(aEvent)
{
var tagName = aEvent.target.tagName;
if (!(aEvent.target.getAttribute("contenteditable") ||
tagName == "TEXTAREA" || tagName == "INPUT")) {
return false;
}
this.inputNode = aEvent.target;
this.checkKey();
console.log("chooseInputNode: editable node found");
alert("Please send the current *unedited* chat message to begin using Chatter");
return true;
}
};
function _chatter_toggle(aNode)
{
if (!_chatter.uiMinimized) {
aNode.parentNode.parentNode.style.width = "1em";
aNode.parentNode.parentNode.style.height = "1em";
var nodes = document.querySelectorAll(".min");
for (var node in nodes) {
if (nodes[node].style) {
nodes[node].style.display = "none";
}
}
document.querySelector("#_chatter-writing-node").
addEventListener("click", function _chatterMax(aEvent) {
document.querySelector("#_chatter-writing-node").
removeEventListener("click", _chatterMax, false);
_chatter_toggle(document.querySelector("#_chatter-toggle-btn"));
}, false);
}
else {
aNode.parentNode.parentNode.style.width = "400px";
aNode.parentNode.parentNode.style.height = "8em";
var nodes = document.querySelectorAll(".min");
for (var node in nodes) {
if (nodes[node].style) {
nodes[node].style.display = "block";
}
}
}
}
window._chatter = new Chatter();
@mygithubdechu
Copy link

jhkjhh

@mygithubdechu
Copy link

njnkjnkj

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment