Files

222 lines
7.3 KiB
JavaScript

/**
* Models of URLRedirector.
*/
/* A rule */
function Rule() {
this.description = null; // Rule description
this.origin = null; // Origin url pattern
this.exclude = null; // Exclude url pattern
this.methods = []; // Http methods
this.types = []; // Resource types
this.target = null; // Target url pattern
this.example = null; // An Test example
this.enable = false; // Enable or not
this.process = null; // Process match, urlEncode / urlDecode / base64Encode / base64Decode
}
/* From a plain object */
Rule.prototype.fromObject = function (obj) {
for (var i in obj){
if (this.hasOwnProperty(i)) {
this[i] = obj[i];
}
}
if (this.origin) {
this._originRe = new RegExp(this.origin, "g");
}
if (this.exclude) {
this._excludeRe = new RegExp(this.exclude, "g");
}
};
/* Redirect of a rule */
Rule.prototype.redirect = function (url, method, type) {
if (this.enable && this._originRe) {
this._originRe.lastIndex = 0;
if (this._originRe.test(url)) {
/* Check method */
if (arguments.length > 1 && method) {
if (this.methods && this.methods.length > 0) {
var methodMatched = false;
for (var i = 0; i < this.methods.length; i++) {
if (this.methods[i] == method) {
methodMatched = true;
break;
}
}
if (!methodMatched) {
return null;
}
}
}
/* Check resource type */
if (arguments.length > 2 && type) {
if (this.types && this.types.length > 0) {
var typeMatched = false;
for (var i = 0; i < this.types.length; i++) {
if (this.types[i] == type) {
typeMatched = true;
break;
}
}
if (!typeMatched) {
return null;
}
}
}
/* Exclude some rule */
if (this._excludeRe) {
this._excludeRe.lastIndex = 0;
if (this._excludeRe.test(url)) {
return null;
}
}
/* Process match or not */
if (this.process) {
this._originRe.lastIndex = 0;
var matches = this._originRe.exec(url);
var newURL = this.target;
if (matches) {
for (var i = 1; i < matches.length; i++) {
var m = matches[i] || "";
try {
if (this.process == "urlEncode") {
m = encodeURIComponent(m);
}
else if (this.process == "urlDecode") {
m = decodeURIComponent(m);
}
else if (this.process == "base64Encode") {
m = btoa(m);
}
else if (this.process == "base64Decode") {
m = atob(m);
}
} catch (err) {
// Something error, could not process
// console.warn("Could not process " + this.process + " " + m);
return null;
}
newURL = newURL.replace(new RegExp("\\$" + i, "g"), m);
}
return newURL;
}
} else {
/* Return a new url */
this._originRe.lastIndex = 0;
var newURL = url.replace(this._originRe, this.target);
return newURL;
}
}
}
return null;
};
/* An online url */
function OnlineURL() {
this.description = null; // Description
this.url = null; // URL of the resource
this.enable = false; // Enable or not
this.auto = true; // Auto download
this.rules = []; // Rules
}
/* From a plain object */
OnlineURL.prototype.fromObject = function (obj) {
for (var i in obj){
/* Rules */
if (i == "rules") {
this.rules = [];
if (obj[i] && obj[i].length > 0) {
for (var j=0; j<obj[i].length; j++) {
var rule = new Rule();
rule.fromObject(obj[i][j]);
this.rules.push(rule);
}
}
}
else if (this.hasOwnProperty(i)) {
this[i] = obj[i];
}
}
};
/* Redirect of an online url */
OnlineURL.prototype.redirect = function (url, method, type) {
if (this.enable && this.rules && this.rules.length > 0) {
for (var i=0; i<this.rules.length; i++){
var newURL = this.rules[i].redirect(url, method, type);
if (newURL) {
return newURL;
}
}
}
return null;
};
/* Options storage */
function Storage() {
this.enable = false; // Enable or not
this.sync = false; // Enable sync between browser
this.updateInterval = 900; // Default update interval is 15min
this.updatedAt = null; // Last update time
this.onlineURLs = []; // Online urls
this.customRules = []; // User defined rules
}
/* From a plain object */
Storage.prototype.fromObject = function (obj) {
for (var i in obj) {
/* Online urls */
if (i == "onlineURLs") {
this.onlineURLs = [];
if (obj[i] && obj[i].length > 0) {
for (var j=0; j<obj[i].length; j++) {
var onlineURL = new OnlineURL();
onlineURL.fromObject(obj[i][j]);
this.onlineURLs.push(onlineURL);
}
}
}
/* Custom rules */
else if (i == "customRules") {
this.customRules = [];
if (obj[i] && obj[i].length > 0) {
for (var j=0; j<obj[i].length; j++) {
var customRule = new Rule();
customRule.fromObject(obj[i][j]);
this.customRules.push(customRule);
}
}
}
else if (this.hasOwnProperty(i)) {
this[i] = obj[i];
}
}
};
Storage.prototype.redirect = function (url, method, type) {
if (!this.enable) {
return null;
}
var isChanged = false;
var loopCount = 0;
// To avoid endless redirection
while(loopCount < 1000) {
var thisStageUrl;
if (!this.customRules.some(rule => thisStageUrl = rule.redirect(url, method, type))) {
this.onlineURLs.some(rule => thisStageUrl = rule.redirect(url, method, type));
}
if (!thisStageUrl) {
break;
}
isChanged = true;
url = thisStageUrl;
loopCount += 1;
}
return isChanged && loopCount < 1000 ? url : null;
};