From 96966ca83f96ed1babcd2bd23aa68feb63fbb7a7 Mon Sep 17 00:00:00 2001 From: Einar Egilsson Date: Tue, 15 Sep 2009 21:41:06 +0000 Subject: Total restructuring of files. Unescape matches fully working Export of redirects working. git-svn-id: http://einaregilsson.googlecode.com/svn/mozilla/redirector/trunk@249 119bf307-c92d-0410-89bd-8f53e6181181 --- chrome/content/code/browserOverlay.xul.js | 137 ++++++++++++ chrome/content/code/editRedirect.xul.js | 86 +++++++ chrome/content/code/redirectList.xul.js | 193 ++++++++++++++++ chrome/content/code/redirector.prototype.js | 333 ++++++++++++++++++++++++++++ chrome/content/help.html | 173 --------------- chrome/content/images/redirector.png | Bin 0 -> 1462 bytes chrome/content/images/statusactive.PNG | Bin 0 -> 360 bytes chrome/content/images/statusinactive.PNG | Bin 0 -> 396 bytes chrome/content/overlay.js | 142 ------------ chrome/content/overlay.xul | 38 ---- chrome/content/redirect.js | 86 ------- chrome/content/redirect.xul | 53 ----- chrome/content/redirectList.js | 158 ------------- chrome/content/redirectList.xul | 54 ----- chrome/content/redirector.png | Bin 1462 -> 0 bytes chrome/content/redirector.prototype.js | 272 ----------------------- chrome/content/statusactive.PNG | Bin 360 -> 0 bytes chrome/content/statusinactive.PNG | Bin 396 -> 0 bytes chrome/content/ui/browserOverlay.xul | 38 ++++ chrome/content/ui/editRedirect.xul | 53 +++++ chrome/content/ui/help.html | 173 +++++++++++++++ chrome/content/ui/redirectList.xul | 54 +++++ chrome/content/unittest/run.html | 87 ++++++++ chrome/content/unittest/testcases.js | 39 ++++ chrome/content/unittests.html | 86 ------- chrome/content/unittests.js | 39 ---- 26 files changed, 1193 insertions(+), 1101 deletions(-) create mode 100644 chrome/content/code/browserOverlay.xul.js create mode 100644 chrome/content/code/editRedirect.xul.js create mode 100644 chrome/content/code/redirectList.xul.js create mode 100644 chrome/content/code/redirector.prototype.js delete mode 100644 chrome/content/help.html create mode 100644 chrome/content/images/redirector.png create mode 100644 chrome/content/images/statusactive.PNG create mode 100644 chrome/content/images/statusinactive.PNG delete mode 100644 chrome/content/overlay.js delete mode 100644 chrome/content/overlay.xul delete mode 100644 chrome/content/redirect.js delete mode 100644 chrome/content/redirect.xul delete mode 100644 chrome/content/redirectList.js delete mode 100644 chrome/content/redirectList.xul delete mode 100644 chrome/content/redirector.png delete mode 100644 chrome/content/redirector.prototype.js delete mode 100644 chrome/content/statusactive.PNG delete mode 100644 chrome/content/statusinactive.PNG create mode 100644 chrome/content/ui/browserOverlay.xul create mode 100644 chrome/content/ui/editRedirect.xul create mode 100644 chrome/content/ui/help.html create mode 100644 chrome/content/ui/redirectList.xul create mode 100644 chrome/content/unittest/run.html create mode 100644 chrome/content/unittest/testcases.js delete mode 100644 chrome/content/unittests.html delete mode 100644 chrome/content/unittests.js (limited to 'chrome/content') diff --git a/chrome/content/code/browserOverlay.xul.js b/chrome/content/code/browserOverlay.xul.js new file mode 100644 index 0000000..636c02b --- /dev/null +++ b/chrome/content/code/browserOverlay.xul.js @@ -0,0 +1,137 @@ +//// $Id$ + +var Redirector = Components.classes["@einaregilsson.com/redirector;1"].getService(Components.interfaces.nsISupports).wrappedJSObject; + +var RedirectorOverlay = { + + id : "redirector@einaregilsson.com", + name : "Redirector", + initialized : false, + strings : null, + + onLoad : function(event) { + try { + + // initialization code + Redirector.debug("Initializing..."); + document.getElementById('contentAreaContextMenu') + .addEventListener("popupshowing", function(e) { RedirectorOverlay.showContextMenu(e); }, false); + + if (!Redirector.getBoolPref('showContextMenu')) { + document.getElementById('redirector-context').hidden = true; + } + if (!Redirector.getBoolPref('showStatusBarIcon')) { + document.getElementById('redirector-status').hidden = true; + } + this.strings = document.getElementById("redirector-strings"); + this.prefObserver.register(); + this.setStatusBarImg(); + + Redirector.debug("Finished initialization"); + this.initialized = true; + + } catch(e) { + if (this.strings) { + alert(this.strings.getFormattedString("initError", [this.name]) + "\n\n" + e); + } else { + alert(e); + } + } + }, + + onUnload : function(event) { + RedirectorOverlay.prefObserver.unregister(); + Redirector.debug("Finished cleanup"); + }, + + showContextMenu : function(event) { + if (gContextMenu.onLink) { + document.getElementById("redirector-context").label = this.strings.getString('addLinkUrl'); + } else { + document.getElementById("redirector-context").label = this.strings.getString('addCurrentUrl'); + } + }, + + onContextMenuCommand: function(event) { + + var item = { exampleUrl : window.content.location.href, pattern: window.content.location.href}; + if (gContextMenu.onLink) { + item.redirectUrl = gContextMenu.link.toString(); + } + + window.openDialog("chrome://redirector/content/ui/editRedirect.xul", + "redirect", + "chrome,dialog,modal,centerscreen", item); + + if (item.saved) { + Redirector.addRedirect(item); + } + }, + + onMenuItemCommand: function(event) { + this.openSettings(); + }, + + toggleEnabled : function(event) { + Redirector.setEnabled(!Redirector.enabled); + }, + + openSettings : function() { + var windowName = "redirectorSettings"; + var windowsMediator = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator); + var win = windowsMediator.getMostRecentWindow(windowName); + if (win) { + win.focus(); + } else { + window.openDialog("chrome://redirector/content/ui/redirectList.xul", + windowName, + "chrome,dialog,resizable=no,centerscreen", this); + } + + }, + + statusBarClick : function(event) { + var LEFT = 0, RIGHT = 2; + + if (event.button == LEFT) { + RedirectorOverlay.toggleEnabled(); + } else if (event.button == RIGHT) { + this.openSettings(); + } + }, + + setStatusBarImg : function() { + var statusImg = document.getElementById('redirector-statusbar-img'); + + if (Redirector.enabled) { + statusImg.src = 'chrome://redirector/content/images/statusactive.PNG' + statusImg.setAttribute('tooltiptext', this.strings.getString('enabledTooltip')); + } else { + statusImg.src = 'chrome://redirector/content/images/statusinactive.PNG' + statusImg.setAttribute('tooltiptext', this.strings.getString('disabledTooltip')); + } + }, + + prefObserver : { + + getService : function() { + return Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranchInternal); + }, + + register: function() { + this.getService().addObserver('extensions.redirector', this, false); + }, + + unregister: function() { + this.getService().removeObserver('extensions.redirector', this); + }, + + observe : function(subject, topic, data) { + if (topic == 'nsPref:changed' && data == 'extensions.redirector.enabled') { + RedirectorOverlay.setStatusBarImg(); + } + } + } +}; +window.addEventListener("load", function(event) { RedirectorOverlay.onLoad(event); }, false); +window.addEventListener("unload", function(event) { RedirectorOverlay.onUnload(event); }, false); diff --git a/chrome/content/code/editRedirect.xul.js b/chrome/content/code/editRedirect.xul.js new file mode 100644 index 0000000..6e981d2 --- /dev/null +++ b/chrome/content/code/editRedirect.xul.js @@ -0,0 +1,86 @@ +//// $Id$ + +const kRedirectorWildcard = 'W'; +const kRedirectorRegex= 'R'; +var Redirector = Components.classes["@einaregilsson.com/redirector;1"].getService(Components.interfaces.nsISupports).wrappedJSObject; + +function $(id) { + return document.getElementById(id); +} + +var EditRedirect = { + + onLoad : function() { + var item = window.arguments[0]; + item.saved = false; + $('txtExampleUrl').value = item.exampleUrl; + $('txtPattern').value = item.pattern; + $('txtRedirectUrl').value = item.redirectUrl || ''; + $('txtExcludePattern').value = item.excludePattern || ''; + $('chkUnescapeMatches').setAttribute('checked', !!item.unescapeMatches); + + $('txtPattern').focus(); + this.strings = document.getElementById("redirector-strings"); + + if (item.patternType == kRedirectorRegex) { + $('rdoRegex').setAttribute('selected', true); + $('rdoWildcard').setAttribute('selected', false); + } + }, + + onAccept : function() { + var item = window.arguments[0]; + + item.pattern = $('txtPattern').value; + if ($('rdoRegex').selected) { + item.patternType = kRedirectorRegex; + } else { + item.patternType = kRedirectorWildcard; + } + item.exampleUrl = $('txtExampleUrl').value; + item.redirectUrl = $('txtRedirectUrl').value; + item.excludePattern = $('txtExcludePattern').value; + item.unescapeMatches = $('chkUnescapeMatches').hasAttribute('checked') && $('chkUnescapeMatches').getAttribute('checked'); + item.saved = true; + + return true; + }, + + msgBox : function(title, text) { + Components.classes["@mozilla.org/embedcomp/prompt-service;1"] + .getService(Components.interfaces.nsIPromptService) + .alert(window, title, text); + }, + + testPattern : function() { + var redirectUrl, pattern, excludePattern, example, extName, isExcluded, unescapeMatches; + redirectUrl = $('txtRedirectUrl').value; + pattern = $('txtPattern').value; + excludePattern = $('txtExcludePattern').value; + example = $('txtExampleUrl').value; + unescapeMatches = $('chkUnescapeMatches').checked; + + extName = this.strings.getString('extensionName'); + + if ($('rdoRegex').selected) { + redirectUrl = Redirector.regexMatch(pattern, example, redirectUrl, unescapeMatches); + if (excludePattern) { + isExcluded = Redirector.regexMatch(excludePattern, example, 'exclude'); + } + } else { + redirectUrl = Redirector.wildcardMatch(pattern, example, redirectUrl, unescapeMatches); + if (excludePattern) { + isExcluded = Redirector.wildcardMatch(excludePattern, example, 'exclude'); + } + } + + var isRedirectMatch = redirectUrl || (redirectUrl === '' && $('txtRedirectUrl').value === ''); + if (isRedirectMatch && !isExcluded) { + this.msgBox(extName, this.strings.getFormattedString('testPatternSuccess', [pattern, example, redirectUrl])); + } else if (isExcluded) { + this.msgBox(extName, this.strings.getFormattedString('testPatternExclude', [example, excludePattern])); + } else { + this.msgBox(extName, this.strings.getFormattedString('testPatternFailure', [pattern, example])); + } + } +}; \ No newline at end of file diff --git a/chrome/content/code/redirectList.xul.js b/chrome/content/code/redirectList.xul.js new file mode 100644 index 0000000..65957b4 --- /dev/null +++ b/chrome/content/code/redirectList.xul.js @@ -0,0 +1,193 @@ +//// $Id$ + +var Redirector = Components.classes["@einaregilsson.com/redirector;1"].getService(Components.interfaces.nsISupports).wrappedJSObject; +const Cc = Components.classes; +const Ci = Components.interfaces; + +function $(id) { + return document.getElementById(id); +} + +var RedirectList = { + + id : "redirector@einaregilsson.com", + name : "Redirector", + lstRedirects: null, + btnDelete : null, + btnEdit : null, + + addItemsToListBox : function(items) { + + var list = $('lstRedirects'); + var item, row, value, newItem; + + for each (item in items) { + newItem = this.template.cloneNode(true); + + newItem.getElementsByAttribute('name', 'dscrIncludePattern')[0].setAttribute('value', item.pattern); + newItem.getElementsByAttribute('name', 'dscrExcludePattern')[0].setAttribute('value', item.excludePattern); + newItem.getElementsByAttribute('name', 'dscrRedirectTo')[0].setAttribute('value', item.redirectUrl); + newItem.item = item; + list.appendChild(newItem); + newItem.setAttribute("selected", false); + } + + }, + + onLoad : function() { + try { + this.lstRedirects = $('lstRedirects'); + this.lstRedirects.selType = 'single'; + this.template = document.getElementsByTagName('richlistitem')[0]; + this.lstRedirects.removeChild(this.template); + this.btnDelete = $('btnDelete'); + this.btnEdit = $('btnEdit'); + this.addItemsToListBox(Redirector.list); + } catch(e) { + alert(e); + } + }, + + openHelp : function() { + var windowName = "redirectorHelp"; + var windowsMediator = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator); + var win; + var iter = windowsMediator.getEnumerator(null); + while (iter.hasMoreElements()) { + win = iter.getNext(); + if (win.name == windowName) { + win.focus(); + return; + } + } + window.openDialog("chrome://redirector/content/ui/help.html", windowName, "chrome,dialog,resizable=yes,location=0,toolbar=0,status=0,width=800px,height=600px,centerscreen", this); + }, + + close : function() { + window.close(); + }, + + moveUp : function(){ + if (this.lstRedirects.selectedIndex <= 0) { + return; + } + this.switchItems(this.lstRedirects.selectedIndex-1); + }, + + moveDown : function() { + if (this.lstRedirects.selectedIndex == Redirector.list.length-1) { + return; + } + this.switchItems(this.lstRedirects.selectedIndex); + }, + + switchItems : function(firstIndex) { + var first = Redirector.list[firstIndex]; + var second = Redirector.list[firstIndex+1]; + Redirector.list[firstIndex] = second; + Redirector.list[firstIndex+1] = first; + this.setListItemValues(this.lstRedirects.children[firstIndex+1], first); + this.setListItemValues(this.lstRedirects.children[firstIndex], second); + this.lstRedirects.selectedIndex -= 1; + Redirector.save(); + }, + + setListItemValues : function(listItem, item){ + listItem.getElementsByAttribute('name', 'dscrIncludePattern')[0].setAttribute('value', item.pattern); + listItem.getElementsByAttribute('name', 'dscrExcludePattern')[0].setAttribute('value', item.excludePattern); + listItem.getElementsByAttribute('name', 'dscrRedirectTo')[0].setAttribute('value', item.redirectUrl); + }, + + addRedirect : function() { + + var item = { pattern : '', exampleUrl : '', redirectUrl : '', patternType : 'W', unescapeMatches : false}; + + window.openDialog("chrome://redirector/content/ui/editRedirect.xul", + "redirect", + "chrome,dialog,modal,centerscreen", item); + + if (item.saved) { + this.addItemsToListBox([item]); + Redirector.addRedirect(item); + } + + }, + + editRedirect : function() { + + var listItem = this.lstRedirects.selectedItem; + + if (!listItem) { + return; + } + + var item = listItem.item; + + window.openDialog("chrome://redirector/content/ui/editRedirect.xul", + "redirect", + "chrome,dialog,modal,centerscreen", item); + + if (item.saved) { + this.setListItemValues(listItem, item); + Redirector.save(); + } + }, + + deleteRedirect : function() { + var index = this.lstRedirects.selectedIndex; + + if (index == -1) { + return; + } + + try { + this.lstRedirects.removeChild(this.lstRedirects.children[index]); + Redirector.deleteAt(index); + } catch(e) { + alert(e); + } + }, + + selectionChange : function() { + var index = $('lstRedirects').selectedIndex; + + $('btnEdit').disabled = (index == -1); + $('btnDelete').disabled = (index == -1); + }, + + importExport : function(mode, captionKey, func) { + //Mostly borrowed from Adblock Plus + var picker = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker); + picker.init(window, Redirector.getString(captionKey), mode); + picker.defaultExtension = ".rdx"; + var dir = Redirector.getDefaultDir(); + if (dir) { + picker.displayDirectory = dir; + } + picker.appendFilter(Redirector.getString('redirectorFiles'), '*.rdx'); + + if (picker.show() != picker.returnCancel) + { + try + { + func(picker.file); + } + catch (e) + { + alert(e); + } + } + }, + + export : function() { + this.importExport(Ci.nsIFilePicker.modeSave, 'exportCaption', function(file) { + Redirector.exportRedirects(file); + }); + }, + + import : function() { + this.importExport(Ci.nsIFilePicker.modeOpen, 'importCaption', function(file) { + Redirector.importRedirects(file); + }); + } +}; diff --git a/chrome/content/code/redirector.prototype.js b/chrome/content/code/redirector.prototype.js new file mode 100644 index 0000000..24a41ba --- /dev/null +++ b/chrome/content/code/redirector.prototype.js @@ -0,0 +1,333 @@ +//// $Id$ + +Cc = Components.classes; +Ci = Components.interfaces; +Cr = Components.results; +kRedirectorWildcard = 'W'; +kRedirectorRegex= 'R'; +nsIContentPolicy = Ci.nsIContentPolicy; + + +Redirector.prototype = { + prefBranch : null, + list : null, + strings : null, + cout : Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService), + + init : function() { + this.prefBranch = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService).getBranch("extensions.redirector."); + + //Check if we need to update existing redirects + + var data = this.prefBranch.getCharPref('redirects'); + var version = this.prefBranch.getCharPref('version'); + this.debugEnabled = this.prefBranch.getBoolPref('debug'); + this.enabled = this.prefBranch.getBoolPref('enabled'); + this.loadStrings(); + //Here update checks are handled + if (version == 'undefined') { //Either a fresh install of Redirector, or first time install of v2.0 + if (data) { //There is some data in redirects, we are upgrading from a previous version, need to upgrade data + var tempList = eval(data); + var arr; + var newArr = [] + for each (arr in tempList) { + if (arr.length == 5) { + arr.push(''); //For those that don't have an exclude pattern. Backwards compatibility is a bitch! + } + arr.splice(3,1); //Remove the "only if link exists" data + newArr.push(arr.join(',,,')); + } + this.prefBranch.setCharPref('redirects', newArr.join(':::')); + } + this.prefBranch.setCharPref('version', '2.0'); + } + //Update finished + + //Now get from the new format + data = this.prefBranch.getCharPref('redirects'); + var arr; + this.list = []; + if (data != '') { + for each (redirectString in data.split(':::')) { + arr = redirectString.split(',,,'); + this.list.push({ + exampleUrl : arr[0], + pattern : arr[1], + redirectUrl : arr[2], + patternType : arr[3], + excludePattern : arr[4], + unescapeMatches : arr[5] == 'true' //This might be undefined for those upgrading from 1.7.1 but that's ok + }); + } + } + + }, + + getDefaultDir : function() { + return this.prefBranch.getCharPref('defaultDir'); + }, + + setDefaultDir : function(dir) { + this.prefBranch.setCharPref('defaultDir', dir.spec); + }, + + loadStrings : function() { + var src = 'chrome://redirector/locale/redirector.properties'; + var localeService = Cc["@mozilla.org/intl/nslocaleservice;1"].getService(Ci.nsILocaleService); + var appLocale = localeService.getApplicationLocale(); + var stringBundleService = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService); + this.strings = stringBundleService.createBundle(src, appLocale); + }, + + debug : function(msg) { + if (this.debugEnabled) { + this.cout.logStringMessage('REDIRECTOR: ' + msg); + } + }, + + // nsIContentPolicy interface implementation + shouldLoad: function(contentType, contentLocation, requestOrigin, aContext, mimeTypeGuess, extra) { + if (!this.enabled) { + return nsIContentPolicy.ACCEPT; + } + if (contentLocation.scheme != "http" && contentLocation.scheme != "https") { + return nsIContentPolicy.ACCEPT; + } + + if (contentType != nsIContentPolicy.TYPE_DOCUMENT) { + return nsIContentPolicy.ACCEPT; + } + + if (!aContext || !aContext.loadURI) { + return nsIContentPolicy.ACCEPT; + } + this.debug("CHECK: " + contentLocation.spec); + + var url = contentLocation.spec; + + for each (var redirect in this.list) { + var redirectUrl = this.getRedirectUrl(url, redirect); + if (redirectUrl) { + redirectUrl = this.makeAbsoluteUrl(url, redirectUrl); + this.debug('Redirecting ' + url + ' to ' + redirectUrl); + aContext.loadURI(redirectUrl, requestOrigin, null); + return nsIContentPolicy.REJECT_REQUEST; + } + } + return nsIContentPolicy.ACCEPT; + }, + + // nsIContentPolicy interface implementation + shouldProcess: function(contentType, contentLocation, requestOrigin, insecNode, mimeType, extra) { + return nsIContentPolicy.ACCEPT; + }, + + setEnabled : function(val) { + this.enabled = val; + this.prefBranch.setBoolPref('enabled', val); + }, + + reload : function() { + Cc["@mozilla.org/moz/jssubscript-loader;1"] + .getService(Ci.mozIJSSubScriptLoader) + .loadSubScript('chrome://redirector/content/code/redirector.prototype.js'); + + for (var key in Redirector.prototype) { + this[key] = Redirector.prototype[key]; + } + this.init(); + }, + + addRedirect : function(redirect) { + this.list.push(redirect); + this.save(); + }, + + deleteAt : function(index) { + this.list.splice(index, 1); + this.save(); + }, + + save : function() { + this.prefBranch.setCharPref('redirects', this.redirectsAsStrings().join(':::')); + }, + + redirectsAsStrings : function() { + var r + , tempList = []; + + for each (r in this.list) { + this.debug(r.unescapeMatches); + tempList.push([r.exampleUrl, r.pattern, r.redirectUrl, r.patternType, r.excludePattern, r.unescapeMatches].join(',,,')); + } + return tempList; + }, + + getBoolPref : function(name) { + return this.prefBranch.getBoolPref(name); + }, + + regexMatch : function(pattern, text, redirectUrl, unescapeMatches) { + + if (!pattern) { + return null; + } + var strings, rx, match; + try { + rx = new RegExp(pattern, 'gi'); + match = rx.exec(text); + } catch(e) { + this.msgBox(this.strings.GetStringFromName('extensionName'), this.strings.formatStringFromName('regexPatternError', [pattern, e.toString()],2)); + return null; + } + + var rxrepl; + + if (match) { + for (var i = 1; i < match.length; i++) { + rxrepl = new RegExp('\\$' + i, 'gi'); + redirectUrl = redirectUrl.replace(rxrepl, unescapeMatches ? unescape(match[i]) : match[i]); + } + return redirectUrl; + } + + return null; + + }, + + exportRedirects : function(file) { + var fileStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream); + const PR_WRONLY = 0x02; + const PR_CREATE_FILE = 0x08; + const PR_TRUNCATE = 0x20; + + fileStream.init(file, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0644, 0); + //file.parent.QueryInterface(Ci.nsILocalFile) + var stream = Cc["@mozilla.org/intl/converter-output-stream;1"].createInstance(Ci.nsIConverterOutputStream); + stream.init(fileStream, "UTF-8", 16384, Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER); + stream.writeString(this.redirectsAsStrings().join('\n')); + stream.close(); + }, + + importRedirects : function(file) { + var fileStream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream); + fileStream.init(file, 0x01, 0444, 0); //TODO: Find the actual constants for these magic numbers + + var stream = Cc["@mozilla.org/intl/converter-input-stream;1"].createInstance(Ci.nsIConverterInputStream); + stream.init(fileStream, "UTF-8", 16384, Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER); + stream = stream.QueryInterface(Ci.nsIUnicharLineInputStream); + + var importCount = 0, existsCount = 0; + var lines = []; + var line = {value: null}; + while (stream.readLine(line)) { + var parts = line.replace('\n', '').split(',,,'); + if (parts.length < 6) { + var redirect = { + exampleUrl : parts[0], + pattern : parts[1], + redirectUrl : parts[2], + patternType : parts[3], + excludePattern : parts[4], + unescapeMatches : parts[5] == 'true' ? true : false + }; + + + } + } + stream.close(); + this.save(); + }, + + getString : function(name) { + return this.strings.GetStringFromName(name); + }, + + msgBox : function(title, text) { + Cc["@mozilla.org/embedcomp/prompt-service;1"] + .getService(Ci.nsIPromptService) + .alert(null, title, text); + }, + + getRedirectUrl: function(url, redirect) { + + if (redirect.patternType == kRedirectorWildcard) { + if (this.wildcardMatch(redirect.excludePattern, url, 'whatever')) { + this.debug(url + ' matches exclude pattern ' + redirect.excludePattern); + return null; + } + return this.wildcardMatch(redirect.pattern, url, redirect.redirectUrl, redirect.unescapeMatches); + } else if (redirect.patternType == kRedirectorRegex) { + if (this.regexMatch(redirect.excludePattern, url, 'whatever')) { + this.debug(url + ' matches exclude pattern ' + redirect.excludePattern); + return null; + } + return this.regexMatch(redirect.pattern, url, redirect.redirectUrl, redirect.unescapeMatches); + } + return null; + }, + + makeAbsoluteUrl : function(currentUrl, relativeUrl) { + + if (relativeUrl.match(/https?:/)) { + return relativeUrl; + } + + var ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); + //this.debug(currentUrl); + var uri = ioService.newURI(currentUrl, null, null); + + return uri.resolve(relativeUrl); + }, + + wildcardMatch : function(pattern, text, redirectUrl, unescapeMatches) { + + if (!pattern || !text) { + return null; + } + if (pattern.indexOf('*') == -1) { + return (pattern == text) ? redirectUrl : null; + } + + var parts = pattern.split('*'); + var first = parts[0], + last = parts[parts.length-1]; + + if (first) { + if (text.substr(0, first.length) != first) { + return null; + } + text = text.substr(first.length); + } + + if (last) { + if (text.substr(text.length-last.length) != last) { + return null; + } + text = text.substr(0, text.length-last.length); + } + + if ((first || last) && parts.length == 2) { + return redirectUrl.replace('$1', text); + } + parts.splice(0,1); + parts.splice(parts.length-1,1); + var pos = 0, lastPos = 0; + var matches = []; + for each(part in parts) { + pos = text.indexOf(part, lastPos); + if (pos == -1) { + return null; + } + var match = text.substr(lastPos, pos-lastPos); + matches.push(match); + lastPos = pos + part.length; + } + matches.push(text.substr(lastPos)); + for (var i = 1; i <= matches.length; i++) { + redirectUrl = redirectUrl.replace(new RegExp('\\$' + i, 'gi'), unescapeMatches ? unescape(matches[i-1]) : matches[i-1]); + } + + return redirectUrl; + } +}; diff --git a/chrome/content/help.html b/chrome/content/help.html deleted file mode 100644 index 0ce6769..0000000 --- a/chrome/content/help.html +++ /dev/null @@ -1,173 +0,0 @@ -<!-- $Id$ --> -<html> - <head> - <title>Redirector Help</title> - <style type="text/css"> - body { font-family: Verdana, Arial; color:black; background-color:white; font-size:0.9em;} - a { color:blue; } - </style> - </head> - <body> - <h1>Redirector Help</h1> - <h3>Table of contents</h3> - <ul> - <li><a href="#whatisredirector">What is Redirector?</a></li> - <li><a href="#basicusage">Basic usage</a> - <ul> - <li><a href="#exampleurl">Example url</a></li> - <li><a href="#includepattern">Include pattern</a></li> - <li><a href="#excludepattern">Exclude pattern</a></li> - <li><a href="#redirectto">Redirect to</a></li> - <li><a href="#patterntype">Pattern type</a></li> - </ul> - </li> - <li><a href="#wildcards">Wildcards</a></li> - <li><a href="#regularexpressions">Regular expressions</a></li> - <li><a href="#examples">Examples</a> - <ol> - <li><a href="#ex1">Static redirect</a></li> - <li><a href="#ex2">Redirect using query string parameter and wildcards</a></li> - <li><a href="#ex3">Redirect using query string parameter and regular expressions</a></li> - <li><a href="#ex4">Redirect to a different folder using wildcards</a></li> - <li><a href="#ex5">Redirect http to https using wildcards</a></li> - </ol> - - </li> - </ul> - - - <a name="whatisredirector"></a> - <h4>What is Redirector?</h4> - - <p>Redirector is an extension for Firefox that allows you to automatically redirect from - one webpage to another. For example, every time you visit http://abc.com you will automatically - load http://def.com instead. This can be useful for instance to always redirect articles to printer friendly - versions, redirect http:// to https:// for sites that support both, bypass advertising pages that appear before - being able to view certain pages and more.</p> - - <a name="basicusage"></a> - <h4>Basic usage</h4> - <p>To add a new redirect you can go to the <em>Tools</em> menuitem and select <em>Redirector</em>. That will - open the <em>Redirector settings</em> window which shows all your redirects. The window can also be opened - by right clicking on the <strong>R</strong> icon in your statusbar. - There you can press the <em>Add...</em> button and then you can enter the details for the new redirect. A redirect - consists of a few things: - <ul> - <li><a name="exampleurl"></a><strong>Example url:</strong> This is an example of an url you want to redirect. It is not really used for anything, - it's just there to show what types of urls you're targetting. You can leave this out, but then you can't use the <em>Test pattern</em> button.</li> - - <li><a name="includepattern"></a><strong>Include pattern:</strong> This is pattern for the urls you want to redirect. In the simplest case, where you just want - to redirect one specific url to another then this will just be the exact url you want to redirect. For instance, if you just want http://aaa.com to - redirect to http://bbb.com then <em>Include pattern</em> will just be http://aaa.com. For more complex patterns that match many - urls you can use either <a href="#wildcards">wildcards</a> or <a href="#regularexpressions">regular expressions</a>.</li> - - <li><a name="excludepattern"></a><strong>Exclude pattern:</strong> Urls that match this pattern will never be redirected. This is not necessary to - fill out, but can be useful when you want to redirect all urls that contain some text except if they contain some other text. - Redirects like that can often be done with a complex regular expression, but using an exclude pattern makes it much simpler. The exclude - patterns can use wildcard characters or regular expressions like the include patterns.</li> - - <li><a name="redirectto"></a><strong>Redirect to:</strong> This is the url that you will be redirected to when you open any page where the url matches the - include pattern. You can use the special signs $1, $2, $3 etc. in the url, they will be replaced by the results of captures with regular - expressions or stars with wildcards. For instance, if you have the include pattern <em>http://google.com/*</em>, redirect to <em>http://froogle.com/$1</em> - and you open the page http://google.com/foobar, then you will be redireced to http://froogle.com/foobar, since 'foobar' was what the star replaced. $1 is for the - first star in the pattern, $2 for the second and so on. For regular expression $1 is for the first parantheses, $2 for the second etc.</li> - - <li><a name="patterntype"></a><strong>Pattern type:</strong> This specifies how Redirector should interpret the patterns, either as - <a href="#wildcards">wildcards</a> or <a href="#regularexpressions#">regular expressions</a>.</li> - - </ul> - </p> - - <a name="wildcards"></a> - <h4>Wildcards</h4> - - <p>Wildcards are the simplest way to specify include and exclude patterns. When you create a wildcard pattern there - is just one special character, the asterisk *. An asterisk in your pattern will match zero or more characters and you can - have more than one star in your pattern. Some examples: - <ul> - <li><em>http://example.com/*</em> matches http://example.com/, http://example.com/foo, http://example.com/bar and all other urls that start with http://example.com/.</li> - <li><em>http://*.example.com</em> matches all subdomains of example.com, like http://www.example.com, http://mail.example.com.</li> - <li><em>http*://example.com</em> matches both http://example.com and https://example.com.</li> - <li><em>http://example.com/index.asp*</em> matches http://example.com/index.asp, http://example.com/index.asp?a=b&c=d.</li> - </ul> - $1, $2, $3 in the redirect urls will match the text that the stars matched. Examples: - <ul> - <li><em>http://example.com/*</em> matches http://example.com/foobar, $1 is foobar.</li> - <li><em>http://*.example.com/*</em> matches http://www.example.com/foobar, $1 is www, $2 is foobar.</li> - </ul> - </p> - - <a name="regularexpressions"></a> - <h4>Regular expressions</h4> - - <p>Regular expressions allow for more complicated patterns but they are a lot harder to learn than wildcards. I'm not gonna - create a regex tutorial here but normal javascript regex syntax works, look at <a href="http://regular-expressions.info" target="_blank">http://regular-expressions.info</a> for - an introduction to regular expressions. $1,$2 etc. can be used in the redirect url and will be replaced with contents of captures in - the regular expressions. Captures are specified with parantheses. Example: http://example.com/index.asp\?id=(\d+) will match the url - http://example.com/index.asp?id=12345 and $1 will be replaced by 12345. (A common mistake in regex patterns is to forget to escape - the ? sign in the querystring of the url. ? is a special character in regular expressions so if you want to match an url with a querystring - you should escape it as \?).</p> - - <a name="examples"></a> - <h4>Examples</h4> - - <ol> - <li> - <strong><a name="ex1"></a>Static redirect</strong><br/> - Redirects from http://example.com/foo to http://example.com/bar - <p> - <strong>Include pattern:</strong> http://example.com/foo<br/> - <strong>Exclude pattern:</strong><br/> - <strong>Redirect to:</strong> http://example.com/bar<br/> - <strong>Pattern type:</strong> Wildcard<br /> - </p> - - </li> - <li> - <strong><a name="ex2"></a>Redirect using query string parameter and wildcards</strong><br/> - Redirects from http://example.com/index.php?id=12345&a=b to http://example.com/printerfriendly.php?id=12345&a=b - where 12345 could be any number. - <p> - <strong>Include pattern:</strong> http://example.com/index.php?id=*&a=b<br/> - <strong>Exclude pattern:</strong><br/> - <strong>Redirect to:</strong> http://example.com/printerfriendly.com?id=$1&a=b<br/> - <strong>Pattern type:</strong> Wildcard<br /> - </p> - </li> - <li> - <strong><a name="ex3"></a>Redirect using query string parameter and regular expressions</strong><br/> - Redirects from http://example.com/index.php?id=12345&a=b to http://example.com/printerfriendly.php?id=12345&a=b - where 12345 could be any number. - <p> - <strong>Include pattern:</strong> http://example.com/index.php\?id=(\d+)&a=b<br/> - <strong>Exclude pattern:</strong><br/> - <strong>Redirect to:</strong> http://example.com/printerfriendly.com?id=$1&a=b<br/> - <strong>Pattern type:</strong> Regular Expression<br /> - </p> - </li> - <li> - <strong><a name="ex4"></a>Redirect to a different folder using wildcards</strong><br/> - Redirects from http://example.com/category/fish/index.php to http://example.com/category/cats/index.php - where fish could be any word. The exclude pattern makes sure that there is only one - folder there, so for instance http://example.com/category/fish/cat/mouse/index.php would not match. - <p> - <strong>Include pattern:</strong> http://example.com/category/*/index.php<br/> - <strong>Exclude pattern:</strong> http://example.com/category/*/*/index.php<br/> - <strong>Redirect to:</strong> http://example.com/category/cats/index.php<br/> - <strong>Pattern type:</strong> Wildcard<br /> - </p> - </li> - <li> - <strong><a name="ex5"></a>Redirect http to https using wildcards</strong><br/> - Redirects from http://mail.google.com/randomcharacters to https://mail.google.com/randomcharacters - where randomcharacters could be anything. - <p> - <strong>Include pattern:</strong> http://mail.google.com*<br/> - <strong>Exclude pattern:</strong><br/> - <strong>Redirect to:</strong> https://mail.google.com$1<br/> - <strong>Pattern type:</strong> Wildcard<br /> - </p> - </li> - </ol> - </body> -</html> \ No newline at end of file diff --git a/chrome/content/images/redirector.png b/chrome/content/images/redirector.png new file mode 100644 index 0000000..f8de12c Binary files /dev/null and b/chrome/content/images/redirector.png differ diff --git a/chrome/content/images/statusactive.PNG b/chrome/content/images/statusactive.PNG new file mode 100644 index 0000000..06ce766 Binary files /dev/null and b/chrome/content/images/statusactive.PNG differ diff --git a/chrome/content/images/statusinactive.PNG b/chrome/content/images/statusinactive.PNG new file mode 100644 index 0000000..8b83562 Binary files /dev/null and b/chrome/content/images/statusinactive.PNG differ diff --git a/chrome/content/overlay.js b/chrome/content/overlay.js deleted file mode 100644 index 760f828..0000000 --- a/chrome/content/overlay.js +++ /dev/null @@ -1,142 +0,0 @@ -//// $Id$ - -var Redirector = Components.classes["@einaregilsson.com/redirector;1"].getService(Components.interfaces.nsISupports).wrappedJSObject; - -function $(id) { - return document.getElementById(id); -} - -var RedirectorOverlay = { - - id : "redirector@einaregilsson.com", - name : "Redirector", - initialized : false, - strings : null, - - onLoad : function(event) { - try { - - // initialization code - Redirector.debug("Initializing..."); - $('contentAreaContextMenu') - .addEventListener("popupshowing", function(e) { RedirectorOverlay.showContextMenu(e); }, false); - - if (!Redirector.getBoolPref('showContextMenu')) { - $('redirector-context').hidden = true; - } - if (!Redirector.getBoolPref('showStatusBarIcon')) { - $('redirector-status').hidden = true; - } - this.strings = document.getElementById("redirector-strings"); - this.prefObserver.register(); - this.setStatusBarImg(); - - Redirector.debug("Finished initialization"); - this.initialized = true; - - } catch(e) { - if (this.strings) { - alert(this.strings.getFormattedString("initError", [this.name]) + "\n\n" + e); - } else { - alert(e); - } - } - }, - - onUnload : function(event) { - RedirectorOverlay.prefObserver.unregister(); - Redirector.debug("Finished cleanup"); - }, - - showContextMenu : function(event) { - if (gContextMenu.onLink) { - $("redirector-context").label = this.strings.getString('addLinkUrl'); - } else { - $("redirector-context").label = this.strings.getString('addCurrentUrl'); - } - }, - - onContextMenuCommand: function(event) { - - var item = { exampleUrl : window.content.location.href, pattern: window.content.location.href}; - if (gContextMenu.onLink) { - item.redirectUrl = gContextMenu.link.toString(); - } - - window.openDialog("chrome://redirector/content/redirect.xul", - "redirect", - "chrome,dialog,modal,centerscreen", item); - - if (item.saved) { - Redirector.addRedirect(item); - } - }, - - onMenuItemCommand: function(event) { - this.openSettings(); - }, - - toggleEnabled : function(event) { - Redirector.setEnabled(!Redirector.enabled); - }, - - openSettings : function() { - var windowName = "redirectorSettings"; - var windowsMediator = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator); - var win = windowsMediator.getMostRecentWindow(windowName); - if (win) { - win.focus(); - } else { - window.openDialog("chrome://redirector/content/redirectList.xul", - windowName, - "chrome,dialog,resizable=no,centerscreen", this); - } - - }, - - statusBarClick : function(event) { - var LEFT = 0, RIGHT = 2; - - if (event.button == LEFT) { - RedirectorOverlay.toggleEnabled(); - } else if (event.button == RIGHT) { - this.openSettings(); - //$('redirector-status-popup').showPopup(); - } - }, - - setStatusBarImg : function() { - var statusImg = $('redirector-statusbar-img'); - - if (Redirector.enabled) { - statusImg.src = 'chrome://redirector/content/statusactive.PNG' - statusImg.setAttribute('tooltiptext', this.strings.getString('enabledTooltip')); - } else { - statusImg.src = 'chrome://redirector/content/statusinactive.PNG' - statusImg.setAttribute('tooltiptext', this.strings.getString('disabledTooltip')); - } - }, - - prefObserver : { - - getService : function() { - return Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranchInternal); - }, - - register: function() { - this.getService().addObserver('extensions.redirector', this, false); - }, - - unregister: function() { - this.getService().removeObserver('extensions.redirector', this); - }, - - observe : function(subject, topic, data) { - if (topic == 'nsPref:changed' && data == 'extensions.redirector.enabled') { - RedirectorOverlay.setStatusBarImg(); - } - } - } -}; -window.addEventListener("load", function(event) { RedirectorOverlay.onLoad(event); }, false); -window.addEventListener("unload", function(event) { RedirectorOverlay.onUnload(event); }, false); diff --git a/chrome/content/overlay.xul b/chrome/content/overlay.xul deleted file mode 100644 index 9c4619e..0000000 --- a/chrome/content/overlay.xul +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- $Id$ --> -<!DOCTYPE overlay SYSTEM "chrome://redirector/locale/redirector.dtd"> -<overlay id="redirector-overlay" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - <script src="overlay.js"/> - - <stringbundleset id="stringbundleset"> - <stringbundle id="redirector-strings" src="chrome://redirector/locale/redirector.properties"/> - </stringbundleset> - - <menupopup id="menu_ToolsPopup"> - <menuitem id="redirector-menuitem" label="&RedirectorMenuItem.label;" - accesskey="&RedirectorMenuItem.accesskey;" - oncommand="RedirectorOverlay.onMenuItemCommand(event);"/> - </menupopup> - <popup id="contentAreaContextMenu"> - <menuitem id="redirector-context" label="&RedirectorContext.label;" - accesskey="&RedirectorContext.accesskey;" - insertafter="context-stop" - oncommand="RedirectorOverlay.onContextMenuCommand(event)"/> - </popup> - <statusbar id="status-bar"> - <statusbarpanel id="redirector-status"> - <!-- Put back in later - <menupopup id="redirector-status-popup" position="at_pointer"> - <menuitem label="&RedirectorManageRedirects.label;" accesskey="&RedirectorManageRedirects.accesskey;" oncommand="RedirectorOverlay.openSettings();" /> - <menuitem label="&RedirectorHelp.label;" accesskey="&RedirectorHelp.accesskey;" oncommand="Redirector.openHelp();" /> - </menupopup> - --> - <image id="redirector-statusbar-img" src="chrome://redirector/content/statusactive.PNG" - tooltiptext="Redirector is enabled;" - style="width:16px; height:16px;" - onclick="RedirectorOverlay.statusBarClick(event);" /> - </statusbarpanel> - </statusbar> - -</overlay> \ No newline at end of file diff --git a/chrome/content/redirect.js b/chrome/content/redirect.js deleted file mode 100644 index f51e7f2..0000000 --- a/chrome/content/redirect.js +++ /dev/null @@ -1,86 +0,0 @@ -//// $Id$ - -const kRedirectorWildcard = 'W'; -const kRedirectorRegex= 'R'; -var Redirector = Components.classes["@einaregilsson.com/redirector;1"].getService(Components.interfaces.nsISupports).wrappedJSObject; - -function $(id) { - return document.getElementById(id); -} - -var Redirect = { - - onLoad : function() { - var item = window.arguments[0]; - item.saved = false; - $('txtExampleUrl').value = item.exampleUrl; - $('txtPattern').value = item.pattern; - $('txtRedirectUrl').value = item.redirectUrl || ''; - $('txtExcludePattern').value = item.excludePattern || ''; - $('chkUnescapeMatches').setAttribute('selected', !!item.unescapeMatches); - - $('txtPattern').focus(); - this.strings = document.getElementById("redirector-strings"); - - if (item.patternType == kRedirectorRegex) { - $('rdoRegex').setAttribute('selected', true); - $('rdoWildcard').setAttribute('selected', false); - } - }, - - onAccept : function() { - var item = window.arguments[0]; - - item.pattern = $('txtPattern').value; - if ($('rdoRegex').selected) { - item.patternType = kRedirectorRegex; - } else { - item.patternType = kRedirectorWildcard; - } - item.exampleUrl =$('txtExampleUrl').value; - item.redirectUrl = $('txtRedirectUrl').value; - item.excludePattern = $('txtExcludePattern').value; - item.unescapeMatches = $('chkUnescapeMatches').selected; - item.saved = true; - - return true; - }, - - msgBox : function(title, text) { - Components.classes["@mozilla.org/embedcomp/prompt-service;1"] - .getService(Components.interfaces.nsIPromptService) - .alert(window, title, text); - }, - - testPattern : function() { - var redirectUrl, pattern, excludePattern, example, extName, isExcluded, unescapeMatches; - redirectUrl = $('txtRedirectUrl').value; - pattern = $('txtPattern').value; - excludePattern = $('txtExcludePattern').value; - example = $('txtExampleUrl').value; - unescapeMatches = $('chkUnescapeMatches').checked; - - extName = this.strings.getString('extensionName'); - - if ($('rdoRegex').selected) { - redirectUrl = Redirector.regexMatch(pattern, example, redirectUrl, unescapeMatches); - if (excludePattern) { - isExcluded = Redirector.regexMatch(excludePattern, example, 'exclude'); - } - } else { - redirectUrl = Redirector.wildcardMatch(pattern, example, redirectUrl, unescapeMatches); - if (excludePattern) { - isExcluded = Redirector.wildcardMatch(excludePattern, example, 'exclude'); - } - } - - var isRedirectMatch = redirectUrl || (redirectUrl === '' && $('txtRedirectUrl').value === ''); - if (isRedirectMatch && !isExcluded) { - this.msgBox(extName, this.strings.getFormattedString('testPatternSuccess', [pattern, example, redirectUrl])); - } else if (isExcluded) { - this.msgBox(extName, this.strings.getFormattedString('testPatternExclude', [example, excludePattern])); - } else { - this.msgBox(extName, this.strings.getFormattedString('testPatternFailure', [pattern, example])); - } - } -}; \ No newline at end of file diff --git a/chrome/content/redirect.xul b/chrome/content/redirect.xul deleted file mode 100644 index d3b0907..0000000 --- a/chrome/content/redirect.xul +++ /dev/null @@ -1,53 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- $Id$ --> -<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> -<!DOCTYPE dialog SYSTEM "chrome://redirector/locale/redirect.dtd"> -<dialog title="&redirectWindow.title;" - orient="vertical" - autostretch="always" - onload="Redirect.onLoad();" - buttons="accept,cancel" - ondialogaccept="return Redirect.onAccept();" - xmlns:nc="http://home.netscape.com/NC-rdf#" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - - <script type="application/x-javascript" src="redirect.js"/> - <stringbundleset id="stringbundleset"> - <stringbundle id="redirector-strings" src="chrome://redirector/locale/redirector.properties"/> - </stringbundleset> - - <grid> - <rows> - <row align="center"> - <text value="&txtExampleUrl.label;" style="margin-top:6px;"/> - <textbox id="txtExampleUrl" style="width:400px;"/> - </row> - <row align="center"> - <text value="&txtPattern.label;" style="margin-top:6px;"/> - <textbox id="txtPattern" taborder="1"/> - <button id="btnTestPattern" label="&btnTestPattern.label;" onclick="Redirect.testPattern();" taborder="2"/> - </row> - <row align="center"> - <text value="&txtExcludePattern.label;" style="margin-top:6px;"/> - <textbox id="txtExcludePattern" taborder="3"/> - </row> - <row align="center"> - <text value="&txtRedirectUrl.label;" style="margin-top:6px;"/> - <textbox id="txtRedirectUrl" taborder="4"/> - </row> - <row align="center"> - <text value="&rdoPatternTypes.label;"/> - <radiogroup> - <hbox> - <radio id="rdoWildcard" label="&rdoWildcard.label;" accesskey="&rdoWildcard.accessKey;" selected="true" taborder="5"/> - <radio id="rdoRegex" label="&rdoRegex.label;" accesskey="&rdoRegex.accessKey;" taborder="6"/> - </hbox> - </radiogroup> - </row> - <row align="center"> - <text value="&chkUnescapeMatches.label;" /> - <checkbox id="chkUnescapeMatches" label="" taborder="7"/> - </row> - </rows> - </grid> -</dialog> diff --git a/chrome/content/redirectList.js b/chrome/content/redirectList.js deleted file mode 100644 index b3a3200..0000000 --- a/chrome/content/redirectList.js +++ /dev/null @@ -1,158 +0,0 @@ -//// $Id$ - -var Redirector = Components.classes["@einaregilsson.com/redirector;1"].getService(Components.interfaces.nsISupports).wrappedJSObject; -const Cc = Components.classes; -const Ci = Components.interfaces; - -function $(id) { - return document.getElementById(id); -} - -var RedirectList = { - - id : "redirector@einaregilsson.com", - name : "Redirector", - lstRedirects: null, - btnDelete : null, - btnEdit : null, - - addItemsToListBox : function(items) { - - var list = $('lstRedirects'); - var item, row, value, newItem; - - for each (item in items) { - newItem = this.template.cloneNode(true); - - newItem.getElementsByAttribute('name', 'dscrIncludePattern')[0].setAttribute('value', item.pattern); - newItem.getElementsByAttribute('name', 'dscrExcludePattern')[0].setAttribute('value', item.excludePattern); - newItem.getElementsByAttribute('name', 'dscrRedirectTo')[0].setAttribute('value', item.redirectUrl); - newItem.item = item; - list.appendChild(newItem); - newItem.setAttribute("selected", false); - } - - }, - - onLoad : function() { - try { - this.lstRedirects = $('lstRedirects'); - this.lstRedirects.selType = 'single'; - this.template = document.getElementsByTagName('richlistitem')[0]; - this.lstRedirects.removeChild(this.template); - this.btnDelete = $('btnDelete'); - this.btnEdit = $('btnEdit'); - this.addItemsToListBox(Redirector.list); - } catch(e) { - alert(e); - } - }, - - openHelp : function() { - var windowName = "redirectorHelp"; - var windowsMediator = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator); - var win; - var iter = windowsMediator.getEnumerator(null); - while (iter.hasMoreElements()) { - win = iter.getNext(); - if (win.name == windowName) { - win.focus(); - return; - } - } - window.openDialog("chrome://redirector/content/help.html", windowName, "chrome,dialog,resizable=yes,location=0,toolbar=0,status=0,width=800px,height=600px,centerscreen", this); - }, - - close : function() { - window.close(); - }, - - moveUp : function(){ - if (this.lstRedirects.selectedIndex <= 0) { - return; - } - this.switchItems(this.lstRedirects.selectedIndex-1); - }, - - moveDown : function() { - if (this.lstRedirects.selectedIndex == Redirector.list.length-1) { - return; - } - this.switchItems(this.lstRedirects.selectedIndex); - }, - - switchItems : function(firstIndex) { - var first = Redirector.list[firstIndex]; - var second = Redirector.list[firstIndex+1]; - Redirector.list[firstIndex] = second; - Redirector.list[firstIndex+1] = first; - this.setListItemValues(this.lstRedirects.children[firstIndex+1], first); - this.setListItemValues(this.lstRedirects.children[firstIndex], second); - this.lstRedirects.selectedIndex -= 1; - Redirector.save(); - }, - - setListItemValues : function(listItem, item){ - listItem.getElementsByAttribute('name', 'dscrIncludePattern')[0].setAttribute('value', item.pattern); - listItem.getElementsByAttribute('name', 'dscrExcludePattern')[0].setAttribute('value', item.excludePattern); - listItem.getElementsByAttribute('name', 'dscrRedirectTo')[0].setAttribute('value', item.redirectUrl); - }, - - addRedirect : function() { - - var item = { pattern : '', exampleUrl : '', redirectUrl : '', patternType : 'W'}; - - window.openDialog("chrome://redirector/content/redirect.xul", - "redirect", - "chrome,dialog,modal,centerscreen", item); - - if (item.saved) { - this.addItemsToListBox([item]); - Redirector.addRedirect(item); - } - - }, - - editRedirect : function() { - - var listItem = this.lstRedirects.selectedItem; - - if (!listItem) { - return; - } - - var item = listItem.item; - - window.openDialog("chrome://redirector/content/redirect.xul", - "redirect", - "chrome,dialog,modal,centerscreen", item); - - if (item.saved) { - this.setListItemValues(listItem, item); - Redirector.save(); - } - }, - - deleteRedirect : function() { - var index = this.lstRedirects.selectedIndex; - - if (index == -1) { - return; - } - - try { - this.lstRedirects.removeChild(this.lstRedirects.children[index]); - Redirector.deleteAt(index); - } catch(e) { - alert(e); - } - }, - - selectionChange : function() { - var index = $('lstRedirects').selectedIndex; - - $('btnEdit').disabled = (index == -1); - $('btnDelete').disabled = (index == -1); - } - -}; diff --git a/chrome/content/redirectList.xul b/chrome/content/redirectList.xul deleted file mode 100644 index 77bbf9b..0000000 --- a/chrome/content/redirectList.xul +++ /dev/null @@ -1,54 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- $Id --> -<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> -<!DOCTYPE dialog SYSTEM "chrome://redirector/locale/redirectList.dtd"> -<window title="&window.title;" - orient="vertical" - onload="RedirectList.onLoad();" - buttons="accept" - width="600px" - height="400px" - windowtype="redirectorSettings" - xmlns:nc="http://home.netscape.com/NC-rdf#" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - - <script type="application/x-javascript" src="redirectList.js"/> - - <vbox> - <richlistbox seltype="single" id="lstRedirects" style="margin-bottom:5px; border:solid 1px grey;" height="330px" ondblclick="RedirectList.editRedirect();" onselect="RedirectList.selectionChange();"> - <richlistitem style="border-bottom:dotted 1px grey;" selected="false"> - <grid> - <cols> - </cols> - <rows> - <row> - <label style="font-weight:bold;" value="&colIncludePattern.label;:" /> - <description name="dscrIncludePattern" /> - </row> - <row> - <label style="font-weight:bold;" value="&colExcludePattern.label;:" /> - <description name="dscrExcludePattern" /> - </row> - <row> - <label style="font-weight:bold;" value="&colRedirectTo.label;:" /> - <description name="dscrRedirectTo" /> - </row> - </rows> - </grid> - </richlistitem> - </richlistbox> - <hbox style="align:right;"> - <button id="btnAdd" onclick="RedirectList.addRedirect();" label="&btnAdd.label;" disabled="false" /> - <button id="btnEdit" onclick="RedirectList.editRedirect();" label="&btnEdit.label;" disabled="true" /> - <button id="btnDelete" onclick="RedirectList.deleteRedirect();" label="&btnDelete.label;" disabled="true" /> - <button id="btnClose" onclick="RedirectList.close();" label="&btnClose.label;"/> - <button id="btnHelp" onclick="RedirectList.openHelp();" label="&btnHelp.label;"/> - <button id="btnImport" onclick="RedirectList.import();" label="&btnImport.label;"/> - <button id="btnExport" onclick="RedirectList.export();" label="&btnExport.label;"/> - <!-- TODO: include in v2.0 - <button id="btnUp" onclick="RedirectList.moveUp();" label="UP" disabled="false" /> - <button id="btnDown" onclick="RedirectList.moveDown();" label="Down" /> - --> - </hbox> - </vbox> -</window> diff --git a/chrome/content/redirector.png b/chrome/content/redirector.png deleted file mode 100644 index f8de12c..0000000 Binary files a/chrome/content/redirector.png and /dev/null differ diff --git a/chrome/content/redirector.prototype.js b/chrome/content/redirector.prototype.js deleted file mode 100644 index d064764..0000000 --- a/chrome/content/redirector.prototype.js +++ /dev/null @@ -1,272 +0,0 @@ -//// $Id$ - -Cc = Components.classes; -Ci = Components.interfaces; -Cr = Components.results; -kRedirectorWildcard = 'W'; -kRedirectorRegex= 'R'; -nsIContentPolicy = Ci.nsIContentPolicy; - - -Redirector.prototype = { - prefBranch : null, - list : null, - strings : null, - cout : Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService), - - init : function() { - this.prefBranch = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService).getBranch("extensions.redirector."); - - //Check if we need to update existing redirects - - var data = this.prefBranch.getCharPref('redirects'); - var version = this.prefBranch.getCharPref('version'); - this.debugEnabled = this.prefBranch.getBoolPref('debug'); - this.enabled = this.prefBranch.getBoolPref('enabled'); - this.loadStrings(); - //Here update checks are handled - if (version == 'undefined') { //Either a fresh install of Redirector, or first time install of v2.0 - if (data) { //There is some data in redirects, we are upgrading from a previous version, need to upgrade data - var tempList = eval(data); - var arr; - var newArr = [] - for each (arr in tempList) { - if (arr.length == 5) { - arr.push(''); //For those that don't have an exclude pattern. Backwards compatibility is a bitch! - } - arr.splice(3,1); //Remove the "only if link exists" data - newArr.push(arr.join(',,,')); - } - this.prefBranch.setCharPref('redirects', newArr.join(':::')); - } - this.prefBranch.setCharPref('version', '2.0'); - } - //Update finished - - //Now get from the new format - data = this.prefBranch.getCharPref('redirects'); - var arr; - this.list = []; - if (data != '') { - for each (redirectString in data.split(':::')) { - arr = redirectString.split(',,,'); - this.list.push({ - exampleUrl : arr[0], - pattern : arr[1], - redirectUrl : arr[2], - patternType : arr[3], - excludePattern : arr[4], - unescapeMatches : !!arr[5] //This might be undefined for those upgrading from 1.7.1 but that's ok - }); - } - } - - }, - - loadStrings : function() { - var src = 'chrome://redirector/locale/redirector.properties'; - var localeService = Cc["@mozilla.org/intl/nslocaleservice;1"].getService(Ci.nsILocaleService); - var appLocale = localeService.getApplicationLocale(); - var stringBundleService = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService); - this.strings = stringBundleService.createBundle(src, appLocale); - }, - - debug : function(msg) { - if (this.debugEnabled) { - this.cout.logStringMessage('REDIRECTOR: ' + msg); - } - }, - - // nsIContentPolicy interface implementation - shouldLoad: function(contentType, contentLocation, requestOrigin, aContext, mimeTypeGuess, extra) { - if (!this.enabled) { - return nsIContentPolicy.ACCEPT; - } - if (contentLocation.scheme != "http" && contentLocation.scheme != "https") { - return nsIContentPolicy.ACCEPT; - } - - if (contentType != nsIContentPolicy.TYPE_DOCUMENT) { - return nsIContentPolicy.ACCEPT; - } - - if (!aContext || !aContext.loadURI) { - return nsIContentPolicy.ACCEPT; - } - this.debug("CHECK: " + contentLocation.spec); - - var url = contentLocation.spec; - - for each (var redirect in this.list) { - var redirectUrl = this.getRedirectUrl(url, redirect); - if (redirectUrl) { - redirectUrl = this.makeAbsoluteUrl(url, redirectUrl); - this.debug('Redirecting ' + url + ' to ' + redirectUrl); - aContext.loadURI(redirectUrl, requestOrigin, null); - return nsIContentPolicy.REJECT_REQUEST; - } - } - return nsIContentPolicy.ACCEPT; - }, - - // nsIContentPolicy interface implementation - shouldProcess: function(contentType, contentLocation, requestOrigin, insecNode, mimeType, extra) { - return nsIContentPolicy.ACCEPT; - }, - - setEnabled : function(val) { - this.enabled = val; - this.prefBranch.setBoolPref('enabled', val); - }, - - reload : function() { - Cc["@mozilla.org/moz/jssubscript-loader;1"] - .getService(Ci.mozIJSSubScriptLoader) - .loadSubScript('chrome://redirector/content/redirector.prototype.js'); - - for (var key in Redirector.prototype) { - this[key] = Redirector.prototype[key]; - } - this.init(); - }, - - addRedirect : function(redirect) { - this.list.push(redirect); - this.save(); - }, - - deleteAt : function(index) { - this.list.splice(index, 1); - this.save(); - }, - - save : function() { - var r - , tempList = []; - - for each (r in this.list) { - tempList.push([r.exampleUrl, r.pattern, r.redirectUrl, r.patternType, r.excludePattern, r.unescapeMatches].join(',,,')); - } - this.prefBranch.setCharPref('redirects', tempList.join(':::')); - }, - - getBoolPref : function(name) { - return this.prefBranch.getBoolPref(name); - }, - - regexMatch : function(pattern, text, redirectUrl, unescapeMatches) { - - if (!pattern) { - return null; - } - var strings, rx, match; - try { - rx = new RegExp(pattern, 'gi'); - match = rx.exec(text); - } catch(e) { - this.msgBox(this.strings.GetStringFromName('extensionName'), this.strings.formatStringFromName('regexPatternError', [pattern, e.toString()],2)); - return null; - } - - var rxrepl; - - if (match) { - for (var i = 1; i < match.length; i++) { - rxrepl = new RegExp('\\$' + i, 'gi'); - redirectUrl = redirectUrl.replace(rxrepl, unescapeMatches ? unescape(match[i]) : match[i]); - } - return redirectUrl; - } - - return null; - - }, - - msgBox : function(title, text) { - Cc["@mozilla.org/embedcomp/prompt-service;1"] - .getService(Ci.nsIPromptService) - .alert(null, title, text); - }, - - getRedirectUrl: function(url, redirect) { - - if (redirect.patternType == kRedirectorWildcard) { - if (this.wildcardMatch(redirect.excludePattern, url, 'whatever')) { - this.debug(url + ' matches exclude pattern ' + redirect.excludePattern); - return null; - } - return this.wildcardMatch(redirect.pattern, url, redirect.redirectUrl, redirect.unescapeMatches); - } else if (redirect.patternType == kRedirectorRegex) { - if (this.regexMatch(redirect.excludePattern, url, 'whatever')) { - this.debug(url + ' matches exclude pattern ' + redirect.excludePattern); - return null; - } - return this.regexMatch(redirect.pattern, url, redirect.redirectUrl, redirect.unescapeMatches); - } - return null; - }, - - makeAbsoluteUrl : function(currentUrl, relativeUrl) { - - if (relativeUrl.match(/https?:/)) { - return relativeUrl; - } - - var ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - //this.debug(currentUrl); - var uri = ioService.newURI(currentUrl, null, null); - - return uri.resolve(relativeUrl); - }, - - wildcardMatch : function(pattern, text, redirectUrl, unescapeMatches) { - - if (!pattern || !text) { - return null; - } - if (pattern.indexOf('*') == -1) { - return (pattern == text) ? redirectUrl : null; - } - - var parts = pattern.split('*'); - var first = parts[0], - last = parts[parts.length-1]; - - if (first) { - if (text.substr(0, first.length) != first) { - return null; - } - text = text.substr(first.length); - } - - if (last) { - if (text.substr(text.length-last.length) != last) { - return null; - } - text = text.substr(0, text.length-last.length); - } - - if ((first || last) && parts.length == 2) { - return redirectUrl.replace('$1', text); - } - parts.splice(0,1); - parts.splice(parts.length-1,1); - var pos = 0, lastPos = 0; - var matches = []; - for each(part in parts) { - pos = text.indexOf(part, lastPos); - if (pos == -1) { - return null; - } - var match = text.substr(lastPos, pos-lastPos); - matches.push(match); - lastPos = pos + part.length; - } - matches.push(text.substr(lastPos)); - for (var i = 1; i <= matches.length; i++) { - redirectUrl = redirectUrl.replace(new RegExp('\\$' + i, 'gi'), unescapeMatches ? unescape(matches[i-1]) : matches[i-1]); - } - - return redirectUrl; - } -}; diff --git a/chrome/content/statusactive.PNG b/chrome/content/statusactive.PNG deleted file mode 100644 index 06ce766..0000000 Binary files a/chrome/content/statusactive.PNG and /dev/null differ diff --git a/chrome/content/statusinactive.PNG b/chrome/content/statusinactive.PNG deleted file mode 100644 index 8b83562..0000000 Binary files a/chrome/content/statusinactive.PNG and /dev/null differ diff --git a/chrome/content/ui/browserOverlay.xul b/chrome/content/ui/browserOverlay.xul new file mode 100644 index 0000000..9a02332 --- /dev/null +++ b/chrome/content/ui/browserOverlay.xul @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- $Id$ --> +<!DOCTYPE overlay SYSTEM "chrome://redirector/locale/browserOverlay.xul.dtd"> +<overlay id="redirector-overlay" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="../code/browserOverlay.xul.js"/> + + <stringbundleset id="stringbundleset"> + <stringbundle id="redirector-strings" src="chrome://redirector/locale/redirector.properties"/> + </stringbundleset> + + <menupopup id="menu_ToolsPopup"> + <menuitem id="redirector-menuitem" label="&RedirectorMenuItem.label;" + accesskey="&RedirectorMenuItem.accesskey;" + oncommand="RedirectorOverlay.onMenuItemCommand(event);"/> + </menupopup> + <popup id="contentAreaContextMenu"> + <menuitem id="redirector-context" label="&RedirectorContext.label;" + accesskey="&RedirectorContext.accesskey;" + insertafter="context-stop" + oncommand="RedirectorOverlay.onContextMenuCommand(event)"/> + </popup> + <statusbar id="status-bar"> + <statusbarpanel id="redirector-status"> + <!-- Put back in later + <menupopup id="redirector-status-popup" position="at_pointer"> + <menuitem label="&RedirectorManageRedirects.label;" accesskey="&RedirectorManageRedirects.accesskey;" oncommand="RedirectorOverlay.openSettings();" /> + <menuitem label="&RedirectorHelp.label;" accesskey="&RedirectorHelp.accesskey;" oncommand="Redirector.openHelp();" /> + </menupopup> + --> + <image id="redirector-statusbar-img" src="chrome://redirector/content/images/statusactive.PNG" + tooltiptext="Redirector is enabled;" + style="width:16px; height:16px;" + onclick="RedirectorOverlay.statusBarClick(event);" /> + </statusbarpanel> + </statusbar> + +</overlay> \ No newline at end of file diff --git a/chrome/content/ui/editRedirect.xul b/chrome/content/ui/editRedirect.xul new file mode 100644 index 0000000..afca5b6 --- /dev/null +++ b/chrome/content/ui/editRedirect.xul @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- $Id$ --> +<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> +<!DOCTYPE dialog SYSTEM "chrome://redirector/locale/editRedirect.xul.dtd"> +<dialog title="&redirectWindow.title;" + orient="vertical" + autostretch="always" + onload="EditRedirect.onLoad();" + buttons="accept,cancel" + ondialogaccept="return EditRedirect.onAccept();" + xmlns:nc="http://home.netscape.com/NC-rdf#" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <script type="application/x-javascript" src="../code/editRedirect.xul.js"/> + <stringbundleset id="stringbundleset"> + <stringbundle id="redirector-strings" src="chrome://redirector/locale/redirector.properties"/> + </stringbundleset> + + <grid> + <rows> + <row align="center"> + <text value="&txtExampleUrl.label;" style="margin-top:6px;"/> + <textbox id="txtExampleUrl" style="width:400px;"/> + </row> + <row align="center"> + <text value="&txtPattern.label;" style="margin-top:6px;"/> + <textbox id="txtPattern" taborder="1"/> + <button id="btnTestPattern" label="&btnTestPattern.label;" onclick="EditRedirect.testPattern();" taborder="2"/> + </row> + <row align="center"> + <text value="&txtExcludePattern.label;" style="margin-top:6px;"/> + <textbox id="txtExcludePattern" taborder="3"/> + </row> + <row align="center"> + <text value="&txtRedirectUrl.label;" style="margin-top:6px;"/> + <textbox id="txtRedirectUrl" taborder="4"/> + </row> + <row align="center"> + <text value="&rdoPatternTypes.label;"/> + <radiogroup> + <hbox> + <radio id="rdoWildcard" label="&rdoWildcard.label;" accesskey="&rdoWildcard.accessKey;" selected="true" taborder="5"/> + <radio id="rdoRegex" label="&rdoRegex.label;" accesskey="&rdoRegex.accessKey;" taborder="6"/> + </hbox> + </radiogroup> + </row> + <row align="center"> + <text value="&chkUnescapeMatches.label;" /> + <checkbox id="chkUnescapeMatches" label="" taborder="7"/> + </row> + </rows> + </grid> +</dialog> diff --git a/chrome/content/ui/help.html b/chrome/content/ui/help.html new file mode 100644 index 0000000..0ce6769 --- /dev/null +++ b/chrome/content/ui/help.html @@ -0,0 +1,173 @@ +<!-- $Id$ --> +<html> + <head> + <title>Redirector Help</title> + <style type="text/css"> + body { font-family: Verdana, Arial; color:black; background-color:white; font-size:0.9em;} + a { color:blue; } + </style> + </head> + <body> + <h1>Redirector Help</h1> + <h3>Table of contents</h3> + <ul> + <li><a href="#whatisredirector">What is Redirector?</a></li> + <li><a href="#basicusage">Basic usage</a> + <ul> + <li><a href="#exampleurl">Example url</a></li> + <li><a href="#includepattern">Include pattern</a></li> + <li><a href="#excludepattern">Exclude pattern</a></li> + <li><a href="#redirectto">Redirect to</a></li> + <li><a href="#patterntype">Pattern type</a></li> + </ul> + </li> + <li><a href="#wildcards">Wildcards</a></li> + <li><a href="#regularexpressions">Regular expressions</a></li> + <li><a href="#examples">Examples</a> + <ol> + <li><a href="#ex1">Static redirect</a></li> + <li><a href="#ex2">Redirect using query string parameter and wildcards</a></li> + <li><a href="#ex3">Redirect using query string parameter and regular expressions</a></li> + <li><a href="#ex4">Redirect to a different folder using wildcards</a></li> + <li><a href="#ex5">Redirect http to https using wildcards</a></li> + </ol> + + </li> + </ul> + + + <a name="whatisredirector"></a> + <h4>What is Redirector?</h4> + + <p>Redirector is an extension for Firefox that allows you to automatically redirect from + one webpage to another. For example, every time you visit http://abc.com you will automatically + load http://def.com instead. This can be useful for instance to always redirect articles to printer friendly + versions, redirect http:// to https:// for sites that support both, bypass advertising pages that appear before + being able to view certain pages and more.</p> + + <a name="basicusage"></a> + <h4>Basic usage</h4> + <p>To add a new redirect you can go to the <em>Tools</em> menuitem and select <em>Redirector</em>. That will + open the <em>Redirector settings</em> window which shows all your redirects. The window can also be opened + by right clicking on the <strong>R</strong> icon in your statusbar. + There you can press the <em>Add...</em> button and then you can enter the details for the new redirect. A redirect + consists of a few things: + <ul> + <li><a name="exampleurl"></a><strong>Example url:</strong> This is an example of an url you want to redirect. It is not really used for anything, + it's just there to show what types of urls you're targetting. You can leave this out, but then you can't use the <em>Test pattern</em> button.</li> + + <li><a name="includepattern"></a><strong>Include pattern:</strong> This is pattern for the urls you want to redirect. In the simplest case, where you just want + to redirect one specific url to another then this will just be the exact url you want to redirect. For instance, if you just want http://aaa.com to + redirect to http://bbb.com then <em>Include pattern</em> will just be http://aaa.com. For more complex patterns that match many + urls you can use either <a href="#wildcards">wildcards</a> or <a href="#regularexpressions">regular expressions</a>.</li> + + <li><a name="excludepattern"></a><strong>Exclude pattern:</strong> Urls that match this pattern will never be redirected. This is not necessary to + fill out, but can be useful when you want to redirect all urls that contain some text except if they contain some other text. + Redirects like that can often be done with a complex regular expression, but using an exclude pattern makes it much simpler. The exclude + patterns can use wildcard characters or regular expressions like the include patterns.</li> + + <li><a name="redirectto"></a><strong>Redirect to:</strong> This is the url that you will be redirected to when you open any page where the url matches the + include pattern. You can use the special signs $1, $2, $3 etc. in the url, they will be replaced by the results of captures with regular + expressions or stars with wildcards. For instance, if you have the include pattern <em>http://google.com/*</em>, redirect to <em>http://froogle.com/$1</em> + and you open the page http://google.com/foobar, then you will be redireced to http://froogle.com/foobar, since 'foobar' was what the star replaced. $1 is for the + first star in the pattern, $2 for the second and so on. For regular expression $1 is for the first parantheses, $2 for the second etc.</li> + + <li><a name="patterntype"></a><strong>Pattern type:</strong> This specifies how Redirector should interpret the patterns, either as + <a href="#wildcards">wildcards</a> or <a href="#regularexpressions#">regular expressions</a>.</li> + + </ul> + </p> + + <a name="wildcards"></a> + <h4>Wildcards</h4> + + <p>Wildcards are the simplest way to specify include and exclude patterns. When you create a wildcard pattern there + is just one special character, the asterisk *. An asterisk in your pattern will match zero or more characters and you can + have more than one star in your pattern. Some examples: + <ul> + <li><em>http://example.com/*</em> matches http://example.com/, http://example.com/foo, http://example.com/bar and all other urls that start with http://example.com/.</li> + <li><em>http://*.example.com</em> matches all subdomains of example.com, like http://www.example.com, http://mail.example.com.</li> + <li><em>http*://example.com</em> matches both http://example.com and https://example.com.</li> + <li><em>http://example.com/index.asp*</em> matches http://example.com/index.asp, http://example.com/index.asp?a=b&c=d.</li> + </ul> + $1, $2, $3 in the redirect urls will match the text that the stars matched. Examples: + <ul> + <li><em>http://example.com/*</em> matches http://example.com/foobar, $1 is foobar.</li> + <li><em>http://*.example.com/*</em> matches http://www.example.com/foobar, $1 is www, $2 is foobar.</li> + </ul> + </p> + + <a name="regularexpressions"></a> + <h4>Regular expressions</h4> + + <p>Regular expressions allow for more complicated patterns but they are a lot harder to learn than wildcards. I'm not gonna + create a regex tutorial here but normal javascript regex syntax works, look at <a href="http://regular-expressions.info" target="_blank">http://regular-expressions.info</a> for + an introduction to regular expressions. $1,$2 etc. can be used in the redirect url and will be replaced with contents of captures in + the regular expressions. Captures are specified with parantheses. Example: http://example.com/index.asp\?id=(\d+) will match the url + http://example.com/index.asp?id=12345 and $1 will be replaced by 12345. (A common mistake in regex patterns is to forget to escape + the ? sign in the querystring of the url. ? is a special character in regular expressions so if you want to match an url with a querystring + you should escape it as \?).</p> + + <a name="examples"></a> + <h4>Examples</h4> + + <ol> + <li> + <strong><a name="ex1"></a>Static redirect</strong><br/> + Redirects from http://example.com/foo to http://example.com/bar + <p> + <strong>Include pattern:</strong> http://example.com/foo<br/> + <strong>Exclude pattern:</strong><br/> + <strong>Redirect to:</strong> http://example.com/bar<br/> + <strong>Pattern type:</strong> Wildcard<br /> + </p> + + </li> + <li> + <strong><a name="ex2"></a>Redirect using query string parameter and wildcards</strong><br/> + Redirects from http://example.com/index.php?id=12345&a=b to http://example.com/printerfriendly.php?id=12345&a=b + where 12345 could be any number. + <p> + <strong>Include pattern:</strong> http://example.com/index.php?id=*&a=b<br/> + <strong>Exclude pattern:</strong><br/> + <strong>Redirect to:</strong> http://example.com/printerfriendly.com?id=$1&a=b<br/> + <strong>Pattern type:</strong> Wildcard<br /> + </p> + </li> + <li> + <strong><a name="ex3"></a>Redirect using query string parameter and regular expressions</strong><br/> + Redirects from http://example.com/index.php?id=12345&a=b to http://example.com/printerfriendly.php?id=12345&a=b + where 12345 could be any number. + <p> + <strong>Include pattern:</strong> http://example.com/index.php\?id=(\d+)&a=b<br/> + <strong>Exclude pattern:</strong><br/> + <strong>Redirect to:</strong> http://example.com/printerfriendly.com?id=$1&a=b<br/> + <strong>Pattern type:</strong> Regular Expression<br /> + </p> + </li> + <li> + <strong><a name="ex4"></a>Redirect to a different folder using wildcards</strong><br/> + Redirects from http://example.com/category/fish/index.php to http://example.com/category/cats/index.php + where fish could be any word. The exclude pattern makes sure that there is only one + folder there, so for instance http://example.com/category/fish/cat/mouse/index.php would not match. + <p> + <strong>Include pattern:</strong> http://example.com/category/*/index.php<br/> + <strong>Exclude pattern:</strong> http://example.com/category/*/*/index.php<br/> + <strong>Redirect to:</strong> http://example.com/category/cats/index.php<br/> + <strong>Pattern type:</strong> Wildcard<br /> + </p> + </li> + <li> + <strong><a name="ex5"></a>Redirect http to https using wildcards</strong><br/> + Redirects from http://mail.google.com/randomcharacters to https://mail.google.com/randomcharacters + where randomcharacters could be anything. + <p> + <strong>Include pattern:</strong> http://mail.google.com*<br/> + <strong>Exclude pattern:</strong><br/> + <strong>Redirect to:</strong> https://mail.google.com$1<br/> + <strong>Pattern type:</strong> Wildcard<br /> + </p> + </li> + </ol> + </body> +</html> \ No newline at end of file diff --git a/chrome/content/ui/redirectList.xul b/chrome/content/ui/redirectList.xul new file mode 100644 index 0000000..29d5ceb --- /dev/null +++ b/chrome/content/ui/redirectList.xul @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- $Id --> +<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> +<!DOCTYPE dialog SYSTEM "chrome://redirector/locale/redirectList.xul.dtd"> +<window title="&window.title;" + orient="vertical" + onload="RedirectList.onLoad();" + buttons="accept" + width="600px" + height="400px" + windowtype="redirectorSettings" + xmlns:nc="http://home.netscape.com/NC-rdf#" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <script type="application/x-javascript" src="../code/redirectList.xul.js"/> + + <vbox> + <richlistbox seltype="single" id="lstRedirects" style="margin-bottom:5px; border:solid 1px grey;" height="330px" ondblclick="RedirectList.editRedirect();" onselect="RedirectList.selectionChange();"> + <richlistitem style="border-bottom:dotted 1px grey;" selected="false"> + <grid> + <cols> + </cols> + <rows> + <row> + <label style="font-weight:bold;" value="&colIncludePattern.label;:" /> + <description name="dscrIncludePattern" /> + </row> + <row> + <label style="font-weight:bold;" value="&colExcludePattern.label;:" /> + <description name="dscrExcludePattern" /> + </row> + <row> + <label style="font-weight:bold;" value="&colRedirectTo.label;:" /> + <description name="dscrRedirectTo" /> + </row> + </rows> + </grid> + </richlistitem> + </richlistbox> + <hbox style="align:right;"> + <button id="btnAdd" onclick="RedirectList.addRedirect();" label="&btnAdd.label;" disabled="false" /> + <button id="btnEdit" onclick="RedirectList.editRedirect();" label="&btnEdit.label;" disabled="true" /> + <button id="btnDelete" onclick="RedirectList.deleteRedirect();" label="&btnDelete.label;" disabled="true" /> + <button id="btnImport" onclick="RedirectList.import();" label="&btnImport.label;"/> + <button id="btnExport" onclick="RedirectList.export();" label="&btnExport.label;"/> + <button id="btnHelp" onclick="RedirectList.openHelp();" label="&btnHelp.label;"/> + <button id="btnClose" onclick="RedirectList.close();" label="&btnClose.label;"/> + <!-- TODO: include in v2.0 + <button id="btnUp" onclick="RedirectList.moveUp();" label="UP" disabled="false" /> + <button id="btnDown" onclick="RedirectList.moveDown();" label="Down" /> + --> + </hbox> + </vbox> +</window> diff --git a/chrome/content/unittest/run.html b/chrome/content/unittest/run.html new file mode 100644 index 0000000..2c4f968 --- /dev/null +++ b/chrome/content/unittest/run.html @@ -0,0 +1,87 @@ +<!-- $Id$ --> +<html> + <head> + <title>Redirector Unit Tests</title> + <style type="text/css"> + body { font-family: Verdana, Arial; color:black; background-color:white; font-size:0.8em; width:800px; margin:auto; text-align:center;} + a { color:blue; } + h1 { text-align:center; margin:10px 0px; } + table { margin:auto; border:solid 1px black; width:700px; border-collapse:collapse;} + td { border:solid 1px black; padding:3px; } + td.result { width:20px; height:20px; padding:0;} + td.result div { width:70%; height:70%; margin:auto; } + button { margin:20px auto; } + </style> + <script type="text/javascript"> + + //Global variables + var subscriptLoader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader); + var redirector = Components.classes["@einaregilsson.com/redirector;1"].getService(Components.interfaces.nsISupports).wrappedJSObject; + + function setupTest(name, testcase) { + var table = document.createElement('table'); + var row = document.createElement('tr'); + var cell = document.createElement('th'); + var testdata; + cell.setAttribute('colspan', 2); + row.appendChild(cell); + table.appendChild(row); + cell.innerHTML = name; + document.getElementsByTagName('body')[0].appendChild(table); + for (var i = 0; i < testcase.tests.length; i++) { + var testdata = testcase.tests[i]; + row = document.createElement('tr'); + cell = document.createElement('td'); + cell.setAttribute('class', 'result'); + var dot = document.createElement('div'); + dot.setAttribute('id', name + '_' + i); + cell.appendChild(dot); + + row.appendChild(cell); + cell = document.createElement('td'); + cell.innerHTML = testcase.describe(testdata); + row.appendChild(cell); + table.appendChild(row); + } + } + + function setup() { + var tables = document.getElementsByTagName('table'); + for (var i = 0; i < tables.length; i++) { + tables[i].parentNode.removeChild(tables[i]); + } + + subscriptLoader.loadSubScript('chrome://redirector/content/unittest/testcases.js'); + redirector.reload(); + + for (var name in tests) { + setupTest(name, tests[name]); + } + } + + function runTests() { + for (var testcaseName in tests) { + var testcase = tests[testcaseName]; + for (var i = 0; i < testcase.tests.length; i++) { + try { + var result = testcase.run(testcase.tests[i]); + if (result) { + document.getElementById(testcaseName + '_' + i).style.backgroundColor = '#17f816'; + } else { + document.getElementById(testcaseName + '_' + i).style.backgroundColor = '#ff0000'; + } + } catch(e) { + document.getElementById(testcaseName + '_' + i).style.backgroundColor = '#ff0000'; + } + } + } + } + + </script> + </head> + <body onload="setup();"> + <h1>Redirector Unit Tests</h1> + <button onclick="runTests();">Run tests</button> + <button onclick="setup();">Reload tests</button> + </body> +</html> \ No newline at end of file diff --git a/chrome/content/unittest/testcases.js b/chrome/content/unittest/testcases.js new file mode 100644 index 0000000..ea6e26b --- /dev/null +++ b/chrome/content/unittest/testcases.js @@ -0,0 +1,39 @@ +//// $Id$ +var tests = { + "Wildcard matches" : { + run : function(data) { + var pattern = data[0], + url = data[1], + expected = data[2]; + var parts = expected.split(','); + var redirectUrl = ''; + if (!(parts.length == 1 && parts[0] == '')) { + for (var i in parts) { + redirectUrl += '$' + (parseFloat(i)+1) + ','; + } + redirectUrl = redirectUrl.substr(0, redirectUrl.length-1); + } + var result = redirector.wildcardMatch(pattern, url, redirectUrl, false); + return result == expected; + }, + + describe : function(data) { return data[0] + ' == ' + data[1] + ', matches=' + data[2]; }, + tests : [ + ['http://foo*', 'http://foobar.is', 'bar.is'], + ['http://foo*', 'http://foo', ''], + ['*://foo.is', 'http://foo.is', 'http'], + ['*http://foo.is', 'http://foo.is', ''], + ['http*foo*', 'http://foobar.is', '://,bar.is'], + ['http*foo*', 'http://foo', '://,'], + ['*://f*.is', 'http://foo.is', 'http,oo'], + ['*http://f*.is', 'http://foo.is', ',oo'], + ['*foo*', 'http://foo', 'http://,'], + ['*foo*', 'foobar.is', ',bar.is'], + ['*foo*', 'http://foobar.is', 'http://,bar.is'], + ['http://foo.is', 'http://foo.is', ''], + ['*', 'http://foo.is', 'http://foo.is'], + ['*://*oo*bar*', 'http://foo.is/bar/baz', 'http,f,.is/,/baz'], + ['*://**oo*bar*', 'http://foo.is/bar/baz', 'http,,f,.is/,/baz'], + ] + } +}; diff --git a/chrome/content/unittests.html b/chrome/content/unittests.html deleted file mode 100644 index 0989562..0000000 --- a/chrome/content/unittests.html +++ /dev/null @@ -1,86 +0,0 @@ -<!-- $Id$ --> -<html> - <head> - <title>Redirector Unit Tests</title> - <style type="text/css"> - body { font-family: Verdana, Arial; color:black; background-color:white; font-size:0.8em; width:800px; margin:auto; text-align:center;} - a { color:blue; } - h1 { text-align:center; margin:20px 0px; } - table { margin:auto; border:solid 1px black; width:700px; border-collapse:collapse;} - td { border:solid 1px black; padding:3px; } - td.result { width:20px; height:20px; padding:0;} - td.result div { width:70%; height:70%; margin:auto; } - </style> - <script type="text/javascript"> - - //Global variables - var subscriptLoader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader); - var redirector = Components.classes["@einaregilsson.com/redirector;1"].getService(Components.interfaces.nsISupports).wrappedJSObject; - - function setupTest(name, testcase) { - var table = document.createElement('table'); - var row = document.createElement('tr'); - var cell = document.createElement('th'); - var testdata; - cell.setAttribute('colspan', 2); - row.appendChild(cell); - table.appendChild(row); - cell.innerHTML = name; - document.getElementsByTagName('body')[0].appendChild(table); - for (var i = 0; i < testcase.tests.length; i++) { - var testdata = testcase.tests[i]; - row = document.createElement('tr'); - cell = document.createElement('td'); - cell.setAttribute('class', 'result'); - var dot = document.createElement('div'); - dot.setAttribute('id', name + '_' + i); - cell.appendChild(dot); - - row.appendChild(cell); - cell = document.createElement('td'); - cell.innerHTML = testcase.describe(testdata); - row.appendChild(cell); - table.appendChild(row); - } - } - - function setup() { - var tables = document.getElementsByTagName('table'); - for (var i = 0; i < tables.length; i++) { - tables[i].parentNode.removeChild(tables[i]); - } - - subscriptLoader.loadSubScript('chrome://redirector/content/unittests.js'); - redirector.reload(); - - for (var name in tests) { - setupTest(name, tests[name]); - } - } - - function runTests() { - for (var testcaseName in tests) { - var testcase = tests[testcaseName]; - for (var i = 0; i < testcase.tests.length; i++) { - try { - var result = testcase.run(testcase.tests[i]); - if (result) { - document.getElementById(testcaseName + '_' + i).style.backgroundColor = '#17f816'; - } else { - document.getElementById(testcaseName + '_' + i).style.backgroundColor = '#ff0000'; - } - } catch(e) { - document.getElementById(testcaseName + '_' + i).style.backgroundColor = '#ff0000'; - } - } - } - } - - </script> - </head> - <body onload="setup();"> - <h1>Redirector Unit Tests</h1> - <button onclick="runTests();">Run tests</button> - <button onclick="setup();">Reload tests</button> - </body> -</html> \ No newline at end of file diff --git a/chrome/content/unittests.js b/chrome/content/unittests.js deleted file mode 100644 index ea6e26b..0000000 --- a/chrome/content/unittests.js +++ /dev/null @@ -1,39 +0,0 @@ -//// $Id$ -var tests = { - "Wildcard matches" : { - run : function(data) { - var pattern = data[0], - url = data[1], - expected = data[2]; - var parts = expected.split(','); - var redirectUrl = ''; - if (!(parts.length == 1 && parts[0] == '')) { - for (var i in parts) { - redirectUrl += '$' + (parseFloat(i)+1) + ','; - } - redirectUrl = redirectUrl.substr(0, redirectUrl.length-1); - } - var result = redirector.wildcardMatch(pattern, url, redirectUrl, false); - return result == expected; - }, - - describe : function(data) { return data[0] + ' == ' + data[1] + ', matches=' + data[2]; }, - tests : [ - ['http://foo*', 'http://foobar.is', 'bar.is'], - ['http://foo*', 'http://foo', ''], - ['*://foo.is', 'http://foo.is', 'http'], - ['*http://foo.is', 'http://foo.is', ''], - ['http*foo*', 'http://foobar.is', '://,bar.is'], - ['http*foo*', 'http://foo', '://,'], - ['*://f*.is', 'http://foo.is', 'http,oo'], - ['*http://f*.is', 'http://foo.is', ',oo'], - ['*foo*', 'http://foo', 'http://,'], - ['*foo*', 'foobar.is', ',bar.is'], - ['*foo*', 'http://foobar.is', 'http://,bar.is'], - ['http://foo.is', 'http://foo.is', ''], - ['*', 'http://foo.is', 'http://foo.is'], - ['*://*oo*bar*', 'http://foo.is/bar/baz', 'http,f,.is/,/baz'], - ['*://**oo*bar*', 'http://foo.is/bar/baz', 'http,,f,.is/,/baz'], - ] - } -}; -- cgit v1.2.3-70-g09d2