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') {
|
||||
// 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"
|
||||
"0123456789+/";
|
||||
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,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
|
||||
,-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
|
||||
,-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
|
||||
};
|
||||
#define unbase64(x) unbase64_table[(int)(x)]
|
||||
|
||||
|
||||
Handle<Value> Buffer::Base64Slice(const Arguments &args) {
|
||||
@ -436,16 +437,21 @@ Handle<Value> Buffer::AsciiWrite(const Arguments &args) {
|
||||
return scope.Close(Integer::New(written));
|
||||
}
|
||||
|
||||
|
||||
// var bytesWritten = buffer.base64Write(string, offset, [maxLength]);
|
||||
Handle<Value> Buffer::Base64Write(const Arguments &args) {
|
||||
HandleScope scope;
|
||||
|
||||
assert(unbase64_table[(int)'/'] == 63);
|
||||
assert(unbase64_table[(int)'+'] == 62);
|
||||
assert(unbase64_table[(int)'T'] == 19);
|
||||
assert(unbase64_table[(int)'Z'] == 25);
|
||||
assert(unbase64_table[(int)'t'] == 45);
|
||||
assert(unbase64_table[(int)'z'] == 51);
|
||||
assert(unbase64('/') == 63);
|
||||
assert(unbase64('+') == 62);
|
||||
assert(unbase64('T') == 19);
|
||||
assert(unbase64('Z') == 25);
|
||||
assert(unbase64('t') == 45);
|
||||
assert(unbase64('z') == 51);
|
||||
|
||||
assert(unbase64(' ') == -2);
|
||||
assert(unbase64('\n') == -2);
|
||||
assert(unbase64('\r') == -2);
|
||||
|
||||
Buffer *buffer = ObjectWrap::Unwrap<Buffer>(args.This());
|
||||
|
||||
@ -475,29 +481,47 @@ Handle<Value> Buffer::Base64Write(const Arguments &args) {
|
||||
}
|
||||
|
||||
char a, b, c, d;
|
||||
char* dst = buffer->data_ + offset;
|
||||
char* start = buffer->data_ + offset;
|
||||
char* dst = start;
|
||||
const char *src = *s;
|
||||
const char *const srcEnd = src + s.length();
|
||||
|
||||
while (src < srcEnd) {
|
||||
const int remaining = srcEnd - src;
|
||||
if (remaining == 0 || *src == '=') break;
|
||||
a = unbase64_table[(int)*src++];
|
||||
int remaining = srcEnd - src;
|
||||
|
||||
if (remaining == 1 || *src == '=') break;
|
||||
b = unbase64_table[(int)*src++];
|
||||
while (unbase64(*src) < 0 && src < srcEnd) {
|
||||
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);
|
||||
|
||||
if (remaining == 2 || *src == '=') break;
|
||||
c = unbase64_table[(int)*src++];
|
||||
while (unbase64(*src) < 0 && src < srcEnd) {
|
||||
src++;
|
||||
remaining--;
|
||||
}
|
||||
if (remaining <= 2 || *src == '=') break;
|
||||
c = unbase64(*src++);
|
||||
*dst++ = ((b & 0x0F) << 4) | ((c & 0x3C) >> 2);
|
||||
|
||||
if (remaining == 3 || *src == '=') break;
|
||||
d = unbase64_table[(int)*src++];
|
||||
while (unbase64(*src) < 0 && src < srcEnd) {
|
||||
src++;
|
||||
remaining--;
|
||||
}
|
||||
if (remaining <= 3 || *src == '=') break;
|
||||
d = unbase64(*src++);
|
||||
*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, 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('K', 'base64').toString(), '');
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user