Commit 5690f587 authored by fxa's avatar fxa

improved encoding (not optimal, yet)

parent b74e1c1d
...@@ -23,5 +23,5 @@ ...@@ -23,5 +23,5 @@
"uritemplate-test/spec-examples-by-sections.json", "uritemplate-test/spec-examples-by-sections.json",
"uritemplate-test/spec-examples.json" "uritemplate-test/spec-examples.json"
], ],
"version" : "0.1.3" "version" : "0.1.4"
} }
\ No newline at end of file
(function (exportCallback) { (function (exportCallback) {
"use strict"; "use strict";
// http://blog.sangupta.com/2010/05/encodeuricomponent-and.html
// //
// helpers // helpers
// //
...@@ -32,17 +33,6 @@ ...@@ -32,17 +33,6 @@
return currentValue; return currentValue;
} }
// TODO remove
function arrayAll(array, predicate) {
var index;
for (index = 0; index < array.length; index += 1) {
if (!predicate(array[index], index, array)) {
return false;
}
}
return true;
}
function reduce(arrayOrObject, callback, initialValue) { function reduce(arrayOrObject, callback, initialValue) {
return isArray(arrayOrObject) ? arrayReduce(arrayOrObject, callback, initialValue) : objectReduce(arrayOrObject, callback, initialValue); return isArray(arrayOrObject) ? arrayReduce(arrayOrObject, callback, initialValue) : objectReduce(arrayOrObject, callback, initialValue);
} }
...@@ -52,8 +42,8 @@ ...@@ -52,8 +42,8 @@
* Section 2.3 of the RFC makes clear defintions: * Section 2.3 of the RFC makes clear defintions:
* * undefined and null are not defined. * * undefined and null are not defined.
* * the empty string is defined * * the empty string is defined
* * an array is defined, if it contains at least one defined element * * an array ("list") is defined, if it contains at least one defined element
* * an object is defined, if it contains at least one defined property * * an object ("map") is defined, if it contains at least one defined property
* @param object * @param object
* @return {Boolean} * @return {Boolean}
*/ */
...@@ -97,9 +87,58 @@ ...@@ -97,9 +87,58 @@
return isDigit(chr) || (chr >= 'a' && chr <= 'f') || (chr >= 'A' && chr <= 'F'); return isDigit(chr) || (chr >= 'a' && chr <= 'f') || (chr >= 'A' && chr <= 'F');
} }
function isPctEncoded(chr) { var pctEncoder = (function () {
return chr.length === 3 && chr.charAt(0) === '%' && isHexDigit(chr.charAt(1) && isHexDigit(chr.charAt(2)));
} // see http://ecmanaut.blogspot.de/2006/07/encoding-decoding-utf8-in-javascript.html
function toUtf8 (s) {
return unescape(encodeURIComponent(s));
}
function encode(chr) {
var
result = '',
octets = toUtf8(chr),
octet,
index;
for (index = 0; index < octets.length; index += 1) {
octet = octets.charCodeAt(index);
result += '%' + octet.toString(16).toUpperCase();
}
return result;
}
function isPctEncoded (chr) {
if (chr.length < 3) {
return false;
}
for (var index = 0; index < chr.length; index += 3) {
if (chr.charAt(index) !== '%' || !isHexDigit(chr.charAt(index + 1) || !isHexDigit(chr.charAt(index + 2)))) {
return false;
}
}
return true;
}
function pctCharAt(text, startIndex) {
var chr = text.charAt(startIndex);
if (chr !== '%') {
return chr;
}
chr = text.substr(startIndex, 3);
if (!isPctEncoded(chr)) {
return '%';
}
return chr;
}
return {
encodeCharacter: encode,
decodeCharacter: decodeURIComponent,
isPctEncoded: isPctEncoded,
pctCharAt: pctCharAt
};
}());
/** /**
* Returns if an character is an varchar character according 2.3 of rfc 6570 * Returns if an character is an varchar character according 2.3 of rfc 6570
...@@ -107,7 +146,7 @@ ...@@ -107,7 +146,7 @@
* @return (Boolean) * @return (Boolean)
*/ */
function isVarchar(chr) { function isVarchar(chr) {
return isAlpha(chr) || isDigit(chr) || chr === '_' || isPctEncoded(chr); return isAlpha(chr) || isDigit(chr) || chr === '_' || pctEncoder.isPctEncoded(chr);
} }
/** /**
...@@ -129,31 +168,21 @@ ...@@ -129,31 +168,21 @@
chr === ')' || chr === '*' || chr === '+' || chr === ',' || chr === ';' || chr === '=' || chr === "'"; chr === ')' || chr === '*' || chr === '+' || chr === ',' || chr === ';' || chr === '=' || chr === "'";
} }
function pctEncode(chr) {
return '%' + chr.charCodeAt(0).toString(16).toUpperCase();
}
function encode(text, passReserved) { function encode(text, passReserved) {
var var
result = '', result = '',
index, index,
chr; chr = '';
if (typeof text === "number" || typeof text === "boolean") { if (typeof text === "number" || typeof text === "boolean") {
text = text.toString(); text = text.toString();
} }
for (index = 0; index < text.length; index += 1) { for (index = 0; index < text.length; index += chr.length) {
chr = text.charAt(index); chr = pctEncoder.pctCharAt(text, index);
if (chr === '%') { if (chr.length > 1) {
if (isHexDigit(text.charAt(index+1)) && isHexDigit(text.charAt(index+2))) { result += chr;
// pass three chars to the result
result += text.substr(index, 3);
index += 2;
} else {
result += '%25';
}
} }
else { else {
result += isUnreserved(chr) || (passReserved && isReserved(chr)) ? chr : pctEncode(chr); result += isUnreserved(chr) || (passReserved && isReserved(chr)) ? chr : pctEncoder.encodeCharacter(chr);
} }
} }
return result; return result;
...@@ -220,20 +249,14 @@ ...@@ -220,20 +249,14 @@
var var
result = '', result = '',
index, index,
chr; chr = '';
for (index = 0; index < literal.length; index += 1) { for (index = 0; index < literal.length; index += chr.length) {
chr = literal.charAt(index); chr = pctEncoder.pctCharAt(literal, index);
if (chr === '%') { if (chr.length > 0) {
if (isHexDigit(literal.charAt(index + 1)) && isHexDigit(literal.charAt(index + 2))) { result += chr;
result += literal.substr(index, 3);
index += 2;
}
else {
throw new Error('illegal % found at position ' + index);
}
} }
else { else {
result += isReserved(chr) || isUnreserved(chr) ? chr : pctEncode(chr); result += isReserved(chr) || isUnreserved(chr) ? chr : pctEncoder.encodeCharacter(chr);
} }
} }
return result; return result;
...@@ -383,9 +406,11 @@ ...@@ -383,9 +406,11 @@
varspec.maxLength = parseInt(text.substring(maxLengthStart, index), 10); varspec.maxLength = parseInt(text.substring(maxLengthStart, index), 10);
maxLengthStart = null; maxLengthStart = null;
} }
// remove outer {}
text = outerText.substr(1, outerText.length - 2); text = outerText.substr(1, outerText.length - 2);
for (index = 0; index < text.length; index += chr.length) { for (index = 0; index < text.length; index += chr.length) {
chr = text[index]; chr = pctEncoder.pctCharAt(text, index);
if (index === 0) { if (index === 0) {
operator = operators.valueOf(chr); operator = operators.valueOf(chr);
if (operator.symbol !== '') { if (operator.symbol !== '') {
...@@ -397,13 +422,7 @@ ...@@ -397,13 +422,7 @@
varnameStart = 0; varnameStart = 0;
} }
if (varnameStart !== null) { if (varnameStart !== null) {
// Within varnames pct encoded values are allowed. looks strange to me.
if (chr === '%') {
if (index > text.length - 2 || !isDigit(text[index + 1] || !isDigit(text[index + 2]))) {
throw new Error('illegal char "%" at position ' + index);
}
chr += text[index + 1] + text[index + 2];
}
// the spec says: varname = varchar *( ["."] varchar ) // the spec says: varname = varchar *( ["."] varchar )
// so a dot is allowed except for the first char // so a dot is allowed except for the first char
if (chr === '.') { if (chr === '.') {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment