Bug Me Not

By deleted user Last update Jul 17, 2005 — Installed 7,334 times.
// Bug Me Not
// version 1.0
// 2005-06-22
// Copyright (c) 2005, Reify
//
// --------------------------------------------------------------------
//
// This user script retrieves website login information
// from BugMeNot.com to help you bypass compulsory registration.
// If you use this, you are subject to the terms listed here:
// http://bugmenot.com/termsofuse.php
//
// To install for Internet Explorer, you need Turnabout:
// http://www.reifysoft.com/turnabout.php
// See instructions for using Turnabout here:
// http://www.reifysoft.com/turnabout.php?p=u
//
// To install for Firefox, you need Greasemonkey:
// http://greasemonkey.mozdev.org/
// Then restart Firefox and revisit this script.
// Under Tools, there will be a new menu item to "Install User Script".
// Accept the default configuration and install.
//
// --------------------------------------------------------------------
//
// ==UserScript==
// @name          Bug Me Not
// @namespace     http://www.reifysoft.com/?scr=BugMeNot
// @description   Bypass required registration using Bug Me Not
// @include       *
// ==/UserScript==

var allInputs = null;
var retrievals = 0;	// new logins gotten from the current page (i.e. reset on every page load)
var bmnView = "http://bugmenot.com/view.php";
var bmnUri = bmnView + "?url=" + location.href;
var bmnHomeUri = "http://bugmenot.com/";
var DEBUG = false;
var BLUR_TIMEOUT = 150;	// ms between a field losing focus and checking to see if any other of our fields has focus. If this is too low, the menu won't work because it will get display: none and its onclick won't fire.
var bmnWrappers = new Object();

var Style =
{
	menuLink:
	{
		border: "none",
		backgroundColor: "#fff",
		color: "#000",

		display: "block",
		padding: "2px",
		margin: "0",
		width: "12em",

		fontSize: "8pt",
		fontWeight: "normal",
		textDecoration: "none"
	},

	menuLinkHover:
	{
		backgroundColor: "#316AC5",
		color: "#fff"
	},

	menuLinkWrapper:
	{
		textAlign: "left",

		padding: "1px",
		margin: 0
	},

	bmnWrapper:
	{
		display: "none",
		fontFamily: "tahoma, verdana, arial, sans-serif",
		whiteSpace: "nowrap",

		position: "absolute",
		zIndex: 1000,

		padding: "2px",
		border: "1px solid #ACA899",
		backgroundColor: "#fff",

		opacity: "0.9",
		filter: "alpha(opacity=90)"
	}
};

function copyProperties(to, from)
{
	for (var i in from) to[i] = from[i];
}

function main()
{
	processPasswordFields();
}

function getBmnWrapper(pwFieldIndex)
{
	return document.getElementById("reify-bugmenot-bmnWrapper" + pwFieldIndex);
}

function processPasswordFields()
{
	allInputs = document.getElementsByTagName("input");
	var bmnContainer = document.createElement("div");
	bmnContainer.id = "reify-bugmenot-container";

	var bodyEl = document.getElementsByTagName("body")[0];
	if (!bodyEl) return;

	for (var i = 0; i < allInputs.length; i++)
	{
		var pwField = allInputs[i];
		if (!(pwField.type && pwField.type.toLowerCase() == "password"))
			continue;

		var previousTextFieldInd = getPreviousTextField(i);
		if (previousTextFieldInd == -1) { if (DEBUG) GM_log("Couldn't find text field before password input " + i + "."); continue; }

		var usernameField = allInputs[previousTextFieldInd];
		usernameField.usernameInputIndex = previousTextFieldInd;
		usernameField.passwordInputIndex = i;
		Utility.addEventHandler(usernameField, "focus", usernameField_onfocus);
		Utility.addEventHandler(usernameField, "blur", usernameField_onblur);

		Utility.addEventHandler(pwField, "focus", pwField_onfocus);
		Utility.addEventHandler(pwField, "blur", pwField_onblur);
		pwField.usernameInputIndex = previousTextFieldInd;
		pwField.passwordInputIndex = i;

		var menuLinkProperties =
		{
			passwordInputIndex: i,
			usernameInputIndex: previousTextFieldInd,
			onmouseover: menuLink_onmouseover,
			onmouseout: menuLink_onmouseout
		};

		var getLoginLink = menuLink(bmnUri, "Get login from Bug Me Not", "Get a login from Bug Me Not", getLoginLink_onclick, menuLinkProperties, Style.menuLink);
		var getLoginLinkWrapper = menuEntry(getLoginLink, Style.menuLinkWrapper);

		var fullFormLink = menuLink(bmnUri, "More options", "See more options for getting logins from BugMeNot.com (opens a new window)", openMenuLink_onclick, menuLinkProperties, Style.menuLink);
		var fullFormLinkWrapper = menuEntry(fullFormLink, Style.menuLinkWrapper);

		var visitBmnLink = menuLink(bmnHomeUri, "Visit Bug Me Not", "Go to the Bug Me Not home page (opens a new window)", openMenuLink_onclick, menuLinkProperties, Style.menuLink);
		var visitBmnLinkWrapper = menuEntry(visitBmnLink, Style.menuLinkWrapper);

		var bmnWrapper = document.createElement("div");
		bmnWrapper.id = "reify-bugmenot-bmnWrapper" + i;
		bmnWrapper.className = "reify-bugmenot-bmnWrapper";
		bmnWrapper.appendChild(getLoginLinkWrapper);
		bmnWrapper.appendChild(fullFormLinkWrapper);
		bmnWrapper.appendChild(visitBmnLinkWrapper);
		copyProperties(bmnWrapper.style, Style.bmnWrapper);

		bmnContainer.appendChild(bmnWrapper);
	}

	if (bmnContainer.hasChildNodes())
		bodyEl.appendChild(bmnContainer);
}

function menuEntry(linkEl, styleObj)
{
	var p = document.createElement("p");
	copyProperties(p.style, styleObj);
	p.appendChild(linkEl);
	return p;
}

function menuLink(href, text, title, onclick, moreProperties, styleObj)
{
	var newMenuLink = document.createElement("a");
	newMenuLink.href = href;
	newMenuLink.appendChild(document.createTextNode(text));
	newMenuLink.title = title;
	newMenuLink.onclick = onclick;

	copyProperties(newMenuLink, moreProperties);
	copyProperties(newMenuLink.style, styleObj);

	return newMenuLink;
}

function menuLink_onmouseover()
{
	copyProperties(this.style, Style.menuLinkHover);
}

function menuLink_onmouseout()
{
	copyProperties(this.style, Style.menuLink);
}

function getLoginLink_onclick()
{
	if
	(
		(
			allInputs[this.passwordInputIndex].value.length == 0 &&
			allInputs[this.usernameInputIndex].value.length == 0
		) ||
		confirm("Overwrite the current login entry?")
	)
		getLogin(bmnUri, this.usernameInputIndex, this.passwordInputIndex);

	this.onmouseout();
	return false;
}

function openMenuLink_onclick()
{
	window.open(this.href);
	this.onmouseout();
	return false;
}


function usernameField_onfocus()
{
	var target = window.event ? window.event.srcElement : this;

	target.hasFocus = true;
	showHideBmnWrapper(target, allInputs[target.passwordInputIndex], true);
}

function usernameField_onblur()
{
	var target = window.event ? window.event.srcElement : this;

	target.hasFocus = false;
	var fRef = hideIfNoFocus(allInputs[target.usernameInputIndex], allInputs[target.passwordInputIndex]);
	setTimeout(fRef, BLUR_TIMEOUT);	// race condition: wait for other element's onfocus
}

function pwField_onfocus()
{
	var target = window.event ? window.event.srcElement : this;

	target.hasFocus = true;
	showHideBmnWrapper(allInputs[target.usernameInputIndex], target, true);
}

function pwField_onblur()
{
	var target = window.event ? window.event.srcElement : this;

	target.hasFocus = false;
	var fRef = hideIfNoFocus(allInputs[target.usernameInputIndex], allInputs[target.passwordInputIndex]);
	setTimeout(fRef, BLUR_TIMEOUT);	// race condition: wait for other element's onfocus
}

function hideIfNoFocus(usernameField, pwField)
{
	return (function()
	{
		if (!(usernameField.hasFocus || pwField.hasFocus))
			showHideBmnWrapper(usernameField, pwField, false);
	});
}

function showHideBmnWrapper(usernameField, pwField, show)
{
	var bmnWrapper = getBmnWrapper(pwField.passwordInputIndex);

	if (show)
	{
		bmnWrapper.style.display = "block";
		positionBmnWrapper(bmnWrapper, usernameField, pwField);
	}
	else
	{
		bmnWrapper.style.display = "none";

		// Menu links may not get onmouseout event, so they get
		// stuck with the hover style unless we do this.
		var menuLinks = bmnWrapper.getElementsByTagName("div");
		for (var i = 0; i < menuLinks.length; i++)
			copyProperties(menuLinks[i].style, Style.menuLink);
	}
}

function positionBmnWrapper(bmnWrapper, usernameField, pwField)
{
	var pwLeft = Utility.elementLeft(pwField);

	if (pwLeft + pwField.offsetWidth + bmnWrapper.offsetWidth + Utility.scrollLeft() + 10 < Utility.viewportWidth())
	{
		bmnWrapper.style.left = (pwLeft + pwField.offsetWidth + 2) + "px";
		bmnWrapper.style.top = Utility.elementTop(pwField) + "px";
	}
	else
	{
		bmnWrapper.style.left = (Utility.elementLeft(usernameField) - bmnWrapper.offsetWidth - 2) + "px";
		bmnWrapper.style.top = Utility.elementTop(usernameField) + "px";
	}
}

// We have a uri param rather than assuming it's for the current
// page so this function can be modular and potentially used
// for pages other than the current one.
function getLogin(uri, usernameInputIndex, passwordInputIndex)
{
	var usernameField = allInputs[usernameInputIndex];
	var pwField = allInputs[passwordInputIndex];
	waitOrRestoreFields(usernameField, pwField, false);

	var hostUri = location.hostname;
	var firstAttempt = retrievals == 0;
	var submitData = "submit=This+login+didn%27t+work&num=" + retrievals + "&site=" + encodeURI(location.hostname);

	GM_xmlhttpRequest({
		method: firstAttempt ? "get" : "post",
		headers: firstAttempt ? null : {"Content-type": "application/x-www-form-urlencoded"},
		data: firstAttempt ? null : submitData,
		url: firstAttempt ? uri : bmnView,
		onload: function(responseDetails)
		{
			waitOrRestoreFields(usernameField, pwField, true);
			var doc = textToXml(responseDetails.responseText);
			if (!(doc && doc.documentElement))
				return Errors.say(Errors.malformedResponse);

			var accountInfo = doc.documentElement.getElementsByTagName("dd")[0];
			if (!(accountInfo && accountInfo.childNodes.length > 2))
				return Errors.say(Errors.noLoginAvailable);

			usernameField.value = accountInfo.childNodes[0].nodeValue;
			pwField.value = accountInfo.childNodes[2].nodeValue;
			retrievals++;
		},
		onerror: function(responseDetails)
		{
			waitOrRestoreFields(usernameField, pwField, true);
			Errors.say(Errors.xmlHttpFailure);
		}
	});
}

function waitOrRestoreFields(usernameField, pwField, restore)
{
	document.documentElement.style.cursor = restore ? "default" : "progress";
	usernameField.value = restore ? "" : "Loading...";
	usernameField.disabled = !restore;
	pwField.disabled = !restore;
}

function getPreviousTextField(pwFieldIndex)
{
	for (var i = pwFieldIndex; i >= 0 && i < allInputs.length; i--)
		if (allInputs[i].type && allInputs[i].type.toLowerCase() == "text")
			return i;

	return -1;
}

function textToXml(t)
{
	try
	{
		if (window.ActiveXObject)
		{
			var dp = new ActiveXObject("Microsoft.XMLDOM");
			dp.async = false;
			dp.loadXML(t);
			return dp;
		}
		else if (typeof DOMParser != undefined)
		{
			var dp = new DOMParser();
			return dp.parseFromString(t, "text/xml");
		}
		else
		{
			return null;
		}
	}
	catch (e)
	{
		return null;
	}
}

var Errors =
{
	noLoginAvailable: "Sorry, but BugMeNot.com had no login available for this site.\nIf you're feeling helpful, you can click \"More options\" to provide a login for future visitors.",
	malformedResponse: "Sorry, but I couldn't understand the response from BugMeNot.com.\nThe service might be unavailable.",
	xmlHttpFailure: "There was an error in contacting BugMeNot.com.\nThe server may be unavailable or having internal errors.",

	say: function(msg) { alert(msg); return false; }
};


var Utility =
{
	elementTop: function(el) { return Utility.recursiveOffset(el, "offsetTop"); },
	elementLeft: function(el) { return Utility.recursiveOffset(el, "offsetLeft"); },

	recursiveOffset: function(el, prop)
	{
		var dist = 0;
		while (el.offsetParent)
		{
			dist += el[prop];
			el = el.offsetParent;
		}
		return dist;
	},

	viewportWidth: function() { return Utility.detectAndUseAppropriateObj("clientWidth"); },
	viewportHeight: function() { return Utility.detectAndUseAppropriateObj("clientHeight"); },
	scrollLeft: function() { return Utility.detectAndUseAppropriateObj("scrollLeft"); },
	scrollTop: function() { return Utility.detectAndUseAppropriateObj("scrollTop"); },

	// Thanks to PPK of Quirksmode for this detection scheme.
	detectAndUseAppropriateObj: function(prop)
	{
		if (document.documentElement && document.documentElement[prop])
			return document.documentElement[prop];
		else if (document.body && document.body[prop])
			return document.body[prop];
		else
			return -1;
	},

	addEventHandler: function(target, eventName, eventHandler)
	{
		if (target.addEventListener)
			target.addEventListener(eventName, eventHandler, false);
		else if (target.attachEvent)
			target.attachEvent("on" + eventName, eventHandler);
	}
};


main();