mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-18 15:55:36 +00:00
Bug 1658563
- Support .lnk files in file: protocol r=necko-reviewers,dragana
Differential Revision: https://phabricator.services.mozilla.com/D90283
This commit is contained in:
parent
a4a8cb224d
commit
bcf37d1286
@ -334,8 +334,8 @@ nsresult nsFileChannel::OpenContentStream(bool async, nsIInputStream** result,
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIURI> newURI;
|
||||
rv = fileHandler->ReadURLFile(file, getter_AddRefs(newURI));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (NS_SUCCEEDED(fileHandler->ReadURLFile(file, getter_AddRefs(newURI))) ||
|
||||
NS_SUCCEEDED(fileHandler->ReadShellLink(file, getter_AddRefs(newURI)))) {
|
||||
nsCOMPtr<nsIChannel> newChannel;
|
||||
rv = NS_NewChannel(getter_AddRefs(newChannel), newURI,
|
||||
nsContentUtils::GetSystemPrincipal(),
|
||||
|
@ -15,6 +15,8 @@
|
||||
|
||||
#include "FileChannelChild.h"
|
||||
|
||||
#include "mozilla/ResultExtensions.h"
|
||||
|
||||
// URL file handling, copied and modified from
|
||||
// xpfe/components/bookmarks/src/nsBookmarksService.cpp
|
||||
#ifdef XP_WIN
|
||||
@ -123,6 +125,38 @@ nsFileProtocolHandler::ReadURLFile(nsIFile* aFile, nsIURI** aURI) {
|
||||
}
|
||||
#endif // ReadURLFile()
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFileProtocolHandler::ReadShellLink(nsIFile* aFile, nsIURI** aURI) {
|
||||
#if defined(XP_WIN)
|
||||
nsAutoString path;
|
||||
MOZ_TRY(aFile->GetPath(path));
|
||||
|
||||
if (path.Length() < 4 ||
|
||||
!StringTail(path, 4).LowerCaseEqualsLiteral(".lnk")) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
RefPtr<IPersistFile> persistFile;
|
||||
RefPtr<IShellLinkW> shellLink;
|
||||
WCHAR lpTemp[MAX_PATH];
|
||||
// Get a pointer to the IPersistFile interface.
|
||||
if (FAILED(CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER,
|
||||
IID_IShellLinkW, getter_AddRefs(shellLink))) ||
|
||||
FAILED(shellLink->QueryInterface(IID_IPersistFile,
|
||||
getter_AddRefs(persistFile))) ||
|
||||
FAILED(persistFile->Load(path.get(), STGM_READ)) ||
|
||||
FAILED(shellLink->Resolve(nullptr, SLR_NO_UI)) ||
|
||||
FAILED(shellLink->GetPath(lpTemp, MAX_PATH, nullptr, SLGP_UNCPRIORITY))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsCOMPtr<nsIFile> linkedFile;
|
||||
MOZ_TRY(NS_NewLocalFile(nsDependentString(lpTemp), false,
|
||||
getter_AddRefs(linkedFile)));
|
||||
return NS_NewFileURI(aURI, linkedFile);
|
||||
#else
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFileProtocolHandler::GetScheme(nsACString& result) {
|
||||
result.AssignLiteral("file");
|
||||
|
@ -73,4 +73,15 @@ interface nsIFileProtocolHandler : nsIProtocolHandler
|
||||
* @throw NS_ERROR_NOT_AVAILABLE if this file is not an internet shortcut.
|
||||
*/
|
||||
nsIURI readURLFile(in nsIFile file);
|
||||
|
||||
/**
|
||||
* Takes a local file and tries to interpret it as a shell link file
|
||||
* (.lnk files on Windows)
|
||||
* @param file The local file to read
|
||||
* @return The URI the file refers to
|
||||
*
|
||||
* @throw NS_ERROR_NOT_AVAILABLE if the OS does not support such files.
|
||||
* @throw NS_ERROR_NOT_AVAILABLE if this file is not a shell link.
|
||||
*/
|
||||
nsIURI readShellLink(in nsIFile file);
|
||||
};
|
||||
|
@ -22,3 +22,7 @@ support-files =
|
||||
damonbowling.jpg
|
||||
damonbowling.jpg^headers^
|
||||
file_favicon.html
|
||||
[browser_fetch_lnk.js]
|
||||
run-if = os == "win"
|
||||
support-files =
|
||||
file_lnk.lnk
|
||||
|
27
netwerk/test/browser/browser_fetch_lnk.js
Normal file
27
netwerk/test/browser/browser_fetch_lnk.js
Normal file
@ -0,0 +1,27 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(async () => {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["privacy.file_unique_origin", false]],
|
||||
});
|
||||
|
||||
const FILE_PAGE = Services.io.newFileURI(
|
||||
new FileUtils.File(getTestFilePath("dummy.html"))
|
||||
).spec;
|
||||
await BrowserTestUtils.withNewTab(FILE_PAGE, async browser => {
|
||||
try {
|
||||
await SpecialPowers.spawn(browser, [], () =>
|
||||
content.fetch("./file_lnk.lnk")
|
||||
);
|
||||
ok(
|
||||
false,
|
||||
"Loading lnk must fail if it links to a file from other directory"
|
||||
);
|
||||
} catch (err) {
|
||||
is(err.constructor.name, "TypeError", "Should fail on Windows");
|
||||
}
|
||||
});
|
||||
});
|
BIN
netwerk/test/browser/file_lnk.lnk
Normal file
BIN
netwerk/test/browser/file_lnk.lnk
Normal file
Binary file not shown.
BIN
netwerk/test/mochitests/file_lnk.lnk
Normal file
BIN
netwerk/test/mochitests/file_lnk.lnk
Normal file
Binary file not shown.
@ -37,6 +37,7 @@ support-files =
|
||||
file_image_inner.html^headers^
|
||||
file_image_inner_inner.html
|
||||
file_image_inner_inner.html^headers^
|
||||
file_lnk.lnk
|
||||
file_loadflags_inner.html
|
||||
file_loadflags_inner.html^headers^
|
||||
file_localhost_inner.html
|
||||
@ -84,6 +85,7 @@ support-files = sw_1502055.js file_1502055.sjs iframe_1502055.html
|
||||
support-files = test_accept_header.sjs
|
||||
[test_different_domain_in_hierarchy.html]
|
||||
[test_differentdomain.html]
|
||||
[test_fetch_lnk.html]
|
||||
[test_image.html]
|
||||
[test_loadflags.html]
|
||||
[test_same_base_domain.html]
|
||||
|
17
netwerk/test/mochitests/test_fetch_lnk.html
Normal file
17
netwerk/test/mochitests/test_fetch_lnk.html
Normal file
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Downloading .lnk through HTTP should always download the file without parsing it</title>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script>
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
// Download .lnk which points to a system executable
|
||||
fetch("file_lnk.lnk").then(async res => {
|
||||
ok(res.ok, "Download success");
|
||||
ok(res.url.endsWith("file_lnk.lnk"), "file name should be of the lnk file");
|
||||
is(res.headers.get("Content-Length"), "1531", "The size should be of the lnk file");
|
||||
SimpleTest.finish();
|
||||
}, () => {
|
||||
ok(false, "Unreachable code");
|
||||
})
|
||||
</script>
|
@ -1,6 +1,6 @@
|
||||
"use strict";
|
||||
|
||||
function getLinkFile() {
|
||||
function getUrlLinkFile() {
|
||||
if (mozinfo.os == "win") {
|
||||
return do_get_file("test_link.url");
|
||||
}
|
||||
@ -12,9 +12,6 @@ function getLinkFile() {
|
||||
}
|
||||
|
||||
const ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
|
||||
var link;
|
||||
var linkURI;
|
||||
const newURI = ios.newURI("http://www.mozilla.org/");
|
||||
|
||||
function NotificationCallbacks(origURI, newURI) {
|
||||
this._origURI = origURI;
|
||||
@ -74,7 +71,7 @@ RequestObserver.prototype = {
|
||||
},
|
||||
};
|
||||
|
||||
function test_cancel() {
|
||||
function test_cancel(linkURI, newURI) {
|
||||
var chan = NetUtil.newChannel({
|
||||
uri: linkURI,
|
||||
loadUsingSystemPrincipal: true,
|
||||
@ -87,12 +84,27 @@ function test_cancel() {
|
||||
Assert.ok(chan.isPending());
|
||||
}
|
||||
|
||||
function test_channel(linkURI, newURI) {
|
||||
const chan = NetUtil.newChannel({
|
||||
uri: linkURI,
|
||||
loadUsingSystemPrincipal: true,
|
||||
});
|
||||
Assert.equal(chan.URI, linkURI);
|
||||
Assert.equal(chan.originalURI, linkURI);
|
||||
chan.notificationCallbacks = new NotificationCallbacks(linkURI, newURI);
|
||||
chan.asyncOpen(
|
||||
new RequestObserver(linkURI, newURI, () => test_cancel(linkURI, newURI))
|
||||
);
|
||||
Assert.ok(chan.isPending());
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
if (mozinfo.os != "win" && mozinfo.os != "linux") {
|
||||
return;
|
||||
}
|
||||
|
||||
link = getLinkFile();
|
||||
let link = getUrlLinkFile();
|
||||
let linkURI;
|
||||
if (link.isSymlink()) {
|
||||
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
||||
file.initWithPath(link.target);
|
||||
@ -102,13 +114,15 @@ function run_test() {
|
||||
}
|
||||
|
||||
do_test_pending();
|
||||
var chan = NetUtil.newChannel({
|
||||
uri: linkURI,
|
||||
loadUsingSystemPrincipal: true,
|
||||
});
|
||||
Assert.equal(chan.URI, linkURI);
|
||||
Assert.equal(chan.originalURI, linkURI);
|
||||
chan.notificationCallbacks = new NotificationCallbacks(linkURI, newURI);
|
||||
chan.asyncOpen(new RequestObserver(linkURI, newURI, test_cancel));
|
||||
Assert.ok(chan.isPending());
|
||||
test_channel(linkURI, ios.newURI("http://www.mozilla.org/"));
|
||||
|
||||
if (mozinfo.os != "win") {
|
||||
return;
|
||||
}
|
||||
|
||||
link = do_get_file("test_link.lnk");
|
||||
test_channel(
|
||||
ios.newFileURI(link),
|
||||
ios.newURI("file:///Z:/moz-nonexistent/index.html")
|
||||
);
|
||||
}
|
||||
|
BIN
netwerk/test/unit/test_link.lnk
Normal file
BIN
netwerk/test/unit/test_link.lnk
Normal file
Binary file not shown.
@ -20,6 +20,7 @@ support-files =
|
||||
socks_client_subprocess.js
|
||||
test_link.desktop
|
||||
test_link.url
|
||||
test_link.lnk
|
||||
../../dns/effective_tld_names.dat
|
||||
test_alt-data_cross_process.js
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user