| Differences between
and this patch
- WebCore/ChangeLog +23 lines
Lines 1-3 WebCore/ChangeLog_sec1
1
2010-09-08  Patrick Gansterer  <paroga@paroga.com>
2
3
        Reviewed by Darin Adler.
4
5
        Add Base64DecodePolicy option at base64Decode()
6
        https://bugs.webkit.org/show_bug.cgi?id=41510
7
8
        Add an option for ignoring characters in base64 data.
9
        This is necessary for decoding data urls.
10
11
        Also add an overload to decode WebCore::String directly.
12
13
        * page/DOMWindow.cpp:
14
        (WebCore::DOMWindow::atob):
15
        * page/Page.cpp:
16
        (WebCore::Page::userStyleSheetLocationChanged):
17
        * platform/text/Base64.cpp:
18
        (WebCore::base64Encode):
19
        (WebCore::base64Decode):
20
        (WebCore::base64DecodeInternal):
21
        * platform/text/Base64.h:
22
        (WebCore::):
23
1
2010-09-08  Andy Estes  <aestes@apple.com>
24
2010-09-08  Andy Estes  <aestes@apple.com>
2
25
3
        Rubber-stamped by Darin Adler.
26
        Rubber-stamped by Darin Adler.
- WebCore/page/DOMWindow.cpp -4 / +1 lines
Lines 994-1004 String DOMWindow::atob(const String& enc WebCore/page/DOMWindow.cpp_sec1
994
        return String();
994
        return String();
995
    }
995
    }
996
996
997
    Vector<char> in;
998
    in.append(encodedString.characters(), encodedString.length());
999
    Vector<char> out;
997
    Vector<char> out;
1000
998
    if (!base64Decode(encodedString, out, FailOnInvalidCharacter)) {
1001
    if (!base64Decode(in, out)) {
1002
        ec = INVALID_CHARACTER_ERR;
999
        ec = INVALID_CHARACTER_ERR;
1003
        return String();
1000
        return String();
1004
    }
1001
    }
- WebCore/page/Page.cpp -8 / +3 lines
Lines 621-642 void Page::userStyleSheetLocationChanged WebCore/page/Page.cpp_sec1
621
    m_didLoadUserStyleSheet = false;
621
    m_didLoadUserStyleSheet = false;
622
    m_userStyleSheet = String();
622
    m_userStyleSheet = String();
623
    m_userStyleSheetModificationTime = 0;
623
    m_userStyleSheetModificationTime = 0;
624
    
624
625
    // Data URLs with base64-encoded UTF-8 style sheets are common. We can process them
625
    // Data URLs with base64-encoded UTF-8 style sheets are common. We can process them
626
    // synchronously and avoid using a loader. 
626
    // synchronously and avoid using a loader. 
627
    if (url.protocolIs("data") && url.string().startsWith("data:text/css;charset=utf-8;base64,")) {
627
    if (url.protocolIs("data") && url.string().startsWith("data:text/css;charset=utf-8;base64,")) {
628
        m_didLoadUserStyleSheet = true;
628
        m_didLoadUserStyleSheet = true;
629
        
630
        const unsigned prefixLength = 35;
631
        Vector<char> encodedData(url.string().length() - prefixLength);
632
        for (unsigned i = prefixLength; i < url.string().length(); ++i)
633
            encodedData[i - prefixLength] = static_cast<char>(url.string()[i]);
634
629
635
        Vector<char> styleSheetAsUTF8;
630
        Vector<char> styleSheetAsUTF8;
636
        if (base64Decode(encodedData, styleSheetAsUTF8))
631
        if (base64Decode(decodeURLEscapeSequences(url.string().substring(35)), styleSheetAsUTF8, IgnoreWhitespace))
637
            m_userStyleSheet = String::fromUTF8(styleSheetAsUTF8.data(), styleSheetAsUTF8.size());
632
            m_userStyleSheet = String::fromUTF8(styleSheetAsUTF8.data(), styleSheetAsUTF8.size());
638
    }
633
    }
639
    
634
640
    for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
635
    for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
641
        if (frame->document())
636
        if (frame->document())
642
            frame->document()->updatePageUserSheet();
637
            frame->document()->updatePageUserSheet();
- WebCore/platform/text/Base64.cpp -26 / +51 lines
Lines 2-7 WebCore/platform/text/Base64.cpp_sec1
2
   Copyright (C) 2000-2001 Dawit Alemayehu <adawit@kde.org>
2
   Copyright (C) 2000-2001 Dawit Alemayehu <adawit@kde.org>
3
   Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
3
   Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
4
   Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
4
   Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
5
   Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
5
6
6
   This program is free software; you can redistribute it and/or modify
7
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU Lesser General Public License (LGPL)
8
   it under the terms of the GNU Lesser General Public License (LGPL)
Lines 25-30 WebCore/platform/text/Base64.cpp_sec2
25
26
26
#include <limits.h>
27
#include <limits.h>
27
#include <wtf/StringExtras.h>
28
#include <wtf/StringExtras.h>
29
#include <wtf/text/WTFString.h>
28
30
29
namespace WebCore {
31
namespace WebCore {
30
32
Lines 70-76 void base64Encode(const char* data, unsi WebCore/platform/text/Base64.cpp_sec3
70
        return;
72
        return;
71
73
72
    // If the input string is pathologically large, just return nothing.
74
    // If the input string is pathologically large, just return nothing.
73
    // Note: Keep this in sync with the "out_len" computation below.
75
    // Note: Keep this in sync with the "outLength" computation below.
74
    // Rather than being perfectly precise, this is a bit conservative.
76
    // Rather than being perfectly precise, this is a bit conservative.
75
    const unsigned maxInputBufferSize = UINT_MAX / 77 * 76 / 4 * 3 - 2;
77
    const unsigned maxInputBufferSize = UINT_MAX / 77 * 76 / 4 * 3 - 2;
76
    if (len > maxInputBufferSize)
78
    if (len > maxInputBufferSize)
Lines 79-99 void base64Encode(const char* data, unsi WebCore/platform/text/Base64.cpp_sec4
79
    unsigned sidx = 0;
81
    unsigned sidx = 0;
80
    unsigned didx = 0;
82
    unsigned didx = 0;
81
83
82
    unsigned out_len = ((len + 2) / 3) * 4;
84
    unsigned outLength = ((len + 2) / 3) * 4;
83
85
84
    // Deal with the 76 character per line limit specified in RFC 2045.
86
    // Deal with the 76 character per line limit specified in RFC 2045.
85
    insertLFs = (insertLFs && out_len > 76);
87
    insertLFs = (insertLFs && outLength > 76);
86
    if (insertLFs)
88
    if (insertLFs)
87
        out_len += ((out_len - 1) / 76);
89
        outLength += ((outLength - 1) / 76);
88
90
89
    int count = 0;
91
    int count = 0;
90
    out.grow(out_len);
92
    out.grow(outLength);
91
93
92
    // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
94
    // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
93
    if (len > 1) {
95
    if (len > 1) {
94
        while (sidx < len - 2) {
96
        while (sidx < len - 2) {
95
            if (insertLFs) {
97
            if (insertLFs) {
96
                if (count && (count % 76) == 0)
98
                if (count && !(count % 76))
97
                    out[didx++] = '\n';
99
                    out[didx++] = '\n';
98
                count += 4;
100
                count += 4;
99
            }
101
            }
Lines 106-112 void base64Encode(const char* data, unsi WebCore/platform/text/Base64.cpp_sec5
106
    }
108
    }
107
109
108
    if (sidx < len) {
110
    if (sidx < len) {
109
        if (insertLFs && (count > 0) && (count % 76) == 0)
111
        if (insertLFs && (count > 0) && !(count % 76))
110
           out[didx++] = '\n';
112
           out[didx++] = '\n';
111
113
112
        out[didx++] = base64EncMap[(data[sidx] >> 2) & 077];
114
        out[didx++] = base64EncMap[(data[sidx] >> 2) & 077];
Lines 124-130 void base64Encode(const char* data, unsi WebCore/platform/text/Base64.cpp_sec6
124
    }
126
    }
125
}
127
}
126
128
127
bool base64Decode(const Vector<char>& in, Vector<char>& out)
129
bool base64Decode(const Vector<char>& in, Vector<char>& out, Base64DecodePolicy policy)
128
{
130
{
129
    out.clear();
131
    out.clear();
130
132
Lines 132-167 bool base64Decode(const Vector<char>& in WebCore/platform/text/Base64.cpp_sec7
132
    if (in.size() > UINT_MAX)
134
    if (in.size() > UINT_MAX)
133
        return false;
135
        return false;
134
136
135
    return base64Decode(in.data(), in.size(), out);
137
    return base64Decode(in.data(), in.size(), out, policy);
136
}
138
}
137
139
138
bool base64Decode(const char* data, unsigned len, Vector<char>& out)
140
template<typename T>
141
static inline bool base64DecodeInternal(const T* data, unsigned len, Vector<char>& out, Base64DecodePolicy policy)
139
{
142
{
140
    out.clear();
143
    out.clear();
141
    if (len == 0)
144
    if (!len)
142
        return true;
145
        return true;
143
146
144
    while (len && data[len-1] == '=')
145
        --len;
146
147
    out.grow(len);
147
    out.grow(len);
148
149
    bool sawEqualsSign = false;
150
    unsigned outLength = 0;
148
    for (unsigned idx = 0; idx < len; idx++) {
151
    for (unsigned idx = 0; idx < len; idx++) {
149
        unsigned char ch = data[idx];
152
        unsigned ch = data[idx];
150
        if ((ch > 47 && ch < 58) || (ch > 64 && ch < 91) || (ch > 96 && ch < 123) || ch == '+' || ch == '/' || ch == '=')
153
        if (ch == '=')
151
            out[idx] = base64DecMap[ch];
154
            sawEqualsSign = true;
152
        else
155
        else if (('0' <= ch && ch <= '9') || ('A' <= ch && ch <= 'Z') || ('a' <= ch && ch <= 'z') || ch == '+' || ch == '/') {
156
            if (sawEqualsSign)
157
                return false;
158
            out[outLength] = base64DecMap[ch];
159
            outLength++;
160
        } else if (policy == FailOnInvalidCharacter || (policy == IgnoreWhitespace && !isSpaceOrNewline(ch)))
153
            return false;
161
            return false;
154
    }
162
    }
155
163
164
    if (!outLength)
165
        return !sawEqualsSign;
166
167
    // Valid data is (n * 4 + [0,2,3]) characters long.
168
    if ((outLength % 4) == 1)
169
        return false;
170
    
156
    // 4-byte to 3-byte conversion
171
    // 4-byte to 3-byte conversion
157
    unsigned outLen = len - ((len + 3) / 4);
172
    outLength -= (outLength + 3) / 4;
158
    if (!outLen || ((outLen + 2) / 3) * 4 < len)
173
    if (!outLength)
159
        return false;
174
        return false;
160
175
161
    unsigned sidx = 0;
176
    unsigned sidx = 0;
162
    unsigned didx = 0;
177
    unsigned didx = 0;
163
    if (outLen > 1) {
178
    if (outLength > 1) {
164
        while (didx < outLen - 2) {
179
        while (didx < outLength - 2) {
165
            out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx + 1] >> 4) & 003));
180
            out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx + 1] >> 4) & 003));
166
            out[didx + 1] = (((out[sidx + 1] << 4) & 255) | ((out[sidx + 2] >> 2) & 017));
181
            out[didx + 1] = (((out[sidx + 1] << 4) & 255) | ((out[sidx + 2] >> 2) & 017));
167
            out[didx + 2] = (((out[sidx + 2] << 6) & 255) | (out[sidx + 3] & 077));
182
            out[didx + 2] = (((out[sidx + 2] << 6) & 255) | (out[sidx + 3] & 077));
Lines 170-185 bool base64Decode(const char* data, unsi WebCore/platform/text/Base64.cpp_sec8
170
        }
185
        }
171
    }
186
    }
172
187
173
    if (didx < outLen)
188
    if (didx < outLength)
174
        out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx + 1] >> 4) & 003));
189
        out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx + 1] >> 4) & 003));
175
190
176
    if (++didx < outLen)
191
    if (++didx < outLength)
177
        out[didx] = (((out[sidx + 1] << 4) & 255) | ((out[sidx + 2] >> 2) & 017));
192
        out[didx] = (((out[sidx + 1] << 4) & 255) | ((out[sidx + 2] >> 2) & 017));
178
193
179
    if (outLen < out.size())
194
    if (outLength < out.size())
180
        out.shrink(outLen);
195
        out.shrink(outLength);
181
196
182
    return true;
197
    return true;
183
}
198
}
184
199
200
bool base64Decode(const char* data, unsigned len, Vector<char>& out, Base64DecodePolicy policy)
201
{
202
    return base64DecodeInternal<char>(data, len, out, policy);
185
}
203
}
204
205
bool base64Decode(const String& in, Vector<char>& out, Base64DecodePolicy policy)
206
{
207
    return base64DecodeInternal<UChar>(in.characters(), in.length(), out, policy);
208
}
209
210
} // namespace WebCore
- WebCore/platform/text/Base64.h -4 / +8 lines
Lines 1-5 WebCore/platform/text/Base64.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
2
 * Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
3
 * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
3
 *
4
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
Lines 26-41 WebCore/platform/text/Base64.h_sec2
26
#ifndef Base64_h
27
#ifndef Base64_h
27
#define Base64_h
28
#define Base64_h
28
29
30
#include <wtf/Forward.h>
29
#include <wtf/Vector.h>
31
#include <wtf/Vector.h>
30
32
31
namespace WebCore {
33
namespace WebCore {
32
34
35
enum Base64DecodePolicy { FailOnInvalidCharacter, IgnoreWhitespace, IgnoreInvalidCharacters };
36
33
void base64Encode(const Vector<char>&, Vector<char>&, bool insertLFs = false);
37
void base64Encode(const Vector<char>&, Vector<char>&, bool insertLFs = false);
34
void base64Encode(const char*, unsigned, Vector<char>&, bool insertLFs = false);
38
void base64Encode(const char*, unsigned, Vector<char>&, bool insertLFs = false);
35
39
36
// this decoder is not general purpose - it returns an error if it encounters a linefeed, as needed for window.atob
40
bool base64Decode(const String&, Vector<char>&, Base64DecodePolicy = FailOnInvalidCharacter);
37
bool base64Decode(const Vector<char>&, Vector<char>&);
41
bool base64Decode(const Vector<char>&, Vector<char>&, Base64DecodePolicy = FailOnInvalidCharacter);
38
bool base64Decode(const char*, unsigned, Vector<char>&);
42
bool base64Decode(const char*, unsigned, Vector<char>&, Base64DecodePolicy = FailOnInvalidCharacter);
39
43
40
}
44
}
41
45
- LayoutTests/ChangeLog +12 lines
Lines 1-3 LayoutTests/ChangeLog_sec1
1
2010-09-08  Patrick Gansterer  <paroga@paroga.com>
2
3
        Reviewed by Darin Adler.
4
5
        Add Base64DecodePolicy option at base64Decode()
6
        https://bugs.webkit.org/show_bug.cgi?id=41510
7
8
        * fast/dom/Window/atob-btoa-expected.txt:
9
        * fast/dom/Window/atob-btoa.html:
10
        * platform/mac/fast/loader/user-stylesheet-fast-path-expected.txt:
11
        * platform/mac/fast/loader/user-stylesheet-fast-path.html: Added additional data urls tests.
12
1
2010-09-08  Andy Estes  <aestes@apple.com>
13
2010-09-08  Andy Estes  <aestes@apple.com>
2
14
3
        Reviewed by Eric Carlson.
15
        Reviewed by Eric Carlson.
- LayoutTests/fast/dom/Window/atob-btoa-expected.txt +5 lines
Lines 35-42 PASS window.atob("тест") threw excep LayoutTests/fast/dom/Window/atob-btoa-expected.txt_sec1
35
PASS window.atob("z") threw exception Error: INVALID_CHARACTER_ERR: DOM Exception 5.
35
PASS window.atob("z") threw exception Error: INVALID_CHARACTER_ERR: DOM Exception 5.
36
PASS window.atob("zz") is "Ï"
36
PASS window.atob("zz") is "Ï"
37
PASS window.atob("zzz") is "Ï<"
37
PASS window.atob("zzz") is "Ï<"
38
PASS window.atob("zzz=") is "Ï<"
39
PASS window.atob("zzz==") is "Ï<"
40
PASS window.atob("zzz===") is "Ï<"
41
PASS window.atob("zzz====") is "Ï<"
38
PASS window.atob("zzzz") is "Ï<ó"
42
PASS window.atob("zzzz") is "Ï<ó"
39
PASS window.atob("zzzzz") threw exception Error: INVALID_CHARACTER_ERR: DOM Exception 5.
43
PASS window.atob("zzzzz") threw exception Error: INVALID_CHARACTER_ERR: DOM Exception 5.
44
PASS window.atob("z=zz") threw exception Error: INVALID_CHARACTER_ERR: DOM Exception 5.
40
PASS window.atob("=") threw exception Error: INVALID_CHARACTER_ERR: DOM Exception 5.
45
PASS window.atob("=") threw exception Error: INVALID_CHARACTER_ERR: DOM Exception 5.
41
PASS window.atob("==") threw exception Error: INVALID_CHARACTER_ERR: DOM Exception 5.
46
PASS window.atob("==") threw exception Error: INVALID_CHARACTER_ERR: DOM Exception 5.
42
PASS window.atob("===") threw exception Error: INVALID_CHARACTER_ERR: DOM Exception 5.
47
PASS window.atob("===") threw exception Error: INVALID_CHARACTER_ERR: DOM Exception 5.
- LayoutTests/fast/dom/Window/atob-btoa.html +5 lines
Lines 48-55 shouldThrow('window.atob("тест")'); LayoutTests/fast/dom/Window/atob-btoa.html_sec1
48
shouldThrow('window.atob("z")');
48
shouldThrow('window.atob("z")');
49
shouldBe('window.atob("zz")', '"Ï"');
49
shouldBe('window.atob("zz")', '"Ï"');
50
shouldBe('window.atob("zzz")', '"Ï\u003C"');
50
shouldBe('window.atob("zzz")', '"Ï\u003C"');
51
shouldBe('window.atob("zzz=")', '"Ï\u003C"');
52
shouldBe('window.atob("zzz==")', '"Ï\u003C"');
53
shouldBe('window.atob("zzz===")', '"Ï\u003C"');
54
shouldBe('window.atob("zzz====")', '"Ï\u003C"');
51
shouldBe('window.atob("zzzz")', '"Ï\u003Có"');
55
shouldBe('window.atob("zzzz")', '"Ï\u003Có"');
52
shouldThrow('window.atob("zzzzz")');
56
shouldThrow('window.atob("zzzzz")');
57
shouldThrow('window.atob("z=zz")');
53
shouldThrow('window.atob("=")');
58
shouldThrow('window.atob("=")');
54
shouldThrow('window.atob("==")');
59
shouldThrow('window.atob("==")');
55
shouldThrow('window.atob("===")');
60
shouldThrow('window.atob("===")');
- LayoutTests/platform/mac/fast/loader/user-stylesheet-fast-path-expected.txt +3 lines
Lines 1-6 LayoutTests/platform/mac/fast/loader/user-stylesheet-fast-path-expected.txt_sec1
1
This tests that when the user style sheet location is set to a data: URL with base64-encoded UTF-8 data, the style sheet is processed synchronously, instead of invoking the asynchronous loader.
1
This tests that when the user style sheet location is set to a data: URL with base64-encoded UTF-8 data, the style sheet is processed synchronously, instead of invoking the asynchronous loader.
2
2
3
PASS 100px
3
PASS 100px
4
PASS 110px
5
PASS 120px
6
PASS 130px
4
PASS 140px
7
PASS 140px
5
PASS 150px
8
PASS 150px
6
PASS 160px
9
PASS 160px
- LayoutTests/platform/mac/fast/loader/user-stylesheet-fast-path.html +3 lines
Lines 6-11 LayoutTests/platform/mac/fast/loader/user-stylesheet-fast-path.html_sec1
6
<script>
6
<script>
7
    var testObjects = [
7
    var testObjects = [
8
        {result:true,  size:"100px", url:"data:text/css;charset=utf-8;base64,Ym9keSB7Zm9udC1zaXplOiAxMDBweH0="},
8
        {result:true,  size:"100px", url:"data:text/css;charset=utf-8;base64,Ym9keSB7Zm9udC1zaXplOiAxMDBweH0="},
9
        {result:true,  size:"110px", url:"data:text/css;charset=utf-8;base64,                       Ym9keSB7Zm9udC1zaXplOiAxMTBweH0=                  "},
10
        {result:true,  size:"120px", url:"data:text/css;charset=utf-8;base64,\n \r \t Ym9k \t eSB7 \r Zm9ud \n \n C1zaXp \r lOiAxM \t jBweH0= \t \r \n"},
11
        {result:true,  size:"130px", url:"data:text/css;charset=utf-8;base64,\u0059 \u006D \u0039 \u006B eSB7Zm9ud C1zaXplOiAxMzBwe \u0048 \u0030 \u003D"},
9
        {result:false, size:"140px", url:"data:text/css;charset=utf-8;base64,Ym9k$#eSB7Zm#9ud(C1zaXp)lOiAxNDBweH0="},
12
        {result:false, size:"140px", url:"data:text/css;charset=utf-8;base64,Ym9k$#eSB7Zm#9ud(C1zaXp)lOiAxNDBweH0="},
10
        {result:false, size:"150px", url:"data:text/css;charset=utf-8;base64,Ym9ke%00SB7Z%20m9udC1z\n\taXplO#iAx%03NTBw%eH0="},
13
        {result:false, size:"150px", url:"data:text/css;charset=utf-8;base64,Ym9ke%00SB7Z%20m9udC1z\n\taXplO#iAx%03NTBw%eH0="},
11
        {result:false, size:"160px", url:"%50%30%10%00%20%40"}
14
        {result:false, size:"160px", url:"%50%30%10%00%20%40"}

Return to Bug 41510