Exemple #1
0
void Application::startUpdateCheck(bool forceWait) {
	updateCheckTimer.stop();
	if (updateRequestId || updateThread || updateReply || !cAutoUpdate()) return;
	
	int32 updateInSecs = cLastUpdateCheck() + 3600 + (rand() % 3600) - unixtime();
	bool sendRequest = (updateInSecs <= 0 || updateInSecs > 7200);
	if (!sendRequest && !forceWait) {
		QDir updates(cWorkingDir() + "tupdates");
		if (updates.exists()) {
			QFileInfoList list = updates.entryInfoList(QDir::Files);
			for (QFileInfoList::iterator i = list.begin(), e = list.end(); i != e; ++i) {
                if (QRegularExpression("^(tupdate|tmacupd|tlinuxupd|tlinux32upd)\\d+$", QRegularExpression::CaseInsensitiveOption).match(i->fileName()).hasMatch()) {
					sendRequest = true;
				}
			}
		}
	}
    if (cManyInstance() && !cDebug()) return; // only main instance is updating

	if (sendRequest) {
		QNetworkRequest checkVersion(cUpdateURL());
		if (updateReply) updateReply->deleteLater();

		App::setProxySettings(updateManager);
		updateReply = updateManager.get(checkVersion);
		connect(updateReply, SIGNAL(finished()), this, SLOT(updateGotCurrent()));
		connect(updateReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(updateFailedCurrent(QNetworkReply::NetworkError)));
//		updateRequestId = MTP::send(MTPhelp_GetAppUpdate(MTP_string(cApiDeviceModel()), MTP_string(cApiSystemVersion()), MTP_string(cApiAppVersion()), MTP_string(cApiLang())), rpcDone(&Application::onAppUpdate), rpcFail(&Application::onAppUpdateFail);
		emit updateChecking();
	} else {
		updateCheckTimer.start((updateInSecs + 5) * 1000);
	}
}
bool validateShortcut() {
	QString path = systemShortcutPath();
	if (path.isEmpty() || cExeName().isEmpty()) return false;

	if (cAlphaVersion()) {
		path += qsl("TelegramAlpha.lnk");
		if (validateShortcutAt(path)) return true;
	} else {
		if (validateShortcutAt(path + qsl("Telegram Desktop/Telegram.lnk"))) return true;
		if (validateShortcutAt(path + qsl("Telegram Win (Unofficial)/Telegram.lnk"))) return true;

		path += qsl("Telegram.lnk");
		if (validateShortcutAt(path)) return true;
	}

	ComPtr<IShellLink> shellLink;
	HRESULT hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink));
	if (!SUCCEEDED(hr)) return false;

	hr = shellLink->SetPath(QDir::toNativeSeparators(cExeDir() + cExeName()).toStdWString().c_str());
	if (!SUCCEEDED(hr)) return false;

	hr = shellLink->SetArguments(L"");
	if (!SUCCEEDED(hr)) return false;

	hr = shellLink->SetWorkingDirectory(QDir::toNativeSeparators(QDir(cWorkingDir()).absolutePath()).toStdWString().c_str());
	if (!SUCCEEDED(hr)) return false;

	ComPtr<IPropertyStore> propertyStore;
	hr = shellLink.As(&propertyStore);
	if (!SUCCEEDED(hr)) return false;

	PROPVARIANT appIdPropVar;
	hr = InitPropVariantFromString(getId(), &appIdPropVar);
	if (!SUCCEEDED(hr)) return false;

	hr = propertyStore->SetValue(getKey(), appIdPropVar);
	PropVariantClear(&appIdPropVar);
	if (!SUCCEEDED(hr)) return false;

	PROPVARIANT startPinPropVar;
	hr = InitPropVariantFromUInt32(APPUSERMODEL_STARTPINOPTION_NOPINONINSTALL, &startPinPropVar);
	if (!SUCCEEDED(hr)) return false;

	hr = propertyStore->SetValue(pkey_AppUserModel_StartPinOption, startPinPropVar);
	PropVariantClear(&startPinPropVar);
	if (!SUCCEEDED(hr)) return false;

	hr = propertyStore->Commit();
	if (!SUCCEEDED(hr)) return false;

	ComPtr<IPersistFile> persistFile;
	hr = shellLink.As(&persistFile);
	if (!SUCCEEDED(hr)) return false;

	hr = persistFile->Save(QDir::toNativeSeparators(path).toStdWString().c_str(), TRUE);
	if (!SUCCEEDED(hr)) return false;

	return true;
}
Exemple #3
0
int Launcher::exec() {
	init();

	if (cLaunchMode() == LaunchModeFixPrevious) {
		return psFixPrevious();
	} else if (cLaunchMode() == LaunchModeCleanup) {
		return psCleanup();
	}

	// both are finished in Application::closeApplication
	Logs::start(this); // must be started before Platform is started
	Platform::start(); // must be started before QApplication is created

	auto result = executeApplication();

	DEBUG_LOG(("Telegram finished, result: %1").arg(result));

	if (!UpdaterDisabled() && cRestartingUpdate()) {
		DEBUG_LOG(("Application Info: executing updater to install update..."));
		if (!launchUpdater(UpdaterLaunch::PerformUpdate)) {
			psDeleteDir(cWorkingDir() + qsl("tupdates/temp"));
		}
	} else if (cRestarting()) {
		DEBUG_LOG(("Application Info: executing Telegram, because of restart..."));
		launchUpdater(UpdaterLaunch::JustRelaunch);
	}

	CrashReports::Finish();
	Platform::finish();
	Logs::finish();

	return result;
}
QString CachedUserpics::get(const StorageKey &key, PeerData *peer) {
	auto ms = getms(true);
	auto i = _images.find(key);
	if (i != _images.cend()) {
		if (i->until) {
			i->until = ms + kNotifyDeletePhotoAfterMs;
			clearInMs(-kNotifyDeletePhotoAfterMs);
		}
	} else {
		Image v;
		if (key.first) {
			v.until = ms + kNotifyDeletePhotoAfterMs;
			clearInMs(-kNotifyDeletePhotoAfterMs);
		} else {
			v.until = 0;
		}
		v.path = cWorkingDir() + qsl("tdata/temp/") + QString::number(rand_value<uint64>(), 16) + qsl(".png");
		if (key.first || key.second) {
			if (_type == Type::Rounded) {
				peer->saveUserpicRounded(v.path, st::notifyMacPhotoSize);
			} else {
				peer->saveUserpic(v.path, st::notifyMacPhotoSize);
			}
		} else {
			App::wnd()->iconLarge().save(v.path, "PNG");
		}
		i = _images.insert(key, v);
		_someSavedFlag = true;
	}
	return i->path;
}
Exemple #5
0
void Application::updateGotCurrent() {
	if (!updateReply || updateThread) return;

	cSetLastUpdateCheck(unixtime());
	QRegularExpressionMatch m = QRegularExpression(qsl("^\\s*(\\d+)\\s*:\\s*([\\x21-\\x7f]+)\\s*$")).match(QString::fromUtf8(updateReply->readAll()));
	if (m.hasMatch()) {
		int32 currentVersion = m.captured(1).toInt();
		if (currentVersion > AppVersion) {
			updateThread = new QThread();
			connect(updateThread, SIGNAL(finished()), updateThread, SLOT(deleteLater()));
			updateDownloader = new PsUpdateDownloader(updateThread, m.captured(2));
			updateThread->start();
		}
	}
	if (updateReply) updateReply->deleteLater();
	updateReply = 0;
	if (!updateThread) {
		QDir updates(cWorkingDir() + "tupdates");
		if (updates.exists()) {
			QFileInfoList list = updates.entryInfoList(QDir::Files);
			for (QFileInfoList::iterator i = list.begin(), e = list.end(); i != e; ++i) {
                if (QRegularExpression("^(tupdate|tmacupd|tlinuxupd|tlinux32upd)\\d+$", QRegularExpression::CaseInsensitiveOption).match(i->fileName()).hasMatch()) {
					QFile(i->absoluteFilePath()).remove();
				}
			}
		}
		emit updateLatest();
	}
	startUpdateCheck(true);
	App::writeConfig();
}
Exemple #6
0
void logsInit() {
	static _StreamCreator streamCreator;
	if (mainLogStream) return;

    QString wasDir = cWorkingDir();
#if (defined Q_OS_MAC || defined Q_OS_LINUX)

#ifdef _DEBUG
    cForceWorkingDir(cExeDir());
#else
    cForceWorkingDir(psAppDataPath());
#endif

#if (defined Q_OS_LINUX && !defined _DEBUG) // fix first version
	moveOldDataFiles(wasDir);
#endif
#endif

    QString rightDir = cWorkingDir();
    cForceWorkingDir(rightDir);
	mainLog.setFileName(cWorkingDir() + "log.txt");
	mainLog.open(QIODevice::WriteOnly | QIODevice::Text);
	if (!mainLog.isOpen()) {
		cForceWorkingDir(cExeDir());
		mainLog.setFileName(cWorkingDir() + "log.txt");
		mainLog.open(QIODevice::WriteOnly | QIODevice::Text);
		if (!mainLog.isOpen()) {
			cForceWorkingDir(psAppDataPath());
			mainLog.setFileName(cWorkingDir() + "log.txt");
			mainLog.open(QIODevice::WriteOnly | QIODevice::Text);
		}
	}
	if (mainLog.isOpen()) {
		mainLogStream = new QTextStream();
		mainLogStream->setDevice(&mainLog);
		mainLogStream->setCodec("UTF-8");
	} else {
        cForceWorkingDir(rightDir);
	}
	cForceWorkingDir(QDir(cWorkingDir()).absolutePath() + '/');

#ifdef Q_OS_WIN
	if (cWorkingDir() == psAppDataPath()) { // fix old "Telegram Win (Unofficial)" version
		moveOldDataFiles(psAppDataPathOld());
	}
#endif
	if (cDebug()) {
		logsInitDebug();
	} else if (QFile(cWorkingDir() + qsl("tdata/withdebug")).exists()) {
		logsInitDebug();
		cSetDebug(true);
	}
}
Exemple #7
0
void PsUpdateDownloader::initOutput() {
	QString fileName;
	QRegularExpressionMatch m = QRegularExpression(qsl("/([^/\\?]+)(\\?|$)")).match(updateUrl);
	if (m.hasMatch()) {
		fileName = m.captured(1).replace(QRegularExpression(qsl("[^a-zA-Z0-9_\\-]")), QString());
	}
	if (fileName.isEmpty()) {
		fileName = qsl("tupdate-%1").arg(rand());
	}
	QString dirStr = cWorkingDir() + qsl("tupdates/");
	fileName = dirStr + fileName;
	QFileInfo file(fileName);

	QDir dir(dirStr);
	if (dir.exists()) {
		QFileInfoList all = dir.entryInfoList(QDir::Files);
		for (QFileInfoList::iterator i = all.begin(), e = all.end(); i != e; ++i) {
			if (i->absoluteFilePath() != file.absoluteFilePath()) {
				QFile::remove(i->absoluteFilePath());
			}
		}
	} else {
		dir.mkdir(dir.absolutePath());
	}
	outputFile.setFileName(fileName);
	if (file.exists()) {
		uint64 fullSize = file.size();
		if (fullSize < INT_MAX) {
			int32 goodSize = (int32)fullSize;
			if (goodSize % UpdateChunk) {
				goodSize = goodSize - (goodSize % UpdateChunk);
				if (goodSize) {
					if (outputFile.open(QIODevice::ReadOnly)) {
						QByteArray goodData = outputFile.readAll().mid(0, goodSize);
						outputFile.close();
						if (outputFile.open(QIODevice::WriteOnly)) {
							outputFile.write(goodData);
							outputFile.close();

							QMutexLocker lock(&mutex);
							already = goodSize;
						}
					}
				}
			} else {
				QMutexLocker lock(&mutex);
				already = goodSize;
			}
		}
		if (!already) {
			QFile::remove(fileName);
		}
	}
}
Exemple #8
0
void Application::onEnableDebugMode() {
	if (!cDebug()) {
		logsInitDebug();
		cSetDebug(true);
		QFile f(cWorkingDir() + qsl("tdata/withdebug"));
		if (f.open(QIODevice::WriteOnly)) {
			f.write("1");
			f.close();
		}
	}
	App::wnd()->hideLayer();
}
Exemple #9
0
void installSignalHandlers() {
	_crashDump = fopen((cWorkingDir() + qsl("tdata/working")).toUtf8().constData(), "wb");
	if (_crashDump) _crashDumpNo = fileno(_crashDump);

	signal(SIGABRT, _signalHandler);
	signal(SIGSEGV, _signalHandler);
	signal(SIGILL, _signalHandler);
	signal(SIGFPE, _signalHandler);
#ifndef Q_OS_WIN
	signal(SIGBUS, _signalHandler);
	signal(SIGSYS, _signalHandler);
#endif
}
Exemple #10
0
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;
}
Exemple #11
0
bool _execUpdater(bool update = true) {
    static const int MaxLen = 65536, MaxArgsCount = 128;

    char path[MaxLen] = {0};
    QByteArray data(QFile::encodeName(cExeDir() + "Updater"));
    memcpy(path, data.constData(), data.size());

    char *args[MaxArgsCount] = {0}, p_noupdate[] = "-noupdate", p_autostart[] = "-autostart", p_debug[] = "-debug", p_tosettings[] = "-tosettings", p_key[] = "-key", p_path[] = "-workpath", p_startintray[] = "-startintray", p_testmode[] = "-testmode";
    char p_datafile[MaxLen] = {0}, p_pathbuf[MaxLen] = {0};
    int argIndex = 0;
    args[argIndex++] = path;
    if (!update) {
        args[argIndex++] = p_noupdate;
        args[argIndex++] = p_tosettings;
    }
    if (cFromAutoStart()) 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 = cWorkingDir().toUtf8();
    if (pathf.size() < MaxLen) {
        memcpy(p_pathbuf, pathf.constData(), pathf.size());
        args[argIndex++] = p_path;
        args[argIndex++] = p_pathbuf;
    }

    pid_t pid = fork();
    switch (pid) {
    case -1: return false;
    case 0: execv(path, args); return false;
    }
    return true;
}
Exemple #12
0
void moveOldDataFiles(const QString &wasDir) {
	QFile data(wasDir + "data"), dataConfig(wasDir + "data_config"), tdataConfig(wasDir + "tdata/config");
	if (data.exists() && dataConfig.exists() && !QFileInfo(cWorkingDir() + "data").exists() && !QFileInfo(cWorkingDir() + "data_config").exists()) { // move to home dir
		LOG(("Copying data to home dir '%1' from '%2'").arg(cWorkingDir()).arg(wasDir));
		if (data.copy(cWorkingDir() + "data")) {
			LOG(("Copied 'data' to home dir"));
			if (dataConfig.copy(cWorkingDir() + "data_config")) {
				LOG(("Copied 'data_config' to home dir"));
				bool tdataGood = true;
				if (tdataConfig.exists()) {
					tdataGood = false;
					QDir().mkpath(cWorkingDir() + "tdata");
					if (tdataConfig.copy(cWorkingDir() + "tdata/config")) {
						LOG(("Copied 'tdata/config' to home dir"));
						tdataGood = true;
					} else {
						LOG(("Copied 'data' and 'data_config', but could not copy 'tdata/config'!"));
					}
				}
				if (tdataGood) {
					if (data.remove()) {
						LOG(("Removed 'data'"));
					} else {
						LOG(("Could not remove 'data'"));
					}
					if (dataConfig.remove()) {
						LOG(("Removed 'data_config'"));
					} else {
						LOG(("Could not remove 'data_config'"));
					}
					if (!tdataConfig.exists() || tdataConfig.remove()) {
						LOG(("Removed 'tdata/config'"));
						LOG(("Could not remove 'tdata/config'"));
					} else {
					}
					QDir().rmdir(wasDir + "tdata");
				}
			} else {
				LOG(("Copied 'data', but could not copy 'data_config'!!"));
			}
		} else {
			LOG(("Could not copy 'data'!"));
		}
	}
}
Exemple #13
0
void PsUpdateDownloader::clearAll() {
	deleteDir(cWorkingDir() + qsl("tupdates"));
}
Exemple #14
0
void logsInitDebug() {
	time_t t = time(NULL);
	struct tm tm;
	mylocaltime(&tm, &t);

	static const int switchEach = 15; // minutes
	int32 newPart = (tm.tm_min + tm.tm_hour * 60) / switchEach;
	if (newPart == part) return;

	part = newPart;

	int32 dayIndex = (tm.tm_year + 1900) * 10000 + (tm.tm_mon + 1) * 100 + tm.tm_mday;
	QString logPostfix = QString("_%4_%5").arg((part * switchEach) / 60, 2, 10, zero).arg((part * switchEach) % 60, 2, 10, zero);

	if (debugLogStream) {
		delete debugLogStream;
		debugLogStream = 0;
		debugLog.close();
	}
	debugLog.setFileName(cWorkingDir() + qsl("DebugLogs/log") + logPostfix + qsl(".txt"));
	QIODevice::OpenMode debugLogMode = QIODevice::WriteOnly | QIODevice::Text;
	if (debugLog.exists()) {
		if (debugLog.open(QIODevice::ReadOnly | QIODevice::Text)) {
			if (QString::fromUtf8(debugLog.readLine()).toInt() == dayIndex) {
				debugLogMode |= QIODevice::Append;
			}
			debugLog.close();
		}
	}
	if (!debugLog.open(debugLogMode)) {
		QDir dir(QDir::current());
		dir.mkdir(cWorkingDir() + qsl("DebugLogs"));
		debugLog.open(debugLogMode);
	}
	if (debugLog.isOpen()) {
		debugLogStream = new QTextStream();
		debugLogStream->setDevice(&debugLog);
		debugLogStream->setCodec("UTF-8");
		(*debugLogStream) << ((debugLogMode & QIODevice::Append) ? qsl("----------------------------------------------------------------\nNEW LOGGING INSTANCE STARTED!!!\n----------------------------------------------------------------\n") : qsl("%1\n").arg(dayIndex));
		debugLogStream->flush();
	}
	if (tcpLogStream) {
		delete tcpLogStream;
		tcpLogStream = 0;
		tcpLog.close();
	}
	tcpLog.setFileName(cWorkingDir() + qsl("DebugLogs/tcp") + logPostfix + qsl(".txt"));
	QIODevice::OpenMode tcpLogMode = QIODevice::WriteOnly | QIODevice::Text;
	if (tcpLog.exists()) {
		if (tcpLog.open(QIODevice::ReadOnly | QIODevice::Text)) {
			if (QString::fromUtf8(tcpLog.readLine()).toInt() == dayIndex) {
				tcpLogMode |= QIODevice::Append;
			}
			tcpLog.close();
		}
	}
	if (tcpLog.open(tcpLogMode)) {
		tcpLogStream = new QTextStream();
		tcpLogStream->setDevice(&tcpLog);
		tcpLogStream->setCodec("UTF-8");
		(*tcpLogStream) << ((tcpLogMode & QIODevice::Append) ? qsl("----------------------------------------------------------------\nNEW LOGGING INSTANCE STARTED!!!\n----------------------------------------------------------------\n") : qsl("%1\n").arg(dayIndex));
		tcpLogStream->flush();
	}
	if (mtpLogStream) {
		delete mtpLogStream;
		mtpLogStream = 0;
		mtpLog.close();
	}
	mtpLog.setFileName(cWorkingDir() + qsl("DebugLogs/mtp") + logPostfix + qsl(".txt"));
	QIODevice::OpenMode mtpLogMode = QIODevice::WriteOnly | QIODevice::Text;
	if (mtpLog.exists()) {
		if (mtpLog.open(QIODevice::ReadOnly | QIODevice::Text)) {
			if (QString::fromUtf8(mtpLog.readLine()).toInt() == dayIndex) {
				mtpLogMode |= QIODevice::Append;
			}
			mtpLog.close();
		}
	}
	if (mtpLog.open(mtpLogMode)) {
		mtpLogStream = new QTextStream();
		mtpLogStream->setDevice(&mtpLog);
		mtpLogStream->setCodec("UTF-8");
		(*mtpLogStream) << ((mtpLogMode & QIODevice::Append) ? qsl("----------------------------------------------------------------\nNEW LOGGING INSTANCE STARTED!!!\n----------------------------------------------------------------\n") : qsl("%1\n").arg(dayIndex));
		mtpLogStream->flush();
	}
}
Exemple #15
0
void psExecUpdater() {
	if (!objc_execUpdater()) {
		QString readyPath = cWorkingDir() + qsl("tupdates/ready");
		PsUpdateDownloader::deleteDir(readyPath);
	}
}
Exemple #16
0
bool psCheckReadyUpdate() {
    QString readyPath = cWorkingDir() + qsl("tupdates/ready");
	if (!QDir(readyPath).exists()) {
		return false;
	}

	// check ready version
	QString versionPath = readyPath + qsl("/tdata/version");
	{
		QFile fVersion(versionPath);
		if (!fVersion.open(QIODevice::ReadOnly)) {
			LOG(("Update Error: cant read version file '%1'").arg(versionPath));
			PsUpdateDownloader::clearAll();
			return false;
		}
		VerInt versionNum;
		if (fVersion.read((char*)&versionNum, sizeof(VerInt)) != sizeof(VerInt)) {
			LOG(("Update Error: cant read version from file '%1'").arg(versionPath));
			PsUpdateDownloader::clearAll();
			return false;
		}
		fVersion.close();
		if (versionNum <= AppVersion) {
			LOG(("Update Error: cant install version %1 having version %2").arg(versionNum).arg(AppVersion));
			PsUpdateDownloader::clearAll();
			return false;
		}
	}

#ifdef Q_OS_WIN
	QString curUpdater = (cExeDir() + qsl("Updater.exe"));
	QFileInfo updater(cWorkingDir() + qsl("tupdates/ready/Updater.exe"));
#elif defined Q_OS_MAC
	QString curUpdater = (cExeDir() + cExeName() + qsl("/Contents/Frameworks/Updater"));
	QFileInfo updater(cWorkingDir() + qsl("tupdates/ready/Telegram.app/Contents/Frameworks/Updater"));
#endif
	if (!updater.exists()) {
		QFileInfo current(curUpdater);
		if (!current.exists()) {
			PsUpdateDownloader::clearAll();
			return false;
		}
		if (!QFile(current.absoluteFilePath()).copy(updater.absoluteFilePath())) {
			PsUpdateDownloader::clearAll();
			return false;
		}
	}
#ifdef Q_OS_WIN
	if (CopyFile(updater.absoluteFilePath().toStdWString().c_str(), curUpdater.toStdWString().c_str(), FALSE) == FALSE) {
		PsUpdateDownloader::clearAll();
		return false;
	}
	if (DeleteFile(updater.absoluteFilePath().toStdWString().c_str()) == FALSE) {
		PsUpdateDownloader::clearAll();
		return false;
    }
#elif defined Q_OS_MAC
	QDir().mkpath(QFileInfo(curUpdater).absolutePath());
	DEBUG_LOG(("Update Info: moving %1 to %2..").arg(updater.absoluteFilePath()).arg(curUpdater));
	if (!objc_moveFile(updater.absoluteFilePath(), curUpdater)) {
		PsUpdateDownloader::clearAll();
		return false;
	}
#endif
    return true;
}
Exemple #17
0
int main(int argc, char *argv[]) {
#ifdef Q_OS_WIN
	_oldWndExceptionFilter = SetUnhandledExceptionFilter(_exceptionFilter);
//	CAPIHook apiHook("kernel32.dll", "SetUnhandledExceptionFilter", (PROC)RedirectedSetUnhandledExceptionFilter);
#endif

	settingsParseArgs(argc, argv);
	for (int32 i = 0; i < argc; ++i) {
		if (string("-fixprevious") == argv[i]) {
			return psFixPrevious();
		} else if (string("-cleanup") == argv[i]) {
			return psCleanup();
		}
	}
	if (!logsInit()) {
		return 0;
	}

	installSignalHandlers();

	Global::Initializer _init;

	Local::readSettings();
	if (Local::oldSettingsVersion() < AppVersion) {
		psNewVersion();
	}
	if (cFromAutoStart() && !cAutoStart()) {
		psAutoStart(false, true);
		Local::stop();
		return 0;
	}

	DEBUG_LOG(("Application Info: Telegram started, test mode: %1, exe dir: %2").arg(logBool(cTestMode())).arg(cExeDir()));
	if (cDebug()) {
		LOG(("Application Info: Telegram started in debug mode"));
		for (int32 i = 0; i < argc; ++i) {
			LOG(("Argument: %1").arg(fromUtf8Safe(argv[i])));
		}
        QStringList logs = psInitLogs();
        for (int32 i = 0, l = logs.size(); i < l; ++i) {
            LOG(("Init Log: %1").arg(logs.at(i)));
        }
    }
    psClearInitLogs();

	DEBUG_LOG(("Application Info: ideal thread count: %1, using %2 connections per session").arg(QThread::idealThreadCount()).arg(cConnectionsInSession()));

	psStart();
	int result = 0;
	{
		QByteArray args[] = { "-style=0" }; // prepare fake args
		static const int a_cnt = sizeof(args) / sizeof(args[0]);
		int a_argc = a_cnt + 1;
		char *a_argv[a_cnt + 1] = { argv[0], args[0].data() };

		Application app(a_argc, a_argv);
		if (!App::quiting()) {
			result = app.exec();
		}
	}
    psFinish();
	Local::stop();

	DEBUG_LOG(("Application Info: Telegram done, result: %1").arg(result));

	#ifndef TDESKTOP_DISABLE_AUTOUPDATE
	if (cRestartingUpdate()) {
		if (!cBetaVersion() && DevVersion) {
			LOG(("Writing 'devversion' file before launching the Updater!"));
			QFile f(cWorkingDir() + qsl("tdata/devversion"));
			if (!f.exists() && f.open(QIODevice::WriteOnly)) {
				f.write("1");
				f.close();
			}
		}

		DEBUG_LOG(("Application Info: executing updater to install update.."));
		psExecUpdater();
	} else
	#endif
	if (cRestarting()) {
		DEBUG_LOG(("Application Info: executing Telegram, because of restart.."));
		psExecTelegram();
	}

	logsClose();
	return result;
}
Exemple #18
0
void UpdateChecker::unpackUpdate() {
	QByteArray packed;
	if (!outputFile.open(QIODevice::ReadOnly)) {
		LOG(("Update Error: cant read updates file!"));
		return fatalFail();
	}

#ifdef Q_OS_WIN // use Lzma SDK for win
	const int32 hSigLen = 128, hShaLen = 20, hPropsLen = LZMA_PROPS_SIZE, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hPropsLen + hOriginalSizeLen; // header
#else // Q_OS_WIN
	const int32 hSigLen = 128, hShaLen = 20, hPropsLen = 0, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hOriginalSizeLen; // header
#endif // Q_OS_WIN

	QByteArray compressed = outputFile.readAll();
	int32 compressedLen = compressed.size() - hSize;
	if (compressedLen <= 0) {
		LOG(("Update Error: bad compressed size: %1").arg(compressed.size()));
		return fatalFail();
	}
	outputFile.close();

	QString tempDirPath = cWorkingDir() + qsl("tupdates/temp"), readyFilePath = cWorkingDir() + qsl("tupdates/temp/ready");
	psDeleteDir(tempDirPath);

	QDir tempDir(tempDirPath);
	if (tempDir.exists() || QFile(readyFilePath).exists()) {
		LOG(("Update Error: cant clear tupdates/temp dir!"));
		return fatalFail();
	}

	uchar sha1Buffer[20];
	bool goodSha1 = !memcmp(compressed.constData() + hSigLen, hashSha1(compressed.constData() + hSigLen + hShaLen, compressedLen + hPropsLen + hOriginalSizeLen, sha1Buffer), hShaLen);
	if (!goodSha1) {
		LOG(("Update Error: bad SHA1 hash of update file!"));
		return fatalFail();
	}

	RSA *pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<char*>(AppAlphaVersion ? UpdatesPublicAlphaKey : UpdatesPublicKey), -1), 0, 0, 0);
	if (!pbKey) {
		LOG(("Update Error: cant read public rsa key!"));
		return fatalFail();
	}
	if (RSA_verify(NID_sha1, (const uchar*)(compressed.constData() + hSigLen), hShaLen, (const uchar*)(compressed.constData()), hSigLen, pbKey) != 1) { // verify signature
		RSA_free(pbKey);
		if (cAlphaVersion() || cBetaVersion()) { // try other public key, if we are in alpha or beta version
			pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<char*>(AppAlphaVersion ? UpdatesPublicKey : UpdatesPublicAlphaKey), -1), 0, 0, 0);
			if (!pbKey) {
				LOG(("Update Error: cant read public rsa key!"));
				return fatalFail();
			}
			if (RSA_verify(NID_sha1, (const uchar*)(compressed.constData() + hSigLen), hShaLen, (const uchar*)(compressed.constData()), hSigLen, pbKey) != 1) { // verify signature
				RSA_free(pbKey);
				LOG(("Update Error: bad RSA signature of update file!"));
				return fatalFail();
			}
		} else {
			LOG(("Update Error: bad RSA signature of update file!"));
			return fatalFail();
		}
	}
	RSA_free(pbKey);

	QByteArray uncompressed;

	int32 uncompressedLen;
	memcpy(&uncompressedLen, compressed.constData() + hSigLen + hShaLen + hPropsLen, hOriginalSizeLen);
	uncompressed.resize(uncompressedLen);

	size_t resultLen = uncompressed.size();
#ifdef Q_OS_WIN // use Lzma SDK for win
	SizeT srcLen = compressedLen;
	int uncompressRes = LzmaUncompress((uchar*)uncompressed.data(), &resultLen, (const uchar*)(compressed.constData() + hSize), &srcLen, (const uchar*)(compressed.constData() + hSigLen + hShaLen), LZMA_PROPS_SIZE);
	if (uncompressRes != SZ_OK) {
		LOG(("Update Error: could not uncompress lzma, code: %1").arg(uncompressRes));
		return fatalFail();
	}
#else // Q_OS_WIN
	lzma_stream stream = LZMA_STREAM_INIT;

	lzma_ret ret = lzma_stream_decoder(&stream, UINT64_MAX, LZMA_CONCATENATED);
	if (ret != LZMA_OK) {
		const char *msg;
		switch (ret) {
		case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break;
		case LZMA_OPTIONS_ERROR: msg = "Specified preset is not supported"; break;
		case LZMA_UNSUPPORTED_CHECK: msg = "Specified integrity check is not supported"; break;
		default: msg = "Unknown error, possibly a bug"; break;
		}
		LOG(("Error initializing the decoder: %1 (error code %2)").arg(msg).arg(ret));
		return fatalFail();
	}

	stream.avail_in = compressedLen;
	stream.next_in = (uint8_t*)(compressed.constData() + hSize);
	stream.avail_out = resultLen;
	stream.next_out = (uint8_t*)uncompressed.data();

	lzma_ret res = lzma_code(&stream, LZMA_FINISH);
	if (stream.avail_in) {
		LOG(("Error in decompression, %1 bytes left in _in of %2 whole.").arg(stream.avail_in).arg(compressedLen));
		return fatalFail();
	} else if (stream.avail_out) {
		LOG(("Error in decompression, %1 bytes free left in _out of %2 whole.").arg(stream.avail_out).arg(resultLen));
		return fatalFail();
	}
	lzma_end(&stream);
	if (res != LZMA_OK && res != LZMA_STREAM_END) {
		const char *msg;
		switch (res) {
		case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break;
		case LZMA_FORMAT_ERROR: msg = "The input data is not in the .xz format"; break;
		case LZMA_OPTIONS_ERROR: msg = "Unsupported compression options"; break;
		case LZMA_DATA_ERROR: msg = "Compressed file is corrupt"; break;
		case LZMA_BUF_ERROR: msg = "Compressed data is truncated or otherwise corrupt"; break;
		default: msg = "Unknown error, possibly a bug"; break;
		}
		LOG(("Error in decompression: %1 (error code %2)").arg(msg).arg(res));
		return fatalFail();
	}
#endif // Q_OS_WIN

	tempDir.mkdir(tempDir.absolutePath());

	quint32 version;
	{
		QBuffer buffer(&uncompressed);
		buffer.open(QIODevice::ReadOnly);
		QDataStream stream(&buffer);
		stream.setVersion(QDataStream::Qt_5_1);

		stream >> version;
		if (stream.status() != QDataStream::Ok) {
			LOG(("Update Error: cant read version from downloaded stream, status: %1").arg(stream.status()));
			return fatalFail();
		}

		quint64 betaVersion = 0;
		if (version == 0x7FFFFFFF) { // beta version
			stream >> betaVersion;
			if (stream.status() != QDataStream::Ok) {
				LOG(("Update Error: cant read beta version from downloaded stream, status: %1").arg(stream.status()));
				return fatalFail();
			}
			if (!cBetaVersion() || betaVersion <= cBetaVersion()) {
				LOG(("Update Error: downloaded beta version %1 is not greater, than mine %2").arg(betaVersion).arg(cBetaVersion()));
				return fatalFail();
			}
		} else if (int32(version) <= AppVersion) {
CachedUserpics::~CachedUserpics() {
	if (_someSavedFlag) {
		psDeleteDir(cWorkingDir() + qsl("tdata/temp"));
	}
}
Exemple #20
0
Application::Application(int &argc, char **argv) : PsApplication(argc, argv),
    serverName(psServerPrefix() + cGUIDStr()), closing(false),
	updateRequestId(0), updateReply(0), updateThread(0), updateDownloader(0) {

	DEBUG_LOG(("Application Info: creation.."));

	QByteArray d(QDir((cPlatform() == dbipWindows ? cExeDir() : cWorkingDir()).toLower()).absolutePath().toUtf8());
	char h[33] = { 0 };
	hashMd5Hex(d.constData(), d.size(), h);
	serverName = psServerPrefix() + h + '-' + cGUIDStr();

	if (mainApp) {
		DEBUG_LOG(("Application Error: another Application was created, terminating.."));
		exit(0);
	}
	mainApp = this;

	installEventFilter(new _DebugWaiter(this));

#if defined Q_OS_LINUX || defined Q_OS_LINUX64
    QFontDatabase::addApplicationFont(qsl(":/gui/art/fonts/DejaVuSans.ttf"));
    QFontDatabase::addApplicationFont(qsl(":/gui/art/fonts/NanumMyeongjo-Regular.ttf"));
#endif
    QFontDatabase::addApplicationFont(qsl(":/gui/art/fonts/OpenSans-Regular.ttf"));
    QFontDatabase::addApplicationFont(qsl(":/gui/art/fonts/OpenSans-Bold.ttf"));
    QFontDatabase::addApplicationFont(qsl(":/gui/art/fonts/OpenSans-Semibold.ttf"));

	float64 dpi = primaryScreen()->logicalDotsPerInch();
	if (dpi <= 108) { // 0-96-108
		cSetScreenScale(dbisOne);
	} else if (dpi <= 132) { // 108-120-132
		cSetScreenScale(dbisOneAndQuarter);
	} else if (dpi <= 168) { // 132-144-168
		cSetScreenScale(dbisOneAndHalf);
	} else { // 168-192-inf
		cSetScreenScale(dbisTwo);
	}

    if (devicePixelRatio() > 1) {
        cSetRetina(true);
        cSetRetinaFactor(devicePixelRatio());
        cSetIntRetinaFactor(int32(cRetinaFactor()));
    }

	if (!cLangFile().isEmpty()) {
		LangLoaderPlain loader(cLangFile());
		if (!loader.errors().isEmpty()) {
			LOG(("Lang load errors: %1").arg(loader.errors()));
		} else if (!loader.warnings().isEmpty()) {
			LOG(("Lang load warnings: %1").arg(loader.warnings()));
		}
	}

	Local::start();
	style::startManager();
	anim::startManager();
	historyInit();

	DEBUG_LOG(("Application Info: inited.."));

    window = new Window();

	psInstallEventFilter();

	connect(&socket, SIGNAL(connected()), this, SLOT(socketConnected()));
	connect(&socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
	connect(&socket, SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(socketError(QLocalSocket::LocalSocketError)));
	connect(&socket, SIGNAL(bytesWritten(qint64)), this, SLOT(socketWritten(qint64)));
	connect(&socket, SIGNAL(readyRead()), this, SLOT(socketReading()));
	connect(&server, SIGNAL(newConnection()), this, SLOT(newInstanceConnected()));
	connect(this, SIGNAL(aboutToQuit()), this, SLOT(closeApplication()));
	connect(&updateCheckTimer, SIGNAL(timeout()), this, SLOT(startUpdateCheck()));
	connect(this, SIGNAL(updateFailed()), this, SLOT(onUpdateFailed()));
	connect(this, SIGNAL(updateReady()), this, SLOT(onUpdateReady()));
	connect(this, SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(onAppStateChanged(Qt::ApplicationState)));
	connect(&writeUserConfigTimer, SIGNAL(timeout()), this, SLOT(onWriteUserConfig()));
	writeUserConfigTimer.setSingleShot(true);

	connect(&killDownloadSessionsTimer, SIGNAL(timeout()), this, SLOT(killDownloadSessions()));

	if (cManyInstance()) {
		startApp();
	} else {
        DEBUG_LOG(("Application Info: connecting local socket to %1..").arg(serverName));
		socket.connectToServer(serverName);
	}
}
Exemple #21
0
void psRegisterCustomScheme() {
    QString home(_psHomeDir());
    if (home.isEmpty()) return;

    DEBUG_LOG(("App Info: placing .desktop file"));
    if (QDir(home + qsl(".local/")).exists()) {
        QString apps = home + qsl(".local/share/applications/");
        if (!QDir(apps).exists()) QDir().mkpath(apps);

        QString path = cWorkingDir() + qsl("tdata/"), file = path + qsl("telegramdesktop.desktop");
        QDir().mkpath(path);
        QFile f(file);
        if (f.open(QIODevice::WriteOnly)) {
            QString icon = path + qsl("icon.png");
            if (!QFile(icon).exists()) {
                if (QFile(qsl(":/gui/art/icon256.png")).copy(icon)) {
                    DEBUG_LOG(("App Info: Icon copied to 'tdata'"));
                }

            }

            QTextStream s(&f);
            s.setCodec("UTF-8");
            s << "[Desktop Entry]\n";
            s << "Encoding=UTF-8\n";
            s << "Version=1.0\n";
            s << "Name=Telegram Desktop\n";
            s << "Comment=Official desktop version of Telegram messaging app\n";
            s << "Exec=" << escapeShell(cExeDir() + cExeName()) << " -- %u\n";
            s << "Icon=" << icon << "\n";
            s << "Terminal=false\n";
            s << "Type=Application\n";
            s << "Categories=Network;\n";
            s << "MimeType=application/x-xdg-protocol-tg;x-scheme-handler/tg;\n";
            f.close();

            if (_psRunCommand(qsl("desktop-file-install --dir=%1 --delete-original %2").arg(escapeShell(home + qsl(".local/share/applications"))).arg(escapeShell(file)))) {
                DEBUG_LOG(("App Info: removing old .desktop file"));
                QFile(qsl("%1.local/share/applications/telegram.desktop").arg(home)).remove();

                _psRunCommand(qsl("update-desktop-database %1").arg(escapeShell(home + qsl(".local/share/applications"))));
                _psRunCommand(qsl("xdg-mime default telegramdesktop.desktop x-scheme-handler/tg"));
            }
        } else {
            LOG(("App Error: Could not open '%1' for write").arg(file));
        }
    }

    DEBUG_LOG(("App Info: registerting for Gnome"));
    if (_psRunCommand(qsl("gconftool-2 -t string -s /desktop/gnome/url-handlers/tg/command %1").arg(escapeShell(qsl("%1 -- %s").arg(escapeShell(cExeDir() + cExeName())))))) {
        _psRunCommand(qsl("gconftool-2 -t bool -s /desktop/gnome/url-handlers/tg/needs_terminal false"));
        _psRunCommand(qsl("gconftool-2 -t bool -s /desktop/gnome/url-handlers/tg/enabled true"));
    }

    DEBUG_LOG(("App Info: placing .protocol file"));
    QString services;
    if (QDir(home + qsl(".kde4/")).exists()) {
        services = home + qsl(".kde4/share/kde4/services/");
    } else if (QDir(home + qsl(".kde/")).exists()) {
        services = home + qsl(".kde/share/kde4/services/");
    }
    if (!services.isEmpty()) {
        if (!QDir(services).exists()) QDir().mkpath(services);

        QString path = services, file = path + qsl("tg.protocol");
        QFile f(file);
        if (f.open(QIODevice::WriteOnly)) {
            QTextStream s(&f);
            s.setCodec("UTF-8");
            s << "[Protocol]\n";
            s << "exec=" << escapeShell(cExeDir() + cExeName()) << " -- %u\n";
            s << "protocol=tg\n";
            s << "input=none\n";
            s << "output=none\n";
            s << "helper=true\n";
            s << "listing=false\n";
            s << "reading=false\n";
            s << "writing=false\n";
            s << "makedir=false\n";
            s << "deleting=false\n";
            f.close();
        } else {
            LOG(("App Error: Could not open '%1' for write").arg(file));
        }
    }
}
Exemple #22
0
void PsUpdateDownloader::unpackUpdate() {
    QByteArray packed;
	if (!outputFile.open(QIODevice::ReadOnly)) {
		LOG(("Update Error: cant read updates file!"));
		return fatalFail();
	}
#ifdef Q_OS_WIN // use Lzma SDK for win
	const int32 hSigLen = 128, hShaLen = 20, hPropsLen = LZMA_PROPS_SIZE, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hPropsLen + hOriginalSizeLen; // header
#else
	const int32 hSigLen = 128, hShaLen = 20, hPropsLen = 0, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hOriginalSizeLen; // header
#endif
	QByteArray compressed = outputFile.readAll();
	int32 compressedLen = compressed.size() - hSize;
	if (compressedLen <= 0) {
		LOG(("Update Error: bad compressed size: %1").arg(compressed.size()));
		return fatalFail();
	}
	outputFile.close();

	QString tempDirPath = cWorkingDir() + qsl("tupdates/temp"), readyDirPath = cWorkingDir() + qsl("tupdates/ready");
	deleteDir(tempDirPath);
	deleteDir(readyDirPath);

	QDir tempDir(tempDirPath), readyDir(readyDirPath);
	if (tempDir.exists() || readyDir.exists()) {
		LOG(("Update Error: cant clear tupdates/temp or tupdates/ready dir!"));
		return fatalFail();
	}

	uchar sha1Buffer[20];
	bool goodSha1 = !memcmp(compressed.constData() + hSigLen, hashSha1(compressed.constData() + hSigLen + hShaLen, compressedLen + hPropsLen + hOriginalSizeLen, sha1Buffer), hShaLen);
	if (!goodSha1) {
		LOG(("Update Error: bad SHA1 hash of update file!"));
		return fatalFail();
	}

	RSA *pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<char*>(UpdatesPublicKey), -1), 0, 0, 0);
	if (!pbKey) {
		LOG(("Update Error: cant read public rsa key!"));
		return fatalFail();
	}
    if (RSA_verify(NID_sha1, (const uchar*)(compressed.constData() + hSigLen), hShaLen, (const uchar*)(compressed.constData()), hSigLen, pbKey) != 1) { // verify signature
		RSA_free(pbKey);
		LOG(("Update Error: bad RSA signature of update file!"));
		return fatalFail();
    }
	RSA_free(pbKey);

	QByteArray uncompressed;

	int32 uncompressedLen;
	memcpy(&uncompressedLen, compressed.constData() + hSigLen + hShaLen + hPropsLen, hOriginalSizeLen);
	uncompressed.resize(uncompressedLen);

	size_t resultLen = uncompressed.size();
#ifdef Q_OS_WIN // use Lzma SDK for win
	SizeT srcLen = compressedLen;
	int uncompressRes = LzmaUncompress((uchar*)uncompressed.data(), &resultLen, (const uchar*)(compressed.constData() + hSize), &srcLen, (const uchar*)(compressed.constData() + hSigLen + hShaLen), LZMA_PROPS_SIZE);
	if (uncompressRes != SZ_OK) {
		LOG(("Update Error: could not uncompress lzma, code: %1").arg(uncompressRes));
		return fatalFail();
	}
#else
	lzma_stream stream = LZMA_STREAM_INIT;

	lzma_ret ret = lzma_stream_decoder(&stream, UINT64_MAX, LZMA_CONCATENATED);
	if (ret != LZMA_OK) {
		const char *msg;
		switch (ret) {
			case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break;
			case LZMA_OPTIONS_ERROR: msg = "Specified preset is not supported"; break;
			case LZMA_UNSUPPORTED_CHECK: msg = "Specified integrity check is not supported"; break;
			default: msg = "Unknown error, possibly a bug"; break;
		}
		LOG(("Error initializing the decoder: %1 (error code %2)").arg(msg).arg(ret));
		return fatalFail();
	}

	stream.avail_in = compressedLen;
	stream.next_in = (uint8_t*)(compressed.constData() + hSize);
	stream.avail_out = resultLen;
	stream.next_out = (uint8_t*)uncompressed.data();

	lzma_ret res = lzma_code(&stream, LZMA_FINISH);
	if (stream.avail_in) {
		LOG(("Error in decompression, %1 bytes left in _in of %2 whole.").arg(stream.avail_in).arg(compressedLen));
		return fatalFail();
	} else if (stream.avail_out) {
		LOG(("Error in decompression, %1 bytes free left in _out of %2 whole.").arg(stream.avail_out).arg(resultLen));
		return fatalFail();
	}
	lzma_end(&stream);
	if (res != LZMA_OK && res != LZMA_STREAM_END) {
		const char *msg;
		switch (res) {
			case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break;
			case LZMA_FORMAT_ERROR: msg = "The input data is not in the .xz format"; break;
			case LZMA_OPTIONS_ERROR: msg = "Unsupported compression options"; break;
			case LZMA_DATA_ERROR: msg = "Compressed file is corrupt"; break;
			case LZMA_BUF_ERROR: msg = "Compressed data is truncated or otherwise corrupt"; break;
			default: msg = "Unknown error, possibly a bug"; break;
		}
		LOG(("Error in decompression: %1 (error code %2)").arg(msg).arg(res));
		return fatalFail();
	}
#endif

	tempDir.mkdir(tempDir.absolutePath());

	quint32 version;
	{
		QBuffer buffer(&uncompressed);
		buffer.open(QIODevice::ReadOnly);
		QDataStream stream(&buffer);
		stream.setVersion(QDataStream::Qt_5_1);

		stream >> version;
		if (stream.status() != QDataStream::Ok) {
			LOG(("Update Error: cant read version from downloaded stream, status: %1").arg(stream.status()));
			return fatalFail();
		}
		if (version <= AppVersion) {
			LOG(("Update Error: downloaded version %1 is not greater, than mine %2").arg(version).arg(AppVersion));
			return fatalFail();
		}

		quint32 filesCount;
		stream >> filesCount;
		if (stream.status() != QDataStream::Ok) {
			LOG(("Update Error: cant read files count from downloaded stream, status: %1").arg(stream.status()));
			return fatalFail();
		}
		if (!filesCount) {
			LOG(("Update Error: update is empty!"));
			return fatalFail();
		}
		for (uint32 i = 0; i < filesCount; ++i) {
			QString relativeName;
			quint32 fileSize;
			QByteArray fileInnerData;
			bool executable = false;

			stream >> relativeName >> fileSize >> fileInnerData;
#if defined Q_OS_MAC || defined Q_OS_LINUX
			stream >> executable;
#endif
			if (stream.status() != QDataStream::Ok) {
				LOG(("Update Error: cant read file from downloaded stream, status: %1").arg(stream.status()));
				return fatalFail();
			}
			if (fileSize != quint32(fileInnerData.size())) {
				LOG(("Update Error: bad file size %1 not matching data size %2").arg(fileSize).arg(fileInnerData.size()));
				return fatalFail();
			}

			QFile f(tempDirPath + '/' + relativeName);
			if (!QDir().mkpath(QFileInfo(f).absolutePath())) {
				LOG(("Update Error: cant mkpath for file '%1'").arg(tempDirPath + '/' + relativeName));
				return fatalFail();
			}
			if (!f.open(QIODevice::WriteOnly)) {
				LOG(("Update Error: cant open file '%1' for writing").arg(tempDirPath + '/' + relativeName));
				return fatalFail();
			}
			if (f.write(fileInnerData) != fileSize) {
				f.close();
				LOG(("Update Error: cant write file '%1'").arg(tempDirPath + '/' + relativeName));
				return fatalFail();
			}
			f.close();
			if (executable) {
				QFileDevice::Permissions p = f.permissions();
				p |= QFileDevice::ExeOwner | QFileDevice::ExeUser | QFileDevice::ExeGroup | QFileDevice::ExeOther;
				f.setPermissions(p);
			}
		}

		// create tdata/version file
		tempDir.mkdir(QDir(tempDirPath + qsl("/tdata")).absolutePath());
		std::wstring versionString = ((version % 1000) ? QString("%1.%2.%3").arg(int(version / 1000000)).arg(int((version % 1000000) / 1000)).arg(int(version % 1000)) : QString("%1.%2").arg(int(version / 1000000)).arg(int((version % 1000000) / 1000))).toStdWString();

		VerInt versionNum = VerInt(version), versionLen = VerInt(versionString.size() * sizeof(VerChar));
		VerChar versionStr[32];
		memcpy(versionStr, versionString.c_str(), versionLen);

		QFile fVersion(tempDirPath + qsl("/tdata/version"));
		if (!fVersion.open(QIODevice::WriteOnly)) {
			LOG(("Update Error: cant write version file '%1'").arg(tempDirPath + qsl("/version")));
			return fatalFail();
		}
		fVersion.write((const char*)&versionNum, sizeof(VerInt));
		fVersion.write((const char*)&versionLen, sizeof(VerInt));
		fVersion.write((const char*)&versionStr[0], versionLen);
		fVersion.close();
	}

	if (!tempDir.rename(tempDir.absolutePath(), readyDir.absolutePath())) {
		LOG(("Update Error: cant rename temp dir '%1' to ready dir '%2'").arg(tempDir.absolutePath()).arg(readyDir.absolutePath()));
		return fatalFail();
	}
	deleteDir(tempDirPath);
	outputFile.remove();

    emit App::app()->updateReady();
}
Exemple #23
0
void UpdateChecker::clearAll() {
	psDeleteDir(cWorkingDir() + qsl("tupdates"));
}
Exemple #24
0
void psExecUpdater() {
	if (!objc_execUpdater()) {
		psDeleteDir(cWorkingDir() + qsl("tupdates/temp"));
	}
}
CachedUserpics::CachedUserpics(Type type) : _type(type) {
	connect(&_clearTimer, SIGNAL(timeout()), this, SLOT(onClear()));
	QDir().mkpath(cWorkingDir() + qsl("tdata/temp"));
}
Exemple #26
0
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 (Logs::DebugEnabled()) {
		pushArgument(qsl("-debug"));
	}
	if (cStartInTray()) {
		pushArgument(qsl("-startintray"));
	}
	if (cTestMode()) {
		pushArgument(qsl("-testmode"));
	}
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
	if (Core::UpdaterDisabled()) {
		pushArgument(qsl("-externalupdater"));
	}
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
	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);
}
Exemple #27
0
int main(int argc, char *argv[]) {
#ifdef _NEED_WIN_GENERATE_DUMP
	_oldWndExceptionFilter = SetUnhandledExceptionFilter(_exceptionFilter);
#endif

	InitOpenSSL _init;

	settingsParseArgs(argc, argv);
	for (int32 i = 0; i < argc; ++i) {
		if (string("-fixprevious") == argv[i]) {
			return psFixPrevious();
		} else if (string("-cleanup") == argv[i]) {
			return psCleanup();
		}
	}
	logsInit();

	Local::readSettings();
	if (cFromAutoStart() && !cAutoStart()) {
		psAutoStart(false, true);
		Local::stop();
		return 0;
	}

	DEBUG_LOG(("Application Info: Telegram started, test mode: %1, exe dir: %2").arg(logBool(cTestMode())).arg(cExeDir()));
	if (cDebug()) {
		LOG(("Application Info: Telegram started in debug mode"));
		for (int32 i = 0; i < argc; ++i) {
			LOG(("Argument: %1").arg(QString::fromLocal8Bit(argv[i])));
		}
        QStringList logs = psInitLogs();
        for (int32 i = 0, l = logs.size(); i < l; ++i) {
            LOG(("Init Log: %1").arg(logs.at(i)));
        }
    }
    psClearInitLogs();

	DEBUG_LOG(("Application Info: ideal thread count: %1, using %2 connections per session").arg(QThread::idealThreadCount()).arg(cConnectionsInSession()));

	psStart();
	int result = 0;
	{
		QByteArray args[] = { "-style=0" }; // prepare fake args
		static const int a_cnt = sizeof(args) / sizeof(args[0]);
		int a_argc = a_cnt + 1;
		char *a_argv[a_cnt + 1] = { argv[0], args[0].data() };

		Application app(a_argc, a_argv);
		if (!App::quiting()) {
			result = app.exec();
		}
	}
    psFinish();
	Local::stop();

	DEBUG_LOG(("Application Info: Telegram done, result: %1").arg(result));

	if (cRestartingUpdate()) {
		if (DevVersion) {
			LOG(("Writing 'devversion' file before launching the Updater!"));
			QFile f(cWorkingDir() + qsl("tdata/devversion"));
			if (!f.exists() && f.open(QIODevice::WriteOnly)) {
				f.write("1");
				f.close();
			}
		}

		DEBUG_LOG(("Application Info: executing updater to install update.."));
		psExecUpdater();
	} else if (cRestarting()) {
		DEBUG_LOG(("Application Info: executing Telegram, because of restart.."));
		psExecTelegram();
	}

	logsClose();
	return result;
}