Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion css/redirector.css
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ a.disabled:hover, button[disabled]:hover {
margin-top:8px;
}

.hidden {
.hidden, .replace-process-input.hidden {
display:none;
}

Expand Down Expand Up @@ -521,6 +521,10 @@ a[ng-click] {
padding-bottom:10px;
}

.replace-process-input input[type='checkbox'] {
margin-top: 6px;
}

/* Footer with link */
footer {
margin-top:30px;
Expand Down
5 changes: 5 additions & 0 deletions help.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ <h3>Table of contents</h3>
<li><a href="#processmatches">Process Matches</a>
<ol>
<li><a href="#noprocessing">No Processing</a></li>
<li><a href="#replacematches">Replace matches</a></li>
<li><a href="#urldecodematches">URL decode matches</a></li>
<li><a href="#doubleurldecodematches">Double URL decode matches</a></li>
<li><a href="#urlencodematches">URL encode matches</a></li>
Expand Down Expand Up @@ -95,6 +96,10 @@ <h4>Basic usage</h4>
different ways to process the Regular expression matches before using them. The decoding options available are:
<ul>
<li><a name="noprocessing"></a><strong>No Processing:</strong> This is the default. Just use the matches from the original url exactly as they are.</li>
<li><a name="replacematches"></a><strong>Replace matches:</strong> Sometimes you may want to modify some parts of your matches.
This helps you replace, delete or add something. You can use this as simple as possible like finding a character and changing it or by using search patterns to find something and javascript
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_a_parameter" target="_blank">replacement patterns</a> to replace it.
</li>
<li><a name="urldecodematches"></a><strong>URL Decode matches:</strong> A common usage of Redirector is to catch urls like
<span class="url">http://foo.com/redirect.php?url=http%3A%2F%2Fbar%2Ecom%2Fpath</span> and try to catch the url parameter and redirect to it. A pattern
like <span class="pattern">http://foo.com/redirect.php?url=*</span> might be used for that purpose. However, if the url parameter is <em>escaped</em> (also known
Expand Down
18 changes: 17 additions & 1 deletion js/editredirect.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ function editRedirect(index) {
activeRedirect = new Redirect(REDIRECTS[index]); //Make a new one, which we can dump a bunch of stuff on...
activeRedirect.existing = true;
activeRedirect.index = index;
toggleReplaceProcessForm(activeRedirect.processMatches);
showForm('#edit-redirect-form', activeRedirect);
setTimeout(() => el('input[data-bind="description"]').focus(), 200); //Why not working...?
}

function cancelEdit() {
toggleReplaceProcessForm(activeRedirect.processMatches, true);
activeRedirect = null;
hideForm('#edit-redirect-form');
}
Expand Down Expand Up @@ -51,12 +53,23 @@ function toggleAdvancedOptions(ev) {
}
}

function toggleReplaceProcessForm(currentProcess, force) {
force = force ?? currentProcess !== 'replace';

for (const input of document.querySelectorAll('.replace-process-input')) {
input.classList.toggle('hidden', force);
}
}

function editFormChange() {
//Now read values back from the form...
for (let input of el('#edit-redirect-form').querySelectorAll('input[type="text"][data-bind]')) {
let prop = input.getAttribute('data-bind');
activeRedirect[prop] = input.value;

if (prop === 'replaceFrom') {
activeRedirect.replacePattern = input.value;
}
}
activeRedirect.appliesTo = [];
for (let input of el('#apply-to').querySelectorAll('input:checked')) {
Expand All @@ -65,6 +78,10 @@ function editFormChange() {

activeRedirect.processMatches = el('#process-matches option:checked').value;
activeRedirect.patternType = el('[name="patterntype"]:checked').value;
activeRedirect.usePatternForReplace = el('#use-pattern').checked;
activeRedirect.replaceAll = el('#replace-all').checked;

toggleReplaceProcessForm(activeRedirect.processMatches);

activeRedirect.updateExampleResult();

Expand Down Expand Up @@ -93,7 +110,6 @@ function cancelDelete() {
hideForm('#delete-redirect-form');
}


function setupEditAndDeleteEventListeners() {

el('#btn-save-redirect').addEventListener('click', saveRedirect);
Expand Down
44 changes: 43 additions & 1 deletion js/redirect.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ Redirect.prototype = {
error : null,
includePattern : '',
excludePattern : '',
replacePattern : '',
replaceFrom : '',
replacement : '',
replaceAll : false,
usePatternForReplace : false,
patternDesc:'',
redirectUrl : '',
patternType : '',
Expand All @@ -48,20 +53,29 @@ Redirect.prototype = {

var incPattern = this._preparePattern(this.includePattern);
var excPattern = this._preparePattern(this.excludePattern);
var replPattern = this._preparePattern(this.replacePattern);

if (incPattern) {
this._rxInclude = new RegExp(incPattern, 'gi');
}
if (excPattern) {
this._rxExclude = new RegExp(excPattern, 'gi');
}
if (this.usePatternForReplace && replPattern) {
this._rxReplace = new RegExp(replPattern, this.replaceAll ? 'gi' : 'i');
}
},

equals : function(redirect) {
return this.description == redirect.description
&& this.exampleUrl == redirect.exampleUrl
&& this.includePattern == redirect.includePattern
&& this.excludePattern == redirect.excludePattern
&& this.replacePattern == redirect.replacePattern
&& this.replaceFrom == redirect.replaceFrom
&& this.replacement == redirect.replacement
&& this.replaceAll == redirect.replaceAll
&& this.usePatternForReplace == redirect.usePatternForReplace
&& this.patternDesc == redirect.patternDesc
&& this.redirectUrl == redirect.redirectUrl
&& this.patternType == redirect.patternType
Expand All @@ -77,6 +91,11 @@ Redirect.prototype = {
error : this.error,
includePattern : this.includePattern,
excludePattern : this.excludePattern,
replacePattern : this.replacePattern,
replaceFrom : this.replaceFrom,
replacement : this.replacement,
replaceAll : this.replaceAll,
usePatternForReplace : this.usePatternForReplace,
patternDesc : this.patternDesc,
redirectUrl : this.redirectUrl,
patternType : this.patternType,
Expand Down Expand Up @@ -146,6 +165,15 @@ Redirect.prototype = {
}
}

if (this.patternType == Redirect.REGEX && this.usePatternForReplace && this.replacePattern) {
try {
new RegExp(this.replacePattern, this.replaceAll ? 'gi' : 'i');
} catch(e) {
this.error = 'Invalid regular expression in Replace pattern.';
return;
}
}

if (!this.appliesTo || this.appliesTo.length == 0) {
this.error = 'At least one request type must be chosen.';
return;
Expand Down Expand Up @@ -189,6 +217,7 @@ Redirect.prototype = {
//Private functions below
_rxInclude : null,
_rxExclude : null,
_rxReplace : null,

_preparePattern : function(pattern) {
if (!pattern) {
Expand Down Expand Up @@ -221,6 +250,11 @@ Redirect.prototype = {
this.error = o.error || null;
this.includePattern = o.includePattern || '';
this.excludePattern = o.excludePattern || '';
this.replacePattern = o.replacePattern || '';
this.replaceFrom = o.replaceFrom || '';
this.replacement = o.replacement || '';
this.replaceAll = o.replaceAll || false;
this.usePatternForReplace = o.usePatternForReplace || false;
this.redirectUrl = o.redirectUrl || '';
this.patternType = o.patternType || Redirect.WILDCARD;

Expand Down Expand Up @@ -274,7 +308,15 @@ Redirect.prototype = {
var resultUrl = this.redirectUrl;
for (var i = matches.length - 1; i > 0; i--) {
var repl = matches[i] || '';
if (this.processMatches == 'urlDecode') {
if (this.processMatches == 'replace') {
const pattern = this.usePatternForReplace ? this._rxReplace ?? '' : this.replaceFrom;

if (this.replaceAll) {
repl = repl.replaceAll(pattern, this.replacement);
} else {
repl = repl.replace(pattern, this.replacement);
}
} else if (this.processMatches == 'urlDecode') {
repl = unescape(repl);
} else if (this.processMatches == 'doubleUrlDecode') {
repl = unescape(unescape(repl));
Expand Down
4 changes: 3 additions & 1 deletion js/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ function dataBind(el, dataObject) {
} else if (tag.tagName.toLowerCase() === 'select') {
for (let opt of tag.querySelectorAll('option')) {
if (opt.getAttribute('value') === dataObject[prop]) {
opt.setAttribute('selected', 'selected');
opt.setAttribute('selected', '');
opt.selected = true;
} else {
opt.removeAttribute('selected');
opt.selected = false;
}
}
} else if (Array.isArray(dataObject[prop])) {
Expand Down
15 changes: 15 additions & 0 deletions redirector.html
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ <h3>Create Redirect</h3>
<div class="input-cell">
<select id="process-matches" data-bind="processMatches">
<option value="noProcessing">No Processing</option>
<option value="replace">Replace</option>
<option value="urlEncode">URL Encode</option>
<option value="urlDecode">URL Decode</option>
<option value="doubleUrlDecode">Double URL Decode</option>
Expand All @@ -101,6 +102,20 @@ <h3>Create Redirect</h3>
<span class="placeholder" data-bind="processMatchesExampleText"></span>
</div>
</div>
<div class="replace-process-input hidden">
<label>Find:</label>
<div class="input-cell"><input type="text" data-bind="replaceFrom" placeholder="Find in matches" /></div>
</div>
<div class="replace-process-input hidden">
<label>Replace with:</label>
<div class="input-cell"><input type="text" data-bind="replacement" placeholder="Enter a text or replacement pattern to replace with matches"/></div>
<div class="input-cell">
<label for="replace-all"><input type="checkbox" id="replace-all" data-bind="replaceAll"><span>Replace All</span></label>
</div>
<div class="input-cell">
<label for="use-pattern"><input type="checkbox" id="use-pattern" data-bind="usePatternForReplace"><span>Match using selected pattern</span></label>
</div>
</div>
<div>
<label>Apply to:</label>
<div class="input-cell" id="apply-to" data-bind="appliesTo">
Expand Down