1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:expandtab:shiftwidth=2:tabstop=2:
*/
/* 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/. */
#include "nsUnixRemoteServer.h"
#include "nsGTKToolkit.h"
#include "nsCOMPtr.h"
#include "nsICommandLineRunner.h"
#include "nsCommandLine.h"
#include "nsIFile.h"
// Set desktop startup ID to the passed ID, if there is one, so that any created
// windows get created with the right window manager metadata, and any windows
// that get new tabs and are activated also get the right WM metadata.
// The timestamp will be used if there is no desktop startup ID, or if we're
// raising an existing window rather than showing a new window for the first
// time.
void nsUnixRemoteServer::SetStartupTokenOrTimestamp(
const nsACString& aStartupToken, uint32_t aTimestamp) {
nsGTKToolkit* toolkit = nsGTKToolkit::GetToolkit();
if (!toolkit) {
return;
}
if (!aStartupToken.IsEmpty()) {
toolkit->SetStartupToken(aStartupToken);
}
toolkit->SetFocusTimestamp(aTimestamp);
}
static bool FindExtensionParameterInCommand(const char* aParameterName,
const nsACString& aCommand,
char aSeparator,
nsACString* aValue) {
nsAutoCString searchFor;
searchFor.Append(aSeparator);
searchFor.Append(aParameterName);
searchFor.Append('=');
nsACString::const_iterator start, end;
aCommand.BeginReading(start);
aCommand.EndReading(end);
if (!FindInReadable(searchFor, start, end)) return false;
nsACString::const_iterator charStart, charEnd;
charStart = end;
aCommand.EndReading(charEnd);
nsACString::const_iterator idStart = charStart, idEnd;
if (FindCharInReadable(aSeparator, charStart, charEnd)) {
idEnd = charStart;
} else {
idEnd = charEnd;
}
*aValue = nsDependentCSubstring(idStart, idEnd);
return true;
}
const char* nsUnixRemoteServer::HandleCommandLine(
mozilla::Span<const char> aBuffer, uint32_t aTimestamp) {
nsCOMPtr<nsICommandLineRunner> cmdline(new nsCommandLine());
// the commandline property is constructed as an array of int32_t
// followed by a series of null-terminated strings:
//
// [argc][offsetargv0][offsetargv1...]<workingdir>\0<argv[0]>\0argv[1]...\0
// (offset is from the beginning of the buffer)
if (aBuffer.size() < sizeof(uint32_t)) {
return "500 command not parseable";
}
uint32_t argc =
TO_LITTLE_ENDIAN32(*reinterpret_cast<const uint32_t*>(aBuffer.data()));
uint32_t offsetFilelist = ((argc + 1) * sizeof(uint32_t));
if (offsetFilelist >= aBuffer.size()) {
return "500 command not parseable";
}
const char* workingDir = aBuffer.data() + offsetFilelist;
nsCOMPtr<nsIFile> lf;
nsresult rv =
NS_NewNativeLocalFile(nsDependentCString(workingDir), getter_AddRefs(lf));
if (NS_FAILED(rv)) {
return "509 internal error";
}
const char** argv = (const char**)malloc(sizeof(char*) * argc);
if (!argv) {
return "509 internal error";
}
const uint32_t* offset =
reinterpret_cast<const uint32_t*>(aBuffer.data()) + 1;
nsAutoCString desktopStartupID;
for (unsigned int i = 0; i < argc; ++i) {
uint32_t argvOffset = TO_LITTLE_ENDIAN32(offset[i]);
if (argvOffset >= aBuffer.size()) {
return "500 command not parseable";
}
argv[i] = aBuffer.data() + argvOffset;
if (i == 0) {
nsDependentCString cmd(argv[0]);
FindExtensionParameterInCommand("STARTUP_TOKEN", cmd, ' ',
&desktopStartupID);
}
}
rv = cmdline->Init(argc, argv, lf, nsICommandLine::STATE_REMOTE_AUTO);
free(argv);
if (NS_FAILED(rv)) {
return "509 internal error";
}
SetStartupTokenOrTimestamp(desktopStartupID, aTimestamp);
rv = cmdline->Run();
if (NS_ERROR_ABORT == rv) {
return "500 command not parseable";
}
if (NS_FAILED(rv)) {
return "509 internal error";
}
return "200 executed command";
}
|