base64 decode should handle whitespace
This commit is contained in:
parent
ccf2a04ea2
commit
cf1db4f304
@ -145,7 +145,7 @@ function Buffer (subject, encoding, offset) {
|
|||||||
}
|
}
|
||||||
} else if (type == 'string') {
|
} else if (type == 'string') {
|
||||||
// We are a string
|
// We are a string
|
||||||
this.write(subject, 0, encoding);
|
this.length = this.write(subject, 0, encoding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,15 +222,16 @@ static const char *base64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|||||||
"abcdefghijklmnopqrstuvwxyz"
|
"abcdefghijklmnopqrstuvwxyz"
|
||||||
"0123456789+/";
|
"0123456789+/";
|
||||||
static const int unbase64_table[] =
|
static const int unbase64_table[] =
|
||||||
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1
|
||||||
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
||||||
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63
|
,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63
|
||||||
,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1
|
,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1
|
||||||
,-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14
|
,-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14
|
||||||
,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1
|
,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1
|
||||||
,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40
|
,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40
|
||||||
,41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1
|
,41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1
|
||||||
};
|
};
|
||||||
|
#define unbase64(x) unbase64_table[(int)(x)]
|
||||||
|
|
||||||
|
|
||||||
Handle<Value> Buffer::Base64Slice(const Arguments &args) {
|
Handle<Value> Buffer::Base64Slice(const Arguments &args) {
|
||||||
@ -436,16 +437,21 @@ Handle<Value> Buffer::AsciiWrite(const Arguments &args) {
|
|||||||
return scope.Close(Integer::New(written));
|
return scope.Close(Integer::New(written));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// var bytesWritten = buffer.base64Write(string, offset, [maxLength]);
|
// var bytesWritten = buffer.base64Write(string, offset, [maxLength]);
|
||||||
Handle<Value> Buffer::Base64Write(const Arguments &args) {
|
Handle<Value> Buffer::Base64Write(const Arguments &args) {
|
||||||
HandleScope scope;
|
HandleScope scope;
|
||||||
|
|
||||||
assert(unbase64_table[(int)'/'] == 63);
|
assert(unbase64('/') == 63);
|
||||||
assert(unbase64_table[(int)'+'] == 62);
|
assert(unbase64('+') == 62);
|
||||||
assert(unbase64_table[(int)'T'] == 19);
|
assert(unbase64('T') == 19);
|
||||||
assert(unbase64_table[(int)'Z'] == 25);
|
assert(unbase64('Z') == 25);
|
||||||
assert(unbase64_table[(int)'t'] == 45);
|
assert(unbase64('t') == 45);
|
||||||
assert(unbase64_table[(int)'z'] == 51);
|
assert(unbase64('z') == 51);
|
||||||
|
|
||||||
|
assert(unbase64(' ') == -2);
|
||||||
|
assert(unbase64('\n') == -2);
|
||||||
|
assert(unbase64('\r') == -2);
|
||||||
|
|
||||||
Buffer *buffer = ObjectWrap::Unwrap<Buffer>(args.This());
|
Buffer *buffer = ObjectWrap::Unwrap<Buffer>(args.This());
|
||||||
|
|
||||||
@ -475,29 +481,47 @@ Handle<Value> Buffer::Base64Write(const Arguments &args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
char a, b, c, d;
|
char a, b, c, d;
|
||||||
char* dst = buffer->data_ + offset;
|
char* start = buffer->data_ + offset;
|
||||||
|
char* dst = start;
|
||||||
const char *src = *s;
|
const char *src = *s;
|
||||||
const char *const srcEnd = src + s.length();
|
const char *const srcEnd = src + s.length();
|
||||||
|
|
||||||
while (src < srcEnd) {
|
while (src < srcEnd) {
|
||||||
const int remaining = srcEnd - src;
|
int remaining = srcEnd - src;
|
||||||
if (remaining == 0 || *src == '=') break;
|
|
||||||
a = unbase64_table[(int)*src++];
|
|
||||||
|
|
||||||
if (remaining == 1 || *src == '=') break;
|
while (unbase64(*src) < 0 && src < srcEnd) {
|
||||||
b = unbase64_table[(int)*src++];
|
src++;
|
||||||
|
remaining--;
|
||||||
|
}
|
||||||
|
if (remaining == 0 || *src == '=') break;
|
||||||
|
a = unbase64(*src++);
|
||||||
|
|
||||||
|
while (unbase64(*src) < 0 && src < srcEnd) {
|
||||||
|
src++;
|
||||||
|
remaining--;
|
||||||
|
}
|
||||||
|
if (remaining <= 1 || *src == '=') break;
|
||||||
|
b = unbase64(*src++);
|
||||||
*dst++ = (a << 2) | ((b & 0x30) >> 4);
|
*dst++ = (a << 2) | ((b & 0x30) >> 4);
|
||||||
|
|
||||||
if (remaining == 2 || *src == '=') break;
|
while (unbase64(*src) < 0 && src < srcEnd) {
|
||||||
c = unbase64_table[(int)*src++];
|
src++;
|
||||||
|
remaining--;
|
||||||
|
}
|
||||||
|
if (remaining <= 2 || *src == '=') break;
|
||||||
|
c = unbase64(*src++);
|
||||||
*dst++ = ((b & 0x0F) << 4) | ((c & 0x3C) >> 2);
|
*dst++ = ((b & 0x0F) << 4) | ((c & 0x3C) >> 2);
|
||||||
|
|
||||||
if (remaining == 3 || *src == '=') break;
|
while (unbase64(*src) < 0 && src < srcEnd) {
|
||||||
d = unbase64_table[(int)*src++];
|
src++;
|
||||||
|
remaining--;
|
||||||
|
}
|
||||||
|
if (remaining <= 3 || *src == '=') break;
|
||||||
|
d = unbase64(*src++);
|
||||||
*dst++ = ((c & 0x03) << 6) | (d & 0x3F);
|
*dst++ = ((c & 0x03) << 6) | (d & 0x3F);
|
||||||
}
|
}
|
||||||
|
|
||||||
return scope.Close(Integer::New(size));
|
return scope.Close(Integer::New(dst - start));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -238,6 +238,25 @@ bytesWritten = b.write(expected, 0, 'base64');
|
|||||||
assert.equal(quote.length, bytesWritten);
|
assert.equal(quote.length, bytesWritten);
|
||||||
assert.equal(quote, b.toString('ascii', 0, quote.length));
|
assert.equal(quote, b.toString('ascii', 0, quote.length));
|
||||||
|
|
||||||
|
// check that the base64 decoder ignores whitespace
|
||||||
|
var expectedWhite = expected.slice(0, 60) + " \n" +
|
||||||
|
expected.slice(60, 120) + " \n" +
|
||||||
|
expected.slice(120, 180) + " \n" +
|
||||||
|
expected.slice(180, 240) + " \n" +
|
||||||
|
expected.slice(240, 300) + "\n" +
|
||||||
|
expected.slice(300, 360) + "\n";
|
||||||
|
b = new Buffer(1024);
|
||||||
|
bytesWritten = b.write(expectedWhite, 0, 'base64');
|
||||||
|
assert.equal(quote.length, bytesWritten);
|
||||||
|
assert.equal(quote, b.toString('ascii', 0, quote.length));
|
||||||
|
|
||||||
|
// check that the base64 decoder on the constructor works
|
||||||
|
// even in the presence of whitespace.
|
||||||
|
b = new Buffer(expectedWhite, 'base64');
|
||||||
|
assert.equal(quote.length, b.length);
|
||||||
|
assert.equal(quote, b.toString('ascii', 0, quote.length));
|
||||||
|
|
||||||
|
|
||||||
assert.equal(new Buffer('', 'base64').toString(), '');
|
assert.equal(new Buffer('', 'base64').toString(), '');
|
||||||
assert.equal(new Buffer('K', 'base64').toString(), '');
|
assert.equal(new Buffer('K', 'base64').toString(), '');
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user