Fixed a bunch more encoding issues.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3358 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
Cory McWilliams 2016-12-22 17:38:21 +00:00
parent 937e32fb99
commit 5c855afbb3
10 changed files with 3412 additions and 725 deletions

View File

@ -16,7 +16,7 @@ File.makeDirectory("data/auth/db");
var gDatabase = new Database("data/auth/db");
try {
gAccounts = JSON.parse(File.readFile(kAccountsFile));
gAccounts = JSON.parse(new TextDecoder("UTF-8").decode(File.readFile(kAccountsFile)));
} catch (error) {
}
@ -131,7 +131,7 @@ function authHandler(request, response) {
response.writeHead(303, {"Location": formData.return, "Set-Cookie": cookie});
response.end();
} else {
var html = File.readFile("core/auth.html");
var html = new TextDecoder("UTF-8").decode(File.readFile("core/auth.html"));
var contents = "";
if (entry) {

View File

@ -1,5 +1,9 @@
"use strict";
require("encoding-indexes");
require("encoding");
var terminal = require("terminal");
var auth = require("auth");
var network = require("network");
@ -188,9 +192,13 @@ function badName(name) {
return bad;
}
function readFileUtf8(fileName) {
return new TextDecoder("UTF-8").decode(File.readFile(fileName));
}
function getManifest(fileName) {
let manifest = [];
let lines = File.readFile(fileName).split("\n").map(x => x.trimRight());
let lines = readFileUtf8(fileName).split("\n").map(x => x.trimRight());
for (let i = 0; i < lines.length; i++) {
if (lines[i].substring(0, 4) == "//! ") {
manifest.push(lines[i].substring(4));
@ -339,7 +347,7 @@ function getProcess(packageOwner, packageName, key, options) {
let source = {};
for (let i in manifest.require) {
let name = manifest.require[i];
source[name] = File.readFile("packages/" + process.packageOwner + "/" + name + "/" + name + ".js");
source[name] = readFileUtf8("packages/" + process.packageOwner + "/" + name + "/" + name + ".js");
}
process.task.setRequires(source);
}
@ -347,7 +355,7 @@ function getProcess(packageOwner, packageName, key, options) {
print("Activating task");
process.task.activate();
print("Executing task");
process.task.execute({name: fileName, source: File.readFile(fileName)}).then(function() {
process.task.execute({name: fileName, source: readFileUtf8(fileName)}).then(function() {
print("Task ready");
broadcastEvent('onSessionBegin', [getUser(process, process)]);
resolveReady(process);
@ -404,7 +412,7 @@ function setGlobalSettings(settings) {
}
try {
gGlobalSettings = JSON.parse(File.readFile(kGlobalSettingsFile));
gGlobalSettings = JSON.parse(readFileUtf8(kGlobalSettingsFile));
} catch (error) {
print("Error loading settings from " + kGlobalSettingsFile + ": " + error);
}

39
core/encoding-indexes.js Normal file

File diff suppressed because one or more lines are too long

3309
core/encoding.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,5 @@
"use strict";
require("stringview");
var gHandlers = [];
var gSocketHandlers = [];
@ -188,7 +186,7 @@ function handleRequest(request, response) {
function handleWebSocketRequest(request, response, client) {
var buffer = new Uint8Array(0);
var frame = "";
var frame = new Uint8Array(0);
var frameOpCode = 0x0;
var handler = findSocketHandler(request);
@ -202,7 +200,7 @@ function handleWebSocketRequest(request, response, client) {
opCode = 0x2;
}
if (opCode == 0x1 && (typeof message == "string" || message instanceof String)) {
message = new StringView(message, "UTF-8").rawData;
message = new TextEncoder("UTF-8").encode(message);
}
var fin = true;
var packet = [(fin ? (1 << 7) : 0) | (opCode & 0xf)];
@ -268,14 +266,18 @@ function handleWebSocketRequest(request, response, client) {
if (havePayload) {
var mask = buffer.slice(maskStart, maskStart + 4);
var dataStart = maskStart + 4;
var decoded = "";
var decoded = new Array(payloadLength);
var payload = buffer.slice(dataStart, dataStart + payloadLength);
buffer = buffer.slice(dataStart + payloadLength);
for (var i = 0; i < payloadLength; i++) {
decoded += String.fromCharCode(payload[i] ^ mask[i % 4]);
decoded[i] = payload[i] ^ mask[i % 4];
}
frame += decoded;
var newBuffer = new Uint8Array(frame.length + decoded.length);
newBuffer.set(frame, 0);
newBuffer.set(decoded, frame.length);
frame = newBuffer;
if (opCode) {
frameOpCode = opCode;
}
@ -283,11 +285,11 @@ function handleWebSocketRequest(request, response, client) {
if (fin) {
if (response.onMessage) {
response.onMessage({
data: frame,
data: frameOpCode == 0x1 ? new TextDecoder("UTF-8").decode(frame) : frame,
opCode: frameOpCode,
});
}
frame = "";
frame = new Uint8Array(0);
}
}
}
@ -362,7 +364,7 @@ function handleConnection(client) {
function handleLine(line, length) {
if (bodyToRead == -1) {
line = new StringView(line, "ASCII").toString();
line = new TextDecoder("ASCII").decode(line);
if (!request) {
request = line.split(' ');
return true;
@ -392,7 +394,7 @@ function handleConnection(client) {
}
}
} else {
line = new StringView(line, "UTF-8").toString();
line = new TextDecoder("UTF-8").decode(line);
body += line;
bodyToRead -= length;
if (bodyToRead <= 0) {
@ -454,8 +456,8 @@ socket.bind(kHost, kHttpPort).then(function() {
logError("[" + new Date() + "] " + error);
});
var privateKey = File.readFile("data/httpd/privatekey.pem");
var certificate = File.readFile("data/httpd/certificate.pem");
var privateKey = new TextDecoder("ASCII").decode(File.readFile("data/httpd/privatekey.pem"));
var certificate = new TextDecoder("ASCII").decode(File.readFile("data/httpd/certificate.pem"));
if (privateKey && certificate) {
var tls = new TlsContext();

View File

@ -9,7 +9,7 @@
</head>
<body style="display: flex; flex-flow: column">
<div class="navigation">
<span>~😎</span>
<span>😎</span>
<span id="title">Tilde Friends</span>
<a href="/">home</a>
<a href="$(EDIT_SOURCE)">edit</a>

View File

@ -1,679 +0,0 @@
"use strict";
/*\
|*|
|*| :: Number.isInteger() polyfill ::
|*|
|*| https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger
|*|
\*/
if (!Number.isInteger) {
Number.isInteger = function isInteger (nVal) {
return typeof nVal === "number" && isFinite(nVal) && nVal > -9007199254740992 && nVal < 9007199254740992 && Math.floor(nVal) === nVal;
};
}
/*\
|*|
|*| StringView - Mozilla Developer Network
|*|
|*| Revision #9, October 30, 2016
|*|
|*| https://developer.mozilla.org/en-US/Add-ons/Code_snippets/StringView
|*| https://developer.mozilla.org/en-US/docs/User:fusionchess
|*| https://github.com/madmurphy/stringview.js
|*|
|*| This framework is released under the GNU Lesser General Public License, version 3 or later.
|*| http://www.gnu.org/licenses/lgpl-3.0.html
|*|
\*/
function StringView (vInput, sEncoding /* optional (default: UTF-8) */, nOffset /* optional */, nLength /* optional */) {
var fTAView, aWhole, aRaw, fPutOutptCode, fGetOutptChrSize, nInptLen, nStartIdx = isFinite(nOffset) ? nOffset : 0, nTranscrType = 15;
if (sEncoding) { this.encoding = sEncoding.toString(); }
encSwitch: switch (this.encoding) {
case "UTF-8":
fPutOutptCode = StringView.putUTF8CharCode;
fGetOutptChrSize = StringView.getUTF8CharLength;
fTAView = Uint8Array;
break encSwitch;
case "UTF-16":
fPutOutptCode = StringView.putUTF16CharCode;
fGetOutptChrSize = StringView.getUTF16CharLength;
fTAView = Uint16Array;
break encSwitch;
case "UTF-32":
fTAView = Uint32Array;
nTranscrType &= 14;
break encSwitch;
default:
/* case "ASCII", or case "BinaryString" or unknown cases */
fTAView = Uint8Array;
nTranscrType &= 14;
}
typeSwitch: switch (typeof vInput) {
case "string":
/* the input argument is a primitive string: a new buffer will be created. */
nTranscrType &= 7;
break typeSwitch;
case "object":
classSwitch: switch (vInput.constructor) {
case StringView:
/* the input argument is a stringView: a new buffer will be created. */
nTranscrType &= 3;
break typeSwitch;
case String:
/* the input argument is an objectified string: a new buffer will be created. */
nTranscrType &= 7;
break typeSwitch;
case ArrayBuffer:
/* the input argument is an arrayBuffer: the buffer will be shared. */
aWhole = new fTAView(vInput);
nInptLen = this.encoding === "UTF-32" ?
vInput.byteLength >>> 2
: this.encoding === "UTF-16" ?
vInput.byteLength >>> 1
:
vInput.byteLength;
aRaw = nStartIdx === 0 && (!isFinite(nLength) || nLength === nInptLen) ?
aWhole
: new fTAView(vInput, nStartIdx, !isFinite(nLength) ? nInptLen - nStartIdx : nLength);
break typeSwitch;
case Uint32Array:
case Uint16Array:
case Uint8Array:
/* the input argument is a typedArray: the buffer, and possibly the array itself, will be shared. */
fTAView = vInput.constructor;
nInptLen = vInput.length;
aWhole = vInput.byteOffset === 0 && vInput.length === (
fTAView === Uint32Array ?
vInput.buffer.byteLength >>> 2
: fTAView === Uint16Array ?
vInput.buffer.byteLength >>> 1
:
vInput.buffer.byteLength
) ? vInput : new fTAView(vInput.buffer);
aRaw = nStartIdx === 0 && (!isFinite(nLength) || nLength === nInptLen) ?
vInput
: vInput.subarray(nStartIdx, isFinite(nLength) ? nStartIdx + nLength : nInptLen);
break typeSwitch;
default:
/* the input argument is an array or another serializable object: a new typedArray will be created. */
aWhole = new fTAView(vInput);
nInptLen = aWhole.length;
aRaw = nStartIdx === 0 && (!isFinite(nLength) || nLength === nInptLen) ?
aWhole
: aWhole.subarray(nStartIdx, isFinite(nLength) ? nStartIdx + nLength : nInptLen);
}
break typeSwitch;
default:
/* the input argument is a number, a boolean or a function: a new typedArray will be created. */
aWhole = aRaw = new fTAView(Number(vInput) || 0);
}
if (nTranscrType < 8) {
var vSource, nOutptLen, nCharStart, nCharEnd, nEndIdx, fGetInptChrSize, fGetInptChrCode;
if (nTranscrType & 4) { /* input is string */
vSource = vInput;
nOutptLen = nInptLen = vSource.length;
nTranscrType ^= this.encoding === "UTF-32" ? 0 : 2;
/* ...or...: nTranscrType ^= Number(this.encoding !== "UTF-32") << 1; */
nStartIdx = nCharStart = nOffset ? Math.max((nOutptLen + nOffset) % nOutptLen, 0) : 0;
nEndIdx = nCharEnd = (Number.isInteger(nLength) ? Math.min(Math.max(nLength, 0) + nStartIdx, nOutptLen) : nOutptLen) - 1;
} else { /* input is stringView */
vSource = vInput.rawData;
nInptLen = vInput.makeIndex();
nStartIdx = nCharStart = nOffset ? Math.max((nInptLen + nOffset) % nInptLen, 0) : 0;
nOutptLen = Number.isInteger(nLength) ? Math.min(Math.max(nLength, 0), nInptLen - nCharStart) : nInptLen;
nEndIdx = nCharEnd = nOutptLen + nCharStart;
if (vInput.encoding === "UTF-8") {
fGetInptChrSize = StringView.getUTF8CharLength;
fGetInptChrCode = StringView.loadUTF8CharCode;
} else if (vInput.encoding === "UTF-16") {
fGetInptChrSize = StringView.getUTF16CharLength;
fGetInptChrCode = StringView.loadUTF16CharCode;
} else {
nTranscrType &= 1;
}
}
if (nOutptLen === 0 || nTranscrType < 4 && vSource.encoding === this.encoding && nCharStart === 0 && nOutptLen === nInptLen) {
/* the encoding is the same, the length too and the offset is 0... or the input is empty! */
nTranscrType = 7;
}
conversionSwitch: switch (nTranscrType) {
case 0:
/* both the source and the new StringView have a fixed-length encoding... */
aWhole = new fTAView(nOutptLen);
for (var nOutptIdx = 0; nOutptIdx < nOutptLen; aWhole[nOutptIdx] = vSource[nStartIdx + nOutptIdx++]);
break conversionSwitch;
case 1:
/* the source has a fixed-length encoding but the new StringView has a variable-length encoding... */
/* mapping... */
nOutptLen = 0;
for (var nInptIdx = nStartIdx; nInptIdx < nEndIdx; nInptIdx++) {
nOutptLen += fGetOutptChrSize(vSource[nInptIdx]);
}
aWhole = new fTAView(nOutptLen);
/* transcription of the source... */
for (var nInptIdx = nStartIdx, nOutptIdx = 0; nOutptIdx < nOutptLen; nInptIdx++) {
nOutptIdx = fPutOutptCode(aWhole, vSource[nInptIdx], nOutptIdx);
}
break conversionSwitch;
case 2:
/* the source has a variable-length encoding but the new StringView has a fixed-length encoding... */
/* mapping... */
nStartIdx = 0;
var nChrCode;
for (nChrIdx = 0; nChrIdx < nCharStart; nChrIdx++) {
nChrCode = fGetInptChrCode(vSource, nStartIdx);
nStartIdx += fGetInptChrSize(nChrCode);
}
aWhole = new fTAView(nOutptLen);
/* transcription of the source... */
for (var nInptIdx = nStartIdx, nOutptIdx = 0; nOutptIdx < nOutptLen; nInptIdx += fGetInptChrSize(nChrCode), nOutptIdx++) {
nChrCode = fGetInptChrCode(vSource, nInptIdx);
aWhole[nOutptIdx] = nChrCode;
}
break conversionSwitch;
case 3:
/* both the source and the new StringView have a variable-length encoding... */
/* mapping... */
nOutptLen = 0;
var nChrCode;
for (var nChrIdx = 0, nInptIdx = 0; nChrIdx < nCharEnd; nInptIdx += fGetInptChrSize(nChrCode)) {
nChrCode = fGetInptChrCode(vSource, nInptIdx);
if (nChrIdx === nCharStart) { nStartIdx = nInptIdx; }
if (++nChrIdx > nCharStart) { nOutptLen += fGetOutptChrSize(nChrCode); }
}
aWhole = new fTAView(nOutptLen);
/* transcription... */
for (var nInptIdx = nStartIdx, nOutptIdx = 0; nOutptIdx < nOutptLen; nInptIdx += fGetInptChrSize(nChrCode)) {
nChrCode = fGetInptChrCode(vSource, nInptIdx);
nOutptIdx = fPutOutptCode(aWhole, nChrCode, nOutptIdx);
}
break conversionSwitch;
case 4:
/* DOMString to ASCII or BinaryString or other unknown encodings */
aWhole = new fTAView(nOutptLen);
/* transcription... */
for (var nIdx = 0; nIdx < nOutptLen; nIdx++) {
aWhole[nIdx] = vSource.charCodeAt(nIdx) & 0xff;
}
break conversionSwitch;
case 5:
/* DOMString to UTF-8 or to UTF-16 */
/* mapping... */
nOutptLen = 0;
for (var nMapIdx = 0; nMapIdx < nInptLen; nMapIdx++) {
if (nMapIdx === nCharStart) { nStartIdx = nOutptLen; }
nOutptLen += fGetOutptChrSize(vSource.charCodeAt(nMapIdx));
if (nMapIdx === nCharEnd) { nEndIdx = nOutptLen; }
}
aWhole = new fTAView(nOutptLen);
/* transcription... */
for (var nOutptIdx = 0, nChrIdx = 0; nOutptIdx < nOutptLen; nChrIdx++) {
nOutptIdx = fPutOutptCode(aWhole, vSource.charCodeAt(nChrIdx), nOutptIdx);
}
break conversionSwitch;
case 6:
/* DOMString to UTF-32 */
aWhole = new fTAView(nOutptLen);
/* transcription... */
for (var nIdx = 0; nIdx < nOutptLen; nIdx++) {
aWhole[nIdx] = vSource.charCodeAt(nIdx);
}
break conversionSwitch;
case 7:
aWhole = new fTAView(nOutptLen ? vSource : 0);
break conversionSwitch;
}
aRaw = nTranscrType > 3 && (nStartIdx > 0 || nEndIdx < aWhole.length - 1) ? aWhole.subarray(nStartIdx, nEndIdx) : aWhole;
}
this.buffer = aWhole.buffer;
this.bufferView = aWhole;
this.rawData = aRaw;
Object.freeze(this);
}
/* CONSTRUCTOR'S METHODS */
StringView.loadUTF8CharCode = function (aChars, nIdx) {
var nLen = aChars.length, nPart = aChars[nIdx];
return nPart > 251 && nPart < 254 && nIdx + 5 < nLen ?
/* (nPart - 252 << 30) may be not safe in ECMAScript! So...: */
/* six bytes */ (nPart - 252) * 1073741824 + (aChars[nIdx + 1] - 128 << 24) + (aChars[nIdx + 2] - 128 << 18) + (aChars[nIdx + 3] - 128 << 12) + (aChars[nIdx + 4] - 128 << 6) + aChars[nIdx + 5] - 128
: nPart > 247 && nPart < 252 && nIdx + 4 < nLen ?
/* five bytes */ (nPart - 248 << 24) + (aChars[nIdx + 1] - 128 << 18) + (aChars[nIdx + 2] - 128 << 12) + (aChars[nIdx + 3] - 128 << 6) + aChars[nIdx + 4] - 128
: nPart > 239 && nPart < 248 && nIdx + 3 < nLen ?
/* four bytes */(nPart - 240 << 18) + (aChars[nIdx + 1] - 128 << 12) + (aChars[nIdx + 2] - 128 << 6) + aChars[nIdx + 3] - 128
: nPart > 223 && nPart < 240 && nIdx + 2 < nLen ?
/* three bytes */ (nPart - 224 << 12) + (aChars[nIdx + 1] - 128 << 6) + aChars[nIdx + 2] - 128
: nPart > 191 && nPart < 224 && nIdx + 1 < nLen ?
/* two bytes */ (nPart - 192 << 6) + aChars[nIdx + 1] - 128
:
/* one byte */ nPart;
};
StringView.putUTF8CharCode = function (aTarget, nChar, nPutAt) {
var nIdx = nPutAt;
if (nChar < 0x80 /* 128 */) {
/* one byte */
aTarget[nIdx++] = nChar;
} else if (nChar < 0x800 /* 2048 */) {
/* two bytes */
aTarget[nIdx++] = 0xc0 /* 192 */ + (nChar >>> 6);
aTarget[nIdx++] = 0x80 /* 128 */ + (nChar & 0x3f /* 63 */);
} else if (nChar < 0x10000 /* 65536 */) {
/* three bytes */
aTarget[nIdx++] = 0xe0 /* 224 */ + (nChar >>> 12);
aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 6) & 0x3f /* 63 */);
aTarget[nIdx++] = 0x80 /* 128 */ + (nChar & 0x3f /* 63 */);
} else if (nChar < 0x200000 /* 2097152 */) {
/* four bytes */
aTarget[nIdx++] = 0xf0 /* 240 */ + (nChar >>> 18);
aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 12) & 0x3f /* 63 */);
aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 6) & 0x3f /* 63 */);
aTarget[nIdx++] = 0x80 /* 128 */ + (nChar & 0x3f /* 63 */);
} else if (nChar < 0x4000000 /* 67108864 */) {
/* five bytes */
aTarget[nIdx++] = 0xf8 /* 248 */ + (nChar >>> 24);
aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 18) & 0x3f /* 63 */);
aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 12) & 0x3f /* 63 */);
aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 6) & 0x3f /* 63 */);
aTarget[nIdx++] = 0x80 /* 128 */ + (nChar & 0x3f /* 63 */);
} else /* if (nChar <= 0x7fffffff) */ { /* 2147483647 */
/* six bytes */
aTarget[nIdx++] = 0xfc /* 252 */ + /* (nChar >>> 30) may be not safe in ECMAScript! So...: */ (nChar / 1073741824);
aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 24) & 0x3f /* 63 */);
aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 18) & 0x3f /* 63 */);
aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 12) & 0x3f /* 63 */);
aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 6) & 0x3f /* 63 */);
aTarget[nIdx++] = 0x80 /* 128 */ + (nChar & 0x3f /* 63 */);
}
return nIdx;
};
StringView.getUTF8CharLength = function (nChar) {
return nChar < 0x80 ? 1 : nChar < 0x800 ? 2 : nChar < 0x10000 ? 3 : nChar < 0x200000 ? 4 : nChar < 0x4000000 ? 5 : 6;
};
StringView.loadUTF16CharCode = function (aChars, nIdx) {
/* UTF-16 to DOMString decoding algorithm */
var nFrstChr = aChars[nIdx];
return nFrstChr > 0xD7BF /* 55231 */ && nIdx + 1 < aChars.length ?
(nFrstChr - 0xD800 /* 55296 */ << 10) + aChars[nIdx + 1] + 0x2400 /* 9216 */
: nFrstChr;
};
StringView.putUTF16CharCode = function (aTarget, nChar, nPutAt) {
var nIdx = nPutAt;
if (nChar < 0x10000 /* 65536 */) {
/* one element */
aTarget[nIdx++] = nChar;
} else {
/* two elements */
aTarget[nIdx++] = 0xD7C0 /* 55232 */ + (nChar >>> 10);
aTarget[nIdx++] = 0xDC00 /* 56320 */ + (nChar & 0x3FF /* 1023 */);
}
return nIdx;
};
StringView.getUTF16CharLength = function (nChar) {
return nChar < 0x10000 ? 1 : 2;
};
/* Array of bytes to base64 string decoding */
StringView.b64ToUint6 = function (nChr) {
return nChr > 64 && nChr < 91 ?
nChr - 65
: nChr > 96 && nChr < 123 ?
nChr - 71
: nChr > 47 && nChr < 58 ?
nChr + 4
: nChr === 43 ?
62
: nChr === 47 ?
63
:
0;
};
StringView.uint6ToB64 = function (nUint6) {
return nUint6 < 26 ?
nUint6 + 65
: nUint6 < 52 ?
nUint6 + 71
: nUint6 < 62 ?
nUint6 - 4
: nUint6 === 62 ?
43
: nUint6 === 63 ?
47
:
65;
};
/* Base64 string to array encoding */
StringView.bytesToBase64 = function (aBytes) {
var eqLen = (3 - (aBytes.length % 3)) % 3, sB64Enc = "";
for (var nMod3, nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) {
nMod3 = nIdx % 3;
/* Uncomment the following line in order to split the output in lines 76-character long: */
/*
if (nIdx > 0 && (nIdx * 4 / 3) % 76 === 0) { sB64Enc += "\r\n"; }
*/
nUint24 |= aBytes[nIdx] << (16 >>> nMod3 & 24);
if (nMod3 === 2 || aBytes.length - nIdx === 1) {
sB64Enc += String.fromCharCode(StringView.uint6ToB64(nUint24 >>> 18 & 63), StringView.uint6ToB64(nUint24 >>> 12 & 63), StringView.uint6ToB64(nUint24 >>> 6 & 63), StringView.uint6ToB64(nUint24 & 63));
nUint24 = 0;
}
}
return eqLen === 0 ?
sB64Enc
:
sB64Enc.substring(0, sB64Enc.length - eqLen) + (eqLen === 1 ? "=" : "==");
};
StringView.base64ToBytes = function (sBase64, nBlockBytes) {
var
sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, ""), nInLen = sB64Enc.length,
nOutLen = nBlockBytes ? Math.ceil((nInLen * 3 + 1 >>> 2) / nBlockBytes) * nBlockBytes : nInLen * 3 + 1 >>> 2, aBytes = new Uint8Array(nOutLen);
for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) {
nMod4 = nInIdx & 3;
nUint24 |= StringView.b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 18 - 6 * nMod4;
if (nMod4 === 3 || nInLen - nInIdx === 1) {
for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) {
aBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255;
}
nUint24 = 0;
}
}
return aBytes;
};
StringView.makeFromBase64 = function (sB64Inpt, sEncoding, nByteOffset, nLength) {
return new StringView(sEncoding === "UTF-16" || sEncoding === "UTF-32" ? StringView.base64ToBytes(sB64Inpt, sEncoding === "UTF-16" ? 2 : 4).buffer : StringView.base64ToBytes(sB64Inpt), sEncoding, nByteOffset, nLength);
};
/* DEFAULT VALUES */
StringView.prototype.encoding = "UTF-8"; /* Default encoding... */
/* INSTANCES' METHODS */
StringView.prototype.makeIndex = function (nChrLength, nStartFrom) {
var
aTarget = this.rawData, nChrEnd, nRawLength = aTarget.length,
nStartIdx = nStartFrom || 0, nIdxEnd = nStartIdx, nStopAtChr = isNaN(nChrLength) ? Infinity : nChrLength;
if (nChrLength + 1 > aTarget.length) { throw new RangeError("StringView.prototype.makeIndex - The offset can\'t be major than the length of the array - 1."); }
switch (this.encoding) {
case "UTF-8":
var nPart;
for (nChrEnd = 0; nIdxEnd < nRawLength && nChrEnd < nStopAtChr; nChrEnd++) {
nPart = aTarget[nIdxEnd];
nIdxEnd += nPart > 251 && nPart < 254 && nIdxEnd + 5 < nRawLength ? 6
: nPart > 247 && nPart < 252 && nIdxEnd + 4 < nRawLength ? 5
: nPart > 239 && nPart < 248 && nIdxEnd + 3 < nRawLength ? 4
: nPart > 223 && nPart < 240 && nIdxEnd + 2 < nRawLength ? 3
: nPart > 191 && nPart < 224 && nIdxEnd + 1 < nRawLength ? 2
: 1;
}
break;
case "UTF-16":
for (nChrEnd = nStartIdx; nIdxEnd < nRawLength && nChrEnd < nStopAtChr; nChrEnd++) {
nIdxEnd += aTarget[nIdxEnd] > 0xD7BF /* 55231 */ && nIdxEnd + 1 < aTarget.length ? 2 : 1;
}
break;
default:
nIdxEnd = nChrEnd = isFinite(nChrLength) ? nChrLength : nRawLength - 1;
}
if (nChrLength) { return nIdxEnd; }
return nChrEnd;
};
StringView.prototype.toBase64 = function (bWholeBuffer) {
return StringView.bytesToBase64(
bWholeBuffer ?
(
this.bufferView.constructor === Uint8Array ?
this.bufferView
:
new Uint8Array(this.buffer)
)
: this.rawData.constructor === Uint8Array ?
this.rawData
:
new Uint8Array(this.buffer, this.rawData.byteOffset, this.rawData.length << (this.rawData.constructor === Uint16Array ? 1 : 2))
);
};
StringView.prototype.subview = function (nCharOffset /* optional */, nCharLength /* optional */) {
var
nChrLen, nCharStart, nStrLen, bVariableLen = this.encoding === "UTF-8" || this.encoding === "UTF-16",
nStartOffset = nCharOffset, nStringLength, nRawLen = this.rawData.length;
if (nRawLen === 0) {
return new StringView(this.buffer, this.encoding);
}
nStringLength = bVariableLen ? this.makeIndex() : nRawLen;
nCharStart = nCharOffset ? Math.max((nStringLength + nCharOffset) % nStringLength, 0) : 0;
nStrLen = Number.isInteger(nCharLength) ? Math.max(nCharLength, 0) + nCharStart > nStringLength ? nStringLength - nCharStart : nCharLength : nStringLength;
if (nCharStart === 0 && nStrLen === nStringLength) { return this; }
if (bVariableLen) {
nStartOffset = this.makeIndex(nCharStart);
nChrLen = this.makeIndex(nStrLen, nStartOffset) - nStartOffset;
} else {
nStartOffset = nCharStart;
nChrLen = nStrLen - nCharStart;
}
if (this.encoding === "UTF-16") {
nStartOffset <<= 1;
} else if (this.encoding === "UTF-32") {
nStartOffset <<= 2;
}
return new StringView(this.buffer, this.encoding, nStartOffset, nChrLen);
};
StringView.prototype.forEachChar = function (fCallback, oThat, nChrOffset, nChrLen) {
var aSource = this.rawData, nRawEnd, nRawIdx;
if (this.encoding === "UTF-8" || this.encoding === "UTF-16") {
var fGetInptChrSize, fGetInptChrCode;
if (this.encoding === "UTF-8") {
fGetInptChrSize = StringView.getUTF8CharLength;
fGetInptChrCode = StringView.loadUTF8CharCode;
} else if (this.encoding === "UTF-16") {
fGetInptChrSize = StringView.getUTF16CharLength;
fGetInptChrCode = StringView.loadUTF16CharCode;
}
nRawIdx = isFinite(nChrOffset) ? this.makeIndex(nChrOffset) : 0;
nRawEnd = isFinite(nChrLen) ? this.makeIndex(nChrLen, nRawIdx) : aSource.length;
for (var nChrCode, nChrIdx = 0; nRawIdx < nRawEnd; nChrIdx++) {
nChrCode = fGetInptChrCode(aSource, nRawIdx);
fCallback.call(oThat || null, nChrCode, nChrIdx, nRawIdx, aSource);
nRawIdx += fGetInptChrSize(nChrCode);
}
} else {
nRawIdx = isFinite(nChrOffset) ? nChrOffset : 0;
nRawEnd = isFinite(nChrLen) ? nChrLen + nRawIdx : aSource.length;
for (nRawIdx; nRawIdx < nRawEnd; nRawIdx++) {
fCallback.call(oThat || null, aSource[nRawIdx], nRawIdx, nRawIdx, aSource);
}
}
};
StringView.prototype.valueOf = StringView.prototype.toString = function () {
if (this.encoding !== "UTF-8" && this.encoding !== "UTF-16") {
/* ASCII, UTF-32 or BinaryString to DOMString */
return String.fromCharCode.apply(null, this.rawData);
}
var fGetCode, fGetIncr, sView = "";
if (this.encoding === "UTF-8") {
fGetIncr = StringView.getUTF8CharLength;
fGetCode = StringView.loadUTF8CharCode;
} else if (this.encoding === "UTF-16") {
fGetIncr = StringView.getUTF16CharLength;
fGetCode = StringView.loadUTF16CharCode;
}
for (var nChr, nLen = this.rawData.length, nIdx = 0; nIdx < nLen; nIdx += fGetIncr(nChr)) {
nChr = fGetCode(this.rawData, nIdx);
sView += String.fromCharCode(nChr);
}
return sView;
};

View File

@ -1,14 +1,14 @@
"use strict";
var kStaticFiles = [
{uri: '', path: 'index.html', type: 'text/html; charset=utf-8'},
{uri: '/edit', path: 'edit.html', type: 'text/html; charset=utf-8'},
{uri: '/style.css', path: 'style.css', type: 'text/css; charset=utf-8'},
{uri: '', path: 'index.html', type: 'text/html; charset=UTF-8'},
{uri: '/edit', path: 'edit.html', type: 'text/html; charset=UTF-8'},
{uri: '/style.css', path: 'style.css', type: 'text/css; charset=UTF-8'},
{uri: '/favicon.png', path: 'favicon.png', type: 'image/png'},
{uri: '/client.js', path: 'client.js', type: 'text/javascript; charset=utf-8'},
{uri: '/editor.js', path: 'editor.js', type: 'text/javascript; charset=utf-8'},
{uri: '/client.js', path: 'client.js', type: 'text/javascript; charset=UTF-8'},
{uri: '/editor.js', path: 'editor.js', type: 'text/javascript; charset=UTF-8'},
{uri: '/agplv3-88x31.png', path: 'agplv3-88x31.png', type: 'image/png'},
{uri: '/robots.txt', path: 'robots.txt', type: 'text/plain; charset=utf-8'},
{uri: '/robots.txt', path: 'robots.txt', type: 'text/plain; charset=UTF-8'},
];
var auth = require('auth');
@ -240,7 +240,7 @@ function handler(request, response, packageOwner, packageName, uri) {
for (var i in kStaticFiles) {
if (uri === kStaticFiles[i].uri) {
found = true;
var data = File.readFile("core/" + kStaticFiles[i].path);
var data = new TextDecoder("UTF-8").decode(File.readFile("core/" + kStaticFiles[i].path));
if (kStaticFiles[i].uri == "") {
if (gGlobalSettings && gGlobalSettings['google-signin-client_id']) {
data = data.replace("<!--HEAD-->", `
@ -250,14 +250,15 @@ function handler(request, response, packageOwner, packageName, uri) {
data = data.replace("$(VIEW_SOURCE)", "/~" + packageOwner + "/" + packageName + "/view");
data = data.replace("$(EDIT_SOURCE)", "/~" + packageOwner + "/" + packageName + "/edit");
} else if (kStaticFiles[i].uri == "/edit") {
var source = File.readFile("packages/" + packageOwner + "/" + packageName + "/" + packageName + ".js") || "";
var source = new TextDecoder("UTF-8").decode(File.readFile("packages/" + packageOwner + "/" + packageName + "/" + packageName + ".js")) || "";
source = source.replace(/([&<>"])/g, function(x, item) {
return {'&': '&amp;', '"': '&quot;', '<': '&lt;', '>': '&gt;'}[item];
});
data = data.replace("$(SOURCE)", source);
}
response.writeHead(200, {"Content-Type": kStaticFiles[i].type, "Content-Length": data.length});
response.end(data);
var raw = new TextEncoder("UTF-8").encode(data);
response.writeHead(200, {"Content-Type": kStaticFiles[i].type, "Content-Length": raw.length});
response.end(raw);
break;
}
}
@ -266,7 +267,7 @@ function handler(request, response, packageOwner, packageName, uri) {
if (!found) {
var process;
if (uri === "/view") {
var data = File.readFile("packages/" + packageOwner + "/" + packageName + "/" + packageName + ".js");
var data = new TextDecode("UTF-8").decode(File.readFile("packages/" + packageOwner + "/" + packageName + "/" + packageName + ".js"));
response.writeHead(200, {"Content-Type": "text/javascript; charset=utf-8", "Content-Length": data.length});
response.end(data);
} else if (uri == "/save") {

View File

@ -34,34 +34,41 @@ void File::readFile(const v8::FunctionCallbackInfo<v8::Value>& args) {
std::streampos fileSize = file.tellg();
if (fileSize >= 0 && fileSize < 4 * 1024 * 1024) {
file.seekg(0, std::ios_base::beg);
char* buffer = new char[fileSize];
file.read(buffer, fileSize);
std::string contents(buffer, buffer + fileSize);
args.GetReturnValue().Set(v8::String::NewFromOneByte(args.GetIsolate(), reinterpret_cast<const uint8_t*>(buffer), v8::String::kNormalString, fileSize));
delete[] buffer;
v8::Handle<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(args.GetIsolate(), fileSize);
file.read(reinterpret_cast<char*>(buffer->GetContents().Data()), fileSize);
v8::Handle<v8::Uint8Array> array = v8::Uint8Array::New(buffer, 0, fileSize);
args.GetReturnValue().Set(array);
}
}
void File::writeFile(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::HandleScope scope(args.GetIsolate());
v8::Handle<v8::String> fileName = args[0]->ToString();
v8::Handle<v8::String> contents = args[1]->ToString();
v8::Handle<v8::Value> value = args[1];
v8::String::Utf8Value utf8FileName(fileName);
std::ofstream file(*utf8FileName, std::ios_base::out | std::ios_base::binary);
if (contents->ContainsOnlyOneByte()) {
std::vector<uint8_t> bytes(contents->Length());
contents->WriteOneByte(bytes.data(), 0, bytes.size(), v8::String::NO_NULL_TERMINATION);
if (value->IsArrayBufferView()) {
v8::Handle<v8::ArrayBufferView> array = v8::Handle<v8::ArrayBufferView>::Cast(value);
if (!file.write(reinterpret_cast<const char*>(array->Buffer()->GetContents().Data()), array->Buffer()->GetContents().ByteLength())) {
args.GetReturnValue().Set(v8::Integer::New(args.GetIsolate(), -1));
}
} else if (value->IsString()) {
v8::Handle<v8::String> stringValue = v8::Handle<v8::String>::Cast(value);
if (stringValue->ContainsOnlyOneByte()) {
std::vector<uint8_t> bytes(stringValue->Length());
stringValue->WriteOneByte(bytes.data(), 0, bytes.size(), v8::String::NO_NULL_TERMINATION);
if (!file.write(reinterpret_cast<const char*>(bytes.data()), bytes.size())) {
args.GetReturnValue().Set(v8::Integer::New(args.GetIsolate(), -1));
}
} else {
v8::String::Utf8Value utf8Contents(contents);
v8::String::Utf8Value utf8Contents(stringValue);
if (!file.write(*utf8Contents, utf8Contents.length())) {
args.GetReturnValue().Set(v8::Integer::New(args.GetIsolate(), -1));
}
}
}
}
void File::renameFile(const v8::FunctionCallbackInfo<v8::Value>& args) {

View File

@ -146,7 +146,7 @@ v8::Handle<v8::String> Task::loadFile(v8::Isolate* isolate, const char* fileName
char* buffer = new char[fileSize];
file.read(buffer, fileSize);
std::string contents(buffer, buffer + fileSize);
value = v8::String::NewFromOneByte(isolate, reinterpret_cast<const uint8_t*>(buffer), v8::String::kNormalString, fileSize);
value = v8::String::NewFromUtf8(isolate, buffer, v8::String::kNormalString, fileSize);
delete[] buffer;
}
return value;