summaryrefslogtreecommitdiffstats
path: root/devtools/client/netmonitor/src/utils/powershell.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--devtools/client/netmonitor/src/utils/powershell.js142
1 files changed, 142 insertions, 0 deletions
diff --git a/devtools/client/netmonitor/src/utils/powershell.js b/devtools/client/netmonitor/src/utils/powershell.js
new file mode 100644
index 0000000000..2efcfd8faa
--- /dev/null
+++ b/devtools/client/netmonitor/src/utils/powershell.js
@@ -0,0 +1,142 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Anthony Ricaud <rik@webkit.org>
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2022 Mozilla Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Utility to generate commands to invoke a request for powershell
+"use strict";
+
+// Some of these headers are passed in as seperate `Invoke-WebRequest` parameters so ignore
+// when building the headers list, others are not to neccesarily restrict the request.
+const IGNORED_HEADERS = [
+ "connection",
+ "proxy-connection",
+ "content-length",
+ "expect",
+ "range",
+ "host",
+ "content-type",
+ "user-agent",
+ "cookie",
+];
+/**
+ * This escapes strings for the powershell command
+ *
+ * 1. Escape the backtick, dollar sign and the double quotes See https://www.rlmueller.net/PowerShellEscape.htm
+ * 2. Convert any non printing ASCII characters found, using the ASCII code.
+ */
+function escapeStr(str) {
+ return `"${str
+ .replace(/[`\$"]/g, "`$&")
+ .replace(/[^\x20-\x7E]/g, char => "$([char]" + char.charCodeAt(0) + ")")}"`;
+}
+
+const PowerShell = {
+ generateCommand(url, method, headers, postData, cookies) {
+ const parameters = [];
+
+ // Create a WebSession to pass the information about cookies
+ // See https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-webrequest?view=powershell-7.2#-websession
+ const session = [];
+ for (const { name, value, domain } of cookies) {
+ if (!session.length) {
+ session.push(
+ "$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession"
+ );
+ }
+ session.push(
+ `$session.Cookies.Add((New-Object System.Net.Cookie(${escapeStr(
+ name
+ )}, ${escapeStr(value)}, "/", ${escapeStr(
+ domain || new URL(url).host
+ )})))`
+ );
+ }
+
+ parameters.push(`-Uri ${escapeStr(url)}`);
+
+ if (method !== "GET") {
+ parameters.push(`-Method ${method}`);
+ }
+
+ if (session.length) {
+ parameters.push("-WebSession $session");
+ }
+
+ const userAgent = headers.find(
+ ({ name }) => name.toLowerCase() === "user-agent"
+ );
+ if (userAgent) {
+ parameters.push("-UserAgent " + escapeStr(userAgent.value));
+ }
+
+ const headersStr = [];
+ for (let { name, value } of headers) {
+ // Translate any HTTP2 pseudo headers to HTTP headers
+ name = name.replace(/^:/, "");
+
+ if (IGNORED_HEADERS.includes(name.toLowerCase())) {
+ continue;
+ }
+ headersStr.push(`${escapeStr(name)} = ${escapeStr(value)}`);
+ }
+ if (headersStr.length) {
+ parameters.push(`-Headers @{\n${headersStr.join("\n ")}\n}`);
+ }
+
+ const contentType = headers.find(
+ header => header.name.toLowerCase() === "content-type"
+ );
+ if (contentType) {
+ parameters.push("-ContentType " + escapeStr(contentType.value));
+ }
+
+ const formData = postData.text;
+ if (formData) {
+ // Encode bytes if any of the characters is not an ASCII printing character (not between Space character and ~ character)
+ // a-zA-Z0-9 etc. See http://www.asciitable.com/
+ const body = /[^\x20-\x7E]/.test(formData)
+ ? "([System.Text.Encoding]::UTF8.GetBytes(" + escapeStr(formData) + "))"
+ : escapeStr(formData);
+ parameters.push("-Body " + body);
+ }
+
+ return `${
+ session.length ? session.join("\n").concat("\n") : ""
+ // -UseBasicParsing is added for backward compatibility.
+ // See https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-webrequest?view=powershell-7.2#-usebasicparsing
+ }Invoke-WebRequest -UseBasicParsing ${parameters.join(" `\n")}`;
+ },
+};
+
+exports.PowerShell = PowerShell;