Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/netwerk/protocol/data/nsDataChannel.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
// data implementation
7
8
#include "nsDataChannel.h"
9
10
#include "mozilla/Base64.h"
11
#include "nsIOService.h"
12
#include "nsDataHandler.h"
13
#include "nsIPipe.h"
14
#include "nsIInputStream.h"
15
#include "nsIOutputStream.h"
16
#include "nsEscape.h"
17
18
using namespace mozilla;
19
20
/**
21
 * Helper for performing a fallible unescape.
22
 *
23
 * @param aStr The string to unescape.
24
 * @param aBuffer Buffer to unescape into if necessary.
25
 * @param rv Out: nsresult indicating success or failure of unescaping.
26
 * @return Reference to the string containing the unescaped data.
27
 */
28
const nsACString& Unescape(const nsACString& aStr, nsACString& aBuffer,
29
                           nsresult* rv)
30
0
{
31
0
    MOZ_ASSERT(rv);
32
0
33
0
    bool appended = false;
34
0
    *rv = NS_UnescapeURL(aStr.Data(), aStr.Length(), /* aFlags = */ 0,
35
0
                         aBuffer, appended, mozilla::fallible);
36
0
    if (NS_FAILED(*rv) || !appended) {
37
0
        return aStr;
38
0
    }
39
0
40
0
    return aBuffer;
41
0
}
42
43
nsresult
44
nsDataChannel::OpenContentStream(bool async, nsIInputStream **result,
45
                                 nsIChannel** channel)
46
0
{
47
0
    NS_ENSURE_TRUE(URI(), NS_ERROR_NOT_INITIALIZED);
48
0
49
0
    nsresult rv;
50
0
51
0
    // In order to avoid potentially building up a new path including the
52
0
    // ref portion of the URI, which we don't care about, we clone a version
53
0
    // of the URI that does not have a ref and in most cases should share
54
0
    // string buffers with the original URI.
55
0
    nsCOMPtr<nsIURI> uri;
56
0
    rv = NS_GetURIWithoutRef(URI(), getter_AddRefs(uri));
57
0
    if (NS_FAILED(rv))
58
0
        return rv;
59
0
60
0
    nsAutoCString path;
61
0
    rv = uri->GetPathQueryRef(path);
62
0
    if (NS_FAILED(rv))
63
0
        return rv;
64
0
65
0
    nsCString contentType, contentCharset;
66
0
    nsDependentCSubstring dataRange;
67
0
    bool lBase64;
68
0
    rv = nsDataHandler::ParsePathWithoutRef(path, contentType, &contentCharset,
69
0
                                            lBase64, &dataRange);
70
0
    if (NS_FAILED(rv))
71
0
        return rv;
72
0
73
0
    // This will avoid a copy if nothing needs to be unescaped.
74
0
    nsAutoCString unescapedBuffer;
75
0
    const nsACString& data = Unescape(dataRange, unescapedBuffer, &rv);
76
0
    if (NS_FAILED(rv)) {
77
0
        return rv;
78
0
    }
79
0
80
0
    if (lBase64 && &data == &unescapedBuffer) {
81
0
        // Don't allow spaces in base64-encoded content. This is only
82
0
        // relevant for escaped spaces; other spaces are stripped in
83
0
        // NewURI. We know there were no escaped spaces if the data buffer
84
0
        // wasn't used in |Unescape|.
85
0
        unescapedBuffer.StripWhitespace();
86
0
    }
87
0
88
0
    nsCOMPtr<nsIInputStream> bufInStream;
89
0
    nsCOMPtr<nsIOutputStream> bufOutStream;
90
0
91
0
    // create an unbounded pipe.
92
0
    rv = NS_NewPipe(getter_AddRefs(bufInStream),
93
0
                    getter_AddRefs(bufOutStream),
94
0
                    net::nsIOService::gDefaultSegmentSize,
95
0
                    UINT32_MAX,
96
0
                    async, true);
97
0
    if (NS_FAILED(rv))
98
0
        return rv;
99
0
100
0
    uint32_t contentLen;
101
0
    if (lBase64) {
102
0
        nsAutoCString decodedData;
103
0
        rv = Base64Decode(data, decodedData);
104
0
        NS_ENSURE_SUCCESS(rv, rv);
105
0
106
0
        rv = bufOutStream->Write(decodedData.get(), decodedData.Length(), &contentLen);
107
0
    } else {
108
0
        rv = bufOutStream->Write(data.Data(), data.Length(), &contentLen);
109
0
    }
110
0
111
0
    if (NS_FAILED(rv))
112
0
        return rv;
113
0
114
0
    SetContentType(contentType);
115
0
    SetContentCharset(contentCharset);
116
0
    mContentLength = contentLen;
117
0
118
0
    bufInStream.forget(result);
119
0
120
0
    return NS_OK;
121
0
}