|
|
|
@ -332,23 +332,47 @@ void Application::runExternalProgram(const BitTorrent::TorrentHandle *torrent) c
@@ -332,23 +332,47 @@ void Application::runExternalProgram(const BitTorrent::TorrentHandle *torrent) c
|
|
|
|
|
logger->addMessage(tr("Torrent: %1, running external program, command: %2").arg(torrent->name(), program)); |
|
|
|
|
|
|
|
|
|
#if defined(Q_OS_WIN) |
|
|
|
|
std::unique_ptr<wchar_t[]> programWchar(new wchar_t[program.length() + 1] {}); |
|
|
|
|
auto programWchar = std::make_unique<wchar_t[]>(program.length() + 1); |
|
|
|
|
program.toWCharArray(programWchar.get()); |
|
|
|
|
|
|
|
|
|
// Need to split arguments manually because QProcess::startDetached(QString)
|
|
|
|
|
// will strip off empty parameters.
|
|
|
|
|
// E.g. `python.exe "1" "" "3"` will become `python.exe "1" "3"`
|
|
|
|
|
int argCount = 0; |
|
|
|
|
LPWSTR *args = ::CommandLineToArgvW(programWchar.get(), &argCount); |
|
|
|
|
std::unique_ptr<LPWSTR[], decltype(&::LocalFree)> args {::CommandLineToArgvW(programWchar.get(), &argCount), ::LocalFree}; |
|
|
|
|
|
|
|
|
|
QStringList argList; |
|
|
|
|
for (int i = 1; i < argCount; ++i) |
|
|
|
|
argList += QString::fromWCharArray(args[i]); |
|
|
|
|
|
|
|
|
|
QProcess::startDetached(QString::fromWCharArray(args[0]), argList); |
|
|
|
|
|
|
|
|
|
::LocalFree(args); |
|
|
|
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)) |
|
|
|
|
QProcess proc; |
|
|
|
|
proc.setProgram(QString::fromWCharArray(args[0])); |
|
|
|
|
proc.setArguments(argList); |
|
|
|
|
proc.setCreateProcessArgumentsModifier([](QProcess::CreateProcessArguments *args) |
|
|
|
|
{ |
|
|
|
|
if (Preferences::instance()->isAutoRunConsoleEnabled()) { |
|
|
|
|
args->flags |= CREATE_NEW_CONSOLE; |
|
|
|
|
args->flags &= ~(CREATE_NO_WINDOW | DETACHED_PROCESS); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
args->flags |= CREATE_NO_WINDOW; |
|
|
|
|
args->flags &= ~(CREATE_NEW_CONSOLE | DETACHED_PROCESS); |
|
|
|
|
} |
|
|
|
|
args->inheritHandles = false; |
|
|
|
|
args->startupInfo->dwFlags &= ~STARTF_USESTDHANDLES; |
|
|
|
|
::CloseHandle(args->startupInfo->hStdInput); |
|
|
|
|
::CloseHandle(args->startupInfo->hStdOutput); |
|
|
|
|
::CloseHandle(args->startupInfo->hStdError); |
|
|
|
|
args->startupInfo->hStdInput = nullptr; |
|
|
|
|
args->startupInfo->hStdOutput = nullptr; |
|
|
|
|
args->startupInfo->hStdError = nullptr; |
|
|
|
|
}); |
|
|
|
|
proc.startDetached(); |
|
|
|
|
#else |
|
|
|
|
QProcess::startDetached(QString::fromWCharArray(args[0]), argList); |
|
|
|
|
#endif // QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
|
|
|
|
|
#else // Q_OS_WIN
|
|
|
|
|
// Cannot give users shell environment by default, as doing so could
|
|
|
|
|
// enable command injection via torrent name and other arguments
|
|
|
|
|
// (especially when some automated download mechanism has been setup).
|
|
|
|
|