Move relaunch / update logic to Core::Launcher.

Also pass "-workdir" argument through relaunch / update.

Fixes #4149.
This commit is contained in:
John Preston 2017-12-12 11:52:53 +04:00
parent 97c15865a5
commit 251176df47
21 changed files with 505 additions and 415 deletions

View file

@ -22,7 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
bool _debug = false;
wstring updaterName, updaterDir, updateTo, exeName;
wstring updaterName, updaterDir, updateTo, exeName, customWorkingDir, customKeyFile;
bool equal(const wstring &a, const wstring &b) {
return !_wcsicmp(a.c_str(), b.c_str());
@ -356,6 +356,7 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdPara
args = CommandLineToArgvW(GetCommandLine(), &argsCount);
if (args) {
for (int i = 1; i < argsCount; ++i) {
writeLog(std::wstring(L"Argument: ") + args[i]);
if (equal(args[i], L"-update")) {
needupdate = true;
} else if (equal(args[i], L"-autostart")) {
@ -368,17 +369,25 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdPara
} else if (equal(args[i], L"-testmode")) {
testmode = true;
} else if (equal(args[i], L"-writeprotected") && ++i < argsCount) {
writeLog(std::wstring(L"Argument: ") + args[i]);
writeprotected = true;
updateTo = args[i];
for (int i = 0, l = updateTo.size(); i < l; ++i) {
if (updateTo[i] == L'/') {
updateTo[i] = L'\\';
for (int j = 0, l = updateTo.size(); j < l; ++j) {
if (updateTo[j] == L'/') {
updateTo[j] = L'\\';
}
}
} else if (equal(args[i], L"-workdir") && ++i < argsCount) {
writeLog(std::wstring(L"Argument: ") + args[i]);
customWorkingDir = args[i];
} else if (equal(args[i], L"-key") && ++i < argsCount) {
writeLog(std::wstring(L"Argument: ") + args[i]);
customKeyFile = args[i];
} else if (equal(args[i], L"-exename") && ++i < argsCount) {
writeLog(std::wstring(L"Argument: ") + args[i]);
exeName = args[i];
for (int i = 0, l = exeName.size(); i < l; ++i) {
if (exeName[i] == L'/' || exeName[i] == L'\\') {
for (int j = 0, l = exeName.size(); j < l; ++j) {
if (exeName[j] == L'/' || exeName[j] == L'\\') {
exeName = L"Telegram.exe";
break;
}
@ -391,6 +400,7 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdPara
if (needupdate) writeLog(L"Need to update!");
if (autostart) writeLog(L"From autostart!");
if (writeprotected) writeLog(L"Write Protected folder!");
if (!customWorkingDir.empty()) writeLog(L"Will pass custom working dir: " + customWorkingDir);
updaterName = args[0];
writeLog(L"Updater name is: " + updaterName);
@ -428,6 +438,13 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdPara
if (debug) targs += L" -debug";
if (startintray) targs += L" -startintray";
if (testmode) targs += L" -testmode";
if (!customWorkingDir.empty()) {
targs += L" -workdir \"" + customWorkingDir + L"\"";
}
if (!customKeyFile.empty()) {
targs += L" -key \"" + customKeyFile + L"\"";
}
writeLog(L"Result arguments: " + targs);
bool executed = false;
if (writeprotected) { // run un-elevated

View file

@ -344,9 +344,16 @@ string CurrentExecutablePath(int argc, char *argv[]) {
}
int main(int argc, char *argv[]) {
bool needupdate = true, autostart = false, debug = false, tosettings = false, startintray = false, testmode = false;
bool needupdate = true;
bool autostart = false;
bool debug = false;
bool tosettings = false;
bool startintray = false;
bool testmode = false;
bool customWorkingDir = false;
char *key = 0, *crashreport = 0;
char *key = 0;
char *workdir = 0;
for (int i = 1; i < argc; ++i) {
if (equal(argv[i], "-noupdate")) {
needupdate = false;
@ -360,12 +367,12 @@ int main(int argc, char *argv[]) {
testmode = true;
} else if (equal(argv[i], "-tosettings")) {
tosettings = true;
} else if (equal(argv[i], "-workdir_custom")) {
customWorkingDir = true;
} else if (equal(argv[i], "-key") && ++i < argc) {
key = argv[i];
} else if (equal(argv[i], "-workpath") && ++i < argc) {
workDir = argv[i];
} else if (equal(argv[i], "-crashreport") && ++i < argc) {
crashreport = argv[i];
workDir = workdir = argv[i];
} else if (equal(argv[i], "-exename") && ++i < argc) {
exeName = argv[i];
} else if (equal(argv[i], "-exepath") && ++i < argc) {
@ -401,6 +408,8 @@ int main(int argc, char *argv[]) {
}
if (needupdate) {
if (workDir.empty()) { // old app launched, update prepared in tupdates/ready (not in tupdates/temp)
customWorkingDir = false;
writeLog("No workdir, trying to figure it out");
struct passwd *pw = getpwuid(getuid());
if (pw && pw->pw_dir && strlen(pw->pw_dir)) {
@ -446,22 +455,30 @@ int main(int argc, char *argv[]) {
string fullBinaryPath = exePath + exeName;
strcpy(path, fullBinaryPath.c_str());
char *args[MaxArgsCount] = {0}, p_noupdate[] = "-noupdate", p_autostart[] = "-autostart", p_debug[] = "-debug", p_tosettings[] = "-tosettings", p_key[] = "-key", p_startintray[] = "-startintray", p_testmode[] = "-testmode";
char *args[MaxArgsCount] = { 0 };
char p_noupdate[] = "-noupdate";
char p_autostart[] = "-autostart";
char p_debug[] = "-debug";
char p_tosettings[] = "-tosettings";
char p_key[] = "-key";
char p_startintray[] = "-startintray";
char p_testmode[] = "-testmode";
char p_workdir[] = "-workdir";
int argIndex = 0;
args[argIndex++] = path;
if (crashreport) {
args[argIndex++] = crashreport;
} else {
args[argIndex++] = p_noupdate;
if (autostart) args[argIndex++] = p_autostart;
if (debug) args[argIndex++] = p_debug;
if (startintray) args[argIndex++] = p_startintray;
if (testmode) args[argIndex++] = p_testmode;
if (tosettings) args[argIndex++] = p_tosettings;
if (key) {
args[argIndex++] = p_key;
args[argIndex++] = key;
}
args[argIndex++] = p_noupdate;
if (autostart) args[argIndex++] = p_autostart;
if (debug) args[argIndex++] = p_debug;
if (startintray) args[argIndex++] = p_startintray;
if (testmode) args[argIndex++] = p_testmode;
if (tosettings) args[argIndex++] = p_tosettings;
if (key) {
args[argIndex++] = p_key;
args[argIndex++] = key;
}
if (customWorkingDir && workdir) {
args[argIndex++] = p_workdir;
args[argIndex++] = workdir;
}
pid_t pid = fork();
switch (pid) {

View file

@ -23,7 +23,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
NSString *appName = @"Telegram.app";
NSString *appDir = nil;
NSString *workDir = nil;
NSString *crashReportArg = nil;
#ifdef _DEBUG
BOOL _debug = YES;
@ -90,6 +89,7 @@ int main(int argc, const char * argv[]) {
openLog();
pid_t procId = 0;
BOOL update = YES, toSettings = NO, autoStart = NO, startInTray = NO, testMode = NO;
BOOL customWorkingDir = NO;
NSString *key = nil;
for (int i = 0; i < argc; ++i) {
if ([@"-workpath" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
@ -102,10 +102,6 @@ int main(int argc, const char * argv[]) {
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
procId = [[formatter numberFromString:[NSString stringWithUTF8String:argv[i]]] intValue];
}
} else if ([@"-crashreport" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
if (++i < argc) {
crashReportArg = [NSString stringWithUTF8String:argv[i]];
}
} else if ([@"-noupdate" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
update = NO;
} else if ([@"-tosettings" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
@ -118,11 +114,16 @@ int main(int argc, const char * argv[]) {
startInTray = YES;
} else if ([@"-testmode" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
testMode = YES;
} else if ([@"-workdir_custom" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
customWorkingDir = YES;
} else if ([@"-key" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
if (++i < argc) key = [NSString stringWithUTF8String:argv[i]];
}
}
if (!workDir) workDir = appDir;
if (!workDir) {
workDir = appDir;
customWorkingDir = NO;
}
openLog();
NSMutableArray *argsArr = [[NSMutableArray alloc] initWithCapacity:argc];
for (int i = 0; i < argc; ++i) {
@ -242,17 +243,19 @@ int main(int argc, const char * argv[]) {
}
NSString *appPath = [[NSArray arrayWithObjects:appDir, appRealName, nil] componentsJoinedByString:@""];
NSMutableArray *args = [[NSMutableArray alloc] initWithObjects: crashReportArg ? crashReportArg : @"-noupdate", nil];
if (!crashReportArg) {
if (toSettings) [args addObject:@"-tosettings"];
if (_debug) [args addObject:@"-debug"];
if (startInTray) [args addObject:@"-startintray"];
if (testMode) [args addObject:@"-testmode"];
if (autoStart) [args addObject:@"-autostart"];
if (key) {
[args addObject:@"-key"];
[args addObject:key];
}
NSMutableArray *args = [[NSMutableArray alloc] initWithObjects: @"-noupdate", nil];
if (toSettings) [args addObject:@"-tosettings"];
if (_debug) [args addObject:@"-debug"];
if (startInTray) [args addObject:@"-startintray"];
if (testMode) [args addObject:@"-testmode"];
if (autoStart) [args addObject:@"-autostart"];
if (key) {
[args addObject:@"-key"];
[args addObject:key];
}
if (customWorkingDir) {
[args addObject:@"-workdir"];
[args addObject:workDir];
}
writeLog([[NSArray arrayWithObjects:@"Running application '", appPath, @"' with args '", [args componentsJoinedByString:@"' '"], @"'..", nil] componentsJoinedByString:@""]);
NSError *error = nil;

View file

@ -29,6 +29,8 @@ namespace Core {
namespace {
QStringList ReadArguments(int argc, char *argv[]) {
Expects(argc >= 0);
auto result = QStringList();
result.reserve(argc);
for (auto i = 0; i != argc; ++i) {
@ -47,7 +49,7 @@ Launcher::Launcher(int argc, char *argv[])
: _argc(argc)
, _argv(argv)
, _arguments(ReadArguments(argc, argv)) {
InitFromCommandLine(argc, argv);
prepareSettings();
}
void Launcher::init() {
@ -84,12 +86,14 @@ int Launcher::exec() {
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
if (cRestartingUpdate()) {
DEBUG_LOG(("Application Info: executing updater to install update..."));
psExecUpdater();
if (!launchUpdater(UpdaterLaunch::PerformUpdate)) {
psDeleteDir(cWorkingDir() + qsl("tupdates/temp"));
}
} else
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
if (cRestarting()) {
DEBUG_LOG(("Application Info: executing Telegram, because of restart..."));
psExecTelegram();
launchUpdater(UpdaterLaunch::JustRelaunch);
}
CrashReports::Finish();
@ -103,4 +107,134 @@ QString Launcher::argumentsString() const {
return _arguments.join(' ');
}
void Launcher::prepareSettings() {
#ifdef Q_OS_MAC
#ifndef OS_MAC_OLD
if (QSysInfo::macVersion() >= QSysInfo::MV_10_11) {
gIsElCapitan = true;
}
#else // OS_MAC_OLD
if (QSysInfo::macVersion() < QSysInfo::MV_10_7) {
gIsSnowLeopard = true;
}
#endif // OS_MAC_OLD
#endif // Q_OS_MAC
switch (cPlatform()) {
case dbipWindows:
gUpdateURL = QUrl(qsl("http://tdesktop.com/win/tupdates/current"));
#ifndef OS_WIN_STORE
gPlatformString = qsl("Windows");
#else // OS_WIN_STORE
gPlatformString = qsl("WinStore");
#endif // OS_WIN_STORE
break;
case dbipMac:
gUpdateURL = QUrl(qsl("http://tdesktop.com/mac/tupdates/current"));
#ifndef OS_MAC_STORE
gPlatformString = qsl("MacOS");
#else // OS_MAC_STORE
gPlatformString = qsl("MacAppStore");
#endif // OS_MAC_STORE
break;
case dbipMacOld:
gUpdateURL = QUrl(qsl("http://tdesktop.com/mac32/tupdates/current"));
gPlatformString = qsl("MacOSold");
break;
case dbipLinux64:
gUpdateURL = QUrl(qsl("http://tdesktop.com/linux/tupdates/current"));
gPlatformString = qsl("Linux64bit");
break;
case dbipLinux32:
gUpdateURL = QUrl(qsl("http://tdesktop.com/linux32/tupdates/current"));
gPlatformString = qsl("Linux32bit");
break;
}
auto path = Platform::CurrentExecutablePath(_argc, _argv);
LOG(("Executable path before check: %1").arg(path));
if (!path.isEmpty()) {
auto info = QFileInfo(path);
if (info.isSymLink()) {
info = info.symLinkTarget();
}
if (info.exists()) {
gExeDir = info.absoluteDir().absolutePath() + '/';
gExeName = info.fileName();
}
}
if (cExeName().isEmpty()) {
LOG(("WARNING: Could not compute executable path, some features will be disabled."));
}
processArguments();
}
void Launcher::processArguments() {
enum class KeyFormat {
NoValues,
OneValue,
AllLeftValues,
};
auto parseMap = std::map<QByteArray, KeyFormat> {
{ "-testmode" , KeyFormat::NoValues },
{ "-debug" , KeyFormat::NoValues },
{ "-many" , KeyFormat::NoValues },
{ "-key" , KeyFormat::OneValue },
{ "-autostart" , KeyFormat::NoValues },
{ "-fixprevious", KeyFormat::NoValues },
{ "-cleanup" , KeyFormat::NoValues },
{ "-noupdate" , KeyFormat::NoValues },
{ "-tosettings" , KeyFormat::NoValues },
{ "-startintray", KeyFormat::NoValues },
{ "-sendpath" , KeyFormat::AllLeftValues },
{ "-workdir" , KeyFormat::OneValue },
{ "--" , KeyFormat::OneValue },
};
auto parseResult = QMap<QByteArray, QStringList>();
auto parsingKey = QByteArray();
auto parsingFormat = KeyFormat::NoValues;
for (const auto &argument : _arguments) {
switch (parsingFormat) {
case KeyFormat::OneValue: {
parseResult[parsingKey] = QStringList(argument.mid(0, 8192));
parsingFormat = KeyFormat::NoValues;
} break;
case KeyFormat::AllLeftValues: {
parseResult[parsingKey].push_back(argument.mid(0, 8192));
} break;
case KeyFormat::NoValues: {
parsingKey = argument.toLatin1();
auto it = parseMap.find(parsingKey);
if (it != parseMap.end()) {
parsingFormat = it->second;
parseResult[parsingKey] = QStringList();
}
} break;
}
}
gTestMode = parseResult.contains("-testmode");
gDebug = parseResult.contains("-debug");
gManyInstance = parseResult.contains("-many");
gKeyFile = parseResult.value("-key", QStringList()).join(QString());
gLaunchMode = parseResult.contains("-autostart") ? LaunchModeAutoStart
: parseResult.contains("-fixprevious") ? LaunchModeFixPrevious
: parseResult.contains("-cleanup") ? LaunchModeCleanup
: LaunchModeNormal;
gNoStartUpdate = parseResult.contains("-noupdate");
gStartToSettings = parseResult.contains("-tosettings");
gStartInTray = parseResult.contains("-startintray");
gSendPaths = parseResult.value("-sendpath", QStringList());
gWorkingDir = parseResult.value("-workdir", QStringList()).join(QString());
if (!gWorkingDir.isEmpty()) {
if (QDir().exists(gWorkingDir)) {
_customWorkingDir = true;
} else {
gWorkingDir = QString();
}
}
gStartUrl = parseResult.value("--", QStringList()).join(QString());
}
} // namespace Core

View file

@ -31,15 +31,32 @@ public:
int exec();
QString argumentsString() const;
bool customWorkingDir() const {
return _customWorkingDir;
}
protected:
enum class UpdaterLaunch {
PerformUpdate,
JustRelaunch,
};
private:
void prepareSettings();
void processArguments();
void init();
virtual void initHook() = 0;
virtual void initHook() {
}
virtual bool launchUpdater(UpdaterLaunch action) = 0;
int _argc;
char **_argv;
QStringList _arguments;
bool _customWorkingDir = false;
};
} // namespace Core

View file

@ -20,9 +20,98 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "platform/linux/launcher_linux.h"
namespace Platform {
#include "core/crash_reports.h"
void Launcher::initHook() {
#include <sys/stat.h>
#include <sys/types.h>
#include <cstdlib>
#include <unistd.h>
#include <dirent.h>
#include <pwd.h>
namespace Platform {
namespace {
class Arguments {
public:
void push(QByteArray argument) {
argument.append(char(0));
_argumentValues.push_back(argument);
_arguments.push_back(_argumentValues.back().data());
}
char **result() {
_arguments.push_back(nullptr);
return _arguments.data();
}
private:
std::vector<QByteArray> _argumentValues;
std::vector<char*> _arguments;
};
} // namespace
bool Launcher::launchUpdater(UpdaterLaunch action) {
if (cExeName().isEmpty()) {
return false;
}
const auto binaryName = (action == UpdaterLaunch::JustRelaunch)
? cExeName()
: QStringLiteral("Updater");
auto argumentsList = Arguments();
argumentsList.push(QFile::encodeName(cExeDir() + binaryName));
if (cLaunchMode() == LaunchModeAutoStart) {
argumentsList.push("-autostart");
}
if (cDebug()) {
argumentsList.push("-debug");
}
if (cStartInTray()) {
argumentsList.push("-startintray");
}
if (cTestMode()) {
argumentsList.push("-testmode");
}
if (cDataFile() != qsl("data")) {
argumentsList.push("-key");
argumentsList.push(QFile::encodeName(cDataFile()));
}
if (action == UpdaterLaunch::JustRelaunch) {
argumentsList.push("-noupdate");
argumentsList.push("-tosettings");
if (customWorkingDir()) {
argumentsList.push("-workdir");
argumentsList.push(QFile::encodeName(cWorkingDir()));
}
} else {
argumentsList.push("-workpath");
argumentsList.push(QFile::encodeName(cWorkingDir()));
argumentsList.push("-exename");
argumentsList.push(QFile::encodeName(cExeName()));
argumentsList.push("-exepath");
argumentsList.push(QFile::encodeName(cExeDir()));
if (customWorkingDir()) {
argumentsList.push("-workdir_custom");
}
}
Logs::closeMain();
CrashReports::Finish();
const auto args = argumentsList.result();
pid_t pid = fork();
switch (pid) {
case -1: return false;
case 0: execv(args[0], args); return false;
}
return true;
}
} // namespace

View file

@ -29,7 +29,7 @@ public:
using Core::Launcher::Launcher;
private:
void initHook() override;
bool launchUpdater(UpdaterLaunch action) override;
};

View file

@ -526,98 +526,6 @@ void psNewVersion() {
psRegisterCustomScheme();
}
bool _execUpdater(bool update = true, const QString &crashreport = QString()) {
if (cExeName().isEmpty()) {
return false;
}
static const int MaxLen = 65536, MaxArgsCount = 128;
char path[MaxLen] = {0};
QByteArray data(QFile::encodeName(cExeDir() + (update ? "Updater" : cExeName())));
memcpy(path, data.constData(), data.size());
char *args[MaxArgsCount] = { 0 };
char p_noupdate[] = "-noupdate";
char p_autostart[] = "-autostart";
char p_debug[] = "-debug";
char p_tosettings[] = "-tosettings";
char p_key[] = "-key";
char p_datafile[MaxLen] = { 0 };
char p_path[] = "-workpath";
char p_pathbuf[MaxLen] = { 0 };
char p_startintray[] = "-startintray";
char p_testmode[] = "-testmode";
char p_crashreport[] = "-crashreport";
char p_crashreportbuf[MaxLen] = { 0 };
char p_exe[] = "-exename";
char p_exebuf[MaxLen] = { 0 };
char p_exepath[] = "-exepath";
char p_exepathbuf[MaxLen] = { 0 };
int argIndex = 0;
args[argIndex++] = path;
if (!update) {
args[argIndex++] = p_noupdate;
args[argIndex++] = p_tosettings;
}
if (cLaunchMode() == LaunchModeAutoStart) args[argIndex++] = p_autostart;
if (cDebug()) args[argIndex++] = p_debug;
if (cStartInTray()) args[argIndex++] = p_startintray;
if (cTestMode()) args[argIndex++] = p_testmode;
if (cDataFile() != qsl("data")) {
QByteArray dataf = QFile::encodeName(cDataFile());
if (dataf.size() < MaxLen) {
memcpy(p_datafile, dataf.constData(), dataf.size());
args[argIndex++] = p_key;
args[argIndex++] = p_datafile;
}
}
QByteArray pathf = QFile::encodeName(cWorkingDir());
if (pathf.size() < MaxLen) {
memcpy(p_pathbuf, pathf.constData(), pathf.size());
args[argIndex++] = p_path;
args[argIndex++] = p_pathbuf;
}
if (!crashreport.isEmpty()) {
QByteArray crashreportf = QFile::encodeName(crashreport);
if (crashreportf.size() < MaxLen) {
memcpy(p_crashreportbuf, crashreportf.constData(), crashreportf.size());
args[argIndex++] = p_crashreport;
args[argIndex++] = p_crashreportbuf;
}
}
QByteArray exef = QFile::encodeName(cExeName());
if (exef.size() > 0 && exef.size() < MaxLen) {
memcpy(p_exebuf, exef.constData(), exef.size());
args[argIndex++] = p_exe;
args[argIndex++] = p_exebuf;
}
QByteArray exepathf = QFile::encodeName(cExeDir());
if (exepathf.size() > 0 && exepathf.size() < MaxLen) {
memcpy(p_exepathbuf, exepathf.constData(), exepathf.size());
args[argIndex++] = p_exepath;
args[argIndex++] = p_exepathbuf;
}
Logs::closeMain();
CrashReports::Finish();
pid_t pid = fork();
switch (pid) {
case -1: return false;
case 0: execv(path, args); return false;
}
return true;
}
void psExecUpdater() {
if (!_execUpdater()) {
psDeleteDir(cWorkingDir() + qsl("tupdates/temp"));
}
}
void psExecTelegram(const QString &crashreport) {
_execUpdater(false, crashreport);
}
bool psShowOpenWithMenu(int x, int y, const QString &file) {
return false;
}

View file

@ -77,9 +77,6 @@ void psBringToBack(QWidget *w);
int psCleanup();
int psFixPrevious();
void psExecUpdater();
void psExecTelegram(const QString &arg = QString());
QAbstractNativeEventFilter *psNativeEventFilter();
void psNewVersion();

View file

@ -31,6 +31,8 @@ public:
private:
void initHook() override;
bool launchUpdater(UpdaterLaunch action) override;
};
} // namespace Platform

View file

@ -20,6 +20,12 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "platform/mac/launcher_mac.h"
#include "core/crash_reports.h"
#include "platform/mac/mac_utilities.h"
#include <Cocoa/Cocoa.h>
#include <CoreFoundation/CFURL.h>
namespace Platform {
void Launcher::initHook() {
@ -29,4 +35,64 @@ void Launcher::initHook() {
#endif // OS_MAC_OLD
}
bool Launcher::launchUpdater(UpdaterLaunch action) {
if (cExeName().isEmpty()) {
return false;
}
@autoreleasepool {
#ifdef OS_MAC_STORE
// In AppStore version we don't have Updater.
// We just relaunch our app.
if (action == UpdaterLaunch::JustRelaunch) {
NSDictionary *conf = [NSDictionary dictionaryWithObject:[NSArray array] forKey:NSWorkspaceLaunchConfigurationArguments];
[[NSWorkspace sharedWorkspace] launchApplicationAtURL:[NSURL fileURLWithPath:Q2NSString(cExeDir() + cExeName())] options:NSWorkspaceLaunchAsync | NSWorkspaceLaunchNewInstance configuration:conf error:0];
return true;
}
#endif // OS_MAC_STORE
NSString *path = @"", *args = @"";
@try {
path = [[NSBundle mainBundle] bundlePath];
if (!path) {
LOG(("Could not get bundle path!!"));
return false;
}
path = [path stringByAppendingString:@"/Contents/Frameworks/Updater"];
NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:@"-workpath", Q2NSString(cWorkingDir()), @"-procid", nil];
[args addObject:[NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]]];
if (cRestartingToSettings()) [args addObject:@"-tosettings"];
if (action == UpdaterLaunch::JustRelaunch) [args addObject:@"-noupdate"];
if (cLaunchMode() == LaunchModeAutoStart) [args addObject:@"-autostart"];
if (cDebug()) [args addObject:@"-debug"];
if (cStartInTray()) [args addObject:@"-startintray"];
if (cTestMode()) [args addObject:@"-testmode"];
if (cDataFile() != qsl("data")) {
[args addObject:@"-key"];
[args addObject:Q2NSString(cDataFile())];
}
if (customWorkingDir()) {
[args addObject:@"-workdir_custom"];
}
DEBUG_LOG(("Application Info: executing %1 %2").arg(NS2QString(path)).arg(NS2QString([args componentsJoinedByString:@" "])));
Logs::closeMain();
CrashReports::Finish();
if (![NSTask launchedTaskWithLaunchPath:path arguments:args]) {
DEBUG_LOG(("Task not launched while executing %1 %2").arg(NS2QString(path)).arg(NS2QString([args componentsJoinedByString:@" "])));
return false;
}
}
@catch (NSException *exception) {
LOG(("Exception caught while executing %1 %2").arg(NS2QString(path)).arg(NS2QString(args)));
return false;
}
@finally {
}
}
return true;
}
} // namespace Platform

View file

@ -78,9 +78,6 @@ void psBringToBack(QWidget *w);
int psCleanup();
int psFixPrevious();
void psExecUpdater();
void psExecTelegram(const QString &crashreport = QString());
bool psShowOpenWithMenu(int x, int y, const QString &file);
QAbstractNativeEventFilter *psNativeEventFilter();

View file

@ -412,16 +412,6 @@ void psNewVersion() {
objc_registerCustomScheme();
}
void psExecUpdater() {
if (!objc_execUpdater()) {
psDeleteDir(cWorkingDir() + qsl("tupdates/temp"));
}
}
void psExecTelegram(const QString &crashreport) {
objc_execTelegram(crashreport);
}
void psAutoStart(bool start, bool silent) {
}

View file

@ -32,8 +32,6 @@ bool objc_idleTime(TimeMs &idleTime);
void objc_start();
void objc_ignoreApplicationActivationRightNow();
void objc_finish();
bool objc_execUpdater();
void objc_execTelegram(const QString &crashreport);
void objc_registerCustomScheme();

View file

@ -411,74 +411,6 @@ void objc_registerCustomScheme() {
#endif // !TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME
}
BOOL _execUpdater(BOOL update = YES, const QString &crashreport = QString()) {
@autoreleasepool {
NSString *path = @"", *args = @"";
@try {
path = [[NSBundle mainBundle] bundlePath];
if (!path) {
LOG(("Could not get bundle path!!"));
return NO;
}
path = [path stringByAppendingString:@"/Contents/Frameworks/Updater"];
NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:@"-workpath", Q2NSString(cWorkingDir()), @"-procid", nil];
[args addObject:[NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]]];
if (cRestartingToSettings()) [args addObject:@"-tosettings"];
if (!update) [args addObject:@"-noupdate"];
if (cLaunchMode() == LaunchModeAutoStart) [args addObject:@"-autostart"];
if (cDebug()) [args addObject:@"-debug"];
if (cStartInTray()) [args addObject:@"-startintray"];
if (cTestMode()) [args addObject:@"-testmode"];
if (cDataFile() != qsl("data")) {
[args addObject:@"-key"];
[args addObject:Q2NSString(cDataFile())];
}
if (!crashreport.isEmpty()) {
[args addObject:@"-crashreport"];
[args addObject:Q2NSString(crashreport)];
}
DEBUG_LOG(("Application Info: executing %1 %2").arg(NS2QString(path)).arg(NS2QString([args componentsJoinedByString:@" "])));
Logs::closeMain();
CrashReports::Finish();
if (![NSTask launchedTaskWithLaunchPath:path arguments:args]) {
DEBUG_LOG(("Task not launched while executing %1 %2").arg(NS2QString(path)).arg(NS2QString([args componentsJoinedByString:@" "])));
return NO;
}
}
@catch (NSException *exception) {
LOG(("Exception caught while executing %1 %2").arg(NS2QString(path)).arg(NS2QString(args)));
return NO;
}
@finally {
}
}
return YES;
}
bool objc_execUpdater() {
return !!_execUpdater();
}
void objc_execTelegram(const QString &crashreport) {
if (cExeName().isEmpty()) {
return;
}
#ifndef OS_MAC_STORE
_execUpdater(NO, crashreport);
#else // OS_MAC_STORE
@autoreleasepool {
NSDictionary *conf = [NSDictionary dictionaryWithObject:[NSArray array] forKey:NSWorkspaceLaunchConfigurationArguments];
[[NSWorkspace sharedWorkspace] launchApplicationAtURL:[NSURL fileURLWithPath:Q2NSString(cExeDir() + cExeName())] options:NSWorkspaceLaunchAsync | NSWorkspaceLaunchNewInstance configuration:conf error:0];
}
#endif // OS_MAC_STORE
}
void objc_activateProgram(WId winId) {
[NSApp activateIgnoringOtherApps:YES];
if (winId) {

View file

@ -20,9 +20,107 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "platform/win/launcher_win.h"
#include "core/crash_reports.h"
#include "platform/platform_specific.h"
#include <shellapi.h>
namespace Platform {
void Launcher::initHook() {
bool Launcher::launchUpdater(UpdaterLaunch action) {
if (cExeName().isEmpty()) {
return false;
}
const auto operation = (action == UpdaterLaunch::JustRelaunch)
? QString()
: (cWriteProtected()
? qsl("runas")
: QString());
const auto binaryPath = (action == UpdaterLaunch::JustRelaunch)
? (cExeDir() + cExeName())
: (cWriteProtected()
? (cWorkingDir() + qsl("tupdates/temp/Updater.exe"))
: (cExeDir() + qsl("Updater.exe")));
auto argumentsList = QStringList();
const auto pushArgument = [&](const QString &argument) {
argumentsList.push_back(argument.trimmed());
};
if (cLaunchMode() == LaunchModeAutoStart) {
pushArgument(qsl("-autostart"));
}
if (cDebug()) {
pushArgument(qsl("-debug"));
}
if (cStartInTray()) {
pushArgument(qsl("-startintray"));
}
if (cTestMode()) {
pushArgument(qsl("-testmode"));
}
if (customWorkingDir()) {
pushArgument(qsl("-workdir"));
pushArgument('"' + cWorkingDir() + '"');
}
if (cDataFile() != qsl("data")) {
pushArgument(qsl("-key"));
pushArgument('"' + cDataFile() + '"');
}
if (action == UpdaterLaunch::JustRelaunch) {
pushArgument(qsl("-noupdate"));
if (cRestartingToSettings()) {
pushArgument(qsl("-tosettings"));
}
} else {
pushArgument(qsl("-update"));
pushArgument(qsl("-exename"));
pushArgument('"' + cExeName() + '"');
if (cWriteProtected()) {
pushArgument(qsl("-writeprotected"));
pushArgument('"' + cExeDir() + '"');
}
}
return launch(operation, binaryPath, argumentsList);
}
bool Launcher::launch(
const QString &operation,
const QString &binaryPath,
const QStringList &argumentsList) {
const auto convertPath = [](const QString &path) {
return QDir::toNativeSeparators(path).toStdWString();
};
const auto nativeBinaryPath = convertPath(binaryPath);
const auto nativeWorkingDir = convertPath(cWorkingDir());
const auto arguments = argumentsList.join(' ');
DEBUG_LOG(("Application Info: executing %1 %2"
).arg(binaryPath
).arg(arguments
));
Logs::closeMain();
CrashReports::Finish();
const auto hwnd = HWND(0);
const auto result = ShellExecute(
hwnd,
operation.isEmpty() ? nullptr : operation.toStdWString().c_str(),
nativeBinaryPath.c_str(),
arguments.toStdWString().c_str(),
nativeWorkingDir.empty() ? nullptr : nativeWorkingDir.c_str(),
SW_SHOWNORMAL);
if (long(result) < 32) {
DEBUG_LOG(("Application Error: failed to execute %1, working directory: '%2', result: %3"
).arg(binaryPath
).arg(cWorkingDir()
).arg(long(result)
));
return false;
}
return true;
}
} // namespace

View file

@ -29,7 +29,12 @@ public:
using Core::Launcher::Launcher;
private:
void initHook() override;
bool launchUpdater(UpdaterLaunch action) override;
bool launch(
const QString &operation,
const QString &binaryPath,
const QStringList &argumentsList);
};

View file

@ -648,53 +648,6 @@ void psNewVersion() {
}
}
void psExecUpdater() {
if (cExeName().isEmpty()) {
return;
}
QString targs = qsl("-update -exename \"") + cExeName() + '"';
if (cLaunchMode() == LaunchModeAutoStart) targs += qsl(" -autostart");
if (cDebug()) targs += qsl(" -debug");
if (cStartInTray()) targs += qsl(" -startintray");
if (cWriteProtected()) targs += qsl(" -writeprotected \"") + cExeDir() + '"';
QString updaterPath = cWriteProtected() ? (cWorkingDir() + qsl("tupdates/temp/Updater.exe")) : (cExeDir() + qsl("Updater.exe"));
QString updater(QDir::toNativeSeparators(updaterPath)), wdir(QDir::toNativeSeparators(cWorkingDir()));
DEBUG_LOG(("Application Info: executing %1 %2").arg(cExeDir() + "Updater.exe").arg(targs));
HINSTANCE r = ShellExecute(0, cWriteProtected() ? L"runas" : 0, updater.toStdWString().c_str(), targs.toStdWString().c_str(), wdir.isEmpty() ? 0 : wdir.toStdWString().c_str(), SW_SHOWNORMAL);
if (long(r) < 32) {
DEBUG_LOG(("Application Error: failed to execute %1, working directory: '%2', result: %3").arg(updater).arg(wdir).arg(long(r)));
psDeleteDir(cWorkingDir() + qsl("tupdates/temp"));
}
}
void psExecTelegram(const QString &crashreport) {
if (cExeName().isEmpty()) {
return;
}
QString targs = crashreport.isEmpty() ? qsl("-noupdate") : ('"' + crashreport + '"');
if (crashreport.isEmpty()) {
if (cRestartingToSettings()) targs += qsl(" -tosettings");
if (cLaunchMode() == LaunchModeAutoStart) targs += qsl(" -autostart");
if (cDebug()) targs += qsl(" -debug");
if (cStartInTray()) targs += qsl(" -startintray");
if (cTestMode()) targs += qsl(" -testmode");
if (cDataFile() != qsl("data")) targs += qsl(" -key \"") + cDataFile() + '"';
}
QString telegram(QDir::toNativeSeparators(cExeDir() + cExeName())), wdir(QDir::toNativeSeparators(cWorkingDir()));
DEBUG_LOG(("Application Info: executing %1 %2").arg(cExeDir() + cExeName()).arg(targs));
Logs::closeMain();
CrashReports::Finish();
HINSTANCE r = ShellExecute(0, 0, telegram.toStdWString().c_str(), targs.toStdWString().c_str(), wdir.isEmpty() ? 0 : wdir.toStdWString().c_str(), SW_SHOWNORMAL);
if (long(r) < 32) {
DEBUG_LOG(("Application Error: failed to execute %1, working directory: '%2', result: %3").arg(telegram).arg(wdir).arg(long(r)));
}
}
void _manageAppLnk(bool create, bool silent, int path_csidl, const wchar_t *args, const wchar_t *description) {
if (cExeName().isEmpty()) {
return;

View file

@ -90,9 +90,6 @@ void psBringToBack(QWidget *w);
int psCleanup();
int psFixPrevious();
void psExecUpdater();
void psExecTelegram(const QString &arg = QString());
QAbstractNativeEventFilter *psNativeEventFilter();
void psNewVersion();

View file

@ -61,7 +61,9 @@ uint32 gConnectionsInSession = 1;
QString gLoggedPhoneNumber;
QByteArray gLocalSalt;
DBIScale gRealScale = dbisAuto, gScreenScale = dbisOne, gConfigScale = dbisAuto;
DBIScale gRealScale = dbisAuto;
DBIScale gScreenScale = dbisOne;
DBIScale gConfigScale = dbisAuto;
bool gCompressPastedImage = true;
QString gTimeFormat = qsl("hh:mm");
@ -87,6 +89,8 @@ int32 gIntRetinaFactor = 1;
#ifdef Q_OS_WIN
DBIPlatform gPlatform = dbipWindows;
#elif defined OS_MAC_OLD
DBIPlatform gPlatform = dbipMacOld;
#elif defined Q_OS_MAC
DBIPlatform gPlatform = dbipMac;
#elif defined Q_OS_LINUX64
@ -112,137 +116,3 @@ int32 gAutoDownloadPhoto = 0; // all auto download
int32 gAutoDownloadAudio = 0;
int32 gAutoDownloadGif = 0;
bool gAutoPlayGif = true;
void ParseCommandLineArguments(const QStringList &arguments) {
enum class KeyFormat {
NoValues,
OneValue,
AllLeftValues,
};
auto parseMap = std::map<QByteArray, KeyFormat> {
{ "-testmode" , KeyFormat::NoValues },
{ "-debug" , KeyFormat::NoValues },
{ "-many" , KeyFormat::NoValues },
{ "-key" , KeyFormat::OneValue },
{ "-autostart" , KeyFormat::NoValues },
{ "-fixprevious", KeyFormat::NoValues },
{ "-cleanup" , KeyFormat::NoValues },
{ "-noupdate" , KeyFormat::NoValues },
{ "-tosettings" , KeyFormat::NoValues },
{ "-startintray", KeyFormat::NoValues },
{ "-sendpath" , KeyFormat::AllLeftValues },
{ "-workdir" , KeyFormat::OneValue },
{ "--" , KeyFormat::OneValue },
};
auto parseResult = QMap<QByteArray, QStringList>();
auto parsingKey = QByteArray();
auto parsingFormat = KeyFormat::NoValues;
for (auto &argument : arguments) {
switch (parsingFormat) {
case KeyFormat::OneValue: {
parseResult[parsingKey] = QStringList(argument.mid(0, 8192));
parsingFormat = KeyFormat::NoValues;
} break;
case KeyFormat::AllLeftValues: {
parseResult[parsingKey].push_back(argument.mid(0, 8192));
} break;
case KeyFormat::NoValues: {
parsingKey = argument.toLatin1();
auto it = parseMap.find(parsingKey);
if (it != parseMap.end()) {
parsingFormat = it->second;
parseResult[parsingKey] = QStringList();
}
} break;
}
}
gTestMode = parseResult.contains("-testmode");
gDebug = parseResult.contains("-debug");
gManyInstance = parseResult.contains("-many");
gKeyFile = parseResult.value("-key", QStringList()).join(QString());
gLaunchMode = parseResult.contains("-autostart") ? LaunchModeAutoStart
: parseResult.contains("-fixprevious") ? LaunchModeFixPrevious
: parseResult.contains("-cleanup") ? LaunchModeCleanup
: LaunchModeNormal;
gNoStartUpdate = parseResult.contains("-noupdate");
gStartToSettings = parseResult.contains("-tosettings");
gStartInTray = parseResult.contains("-startintray");
gSendPaths = parseResult.value("-sendpath", QStringList());
gWorkingDir = parseResult.value("-workdir", QStringList()).join(QString());
if (!gWorkingDir.isEmpty() && !QDir().exists(gWorkingDir)) {
gWorkingDir = QString();
}
gStartUrl = parseResult.value("--", QStringList()).join(QString());
}
void InitFromCommandLine(int argc, char *argv[]) {
Expects(argc >= 0);
auto arguments = QStringList();
arguments.reserve(argc);
for (auto i = 0; i != argc; ++i) {
arguments.push_back(fromUtf8Safe(argv[i]));
}
#ifdef Q_OS_MAC
#ifndef OS_MAC_OLD
if (QSysInfo::macVersion() >= QSysInfo::MV_10_11) {
gIsElCapitan = true;
}
#else // OS_MAC_OLD
if (QSysInfo::macVersion() < QSysInfo::MV_10_7) {
gIsSnowLeopard = true;
}
gPlatform = dbipMacOld;
#endif // OS_MAC_OLD
#endif // Q_OS_MAC
switch (cPlatform()) {
case dbipWindows:
gUpdateURL = QUrl(qsl("http://tdesktop.com/win/tupdates/current"));
#ifndef OS_WIN_STORE
gPlatformString = qsl("Windows");
#else // OS_WIN_STORE
gPlatformString = qsl("WinStore");
#endif // OS_WIN_STORE
break;
case dbipMac:
gUpdateURL = QUrl(qsl("http://tdesktop.com/mac/tupdates/current"));
#ifndef OS_MAC_STORE
gPlatformString = qsl("MacOS");
#else // OS_MAC_STORE
gPlatformString = qsl("MacAppStore");
#endif // OS_MAC_STORE
break;
case dbipMacOld:
gUpdateURL = QUrl(qsl("http://tdesktop.com/mac32/tupdates/current"));
gPlatformString = qsl("MacOSold");
break;
case dbipLinux64:
gUpdateURL = QUrl(qsl("http://tdesktop.com/linux/tupdates/current"));
gPlatformString = qsl("Linux64bit");
break;
case dbipLinux32:
gUpdateURL = QUrl(qsl("http://tdesktop.com/linux32/tupdates/current"));
gPlatformString = qsl("Linux32bit");
break;
}
auto path = Platform::CurrentExecutablePath(argc, argv);
LOG(("Executable path before check: %1").arg(path));
if (!path.isEmpty()) {
auto info = QFileInfo(path);
if (info.isSymLink()) {
info = info.symLinkTarget();
}
if (info.exists()) {
gExeDir = info.absoluteDir().absolutePath() + '/';
gExeName = info.fileName();
}
}
if (cExeName().isEmpty()) {
LOG(("WARNING: Could not compute executable path, some features will be disabled."));
}
ParseCommandLineArguments(arguments);
}

View file

@ -28,7 +28,7 @@ else
#gyp --depth=. --generator-output=../.. -Goutput_dir=out Telegram.gyp --format=xcode-ninja
#gyp --depth=. --generator-output=../.. -Goutput_dir=out Telegram.gyp --format=xcode
# use patched gyp with Xcode project generator
../../../Libraries/gyp/gyp --depth=. --generator-output=.. -Goutput_dir=../out -Gxcode_upgrade_check_project_version=910 -Dofficial_build_target=$BuildTarget Telegram.gyp --format=xcode
../../../Libraries/gyp/gyp --depth=. --generator-output=.. -Goutput_dir=../out -Gxcode_upgrade_check_project_version=920 -Dofficial_build_target=$BuildTarget Telegram.gyp --format=xcode
fi
cd ../..