Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/netwerk/protocol/file/nsFileProtocolHandler.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
// vim:ts=4 sw=4 sts=4 et cin:
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "nsIFile.h"
8
#include "nsFileProtocolHandler.h"
9
#include "nsFileChannel.h"
10
#include "nsStandardURL.h"
11
#include "nsURLHelper.h"
12
#include "nsIURIMutator.h"
13
14
#include "nsNetUtil.h"
15
16
#include "FileChannelChild.h"
17
18
// URL file handling, copied and modified from xpfe/components/bookmarks/src/nsBookmarksService.cpp
19
#ifdef XP_WIN
20
#include <shlobj.h>
21
#include <intshcut.h>
22
#include "nsIFileURL.h"
23
#ifdef CompareString
24
#undef CompareString
25
#endif
26
#endif
27
28
// URL file handling for freedesktop.org
29
#ifdef XP_UNIX
30
#include "nsINIParser.h"
31
0
#define DESKTOP_ENTRY_SECTION "Desktop Entry"
32
#endif
33
34
//-----------------------------------------------------------------------------
35
36
nsresult
37
nsFileProtocolHandler::Init()
38
3
{
39
3
    return NS_OK;
40
3
}
41
42
NS_IMPL_ISUPPORTS(nsFileProtocolHandler,
43
                  nsIFileProtocolHandler,
44
                  nsIProtocolHandler,
45
                  nsISupportsWeakReference)
46
47
//-----------------------------------------------------------------------------
48
// nsIProtocolHandler methods:
49
50
#if defined(XP_WIN)
51
NS_IMETHODIMP
52
nsFileProtocolHandler::ReadURLFile(nsIFile* aFile, nsIURI** aURI)
53
{
54
    nsAutoString path;
55
    nsresult rv = aFile->GetPath(path);
56
    if (NS_FAILED(rv))
57
        return rv;
58
59
    if (path.Length() < 4)
60
        return NS_ERROR_NOT_AVAILABLE;
61
    if (!StringTail(path, 4).LowerCaseEqualsLiteral(".url"))
62
        return NS_ERROR_NOT_AVAILABLE;
63
64
    HRESULT result;
65
66
    rv = NS_ERROR_NOT_AVAILABLE;
67
68
    IUniformResourceLocatorW* urlLink = nullptr;
69
    result = ::CoCreateInstance(CLSID_InternetShortcut, nullptr, CLSCTX_INPROC_SERVER,
70
                                IID_IUniformResourceLocatorW, (void**)&urlLink);
71
    if (SUCCEEDED(result) && urlLink) {
72
        IPersistFile* urlFile = nullptr;
73
        result = urlLink->QueryInterface(IID_IPersistFile, (void**)&urlFile);
74
        if (SUCCEEDED(result) && urlFile) {
75
            result = urlFile->Load(path.get(), STGM_READ);
76
            if (SUCCEEDED(result) ) {
77
                LPWSTR lpTemp = nullptr;
78
79
                // The URL this method will give us back seems to be already
80
                // escaped. Hence, do not do escaping of our own.
81
                result = urlLink->GetURL(&lpTemp);
82
                if (SUCCEEDED(result) && lpTemp) {
83
                    rv = NS_NewURI(aURI, nsDependentString(lpTemp));
84
                    // free the string that GetURL alloc'd
85
                    CoTaskMemFree(lpTemp);
86
                }
87
            }
88
            urlFile->Release();
89
        }
90
        urlLink->Release();
91
    }
92
    return rv;
93
}
94
95
#elif defined(XP_UNIX)
96
NS_IMETHODIMP
97
nsFileProtocolHandler::ReadURLFile(nsIFile* aFile, nsIURI** aURI)
98
0
{
99
0
    // We only support desktop files that end in ".desktop" like the spec says:
100
0
    // http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s02.html
101
0
    nsAutoCString leafName;
102
0
    nsresult rv = aFile->GetNativeLeafName(leafName);
103
0
    if (NS_FAILED(rv) ||
104
0
  !StringEndsWith(leafName, NS_LITERAL_CSTRING(".desktop")))
105
0
        return NS_ERROR_NOT_AVAILABLE;
106
0
107
0
    bool isFile = false;
108
0
    rv = aFile->IsFile(&isFile);
109
0
    if (NS_FAILED(rv) || !isFile) {
110
0
        return NS_ERROR_NOT_AVAILABLE;
111
0
    }
112
0
113
0
    nsINIParser parser;
114
0
    rv = parser.Init(aFile);
115
0
    if (NS_FAILED(rv))
116
0
        return rv;
117
0
118
0
    nsAutoCString type;
119
0
    parser.GetString(DESKTOP_ENTRY_SECTION, "Type", type);
120
0
    if (!type.EqualsLiteral("Link"))
121
0
        return NS_ERROR_NOT_AVAILABLE;
122
0
123
0
    nsAutoCString url;
124
0
    rv = parser.GetString(DESKTOP_ENTRY_SECTION, "URL", url);
125
0
    if (NS_FAILED(rv) || url.IsEmpty())
126
0
        return NS_ERROR_NOT_AVAILABLE;
127
0
128
0
    return NS_NewURI(aURI, url);
129
0
}
130
131
#else // other platforms
132
NS_IMETHODIMP
133
nsFileProtocolHandler::ReadURLFile(nsIFile* aFile, nsIURI** aURI)
134
{
135
    return NS_ERROR_NOT_AVAILABLE;
136
}
137
#endif // ReadURLFile()
138
139
NS_IMETHODIMP
140
nsFileProtocolHandler::GetScheme(nsACString &result)
141
0
{
142
0
    result.AssignLiteral("file");
143
0
    return NS_OK;
144
0
}
145
146
NS_IMETHODIMP
147
nsFileProtocolHandler::GetDefaultPort(int32_t *result)
148
0
{
149
0
    *result = -1;        // no port for file: URLs
150
0
    return NS_OK;
151
0
}
152
153
NS_IMETHODIMP
154
nsFileProtocolHandler::GetProtocolFlags(uint32_t *result)
155
90
{
156
90
    *result = URI_NOAUTH | URI_IS_LOCAL_FILE |
157
90
              URI_IS_LOCAL_RESOURCE | URI_IS_POTENTIALLY_TRUSTWORTHY;
158
90
    return NS_OK;
159
90
}
160
161
NS_IMETHODIMP
162
nsFileProtocolHandler::NewURI(const nsACString &spec,
163
                              const char *charset,
164
                              nsIURI *aBaseURI,
165
                              nsIURI **result)
166
4.68k
{
167
4.68k
    nsAutoCString buf(spec);
168
#if defined(XP_WIN)
169
    buf.Truncate();
170
    if (!net_NormalizeFileURL(spec, buf)) {
171
        buf = spec;
172
    }
173
#endif
174
175
4.68k
    nsCOMPtr<nsIURI> base(aBaseURI);
176
4.68k
    return NS_MutateURI(new nsStandardURL::Mutator())
177
4.68k
      .Apply(NS_MutatorMethod(&nsIFileURLMutator::MarkFileURL))
178
4.68k
      .Apply(NS_MutatorMethod(&nsIStandardURLMutator::Init,
179
4.68k
                              nsIStandardURL::URLTYPE_NO_AUTHORITY,
180
4.68k
                              -1, buf, charset, base, nullptr))
181
4.68k
      .Finalize(result);
182
4.68k
}
183
184
NS_IMETHODIMP
185
nsFileProtocolHandler::NewChannel2(nsIURI* uri,
186
                                   nsILoadInfo* aLoadInfo,
187
                                   nsIChannel** result)
188
0
{
189
0
    nsresult rv;
190
0
191
0
    nsFileChannel *chan;
192
0
    if (IsNeckoChild()) {
193
0
        chan = new mozilla::net::FileChannelChild(uri);
194
0
    } else {
195
0
        chan = new nsFileChannel(uri);
196
0
    }
197
0
    if (!chan)
198
0
        return NS_ERROR_OUT_OF_MEMORY;
199
0
    NS_ADDREF(chan);
200
0
201
0
    // set the loadInfo on the new channel ; must do this
202
0
    // before calling Init() on it, since it needs the load
203
0
    // info be already set.
204
0
    rv = chan->SetLoadInfo(aLoadInfo);
205
0
    if (NS_FAILED(rv)) {
206
0
        NS_RELEASE(chan);
207
0
        return rv;
208
0
    }
209
0
210
0
    rv = chan->Init();
211
0
    if (NS_FAILED(rv)) {
212
0
        NS_RELEASE(chan);
213
0
        return rv;
214
0
    }
215
0
216
0
    *result = chan;
217
0
    return NS_OK;
218
0
}
219
220
NS_IMETHODIMP
221
nsFileProtocolHandler::NewChannel(nsIURI *uri, nsIChannel **result)
222
0
{
223
0
    return NewChannel2(uri, nullptr, result);
224
0
}
225
226
NS_IMETHODIMP
227
nsFileProtocolHandler::AllowPort(int32_t port, const char *scheme, bool *result)
228
0
{
229
0
    // don't override anything.
230
0
    *result = false;
231
0
    return NS_OK;
232
0
}
233
234
//-----------------------------------------------------------------------------
235
// nsIFileProtocolHandler methods:
236
237
NS_IMETHODIMP
238
nsFileProtocolHandler::NewFileURI(nsIFile *aFile, nsIURI **aResult)
239
0
{
240
0
    NS_ENSURE_ARG_POINTER(aFile);
241
0
242
0
    RefPtr<nsIFile> file(aFile);
243
0
    // NOTE: the origin charset is assigned the value of the platform
244
0
    // charset by the SetFile method.
245
0
    return NS_MutateURI(new nsStandardURL::Mutator())
246
0
             .Apply(NS_MutatorMethod(&nsIFileURLMutator::SetFile, file))
247
0
             .Finalize(aResult);
248
0
}
249
250
NS_IMETHODIMP
251
nsFileProtocolHandler::NewFileURIMutator(nsIFile *aFile, nsIURIMutator **aResult)
252
0
{
253
0
    NS_ENSURE_ARG_POINTER(aFile);
254
0
    nsresult rv;
255
0
256
0
    nsCOMPtr<nsIURIMutator> mutator = new nsStandardURL::Mutator();
257
0
    nsCOMPtr<nsIFileURLMutator> fileMutator = do_QueryInterface(mutator, &rv);
258
0
    if (NS_FAILED(rv)) {
259
0
        return rv;
260
0
    }
261
0
262
0
    // NOTE: the origin charset is assigned the value of the platform
263
0
    // charset by the SetFile method.
264
0
    rv = fileMutator->SetFile(aFile);
265
0
    if (NS_FAILED(rv)) {
266
0
        return rv;
267
0
    }
268
0
269
0
    mutator.forget(aResult);
270
0
    return NS_OK;
271
0
}
272
273
NS_IMETHODIMP
274
nsFileProtocolHandler::GetURLSpecFromFile(nsIFile *file, nsACString &result)
275
0
{
276
0
    NS_ENSURE_ARG_POINTER(file);
277
0
    return net_GetURLSpecFromFile(file, result);
278
0
}
279
280
NS_IMETHODIMP
281
nsFileProtocolHandler::GetURLSpecFromActualFile(nsIFile *file,
282
                                                nsACString &result)
283
11
{
284
11
    NS_ENSURE_ARG_POINTER(file);
285
11
    return net_GetURLSpecFromActualFile(file, result);
286
11
}
287
288
NS_IMETHODIMP
289
nsFileProtocolHandler::GetURLSpecFromDir(nsIFile *file, nsACString &result)
290
0
{
291
0
    NS_ENSURE_ARG_POINTER(file);
292
0
    return net_GetURLSpecFromDir(file, result);
293
0
}
294
295
NS_IMETHODIMP
296
nsFileProtocolHandler::GetFileFromURLSpec(const nsACString &spec, nsIFile **result)
297
0
{
298
0
    return net_GetFileFromURLSpec(spec, result);
299
0
}