Skip to content

Instantly share code, notes, and snippets.

@bellbind
Created January 13, 2011 12:54
Show Gist options
  • Save bellbind/777814 to your computer and use it in GitHub Desktop.
Save bellbind/777814 to your computer and use it in GitHub Desktop.
[firefox][userChrome][firefox4] referer control for userChrome.js
// ==UserScript==
// @name refcontrol.uc.js
// @include main
// @description Control referer sending by refControl addon settings
// @version 0.3
// @author bellbind
// @license MPL 1.1/GPL 2.0/LGPL 2.1
// @homepage https://gist.github.com/777814
// ==/UserScript==
/* Usage
* - Install userchromejs addon and this script into firefox 3.x or 4.x
* - Set "refcontrol.actions" value by "about:config"
*
* Example value of refcontrol.actions
* "@DEFAULT=@FORGE image.itmedia.co.jp=http://www.itmedia.co.jp/"
*/
(function(){
//{key: [action, only3rd]}: derived from "refcontrol.actions"
// for spec, see: http://www.stardrifter.org/refcontrol/
//[refcontrol key]
// hostname:
// @DEFAULT: any not specified
//[refControl action]
// @NORMAL : not modified
// @FORGE : set referer as the uri host
// (empty text): block referer
// any uri : set referer as the uri
// @3RDPARTY:anyaction : the action applied only 3rd party request
//[extended action]
// @BLOCK : block referer (same as empty)
// @FORCE : force send origin
// @SELF : referer as same uri
var defaultConf = {
"@DEFAULT": ["@FORGE", false]
};
var OPTION_KEY = "refcontrol.actions";
var RE_3RDPARTY = /^@3RDPARTY:/;
var cc = Components.classes;
var ci = Components.interfaces;
var cPref = cc["@mozilla.org/preferences-service;1"];
var pref = cPref.getService(ci.nsIPrefBranch2);
var cObservable = cc["@mozilla.org/observer-service;1"];
var observable = cObservable.getService(ci.nsIObserverService);
var newObserver = function (handler) {
// see: https://developer.mozilla.org/en/nsIObserver
return {"observe": handler};
};
var conf = {};
var readOptions = function (conf) {
// see: https://developer.mozilla.org/en/nsIPrefBranch2
var actionDefs = pref.getCharPref(OPTION_KEY).split(" ");
for (var i = 0; i < actionDefs.length; i += 1) {
var actionDef = actionDefs[i];
var index = actionDef.indexOf("=");
if (index > 0) {
var right = actionDef.substr(index + 1);
var only3rd = right.match(RE_3RDPARTY) ? true : false;
var action = right.replace(RE_3RDPARTY, "");
conf[actionDef.substr(0, index)] = [action, only3rd];
}
}
};
var updateConf = function () {
conf = {};
for (var key in defaultConf) conf[key] = defaultConf[key];
readOptions(conf);
};
var handlerSyncOptions = function (subject, topic, data) {
updateConf();
};
var resolveAction = function (conf, target, origin) {
var is3rd = origin.protocol != "http:" || target.host != origin.host;
var names = target.host.split(".");
var action = "@NORMAL";
for (var index = names.length; index >= 0; index -= 1) {
var key = names.slice(index).join(".") || "@DEFAULT";
var value = conf[key];
if (value !== undefined && (!value[1] || is3rd)) action = value[0];
}
return action;
};
var actionToReferer = function (action, target, origin) {
// see: https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIURI
switch (action) {
case "@NORMAL":
return undefined;
case "": case "@BLOCK":
return null;
case "@FORGE":
return target.scheme + "://" + target.hostPort + "/";
case "@FORCE":
return origin.href;
case "@SELF":
return target.spec;
}
if (action.match(/^@/)) return undefined;
return action;
}
var handlerRefControl = function(subject, topic, data) {
// see: https://developer.mozilla.org/en/nsIHttpChannel
var http = subject.QueryInterface(ci.nsIHttpChannel);
var target = http.URI;
var origin = window.content.document.location;
var action = resolveAction(conf, target, origin);
var ref = actionToReferer(action, target, origin);
if (ref !== undefined) http.setRequestHeader("Referer", ref, false);
};
var init = function () {
// see: https://developer.mozilla.org/en/nsIPrefBranch2
// see: https://developer.mozilla.org/en/nsIObserverService
// see: https://developer.mozilla.org/en/Observer_Notifications
updateConf();
pref.addObserver(OPTION_KEY, newObserver(handlerSyncOptions), false);
observable.addObserver(
newObserver(handlerRefControl), "http-on-modify-request", false);
};
init();
})();
//[changelog]
//0.3
// * Observe pref modification: e.g. edit via about:config
// * @SELF
//0.2
// * 3RDPARTY: prefix
// * Resolve suffix domain
// * Use refControl addon pref setting
// * @FORCE
//0.1
// * refControl emulation for userChrome.js script
// ==UserScript==
// @name refcontrolui.uc.js
// @include main
// @include chrome://browser/content/browser.xul
// @description Interface for refcontrol.uc.js
// @version 0.1
// @author bellbind
// @license MPL 1.1/GPL 2.0/LGPL 2.1
// @homepage https://gist.github.com/777814
// ==/UserScript==
(function () {
var OPTION_KEY = "refcontrol.actions";
var RE_3RDPARTY = /^@3RDPARTY:/;
var cc = Components.classes;
var ci = Components.interfaces;
//[configuration manage]
var cPref = cc["@mozilla.org/preferences-service;1"];
var pref = cPref.getService(ci.nsIPrefBranch2);
var newObserver = function (handler) {
// see: https://developer.mozilla.org/en/nsIObserver
return {"observe": handler};
};
var conf = {};
var readOptions = function (conf) {
// see: https://developer.mozilla.org/en/nsIPrefBranch2
var actionDefs = pref.getCharPref(OPTION_KEY).split(" ");
for (var i = 0; i < actionDefs.length; i += 1) {
var actionDef = actionDefs[i];
var index = actionDef.indexOf("=");
if (index > 0) {
var right = actionDef.substr(index + 1);
var only3rd = right.match(RE_3RDPARTY) ? true : false;
var action = right.replace(RE_3RDPARTY, "");
conf[actionDef.substr(0, index)] = [action, only3rd];
}
}
};
var writeOptions = function (conf) {
var lines = [];
for (var key in conf) {
var value = conf[key];
lines.push(key + "=" + (value[1] ? "@3RDPARTY:" : "") + value[0]);
}
pref.setCharPref(OPTION_KEY, lines.join(" "));
};
var updateConf = function () {
conf = {};
readOptions(conf);
};
var handlerSyncOptions = function (subject, topic, data) {
updateConf();
};
updateConf();
pref.addObserver(OPTION_KEY, newObserver(handlerSyncOptions), false);
//[context menus]
var menuData = [
["normal", "Normal", "@NORMAL"],
["block", "Block", ""],
["forge", "Forge", "@FORGE"],
];
var setMenuLabels = function () {
var host = window.content.location.host;
domain.setAttribute("label", "\"" + host + "\"");
var value = conf[host];
var action = value ? value[0] : -1;
var only3rd = value ? value[1] : false;
for (var i = 0; i < menuData.length; i += 1) {
var data = menuData[i];
var item = items[data[0]];
item.setAttribute("checked", action == data[2] ? "true" : "false");
}
third.setAttribute("checked", only3rd ? "true" : "false");
};
var setDefaultMenuLabels = function () {
var value = conf["@DEFAULT"];
var action = value ? value[0] : -1;
var only3rd = value ? value[1] : false;
for (var i = 0; i < menuData.length; i += 1) {
var data = menuData[i];
var item = defaultItems[data[0]];
item.setAttribute("checked", action == data[2] ? "true" : "false");
}
defaultThird.setAttribute("checked", only3rd ? "true" : "false");
};
var setActionCommand = function (item, action) {
return function () {
var host = window.content.location.host;
if (item.getAttribute("checked") == "true") {
delete conf[host];
} else {
conf[host] = [action, false];
}
writeOptions(conf);
};
};
var setDefaultActionCommand = function (item, action) {
return function () {
var host = "@DEFAULT";
if (item.getAttribute("checked") == "true") {
delete conf[host];
} else {
conf[host] = [action, false];
}
writeOptions(conf);
};
};
var setThirdCommand = function () {
var host = window.content.location.host;
var values = conf[host];
if (values !== undefined) {
var current = third.getAttribute("checked") == "true";
values[1] = !current;
writeOptions(conf);
}
};
var setDefaultThirdCommand = function () {
var host = "@DEFAULT";
var values = conf[host];
if (values !== undefined) {
var current = defaultThird.getAttribute("checked") == "true";
values[1] = !current;
writeOptions(conf);
}
};
// build UI
// see: https://developer.mozilla.org/en/XUL/menu
// see: https://developer.mozilla.org/en/XUL/menuitem
var menu = document.createElement("menu");
menu.id = "refcontrolui.menu";
menu.setAttribute("label", "Referer Control");
menu.hidden = false;
menu.className = "menu-iconic";
menu.addEventListener("popupshowing", setMenuLabels, false);
var popup = document.createElement("menupopup");
menu.appendChild(popup);
var domain = document.createElement("menuitem");
domain.id = "refcontrolui.menu.domain";
domain.className = "menuitem-non-iconic";
popup.appendChild(domain);
popup.appendChild(document.createElement("menuseparator"));
var items = {};
for (var i = 0; i < menuData.length; i += 1) {
var data = menuData[i];
var item = document.createElement("menuitem");
item.id = "refcontrolui.menu." + data[0];
item.setAttribute("label", data[1]);
item.hidden = false;
item.setAttribute("checked", "false");
item.className = "menuitem-iconic";
item.addEventListener("command", setActionCommand(item, data[2]), false);
popup.appendChild(item);
items[data[0]] = item;
}
popup.appendChild(document.createElement("menuseparator"));
var third = document.createElement("menuitem");
third.id = "refcontrolui.menu.3rd";
third.setAttribute("label", "3rd party only");
third.hidden = false;
third.setAttribute("checked", "false");
third.className = "menuitem-iconic";
third.addEventListener("command", setThirdCommand, false);
popup.appendChild(third);
popup.appendChild(document.createElement("menuseparator"));
// UI for default action edit
var defaultMenu = document.createElement("menu");
defaultMenu.id = "refcontrolui.menu.default";
defaultMenu.setAttribute("label", "All Site");
defaultMenu.hidden = false;
defaultMenu.className = "menu-non-iconic";
defaultMenu.addEventListener("popupshowing", setDefaultMenuLabels, false);
popup.appendChild(defaultMenu);
var defaultPopup = document.createElement("menupopup");
defaultMenu.appendChild(defaultPopup);
var defaultItems = {};
for (var i = 0; i < menuData.length; i += 1) {
var data = menuData[i];
var item = document.createElement("menuitem");
item.id = "refcontrolui.menu.default." + data[0];
item.setAttribute("label", data[1]);
item.hidden = false;
item.setAttribute("checked", "false");
item.className = "menuitem-iconic";
item.addEventListener(
"command", setDefaultActionCommand(item, data[2]), false);
defaultPopup.appendChild(item);
defaultItems[data[0]] = item;
}
defaultPopup.appendChild(document.createElement("menuseparator"));
var defaultThird = document.createElement("menuitem");
defaultThird.id = "refcontrolui.menu.default.3rd";
defaultThird.setAttribute("label", "3rd party only");
defaultThird.hidden = false;
defaultThird.setAttribute("checked", "false");
defaultThird.className = "menuitem-iconic";
defaultThird.addEventListener("command", setDefaultThirdCommand, false);
defaultPopup.appendChild(defaultThird);
// see: https://developer.mozilla.org/ja/XUL/PopupGuide/Extensions
var contextMenu = document.getElementById("contentAreaContextMenu");
contextMenu.appendChild(menu);
})();
//[changelog]
//0.1
// * UI as context menu
// * Edit only refControl compatible area
// <<How to use userChrome.js script>>
// [Setup]
// 1. Install firefox4
// - http://www.mozilla.com/firefox/beta/
// 2. Install userchromejs-1.2
// - http://userchromejs.mozdev.org/
// 3. Copy this file as userChrome.js into the "chrome" folder
// - (Win7)c:\Users\USERNAME\AppData\Roaming\Mozilla\Firefox\Profiles\HASH.default\chrome\
// 4. Create new "SubScript" folder in the "chrome" folder
//
// [Install Script]
// 1. Put ".uc.js" script files into "SubScript" folder
// 2. Restart firefox
userChrome.import("SubScript", "UChrm");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment